mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
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:
parent
8243c1838a
commit
52f6be2639
@ -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
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user