Bug 715232: Don't attempt to CopyTexImage from an RGB framebuffer to an RGBA texture. r=joedrew

This commit is contained in:
Chris Jones 2012-01-25 18:05:34 -08:00
Родитель a7cc927633
Коммит c8932ced3b
8 изменённых файлов: 96 добавлений и 6 удалений

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

@ -214,6 +214,7 @@ ContainerRender(Container* aContainer,
framebufferRect -= childOffset;
aManager->CreateFBOWithTexture(framebufferRect,
mode,
aPreviousFrameBuffer,
&frameBuffer,
&containerSurface);
childOffset.x = visibleRect.x;

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

@ -1132,8 +1132,33 @@ LayerManagerOGL::SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix)
} FOR_EACH_LAYER_PROGRAM_END
}
static GLenum
GetFrameBufferInternalFormat(GLContext* gl,
GLuint aCurrentFrameBuffer,
nsIWidget* aWidget)
{
if (aCurrentFrameBuffer == 0) { // default framebuffer
return aWidget->GetGLFrameBufferFormat();
}
return LOCAL_GL_RGBA;
}
static bool
AreFormatsCompatibleForCopyTexImage2D(GLenum aF1, GLenum aF2)
{
// GL requires that the implementation has to handle copies between
// different formats, so all are "compatible". GLES does not
// require that.
#ifdef USE_GLES2
return (aF1 == aF2);
#else
return true;
#endif
}
void
LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
GLuint aCurrentFrameBuffer,
GLuint *aFBO, GLuint *aTexture)
{
GLuint tex, fbo;
@ -1142,12 +1167,40 @@ LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
mGLContext->fGenTextures(1, &tex);
mGLContext->fBindTexture(mFBOTextureTarget, tex);
if (aInit == InitModeCopy) {
mGLContext->fCopyTexImage2D(mFBOTextureTarget,
0,
LOCAL_GL_RGBA,
aRect.x, aRect.y,
aRect.width, aRect.height,
0);
// We're going to create an RGBA temporary fbo. But to
// CopyTexImage() from the current framebuffer, the framebuffer's
// format has to be compatible with the new texture's. So we
// check the format of the framebuffer here and take a slow path
// if it's incompatible.
GLenum format =
GetFrameBufferInternalFormat(gl(), aCurrentFrameBuffer, mWidget);
if (AreFormatsCompatibleForCopyTexImage2D(format, LOCAL_GL_RGBA)) {
mGLContext->fCopyTexImage2D(mFBOTextureTarget,
0,
LOCAL_GL_RGBA,
aRect.x, aRect.y,
aRect.width, aRect.height,
0);
} else {
// Curses, incompatible formats. Take a slow path.
//
// XXX Technically CopyTexSubImage2D also has the requirement of
// matching formats, but it doesn't seem to affect us in the
// real world.
mGLContext->fTexImage2D(mFBOTextureTarget,
0,
LOCAL_GL_RGBA,
aRect.width, aRect.height,
0,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
NULL);
mGLContext->fCopyTexSubImage2D(mFBOTextureTarget,
0, // level
0, 0, // offset
aRect.x, aRect.y,
aRect.width, aRect.height);
}
} else {
mGLContext->fTexImage2D(mFBOTextureTarget,
0,

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

@ -308,6 +308,7 @@ public:
* texture types.
*/
void CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
GLuint aCurrentFrameBuffer,
GLuint *aFBO, GLuint *aTexture);
GLuint QuadVBO() { return mQuadVBO; }

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

@ -449,3 +449,15 @@ nsWindow::UserActivity()
mIdleService->ResetIdleTimeOut();
}
}
PRUint32
nsWindow::GetGLFrameBufferFormat()
{
if (mLayerManager &&
mLayerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
// We directly map the hardware fb on Gonk. The hardware fb
// has RGB format.
return LOCAL_GL_RGB;
}
return LOCAL_GL_NONE;
}

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

@ -126,6 +126,8 @@ public:
const InputContextAction& aAction);
NS_IMETHOD_(InputContext) GetInputContext();
virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE;
protected:
nsWindow* mParent;
bool mVisible;

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

@ -1510,6 +1510,12 @@ class nsIWidget : public nsISupports {
* parent widget
*/
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0;
/**
* Return the internal format of the default framebuffer for this
* widget.
*/
virtual PRUint32 GetGLFrameBufferFormat() { return 0; /*GL_NONE*/ }
protected:
// keep the list of children. We also keep track of our siblings.

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

@ -1259,6 +1259,18 @@ nsBaseWidget::BeginMoveDrag(nsMouseEvent* aEvent)
return NS_ERROR_NOT_IMPLEMENTED;
}
PRUint32
nsBaseWidget::GetGLFrameBufferFormat()
{
if (mLayerManager &&
mLayerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
// Assume that the default framebuffer has RGBA format. Specific
// backends that know differently will override this method.
return LOCAL_GL_RGBA;
}
return LOCAL_GL_NONE;
}
#ifdef DEBUG
//////////////////////////////////////////////////////////////
//

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

@ -201,6 +201,9 @@ public:
}
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0;
virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE;
/**
* Use this when GetLayerManager() returns a BasicLayerManager
* (nsBaseWidget::GetLayerManager() does). This sets up the widget's