diff --git a/internal/graphicsdriver/opengl/context_js.go b/internal/graphicsdriver/opengl/context_js.go index 1c79a06c7..b2904e8b0 100644 --- a/internal/graphicsdriver/opengl/context_js.go +++ b/internal/graphicsdriver/opengl/context_js.go @@ -89,13 +89,11 @@ var ( ) type contextImpl struct { - gl js.Value + gl *gl lastProgramID programID } func (c *context) initGL() { - c.gl = js.Value{} - var gl js.Value // TODO: Define id? @@ -120,7 +118,7 @@ func (c *context) initGL() { gl = go2cpp.Get("gl") } - c.gl = gl + c.gl = newGL(gl) } func (c *context) reset() error { @@ -133,18 +131,18 @@ func (c *context) reset() error { c.initGL() - if c.gl.Call("isContextLost").Bool() { + if c.gl.isContextLost.Invoke().Bool() { return driver.GraphicsNotReady } gl := c.gl - gl.Call("enable", gles.BLEND) - gl.Call("enable", gles.SCISSOR_TEST) + gl.enable.Invoke(gles.BLEND) + gl.enable.Invoke(gles.SCISSOR_TEST) c.blendFunc(driver.CompositeModeSourceOver) - f := gl.Call("getParameter", gles.FRAMEBUFFER_BINDING) + f := gl.getParameter.Invoke(gles.FRAMEBUFFER_BINDING) c.screenFramebuffer = framebufferNative(f) if !isWebGL2Available { - gl.Call("getExtension", "OES_standard_derivatives") + gl.getExtension.Invoke("OES_standard_derivatives") } return nil } @@ -157,27 +155,27 @@ func (c *context) blendFunc(mode driver.CompositeMode) { s, d := mode.Operations() s2, d2 := convertOperation(s), convertOperation(d) gl := c.gl - gl.Call("blendFunc", int(s2), int(d2)) + gl.blendFunc.Invoke(int(s2), int(d2)) } func (c *context) scissor(x, y, width, height int) { gl := c.gl - gl.Call("scissor", x, y, width, height) + gl.scissor.Invoke(x, y, width, height) } func (c *context) newTexture(width, height int) (textureNative, error) { gl := c.gl - t := gl.Call("createTexture") + t := gl.createTexture.Invoke() if jsutil.Equal(t, js.Null()) { return textureNative(js.Null()), errors.New("opengl: glGenTexture failed") } - gl.Call("pixelStorei", gles.UNPACK_ALIGNMENT, 4) + gl.pixelStorei.Invoke(gles.UNPACK_ALIGNMENT, 4) c.bindTexture(textureNative(t)) - gl.Call("texParameteri", gles.TEXTURE_2D, gles.TEXTURE_MAG_FILTER, gles.NEAREST) - gl.Call("texParameteri", gles.TEXTURE_2D, gles.TEXTURE_MIN_FILTER, gles.NEAREST) - gl.Call("texParameteri", gles.TEXTURE_2D, gles.TEXTURE_WRAP_S, gles.CLAMP_TO_EDGE) - gl.Call("texParameteri", gles.TEXTURE_2D, gles.TEXTURE_WRAP_T, gles.CLAMP_TO_EDGE) + gl.texParameteri.Invoke(gles.TEXTURE_2D, gles.TEXTURE_MAG_FILTER, gles.NEAREST) + gl.texParameteri.Invoke(gles.TEXTURE_2D, gles.TEXTURE_MIN_FILTER, gles.NEAREST) + gl.texParameteri.Invoke(gles.TEXTURE_2D, gles.TEXTURE_WRAP_S, gles.CLAMP_TO_EDGE) + gl.texParameteri.Invoke(gles.TEXTURE_2D, gles.TEXTURE_WRAP_T, gles.CLAMP_TO_EDGE) // Firefox warns the usage of textures without specifying pixels (#629) // @@ -186,14 +184,14 @@ func (c *context) newTexture(width, height int) (textureNative, error) { // In Ebiten, textures are filled with pixels laster by the filter that ignores destination, so it is fine // to leave textures as uninitialized here. Rather, extra memory allocating for initialization should be // avoided. - gl.Call("texImage2D", gles.TEXTURE_2D, 0, gles.RGBA, width, height, 0, gles.RGBA, gles.UNSIGNED_BYTE, nil) + gl.texImage2D.Invoke(gles.TEXTURE_2D, 0, gles.RGBA, width, height, 0, gles.RGBA, gles.UNSIGNED_BYTE, nil) return textureNative(t), nil } func (c *context) bindFramebufferImpl(f framebufferNative) { gl := c.gl - gl.Call("bindFramebuffer", gles.FRAMEBUFFER, js.Value(f)) + gl.bindFramebuffer.Invoke(gles.FRAMEBUFFER, js.Value(f)) } func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte { @@ -203,7 +201,7 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte { l := 4 * width * height p := jsutil.TemporaryUint8Array(l, nil) - gl.Call("readPixels", 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, p) + gl.readPixels.Invoke(0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, p) return jsutil.Uint8ArrayToSlice(p, l) } @@ -212,31 +210,31 @@ func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width gl := c.gl c.bindFramebuffer(f.native) - gl.Call("bindBuffer", gles.PIXEL_PACK_BUFFER, js.Value(buffer)) + gl.bindBuffer.Invoke(gles.PIXEL_PACK_BUFFER, js.Value(buffer)) // void gl.readPixels(x, y, width, height, format, type, GLintptr offset); - gl.Call("readPixels", 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0) - gl.Call("bindBuffer", gles.PIXEL_PACK_BUFFER, nil) + gl.readPixels.Invoke(0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0) + gl.bindBuffer.Invoke(gles.PIXEL_PACK_BUFFER, nil) } func (c *context) activeTexture(idx int) { gl := c.gl - gl.Call("activeTexture", gles.TEXTURE0+idx) + gl.activeTexture.Invoke(gles.TEXTURE0 + idx) } func (c *context) bindTextureImpl(t textureNative) { gl := c.gl - gl.Call("bindTexture", gles.TEXTURE_2D, js.Value(t)) + gl.bindTexture.Invoke(gles.TEXTURE_2D, js.Value(t)) } func (c *context) deleteTexture(t textureNative) { gl := c.gl - if !gl.Call("isTexture", js.Value(t)).Bool() { + if !gl.isTexture.Invoke(js.Value(t)).Bool() { return } if c.lastTexture.equal(t) { c.lastTexture = textureNative(js.Null()) } - gl.Call("deleteTexture", js.Value(t)) + gl.deleteTexture.Invoke(js.Value(t)) } func (c *context) isTexture(t textureNative) bool { @@ -246,11 +244,11 @@ func (c *context) isTexture(t textureNative) bool { func (c *context) newFramebuffer(t textureNative) (framebufferNative, error) { gl := c.gl - f := gl.Call("createFramebuffer") + f := gl.createFramebuffer.Invoke() c.bindFramebuffer(framebufferNative(f)) - gl.Call("framebufferTexture2D", gles.FRAMEBUFFER, gles.COLOR_ATTACHMENT0, gles.TEXTURE_2D, js.Value(t), 0) - if s := gl.Call("checkFramebufferStatus", gles.FRAMEBUFFER); s.Int() != gles.FRAMEBUFFER_COMPLETE { + gl.framebufferTexture2D.Invoke(gles.FRAMEBUFFER, gles.COLOR_ATTACHMENT0, gles.TEXTURE_2D, js.Value(t), 0) + if s := gl.checkFramebufferStatus.Invoke(gles.FRAMEBUFFER); s.Int() != gles.FRAMEBUFFER_COMPLETE { return framebufferNative(js.Null()), errors.New(fmt.Sprintf("opengl: creating framebuffer failed: %d", s.Int())) } @@ -259,12 +257,12 @@ func (c *context) newFramebuffer(t textureNative) (framebufferNative, error) { func (c *context) setViewportImpl(width, height int) { gl := c.gl - gl.Call("viewport", 0, 0, width, height) + gl.viewport.Invoke(0, 0, width, height) } func (c *context) deleteFramebuffer(f framebufferNative) { gl := c.gl - if !gl.Call("isFramebuffer", js.Value(f)).Bool() { + if !gl.isFramebuffer.Invoke(js.Value(f)).Bool() { return } // If a framebuffer to be deleted is bound, a newly bound framebuffer @@ -275,7 +273,7 @@ func (c *context) deleteFramebuffer(f framebufferNative) { c.lastViewportWidth = 0 c.lastViewportHeight = 0 } - gl.Call("deleteFramebuffer", js.Value(f)) + gl.deleteFramebuffer.Invoke(js.Value(f)) } func (c *context) newVertexShader(source string) (shader, error) { @@ -288,16 +286,16 @@ func (c *context) newFragmentShader(source string) (shader, error) { func (c *context) newShader(shaderType int, source string) (shader, error) { gl := c.gl - s := gl.Call("createShader", int(shaderType)) + s := gl.createShader.Invoke(int(shaderType)) if jsutil.Equal(s, js.Null()) { return shader(js.Null()), fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType) } - gl.Call("shaderSource", js.Value(s), source) - gl.Call("compileShader", js.Value(s)) + gl.shaderSource.Invoke(js.Value(s), source) + gl.compileShader.Invoke(js.Value(s)) - if !gl.Call("getShaderParameter", js.Value(s), gles.COMPILE_STATUS).Bool() { - log := gl.Call("getShaderInfoLog", js.Value(s)) + if !gl.getShaderParameter.Invoke(js.Value(s), gles.COMPILE_STATUS).Bool() { + log := gl.getShaderInfoLog.Invoke(js.Value(s)) return shader(js.Null()), fmt.Errorf("opengl: shader compile failed: %s", log) } return shader(s), nil @@ -305,27 +303,27 @@ func (c *context) newShader(shaderType int, source string) (shader, error) { func (c *context) deleteShader(s shader) { gl := c.gl - gl.Call("deleteShader", js.Value(s)) + gl.deleteShader.Invoke(js.Value(s)) } func (c *context) newProgram(shaders []shader, attributes []string) (program, error) { gl := c.gl - v := gl.Call("createProgram") + v := gl.createProgram.Invoke() if jsutil.Equal(v, js.Null()) { return program{}, errors.New("opengl: glCreateProgram failed") } for _, shader := range shaders { - gl.Call("attachShader", v, js.Value(shader)) + gl.attachShader.Invoke(v, js.Value(shader)) } for i, name := range attributes { - gl.Call("bindAttribLocation", v, i, name) + gl.bindAttribLocation.Invoke(v, i, name) } - gl.Call("linkProgram", v) - if !gl.Call("getProgramParameter", v, gles.LINK_STATUS).Bool() { - info := gl.Call("getProgramInfoLog", v).String() + gl.linkProgram.Invoke(v) + if !gl.getProgramParameter.Invoke(v, gles.LINK_STATUS).Bool() { + info := gl.getProgramInfoLog.Invoke(v).String() return program{}, fmt.Errorf("opengl: program error: %s", info) } @@ -339,20 +337,20 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er func (c *context) useProgram(p program) { gl := c.gl - gl.Call("useProgram", p.value) + gl.useProgram.Invoke(p.value) } func (c *context) deleteProgram(p program) { gl := c.gl - if !gl.Call("isProgram", p.value).Bool() { + if !gl.isProgram.Invoke(p.value).Bool() { return } - gl.Call("deleteProgram", p.value) + gl.deleteProgram.Invoke(p.value) } func (c *context) getUniformLocationImpl(p program, location string) uniformLocation { gl := c.gl - return uniformLocation(gl.Call("getUniformLocation", p.value, location)) + return uniformLocation(gl.getUniformLocation.Invoke(p.value, location)) } func (c *context) uniformInt(p program, location string, v int) bool { @@ -361,7 +359,7 @@ func (c *context) uniformInt(p program, location string, v int) bool { if l.equal(invalidUniform) { return false } - gl.Call("uniform1i", js.Value(l), v) + gl.uniform1i.Invoke(js.Value(l), v) return true } @@ -371,7 +369,7 @@ func (c *context) uniformFloat(p program, location string, v float32) bool { if l.equal(invalidUniform) { return false } - gl.Call("uniform1f", js.Value(l), v) + gl.uniform1f.Invoke(js.Value(l), v) return true } @@ -392,45 +390,45 @@ func (c *context) uniformFloats(p program, location string, v []float32, typ sha switch base { case shaderir.Float: if isWebGL2Available { - gl.Call("uniform1fv", js.Value(l), arr, 0, len(v)) + gl.uniform1fv.Invoke(js.Value(l), arr, 0, len(v)) } else { - gl.Call("uniform1fv", js.Value(l), arr.Call("subarray", 0, len(v))) + gl.uniform1fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) } case shaderir.Vec2: if isWebGL2Available { - gl.Call("uniform2fv", js.Value(l), arr, 0, len(v)) + gl.uniform2fv.Invoke(js.Value(l), arr, 0, len(v)) } else { - gl.Call("uniform2fv", js.Value(l), arr.Call("subarray", 0, len(v))) + gl.uniform2fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) } case shaderir.Vec3: if isWebGL2Available { - gl.Call("uniform3fv", js.Value(l), arr, 0, len(v)) + gl.uniform3fv.Invoke(js.Value(l), arr, 0, len(v)) } else { - gl.Call("uniform3fv", js.Value(l), arr.Call("subarray", 0, len(v))) + gl.uniform3fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) } case shaderir.Vec4: if isWebGL2Available { - gl.Call("uniform4fv", js.Value(l), arr, 0, len(v)) + gl.uniform4fv.Invoke(js.Value(l), arr, 0, len(v)) } else { - gl.Call("uniform4fv", js.Value(l), arr.Call("subarray", 0, len(v))) + gl.uniform4fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) } case shaderir.Mat2: if isWebGL2Available { - gl.Call("uniformMatrix2fv", js.Value(l), false, arr, 0, len(v)) + gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr, 0, len(v)) } else { - gl.Call("uniformMatrix2fv", js.Value(l), false, arr.Call("subarray", 0, len(v))) + gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) } case shaderir.Mat3: if isWebGL2Available { - gl.Call("uniformMatrix3fv", js.Value(l), false, arr, 0, len(v)) + gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr, 0, len(v)) } else { - gl.Call("uniformMatrix3fv", js.Value(l), false, arr.Call("subarray", 0, len(v))) + gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) } case shaderir.Mat4: if isWebGL2Available { - gl.Call("uniformMatrix4fv", js.Value(l), false, arr, 0, len(v)) + gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr, 0, len(v)) } else { - gl.Call("uniformMatrix4fv", js.Value(l), false, arr.Call("subarray", 0, len(v))) + gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) } default: panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String())) @@ -441,43 +439,43 @@ func (c *context) uniformFloats(p program, location string, v []float32, typ sha func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) { gl := c.gl - gl.Call("vertexAttribPointer", index, size, gles.FLOAT, false, stride, offset) + gl.vertexAttribPointer.Invoke(index, size, gles.FLOAT, false, stride, offset) } func (c *context) enableVertexAttribArray(index int) { gl := c.gl - gl.Call("enableVertexAttribArray", index) + gl.enableVertexAttribArray.Invoke(index) } func (c *context) disableVertexAttribArray(index int) { gl := c.gl - gl.Call("disableVertexAttribArray", index) + gl.disableVertexAttribArray.Invoke(index) } func (c *context) newArrayBuffer(size int) buffer { gl := c.gl - b := gl.Call("createBuffer") - gl.Call("bindBuffer", gles.ARRAY_BUFFER, js.Value(b)) - gl.Call("bufferData", gles.ARRAY_BUFFER, size, gles.DYNAMIC_DRAW) + b := gl.createBuffer.Invoke() + gl.bindBuffer.Invoke(gles.ARRAY_BUFFER, js.Value(b)) + gl.bufferData.Invoke(gles.ARRAY_BUFFER, size, gles.DYNAMIC_DRAW) return buffer(b) } func (c *context) newElementArrayBuffer(size int) buffer { gl := c.gl - b := gl.Call("createBuffer") - gl.Call("bindBuffer", gles.ELEMENT_ARRAY_BUFFER, js.Value(b)) - gl.Call("bufferData", gles.ELEMENT_ARRAY_BUFFER, size, gles.DYNAMIC_DRAW) + b := gl.createBuffer.Invoke() + gl.bindBuffer.Invoke(gles.ELEMENT_ARRAY_BUFFER, js.Value(b)) + gl.bufferData.Invoke(gles.ELEMENT_ARRAY_BUFFER, size, gles.DYNAMIC_DRAW) return buffer(b) } func (c *context) bindArrayBuffer(b buffer) { gl := c.gl - gl.Call("bindBuffer", gles.ARRAY_BUFFER, js.Value(b)) + gl.bindBuffer.Invoke(gles.ARRAY_BUFFER, js.Value(b)) } func (c *context) bindElementArrayBuffer(b buffer) { gl := c.gl - gl.Call("bindBuffer", gles.ELEMENT_ARRAY_BUFFER, js.Value(b)) + gl.bindBuffer.Invoke(gles.ELEMENT_ARRAY_BUFFER, js.Value(b)) } func (c *context) arrayBufferSubData(data []float32) { @@ -485,9 +483,9 @@ func (c *context) arrayBufferSubData(data []float32) { l := len(data) * 4 arr := jsutil.TemporaryUint8Array(l, data) if isWebGL2Available { - gl.Call("bufferSubData", gles.ARRAY_BUFFER, 0, arr, 0, l) + gl.bufferSubData.Invoke(gles.ARRAY_BUFFER, 0, arr, 0, l) } else { - gl.Call("bufferSubData", gles.ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) + gl.bufferSubData.Invoke(gles.ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) } } @@ -496,35 +494,35 @@ func (c *context) elementArrayBufferSubData(data []uint16) { l := len(data) * 2 arr := jsutil.TemporaryUint8Array(l, data) if isWebGL2Available { - gl.Call("bufferSubData", gles.ELEMENT_ARRAY_BUFFER, 0, arr, 0, l) + gl.bufferSubData.Invoke(gles.ELEMENT_ARRAY_BUFFER, 0, arr, 0, l) } else { - gl.Call("bufferSubData", gles.ELEMENT_ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) + gl.bufferSubData.Invoke(gles.ELEMENT_ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) } } func (c *context) deleteBuffer(b buffer) { gl := c.gl - gl.Call("deleteBuffer", js.Value(b)) + gl.deleteBuffer.Invoke(js.Value(b)) } func (c *context) drawElements(len int, offsetInBytes int) { gl := c.gl - gl.Call("drawElements", gles.TRIANGLES, len, gles.UNSIGNED_SHORT, offsetInBytes) + gl.drawElements.Invoke(gles.TRIANGLES, len, gles.UNSIGNED_SHORT, offsetInBytes) } func (c *context) maxTextureSizeImpl() int { gl := c.gl - return gl.Call("getParameter", gles.MAX_TEXTURE_SIZE).Int() + return gl.getParameter.Invoke(gles.MAX_TEXTURE_SIZE).Int() } func (c *context) getShaderPrecisionFormatPrecision() int { gl := c.gl - return gl.Call("getShaderPrecisionFormat", gles.FRAGMENT_SHADER, gles.HIGH_FLOAT).Get("precision").Int() + return gl.getShaderPrecisionFormat.Invoke(gles.FRAGMENT_SHADER, gles.HIGH_FLOAT).Get("precision").Int() } func (c *context) flush() { gl := c.gl - gl.Call("flush") + gl.flush.Invoke() } func (c *context) needsRestoring() bool { @@ -544,22 +542,22 @@ func (c *context) texSubImage2D(t textureNative, width, height int, args []*driv // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // GLsizei width, GLsizei height, // GLenum format, GLenum type, ArrayBufferView pixels, srcOffset); - gl.Call("texSubImage2D", gles.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gles.RGBA, gles.UNSIGNED_BYTE, arr, 0) + gl.texSubImage2D.Invoke(gles.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gles.RGBA, gles.UNSIGNED_BYTE, arr, 0) } else { // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // GLsizei width, GLsizei height, // GLenum format, GLenum type, ArrayBufferView? pixels); - gl.Call("texSubImage2D", gles.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gles.RGBA, gles.UNSIGNED_BYTE, arr) + gl.texSubImage2D.Invoke(gles.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gles.RGBA, gles.UNSIGNED_BYTE, arr) } } } func (c *context) newPixelBufferObject(width, height int) buffer { gl := c.gl - b := gl.Call("createBuffer") - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, js.Value(b)) - gl.Call("bufferData", gles.PIXEL_UNPACK_BUFFER, 4*width*height, gles.STREAM_DRAW) - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, nil) + b := gl.createBuffer.Invoke() + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, js.Value(b)) + gl.bufferData.Invoke(gles.PIXEL_UNPACK_BUFFER, 4*width*height, gles.STREAM_DRAW) + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, nil) return buffer(b) } @@ -570,34 +568,34 @@ func (c *context) replacePixelsWithPBO(buffer buffer, t textureNative, width, he c.bindTexture(t) gl := c.gl - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, js.Value(buffer)) + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, js.Value(buffer)) stride := 4 * width for _, a := range args { arr := jsutil.TemporaryUint8Array(len(a.Pixels), a.Pixels) offset := 4 * (a.Y*width + a.X) for j := 0; j < a.Height; j++ { - gl.Call("bufferSubData", gles.PIXEL_UNPACK_BUFFER, offset+stride*j, arr, 4*a.Width*j, 4*a.Width) + gl.bufferSubData.Invoke(gles.PIXEL_UNPACK_BUFFER, offset+stride*j, arr, 4*a.Width*j, 4*a.Width) } } // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // GLsizei width, GLsizei height, // GLenum format, GLenum type, GLintptr offset); - gl.Call("texSubImage2D", gles.TEXTURE_2D, 0, 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0) - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, nil) + gl.texSubImage2D.Invoke(gles.TEXTURE_2D, 0, 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0) + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, nil) } func (c *context) getBufferSubData(buffer buffer, width, height int) []byte { gl := c.gl - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, js.Value(buffer)) + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, js.Value(buffer)) l := 4 * width * height arr := jsutil.TemporaryUint8Array(l, nil) if isWebGL2Available { - gl.Call("getBufferSubData", gles.PIXEL_UNPACK_BUFFER, 0, arr, 0, l) + gl.getBufferSubData.Invoke(gles.PIXEL_UNPACK_BUFFER, 0, arr, 0, l) } else { - gl.Call("getBufferSubData", gles.PIXEL_UNPACK_BUFFER, 0, arr.Call("subarray", 0, l)) + gl.getBufferSubData.Invoke(gles.PIXEL_UNPACK_BUFFER, 0, arr.Call("subarray", 0, l)) } - gl.Call("bindBuffer", gles.PIXEL_UNPACK_BUFFER, nil) + gl.bindBuffer.Invoke(gles.PIXEL_UNPACK_BUFFER, nil) return jsutil.Uint8ArrayToSlice(arr, l) } diff --git a/internal/graphicsdriver/opengl/gl_js.go b/internal/graphicsdriver/opengl/gl_js.go new file mode 100644 index 000000000..5cd08d37f --- /dev/null +++ b/internal/graphicsdriver/opengl/gl_js.go @@ -0,0 +1,152 @@ +// Copyright 2021 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package opengl + +import ( + "syscall/js" +) + +type gl struct { + activeTexture js.Value + attachShader js.Value + bindAttribLocation js.Value + bindBuffer js.Value + bindFramebuffer js.Value + bindTexture js.Value + blendFunc js.Value + bufferData js.Value + bufferSubData js.Value + checkFramebufferStatus js.Value + compileShader js.Value + createBuffer js.Value + createFramebuffer js.Value + createProgram js.Value + createShader js.Value + createTexture js.Value + deleteBuffer js.Value + deleteFramebuffer js.Value + deleteProgram js.Value + deleteShader js.Value + deleteTexture js.Value + disableVertexAttribArray js.Value + drawElements js.Value + enable js.Value + enableVertexAttribArray js.Value + framebufferTexture2D js.Value + flush js.Value + getBufferSubData js.Value + getExtension js.Value + getParameter js.Value + getProgramInfoLog js.Value + getProgramParameter js.Value + getShaderInfoLog js.Value + getShaderParameter js.Value + getShaderPrecisionFormat js.Value + getUniformLocation js.Value + isContextLost js.Value + isFramebuffer js.Value + isProgram js.Value + isTexture js.Value + linkProgram js.Value + pixelStorei js.Value + readPixels js.Value + scissor js.Value + shaderSource js.Value + texImage2D js.Value + texSubImage2D js.Value + texParameteri js.Value + uniform1f js.Value + uniform1fv js.Value + uniform2fv js.Value + uniform3fv js.Value + uniform4fv js.Value + uniform1i js.Value + uniformMatrix2fv js.Value + uniformMatrix3fv js.Value + uniformMatrix4fv js.Value + useProgram js.Value + vertexAttribPointer js.Value + viewport js.Value +} + +func newGL(v js.Value) *gl { + // Passing a Go string to the JS world is expensive. This causes conversion to UTF-16 (#1438). + // In order to reduce the cost when calling functions, create the function objects by bind and use them. + g := &gl{ + activeTexture: v.Get("activeTexture").Call("bind", v), + attachShader: v.Get("attachShader").Call("bind", v), + bindAttribLocation: v.Get("bindAttribLocation").Call("bind", v), + bindBuffer: v.Get("bindBuffer").Call("bind", v), + bindFramebuffer: v.Get("bindFramebuffer").Call("bind", v), + bindTexture: v.Get("bindTexture").Call("bind", v), + blendFunc: v.Get("blendFunc").Call("bind", v), + bufferData: v.Get("bufferData").Call("bind", v), + bufferSubData: v.Get("bufferSubData").Call("bind", v), + checkFramebufferStatus: v.Get("checkFramebufferStatus").Call("bind", v), + compileShader: v.Get("compileShader").Call("bind", v), + createBuffer: v.Get("createBuffer").Call("bind", v), + createFramebuffer: v.Get("createFramebuffer").Call("bind", v), + createProgram: v.Get("createProgram").Call("bind", v), + createShader: v.Get("createShader").Call("bind", v), + createTexture: v.Get("createTexture").Call("bind", v), + deleteBuffer: v.Get("deleteBuffer").Call("bind", v), + deleteFramebuffer: v.Get("deleteFramebuffer").Call("bind", v), + deleteProgram: v.Get("deleteProgram").Call("bind", v), + deleteShader: v.Get("deleteShader").Call("bind", v), + deleteTexture: v.Get("deleteTexture").Call("bind", v), + disableVertexAttribArray: v.Get("disableVertexAttribArray").Call("bind", v), + drawElements: v.Get("drawElements").Call("bind", v), + enable: v.Get("enable").Call("bind", v), + enableVertexAttribArray: v.Get("enableVertexAttribArray").Call("bind", v), + framebufferTexture2D: v.Get("framebufferTexture2D").Call("bind", v), + flush: v.Get("flush").Call("bind", v), + getBufferSubData: v.Get("getBufferSubData").Call("bind", v), + getParameter: v.Get("getParameter").Call("bind", v), + getProgramInfoLog: v.Get("getProgramInfoLog").Call("bind", v), + getProgramParameter: v.Get("getProgramParameter").Call("bind", v), + getShaderInfoLog: v.Get("getShaderInfoLog").Call("bind", v), + getShaderParameter: v.Get("getShaderParameter").Call("bind", v), + getShaderPrecisionFormat: v.Get("getShaderPrecisionFormat").Call("bind", v), + getUniformLocation: v.Get("getUniformLocation").Call("bind", v), + isContextLost: v.Get("isContextLost").Call("bind", v), + isFramebuffer: v.Get("isFramebuffer").Call("bind", v), + isProgram: v.Get("isProgram").Call("bind", v), + isTexture: v.Get("isTexture").Call("bind", v), + linkProgram: v.Get("linkProgram").Call("bind", v), + pixelStorei: v.Get("pixelStorei").Call("bind", v), + readPixels: v.Get("readPixels").Call("bind", v), + scissor: v.Get("scissor").Call("bind", v), + shaderSource: v.Get("shaderSource").Call("bind", v), + texImage2D: v.Get("texImage2D").Call("bind", v), + texSubImage2D: v.Get("texSubImage2D").Call("bind", v), + texParameteri: v.Get("texParameteri").Call("bind", v), + uniform1f: v.Get("uniform1f").Call("bind", v), + uniform1fv: v.Get("uniform1fv").Call("bind", v), + uniform2fv: v.Get("uniform2fv").Call("bind", v), + uniform3fv: v.Get("uniform3fv").Call("bind", v), + uniform4fv: v.Get("uniform4fv").Call("bind", v), + uniform1i: v.Get("uniform1i").Call("bind", v), + uniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v), + uniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v), + uniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v), + useProgram: v.Get("useProgram").Call("bind", v), + vertexAttribPointer: v.Get("vertexAttribPointer").Call("bind", v), + viewport: v.Get("viewport").Call("bind", v), + } + if !isWebGL2Available { + g.getExtension = v.Get("getExtension").Call("bind", v) + } + return g +}