From 95b4e67c770fb39a1173b013e3204d13f15acb92 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 17 Nov 2022 13:33:32 +0900 Subject: [PATCH] internal/graphicsdriver/opengl: reduce context functions --- internal/graphicsdriver/opengl/context.go | 126 +----------------- internal/graphicsdriver/opengl/graphics.go | 34 +++-- .../graphicsdriver/opengl/graphics_glfw.go | 2 +- internal/graphicsdriver/opengl/image.go | 12 +- .../graphicsdriver/opengl/locationcache.go | 2 +- internal/graphicsdriver/opengl/program.go | 23 ++-- internal/graphicsdriver/opengl/shader.go | 9 +- .../graphicsdriver/opengl/shader_notjs.go | 2 +- 8 files changed, 55 insertions(+), 155 deletions(-) diff --git a/internal/graphicsdriver/opengl/context.go b/internal/graphicsdriver/opengl/context.go index 7a4d26afd..328e47204 100644 --- a/internal/graphicsdriver/opengl/context.go +++ b/internal/graphicsdriver/opengl/context.go @@ -134,7 +134,7 @@ func (c *context) bindTexture(t textureNative) { if c.lastTexture == t { return } - c.bindTextureImpl(t) + c.ctx.BindTexture(gl.TEXTURE_2D, uint32(t)) c.lastTexture = t } @@ -142,7 +142,7 @@ func (c *context) bindRenderbuffer(r renderbufferNative) { if c.lastRenderbuffer == r { return } - c.bindRenderbufferImpl(r) + c.ctx.BindRenderbuffer(gl.RENDERBUFFER, uint32(r)) c.lastRenderbuffer = r } @@ -150,7 +150,7 @@ func (c *context) bindFramebuffer(f framebufferNative) { if c.lastFramebuffer == f { return } - c.bindFramebufferImpl(f) + c.ctx.BindFramebuffer(gl.FRAMEBUFFER, uint32(f)) c.lastFramebuffer = f } @@ -160,7 +160,7 @@ func (c *context) setViewport(f *framebuffer) { // On some environments, viewport size must be within the framebuffer size. // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). // Use the same size of the framebuffer here. - c.setViewportImpl(f.width, f.height) + c.ctx.Viewport(0, 0, int32(f.width), int32(f.height)) // glViewport must be called at least at every frame on iOS. // As the screen framebuffer is the last render target, next SetViewport should be @@ -181,7 +181,7 @@ func (c *context) getScreenFramebuffer() framebufferNative { func (c *context) getMaxTextureSize() int { c.maxTextureSizeOnce.Do(func() { - c.maxTextureSize = c.maxTextureSizeImpl() + c.maxTextureSize = c.ctx.GetInteger(gl.MAX_TEXTURE_SIZE) }) return c.maxTextureSize } @@ -231,10 +231,6 @@ func (c *context) blend(blend graphicsdriver.Blend) { ) } -func (c *context) scissor(x, y, width, height int) { - c.ctx.Scissor(int32(x), int32(y), int32(width), int32(height)) -} - func (c *context) newTexture(width, height int) (textureNative, error) { t := c.ctx.CreateTexture() if t <= 0 { @@ -260,10 +256,6 @@ func (c *context) newTexture(width, height int) (textureNative, error) { return textureNative(t), nil } -func (c *context) bindFramebufferImpl(f framebufferNative) { - c.ctx.BindFramebuffer(gl.FRAMEBUFFER, uint32(f)) -} - func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) error { if got, want := len(buf), 4*width*height; got != want { return fmt.Errorf("opengl: len(buf) must be %d but was %d at framebufferPixels", got, want) @@ -285,14 +277,6 @@ func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, 0) } -func (c *context) activeTexture(idx int) { - c.ctx.ActiveTexture(uint32(gl.TEXTURE0 + idx)) -} - -func (c *context) bindTextureImpl(t textureNative) { - c.ctx.BindTexture(gl.TEXTURE_2D, uint32(t)) -} - func (c *context) deleteTexture(t textureNative) { if !c.ctx.IsTexture(uint32(t)) { return @@ -303,10 +287,6 @@ func (c *context) deleteTexture(t textureNative) { c.ctx.DeleteTexture(uint32(t)) } -func (c *context) isTexture(t textureNative) bool { - return c.ctx.IsTexture(uint32(t)) -} - func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error) { r := c.ctx.CreateRenderbuffer() if r <= 0 { @@ -344,10 +324,6 @@ func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error) return renderbuffer, nil } -func (c *context) bindRenderbufferImpl(r renderbufferNative) { - c.ctx.BindRenderbuffer(gl.RENDERBUFFER, uint32(r)) -} - func (c *context) deleteRenderbuffer(r renderbufferNative) { if !c.ctx.IsRenderbuffer(uint32(r)) { return @@ -388,10 +364,6 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e return nil } -func (c *context) setViewportImpl(width, height int) { - c.ctx.Viewport(0, 0, int32(width), int32(height)) -} - func (c *context) deleteFramebuffer(f framebufferNative) { if !c.ctx.IsFramebuffer(uint32(f)) { return @@ -407,14 +379,6 @@ func (c *context) deleteFramebuffer(f framebufferNative) { c.ctx.DeleteFramebuffer(uint32(f)) } -func (c *context) newVertexShader(source string) (shader, error) { - return c.newShader(gl.VERTEX_SHADER, source) -} - -func (c *context) newFragmentShader(source string) (shader, error) { - return c.newShader(gl.FRAGMENT_SHADER, source) -} - func (c *context) newShader(shaderType uint32, source string) (shader, error) { s := c.ctx.CreateShader(shaderType) if s == 0 { @@ -431,10 +395,6 @@ func (c *context) newShader(shaderType uint32, source string) (shader, error) { return shader(s), nil } -func (c *context) deleteShader(s shader) { - c.ctx.DeleteShader(uint32(s)) -} - func (c *context) newProgram(shaders []shader, attributes []string) (program, error) { p := c.ctx.CreateProgram() if p == 0 { @@ -457,10 +417,6 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er return program(p), nil } -func (c *context) useProgram(p program) { - c.ctx.UseProgram(uint32(p)) -} - func (c *context) deleteProgram(p program) { c.locationCache.deleteProgram(p) @@ -470,10 +426,6 @@ func (c *context) deleteProgram(p program) { c.ctx.DeleteProgram(uint32(p)) } -func (c *context) getUniformLocationImpl(p program, location string) uniformLocation { - return uniformLocation(c.ctx.GetUniformLocation(uint32(p), location)) -} - func (c *context) uniformInt(p program, location string, v int) bool { l := c.locationCache.GetUniformLocation(c, p, location) if l == invalidUniform { @@ -517,18 +469,6 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir. return true } -func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) { - c.ctx.VertexAttribPointer(uint32(index), int32(size), gl.FLOAT, false, int32(stride), offset) -} - -func (c *context) enableVertexAttribArray(index int) { - c.ctx.EnableVertexAttribArray(uint32(index)) -} - -func (c *context) disableVertexAttribArray(index int) { - c.ctx.DisableVertexAttribArray(uint32(index)) -} - func (c *context) newArrayBuffer(size int) buffer { b := c.ctx.CreateBuffer() c.ctx.BindBuffer(gl.ARRAY_BUFFER, b) @@ -543,14 +483,6 @@ func (c *context) newElementArrayBuffer(size int) buffer { return buffer(b) } -func (c *context) bindArrayBuffer(b buffer) { - c.ctx.BindBuffer(gl.ARRAY_BUFFER, uint32(b)) -} - -func (c *context) bindElementArrayBuffer(b buffer) { - c.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(b)) -} - func (c *context) arrayBufferSubData(data []float32) { s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*4) c.ctx.BufferSubData(gl.ARRAY_BUFFER, 0, s) @@ -560,51 +492,3 @@ func (c *context) elementArrayBufferSubData(data []uint16) { s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*2) c.ctx.BufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, s) } - -func (c *context) deleteBuffer(b buffer) { - c.ctx.DeleteBuffer(uint32(b)) -} - -func (c *context) drawElements(len int, offsetInBytes int) { - c.ctx.DrawElements(gl.TRIANGLES, int32(len), gl.UNSIGNED_SHORT, offsetInBytes) -} - -func (c *context) maxTextureSizeImpl() int { - return c.ctx.GetInteger(gl.MAX_TEXTURE_SIZE) -} - -func (c *context) flush() { - c.ctx.Flush() -} - -func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) { - c.bindTexture(t) - for _, a := range args { - c.ctx.TexSubImage2D(gl.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), gl.RGBA, gl.UNSIGNED_BYTE, a.Pixels) - } -} - -func (c *context) enableStencilTest() { - c.ctx.Enable(gl.STENCIL_TEST) -} - -func (c *context) disableStencilTest() { - c.ctx.Disable(gl.STENCIL_TEST) -} - -func (c *context) beginStencilWithEvenOddRule() { - c.ctx.Clear(gl.STENCIL_BUFFER_BIT) - c.ctx.StencilFunc(gl.ALWAYS, 0x00, 0xff) - c.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.INVERT) - c.ctx.ColorMask(false, false, false, false) -} - -func (c *context) endStencilWithEvenOddRule() { - c.ctx.StencilFunc(gl.NOTEQUAL, 0x00, 0xff) - c.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) - c.ctx.ColorMask(true, true, true, true) -} - -func (c *context) isES() bool { - return c.ctx.IsES() -} diff --git a/internal/graphicsdriver/opengl/graphics.go b/internal/graphicsdriver/opengl/graphics.go index 3496103cf..eaed4d6b8 100644 --- a/internal/graphicsdriver/opengl/graphics.go +++ b/internal/graphicsdriver/opengl/graphics.go @@ -20,6 +20,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" "github.com/hajimehoshi/ebiten/v2/internal/shaderir" ) @@ -59,7 +60,7 @@ func (g *Graphics) Begin() error { func (g *Graphics) End(present bool) error { // Call glFlush to prevent black flicking (especially on Android (#226) and iOS). // TODO: examples/sprites worked without this. Is this really needed? - g.context.flush() + g.context.ctx.Flush() return nil } @@ -231,27 +232,34 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics. if err := destination.ensureStencilBuffer(); err != nil { return err } - g.context.enableStencilTest() + g.context.ctx.Enable(gl.STENCIL_TEST) } for _, dstRegion := range dstRegions { - g.context.scissor( - int(dstRegion.Region.X), - int(dstRegion.Region.Y), - int(dstRegion.Region.Width), - int(dstRegion.Region.Height), + g.context.ctx.Scissor( + int32(dstRegion.Region.X), + int32(dstRegion.Region.Y), + int32(dstRegion.Region.Width), + int32(dstRegion.Region.Height), ) if evenOdd { - g.context.beginStencilWithEvenOddRule() - g.context.drawElements(dstRegion.IndexCount, indexOffset*2) - g.context.endStencilWithEvenOddRule() + g.context.ctx.Clear(gl.STENCIL_BUFFER_BIT) + g.context.ctx.StencilFunc(gl.ALWAYS, 0x00, 0xff) + g.context.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.INVERT) + g.context.ctx.ColorMask(false, false, false, false) + + g.context.ctx.DrawElements(gl.TRIANGLES, int32(dstRegion.IndexCount), gl.UNSIGNED_SHORT, indexOffset*2) + + g.context.ctx.StencilFunc(gl.NOTEQUAL, 0x00, 0xff) + g.context.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) + g.context.ctx.ColorMask(true, true, true, true) } - g.context.drawElements(dstRegion.IndexCount, indexOffset*2) // 2 is uint16 size in bytes + g.context.ctx.DrawElements(gl.TRIANGLES, int32(dstRegion.IndexCount), gl.UNSIGNED_SHORT, indexOffset*2) // 2 is uint16 size in bytes indexOffset += dstRegion.IndexCount } if evenOdd { - g.context.disableStencilTest() + g.context.ctx.Disable(gl.STENCIL_TEST) } return nil @@ -270,7 +278,7 @@ func (g *Graphics) NeedsRestoring() bool { if runtime.GOOS == "js" { return false } - return g.context.isES() + return g.context.ctx.IsES() } func (g *Graphics) NeedsClearingScreen() bool { diff --git a/internal/graphicsdriver/opengl/graphics_glfw.go b/internal/graphicsdriver/opengl/graphics_glfw.go index 0b34343a9..52b9d71ce 100644 --- a/internal/graphicsdriver/opengl/graphics_glfw.go +++ b/internal/graphicsdriver/opengl/graphics_glfw.go @@ -21,7 +21,7 @@ import ( ) func (g *Graphics) SetGLFWClientAPI() { - if g.context.isES() { + if g.context.ctx.IsES() { glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLESAPI) glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 0) diff --git a/internal/graphicsdriver/opengl/image.go b/internal/graphicsdriver/opengl/image.go index 762bf2c9f..6c846491e 100644 --- a/internal/graphicsdriver/opengl/image.go +++ b/internal/graphicsdriver/opengl/image.go @@ -19,6 +19,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" ) type Image struct { @@ -37,7 +38,7 @@ func (i *Image) ID() graphicsdriver.ImageID { } func (i *Image) IsInvalidated() bool { - return !i.graphics.context.isTexture(i.texture) + return !i.graphics.context.ctx.IsTexture(uint32(i.texture)) } func (i *Image) Dispose() { @@ -132,9 +133,14 @@ func (i *Image) WritePixels(args []*graphicsdriver.WritePixelsArgs) error { // glFlush is necessary on Android. // glTexSubImage2D didn't work without this hack at least on Nexus 5x and NuAns NEO [Reloaded] (#211). if i.graphics.drawCalled { - i.graphics.context.flush() + i.graphics.context.ctx.Flush() } i.graphics.drawCalled = false - i.graphics.context.texSubImage2D(i.texture, args) + + i.graphics.context.bindTexture(i.texture) + for _, a := range args { + i.graphics.context.ctx.TexSubImage2D(gl.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), gl.RGBA, gl.UNSIGNED_BYTE, a.Pixels) + } + return nil } diff --git a/internal/graphicsdriver/opengl/locationcache.go b/internal/graphicsdriver/opengl/locationcache.go index b14943d7a..6a82581b9 100644 --- a/internal/graphicsdriver/opengl/locationcache.go +++ b/internal/graphicsdriver/opengl/locationcache.go @@ -30,7 +30,7 @@ func (c *locationCache) GetUniformLocation(context *context, p program, location } l, ok := c.uniformLocationCache[p][location] if !ok { - l = context.getUniformLocationImpl(p, location) + l = uniformLocation(context.ctx.GetUniformLocation(uint32(p), location)) c.uniformLocationCache[p][location] = l } return l diff --git a/internal/graphicsdriver/opengl/program.go b/internal/graphicsdriver/opengl/program.go index 404f4b4f2..20cef3de1 100644 --- a/internal/graphicsdriver/opengl/program.go +++ b/internal/graphicsdriver/opengl/program.go @@ -20,6 +20,7 @@ import ( "unsafe" "github.com/hajimehoshi/ebiten/v2/internal/graphics" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" "github.com/hajimehoshi/ebiten/v2/internal/shaderir" ) @@ -70,12 +71,12 @@ func (a *arrayBufferLayout) newArrayBuffer(context *context) buffer { // enable starts using the array buffer. func (a *arrayBufferLayout) enable(context *context) { for i := range a.parts { - context.enableVertexAttribArray(i) + context.ctx.EnableVertexAttribArray(uint32(i)) } total := a.totalBytes() offset := 0 for i, p := range a.parts { - context.vertexAttribPointer(i, p.num, total, offset) + context.ctx.VertexAttribPointer(uint32(i), int32(p.num), gl.FLOAT, false, int32(total), offset) offset += floatSizeInBytes * p.num } } @@ -84,7 +85,7 @@ func (a *arrayBufferLayout) enable(context *context) { func (a *arrayBufferLayout) disable(context *context) { // TODO: Disabling should be done in reversed order? for i := range a.parts { - context.disableVertexAttribArray(i) + context.ctx.DisableVertexAttribArray(uint32(i)) } } @@ -134,7 +135,7 @@ func (s *openGLState) reset(context *context) error { } s.lastProgram = 0 - context.useProgram(0) + context.ctx.UseProgram(0) for key := range s.lastUniforms { delete(s.lastUniforms, key) } @@ -143,10 +144,10 @@ func (s *openGLState) reset(context *context) error { // and must not be deleted by DeleteBuffer. if runtime.GOOS != "js" { if s.arrayBuffer != 0 { - context.deleteBuffer(s.arrayBuffer) + context.ctx.DeleteBuffer(uint32(s.arrayBuffer)) } if s.elementArrayBuffer != 0 { - context.deleteBuffer(s.elementArrayBuffer) + context.ctx.DeleteBuffer(uint32(s.elementArrayBuffer)) } } @@ -199,11 +200,11 @@ func (g *Graphics) textureVariableName(idx int) string { // useProgram uses the program (programTexture). func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures [graphics.ShaderImageCount]textureVariable) error { if g.state.lastProgram != program { - g.context.useProgram(program) + g.context.ctx.UseProgram(uint32(program)) if g.state.lastProgram == 0 { theArrayBufferLayout.enable(&g.context) - g.context.bindArrayBuffer(g.state.arrayBuffer) - g.context.bindElementArrayBuffer(g.state.elementArrayBuffer) + g.context.ctx.BindBuffer(gl.ARRAY_BUFFER, uint32(g.state.arrayBuffer)) + g.context.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(g.state.elementArrayBuffer)) } g.state.lastProgram = program @@ -211,7 +212,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu delete(g.state.lastUniforms, k) } g.state.lastActiveTexture = 0 - g.context.activeTexture(0) + g.context.ctx.ActiveTexture(gl.TEXTURE0) } for _, u := range uniforms { @@ -258,7 +259,7 @@ loop: }) g.context.uniformInt(program, g.textureVariableName(i), idx) if g.state.lastActiveTexture != idx { - g.context.activeTexture(idx) + g.context.ctx.ActiveTexture(uint32(gl.TEXTURE0 + idx)) g.state.lastActiveTexture = idx } diff --git a/internal/graphicsdriver/opengl/shader.go b/internal/graphicsdriver/opengl/shader.go index 965f02ce2..06336e269 100644 --- a/internal/graphicsdriver/opengl/shader.go +++ b/internal/graphicsdriver/opengl/shader.go @@ -18,6 +18,7 @@ import ( "fmt" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" "github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl" ) @@ -54,17 +55,17 @@ func (s *Shader) Dispose() { func (s *Shader) compile() error { vssrc, fssrc := glsl.Compile(s.ir, s.graphics.context.glslVersion()) - vs, err := s.graphics.context.newVertexShader(vssrc) + vs, err := s.graphics.context.newShader(gl.VERTEX_SHADER, vssrc) if err != nil { return fmt.Errorf("opengl: vertex shader compile error: %v, source:\n%s", err, vssrc) } - defer s.graphics.context.deleteShader(vs) + defer s.graphics.context.ctx.DeleteShader(uint32(vs)) - fs, err := s.graphics.context.newFragmentShader(fssrc) + fs, err := s.graphics.context.newShader(gl.FRAGMENT_SHADER, fssrc) if err != nil { return fmt.Errorf("opengl: fragment shader compile error: %v, source:\n%s", err, fssrc) } - defer s.graphics.context.deleteShader(fs) + defer s.graphics.context.ctx.DeleteShader(uint32(fs)) p, err := s.graphics.context.newProgram([]shader{vs, fs}, theArrayBufferLayout.names()) if err != nil { diff --git a/internal/graphicsdriver/opengl/shader_notjs.go b/internal/graphicsdriver/opengl/shader_notjs.go index 307a17621..e44d736f8 100644 --- a/internal/graphicsdriver/opengl/shader_notjs.go +++ b/internal/graphicsdriver/opengl/shader_notjs.go @@ -21,7 +21,7 @@ import ( ) func (c *context) glslVersion() glsl.GLSLVersion { - if c.isES() { + if c.ctx.IsES() { return glsl.GLSLVersionES100 } return glsl.GLSLVersionDefault