graphics: Add commands to create textures/framebuffers

This commit is contained in:
Hajime Hoshi 2016-06-12 00:23:26 +09:00
parent 2a58c095b8
commit 32c2cb3ead
4 changed files with 96 additions and 56 deletions

View File

@ -311,15 +311,12 @@ func (i *imageImpl) restorePixels(context *opengl.Context) error {
for j := 0; j < i.height; j++ { for j := 0; j < i.height; j++ {
copy(img.Pix[j*img.Stride:], i.pixels[j*i.width*4:(j+1)*i.width*4]) copy(img.Pix[j*img.Stride:], i.pixels[j*i.width*4:(j+1)*i.width*4])
} }
var err error texture, framebuffer, err := graphics.NewImageFromImage(img, glFilter(ui.GLContext(), i.filter))
i.texture, err = graphics.NewTextureFromImage(ui.GLContext(), img, glFilter(ui.GLContext(), i.filter))
if err != nil {
return err
}
i.framebuffer, err = graphics.NewFramebufferFromTexture(ui.GLContext(), i.texture)
if err != nil { if err != nil {
return err return err
} }
i.texture = texture
i.framebuffer = framebuffer
return nil return nil
} }
@ -400,15 +397,10 @@ func NewImage(width, height int, filter Filter) (*Image, error) {
f := func() error { f := func() error {
imageM.Lock() imageM.Lock()
defer imageM.Unlock() defer imageM.Unlock()
texture, err := graphics.NewTexture(ui.GLContext(), width, height, glFilter(ui.GLContext(), filter)) texture, framebuffer, err := graphics.NewImage(width, height, glFilter(ui.GLContext(), filter))
if err != nil { if err != nil {
return err return err
} }
framebuffer, err := graphics.NewFramebufferFromTexture(ui.GLContext(), texture)
if err != nil {
// TODO: texture should be removed here?
return err
}
image.framebuffer = framebuffer image.framebuffer = framebuffer
image.texture = texture image.texture = texture
runtime.SetFinalizer(image, (*imageImpl).Dispose) runtime.SetFinalizer(image, (*imageImpl).Dispose)
@ -455,11 +447,7 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
} }
imageM.Lock() imageM.Lock()
defer imageM.Unlock() defer imageM.Unlock()
texture, err := graphics.NewTextureFromImage(ui.GLContext(), rgbaImg, glFilter(ui.GLContext(), filter)) texture, framebuffer, err := graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter))
if err != nil {
return err
}
framebuffer, err := graphics.NewFramebufferFromTexture(ui.GLContext(), texture)
if err != nil { if err != nil {
// TODO: texture should be removed here? // TODO: texture should be removed here?
return err return err
@ -489,7 +477,7 @@ func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
func newImageWithZeroFramebufferImpl(width, height int) (*Image, error) { func newImageWithZeroFramebufferImpl(width, height int) (*Image, error) {
imageM.Lock() imageM.Lock()
defer imageM.Unlock() defer imageM.Unlock()
f, err := graphics.NewZeroFramebuffer(ui.GLContext(), width, height) f, err := graphics.NewZeroFramebuffer(width, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -17,6 +17,7 @@ package graphics
import ( import (
"errors" "errors"
"fmt" "fmt"
"image"
"image/color" "image/color"
"math" "math"
@ -159,3 +160,63 @@ func (c *disposeCommand) Exec(context *opengl.Context) error {
} }
return nil return nil
} }
type newImageFromImageCommand struct {
texture *Texture
framebuffer *Framebuffer
img *image.RGBA
filter opengl.Filter
}
func (c *newImageFromImageCommand) Exec(context *opengl.Context) error {
origSize := c.img.Bounds().Size()
if origSize.X < 4 {
return errors.New("graphics: width must be equal or more than 4.")
}
if origSize.Y < 4 {
return errors.New("graphics: height must be equal or more than 4.")
}
adjustedImage := adjustImageForTexture(c.img)
size := adjustedImage.Bounds().Size()
native, err := context.NewTexture(size.X, size.Y, adjustedImage.Pix, c.filter)
if err != nil {
return err
}
c.texture.native = native
c.texture.width = origSize.X
c.texture.height = origSize.Y
if err := c.framebuffer.initFromTexture(context, c.texture); err != nil {
return err
}
return nil
}
type newImageCommand struct {
texture *Texture
framebuffer *Framebuffer
width int
height int
filter opengl.Filter
}
func (c *newImageCommand) Exec(context *opengl.Context) error {
w := int(NextPowerOf2Int32(int32(c.width)))
h := int(NextPowerOf2Int32(int32(c.height)))
if w < 4 {
return errors.New("graphics: width must be equal or more than 4.")
}
if h < 4 {
return errors.New("graphics: height must be equal or more than 4.")
}
native, err := context.NewTexture(w, h, nil, c.filter)
if err != nil {
return err
}
c.texture.native = native
c.texture.width = c.width
c.texture.height = c.height
if err := c.framebuffer.initFromTexture(context, c.texture); err != nil {
return err
}
return nil
}

View File

@ -42,7 +42,7 @@ type Framebuffer struct {
proMatrix *[4][4]float64 proMatrix *[4][4]float64
} }
func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, error) { func NewZeroFramebuffer(width, height int) (*Framebuffer, error) {
f := &Framebuffer{ f := &Framebuffer{
width: width, width: width,
height: height, height: height,
@ -51,17 +51,15 @@ func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, err
return f, nil return f, nil
} }
func NewFramebufferFromTexture(c *opengl.Context, texture *Texture) (*Framebuffer, error) { func (f *Framebuffer) initFromTexture(context *opengl.Context, texture *Texture) error {
native, err := c.NewFramebuffer(opengl.Texture(texture.native)) native, err := context.NewFramebuffer(opengl.Texture(texture.native))
if err != nil { if err != nil {
return nil, err return err
} }
f := &Framebuffer{ f.native = native
native: native, f.width = texture.width
width: texture.width, f.height = texture.height
height: texture.height, return nil
}
return f, nil
} }
func Dispose(texture *Texture, framebuffer *Framebuffer) error { func Dispose(texture *Texture, framebuffer *Framebuffer) error {

View File

@ -15,7 +15,6 @@
package graphics package graphics
import ( import (
"errors"
"image" "image"
"image/draw" "image/draw"
@ -50,35 +49,29 @@ type Texture struct {
height int height int
} }
func NewTexture(c *opengl.Context, width, height int, filter opengl.Filter) (*Texture, error) { func NewImage(width, height int, filter opengl.Filter) (*Texture, *Framebuffer, error) {
w := int(NextPowerOf2Int32(int32(width))) texture := &Texture{}
h := int(NextPowerOf2Int32(int32(height))) framebuffer := &Framebuffer{}
if w < 4 { c := &newImageCommand{
return nil, errors.New("width must be equal or more than 4.") texture: texture,
framebuffer: framebuffer,
width: width,
height: height,
filter: filter,
} }
if h < 4 { theCommandQueue.Enqueue(c)
return nil, errors.New("height must be equal or more than 4.") return texture, framebuffer, nil
}
native, err := c.NewTexture(w, h, nil, filter)
if err != nil {
return nil, err
}
return &Texture{native, width, height}, nil
} }
func NewTextureFromImage(c *opengl.Context, img *image.RGBA, filter opengl.Filter) (*Texture, error) { func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Texture, *Framebuffer, error) {
origSize := img.Bounds().Size() texture := &Texture{}
if origSize.X < 4 { framebuffer := &Framebuffer{}
return nil, errors.New("width must be equal or more than 4.") c := &newImageFromImageCommand{
texture: texture,
framebuffer: framebuffer,
img: img,
filter: filter,
} }
if origSize.Y < 4 { theCommandQueue.Enqueue(c)
return nil, errors.New("height must be equal or more than 4.") return texture, framebuffer, nil
}
adjustedImage := adjustImageForTexture(img)
size := adjustedImage.Bounds().Size()
native, err := c.NewTexture(size.X, size.Y, adjustedImage.Pix, filter)
if err != nil {
return nil, err
}
return &Texture{native, origSize.X, origSize.Y}, nil
} }