graphics: Avoid copying images twice

This commit is contained in:
Hajime Hoshi 2016-12-27 03:18:56 +09:00
parent 260b938422
commit 5c403d9969
5 changed files with 20 additions and 45 deletions

View File

@ -84,7 +84,7 @@ func TestImagePixels(t *testing.T) {
} }
if got := img0.Bounds().Size(); got != img.Bounds().Size() { if got := img0.Bounds().Size(); got != img.Bounds().Size() {
t.Errorf("img size: got %d; want %d", got, img.Bounds().Size()) t.Fatalf("img size: got %d; want %d", got, img.Bounds().Size())
} }
for j := 0; j < img0.Bounds().Size().Y; j++ { for j := 0; j < img0.Bounds().Size().Y; j++ {

View File

@ -81,7 +81,7 @@ func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error
for j := 0; j < h; j++ { for j := 0; j < h; j++ {
copy(p[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:]) copy(p[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:])
} }
img, err := restorable.NewImageFromImage(rgbaImg, glFilter(filter)) img, err := restorable.NewImageFromImage(rgbaImg, w, h, glFilter(filter))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -180,9 +180,7 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color {
if i.restorable == nil { if i.restorable == nil {
return color.Transparent return color.Transparent
} }
w, _ := i.restorable.Size() clr, err := i.restorable.At(x, y, context)
idx := 4*x + 4*y*w
clr, err := i.restorable.At(idx, context)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -19,7 +19,6 @@ import (
"fmt" "fmt"
"image" "image"
"image/color" "image/color"
"image/draw"
"math" "math"
"sync" "sync"
@ -287,28 +286,6 @@ type newImageFromImageCommand struct {
filter opengl.Filter filter opengl.Filter
} }
func adjustImageForTexture(img *image.RGBA) *image.RGBA {
width, height := img.Bounds().Size().X, img.Bounds().Size().Y
adjustedImageBounds := image.Rectangle{
image.ZP,
image.Point{
NextPowerOf2Int(width),
NextPowerOf2Int(height),
},
}
if img.Bounds() == adjustedImageBounds {
return img
}
adjustedImage := image.NewRGBA(adjustedImageBounds)
dstBounds := image.Rectangle{
image.ZP,
img.Bounds().Size(),
}
draw.Draw(adjustedImage, dstBounds, img, img.Bounds().Min, draw.Src)
return adjustedImage
}
func (c *newImageFromImageCommand) Exec(context *opengl.Context, indexOffsetInBytes int) error { func (c *newImageFromImageCommand) Exec(context *opengl.Context, indexOffsetInBytes int) error {
origSize := c.img.Bounds().Size() origSize := c.img.Bounds().Size()
if origSize.X < 1 { if origSize.X < 1 {
@ -317,9 +294,11 @@ func (c *newImageFromImageCommand) Exec(context *opengl.Context, indexOffsetInBy
if origSize.Y < 1 { if origSize.Y < 1 {
return errors.New("graphics: height must be equal or more than 1.") return errors.New("graphics: height must be equal or more than 1.")
} }
adjustedImage := adjustImageForTexture(c.img) w, h := c.img.Bounds().Size().X, c.img.Bounds().Size().Y
size := adjustedImage.Bounds().Size() if c.img.Bounds() != image.Rect(0, 0, NextPowerOf2Int(w), NextPowerOf2Int(h)) {
native, err := context.NewTexture(size.X, size.Y, adjustedImage.Pix, c.filter) panic(fmt.Sprintf("graphics: invalid image bounds: %v", c.img.Bounds()))
}
native, err := context.NewTexture(w, h, c.img.Pix, c.filter)
if err != nil { if err != nil {
return err return err
} }

View File

@ -27,7 +27,7 @@ import (
func CopyImage(origImg image.Image) *image.RGBA { func CopyImage(origImg image.Image) *image.RGBA {
size := origImg.Bounds().Size() size := origImg.Bounds().Size()
w, h := size.X, size.Y w, h := size.X, size.Y
newImg := image.NewRGBA(image.Rect(0, 0, w, h)) newImg := image.NewRGBA(image.Rect(0, 0, NextPowerOf2Int(w), NextPowerOf2Int(h)))
switch origImg := origImg.(type) { switch origImg := origImg.(type) {
case *image.Paletted: case *image.Paletted:
b := origImg.Bounds() b := origImg.Bounds()
@ -63,7 +63,7 @@ func CopyImage(origImg image.Image) *image.RGBA {
index1 += d1 index1 += d1
} }
default: default:
draw.Draw(newImg, newImg.Bounds(), origImg, origImg.Bounds().Min, draw.Src) draw.Draw(newImg, image.Rect(0, 0, w, h), origImg, origImg.Bounds().Min, draw.Src)
} }
runtime.Gosched() runtime.Gosched()
return newImg return newImg
@ -93,11 +93,10 @@ func NewImage(width, height int, filter opengl.Filter) (*Image, error) {
return i, nil return i, nil
} }
func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Image, error) { func NewImageFromImage(img *image.RGBA, width, height int, filter opengl.Filter) (*Image, error) {
s := img.Bounds().Size()
i := &Image{ i := &Image{
width: s.X, width: width,
height: s.Y, height: height,
} }
c := &newImageFromImageCommand{ c := &newImageFromImageCommand{
result: i, result: i,

View File

@ -62,14 +62,12 @@ func NewImage(width, height int, filter opengl.Filter, volatile bool) (*Image, e
}, nil }, nil
} }
func NewImageFromImage(source *image.RGBA, filter opengl.Filter) (*Image, error) { func NewImageFromImage(source *image.RGBA, width, height int, filter opengl.Filter) (*Image, error) {
img, err := graphics.NewImageFromImage(source, filter) img, err := graphics.NewImageFromImage(source, width, height, 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
} }
size := source.Bounds().Size()
width, height := size.X, size.Y
return &Image{ return &Image{
image: img, image: img,
width: width, width: width,
@ -172,11 +170,12 @@ func (p *Image) appendDrawImageHistory(image *graphics.Image, vertices []float32
p.drawImageHistory = append(p.drawImageHistory, item) p.drawImageHistory = append(p.drawImageHistory, item)
} }
// At returns a color value at idx. // At returns a color value at (x, y).
// //
// Note that this must not be called until context is available. // Note that this must not be called until context is available.
// This means Pixels members must match with acutal state in VRAM. // This means Pixels members must match with acutal state in VRAM.
func (p *Image) At(idx int, context *opengl.Context) (color.RGBA, error) { func (p *Image) At(x, y int, context *opengl.Context) (color.RGBA, error) {
idx := 4*x + 4*y*p.width
if p.basePixels == nil || p.drawImageHistory != nil || p.stale { if p.basePixels == nil || p.drawImageHistory != nil || p.stale {
if err := p.readPixelsFromVRAM(p.image, context); err != nil { if err := p.readPixelsFromVRAM(p.image, context); err != nil {
return color.RGBA{}, err return color.RGBA{}, err
@ -260,13 +259,13 @@ func (p *Image) Restore(context *opengl.Context) error {
if p.stale { if p.stale {
return errors.New("restorable: pixels must not be stale when restoring") return errors.New("restorable: pixels must not be stale when restoring")
} }
img := image.NewRGBA(image.Rect(0, 0, p.width, p.height)) img := image.NewRGBA(image.Rect(0, 0, graphics.NextPowerOf2Int(p.width), graphics.NextPowerOf2Int(p.height)))
if p.basePixels != nil { if p.basePixels != nil {
for j := 0; j < p.height; j++ { for j := 0; j < p.height; j++ {
copy(img.Pix[j*img.Stride:], p.basePixels[j*p.width*4:(j+1)*p.width*4]) copy(img.Pix[j*img.Stride:], p.basePixels[j*p.width*4:(j+1)*p.width*4])
} }
} }
gimg, err := graphics.NewImageFromImage(img, p.filter) gimg, err := graphics.NewImageFromImage(img, p.width, p.height, p.filter)
if err != nil { if err != nil {
return err return err
} }