From 8cbf545e0f9b361c47e057230cb4d5448b5cb560 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 22 Mar 2023 17:26:38 +0900 Subject: [PATCH] internal/graphicsdriver/opengl: revert commits for graphics.Indices This change reverts these commits: * 13d3a0487b04c4bc0cc220f78a1ded683ce741e4 * 4cd98d512e529d7c65859e2449a0ffdecb018b9f Reason: this caused crashes on Android. Updates #2460 Closes #2610 --- internal/graphics/vertex.go | 2 +- internal/graphicsdriver/opengl/context.go | 20 ++++++-- internal/graphicsdriver/opengl/graphics.go | 7 ++- internal/graphicsdriver/opengl/program.go | 58 ++++++++++++---------- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/internal/graphics/vertex.go b/internal/graphics/vertex.go index f8d5c114b..20a6fd3fd 100644 --- a/internal/graphics/vertex.go +++ b/internal/graphics/vertex.go @@ -48,7 +48,7 @@ const ( ) const ( - IndicesCount = (1 << 16) / 3 * 3 // Adjust num for triangles. TODO: Remove this (#2460). + IndicesCount = (1 << 16) / 3 * 3 // Adjust num for triangles. VertexFloatCount = 8 ) diff --git a/internal/graphicsdriver/opengl/context.go b/internal/graphicsdriver/opengl/context.go index d4799e023..23df2e56b 100644 --- a/internal/graphicsdriver/opengl/context.go +++ b/internal/graphicsdriver/opengl/context.go @@ -124,6 +124,7 @@ type context struct { maxTextureSizeOnce sync.Once highp bool highpOnce sync.Once + initOnce sync.Once contextPlatform } @@ -190,14 +191,25 @@ func (c *context) getMaxTextureSize() int { return c.maxTextureSize } -func (c *context) init() error { - // Load OpenGL functions after WGL is initialized especially for Windows (#2452). - if err := c.ctx.LoadFunctions(); err != nil { - return err +func (c *context) reset() error { + var err1 error + c.initOnce.Do(func() { + // Load OpenGL functions after WGL is initialized especially for Windows (#2452). + if err := c.ctx.LoadFunctions(); err != nil { + err1 = err + return + } + }) + if err1 != nil { + return err1 } c.locationCache = newLocationCache() + c.lastTexture = 0 c.lastFramebuffer = invalidFramebuffer + c.lastViewportWidth = 0 + c.lastViewportHeight = 0 + c.lastBlend = graphicsdriver.Blend{} c.ctx.Enable(gl.BLEND) c.ctx.Enable(gl.SCISSOR_TEST) diff --git a/internal/graphicsdriver/opengl/graphics.go b/internal/graphicsdriver/opengl/graphics.go index 72fcbb648..15d1774ff 100644 --- a/internal/graphicsdriver/opengl/graphics.go +++ b/internal/graphicsdriver/opengl/graphics.go @@ -146,7 +146,12 @@ func (g *Graphics) removeImage(img *Image) { } func (g *Graphics) Initialize() error { - return g.context.init() + return g.state.reset(&g.context) +} + +// Reset resets or initializes the current OpenGL state. +func (g *Graphics) Reset() error { + return g.state.reset(&g.context) } func (g *Graphics) SetVertices(vertices []float32, indices []uint16) error { diff --git a/internal/graphicsdriver/opengl/program.go b/internal/graphicsdriver/opengl/program.go index 55fe5ed31..99fe7da0d 100644 --- a/internal/graphicsdriver/opengl/program.go +++ b/internal/graphicsdriver/opengl/program.go @@ -16,6 +16,7 @@ package opengl import ( "fmt" + "runtime" "unsafe" "github.com/hajimehoshi/ebiten/v2/internal/graphics" @@ -113,50 +114,50 @@ type openGLState struct { // arrayBuffer is OpenGL's array buffer (vertices data). arrayBuffer buffer - arrayBufferSizeInBytes int - // elementArrayBuffer is OpenGL's element array buffer (indices data). elementArrayBuffer buffer - elementArrayBufferSizeInBytes int - lastProgram program lastUniforms map[string][]uint32 lastActiveTexture int } -func pow2(x int) int { - p2 := 1 - for p2 < x { - p2 *= 2 +// reset resets or initializes the OpenGL state. +func (s *openGLState) reset(context *context) error { + if err := context.reset(); err != nil { + return err } - return p2 -} -func (s *openGLState) setVertices(context *context, vertices []float32, indices []uint16) { - if size := len(vertices) * 4; s.arrayBufferSizeInBytes < size { + s.lastProgram = 0 + context.ctx.UseProgram(0) + for key := range s.lastUniforms { + delete(s.lastUniforms, key) + } + + // On browsers (at least Chrome), buffers are already detached from the context + // and must not be deleted by DeleteBuffer. + if runtime.GOOS != "js" { if s.arrayBuffer != 0 { context.ctx.DeleteBuffer(uint32(s.arrayBuffer)) } - - newSize := pow2(size) - // newArrayBuffer calls BindBuffer. - s.arrayBuffer = context.newArrayBuffer(newSize) - s.arrayBufferSizeInBytes = newSize - - // Reenable the array buffer layouter explicitly after resetting the array buffer. - theArrayBufferLayout.enable(context) - } - - if size := len(indices) * 2; s.elementArrayBufferSizeInBytes < size { if s.elementArrayBuffer != 0 { context.ctx.DeleteBuffer(uint32(s.elementArrayBuffer)) } + } + s.arrayBuffer = 0 + s.elementArrayBuffer = 0 - newSize := pow2(size) - // newElementArrayBuffer calls BindBuffer. - s.elementArrayBuffer = context.newElementArrayBuffer(newSize) - s.elementArrayBufferSizeInBytes = newSize + return nil +} + +func (s *openGLState) setVertices(context *context, vertices []float32, indices []uint16) { + if s.arrayBuffer == 0 { + s.arrayBuffer = context.newArrayBuffer(graphics.IndicesCount * graphics.VertexFloatCount * floatSizeInBytes) + context.ctx.BindBuffer(gl.ARRAY_BUFFER, uint32(s.arrayBuffer)) + } + if s.elementArrayBuffer == 0 { + s.elementArrayBuffer = context.newElementArrayBuffer(graphics.IndicesCount * 2) + context.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(s.elementArrayBuffer)) } // Note that the vertices and the indices passed to BufferSubData is not under GC management in the gl package. @@ -212,6 +213,9 @@ func (g *Graphics) textureVariableName(idx int) string { func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures [graphics.ShaderImageCount]textureVariable) error { if g.state.lastProgram != program { g.context.ctx.UseProgram(uint32(program)) + if g.state.lastProgram == 0 { + theArrayBufferLayout.enable(&g.context) + } g.state.lastProgram = program for k := range g.state.lastUniforms {