зеркало из https://github.com/mozilla/gecko-dev.git
b=575469; use CreateOffscreen in layers; r=bas
This commit is contained in:
Родитель
e71cc8f81f
Коммит
27b296ce6e
|
@ -522,6 +522,7 @@ protected:
|
|||
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
nsRefPtr<mozilla::gl::GLContext> mGLContext;
|
||||
PRUint32 mCanvasFramebuffer;
|
||||
|
||||
nsIntRect mBounds;
|
||||
nsIntRect mUpdatedRect;
|
||||
|
@ -543,8 +544,10 @@ BasicCanvasLayer::Initialize(const Data& aData)
|
|||
"CanvasLayer can't have both surface and GLContext");
|
||||
mNeedsYFlip = PR_FALSE;
|
||||
} else if (aData.mGLContext) {
|
||||
NS_ASSERTION(aData.mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
|
||||
mGLContext = aData.mGLContext;
|
||||
mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
|
||||
mCanvasFramebuffer = mGLContext->GetOffscreenFBO();
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
} else {
|
||||
NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
|
||||
|
@ -580,6 +583,15 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
|||
// in the framebuffer before we read.
|
||||
mGLContext->fFlush();
|
||||
|
||||
PRUint32 currentFramebuffer = 0;
|
||||
|
||||
mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)¤tFramebuffer);
|
||||
|
||||
// Make sure that we read pixels from the correct framebuffer, regardless
|
||||
// of what's currently bound.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer);
|
||||
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use mUpdatedRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
|
@ -593,6 +605,10 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
|||
isurf->Data());
|
||||
#endif
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer);
|
||||
|
||||
// If the underlying GLContext doesn't have a framebuffer into which
|
||||
// premultiplied values were written, we have to do this ourselves here.
|
||||
// Note that this is a WebGL attribute; GL itself has no knowledge of
|
||||
|
|
|
@ -59,7 +59,9 @@ CanvasLayerD3D9::Initialize(const Data& aData)
|
|||
"CanvasLayer can't have both surface and GLContext");
|
||||
mNeedsYFlip = PR_FALSE;
|
||||
} else if (aData.mGLContext) {
|
||||
NS_ASSERTION(aData.mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
|
||||
mGLContext = aData.mGLContext;
|
||||
mCanvasFramebuffer = mGLContext->GetOffscreenFBO();
|
||||
mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
} else {
|
||||
|
@ -97,6 +99,15 @@ CanvasLayerD3D9::Updated(const nsIntRect& aRect)
|
|||
// in the framebuffer before we read.
|
||||
mGLContext->fFlush();
|
||||
|
||||
PRUint32 currentFramebuffer = 0;
|
||||
|
||||
mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)¤tFramebuffer);
|
||||
|
||||
// Make sure that we read pixels from the correct framebuffer, regardless
|
||||
// of what's currently bound.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer);
|
||||
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use aRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
|
@ -104,6 +115,10 @@ CanvasLayerD3D9::Updated(const nsIntRect& aRect)
|
|||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
destination);
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer);
|
||||
|
||||
if (r.Pitch != mBounds.width * 4) {
|
||||
for (int y = 0; y < mBounds.height; y++) {
|
||||
memcpy((PRUint8*)r.pBits + r.Pitch * y,
|
||||
|
@ -222,4 +237,4 @@ CanvasLayerD3D9::RenderLayer()
|
|||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -76,6 +76,9 @@ protected:
|
|||
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
PRUint32 mCanvasFramebuffer;
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> mTexture;
|
||||
|
||||
nsIntRect mBounds;
|
||||
|
|
|
@ -68,23 +68,25 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
|||
{
|
||||
NS_ASSERTION(mCanvasSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
|
||||
|
||||
if (aData.mGLContext != nsnull &&
|
||||
aData.mSurface != nsnull)
|
||||
{
|
||||
NS_WARNING("CanvasLayerOGL can't have both surface and GLContext");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aData.mSurface) {
|
||||
mCanvasSurface = aData.mSurface;
|
||||
NS_ASSERTION(aData.mGLContext == nsnull,
|
||||
"CanvasLayerOGL can't have both surface and GLContext");
|
||||
mNeedsYFlip = PR_FALSE;
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeXlib)
|
||||
mCanvasSurfaceAsGLContext = GLContextProvider::CreateForNativePixmapSurface(mCanvasSurface);
|
||||
} else if (aData.mGLContext) {
|
||||
// this must be a pbuffer context
|
||||
void *pbuffer = aData.mGLContext->GetNativeData(GLContext::NativePBuffer);
|
||||
if (!pbuffer) {
|
||||
NS_WARNING("CanvasLayerOGL with GL context without NativePBuffer");
|
||||
if (!aData.mGLContext->IsOffscreen()) {
|
||||
NS_WARNING("CanvasLayerOGL with a non-offscreen GL context given");
|
||||
return;
|
||||
}
|
||||
|
||||
mCanvasGLContext = aData.mGLContext;
|
||||
mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
|
||||
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
} else {
|
||||
NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!");
|
||||
|
@ -94,6 +96,23 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
|||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerOGL::MakeTexture()
|
||||
{
|
||||
if (mTexture != 0)
|
||||
return;
|
||||
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
{
|
||||
|
@ -104,38 +123,16 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
|
||||
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
|
||||
|
||||
if (mCanvasSurfaceAsGLContext) {
|
||||
PRBool newTexture = mTexture == 0;
|
||||
if (newTexture) {
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
mUpdatedRect = mBounds;
|
||||
} else {
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
if (mCanvasGLContext) {
|
||||
if (gl()->BindOffscreenNeedsTexture(mCanvasGLContext) &&
|
||||
mTexture == 0)
|
||||
{
|
||||
MakeTexture();
|
||||
}
|
||||
mCanvasSurfaceAsGLContext->BindTexImage();
|
||||
} else if (mCanvasSurface) {
|
||||
PRBool newTexture = mTexture == 0;
|
||||
if (newTexture) {
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
MakeTexture();
|
||||
mUpdatedRect = mBounds;
|
||||
} else {
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
@ -200,42 +197,6 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
updatedAreaImageSurface->Data());
|
||||
}
|
||||
} else if (mCanvasGLContext) {
|
||||
// we just need to create a texture that we'll use, the first time through
|
||||
PRBool newTexture = mTexture == 0;
|
||||
if (newTexture) {
|
||||
gl()->fGenTextures(1, (GLuint*)&mTexture);
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
mUpdatedRect = mBounds;
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// We only need to do this for the first time we set up the texture
|
||||
if (newTexture) {
|
||||
CGLError err;
|
||||
err = CGLTexImagePBuffer((CGLContextObj) gl()->GetNativeData(GLContext::NativeCGLContext),
|
||||
(CGLPBufferObj) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_GL_BACK);
|
||||
if (err) {
|
||||
NS_WARNING("CanvasLayerOGL::Updated CGLTexImagePBuffer failed");
|
||||
}
|
||||
}
|
||||
#elif defined(XP_WIN)
|
||||
// We need to do this every time before we paint
|
||||
if (!sWGLLibrary.fBindTexImage((HANDLE) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_WGL_FRONT_LEFT_ARB)) {
|
||||
NS_WARNING("CanvasLayerOGL::Updated wglBindTexImageARB failed");
|
||||
}
|
||||
#else
|
||||
NS_WARNING("CanvasLayerOGL::Updated with GL context, but I don't know how to render on this platform!");
|
||||
#endif
|
||||
}
|
||||
|
||||
// sanity
|
||||
|
@ -256,9 +217,17 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
ColorTextureLayerProgram *program = nsnull;
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mCanvasGLContext || mCanvasSurfaceAsGLContext) {
|
||||
if (mTexture) {
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
gl()->BindTex2DOffscreen(mCanvasGLContext);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
program = mOGLManager->GetRGBALayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
|
@ -273,14 +242,11 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
|
||||
mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// We need to do this ever time after we paint, before anyone
|
||||
// draws into the pbuffer again
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
sWGLLibrary.fReleaseTexImage((HANDLE) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_WGL_FRONT_LEFT_ARB);
|
||||
gl()->UnbindTex2DOffscreen(mCanvasGLContext);
|
||||
}
|
||||
#endif
|
||||
|
||||
mUpdatedRect.Empty();
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ protected:
|
|||
nsRefPtr<gfxASurface> mCanvasSurface;
|
||||
nsRefPtr<GLContext> mCanvasGLContext;
|
||||
|
||||
void MakeTexture();
|
||||
GLuint mTexture;
|
||||
|
||||
nsIntRect mBounds;
|
||||
|
@ -79,7 +80,6 @@ protected:
|
|||
|
||||
PRPackedBool mGLBufferIsPremultiplied;
|
||||
PRPackedBool mNeedsYFlip;
|
||||
nsRefPtr<GLContext> mCanvasSurfaceAsGLContext;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -440,7 +440,8 @@ LayerManagerOGL::Render()
|
|||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
// Render our layers.
|
||||
RootLayer()->RenderLayer(mBackBufferFBO, nsIntPoint(0, 0));
|
||||
RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
|
||||
nsIntPoint(0, 0));
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
|
@ -449,6 +450,11 @@ LayerManagerOGL::Render()
|
|||
return;
|
||||
}
|
||||
|
||||
if (mGLContext->IsDoubleBuffered()) {
|
||||
mGLContext->SwapBuffers();
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
||||
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
@ -529,13 +535,7 @@ LayerManagerOGL::Render()
|
|||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
// XXX this is an intermediate workaround for windows that are
|
||||
// double-buffered by default on GLX systems. The swap is a no-op
|
||||
// everywhere else (and for non-double-buffered GLX windows). If
|
||||
// the swap is actually performed, it implicitly glFlush()s.
|
||||
if (!mGLContext->SwapBuffers()) {
|
||||
mGLContext->fFlush();
|
||||
}
|
||||
mGLContext->fFlush();
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
}
|
||||
|
@ -549,10 +549,20 @@ LayerManagerOGL::SetupPipeline(int aWidth, int aHeight)
|
|||
// Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
|
||||
// <1.0, -1.0> bottomright)
|
||||
gfx3DMatrix viewMatrix;
|
||||
viewMatrix._11 = 2.0f / float(aWidth);
|
||||
viewMatrix._22 = 2.0f / float(aHeight);
|
||||
viewMatrix._41 = -1.0f;
|
||||
viewMatrix._42 = -1.0f;
|
||||
if (mGLContext->IsDoubleBuffered()) {
|
||||
/* If it's double buffered, we don't have a frontbuffer FBO,
|
||||
* so put in a Y-flip in this transform.
|
||||
*/
|
||||
viewMatrix._11 = 2.0f / float(aWidth);
|
||||
viewMatrix._22 = -2.0f / float(aHeight);
|
||||
viewMatrix._41 = -1.0f;
|
||||
viewMatrix._42 = 1.0f;
|
||||
} else {
|
||||
viewMatrix._11 = 2.0f / float(aWidth);
|
||||
viewMatrix._22 = 2.0f / float(aHeight);
|
||||
viewMatrix._41 = -1.0f;
|
||||
viewMatrix._42 = -1.0f;
|
||||
}
|
||||
|
||||
SetLayerProgramProjectionMatrix(viewMatrix);
|
||||
}
|
||||
|
@ -560,6 +570,10 @@ LayerManagerOGL::SetupPipeline(int aWidth, int aHeight)
|
|||
void
|
||||
LayerManagerOGL::SetupBackBuffer(int aWidth, int aHeight)
|
||||
{
|
||||
if (mGLContext->IsDoubleBuffered()) {
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
// Do we have a FBO of the right size already?
|
||||
if (mBackBufferSize.width == aWidth &&
|
||||
mBackBufferSize.height == aHeight)
|
||||
|
@ -612,7 +626,8 @@ LayerManagerOGL::CopyToTarget()
|
|||
#ifdef USE_GLES2
|
||||
// GLES2 promises that binding to any custom FBO will attach
|
||||
// to GL_COLOR_ATTACHMENT0 attachment point.
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO);
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO);
|
||||
#else
|
||||
mGLContext->fReadBuffer(LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
#endif
|
||||
|
|
|
@ -1113,10 +1113,10 @@ public:
|
|||
inline void
|
||||
GLDebugPrintError(GLContext* aCx, const char* const aFile, int aLine)
|
||||
{
|
||||
GLenum err = aCx->fGetError();
|
||||
if (err) {
|
||||
fprintf(stderr, "GL ERROR: 0x%04x at %s:%d\n", err, aFile, aLine);
|
||||
}
|
||||
GLenum err = aCx->fGetError();
|
||||
if (err) {
|
||||
printf_stderr("GL ERROR: 0x%04x at %s:%d\n", err, aFile, aLine);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
Загрузка…
Ссылка в новой задаче