mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
graphicsdriver/opengl: Use PBO when retrieving pixels
This commit is contained in:
parent
0366103b2e
commit
86a0c7aa82
@ -470,3 +470,11 @@ func (c *context) replacePixelsWithPBO(buffer buffer, t textureNative, width, he
|
|||||||
gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, nil)
|
gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, nil)
|
||||||
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, 0)
|
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) getBufferSubData(buffer buffer, width, height int) []byte {
|
||||||
|
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, uint32(buffer))
|
||||||
|
pixels := make([]byte, 4*width*height)
|
||||||
|
gl.GetBufferSubData(gl.PIXEL_UNPACK_BUFFER, 0, 4*width*height, gl.Ptr(pixels))
|
||||||
|
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, 0)
|
||||||
|
return pixels
|
||||||
|
}
|
||||||
|
@ -565,3 +565,12 @@ func (c *context) replacePixelsWithPBO(buffer buffer, t textureNative, width, he
|
|||||||
gl.Call("texSubImage2D", gles.TEXTURE_2D, 0, 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0)
|
gl.Call("texSubImage2D", gles.TEXTURE_2D, 0, 0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, 0)
|
||||||
gl.Call("bindBuffer", int(pixelUnpackBuffer), nil)
|
gl.Call("bindBuffer", int(pixelUnpackBuffer), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) getBufferSubData(buffer buffer, width, height int) []byte {
|
||||||
|
gl := c.gl
|
||||||
|
gl.Call("bindBuffer", int(pixelUnpackBuffer), buffer)
|
||||||
|
arr := jsutil.TemporaryUint8Array(4 * width * height)
|
||||||
|
gl.Call("getBufferSubData", int(pixelUnpackBuffer), 0, arr)
|
||||||
|
gl.Call("bindBuffer", int(pixelUnpackBuffer), 0)
|
||||||
|
return jsutil.Uint8ArrayToSlice(arr)
|
||||||
|
}
|
||||||
|
@ -436,3 +436,9 @@ func (c *context) replacePixelsWithPBO(buffer buffer, t textureNative, width, he
|
|||||||
c.ctx.TexSubImage2D(gles.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gles.RGBA, gles.UNSIGNED_BYTE, nil)
|
c.ctx.TexSubImage2D(gles.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gles.RGBA, gles.UNSIGNED_BYTE, nil)
|
||||||
c.ctx.BindBuffer(gles.PIXEL_UNPACK_BUFFER, 0)
|
c.ctx.BindBuffer(gles.PIXEL_UNPACK_BUFFER, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) getBufferSubData(buffer buffer, width, height int) []byte {
|
||||||
|
// gl.GetBufferSubData doesn't exist on OpenGL ES 2 and 3.
|
||||||
|
// As PBO is not used in mobiles, leave this unimplemented so far.
|
||||||
|
panic("opengl: getBufferSubData is not implemented for mobiles")
|
||||||
|
}
|
||||||
|
@ -122,6 +122,7 @@ package gl
|
|||||||
// typedef void (APIENTRYP GPGENBUFFERS)(GLsizei n, GLuint * buffers);
|
// typedef void (APIENTRYP GPGENBUFFERS)(GLsizei n, GLuint * buffers);
|
||||||
// typedef void (APIENTRYP GPGENFRAMEBUFFERSEXT)(GLsizei n, GLuint * framebuffers);
|
// typedef void (APIENTRYP GPGENFRAMEBUFFERSEXT)(GLsizei n, GLuint * framebuffers);
|
||||||
// typedef void (APIENTRYP GPGENTEXTURES)(GLsizei n, GLuint * textures);
|
// typedef void (APIENTRYP GPGENTEXTURES)(GLsizei n, GLuint * textures);
|
||||||
|
// typedef void (APIENTRYP GPGETBUFFERSUBDATA)(GLenum target, GLintptr offset, GLsizeiptr size, void * data);
|
||||||
// typedef void (APIENTRYP GPGETDOUBLEI_V)(GLenum target, GLuint index, GLdouble * data);
|
// typedef void (APIENTRYP GPGETDOUBLEI_V)(GLenum target, GLuint index, GLdouble * data);
|
||||||
// typedef void (APIENTRYP GPGETDOUBLEI_VEXT)(GLenum pname, GLuint index, GLdouble * params);
|
// typedef void (APIENTRYP GPGETDOUBLEI_VEXT)(GLenum pname, GLuint index, GLdouble * params);
|
||||||
// typedef GLenum (APIENTRYP GPGETERROR)();
|
// typedef GLenum (APIENTRYP GPGETERROR)();
|
||||||
@ -246,6 +247,9 @@ package gl
|
|||||||
// static void glowGenTextures(GPGENTEXTURES fnptr, GLsizei n, GLuint * textures) {
|
// static void glowGenTextures(GPGENTEXTURES fnptr, GLsizei n, GLuint * textures) {
|
||||||
// (*fnptr)(n, textures);
|
// (*fnptr)(n, textures);
|
||||||
// }
|
// }
|
||||||
|
// static void glowGetBufferSubData(GPGETBUFFERSUBDATA fnptr, GLenum target, GLintptr offset, GLsizeiptr size, void * data) {
|
||||||
|
// (*fnptr)(target, offset, size, data);
|
||||||
|
// }
|
||||||
// static void glowGetDoublei_v(GPGETDOUBLEI_V fnptr, GLenum target, GLuint index, GLdouble * data) {
|
// static void glowGetDoublei_v(GPGETDOUBLEI_V fnptr, GLenum target, GLuint index, GLdouble * data) {
|
||||||
// (*fnptr)(target, index, data);
|
// (*fnptr)(target, index, data);
|
||||||
// }
|
// }
|
||||||
@ -407,6 +411,7 @@ var (
|
|||||||
gpGenBuffers C.GPGENBUFFERS
|
gpGenBuffers C.GPGENBUFFERS
|
||||||
gpGenFramebuffersEXT C.GPGENFRAMEBUFFERSEXT
|
gpGenFramebuffersEXT C.GPGENFRAMEBUFFERSEXT
|
||||||
gpGenTextures C.GPGENTEXTURES
|
gpGenTextures C.GPGENTEXTURES
|
||||||
|
gpGetBufferSubData C.GPGETBUFFERSUBDATA
|
||||||
gpGetDoublei_v C.GPGETDOUBLEI_V
|
gpGetDoublei_v C.GPGETDOUBLEI_V
|
||||||
gpGetDoublei_vEXT C.GPGETDOUBLEI_VEXT
|
gpGetDoublei_vEXT C.GPGETDOUBLEI_VEXT
|
||||||
gpGetError C.GPGETERROR
|
gpGetError C.GPGETERROR
|
||||||
@ -569,6 +574,10 @@ func GenTextures(n int32, textures *uint32) {
|
|||||||
C.glowGenTextures(gpGenTextures, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(textures)))
|
C.glowGenTextures(gpGenTextures, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(textures)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetBufferSubData(target uint32, offset int, size int, data unsafe.Pointer) {
|
||||||
|
C.glowGetBufferSubData(gpGetBufferSubData, (C.GLenum)(target), (C.GLintptr)(offset), (C.GLsizeiptr)(size), data)
|
||||||
|
}
|
||||||
|
|
||||||
func GetDoublei_v(target uint32, index uint32, data *float64) {
|
func GetDoublei_v(target uint32, index uint32, data *float64) {
|
||||||
C.glowGetDoublei_v(gpGetDoublei_v, (C.GLenum)(target), (C.GLuint)(index), (*C.GLdouble)(unsafe.Pointer(data)))
|
C.glowGetDoublei_v(gpGetDoublei_v, (C.GLenum)(target), (C.GLuint)(index), (*C.GLdouble)(unsafe.Pointer(data)))
|
||||||
}
|
}
|
||||||
@ -832,6 +841,10 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
|||||||
if gpGenTextures == nil {
|
if gpGenTextures == nil {
|
||||||
return errors.New("glGenTextures")
|
return errors.New("glGenTextures")
|
||||||
}
|
}
|
||||||
|
gpGetBufferSubData = (C.GPGETBUFFERSUBDATA)(getProcAddr("glGetBufferSubData"))
|
||||||
|
if gpGetBufferSubData == nil {
|
||||||
|
return errors.New("glGetBufferSubData")
|
||||||
|
}
|
||||||
gpGetDoublei_v = (C.GPGETDOUBLEI_V)(getProcAddr("glGetDoublei_v"))
|
gpGetDoublei_v = (C.GPGETDOUBLEI_V)(getProcAddr("glGetDoublei_v"))
|
||||||
gpGetDoublei_vEXT = (C.GPGETDOUBLEI_VEXT)(getProcAddr("glGetDoublei_vEXT"))
|
gpGetDoublei_vEXT = (C.GPGETDOUBLEI_VEXT)(getProcAddr("glGetDoublei_vEXT"))
|
||||||
gpGetError = (C.GPGETERROR)(getProcAddr("glGetError"))
|
gpGetError = (C.GPGETERROR)(getProcAddr("glGetError"))
|
||||||
|
@ -37,6 +37,7 @@ var (
|
|||||||
gpGenBuffers uintptr
|
gpGenBuffers uintptr
|
||||||
gpGenFramebuffersEXT uintptr
|
gpGenFramebuffersEXT uintptr
|
||||||
gpGenTextures uintptr
|
gpGenTextures uintptr
|
||||||
|
gpGetBufferSubData uintptr
|
||||||
gpGetDoublei_v uintptr
|
gpGetDoublei_v uintptr
|
||||||
gpGetDoublei_vEXT uintptr
|
gpGetDoublei_vEXT uintptr
|
||||||
gpGetError uintptr
|
gpGetError uintptr
|
||||||
@ -199,6 +200,10 @@ func GenTextures(n int32, textures *uint32) {
|
|||||||
syscall.Syscall(gpGenTextures, 2, uintptr(n), uintptr(unsafe.Pointer(textures)), 0)
|
syscall.Syscall(gpGenTextures, 2, uintptr(n), uintptr(unsafe.Pointer(textures)), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetBufferSubData(target uint32, offset int, size int, data unsafe.Pointer) {
|
||||||
|
syscall.Syscall6(gpGetBufferSubData, 4, uintptr(target), uintptr(offset), uintptr(size), uintptr(data), 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func GetDoublei_v(target uint32, index uint32, data *float64) {
|
func GetDoublei_v(target uint32, index uint32, data *float64) {
|
||||||
syscall.Syscall(gpGetDoublei_v, 3, uintptr(target), uintptr(index), uintptr(unsafe.Pointer(data)))
|
syscall.Syscall(gpGetDoublei_v, 3, uintptr(target), uintptr(index), uintptr(unsafe.Pointer(data)))
|
||||||
}
|
}
|
||||||
@ -462,6 +467,10 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
|||||||
if gpGenTextures == 0 {
|
if gpGenTextures == 0 {
|
||||||
return errors.New("glGenTextures")
|
return errors.New("glGenTextures")
|
||||||
}
|
}
|
||||||
|
gpGetBufferSubData = getProcAddr("glGetBufferSubData")
|
||||||
|
if gpGetBufferSubData == 0 {
|
||||||
|
return errors.New("glGetBufferSubData")
|
||||||
|
}
|
||||||
gpGetDoublei_v = getProcAddr("glGetDoublei_v")
|
gpGetDoublei_v = getProcAddr("glGetDoublei_v")
|
||||||
gpGetDoublei_vEXT = getProcAddr("glGetDoublei_vEXT")
|
gpGetDoublei_vEXT = getProcAddr("glGetDoublei_vEXT")
|
||||||
gpGetError = getProcAddr("glGetError")
|
gpGetError = getProcAddr("glGetError")
|
||||||
|
@ -152,6 +152,11 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
|
|||||||
destination := g.images[dst]
|
destination := g.images[dst]
|
||||||
source := g.images[src]
|
source := g.images[src]
|
||||||
|
|
||||||
|
if !destination.pbo.equal(*new(buffer)) {
|
||||||
|
g.context.deleteBuffer(destination.pbo)
|
||||||
|
destination.pbo = *new(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
g.drawCalled = true
|
g.drawCalled = true
|
||||||
|
|
||||||
if err := destination.setViewport(); err != nil {
|
if err := destination.setViewport(); err != nil {
|
||||||
@ -294,6 +299,11 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
|||||||
d := g.images[dst]
|
d := g.images[dst]
|
||||||
s := g.shaders[shader]
|
s := g.shaders[shader]
|
||||||
|
|
||||||
|
if !d.pbo.equal(*new(buffer)) {
|
||||||
|
g.context.deleteBuffer(d.pbo)
|
||||||
|
d.pbo = *new(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
g.drawCalled = true
|
g.drawCalled = true
|
||||||
|
|
||||||
if err := d.setViewport(); err != nil {
|
if err := d.setViewport(); err != nil {
|
||||||
|
@ -71,7 +71,16 @@ func (i *Image) Pixels() ([]byte, error) {
|
|||||||
if err := i.ensureFramebuffer(); err != nil {
|
if err := i.ensureFramebuffer(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p := i.graphics.context.framebufferPixels(i.framebuffer, i.width, i.height)
|
|
||||||
|
// PBO is created only when PBO is enabled AND ReplacePixels is called.
|
||||||
|
// If PBO is enabled but the buffer doesn't exist, this means either ReplacePixels is not called or
|
||||||
|
// different draw calls than ReplacePixels were called.
|
||||||
|
if !i.graphics.context.canUsePBO() || i.pbo.equal(*new(buffer)) {
|
||||||
|
p := i.graphics.context.framebufferPixels(i.framebuffer, i.width, i.height)
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := i.graphics.context.getBufferSubData(i.pbo, i.width, i.height)
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,12 +132,12 @@ func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
|||||||
i.graphics.context.texSubImage2D(i.textureNative, w, h, args)
|
i.graphics.context.texSubImage2D(i.textureNative, w, h, args)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.pbo.equal(*new(buffer)) {
|
if i.pbo.equal(*new(buffer)) {
|
||||||
i.pbo = i.graphics.context.newPixelBufferObject(w, h)
|
i.pbo = i.graphics.context.newPixelBufferObject(w, h)
|
||||||
}
|
}
|
||||||
if i.pbo.equal(*new(buffer)) {
|
if i.pbo.equal(*new(buffer)) {
|
||||||
panic("opengl: newPixelBufferObject failed")
|
panic("opengl: newPixelBufferObject failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
i.graphics.context.replacePixelsWithPBO(i.pbo, i.textureNative, w, h, args)
|
i.graphics.context.replacePixelsWithPBO(i.pbo, i.textureNative, w, h, args)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user