opengl: Move Framebuffer from graphicscommand to opengl and rename it to FramebufferStruct

This commit is contained in:
Hajime Hoshi 2018-11-04 17:28:33 +09:00
parent 97a9e99112
commit c935c28498
8 changed files with 54 additions and 51 deletions

View File

@ -236,13 +236,13 @@ func (c *drawImageCommand) Exec(indexOffsetInBytes int) error {
// On some environments, viewport size must be within the framebuffer size. // On some environments, viewport size must be within the framebuffer size.
// e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691).
// Use the same size of the framebuffer here. // 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) opengl.GetContext().BlendFunc(c.mode)
if c.nindices == 0 { if c.nindices == 0 {
return nil return nil
} }
proj := f.projectionMatrix() proj := f.ProjectionMatrix()
dw, dh := c.dst.Size() dw, dh := c.dst.Size()
sw, sh := c.src.Size() sw, sh := c.src.Size()
opengl.UseProgram(proj, c.src.texture, dw, dh, sw, sh, c.color, c.filter) 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 { if err != nil {
return err 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 { if err != nil {
return err return err
} }
@ -385,9 +385,8 @@ func (c *disposeCommand) String() string {
// Exec executes the disposeCommand. // Exec executes the disposeCommand.
func (c *disposeCommand) Exec(indexOffsetInBytes int) error { func (c *disposeCommand) Exec(indexOffsetInBytes int) error {
if c.target.framebuffer != nil && if c.target.framebuffer != nil {
c.target.framebuffer.native != opengl.GetContext().ScreenFramebuffer() { c.target.framebuffer.Delete()
opengl.GetContext().DeleteFramebuffer(c.target.framebuffer.native)
} }
if c.target.texture != *new(opengl.Texture) { if c.target.texture != *new(opengl.Texture) {
opengl.GetContext().DeleteTexture(c.target.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. // 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 // 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). // 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 return nil
} }

View File

@ -43,7 +43,7 @@ func MaxImageSize() int {
// Image represents an image that is implemented with OpenGL. // Image represents an image that is implemented with OpenGL.
type Image struct { type Image struct {
texture opengl.Texture texture opengl.Texture
framebuffer *framebuffer framebuffer *opengl.FramebufferStruct
width int width int
height int height int
} }
@ -121,11 +121,11 @@ func (i *Image) IsInvalidated() bool {
return !opengl.GetContext().IsTexture(i.texture) return !opengl.GetContext().IsTexture(i.texture)
} }
func (i *Image) ensureFramebuffer() (*framebuffer, error) { func (i *Image) ensureFramebuffer() (*opengl.FramebufferStruct, error) {
if i.framebuffer != nil { if i.framebuffer != nil {
return 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -96,24 +96,24 @@ func (c *Context) bindFramebuffer(f Framebuffer) {
c.lastFramebuffer = f c.lastFramebuffer = f
} }
func (c *Context) SetViewport(f Framebuffer, width, height int) { func (c *Context) SetViewport(f *FramebufferStruct) {
c.bindFramebuffer(f) c.bindFramebuffer(f.native)
if c.lastViewportWidth != width || c.lastViewportHeight != height { if c.lastViewportWidth != f.width || c.lastViewportHeight != f.height {
c.setViewportImpl(width, height) c.setViewportImpl(f.width, f.height)
// glViewport must be called at least at every frame on iOS. // glViewport must be called at least at every frame on iOS.
// As the screen framebuffer is the last render target, next SetViewport should be // As the screen framebuffer is the last render target, next SetViewport should be
// the first call at a frame. // the first call at a frame.
if f == c.screenFramebuffer { if f.native == c.screenFramebuffer {
c.lastViewportWidth = 0 c.lastViewportWidth = 0
c.lastViewportHeight = 0 c.lastViewportHeight = 0
} else { } else {
c.lastViewportWidth = width c.lastViewportWidth = f.width
c.lastViewportHeight = height c.lastViewportHeight = f.height
} }
} }
} }
func (c *Context) ScreenFramebuffer() Framebuffer { func (c *Context) getScreenFramebuffer() Framebuffer {
return c.screenFramebuffer return c.screenFramebuffer
} }

View File

@ -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 var pixels []byte
_ = c.runOnContextThread(func() error { _ = c.runOnContextThread(func() error {
gl.Flush() gl.Flush()
return nil return nil
}) })
c.bindFramebuffer(f) c.bindFramebuffer(f.native)
if err := c.runOnContextThread(func() error { if err := c.runOnContextThread(func() error {
pixels = make([]byte, 4*width*height) pixels = make([]byte, 4*width*height)
gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels)) 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) c.bindFramebuffer(c.screenFramebuffer)
} }
func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) { func (c *Context) newFramebuffer(texture Texture) (Framebuffer, error) {
var framebuffer Framebuffer var framebuffer Framebuffer
var f uint32 var f uint32
if err := c.runOnContextThread(func() error { 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 { _ = c.runOnContextThread(func() error {
ff := uint32(f) ff := uint32(f)
if !gl.IsFramebufferEXT(ff) { if !gl.IsFramebufferEXT(ff) {

View File

@ -204,10 +204,10 @@ func (c *Context) bindFramebufferImpl(f Framebuffer) {
gl.Call("bindFramebuffer", framebuffer, js.Value(f)) 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 gl := c.gl
c.bindFramebuffer(f) c.bindFramebuffer(f.native)
pixels := make([]byte, 4*width*height) pixels := make([]byte, 4*width*height)
p := js.TypedArrayOf(pixels) p := js.TypedArrayOf(pixels)
@ -252,7 +252,7 @@ func (c *Context) TexSubImage2D(t Texture, pixels []byte, x, y, width, height in
p.Release() p.Release()
} }
func (c *Context) NewFramebuffer(t Texture) (Framebuffer, error) { func (c *Context) newFramebuffer(t Texture) (Framebuffer, error) {
gl := c.gl gl := c.gl
f := gl.Call("createFramebuffer") f := gl.Call("createFramebuffer")
c.bindFramebuffer(Framebuffer(f)) c.bindFramebuffer(Framebuffer(f))
@ -270,7 +270,7 @@ func (c *Context) setViewportImpl(width, height int) {
gl.Call("viewport", 0, 0, width, height) gl.Call("viewport", 0, 0, width, height)
} }
func (c *Context) DeleteFramebuffer(f Framebuffer) { func (c *Context) deleteFramebuffer(f Framebuffer) {
gl := c.gl gl := c.gl
if !gl.Call("isFramebuffer", js.Value(f)).Bool() { if !gl.Call("isFramebuffer", js.Value(f)).Bool() {
return return

View File

@ -156,11 +156,11 @@ func (c *Context) bindFramebufferImpl(f Framebuffer) {
gl.BindFramebuffer(mgl.FRAMEBUFFER, mgl.Framebuffer(f)) 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 := c.gl
gl.Flush() gl.Flush()
c.bindFramebuffer(f) c.bindFramebuffer(f.native)
pixels := make([]byte, 4*width*height) pixels := make([]byte, 4*width*height)
gl.ReadPixels(pixels, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE) 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) 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 gl := c.gl
f := gl.CreateFramebuffer() f := gl.CreateFramebuffer()
if f.Value <= 0 { if f.Value <= 0 {
@ -224,7 +224,7 @@ func (c *Context) setViewportImpl(width, height int) {
gl.Viewport(0, 0, width, height) gl.Viewport(0, 0, width, height)
} }
func (c *Context) DeleteFramebuffer(f Framebuffer) { func (c *Context) deleteFramebuffer(f Framebuffer) {
gl := c.gl gl := c.gl
if !gl.IsFramebuffer(mgl.Framebuffer(f)) { if !gl.IsFramebuffer(mgl.Framebuffer(f)) {
return return

View File

@ -12,51 +12,55 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package graphicscommand package opengl
import ( // FramebufferStruct is a wrapper of OpenGL's framebuffer.
"github.com/hajimehoshi/ebiten/internal/opengl" //
) // TODO: Create a new struct Image and embed this struct.
type FramebufferStruct struct {
// framebuffer is a wrapper of OpenGL's framebuffer. native Framebuffer
type framebuffer struct {
native opengl.Framebuffer
proMatrix []float32 proMatrix []float32
width int width int
height int height int
} }
// newFramebufferFromTexture creates a framebuffer from the given texture. // NewFramebufferFromTexture creates a framebuffer from the given texture.
func newFramebufferFromTexture(texture opengl.Texture, width, height int) (*framebuffer, error) { func NewFramebufferFromTexture(texture Texture, width, height int) (*FramebufferStruct, error) {
native, err := opengl.GetContext().NewFramebuffer(texture) native, err := theContext.newFramebuffer(texture)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &framebuffer{ return &FramebufferStruct{
native: native, native: native,
width: width, width: width,
height: height, height: height,
}, nil }, nil
} }
// newScreenFramebuffer creates a framebuffer for the screen. // NewScreenFramebuffer creates a framebuffer for the screen.
func newScreenFramebuffer(width, height int) *framebuffer { func NewScreenFramebuffer(width, height int) *FramebufferStruct {
return &framebuffer{ return &FramebufferStruct{
native: opengl.GetContext().ScreenFramebuffer(), native: theContext.getScreenFramebuffer(),
width: width, width: width,
height: height, 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 // A projection matrix converts the coodinates on the framebuffer
// (0, 0) - (viewport width, viewport height) // (0, 0) - (viewport width, viewport height)
// to the normalized device coodinates (-1, -1) - (1, 1) with adjustment. // 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 { if f.proMatrix != nil {
return f.proMatrix 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 return f.proMatrix
} }
func (f *FramebufferStruct) Delete() {
if f.native != theContext.getScreenFramebuffer() {
theContext.deleteFramebuffer(f.native)
}
}

View File

@ -14,10 +14,10 @@
package opengl 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). // 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) e11 := 2 / float32(right-left)
e22 := 2 / float32(top-bottom) e22 := 2 / float32(top-bottom)
e14 := -1 * float32(right+left) / float32(right-left) e14 := -1 * float32(right+left) / float32(right-left)