From c935c284988b99e13f1bbbfb129262f7ea01d4fb Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 4 Nov 2018 17:28:33 +0900 Subject: [PATCH] opengl: Move Framebuffer from graphicscommand to opengl and rename it to FramebufferStruct --- internal/graphicscommand/command.go | 13 +++--- internal/graphicscommand/image.go | 6 +-- internal/opengl/context.go | 16 +++---- internal/opengl/context_desktop.go | 8 ++-- internal/opengl/context_js.go | 8 ++-- internal/opengl/context_mobile.go | 8 ++-- .../framebuffer.go | 42 ++++++++++--------- internal/opengl/matrix.go | 4 +- 8 files changed, 54 insertions(+), 51 deletions(-) rename internal/{graphicscommand => opengl}/framebuffer.go (52%) diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index d9adba4d9..0a29b0466 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -236,13 +236,13 @@ func (c *drawImageCommand) Exec(indexOffsetInBytes int) error { // 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. - opengl.GetContext().SetViewport(f.native, f.width, f.height) + opengl.GetContext().SetViewport(f) opengl.GetContext().BlendFunc(c.mode) if c.nindices == 0 { return nil } - proj := f.projectionMatrix() + proj := f.ProjectionMatrix() dw, dh := c.dst.Size() sw, sh := c.src.Size() opengl.UseProgram(proj, c.src.texture, dw, dh, sw, sh, c.color, c.filter) @@ -344,7 +344,7 @@ func (c *pixelsCommand) Exec(indexOffsetInBytes int) error { if err != nil { return err } - p, err := opengl.GetContext().FramebufferPixels(f.native, c.img.width, c.img.height) + p, err := opengl.GetContext().FramebufferPixels(f, c.img.width, c.img.height) if err != nil { return err } @@ -385,9 +385,8 @@ func (c *disposeCommand) String() string { // Exec executes the disposeCommand. func (c *disposeCommand) Exec(indexOffsetInBytes int) error { - if c.target.framebuffer != nil && - c.target.framebuffer.native != opengl.GetContext().ScreenFramebuffer() { - opengl.GetContext().DeleteFramebuffer(c.target.framebuffer.native) + if c.target.framebuffer != nil { + c.target.framebuffer.Delete() } if c.target.texture != *new(opengl.Texture) { opengl.GetContext().DeleteTexture(c.target.texture) @@ -488,7 +487,7 @@ func (c *newScreenFramebufferImageCommand) Exec(indexOffsetInBytes int) error { // The (default) framebuffer size can't be converted to a power of 2. // On browsers, c.width and c.height are used as viewport size and // Edge can't treat a bigger viewport than the drawing area (#71). - c.result.framebuffer = newScreenFramebuffer(c.width, c.height) + c.result.framebuffer = opengl.NewScreenFramebuffer(c.width, c.height) return nil } diff --git a/internal/graphicscommand/image.go b/internal/graphicscommand/image.go index 5c9727529..fb5e29416 100644 --- a/internal/graphicscommand/image.go +++ b/internal/graphicscommand/image.go @@ -43,7 +43,7 @@ func MaxImageSize() int { // Image represents an image that is implemented with OpenGL. type Image struct { texture opengl.Texture - framebuffer *framebuffer + framebuffer *opengl.FramebufferStruct width int height int } @@ -121,11 +121,11 @@ func (i *Image) IsInvalidated() bool { return !opengl.GetContext().IsTexture(i.texture) } -func (i *Image) ensureFramebuffer() (*framebuffer, error) { +func (i *Image) ensureFramebuffer() (*opengl.FramebufferStruct, error) { if i.framebuffer != nil { return i.framebuffer, nil } - f, err := newFramebufferFromTexture(i.texture, math.NextPowerOf2Int(i.width), math.NextPowerOf2Int(i.height)) + f, err := opengl.NewFramebufferFromTexture(i.texture, math.NextPowerOf2Int(i.width), math.NextPowerOf2Int(i.height)) if err != nil { return nil, err } diff --git a/internal/opengl/context.go b/internal/opengl/context.go index 7de459750..99822fe6d 100644 --- a/internal/opengl/context.go +++ b/internal/opengl/context.go @@ -96,24 +96,24 @@ func (c *Context) bindFramebuffer(f Framebuffer) { c.lastFramebuffer = f } -func (c *Context) SetViewport(f Framebuffer, width, height int) { - c.bindFramebuffer(f) - if c.lastViewportWidth != width || c.lastViewportHeight != height { - c.setViewportImpl(width, height) +func (c *Context) SetViewport(f *FramebufferStruct) { + c.bindFramebuffer(f.native) + if c.lastViewportWidth != f.width || c.lastViewportHeight != f.height { + c.setViewportImpl(f.width, 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 // the first call at a frame. - if f == c.screenFramebuffer { + if f.native == c.screenFramebuffer { c.lastViewportWidth = 0 c.lastViewportHeight = 0 } else { - c.lastViewportWidth = width - c.lastViewportHeight = height + c.lastViewportWidth = f.width + c.lastViewportHeight = f.height } } } -func (c *Context) ScreenFramebuffer() Framebuffer { +func (c *Context) getScreenFramebuffer() Framebuffer { return c.screenFramebuffer } diff --git a/internal/opengl/context_desktop.go b/internal/opengl/context_desktop.go index a79ab68d7..2a6aff57a 100644 --- a/internal/opengl/context_desktop.go +++ b/internal/opengl/context_desktop.go @@ -169,13 +169,13 @@ func (c *Context) bindFramebufferImpl(f Framebuffer) { }) } -func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]byte, error) { +func (c *Context) FramebufferPixels(f *FramebufferStruct, width, height int) ([]byte, error) { var pixels []byte _ = c.runOnContextThread(func() error { gl.Flush() return nil }) - c.bindFramebuffer(f) + c.bindFramebuffer(f.native) if err := c.runOnContextThread(func() error { pixels = make([]byte, 4*width*height) gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels)) @@ -232,7 +232,7 @@ func (c *Context) BeforeSwapping() { c.bindFramebuffer(c.screenFramebuffer) } -func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) { +func (c *Context) newFramebuffer(texture Texture) (Framebuffer, error) { var framebuffer Framebuffer var f uint32 if err := c.runOnContextThread(func() error { @@ -273,7 +273,7 @@ func (c *Context) setViewportImpl(width, height int) { }) } -func (c *Context) DeleteFramebuffer(f Framebuffer) { +func (c *Context) deleteFramebuffer(f Framebuffer) { _ = c.runOnContextThread(func() error { ff := uint32(f) if !gl.IsFramebufferEXT(ff) { diff --git a/internal/opengl/context_js.go b/internal/opengl/context_js.go index 519d6e159..e81ec5096 100644 --- a/internal/opengl/context_js.go +++ b/internal/opengl/context_js.go @@ -204,10 +204,10 @@ func (c *Context) bindFramebufferImpl(f Framebuffer) { gl.Call("bindFramebuffer", framebuffer, js.Value(f)) } -func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]byte, error) { +func (c *Context) FramebufferPixels(f *FramebufferStruct, width, height int) ([]byte, error) { gl := c.gl - c.bindFramebuffer(f) + c.bindFramebuffer(f.native) pixels := make([]byte, 4*width*height) p := js.TypedArrayOf(pixels) @@ -252,7 +252,7 @@ func (c *Context) TexSubImage2D(t Texture, pixels []byte, x, y, width, height in p.Release() } -func (c *Context) NewFramebuffer(t Texture) (Framebuffer, error) { +func (c *Context) newFramebuffer(t Texture) (Framebuffer, error) { gl := c.gl f := gl.Call("createFramebuffer") c.bindFramebuffer(Framebuffer(f)) @@ -270,7 +270,7 @@ func (c *Context) setViewportImpl(width, height int) { gl.Call("viewport", 0, 0, width, height) } -func (c *Context) DeleteFramebuffer(f Framebuffer) { +func (c *Context) deleteFramebuffer(f Framebuffer) { gl := c.gl if !gl.Call("isFramebuffer", js.Value(f)).Bool() { return diff --git a/internal/opengl/context_mobile.go b/internal/opengl/context_mobile.go index f7d5026d4..b69ebe934 100644 --- a/internal/opengl/context_mobile.go +++ b/internal/opengl/context_mobile.go @@ -156,11 +156,11 @@ func (c *Context) bindFramebufferImpl(f Framebuffer) { gl.BindFramebuffer(mgl.FRAMEBUFFER, mgl.Framebuffer(f)) } -func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]byte, error) { +func (c *Context) FramebufferPixels(f *FramebufferStruct, width, height int) ([]byte, error) { gl := c.gl gl.Flush() - c.bindFramebuffer(f) + c.bindFramebuffer(f.native) pixels := make([]byte, 4*width*height) gl.ReadPixels(pixels, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE) @@ -197,7 +197,7 @@ func (c *Context) TexSubImage2D(t Texture, p []byte, x, y, width, height int) { gl.TexSubImage2D(mgl.TEXTURE_2D, 0, x, y, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p) } -func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) { +func (c *Context) newFramebuffer(texture Texture) (Framebuffer, error) { gl := c.gl f := gl.CreateFramebuffer() if f.Value <= 0 { @@ -224,7 +224,7 @@ func (c *Context) setViewportImpl(width, height int) { gl.Viewport(0, 0, width, height) } -func (c *Context) DeleteFramebuffer(f Framebuffer) { +func (c *Context) deleteFramebuffer(f Framebuffer) { gl := c.gl if !gl.IsFramebuffer(mgl.Framebuffer(f)) { return diff --git a/internal/graphicscommand/framebuffer.go b/internal/opengl/framebuffer.go similarity index 52% rename from internal/graphicscommand/framebuffer.go rename to internal/opengl/framebuffer.go index 05e047fd2..06041f3da 100644 --- a/internal/graphicscommand/framebuffer.go +++ b/internal/opengl/framebuffer.go @@ -12,51 +12,55 @@ // See the License for the specific language governing permissions and // limitations under the License. -package graphicscommand +package opengl -import ( - "github.com/hajimehoshi/ebiten/internal/opengl" -) - -// framebuffer is a wrapper of OpenGL's framebuffer. -type framebuffer struct { - native opengl.Framebuffer +// FramebufferStruct is a wrapper of OpenGL's framebuffer. +// +// TODO: Create a new struct Image and embed this struct. +type FramebufferStruct struct { + native Framebuffer proMatrix []float32 width int height int } -// newFramebufferFromTexture creates a framebuffer from the given texture. -func newFramebufferFromTexture(texture opengl.Texture, width, height int) (*framebuffer, error) { - native, err := opengl.GetContext().NewFramebuffer(texture) +// NewFramebufferFromTexture creates a framebuffer from the given texture. +func NewFramebufferFromTexture(texture Texture, width, height int) (*FramebufferStruct, error) { + native, err := theContext.newFramebuffer(texture) if err != nil { return nil, err } - return &framebuffer{ + return &FramebufferStruct{ native: native, width: width, height: height, }, nil } -// newScreenFramebuffer creates a framebuffer for the screen. -func newScreenFramebuffer(width, height int) *framebuffer { - return &framebuffer{ - native: opengl.GetContext().ScreenFramebuffer(), +// NewScreenFramebuffer creates a framebuffer for the screen. +func NewScreenFramebuffer(width, height int) *FramebufferStruct { + return &FramebufferStruct{ + native: theContext.getScreenFramebuffer(), width: width, height: height, } } -// projectionMatrix returns a projection matrix of the framebuffer. +// ProjectionMatrix returns a projection matrix of the framebuffer. // // A projection matrix converts the coodinates on the framebuffer // (0, 0) - (viewport width, viewport height) // to the normalized device coodinates (-1, -1) - (1, 1) with adjustment. -func (f *framebuffer) projectionMatrix() []float32 { +func (f *FramebufferStruct) ProjectionMatrix() []float32 { if f.proMatrix != nil { return f.proMatrix } - f.proMatrix = opengl.OrthoProjectionMatrix(0, f.width, 0, f.height) + f.proMatrix = orthoProjectionMatrix(0, f.width, 0, f.height) return f.proMatrix } + +func (f *FramebufferStruct) Delete() { + if f.native != theContext.getScreenFramebuffer() { + theContext.deleteFramebuffer(f.native) + } +} diff --git a/internal/opengl/matrix.go b/internal/opengl/matrix.go index b3dc73853..162808cb5 100644 --- a/internal/opengl/matrix.go +++ b/internal/opengl/matrix.go @@ -14,10 +14,10 @@ package opengl -// OrthoProjectionMatrix returns an orthogonal projection matrix for OpenGL. +// orthoProjectionMatrix returns an orthogonal projection matrix for OpenGL. // // The matrix converts the coodinates (left, bottom) - (right, top) to the normalized device coodinates (-1, -1) - (1, 1). -func OrthoProjectionMatrix(left, right, bottom, top int) []float32 { +func orthoProjectionMatrix(left, right, bottom, top int) []float32 { e11 := 2 / float32(right-left) e22 := 2 / float32(top-bottom) e14 := -1 * float32(right+left) / float32(right-left)