зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
3fc5360b6e
Коммит
d76e9ba35f
|
@ -1056,6 +1056,67 @@ void CompositorOGL::CreateFBOWithTexture(const gfx::IntRect& aRect,
|
||||||
mGLContext->fGenFramebuffers(1, aFBO);
|
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 CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
|
||||||
GLuint aSourceFrameBuffer,
|
GLuint aSourceFrameBuffer,
|
||||||
IntSize* aAllocSize) {
|
IntSize* aAllocSize) {
|
||||||
|
@ -1100,6 +1161,7 @@ GLuint CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
|
||||||
mGLContext->fCopyTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
|
mGLContext->fCopyTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
|
||||||
clampedRect.X(), FlipY(clampedRect.YMost()),
|
clampedRect.X(), FlipY(clampedRect.YMost()),
|
||||||
clampedRectWidth, clampedRectHeight, 0);
|
clampedRectWidth, clampedRectHeight, 0);
|
||||||
|
WorkAroundAppleIntelHD3000GraphicsGLDriverBug(mGLContext);
|
||||||
} else {
|
} else {
|
||||||
// Curses, incompatible formats. Take a slow path.
|
// 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(),
|
mGLContext->fReadPixels(clampedRect.X(), clampedRect.Y(),
|
||||||
clampedRectWidth, clampedRectHeight,
|
clampedRectWidth, clampedRectHeight,
|
||||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
|
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
|
||||||
|
WorkAroundAppleIntelHD3000GraphicsGLDriverBug(mGLContext);
|
||||||
mGLContext->fTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
|
mGLContext->fTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
|
||||||
clampedRectWidth, clampedRectHeight, 0,
|
clampedRectWidth, clampedRectHeight, 0,
|
||||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
|
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
|
||||||
|
|
Загрузка…
Ссылка в новой задаче