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/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)
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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
}