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() {
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++ {

View File

@ -81,7 +81,7 @@ func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error
for j := 0; j < h; j++ {
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 {
return nil, err
}
@ -180,9 +180,7 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color {
if i.restorable == nil {
return color.Transparent
}
w, _ := i.restorable.Size()
idx := 4*x + 4*y*w
clr, err := i.restorable.At(idx, context)
clr, err := i.restorable.At(x, y, context)
if err != nil {
panic(err)
}

View File

@ -19,7 +19,6 @@ import (
"fmt"
"image"
"image/color"
"image/draw"
"math"
"sync"
@ -287,28 +286,6 @@ type newImageFromImageCommand struct {
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 {
origSize := c.img.Bounds().Size()
if origSize.X < 1 {
@ -317,9 +294,11 @@ func (c *newImageFromImageCommand) Exec(context *opengl.Context, indexOffsetInBy
if origSize.Y < 1 {
return errors.New("graphics: height must be equal or more than 1.")
}
adjustedImage := adjustImageForTexture(c.img)
size := adjustedImage.Bounds().Size()
native, err := context.NewTexture(size.X, size.Y, adjustedImage.Pix, c.filter)
w, h := c.img.Bounds().Size().X, c.img.Bounds().Size().Y
if c.img.Bounds() != image.Rect(0, 0, NextPowerOf2Int(w), NextPowerOf2Int(h)) {
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 {
return err
}

View File

@ -27,7 +27,7 @@ import (
func CopyImage(origImg image.Image) *image.RGBA {
size := origImg.Bounds().Size()
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) {
case *image.Paletted:
b := origImg.Bounds()
@ -63,7 +63,7 @@ func CopyImage(origImg image.Image) *image.RGBA {
index1 += d1
}
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()
return newImg
@ -93,11 +93,10 @@ func NewImage(width, height int, filter opengl.Filter) (*Image, error) {
return i, nil
}
func NewImageFromImage(img *image.RGBA, filter opengl.Filter) (*Image, error) {
s := img.Bounds().Size()
func NewImageFromImage(img *image.RGBA, width, height int, filter opengl.Filter) (*Image, error) {
i := &Image{
width: s.X,
height: s.Y,
width: width,
height: height,
}
c := &newImageFromImageCommand{
result: i,

View File

@ -62,14 +62,12 @@ func NewImage(width, height int, filter opengl.Filter, volatile bool) (*Image, e
}, nil
}
func NewImageFromImage(source *image.RGBA, filter opengl.Filter) (*Image, error) {
img, err := graphics.NewImageFromImage(source, filter)
func NewImageFromImage(source *image.RGBA, width, height int, filter opengl.Filter) (*Image, error) {
img, err := graphics.NewImageFromImage(source, width, height, filter)
if err != nil {
// TODO: texture should be removed here?
return nil, err
}
size := source.Bounds().Size()
width, height := size.X, size.Y
return &Image{
image: img,
width: width,
@ -172,11 +170,12 @@ func (p *Image) appendDrawImageHistory(image *graphics.Image, vertices []float32
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.
// 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 err := p.readPixelsFromVRAM(p.image, context); err != nil {
return color.RGBA{}, err
@ -260,13 +259,13 @@ func (p *Image) Restore(context *opengl.Context) error {
if p.stale {
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 {
for j := 0; j < p.height; j++ {
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 {
return err
}