diff --git a/graphics/opengl/canvas.go b/graphics/opengl/canvas.go index 86817477e..549ed7873 100644 --- a/graphics/opengl/canvas.go +++ b/graphics/opengl/canvas.go @@ -10,34 +10,52 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics/matrix" "github.com/hajimehoshi/go-ebiten/graphics/opengl/offscreen" "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture" - "image" "math" ) type Canvas struct { - screenId graphics.RenderTargetId - ids *ids - offscreen *offscreen.Offscreen + screenId graphics.RenderTargetId + ids *ids + offscreen *offscreen.Offscreen + screenScale int } -func newCanvas(screenWidth, screenHeight, screenScale int) *Canvas { +func newCanvas(ids *ids, screenWidth, screenHeight, screenScale int) *Canvas { canvas := &Canvas{ - ids: newIds(), - offscreen: offscreen.New(screenWidth, screenHeight, screenScale), + ids: ids, + offscreen: offscreen.New(screenWidth, screenHeight, screenScale), + screenScale: screenScale, } var err error - canvas.screenId, err = canvas.createRenderTarget( + canvas.screenId, err = ids.CreateRenderTarget( screenWidth, screenHeight, texture.FilterNearest) if err != nil { panic("initializing the offscreen failed: " + err.Error()) } - canvas.Init() - return canvas } +func (canvas *Canvas) update(draw func(graphics.Canvas)) { + canvas.init() + canvas.ResetOffscreen() + canvas.Clear() + + draw(canvas) + + canvas.flush() + canvas.setMainFramebufferOffscreen() + canvas.Clear() + + scale := float64(canvas.screenScale) + geometryMatrix := matrix.IdentityGeometry() + geometryMatrix.Scale(scale, scale) + canvas.DrawRenderTarget(canvas.screenId, + geometryMatrix, matrix.IdentityColor()) + canvas.flush() +} + func (canvas *Canvas) Clear() { canvas.Fill(0, 0, 0) } @@ -78,8 +96,8 @@ func (canvas *Canvas) DrawRenderTargetParts( canvas.DrawTextureParts(canvas.ids.ToTexture(id), parts, geometryMatrix, colorMatrix) } -// Init initializes the canvas. The initial state is saved for each GL canvas. -func (canvas *Canvas) Init() { +// init initializes the canvas. The initial state is saved for each GL canvas. +func (canvas *Canvas) init() { C.glEnable(C.GL_TEXTURE_2D) C.glEnable(C.GL_BLEND) } @@ -100,22 +118,3 @@ func (canvas *Canvas) setMainFramebufferOffscreen() { func (canvas *Canvas) flush() { C.glFlush() } - -func (canvas *Canvas) createRenderTarget(width, height int, filter texture.Filter) ( - graphics.RenderTargetId, error) { - renderTargetId, err := canvas.ids.CreateRenderTarget(width, height, filter) - if err != nil { - return 0, err - } - return renderTargetId, nil -} - -func (canvas *Canvas) CreateRenderTarget(width, height int) ( - graphics.RenderTargetId, error) { - return canvas.createRenderTarget(width, height, texture.FilterLinear) -} - -func (canvas *Canvas) CreateTextureFromImage(img image.Image) ( - graphics.TextureId, error) { - return canvas.ids.CreateTextureFromImage(img) -} diff --git a/graphics/opengl/device.go b/graphics/opengl/device.go index 672521857..4a08e5147 100644 --- a/graphics/opengl/device.go +++ b/graphics/opengl/device.go @@ -2,47 +2,37 @@ package opengl import ( "github.com/hajimehoshi/go-ebiten/graphics" - "github.com/hajimehoshi/go-ebiten/graphics/matrix" + "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture" "image" ) type Device struct { - canvas *Canvas - screenScale int + ids *ids } func NewDevice(screenWidth, screenHeight, screenScale int) *Device { - canvas := newCanvas(screenWidth, screenHeight, screenScale) - return &Device{ - canvas: canvas, - screenScale: screenScale, + device := &Device{ + ids: newIds(), } + return device } -func (d *Device) Update(draw func(graphics.Canvas)) { - canvas := d.canvas - canvas.Init() - canvas.ResetOffscreen() - canvas.Clear() +func (d *Device) CreateCanvas(screenWidth, screenHeight, screenScale int) *Canvas { + return newCanvas(d.ids, screenWidth, screenHeight, screenScale) +} - draw(canvas) - - canvas.flush() - canvas.setMainFramebufferOffscreen() - canvas.Clear() - - scale := float64(d.screenScale) - geometryMatrix := matrix.IdentityGeometry() - geometryMatrix.Scale(scale, scale) - canvas.DrawRenderTarget(canvas.screenId, - geometryMatrix, matrix.IdentityColor()) - canvas.flush() +func (d *Device) Update(canvas *Canvas, draw func(graphics.Canvas)) { + canvas.update(draw) } func (d *Device) CreateRenderTarget(width, height int) (graphics.RenderTargetId, error) { - return d.canvas.CreateRenderTarget(width, height) + renderTargetId, err := d.ids.CreateRenderTarget(width, height, texture.FilterLinear) + if err != nil { + return 0, err + } + return renderTargetId, nil } func (d *Device) CreateTexture(img image.Image) (graphics.TextureId, error) { - return d.canvas.CreateTextureFromImage(img) + return d.ids.CreateTextureFromImage(img) } diff --git a/ui/cocoa/cocoa.go b/ui/cocoa/cocoa.go index 3a42ccca7..c6b1c55f9 100644 --- a/ui/cocoa/cocoa.go +++ b/ui/cocoa/cocoa.go @@ -20,7 +20,7 @@ type UI struct { screenWidth int screenHeight int screenScale int - window *window + window *Window initialEventSent bool textureFactory *textureFactory graphicsDevice *opengl.Device @@ -50,11 +50,10 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { u.screenHeight, u.screenScale) }) - - u.window = u.textureFactory.createWindow( - u, - u.screenWidth*u.screenScale, - u.screenHeight*u.screenScale, + u.window = u.CreateWindow( + u.screenWidth, + u.screenHeight, + u.screenScale, title) currentUI = u @@ -62,6 +61,10 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { return u } +func (u *UI) CreateWindow(width, height, scale int, title string) *Window { + return u.textureFactory.createWindow(u, width, height, scale, title) +} + func (u *UI) PollEvents() { C.PollEvents() if !u.initialEventSent { diff --git a/ui/cocoa/texture_factory.go b/ui/cocoa/texture_factory.go index ad083df7b..7946e65d3 100644 --- a/ui/cocoa/texture_factory.go +++ b/ui/cocoa/texture_factory.go @@ -50,6 +50,6 @@ func (t *textureFactory) useContext(f func()) { <-t.funcsDone } -func (t *textureFactory) createWindow(ui *UI, width, height int, title string) *window { - return runWindow(ui, width, height, title, t.sharedContext) +func (t *textureFactory) createWindow(ui *UI, width, height, scale int, title string) *Window { + return runWindow(ui, width, height, scale, title, t.sharedContext) } diff --git a/ui/cocoa/window.go b/ui/cocoa/window.go index 8154e6ed4..f2797116c 100644 --- a/ui/cocoa/window.go +++ b/ui/cocoa/window.go @@ -12,19 +12,21 @@ package cocoa import "C" import ( "github.com/hajimehoshi/go-ebiten/graphics" + "github.com/hajimehoshi/go-ebiten/graphics/opengl" "runtime" "unsafe" ) -type window struct { +type Window struct { ui *UI native unsafe.Pointer + canvas *opengl.Canvas funcs chan func() funcsDone chan struct{} } -func runWindow(ui *UI, width, height int, title string, sharedContext unsafe.Pointer) *window { - w := &window{ +func runWindow(ui *UI, width, height, scale int, title string, sharedContext unsafe.Pointer) *Window { + w := &Window{ ui: ui, funcs: make(chan func()), funcsDone: make(chan struct{}), @@ -37,18 +39,21 @@ func runWindow(ui *UI, width, height int, title string, sharedContext unsafe.Poi go func() { runtime.LockOSThread() glContext := C.CreateGLContext(sharedContext) - w.native = C.CreateWindow(C.size_t(width), - C.size_t(height), + w.native = C.CreateWindow(C.size_t(width*scale), + C.size_t(height*scale), cTitle, glContext) close(ch) w.loop() }() <-ch + w.useContext(func() { + w.canvas = ui.graphicsDevice.CreateCanvas(width, height, scale) + }) return w } -func (w *window) loop() { +func (w *Window) loop() { for { select { case f := <-w.funcs: @@ -61,13 +66,13 @@ func (w *window) loop() { } } -func (w *window) Draw(f func(graphics.Canvas)) { +func (w *Window) Draw(f func(graphics.Canvas)) { w.useContext(func() { - w.ui.graphicsDevice.Update(f) + w.ui.graphicsDevice.Update(w.canvas, f) }) } -func (w *window) useContext(f func()) { +func (w *Window) useContext(f func()) { w.funcs <- f <-w.funcsDone }