internal/graphicsdriver/opengl: refactoring

This commit is contained in:
Hajime Hoshi 2022-11-18 13:15:04 +09:00
parent b2b152e60f
commit 90213d5d80
8 changed files with 70 additions and 134 deletions

View File

@ -127,7 +127,7 @@ type context struct {
highpOnce sync.Once highpOnce sync.Once
initOnce sync.Once initOnce sync.Once
contextImpl contextPlatform
} }
func (c *context) bindTexture(t textureNative) { func (c *context) bindTexture(t textureNative) {
@ -156,27 +156,33 @@ func (c *context) bindFramebuffer(f framebufferNative) {
func (c *context) setViewport(f *framebuffer) { func (c *context) setViewport(f *framebuffer) {
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
if c.lastViewportWidth != f.width || c.lastViewportHeight != f.height { if c.lastViewportWidth == f.width && c.lastViewportHeight == f.height {
// On some environments, viewport size must be within the framebuffer size. return
// e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). }
// Use the same size of the framebuffer here.
c.ctx.Viewport(0, 0, int32(f.width), int32(f.height))
// glViewport must be called at least at every frame on iOS. // On some environments, viewport size must be within the framebuffer size.
// As the screen framebuffer is the last render target, next SetViewport should be // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691).
// the first call at a frame. // Use the same size of the framebuffer here.
if f.native == c.screenFramebuffer { c.ctx.Viewport(0, 0, int32(f.width), int32(f.height))
c.lastViewportWidth = 0
c.lastViewportHeight = 0 // glViewport must be called at least at every frame on iOS.
} else { // As the screen framebuffer is the last render target, next SetViewport should be
c.lastViewportWidth = f.width // the first call at a frame.
c.lastViewportHeight = f.height if f.native == c.screenFramebuffer {
} c.lastViewportWidth = 0
c.lastViewportHeight = 0
} else {
c.lastViewportWidth = f.width
c.lastViewportHeight = f.height
} }
} }
func (c *context) getScreenFramebuffer() framebufferNative { func (c *context) newScreenFramebuffer(width, height int) *framebuffer {
return c.screenFramebuffer return &framebuffer{
native: c.screenFramebuffer,
width: width,
height: height,
}
} }
func (c *context) getMaxTextureSize() int { func (c *context) getMaxTextureSize() int {
@ -334,24 +340,28 @@ func (c *context) deleteRenderbuffer(r renderbufferNative) {
c.ctx.DeleteRenderbuffer(uint32(r)) c.ctx.DeleteRenderbuffer(uint32(r))
} }
func (c *context) newFramebuffer(texture textureNative) (framebufferNative, error) { func (c *context) newFramebuffer(texture textureNative, width, height int) (*framebuffer, error) {
f := c.ctx.CreateFramebuffer() f := c.ctx.CreateFramebuffer()
if f <= 0 { if f <= 0 {
return 0, fmt.Errorf("opengl: creating framebuffer failed: the returned value is not positive but %d", f) return nil, fmt.Errorf("opengl: creating framebuffer failed: the returned value is not positive but %d", f)
} }
c.bindFramebuffer(framebufferNative(f)) c.bindFramebuffer(framebufferNative(f))
c.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0) c.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE { if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
if s != 0 { if s != 0 {
return 0, fmt.Errorf("opengl: creating framebuffer failed: %v", s) return nil, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
} }
if e := c.ctx.GetError(); e != gl.NO_ERROR { if e := c.ctx.GetError(); e != gl.NO_ERROR {
return 0, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e) return nil, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
} }
return 0, fmt.Errorf("opengl: creating framebuffer failed: unknown error") return nil, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
} }
return framebufferNative(f), nil return &framebuffer{
native: framebufferNative(f),
width: width,
height: height,
}, nil
} }
func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error { func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error {
@ -365,6 +375,9 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e
} }
func (c *context) deleteFramebuffer(f framebufferNative) { func (c *context) deleteFramebuffer(f framebufferNative) {
if f == c.screenFramebuffer {
return
}
if !c.ctx.IsFramebuffer(uint32(f)) { if !c.ctx.IsFramebuffer(uint32(f)) {
return return
} }

View File

@ -16,9 +16,18 @@ package opengl
import ( import (
"syscall/js" "syscall/js"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
) )
type contextImpl struct { type contextPlatform struct {
canvas js.Value canvas js.Value
webGL2 bool webGL2 bool
} }
func (c *context) glslVersion() glsl.GLSLVersion {
if c.webGL2 {
return glsl.GLSLVersionES300
}
return glsl.GLSLVersionES100
}

View File

@ -16,5 +16,16 @@
package opengl package opengl
type contextImpl struct { import (
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
)
type contextPlatform struct {
}
func (c *context) glslVersion() glsl.GLSLVersion {
if c.ctx.IsES() {
return glsl.GLSLVersionES100
}
return glsl.GLSLVersionDefault
} }

View File

@ -1,51 +0,0 @@
// Copyright 2014 Hajime Hoshi
//
// 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
// framebuffer is a wrapper of OpenGL's framebuffer.
type framebuffer struct {
graphics *Graphics
native framebufferNative
width int
height int
}
// newFramebufferFromTexture creates a framebuffer from the given texture.
func newFramebufferFromTexture(context *context, texture textureNative, width, height int) (*framebuffer, error) {
native, err := context.newFramebuffer(texture)
if err != nil {
return nil, err
}
return &framebuffer{
native: native,
width: width,
height: height,
}, nil
}
// newScreenFramebuffer creates a framebuffer for the screen.
func newScreenFramebuffer(context *context, width, height int) *framebuffer {
return &framebuffer{
native: context.getScreenFramebuffer(),
width: width,
height: height,
}
}
func (f *framebuffer) delete(context *context) {
if f.native != context.getScreenFramebuffer() {
context.deleteFramebuffer(f.native)
}
}

View File

@ -33,6 +33,14 @@ type Image struct {
screen bool screen bool
} }
// framebuffer is a wrapper of OpenGL's framebuffer.
type framebuffer struct {
graphics *Graphics
native framebufferNative
width int
height int
}
func (i *Image) ID() graphicsdriver.ImageID { func (i *Image) ID() graphicsdriver.ImageID {
return i.id return i.id
} }
@ -43,7 +51,7 @@ func (i *Image) IsInvalidated() bool {
func (i *Image) Dispose() { func (i *Image) Dispose() {
if i.framebuffer != nil { if i.framebuffer != nil {
i.framebuffer.delete(&i.graphics.context) i.graphics.context.deleteFramebuffer(i.framebuffer.native)
} }
if i.texture != 0 { if i.texture != 0 {
i.graphics.context.deleteTexture(i.texture) i.graphics.context.deleteTexture(i.texture)
@ -90,10 +98,10 @@ func (i *Image) ensureFramebuffer() error {
w, h := i.framebufferSize() w, h := i.framebufferSize()
if i.screen { if i.screen {
i.framebuffer = newScreenFramebuffer(&i.graphics.context, w, h) i.framebuffer = i.graphics.context.newScreenFramebuffer(w, h)
return nil return nil
} }
f, err := newFramebufferFromTexture(&i.graphics.context, i.texture, w, h) f, err := i.graphics.context.newFramebuffer(i.texture, w, h)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,26 +0,0 @@
// Copyright 2020 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 (
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
)
func (c *context) glslVersion() glsl.GLSLVersion {
if c.webGL2 {
return glsl.GLSLVersionES300
}
return glsl.GLSLVersionES100
}

View File

@ -1,28 +0,0 @@
// Copyright 2020 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.
//go:build !js
package opengl
import (
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
)
func (c *context) glslVersion() glsl.GLSLVersion {
if c.ctx.IsES() {
return glsl.GLSLVersionES100
}
return glsl.GLSLVersionDefault
}