Bug 1586627 - Work around a bug in AppleIntelHD3000GraphicsGLDriver in CompositorOGL. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D49050

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Markus Stange 2019-10-15 02:14:50 +00:00
Родитель 3fc5360b6e
Коммит d76e9ba35f
1 изменённых файлов: 63 добавлений и 0 удалений

Просмотреть файл

@ -1056,6 +1056,67 @@ void CompositorOGL::CreateFBOWithTexture(const gfx::IntRect& aRect,
mGLContext->fGenFramebuffers(1, aFBO);
}
// Should be called after calls to fReadPixels or fCopyTexImage2D, and other
// GL read calls.
static void WorkAroundAppleIntelHD3000GraphicsGLDriverBug(GLContext* aGL) {
#ifdef XP_MACOSX
if (aGL->WorkAroundDriverBugs() &&
aGL->Renderer() == GLRenderer::IntelHD3000) {
// Work around a bug in the Apple Intel HD Graphics 3000 driver (bug
// 1586627, filed with Apple as FB7379358). This bug has been found present
// on 10.9.3 and on 10.13.6, so it likely affects all shipped versions of
// this driver. (macOS 10.14 does not support this GPU.)
// The bug manifests as follows: Reading from a framebuffer puts that
// framebuffer into a state such that deleting that framebuffer can break
// other framebuffers in certain cases. More specifically, if you have two
// framebuffers A and B, the following sequence of events breaks subsequent
// drawing to B:
// 1. A becomes "most recently read-from framebuffer".
// 2. B is drawn to.
// 3. A is deleted, and other GL state (such as GL_SCISSOR enabled state)
// is touched.
// 4. B is drawn to again.
// Now all draws to framebuffer B, including the draw from step 4, will
// render at the wrong position and upside down.
//
// When AfterGLReadCall() is called, the currently bound framebuffer is the
// framebuffer that has been read from most recently. So in the presence of
// this bug, deleting this framebuffer has now become dangerous. We work
// around the bug by creating a new short-lived framebuffer, making that new
// framebuffer the most recently read-from framebuffer (using
// glCopyTexImage2D), and then deleting it under controlled circumstances.
// This deletion is not affected by the bug because our deletion call is not
// interleaved with draw calls to another framebuffer and a touching of the
// GL scissor enabled state.
ScopedTexture texForReading(aGL);
{
// Initialize a 1x1 texture.
ScopedBindTexture autoBindTexForReading(aGL, texForReading);
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 1, 1, 0,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_LINEAR);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_LINEAR);
}
// Make a framebuffer around the texture.
ScopedFramebufferForTexture autoFBForReading(aGL, texForReading);
if (autoFBForReading.IsComplete()) {
// "Read" from the framebuffer, by initializing a new texture using
// glCopyTexImage2D. This flips the bad bit on autoFBForReading.FB().
ScopedBindFramebuffer autoFB(aGL, autoFBForReading.FB());
ScopedTexture texReadingDest(aGL);
ScopedBindTexture autoBindTexReadingDest(aGL, texReadingDest);
aGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 0, 0, 1, 1,
0);
}
// When autoFBForReading goes out of scope, the "poisoned" framebuffer is
// deleted, and the bad state seems to go away along with it.
}
#endif
}
GLuint CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
GLuint aSourceFrameBuffer,
IntSize* aAllocSize) {
@ -1100,6 +1161,7 @@ GLuint CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
mGLContext->fCopyTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
clampedRect.X(), FlipY(clampedRect.YMost()),
clampedRectWidth, clampedRectHeight, 0);
WorkAroundAppleIntelHD3000GraphicsGLDriverBug(mGLContext);
} else {
// Curses, incompatible formats. Take a slow path.
@ -1110,6 +1172,7 @@ GLuint CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
mGLContext->fReadPixels(clampedRect.X(), clampedRect.Y(),
clampedRectWidth, clampedRectHeight,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
WorkAroundAppleIntelHD3000GraphicsGLDriverBug(mGLContext);
mGLContext->fTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
clampedRectWidth, clampedRectHeight, 0,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());