graphicsdriver/opengl: Fix suspicious GL function calls

Before this change, the pixel object buffer is unbound just after
getting a pointer by glMapBuffer. This seemed suspicious.

This change fixes to do all pixel manipulations once between
glMapBuffer and glUnmapBuffer without changing a bound buffer.

This might fix a wrong rendering on some machines, but I am not
sure.

Updates #993
This commit is contained in:
Hajime Hoshi 2019-11-20 02:41:31 +09:00
parent 8243c1838a
commit 52f6be2639
5 changed files with 50 additions and 29 deletions

View File

@ -530,7 +530,6 @@ func (c *context) mapPixelBuffer(buffer buffer) unsafe.Pointer {
_ = c.t.Call(func() error {
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, uint32(buffer))
ptr = gl.MapBuffer(gl.PIXEL_UNPACK_BUFFER, gl.WRITE_ONLY)
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, 0)
return nil
})
return ptr
@ -538,7 +537,6 @@ func (c *context) mapPixelBuffer(buffer buffer) unsafe.Pointer {
func (c *context) unmapPixelBuffer(buffer buffer, t textureNative, width, height int) {
_ = c.t.Call(func() error {
gl.BindBuffer(gl.PIXEL_UNPACK_BUFFER, uint32(buffer))
gl.UnmapBuffer(gl.PIXEL_UNPACK_BUFFER)
return nil
})

View File

@ -18,6 +18,14 @@ import (
"github.com/hajimehoshi/ebiten/internal/graphics"
)
type bufferedRP struct {
pixels []byte
x int
y int
width int
height int
}
type Image struct {
driver *Driver
textureNative textureNative
@ -26,6 +34,8 @@ type Image struct {
width int
height int
screen bool
bufferedRPs []bufferedRP
}
func (i *Image) IsInvalidated() bool {
@ -33,7 +43,6 @@ func (i *Image) IsInvalidated() bool {
}
func (i *Image) Dispose() {
thePBOState.ensurePBOUnmapped()
if i.pbo != *new(buffer) {
i.driver.context.deleteBuffer(i.pbo)
}
@ -46,6 +55,7 @@ func (i *Image) Dispose() {
}
func (i *Image) SetAsDestination() {
i.resolveReplacePixels()
i.driver.state.destination = i
}
@ -58,7 +68,7 @@ func (i *Image) setViewport() error {
}
func (i *Image) Pixels() ([]byte, error) {
thePBOState.ensurePBOUnmapped()
i.resolveReplacePixels()
if err := i.ensureFramebuffer(); err != nil {
return nil, err
}
@ -96,6 +106,29 @@ func (i *Image) ReplacePixels(p []byte, x, y, width, height int) {
panic("opengl: ReplacePixels cannot be called on the screen, that doesn't have a texture")
}
i.bufferedRPs = append(i.bufferedRPs, bufferedRP{
pixels: p,
x: x,
y: y,
width: width,
height: height,
})
}
func (i *Image) SetAsSource() {
i.resolveReplacePixels()
i.driver.state.source = i
}
func (i *Image) resolveReplacePixels() {
if len(i.bufferedRPs) == 0 {
return
}
defer func() {
i.bufferedRPs = nil
}()
// glFlush is necessary on Android.
// glTexSubImage2D didn't work without this hack at least on Nexus 5x and NuAns NEO [Reloaded] (#211).
if i.driver.drawCalled {
@ -103,14 +136,16 @@ func (i *Image) ReplacePixels(p []byte, x, y, width, height int) {
}
i.driver.drawCalled = false
if canUsePBO {
thePBOState.mapPBOIfNecessary(i)
thePBOState.draw(p, x, y, width, height)
} else {
i.driver.context.texSubImage2D(i.textureNative, p, x, y, width, height)
if !canUsePBO {
for _, rp := range i.bufferedRPs {
i.driver.context.texSubImage2D(i.textureNative, rp.pixels, rp.x, rp.y, rp.width, rp.height)
}
return
}
func (i *Image) SetAsSource() {
i.driver.state.source = i
thePBOState.mapPBO(i)
for _, rp := range i.bufferedRPs {
thePBOState.draw(rp.pixels, rp.x, rp.y, rp.width, rp.height)
}
thePBOState.unmapPBO()
}

View File

@ -36,13 +36,7 @@ type pboState struct {
var thePBOState pboState
func (s *pboState) mapPBOIfNecessary(img *Image) {
if s.image == img {
return
}
s.ensurePBOUnmapped()
func (s *pboState) mapPBO(img *Image) {
if img.pbo == *new(buffer) {
w, h := graphics.InternalImageSize(img.width), graphics.InternalImageSize(img.height)
img.pbo = img.driver.context.newPixelBufferObject(w, h)
@ -73,11 +67,7 @@ func (s *pboState) draw(pix []byte, x, y, width, height int) {
runtime.KeepAlive(mapped)
}
func (s *pboState) ensurePBOUnmapped() {
if s.mappedPBO == nil {
return
}
func (s *pboState) unmapPBO() {
i := s.image
w, h := graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
i.driver.context.unmapPixelBuffer(i.pbo, i.textureNative, w, h)

View File

@ -22,7 +22,7 @@ type pboState struct{}
var thePBOState pboState
func (s *pboState) mapPBOIfNecessary(img *Image) {
func (s *pboState) mapPBO(img *Image) {
panic("opengl: PBO is not available in this environment")
}
@ -30,6 +30,6 @@ func (s *pboState) draw(pix []byte, x, y, width, height int) {
panic("opengl: PBO is not available in this environment")
}
func (s *pboState) ensurePBOUnmapped() {
// Do nothing
func (s *pboState) unmapPBO() {
panic("opengl: PBO is not available in this environment")
}

View File

@ -265,8 +265,6 @@ func (d *Driver) useProgram(mode driver.CompositeMode, colorM *affine.ColorM, fi
panic("source image is not set")
}
thePBOState.ensurePBOUnmapped()
if err := destination.setViewport(); err != nil {
return err
}