mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
Remove 'default framebuffer' and add 'screen framebuffer' for iOS
This commit is contained in:
parent
0b8fe25350
commit
5eb77d2fb5
@ -28,29 +28,29 @@ func newGraphicsContext(f func(*Image) error) *graphicsContext {
|
||||
|
||||
type graphicsContext struct {
|
||||
f func(*Image) error
|
||||
offscreen *Image
|
||||
screen *Image
|
||||
defaultRenderTarget *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
|
||||
}
|
||||
@ -58,11 +58,11 @@ func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) er
|
||||
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 {
|
||||
@ -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 {
|
||||
@ -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() {
|
||||
@ -117,8 +117,8 @@ func (c *graphicsContext) UpdateAndDraw() error {
|
||||
return err
|
||||
}
|
||||
exceptions := map[*imageImpl]struct{}{
|
||||
c.offscreen.impl: {},
|
||||
c.screen.impl: {},
|
||||
c.defaultRenderTarget.impl: {},
|
||||
}
|
||||
if err := theImages.savePixels(ui.GLContext(), exceptions); err != nil {
|
||||
return err
|
||||
|
12
image.go
12
image.go
@ -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() {
|
||||
@ -192,7 +192,7 @@ func (i *Image) ReplacePixels(p []uint8) error {
|
||||
|
||||
type imageImpl struct {
|
||||
image *graphics.Image
|
||||
defaultFramebuffer bool
|
||||
screen bool
|
||||
disposed bool
|
||||
width int
|
||||
height int
|
||||
@ -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 {
|
||||
@ -433,10 +433,10 @@ 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
|
||||
}
|
||||
@ -444,7 +444,7 @@ func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
|
||||
image: i,
|
||||
width: width,
|
||||
height: height,
|
||||
defaultFramebuffer: true,
|
||||
screen: true,
|
||||
}
|
||||
eimg, err := theImages.add(img)
|
||||
if err != nil {
|
||||
|
@ -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 {
|
||||
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
package opengl
|
||||
|
||||
var ZeroFramebuffer Framebuffer
|
||||
|
||||
type Context struct {
|
||||
Nearest Filter
|
||||
Linear Filter
|
||||
@ -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
|
||||
@ -48,3 +47,7 @@ func (c *Context) bindFramebuffer(f Framebuffer) {
|
||||
c.bindFramebufferImpl(f)
|
||||
c.lastFramebuffer = f
|
||||
}
|
||||
|
||||
func (c *Context) ScreenFramebuffer() Framebuffer {
|
||||
return c.screenFramebuffer
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ type attribLocation int32
|
||||
|
||||
type programID uint32
|
||||
|
||||
const invalidFramebuffer = (1 << 32) - 1
|
||||
|
||||
func (p Program) id() programID {
|
||||
return programID(p)
|
||||
}
|
||||
@ -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) {
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
@ -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) {
|
||||
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
@ -75,6 +77,8 @@ 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
|
||||
@ -82,12 +86,14 @@ func NewContext() (*Context, error) {
|
||||
|
||||
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() {
|
||||
@ -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) {
|
||||
@ -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
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ func (u *userInterface) SwapBuffers() error {
|
||||
|
||||
func (u *userInterface) swapBuffers() {
|
||||
// The bound framebuffer must be the default one (0) before swapping buffers.
|
||||
u.context.BindZeroFramebuffer()
|
||||
u.context.BindScreenFramebuffer()
|
||||
u.context.RunOnContextThread(func() error {
|
||||
u.window.SwapBuffers()
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user