graphics: Add Image

This commit is contained in:
Hajime Hoshi 2016-06-12 01:34:21 +09:00
parent 32e773cf10
commit eca175e0f4
3 changed files with 53 additions and 49 deletions

View File

@ -163,8 +163,7 @@ func (i *Image) ReplacePixels(p []uint8) error {
} }
type imageImpl struct { type imageImpl struct {
framebuffer *graphics.Framebuffer image *graphics.Image
texture *graphics.Texture
defaultFramebuffer bool defaultFramebuffer bool
disposed bool disposed bool
width int width int
@ -180,7 +179,7 @@ func (i *imageImpl) Fill(clr color.Color) error {
return errors.New("ebiten: image is already disposed") return errors.New("ebiten: image is already disposed")
} }
i.pixels = nil i.pixels = nil
return i.framebuffer.Fill(clr) return i.image.Fill(clr)
} }
func isWholeNumber(x float64) bool { func isWholeNumber(x float64) bool {
@ -222,7 +221,7 @@ func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
geom := &options.GeoM geom := &options.GeoM
colorm := &options.ColorM colorm := &options.ColorM
mode := opengl.CompositeMode(options.CompositeMode) mode := opengl.CompositeMode(options.CompositeMode)
if err := i.framebuffer.DrawTexture(image.impl.texture, vertices[:16*n], geom, colorm, mode); err != nil { if err := i.image.DrawImage(image.impl.image, vertices[:16*n], geom, colorm, mode); err != nil {
return err return err
} }
return nil return nil
@ -239,7 +238,7 @@ func (i *imageImpl) At(x, y int) color.Color {
} }
if i.pixels == nil { if i.pixels == nil {
var err error var err error
i.pixels, err = i.framebuffer.Pixels(ui.GLContext()) i.pixels, err = i.image.Pixels(ui.GLContext())
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -259,7 +258,7 @@ func (i *imageImpl) restorePixels(context *opengl.Context) error {
return nil return nil
} }
// TODO: As the texture is already disposed, is it correct to delete it here? // TODO: As the texture is already disposed, is it correct to delete it here?
if err := graphics.Dispose(i.texture, i.framebuffer); err != nil { if err := i.image.Dispose(); err != nil {
return err return err
} }
// TODO: Recalc i.pixels here // TODO: Recalc i.pixels here
@ -267,12 +266,11 @@ 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])
} }
texture, framebuffer, err := graphics.NewImageFromImage(img, glFilter(context, i.filter)) var err error
i.image, err = graphics.NewImageFromImage(img, glFilter(context, i.filter))
if err != nil { if err != nil {
return err return err
} }
i.texture = texture
i.framebuffer = framebuffer
return nil return nil
} }
@ -282,11 +280,10 @@ func (i *imageImpl) Dispose() error {
if i.isDisposed() { if i.isDisposed() {
return errors.New("ebiten: image is already disposed") return errors.New("ebiten: image is already disposed")
} }
if err := graphics.Dispose(i.texture, i.framebuffer); err != nil { if err := i.image.Dispose(); err != nil {
return err return err
} }
i.framebuffer = nil i.image = nil
i.texture = nil
i.disposed = true i.disposed = true
i.pixels = nil i.pixels = nil
runtime.SetFinalizer(i, nil) runtime.SetFinalizer(i, nil)
@ -308,7 +305,7 @@ func (i *imageImpl) ReplacePixels(p []uint8) error {
if i.isDisposed() { if i.isDisposed() {
return errors.New("ebiten: image is already disposed") return errors.New("ebiten: image is already disposed")
} }
return i.framebuffer.ReplacePixels(i.texture, p) return i.image.ReplacePixels(p)
} }
// A DrawImageOptions represents options to render an image on an image. // A DrawImageOptions represents options to render an image on an image.
@ -339,14 +336,12 @@ func NewImage(width, height int, filter Filter) (*Image, error) {
} }
imageM.Lock() imageM.Lock()
defer imageM.Unlock() defer imageM.Unlock()
texture, framebuffer, err := graphics.NewImage(width, height, glFilter(ui.GLContext(), filter)) image.image, err = graphics.NewImage(width, height, glFilter(ui.GLContext(), filter))
if err != nil { if err != nil {
return nil, err return nil, err
} }
image.framebuffer = framebuffer
image.texture = texture
runtime.SetFinalizer(image, (*imageImpl).Dispose) runtime.SetFinalizer(image, (*imageImpl).Dispose)
if err := image.framebuffer.Fill(color.Transparent); err != nil { if err := image.image.Fill(color.Transparent); err != nil {
return nil, err return nil, err
} }
return eimg, nil return eimg, nil
@ -380,13 +375,11 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
} }
imageM.Lock() imageM.Lock()
defer imageM.Unlock() defer imageM.Unlock()
texture, framebuffer, err := graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter)) img.image, err = graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter))
if err != nil { if err != nil {
// TODO: texture should be removed here? // TODO: texture should be removed here?
return nil, err return nil, err
} }
img.framebuffer = framebuffer
img.texture = texture
runtime.SetFinalizer(img, (*imageImpl).Dispose) runtime.SetFinalizer(img, (*imageImpl).Dispose)
return eimg, nil return eimg, nil
} }
@ -402,13 +395,12 @@ 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(width, height) i, err := graphics.NewZeroFramebufferImage(width, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
img := &imageImpl{ img := &imageImpl{
framebuffer: f, image: i,
texture: nil,
width: width, width: width,
height: height, height: height,
defaultFramebuffer: true, defaultFramebuffer: true,

View File

@ -42,13 +42,15 @@ type Framebuffer struct {
proMatrix *[4][4]float64 proMatrix *[4][4]float64
} }
func NewZeroFramebuffer(width, height int) (*Framebuffer, error) { func NewZeroFramebufferImage(width, height int) (*Image, error) {
f := &Framebuffer{ f := &Framebuffer{
width: width, width: width,
height: height, height: height,
flipY: true, flipY: true,
} }
return f, nil return &Image{
framebuffer: f,
}, nil
} }
func (f *Framebuffer) initFromTexture(context *opengl.Context, texture *Texture) error { func (f *Framebuffer) initFromTexture(context *opengl.Context, texture *Texture) error {
@ -62,10 +64,10 @@ func (f *Framebuffer) initFromTexture(context *opengl.Context, texture *Texture)
return nil return nil
} }
func Dispose(texture *Texture, framebuffer *Framebuffer) error { func (i *Image) Dispose() error {
c := &disposeCommand{ c := &disposeCommand{
framebuffer: framebuffer, framebuffer: i.framebuffer,
texture: texture, texture: i.texture,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
return nil return nil
@ -94,19 +96,19 @@ func (f *Framebuffer) projectionMatrix() *[4][4]float64 {
return f.proMatrix return f.proMatrix
} }
func (f *Framebuffer) Fill(clr color.Color) error { func (i *Image) Fill(clr color.Color) error {
c := &fillCommand{ c := &fillCommand{
dst: f, dst: i.framebuffer,
color: clr, color: clr,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
return nil return nil
} }
func (f *Framebuffer) DrawTexture(t *Texture, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error { func (i *Image) DrawImage(src *Image, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error {
c := &drawImageCommand{ c := &drawImageCommand{
dst: f, dst: i.framebuffer,
src: t, src: src.texture,
vertices: vertices, vertices: vertices,
geo: geo, geo: geo,
color: clr, color: clr,
@ -116,18 +118,19 @@ func (f *Framebuffer) DrawTexture(t *Texture, vertices []int16, geo, clr Matrix,
return nil return nil
} }
func (f *Framebuffer) Pixels(context *opengl.Context) ([]uint8, error) { func (i *Image) Pixels(context *opengl.Context) ([]uint8, error) {
// Flush the enqueued commands so that pixels are certainly read. // Flush the enqueued commands so that pixels are certainly read.
if err := theCommandQueue.Flush(context); err != nil { if err := theCommandQueue.Flush(context); err != nil {
return nil, err return nil, err
} }
f := i.framebuffer
return context.FramebufferPixels(f.native, f.width, f.height) return context.FramebufferPixels(f.native, f.width, f.height)
} }
func (f *Framebuffer) ReplacePixels(t *Texture, p []uint8) error { func (i *Image) ReplacePixels(p []uint8) error {
c := &replacePixelsCommand{ c := &replacePixelsCommand{
dst: f, dst: i.framebuffer,
texture: t, texture: i.texture,
pixels: p, pixels: p,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)

View File

@ -43,35 +43,44 @@ func adjustImageForTexture(img *image.RGBA) *image.RGBA {
return adjustedImage return adjustedImage
} }
type Image struct {
texture *Texture
framebuffer *Framebuffer
}
type Texture struct { type Texture struct {
native opengl.Texture native opengl.Texture
width int width int
height int height int
} }
func NewImage(width, height int, filter opengl.Filter) (*Texture, *Framebuffer, error) { func NewImage(width, height int, filter opengl.Filter) (*Image, error) {
texture := &Texture{} i := &Image{
framebuffer := &Framebuffer{} texture: &Texture{},
framebuffer: &Framebuffer{},
}
c := &newImageCommand{ c := &newImageCommand{
texture: texture, texture: i.texture,
framebuffer: framebuffer, framebuffer: i.framebuffer,
width: width, width: width,
height: height, height: height,
filter: filter, filter: filter,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
return texture, framebuffer, nil return i, nil
} }
func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Texture, *Framebuffer, error) { func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Image, error) {
texture := &Texture{} i := &Image{
framebuffer := &Framebuffer{} texture: &Texture{},
framebuffer: &Framebuffer{},
}
c := &newImageFromImageCommand{ c := &newImageFromImageCommand{
texture: texture, texture: i.texture,
framebuffer: framebuffer, framebuffer: i.framebuffer,
img: img, img: img,
filter: filter, filter: filter,
} }
theCommandQueue.Enqueue(c) theCommandQueue.Enqueue(c)
return texture, framebuffer, nil return i, nil
} }