Separate Device and Canvas

This commit is contained in:
Hajime Hoshi 2013-12-09 23:52:14 +09:00
parent 7e246015ff
commit c18b1cc9bd
5 changed files with 71 additions and 74 deletions

View File

@ -10,34 +10,52 @@ import (
"github.com/hajimehoshi/go-ebiten/graphics/matrix" "github.com/hajimehoshi/go-ebiten/graphics/matrix"
"github.com/hajimehoshi/go-ebiten/graphics/opengl/offscreen" "github.com/hajimehoshi/go-ebiten/graphics/opengl/offscreen"
"github.com/hajimehoshi/go-ebiten/graphics/opengl/texture" "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture"
"image"
"math" "math"
) )
type Canvas struct { type Canvas struct {
screenId graphics.RenderTargetId screenId graphics.RenderTargetId
ids *ids ids *ids
offscreen *offscreen.Offscreen offscreen *offscreen.Offscreen
screenScale int
} }
func newCanvas(screenWidth, screenHeight, screenScale int) *Canvas { func newCanvas(ids *ids, screenWidth, screenHeight, screenScale int) *Canvas {
canvas := &Canvas{ canvas := &Canvas{
ids: newIds(), ids: ids,
offscreen: offscreen.New(screenWidth, screenHeight, screenScale), offscreen: offscreen.New(screenWidth, screenHeight, screenScale),
screenScale: screenScale,
} }
var err error var err error
canvas.screenId, err = canvas.createRenderTarget( canvas.screenId, err = ids.CreateRenderTarget(
screenWidth, screenHeight, texture.FilterNearest) screenWidth, screenHeight, texture.FilterNearest)
if err != nil { if err != nil {
panic("initializing the offscreen failed: " + err.Error()) panic("initializing the offscreen failed: " + err.Error())
} }
canvas.Init()
return canvas 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() { func (canvas *Canvas) Clear() {
canvas.Fill(0, 0, 0) canvas.Fill(0, 0, 0)
} }
@ -78,8 +96,8 @@ func (canvas *Canvas) DrawRenderTargetParts(
canvas.DrawTextureParts(canvas.ids.ToTexture(id), parts, geometryMatrix, colorMatrix) canvas.DrawTextureParts(canvas.ids.ToTexture(id), parts, geometryMatrix, colorMatrix)
} }
// Init initializes the canvas. The initial state is saved for each GL canvas. // init initializes the canvas. The initial state is saved for each GL canvas.
func (canvas *Canvas) Init() { func (canvas *Canvas) init() {
C.glEnable(C.GL_TEXTURE_2D) C.glEnable(C.GL_TEXTURE_2D)
C.glEnable(C.GL_BLEND) C.glEnable(C.GL_BLEND)
} }
@ -100,22 +118,3 @@ func (canvas *Canvas) setMainFramebufferOffscreen() {
func (canvas *Canvas) flush() { func (canvas *Canvas) flush() {
C.glFlush() 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)
}

View File

@ -2,47 +2,37 @@ package opengl
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/matrix" "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture"
"image" "image"
) )
type Device struct { type Device struct {
canvas *Canvas ids *ids
screenScale int
} }
func NewDevice(screenWidth, screenHeight, screenScale int) *Device { func NewDevice(screenWidth, screenHeight, screenScale int) *Device {
canvas := newCanvas(screenWidth, screenHeight, screenScale) device := &Device{
return &Device{ ids: newIds(),
canvas: canvas,
screenScale: screenScale,
} }
return device
} }
func (d *Device) Update(draw func(graphics.Canvas)) { func (d *Device) CreateCanvas(screenWidth, screenHeight, screenScale int) *Canvas {
canvas := d.canvas return newCanvas(d.ids, screenWidth, screenHeight, screenScale)
canvas.Init() }
canvas.ResetOffscreen()
canvas.Clear()
draw(canvas) func (d *Device) Update(canvas *Canvas, draw func(graphics.Canvas)) {
canvas.update(draw)
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) CreateRenderTarget(width, height int) (graphics.RenderTargetId, error) { 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) { func (d *Device) CreateTexture(img image.Image) (graphics.TextureId, error) {
return d.canvas.CreateTextureFromImage(img) return d.ids.CreateTextureFromImage(img)
} }

View File

@ -20,7 +20,7 @@ type UI struct {
screenWidth int screenWidth int
screenHeight int screenHeight int
screenScale int screenScale int
window *window window *Window
initialEventSent bool initialEventSent bool
textureFactory *textureFactory textureFactory *textureFactory
graphicsDevice *opengl.Device graphicsDevice *opengl.Device
@ -50,11 +50,10 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
u.screenHeight, u.screenHeight,
u.screenScale) u.screenScale)
}) })
u.window = u.CreateWindow(
u.window = u.textureFactory.createWindow( u.screenWidth,
u, u.screenHeight,
u.screenWidth*u.screenScale, u.screenScale,
u.screenHeight*u.screenScale,
title) title)
currentUI = u currentUI = u
@ -62,6 +61,10 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
return u 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() { func (u *UI) PollEvents() {
C.PollEvents() C.PollEvents()
if !u.initialEventSent { if !u.initialEventSent {

View File

@ -50,6 +50,6 @@ func (t *textureFactory) useContext(f func()) {
<-t.funcsDone <-t.funcsDone
} }
func (t *textureFactory) createWindow(ui *UI, width, height int, title string) *window { func (t *textureFactory) createWindow(ui *UI, width, height, scale int, title string) *Window {
return runWindow(ui, width, height, title, t.sharedContext) return runWindow(ui, width, height, scale, title, t.sharedContext)
} }

View File

@ -12,19 +12,21 @@ package cocoa
import "C" import "C"
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/opengl"
"runtime" "runtime"
"unsafe" "unsafe"
) )
type window struct { type Window struct {
ui *UI ui *UI
native unsafe.Pointer native unsafe.Pointer
canvas *opengl.Canvas
funcs chan func() funcs chan func()
funcsDone chan struct{} funcsDone chan struct{}
} }
func runWindow(ui *UI, width, height int, title string, sharedContext unsafe.Pointer) *window { func runWindow(ui *UI, width, height, scale int, title string, sharedContext unsafe.Pointer) *Window {
w := &window{ w := &Window{
ui: ui, ui: ui,
funcs: make(chan func()), funcs: make(chan func()),
funcsDone: make(chan struct{}), funcsDone: make(chan struct{}),
@ -37,18 +39,21 @@ func runWindow(ui *UI, width, height int, title string, sharedContext unsafe.Poi
go func() { go func() {
runtime.LockOSThread() runtime.LockOSThread()
glContext := C.CreateGLContext(sharedContext) glContext := C.CreateGLContext(sharedContext)
w.native = C.CreateWindow(C.size_t(width), w.native = C.CreateWindow(C.size_t(width*scale),
C.size_t(height), C.size_t(height*scale),
cTitle, cTitle,
glContext) glContext)
close(ch) close(ch)
w.loop() w.loop()
}() }()
<-ch <-ch
w.useContext(func() {
w.canvas = ui.graphicsDevice.CreateCanvas(width, height, scale)
})
return w return w
} }
func (w *window) loop() { func (w *Window) loop() {
for { for {
select { select {
case f := <-w.funcs: 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.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.funcs <- f
<-w.funcsDone <-w.funcsDone
} }