b=575469; use CreateOffscreen in layers; r=bas

This commit is contained in:
Vladimir Vukicevic 2010-07-18 22:01:14 -07:00
Родитель e71cc8f81f
Коммит 27b296ce6e
7 изменённых файлов: 114 добавлений и 99 удалений

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

@ -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*)&currentFramebuffer);
// 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*)&currentFramebuffer);
// 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