Refactoring: removing new* functions

This commit is contained in:
Hajime Hoshi 2014-12-08 04:22:50 +09:00
parent 1c52a28a83
commit 1c3273e0a6
10 changed files with 103 additions and 153 deletions

View File

@ -5,40 +5,16 @@ import (
"github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"github.com/hajimehoshi/ebiten/ui"
"sync"
)
type ContextUpdater struct {
context *context
}
func NewContextUpdater(screenWidth, screenHeight, screenScale int) *ContextUpdater {
return &ContextUpdater{
context: newContext(screenWidth, screenHeight, screenScale),
}
}
func (u *ContextUpdater) Update(drawer ui.Drawer) error {
return u.context.update(drawer)
}
var onceInit sync.Once
type context struct {
screenId graphics.RenderTargetID
defaultId graphics.RenderTargetID
currentId graphics.RenderTargetID
screenWidth int
screenHeight int
screenScale int
}
func newContext(screenWidth, screenHeight, screenScale int) *context {
onceInit.Do(func() {
func Initialize(screenWidth, screenHeight, screenScale int) (*ContextUpdater, error) {
gl.Init()
gl.Enable(gl.TEXTURE_2D)
gl.Enable(gl.BLEND)
})
c := &context{
screenWidth: screenWidth,
@ -47,22 +23,34 @@ func newContext(screenWidth, screenHeight, screenScale int) *context {
}
// The defualt framebuffer should be 0.
defaultRenderTarget := &renderTarget{
c.defaultId = idsInstance.addRenderTarget(&renderTarget{
width: screenWidth * screenScale,
height: screenHeight * screenScale,
flipY: true,
}
c.defaultId = idsInstance.addRenderTarget(defaultRenderTarget)
})
var err error
c.screenId, err = idsInstance.newRenderTarget(screenWidth, screenHeight, graphics.FilterNearest)
c.screenId, err = idsInstance.createRenderTarget(screenWidth, screenHeight, graphics.FilterNearest)
if err != nil {
panic("opengl.newContext: initializing the offscreen failed: " + err.Error())
return nil, err
}
c.ResetOffscreen()
c.Clear()
return c
return &ContextUpdater{c}, nil
}
func (u *ContextUpdater) Update(drawer ui.Drawer) error {
return u.context.update(drawer)
}
type context struct {
screenId graphics.RenderTargetID
defaultId graphics.RenderTargetID
currentId graphics.RenderTargetID
screenWidth int
screenHeight int
screenScale int
}
func (c *context) dispose() {

View File

@ -27,11 +27,11 @@ var idsInstance = &ids{
}
func NewRenderTargetID(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) {
return idsInstance.newRenderTarget(width, height, filter)
return idsInstance.createRenderTarget(width, height, filter)
}
func NewTextureID(img image.Image, filter graphics.Filter) (graphics.TextureID, error) {
return idsInstance.newTexture(img, filter)
return idsInstance.createTexture(img, filter)
}
func (i *ids) textureAt(id graphics.TextureID) *texture {
@ -52,8 +52,8 @@ func (i *ids) toTexture(id graphics.RenderTargetID) graphics.TextureID {
return i.renderTargetToTexture[id]
}
func (i *ids) newTexture(img image.Image, filter graphics.Filter) (graphics.TextureID, error) {
texture, err := newTextureFromImage(img, filter)
func (i *ids) createTexture(img image.Image, filter graphics.Filter) (graphics.TextureID, error) {
texture, err := createTextureFromImage(img, filter)
if err != nil {
return 0, err
}
@ -66,12 +66,12 @@ func (i *ids) newTexture(img image.Image, filter graphics.Filter) (graphics.Text
return textureId, nil
}
func (i *ids) newRenderTarget(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) {
texture, err := newTexture(width, height, filter)
func (i *ids) createRenderTarget(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) {
texture, err := createTexture(width, height, filter)
if err != nil {
return 0, err
}
framebuffer := newFramebuffer(gl.Texture(texture.native))
framebuffer := createFramebuffer(gl.Texture(texture.native))
// The current binded framebuffer can be changed.
i.currentRenderTargetId = -1
r := &renderTarget{
@ -128,18 +128,12 @@ func (i *ids) fillRenderTarget(id graphics.RenderTargetID, r, g, b uint8) {
gl.Clear(gl.COLOR_BUFFER_BIT)
}
func (i *ids) drawTexture(
target graphics.RenderTargetID,
id graphics.TextureID,
parts []graphics.TexturePart,
geo matrix.Geometry,
color matrix.Color) {
func (i *ids) drawTexture(target graphics.RenderTargetID, id graphics.TextureID, parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) {
texture := i.textureAt(id)
i.setViewportIfNeeded(target)
r := i.renderTargetAt(target)
projectionMatrix := r.projectionMatrix()
quads := shader.TextureQuads(parts, texture.width, texture.height)
shader.DrawTexture(texture.native, projectionMatrix, quads, geo, color)
shader.DrawTexture(texture.native, texture.width, texture.height, projectionMatrix, parts, geo, color)
}
func (i *ids) setViewportIfNeeded(id graphics.RenderTargetID) {

View File

@ -2,6 +2,7 @@ package shader
import (
"github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"sync"
)
@ -18,14 +19,15 @@ func glMatrix(matrix [4][4]float64) [16]float32 {
var once sync.Once
func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads []TextureQuad, geo matrix.Geometry, color matrix.Color) {
func DrawTexture(native gl.Texture, width, height int, projectionMatrix [4][4]float64, parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) {
once.Do(func() {
initialize()
})
if len(quads) == 0 {
if len(parts) == 0 {
return
}
quads := textureQuads(parts, width, height)
// TODO: Check performance
shaderProgram := use(glMatrix(projectionMatrix), geo, color)

View File

@ -43,62 +43,40 @@ func initialize() {
programColorMatrix.native.Use()
}
type qualifierVariableType int
const (
qualifierVariableTypeAttribute qualifierVariableType = iota
qualifierVariableTypeUniform
)
var (
shaderLocationCache = map[qualifierVariableType]map[string]gl.AttribLocation{
qualifierVariableTypeAttribute: {},
qualifierVariableTypeUniform: {},
}
)
func getLocation(program gl.Program, name string, qvType qualifierVariableType) gl.AttribLocation {
if location, ok := shaderLocationCache[qvType][name]; ok {
return location
}
location := gl.AttribLocation(-1)
switch qvType {
case qualifierVariableTypeAttribute:
location = program.GetAttribLocation(name)
case qualifierVariableTypeUniform:
location = gl.AttribLocation(program.GetUniformLocation(name))
default:
panic("no reach")
}
if location == -1 {
panic("GetAttribLocation failed")
}
shaderLocationCache[qvType][name] = location
return location
}
// NOTE: This caches are now used only for programColorMatrix
var attribLocationCache = map[string]gl.AttribLocation{}
var uniformLocationCache = map[string]gl.UniformLocation{}
func getAttributeLocation(program gl.Program, name string) gl.AttribLocation {
return getLocation(program, name, qualifierVariableTypeAttribute)
if location, ok := attribLocationCache[name]; ok {
return location
}
location := program.GetAttribLocation(name)
attribLocationCache[name] = location
return location
}
func getUniformLocation(program gl.Program, name string) gl.UniformLocation {
return gl.UniformLocation(getLocation(program, name, qualifierVariableTypeUniform))
if location, ok := uniformLocationCache[name]; ok {
return location
}
location := program.GetUniformLocation(name)
uniformLocationCache[name] = location
return location
}
func use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) gl.Program {
func use(projectionMatrix [16]float32, geo matrix.Geometry, color matrix.Color) gl.Program {
// TODO: Check the performance.
program := programColorMatrix
getUniformLocation(program.native, "projection_matrix").UniformMatrix4fv(false, projectionMatrix)
a := float32(geometryMatrix.Elements[0][0])
b := float32(geometryMatrix.Elements[0][1])
c := float32(geometryMatrix.Elements[1][0])
d := float32(geometryMatrix.Elements[1][1])
tx := float32(geometryMatrix.Elements[0][2])
ty := float32(geometryMatrix.Elements[1][2])
a := float32(geo.Elements[0][0])
b := float32(geo.Elements[0][1])
c := float32(geo.Elements[1][0])
d := float32(geo.Elements[1][1])
tx := float32(geo.Elements[0][2])
ty := float32(geo.Elements[1][2])
glModelviewMatrix := [...]float32{
a, c, 0, 0,
b, d, 0, 0,
@ -112,7 +90,7 @@ func use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatr
e := [4][5]float32{}
for i := 0; i < 4; i++ {
for j := 0; j < 5; j++ {
e[i][j] = float32(colorMatrix.Elements[i][j])
e[i][j] = float32(color.Elements[i][j])
}
}

View File

@ -4,7 +4,7 @@ import (
"github.com/hajimehoshi/ebiten/graphics"
)
type TextureQuad struct {
type textureQuad struct {
VertexX1 float32
VertexX2 float32
VertexY1 float32
@ -38,8 +38,8 @@ func v(y int, height int) float32 {
return float32(y) / float32(AdjustSizeForTexture(height))
}
func TextureQuads(parts []graphics.TexturePart, width, height int) []TextureQuad {
quads := []TextureQuad{}
func textureQuads(parts []graphics.TexturePart, width, height int) []textureQuad {
quads := []textureQuad{}
for _, part := range parts {
x1 := float32(part.LocationX)
x2 := float32(part.LocationX + part.Source.Width)
@ -49,7 +49,7 @@ func TextureQuads(parts []graphics.TexturePart, width, height int) []TextureQuad
u2 := u(part.Source.X+part.Source.Width, width)
v1 := v(part.Source.Y, height)
v2 := v(part.Source.Y+part.Source.Height, height)
quad := TextureQuad{x1, x2, y1, y2, u1, u2, v1, v2}
quad := textureQuad{x1, x2, y1, y2, u1, u2, v1, v2}
quads = append(quads, quad)
}
return quads

View File

@ -27,12 +27,11 @@ type renderTarget struct {
flipY bool
}
func newFramebuffer(nativeTexture gl.Texture) gl.Framebuffer {
func createFramebuffer(nativeTexture gl.Texture) gl.Framebuffer {
framebuffer := gl.GenFramebuffer()
framebuffer.Bind()
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, nativeTexture, 0)
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, nativeTexture, 0)
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
panic("creating framebuffer failed")
}

View File

@ -17,8 +17,7 @@ func adjustImageForTexture(img image.Image) *image.NRGBA {
shader.AdjustSizeForTexture(height),
},
}
if nrgba, ok := img.(*image.NRGBA); ok &&
img.Bounds() == adjustedImageBounds {
if nrgba, ok := img.(*image.NRGBA); ok && img.Bounds() == adjustedImageBounds {
return nrgba
}
@ -37,7 +36,7 @@ type texture struct {
height int
}
func newNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter graphics.Filter) gl.Texture {
func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter graphics.Filter) gl.Texture {
nativeTexture := gl.GenTexture()
if nativeTexture < 0 {
panic("glGenTexture failed")
@ -67,17 +66,17 @@ func newNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter gr
return nativeTexture
}
func newTexture(width, height int, filter graphics.Filter) (*texture, error) {
func createTexture(width, height int, filter graphics.Filter) (*texture, error) {
w := shader.AdjustSizeForTexture(width)
h := shader.AdjustSizeForTexture(height)
native := newNativeTexture(w, h, nil, filter)
native := createNativeTexture(w, h, nil, filter)
return &texture{native, width, height}, nil
}
func newTextureFromImage(img image.Image, filter graphics.Filter) (*texture, error) {
func createTextureFromImage(img image.Image, filter graphics.Filter) (*texture, error) {
adjustedImage := adjustImageForTexture(img)
size := adjustedImage.Bounds().Size()
native := newNativeTexture(size.X, size.Y, adjustedImage.Pix, filter)
native := createNativeTexture(size.X, size.Y, adjustedImage.Pix, filter)
return &texture{native, size.X, size.Y}, nil
}

View File

@ -4,7 +4,6 @@ import (
glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/opengl"
"github.com/hajimehoshi/ebiten/input"
"github.com/hajimehoshi/ebiten/ui"
"image"
"runtime"
@ -13,37 +12,11 @@ import (
type canvas struct {
window *glfw.Window
contextUpdater *opengl.ContextUpdater
keyboard *keyboard
keyboard keyboard
funcs chan func()
funcsDone chan struct{}
}
func newCanvas(width, height, scale int, title string) *canvas {
window, err := glfw.CreateWindow(width*scale, height*scale, title, nil, nil)
if err != nil {
panic(err)
}
canvas := &canvas{
window: window,
keyboard: newKeyboard(),
funcs: make(chan func()),
funcsDone: make(chan struct{}),
}
input.SetKeyboard(canvas.keyboard)
graphics.SetTextureFactory(canvas)
// For retina displays, recalculate the scale with the framebuffer size.
windowWidth, _ := window.GetFramebufferSize()
realScale := windowWidth / width
canvas.run()
canvas.use(func() {
canvas.contextUpdater = opengl.NewContextUpdater(width, height, realScale)
})
return canvas
}
func (c *canvas) Draw(d ui.Drawer) (err error) {
c.use(func() {
err = c.contextUpdater.Update(d)
@ -74,7 +47,7 @@ func (c *canvas) NewRenderTargetID(width, height int, filter graphics.Filter) (g
return id, err
}
func (c *canvas) run() {
func (c *canvas) run(width, height, scale int) {
go func() {
runtime.LockOSThread()
c.window.MakeContextCurrent()

View File

@ -6,18 +6,11 @@ import (
)
type keyboard struct {
pressedKeys map[input.Key]struct{}
}
func newKeyboard() *keyboard {
return &keyboard{
pressedKeys: map[input.Key]struct{}{},
}
keyPressed [input.KeyMax]bool
}
func (k *keyboard) IsKeyPressed(key input.Key) bool {
_, ok := k.pressedKeys[key]
return ok
return k.keyPressed[key]
}
var glfwKeyCodeToKey = map[glfw.Key]input.Key{
@ -30,10 +23,6 @@ var glfwKeyCodeToKey = map[glfw.Key]input.Key{
func (k *keyboard) update(window *glfw.Window) {
for g, u := range glfwKeyCodeToKey {
if window.GetKey(g) == glfw.Press {
k.pressedKeys[u] = struct{}{}
} else {
delete(k.pressedKeys, u)
}
k.keyPressed[u] = window.GetKey(g) == glfw.Press
}
}

View File

@ -4,6 +4,9 @@ import (
"errors"
"fmt"
glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/opengl"
"github.com/hajimehoshi/ebiten/input"
"github.com/hajimehoshi/ebiten/ui"
)
@ -22,8 +25,33 @@ func (u *UI) Start(width, height, scale int, title string) (ui.Canvas, error) {
return nil, errors.New("glfw.Init() fails")
}
glfw.WindowHint(glfw.Resizable, glfw.False)
u.canvas = newCanvas(width, height, scale, title)
return u.canvas, nil
window, err := glfw.CreateWindow(width*scale, height*scale, title, nil, nil)
if err != nil {
return nil, err
}
c := &canvas{
window: window,
funcs: make(chan func()),
funcsDone: make(chan struct{}),
}
input.SetKeyboard(&c.keyboard)
graphics.SetTextureFactory(c)
c.run(width, height, scale)
// For retina displays, recalculate the scale with the framebuffer size.
windowWidth, _ := window.GetFramebufferSize()
realScale := windowWidth / width
c.use(func() {
c.contextUpdater, err = opengl.Initialize(width, height, realScale)
})
if err != nil {
return nil, err
}
u.canvas = c
return c, nil
}
func (u *UI) DoEvents() {