Skip to content

Commit

Permalink
Remove 'default framebuffer' and add 'screen framebuffer' for iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
hajimehoshi committed Jun 17, 2016
1 parent 0b8fe25 commit 5eb77d2
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 59 deletions.
40 changes: 20 additions & 20 deletions graphicscontext.go
Expand Up @@ -27,42 +27,42 @@ func newGraphicsContext(f func(*Image) error) *graphicsContext {
}

type graphicsContext struct {
f func(*Image) error
screen *Image
defaultRenderTarget *Image
screenScale int
initialized bool
f func(*Image) error
offscreen *Image
screen *Image
screenScale int
initialized bool
}

func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) error {
if c.defaultRenderTarget != nil {
c.defaultRenderTarget.Dispose()
}
if c.screen != nil {
c.screen.Dispose()
}
screen, err := NewImage(screenWidth, screenHeight, FilterNearest)
if c.offscreen != nil {
c.offscreen.Dispose()
}
offscreen, err := NewImage(screenWidth, screenHeight, FilterNearest)
if err != nil {
return err
}
c.defaultRenderTarget, err = newImageWithZeroFramebuffer(screenWidth*screenScale, screenHeight*screenScale)
c.screen, err = newImageWithScreenFramebuffer(screenWidth*screenScale, screenHeight*screenScale)
if err != nil {
return err
}
c.defaultRenderTarget.Clear()
c.screen = screen
c.screen.Clear()
c.offscreen = offscreen
c.screenScale = screenScale
return nil
}

func (c *graphicsContext) needsRestoring(context *opengl.Context) (bool, error) {
imageM.Lock()
defer imageM.Unlock()
// FlushCommands is required because c.screen.impl might not have an actual texture.
// FlushCommands is required because c.offscreen.impl might not have an actual texture.
if err := graphics.FlushCommands(ui.GLContext()); err != nil {
return false, err
}
return c.screen.impl.isInvalidated(context), nil
return c.offscreen.impl.isInvalidated(context), nil
}

func (c *graphicsContext) initializeIfNeeded() error {
Expand All @@ -85,13 +85,13 @@ func (c *graphicsContext) initializeIfNeeded() error {
}

func (c *graphicsContext) drawToDefaultRenderTarget() error {
if err := c.defaultRenderTarget.Clear(); err != nil {
if err := c.screen.Clear(); err != nil {
return err
}
scale := float64(c.screenScale)
options := &DrawImageOptions{}
options.GeoM.Scale(scale, scale)
if err := c.defaultRenderTarget.DrawImage(c.screen, options); err != nil {
if err := c.screen.DrawImage(c.offscreen, options); err != nil {
return err
}
if err := c.flush(); err != nil {
Expand All @@ -104,10 +104,10 @@ func (c *graphicsContext) UpdateAndDraw() error {
if err := c.initializeIfNeeded(); err != nil {
return err
}
if err := c.screen.Clear(); err != nil {
if err := c.offscreen.Clear(); err != nil {
return err
}
if err := c.f(c.screen); err != nil {
if err := c.f(c.offscreen); err != nil {
return err
}
if IsRunningSlowly() {
Expand All @@ -117,8 +117,8 @@ func (c *graphicsContext) UpdateAndDraw() error {
return err
}
exceptions := map[*imageImpl]struct{}{
c.screen.impl: {},
c.defaultRenderTarget.impl: {},
c.offscreen.impl: {},
c.screen.impl: {},
}
if err := theImages.savePixels(ui.GLContext(), exceptions); err != nil {
return err
Expand Down
30 changes: 15 additions & 15 deletions image.go
Expand Up @@ -78,7 +78,7 @@ func (i *images) restorePixels(context *opengl.Context) error {
i.m.Lock()
defer i.m.Unlock()
for img := range i.images {
if img.defaultFramebuffer {
if img.screen {
continue
}
if img.isDisposed() {
Expand Down Expand Up @@ -191,13 +191,13 @@ func (i *Image) ReplacePixels(p []uint8) error {
}

type imageImpl struct {
image *graphics.Image
defaultFramebuffer bool
disposed bool
width int
height int
filter Filter
pixels []uint8
image *graphics.Image
screen bool
disposed bool
width int
height int
filter Filter
pixels []uint8
}

func (i *imageImpl) Fill(clr color.Color) error {
Expand Down Expand Up @@ -285,7 +285,7 @@ func (i *imageImpl) savePixels(context *opengl.Context) error {
}

func (i *imageImpl) restorePixels(context *opengl.Context) error {
if i.defaultFramebuffer {
if i.screen {
return nil
}
if i.disposed {
Expand Down Expand Up @@ -433,18 +433,18 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
return eimg, nil
}

func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
func newImageWithScreenFramebuffer(width, height int) (*Image, error) {
imageM.Lock()
defer imageM.Unlock()
i, err := graphics.NewZeroFramebufferImage(width, height)
i, err := graphics.NewScreenFramebufferImage(width, height)
if err != nil {
return nil, err
}
img := &imageImpl{
image: i,
width: width,
height: height,
defaultFramebuffer: true,
image: i,
width: width,
height: height,
screen: true,
}
eimg, err := theImages.add(img)
if err != nil {
Expand Down
25 changes: 24 additions & 1 deletion internal/graphics/command.go
Expand Up @@ -151,7 +151,7 @@ type disposeCommand struct {
}

func (c *disposeCommand) Exec(context *opengl.Context) error {
if c.target.framebuffer != nil && c.target.framebuffer.native != opengl.ZeroFramebuffer {
if c.target.framebuffer != nil && c.target.framebuffer.native != context.ScreenFramebuffer() {
context.DeleteFramebuffer(c.target.framebuffer.native)
}
if c.target.texture != nil {
Expand Down Expand Up @@ -245,3 +245,26 @@ func (c *newImageCommand) Exec(context *opengl.Context) error {
}
return nil
}

type newScreenFramebufferImageCommand struct {
result *Image
width int
height int
}

func (c *newScreenFramebufferImageCommand) Exec(context *opengl.Context) error {
if c.width < 4 {
return errors.New("graphics: width must be equal or more than 4.")
}
if c.height < 4 {
return errors.New("graphics: height must be equal or more than 4.")
}
f := &framebuffer{
native: context.ScreenFramebuffer(),
width: c.width,
height: c.height,
flipY: true,
}
c.result.framebuffer = f
return nil
}
12 changes: 6 additions & 6 deletions internal/graphics/image.go
Expand Up @@ -49,15 +49,15 @@ func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Image, error) {
return i, nil
}

func NewZeroFramebufferImage(width, height int) (*Image, error) {
f := &framebuffer{
func NewScreenFramebufferImage(width, height int) (*Image, error) {
i := &Image{}
c := &newScreenFramebufferImageCommand{
result: i,
width: width,
height: height,
flipY: true,
}
return &Image{
framebuffer: f,
}, nil
theCommandQueue.Enqueue(c)
return i, nil
}

func (i *Image) Dispose() error {
Expand Down
7 changes: 5 additions & 2 deletions internal/graphics/opengl/context.go
Expand Up @@ -14,8 +14,6 @@

package opengl

var ZeroFramebuffer Framebuffer

type Context struct {
Nearest Filter
Linear Filter
Expand All @@ -34,6 +32,7 @@ type Context struct {
oneMinusSrcAlpha operation
oneMinusDstAlpha operation
locationCache *locationCache
screenFramebuffer Framebuffer // This might not be the default frame buffer '0' (e.g. iOS).
lastFramebuffer Framebuffer
lastViewportWidth int
lastViewportHeight int
Expand All @@ -48,3 +47,7 @@ func (c *Context) bindFramebuffer(f Framebuffer) {
c.bindFramebufferImpl(f)
c.lastFramebuffer = f
}

func (c *Context) ScreenFramebuffer() Framebuffer {
return c.screenFramebuffer
}
19 changes: 12 additions & 7 deletions internal/graphics/opengl/context_desktop.go
Expand Up @@ -37,6 +37,8 @@ type attribLocation int32

type programID uint32

const invalidFramebuffer = (1 << 32) - 1

func (p Program) id() programID {
return programID(p)
}
Expand Down Expand Up @@ -102,17 +104,23 @@ func (c *Context) Init() error {
return err
}
c.BlendFunc(CompositeModeSourceOver)
f := int32(0)
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
c.screenFramebuffer = Framebuffer(f)
return nil
}

func (c *Context) Resume() {
c.locationCache = newLocationCache()
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
c.lastCompositeMode = CompositeModeUnknown
gl.Enable(gl.BLEND)
c.BlendFunc(CompositeModeSourceOver)
f := int32(0)
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
c.screenFramebuffer = Framebuffer(f)
}

func (c *Context) BlendFunc(mode CompositeMode) {
Expand Down Expand Up @@ -212,9 +220,9 @@ func (c *Context) TexSubImage2D(p []uint8, width, height int) {
})
}

func (c *Context) BindZeroFramebuffer() {
func (c *Context) BindScreenFramebuffer() {
c.RunOnContextThread(func() error {
c.bindFramebuffer(ZeroFramebuffer)
c.bindFramebuffer(c.screenFramebuffer)
return nil
})
}
Expand Down Expand Up @@ -275,11 +283,8 @@ func (c *Context) DeleteFramebuffer(f Framebuffer) {
if !gl.IsFramebuffer(ff) {
return nil
}
// If a framebuffer to be delted is bound, a newly bound framebuffer
// will be a default framebuffer.
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
if c.lastFramebuffer == f {
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
}
Expand Down
11 changes: 8 additions & 3 deletions internal/graphics/opengl/context_js.go
Expand Up @@ -52,6 +52,8 @@ type attribLocation int

type programID int

var invalidFramebuffer = Framebuffer{nil}

func (p Program) id() programID {
return programID(p.Get("__ebiten_programId").Int())
}
Expand Down Expand Up @@ -115,19 +117,22 @@ func (c *Context) init() {
gl := c.gl
// Textures' pixel formats are alpha premultiplied.
gl.Enable(gl.BLEND)
//gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
c.BlendFunc(CompositeModeSourceOver)
f := gl.GetParameter(gl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = Framebuffer{f}
}

func (c *Context) Resume() {
c.locationCache = newLocationCache()
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
c.lastCompositeMode = CompositeModeUnknown
gl := c.gl
gl.Enable(gl.BLEND)
c.BlendFunc(CompositeModeSourceOver)
f := gl.GetParameter(gl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = Framebuffer{f}
}

func (c *Context) BlendFunc(mode CompositeMode) {
Expand Down Expand Up @@ -252,7 +257,7 @@ func (c *Context) DeleteFramebuffer(f Framebuffer) {
// will be a default framebuffer.
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
if c.lastFramebuffer == f {
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
}
Expand Down
14 changes: 10 additions & 4 deletions internal/graphics/opengl/context_mobile.go
Expand Up @@ -34,6 +34,8 @@ type attribLocation mgl.Attrib

type programID uint32

var invalidFramebuffer = Framebuffer(mgl.Framebuffer{(1 << 32) - 1})

func (p Program) id() programID {
return programID(p.Value)
}
Expand Down Expand Up @@ -75,19 +77,23 @@ func NewContext() (*Context, error) {
// Textures' pixel formats are alpha premultiplied.
c.gl.Enable(mgl.BLEND)
c.BlendFunc(CompositeModeSourceOver)
f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
close(c.initialized)
}()
return c, nil
}

func (c *Context) Resume() {
c.locationCache = newLocationCache()
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
c.lastCompositeMode = CompositeModeUnknown
c.gl.Enable(mgl.BLEND)
c.BlendFunc(CompositeModeSourceOver)
f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
}

func (c *Context) WaitUntilInitializingDone() {
Expand Down Expand Up @@ -172,8 +178,8 @@ func (c *Context) TexSubImage2D(p []uint8, width, height int) {
gl.TexSubImage2D(mgl.TEXTURE_2D, 0, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p)
}

func (c *Context) BindZeroFramebuffer() {
c.bindFramebuffer(ZeroFramebuffer)
func (c *Context) BindScreenFramebuffer() {
c.bindFramebuffer(c.screenFramebuffer)
}

func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) {
Expand Down Expand Up @@ -226,7 +232,7 @@ func (c *Context) DeleteFramebuffer(f Framebuffer) {
// will be a default framebuffer.
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
if c.lastFramebuffer == f {
c.lastFramebuffer = ZeroFramebuffer
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
}
Expand Down

0 comments on commit 5eb77d2

Please sign in to comment.