remove Slice and Original from Canvas

This commit is contained in:
faiface 2017-03-31 15:03:06 +02:00
parent b138fc5d5b
commit 2562f6b754
1 changed files with 24 additions and 47 deletions

View File

@ -17,20 +17,15 @@ import (
// //
// It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor. // It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor.
type Canvas struct { type Canvas struct {
// these should **only** be accessed through orig f *glhf.Frame
f *glhf.Frame
borders pixel.Rect
pixels []uint8
dirty bool
// these should **never** be accessed through orig
s *glhf.Shader s *glhf.Shader
bounds pixel.Rect bounds pixel.Rect
pixels []uint8
dirty bool
mat mgl32.Mat3 mat mgl32.Mat3
col mgl32.Vec4 col mgl32.Vec4
smooth bool smooth bool
orig *Canvas
} }
// NewCanvas creates a new empty, fully transparent Canvas with given bounds. If the smooth flag is // NewCanvas creates a new empty, fully transparent Canvas with given bounds. If the smooth flag is
@ -41,7 +36,6 @@ func NewCanvas(bounds pixel.Rect, smooth bool) *Canvas {
mat: mgl32.Ident3(), mat: mgl32.Ident3(),
col: mgl32.Vec4{1, 1, 1, 1}, col: mgl32.Vec4{1, 1, 1, 1},
} }
c.orig = c
mainthread.Call(func() { mainthread.Call(func() {
var err error var err error
@ -171,27 +165,16 @@ func (c *Canvas) SetColorMask(col color.Color) {
} }
// SetBounds resizes the Canvas to the new bounds. Old content will be preserved. // SetBounds resizes the Canvas to the new bounds. Old content will be preserved.
//
// If the new Bounds fit into the Original borders, no new Canvas will be allocated.
func (c *Canvas) SetBounds(bounds pixel.Rect) { func (c *Canvas) SetBounds(bounds pixel.Rect) {
c.bounds = bounds
// if this bounds fit into the original bounds, no need to reallocate
if c.orig.borders.Contains(bounds.Min) && c.orig.borders.Contains(bounds.Max) {
return
}
mainthread.Call(func() { mainthread.Call(func() {
oldF := c.orig.f oldF := c.f
_, _, w, h := intBounds(bounds) _, _, w, h := intBounds(bounds)
c.f = glhf.NewFrame(w, h, c.smooth) c.f = glhf.NewFrame(w, h, c.smooth)
// preserve old content // preserve old content
if oldF != nil { if oldF != nil {
relBounds := bounds ox, oy, ow, oh := intBounds(bounds)
relBounds = relBounds.Moved(-c.orig.borders.Min)
ox, oy, ow, oh := intBounds(relBounds)
oldF.Blit( oldF.Blit(
c.f, c.f,
ox, oy, ox+ow, oy+oh, ox, oy, ox+ow, oy+oh,
@ -200,11 +183,9 @@ func (c *Canvas) SetBounds(bounds pixel.Rect) {
} }
}) })
// detach from orig c.bounds = bounds
c.borders = bounds
c.pixels = nil c.pixels = nil
c.dirty = true c.dirty = true
c.orig = c
} }
// Bounds returns the rectangular bounds of the Canvas. // Bounds returns the rectangular bounds of the Canvas.
@ -226,15 +207,13 @@ func (c *Canvas) Smooth() bool {
// must be manually called inside mainthread // must be manually called inside mainthread
func (c *Canvas) setGlhfBounds() { func (c *Canvas) setGlhfBounds() {
bounds := c.bounds bx, by, bw, bh := intBounds(c.bounds)
bounds.Moved(c.orig.borders.Min)
bx, by, bw, bh := intBounds(bounds)
glhf.Bounds(bx, by, bw, bh) glhf.Bounds(bx, by, bw, bh)
} }
// Clear fills the whole Canvas with a single color. // Clear fills the whole Canvas with a single color.
func (c *Canvas) Clear(color color.Color) { func (c *Canvas) Clear(color color.Color) {
c.orig.dirty = true c.dirty = true
nrgba := pixel.ToNRGBA(color) nrgba := pixel.ToNRGBA(color)
@ -248,39 +227,39 @@ func (c *Canvas) Clear(color color.Color) {
mainthread.CallNonBlock(func() { mainthread.CallNonBlock(func() {
c.setGlhfBounds() c.setGlhfBounds()
c.orig.f.Begin() c.f.Begin()
glhf.Clear( glhf.Clear(
float32(nrgba.R), float32(nrgba.R),
float32(nrgba.G), float32(nrgba.G),
float32(nrgba.B), float32(nrgba.B),
float32(nrgba.A), float32(nrgba.A),
) )
c.orig.f.End() c.f.End()
}) })
} }
// Color returns the color of the pixel over the given position inside the Canvas. // Color returns the color of the pixel over the given position inside the Canvas.
func (c *Canvas) Color(at pixel.Vec) pixel.NRGBA { func (c *Canvas) Color(at pixel.Vec) pixel.NRGBA {
if c.orig.dirty { if c.dirty {
mainthread.Call(func() { mainthread.Call(func() {
tex := c.orig.f.Texture() tex := c.f.Texture()
tex.Begin() tex.Begin()
c.orig.pixels = tex.Pixels(0, 0, tex.Width(), tex.Height()) c.pixels = tex.Pixels(0, 0, tex.Width(), tex.Height())
tex.End() tex.End()
}) })
c.orig.dirty = false c.dirty = false
} }
if !c.bounds.Contains(at) { if !c.bounds.Contains(at) {
return pixel.NRGBA{} return pixel.NRGBA{}
} }
bx, by, bw, _ := intBounds(c.orig.borders) bx, by, bw, _ := intBounds(c.bounds)
x, y := int(at.X())-bx, int(at.Y())-by x, y := int(at.X())-bx, int(at.Y())-by
off := y*bw + x off := y*bw + x
return pixel.NRGBA{ return pixel.NRGBA{
R: float64(c.orig.pixels[off*4+0]) / 255, R: float64(c.pixels[off*4+0]) / 255,
G: float64(c.orig.pixels[off*4+1]) / 255, G: float64(c.pixels[off*4+1]) / 255,
B: float64(c.orig.pixels[off*4+2]) / 255, B: float64(c.pixels[off*4+2]) / 255,
A: float64(c.orig.pixels[off*4+3]) / 255, A: float64(c.pixels[off*4+3]) / 255,
} }
} }
@ -291,7 +270,7 @@ type canvasTriangles struct {
} }
func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) { func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
ct.dst.orig.dirty = true ct.dst.dirty = true
// save the current state vars to avoid race condition // save the current state vars to avoid race condition
mat := ct.dst.mat mat := ct.dst.mat
@ -299,7 +278,7 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
mainthread.CallNonBlock(func() { mainthread.CallNonBlock(func() {
ct.dst.setGlhfBounds() ct.dst.setGlhfBounds()
ct.dst.orig.f.Begin() ct.dst.f.Begin()
ct.dst.s.Begin() ct.dst.s.Begin()
ct.dst.s.SetUniformAttr(canvasBounds, mgl32.Vec4{ ct.dst.s.SetUniformAttr(canvasBounds, mgl32.Vec4{
@ -337,7 +316,7 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
} }
ct.dst.s.End() ct.dst.s.End()
ct.dst.orig.f.End() ct.dst.f.End()
}) })
} }
@ -401,7 +380,7 @@ func (ccp *canvasCanvasPicture) Draw(t pixel.TargetTriangles) {
if ccp.dst != ct.dst { if ccp.dst != ct.dst {
panic(fmt.Errorf("(%T).Draw: TargetTriangles generated by different Canvas", ccp)) panic(fmt.Errorf("(%T).Draw: TargetTriangles generated by different Canvas", ccp))
} }
ct.draw(ccp.src.orig.f.Texture(), ccp.Bounds()) ct.draw(ccp.src.f.Texture(), ccp.Bounds())
} }
const ( const (
@ -445,7 +424,6 @@ out vec2 Texture;
out float Intensity; out float Intensity;
uniform mat3 transform; uniform mat3 transform;
uniform vec4 borders;
uniform vec4 bounds; uniform vec4 bounds;
void main() { void main() {
@ -468,7 +446,6 @@ in float Intensity;
out vec4 color; out vec4 color;
uniform vec4 colorMask; uniform vec4 colorMask;
uniform vec4 texBorders;
uniform vec4 texBounds; uniform vec4 texBounds;
uniform sampler2D tex; uniform sampler2D tex;