From 17f4bcbd9504e48acf4eefd3917a8da5cbd79b97 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 3 Jun 2016 02:34:34 +0900 Subject: [PATCH] graphics: Introduce Commands (WIP) --- internal/graphics/command.go | 104 +++++++++++++++++++++++++++++++ internal/graphics/framebuffer.go | 44 ++++++------- 2 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 internal/graphics/command.go diff --git a/internal/graphics/command.go b/internal/graphics/command.go new file mode 100644 index 000000000..29dc76a0e --- /dev/null +++ b/internal/graphics/command.go @@ -0,0 +1,104 @@ +// Copyright 2016 Hajime Hoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package graphics + +import ( + "image/color" + "math" + + "github.com/hajimehoshi/ebiten/internal/graphics/opengl" +) + +type command interface { + Exec(context *opengl.Context) error +} + +type commandQueue struct { + commands []command +} + +var theCommandQueue = &commandQueue{ + commands: []command{}, +} + +func (q *commandQueue) Enqueue(command command) { + q.commands = append(q.commands, command) +} + +func (q *commandQueue) Exec(context *opengl.Context) error { + // TODO: Do optimizing before executing + for _, c := range q.commands { + if err := c.Exec(context); err != nil { + return err + } + } + q.commands = []command{} + return nil +} + +type fillCommand struct { + dst *Framebuffer + color color.Color +} + +func (c *fillCommand) Exec(context *opengl.Context) error { + if err := c.dst.setAsViewport(context); err != nil { + return err + } + cr, cg, cb, ca := c.color.RGBA() + const max = math.MaxUint16 + r := float64(cr) / max + g := float64(cg) / max + b := float64(cb) / max + a := float64(ca) / max + return context.FillFramebuffer(r, g, b, a) +} + +type drawImageCommand struct { + dst *Framebuffer + src *Texture + vertices []int16 + geo Matrix + color Matrix + mode opengl.CompositeMode +} + +func (c *drawImageCommand) Exec(context *opengl.Context) error { + if err := c.dst.setAsViewport(context); err != nil { + return err + } + p := c.dst.projectionMatrix() + return drawTexture(context, c.src.native, p, c.vertices, c.geo, c.color, c.mode) +} + +type replacePixelsCommand struct { + dst *Framebuffer + texture *Texture + pixels []uint8 +} + +func (c *replacePixelsCommand) Exec(context *opengl.Context) error { + // Filling with non black or white color is required here for glTexSubImage2D. + // Very mysterious but this actually works (Issue #186) + if err := c.dst.setAsViewport(context); err != nil { + return err + } + if err := context.FillFramebuffer(0, 0, 0.5, 1); err != nil { + return err + } + context.BindTexture(c.texture.native) + context.TexSubImage2D(c.pixels, c.texture.width, c.texture.height) + return nil +} diff --git a/internal/graphics/framebuffer.go b/internal/graphics/framebuffer.go index f5d78c806..1b1178512 100644 --- a/internal/graphics/framebuffer.go +++ b/internal/graphics/framebuffer.go @@ -16,7 +16,6 @@ package graphics import ( "image/color" - "math" "github.com/hajimehoshi/ebiten/internal/graphics/opengl" ) @@ -99,25 +98,24 @@ func (f *Framebuffer) projectionMatrix() *[4][4]float64 { return f.proMatrix } -func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error { - if err := f.setAsViewport(c); err != nil { - return err +func (f *Framebuffer) Fill(context *opengl.Context, clr color.Color) error { + c := &fillCommand{ + dst: f, + color: clr, } - cr, cg, cb, ca := clr.RGBA() - const max = math.MaxUint16 - r := float64(cr) / max - g := float64(cg) / max - b := float64(cb) / max - a := float64(ca) / max - return c.FillFramebuffer(r, g, b, a) + return c.Exec(context) } -func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error { - if err := f.setAsViewport(c); err != nil { - return err +func (f *Framebuffer) DrawTexture(context *opengl.Context, t *Texture, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error { + c := &drawImageCommand{ + dst: f, + src: t, + vertices: vertices, + geo: geo, + color: clr, + mode: mode, } - p := f.projectionMatrix() - return drawTexture(c, t.native, p, vertices, geo, clr, mode) + return c.Exec(context) } func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) { @@ -125,13 +123,11 @@ func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) { return c.FramebufferPixels(f.native, w, h) } -func (f *Framebuffer) ReplacePixels(c *opengl.Context, t *Texture, p []uint8) error { - // Filling with non black or white color is required here for glTexSubImage2D. - // Very mysterious but this actually works (Issue #186) - if err := f.Fill(c, color.RGBA{0, 0, 0x01, 0xff}); err != nil { - return err +func (f *Framebuffer) ReplacePixels(context *opengl.Context, t *Texture, p []uint8) error { + c := &replacePixelsCommand{ + dst: f, + texture: t, + pixels: p, } - c.BindTexture(t.native) - c.TexSubImage2D(p, t.width, t.height) - return nil + return c.Exec(context) }