internal/graphicsdriver: replace Pixels with ReadPixels

Now preparing a byte slice is the caller's responsibility.
This commit is contained in:
Hajime Hoshi 2022-02-27 17:41:19 +09:00
parent 1cb7633ff6
commit b22309a0e5
9 changed files with 33 additions and 35 deletions

View File

@ -605,11 +605,9 @@ type pixelsCommand struct {
// Exec executes a pixelsCommand.
func (c *pixelsCommand) Exec(indexOffset int) error {
p, err := c.img.image.Pixels()
if err != nil {
if err := c.img.image.ReadPixels(c.result); err != nil {
return err
}
c.result = p
return nil
}

View File

@ -165,18 +165,19 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, clr, mode, filter, address, dstRegion, srcRegion, shader, uniforms, evenOdd)
}
// Pixels returns the image's pixels.
// Pixels might return nil when OpenGL error happens.
func (i *Image) Pixels() ([]byte, error) {
// ReadPixels reads the image's pixels.
// ReadPixels returns an error when an error happens in the graphics driver.
func (i *Image) ReadPixels(buf []byte) error {
i.resolveBufferedReplacePixels()
c := &pixelsCommand{
img: i,
result: buf,
}
theCommandQueue.Enqueue(c)
if err := theCommandQueue.Flush(); err != nil {
return nil, err
return err
}
return c.result, nil
return nil
}
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
@ -222,8 +223,9 @@ func (i *Image) Dump(path string, blackbg bool, rect image.Rectangle) error {
}
defer f.Close()
pix, err := i.Pixels()
if err != nil {
w, h := i.InternalSize()
pix := make([]byte, 4*w*h)
if err := i.ReadPixels(pix); err != nil {
return err
}

View File

@ -80,7 +80,7 @@ type Image interface {
ID() ImageID
Dispose()
IsInvalidated() bool
Pixels() ([]byte, error)
ReadPixels(buf []byte) error
ReplacePixels(args []*ReplacePixelsArgs)
}

View File

@ -1186,15 +1186,18 @@ func (i *Image) syncTexture() {
cb.WaitUntilCompleted()
}
func (i *Image) Pixels() ([]byte, error) {
func (i *Image) ReadPixels(buf []byte) error {
if got, want := len(buf), 4*i.width*i.height; got != want {
return fmt.Errorf("metal: len(buf) must be %d but %d at ReadPixels", want, got)
}
i.graphics.flushIfNeeded(false)
i.syncTexture()
b := make([]byte, 4*i.width*i.height)
i.texture.GetBytes(&b[0], uintptr(4*i.width), mtl.Region{
i.texture.GetBytes(&buf[0], uintptr(4*i.width), mtl.Region{
Size: mtl.Size{Width: i.width, Height: i.height, Depth: 1},
}, 0)
return b, nil
return nil
}
func (i *Image) ReplacePixels(args []*graphicsdriver.ReplacePixelsArgs) {

View File

@ -162,12 +162,10 @@ func (c *context) bindFramebufferImpl(f framebufferNative) {
gl.BindFramebufferEXT(gl.FRAMEBUFFER, uint32(f))
}
func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte {
func (c *context) framebufferPixels(buf []byte, f *framebuffer, width, height int) {
gl.Flush()
c.bindFramebuffer(f.native)
pixels := make([]byte, 4*width*height)
gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels))
return pixels
gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(buf))
}
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {

View File

@ -236,7 +236,7 @@ func (c *context) bindFramebufferImpl(f framebufferNative) {
gl.bindFramebuffer.Invoke(gles.FRAMEBUFFER, js.Value(f))
}
func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte {
func (c *context) framebufferPixels(buf []byte, f *framebuffer, width, height int) {
gl := c.gl
c.bindFramebuffer(f.native)
@ -244,8 +244,7 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte {
l := 4 * width * height
p := jsutil.TemporaryUint8ArrayFromUint8Slice(l, nil)
gl.readPixels.Invoke(0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, p)
return uint8ArrayToSlice(p, l)
copy(buf, uint8ArrayToSlice(p, l))
}
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {

View File

@ -148,14 +148,12 @@ func (c *context) bindFramebufferImpl(f framebufferNative) {
c.ctx.BindFramebuffer(gles.FRAMEBUFFER, uint32(f))
}
func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte {
func (c *context) framebufferPixels(buf []byte, f *framebuffer, width, height int) {
c.ctx.Flush()
c.bindFramebuffer(f.native)
pixels := make([]byte, 4*width*height)
c.ctx.ReadPixels(pixels, 0, 0, int32(width), int32(height), gles.RGBA, gles.UNSIGNED_BYTE)
return pixels
c.ctx.ReadPixels(buf, 0, 0, int32(width), int32(height), gles.RGBA, gles.UNSIGNED_BYTE)
}
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {

View File

@ -60,13 +60,13 @@ func (i *Image) setViewport() error {
return nil
}
func (i *Image) Pixels() ([]byte, error) {
func (i *Image) ReadPixels(buf []byte) error {
if err := i.ensureFramebuffer(); err != nil {
return nil, err
return err
}
p := i.graphics.context.framebufferPixels(i.framebuffer, i.width, i.height)
return p, nil
i.graphics.context.framebufferPixels(buf, i.framebuffer, i.width, i.height)
return nil
}
func (i *Image) framebufferSize() (int, int) {

View File

@ -497,8 +497,8 @@ func (i *Image) makeStaleIfDependingOnShader(shader *Shader) {
// readPixelsFromGPU reads the pixels from GPU and resolves the image's 'stale' state.
func (i *Image) readPixelsFromGPU() error {
pix, err := i.image.Pixels()
if err != nil {
pix := make([]byte, 4*i.width*i.height)
if err := i.image.ReadPixels(pix); err != nil {
return err
}
i.basePixels = Pixels{}
@ -626,8 +626,8 @@ func (i *Image) restore() error {
if len(i.drawTrianglesHistory) > 0 {
i.basePixels = Pixels{}
pix, err := gimg.Pixels()
if err != nil {
pix := make([]byte, 4*w*h)
if err := gimg.ReadPixels(pix); err != nil {
return err
}
i.basePixels.AddOrReplace(pix, 0, 0, w, h)