diff --git a/image.go b/image.go index e23ae1f29..1409f4082 100644 --- a/image.go +++ b/image.go @@ -311,15 +311,12 @@ func (i *imageImpl) restorePixels(context *opengl.Context) error { for j := 0; j < i.height; j++ { copy(img.Pix[j*img.Stride:], i.pixels[j*i.width*4:(j+1)*i.width*4]) } - var err error - 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) + texture, framebuffer, err := graphics.NewImageFromImage(img, glFilter(ui.GLContext(), i.filter)) if err != nil { return err } + i.texture = texture + i.framebuffer = framebuffer return nil } @@ -400,15 +397,10 @@ func NewImage(width, height int, filter Filter) (*Image, error) { f := func() error { imageM.Lock() 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 { return err } - framebuffer, err := graphics.NewFramebufferFromTexture(ui.GLContext(), texture) - if err != nil { - // TODO: texture should be removed here? - return err - } image.framebuffer = framebuffer image.texture = texture runtime.SetFinalizer(image, (*imageImpl).Dispose) @@ -455,11 +447,7 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) { } imageM.Lock() defer imageM.Unlock() - texture, err := graphics.NewTextureFromImage(ui.GLContext(), rgbaImg, glFilter(ui.GLContext(), filter)) - if err != nil { - return err - } - framebuffer, err := graphics.NewFramebufferFromTexture(ui.GLContext(), texture) + texture, framebuffer, err := graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter)) if err != nil { // TODO: texture should be removed here? return err @@ -489,7 +477,7 @@ func newImageWithZeroFramebuffer(width, height int) (*Image, error) { func newImageWithZeroFramebufferImpl(width, height int) (*Image, error) { imageM.Lock() defer imageM.Unlock() - f, err := graphics.NewZeroFramebuffer(ui.GLContext(), width, height) + f, err := graphics.NewZeroFramebuffer(width, height) if err != nil { return nil, err } diff --git a/internal/graphics/command.go b/internal/graphics/command.go index d336d8fa4..aac33f71c 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -17,6 +17,7 @@ package graphics import ( "errors" "fmt" + "image" "image/color" "math" @@ -159,3 +160,63 @@ func (c *disposeCommand) Exec(context *opengl.Context) error { } 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 +} diff --git a/internal/graphics/framebuffer.go b/internal/graphics/framebuffer.go index bdb048187..30cb3b009 100644 --- a/internal/graphics/framebuffer.go +++ b/internal/graphics/framebuffer.go @@ -42,7 +42,7 @@ type Framebuffer struct { proMatrix *[4][4]float64 } -func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, error) { +func NewZeroFramebuffer(width, height int) (*Framebuffer, error) { f := &Framebuffer{ width: width, height: height, @@ -51,17 +51,15 @@ func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, err return f, nil } -func NewFramebufferFromTexture(c *opengl.Context, texture *Texture) (*Framebuffer, error) { - native, err := c.NewFramebuffer(opengl.Texture(texture.native)) +func (f *Framebuffer) initFromTexture(context *opengl.Context, texture *Texture) error { + native, err := context.NewFramebuffer(opengl.Texture(texture.native)) if err != nil { - return nil, err + return err } - f := &Framebuffer{ - native: native, - width: texture.width, - height: texture.height, - } - return f, nil + f.native = native + f.width = texture.width + f.height = texture.height + return nil } func Dispose(texture *Texture, framebuffer *Framebuffer) error { diff --git a/internal/graphics/texture.go b/internal/graphics/texture.go index d7554ffd4..842d430fb 100644 --- a/internal/graphics/texture.go +++ b/internal/graphics/texture.go @@ -15,7 +15,6 @@ package graphics import ( - "errors" "image" "image/draw" @@ -50,35 +49,29 @@ type Texture struct { height int } -func NewTexture(c *opengl.Context, width, height int, filter opengl.Filter) (*Texture, error) { - w := int(NextPowerOf2Int32(int32(width))) - h := int(NextPowerOf2Int32(int32(height))) - if w < 4 { - return nil, errors.New("width must be equal or more than 4.") +func NewImage(width, height int, filter opengl.Filter) (*Texture, *Framebuffer, error) { + texture := &Texture{} + framebuffer := &Framebuffer{} + c := &newImageCommand{ + texture: texture, + framebuffer: framebuffer, + width: width, + height: height, + filter: filter, } - if h < 4 { - return nil, errors.New("height must be equal or more than 4.") - } - native, err := c.NewTexture(w, h, nil, filter) - if err != nil { - return nil, err - } - return &Texture{native, width, height}, nil + theCommandQueue.Enqueue(c) + return texture, framebuffer, nil } -func NewTextureFromImage(c *opengl.Context, img *image.RGBA, filter opengl.Filter) (*Texture, error) { - origSize := img.Bounds().Size() - if origSize.X < 4 { - return nil, errors.New("width must be equal or more than 4.") +func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Texture, *Framebuffer, error) { + texture := &Texture{} + framebuffer := &Framebuffer{} + c := &newImageFromImageCommand{ + texture: texture, + framebuffer: framebuffer, + img: img, + filter: filter, } - if origSize.Y < 4 { - return nil, errors.New("height must be equal or more than 4.") - } - 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 + theCommandQueue.Enqueue(c) + return texture, framebuffer, nil }