diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index 48e6c06990a3..51a8f26eb5a3 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -461,6 +461,7 @@ public: typedef mozilla::gl::GLContext GLContext; + LayerManagerOGL* OGLManager() const { return mOGLManager; } GLContext *gl() const { return mOGLManager->gl(); } void ApplyFilter(gfxPattern::GraphicsFilter aFilter); diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index c7e10c605ae8..867e5d366cff 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -36,6 +36,11 @@ * * ***** END LICENSE BLOCK ***** */ +#ifdef MOZ_IPC +# include "mozilla/layers/PLayers.h" +# include "mozilla/layers/ShadowLayers.h" +#endif + #include "ThebesLayerBuffer.h" #include "ThebesLayerOGL.h" @@ -120,8 +125,9 @@ public: typedef TextureImage::ContentType ContentType; typedef ThebesLayerBuffer::PaintState PaintState; - ThebesLayerBufferOGL(ThebesLayerOGL* aLayer) + ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer) : mLayer(aLayer) + , mOGLLayer(aOGLLayer) {} virtual ~ThebesLayerBufferOGL() {} @@ -138,9 +144,10 @@ public: protected: virtual nsIntPoint GetOriginOffset() = 0; - GLContext* gl() const { return mLayer->gl(); } + GLContext* gl() const { return mOGLLayer->gl(); } - ThebesLayerOGL* mLayer; + ThebesLayer* mLayer; + LayerOGL* mOGLLayer; nsRefPtr mTexImage; }; @@ -204,7 +211,7 @@ public: typedef ThebesLayerBufferOGL::PaintState PaintState; SurfaceBufferOGL(ThebesLayerOGL* aLayer) - : ThebesLayerBufferOGL(aLayer) + : ThebesLayerBufferOGL(aLayer, aLayer) , ThebesLayerBuffer(SizedToVisibleBounds) { } @@ -242,7 +249,7 @@ class BasicBufferOGL : public ThebesLayerBufferOGL { public: BasicBufferOGL(ThebesLayerOGL* aLayer) - : ThebesLayerBufferOGL(aLayer) + : ThebesLayerBufferOGL(aLayer, aLayer) , mBufferRect(0,0,0,0) , mBufferRotation(0,0) {} @@ -387,7 +394,7 @@ BasicBufferOGL::BeginPaint(ContentType aContentType) if (mTexImage) { // BlitTextureImage depends on the FBO texture target being // TEXTURE_2D. This isn't the case on some older X1600-era Radeons. - if (mLayer->mOGLManager->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) { + if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) { nsIntRect overlap; overlap.IntersectRect(mBufferRect, destBufferRect); @@ -548,5 +555,164 @@ ThebesLayerOGL::IsEmpty() return !mBuffer; } + +#ifdef MOZ_IPC + +class ShadowBufferOGL : public ThebesLayerBufferOGL +{ +public: + ShadowBufferOGL(ShadowThebesLayerOGL* aLayer) + : ThebesLayerBufferOGL(aLayer, aLayer) + {} + + virtual PaintState BeginPaint(ContentType aContentType) { + NS_RUNTIMEABORT("can't BeginPaint for a shadow layer"); + return PaintState(); + } + + void + CreateTexture(ContentType aType, const nsIntSize& aSize) + { + NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color"); + + mTexImage = gl()->CreateTextureImage(aSize, aType, LOCAL_GL_REPEAT); + } + + void Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated, + const nsIntRect& aRect, const nsIntPoint& aRotation); + +protected: + virtual nsIntPoint GetOriginOffset() { + return mBufferRect.TopLeft() - mBufferRotation; + } + +private: + nsIntRect mBufferRect; + nsIntPoint mBufferRotation; +}; + +void +ShadowBufferOGL::Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated, + const nsIntRect& aRect, const nsIntPoint& aRotation) +{ + nsIntRegion destRegion(aUpdated); + // aUpdated is in screen coordinates. Move it so that the layer's + // top-left is 0,0 + nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft(); + destRegion.MoveBy(-visTopLeft); + // NB: this gfxContext must not escape EndUpdate() below + nsRefPtr dest = mTexImage->BeginUpdate(destRegion); + + dest->SetOperator(gfxContext::OPERATOR_SOURCE); + dest->DrawSurface(aUpdate, aUpdate->GetSize()); + + mTexImage->EndUpdate(); + + mBufferRect = aRect; + mBufferRotation = aRotation; +} + +ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager) + : ShadowThebesLayer(aManager, nsnull) + , LayerOGL(aManager) +{ + mImplData = static_cast(this); +} + +ShadowThebesLayerOGL::~ShadowThebesLayerOGL() +{} + +void +ShadowThebesLayerOGL::SetFrontBuffer(const ThebesBuffer& aNewFront, + const nsIntRegion& aValidRegion, + float aXResolution, float aYResolution) +{ + if (mDestroyed) { + return; + } + + if (!mBuffer) { + mBuffer = new ShadowBufferOGL(this); + } + + nsRefPtr surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer()); + gfxIntSize size = surf->GetSize(); + mBuffer->CreateTexture(surf->GetContentType(), + nsIntSize(size.width, size.height)); + + + + mDeadweight = aNewFront.buffer(); +} + +void +ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront, + const nsIntRegion& aUpdatedRegion, + ThebesBuffer* aNewBack, + nsIntRegion* aNewBackValidRegion, + float* aNewXResolution, float* aNewYResolution) +{ + if (!mDestroyed && mBuffer) { + nsRefPtr surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer()); + mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation()); + } + + *aNewBack = aNewFront; + *aNewBackValidRegion = mValidRegion; + *aNewXResolution = 1.0; + *aNewYResolution = 1.0; +} + +void +ShadowThebesLayerOGL::DestroyFrontBuffer() +{ + mBuffer = nsnull; + if (SurfaceDescriptor::T__None != mDeadweight.type()) { + mOGLManager->DestroySharedSurface(&mDeadweight, mAllocator); + } +} + +void +ShadowThebesLayerOGL::Destroy() +{ + if (!mDestroyed) { + mDestroyed = PR_TRUE; + mBuffer = nsnull; + } +} + +Layer* +ShadowThebesLayerOGL::GetLayer() +{ + return this; +} + +PRBool +ShadowThebesLayerOGL::IsEmpty() +{ + return !mBuffer; +} + +void +ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, + const nsIntPoint& aOffset) +{ + if (!mBuffer) { + return; + } + NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here"); + + mOGLManager->MakeCurrent(); + gl()->fActiveTexture(LOCAL_GL_TEXTURE0); + DEBUG_GL_ERROR_CHECK(gl()); + + gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); + mBuffer->RenderTo(aOffset, mOGLManager); + DEBUG_GL_ERROR_CHECK(gl()); +} + +#endif // MOZ_IPC + + } /* layers */ } /* mozilla */ diff --git a/gfx/layers/opengl/ThebesLayerOGL.h b/gfx/layers/opengl/ThebesLayerOGL.h index 0d05ff83877a..5ac6b3d54bcd 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.h +++ b/gfx/layers/opengl/ThebesLayerOGL.h @@ -38,6 +38,11 @@ #ifndef GFX_THEBESLAYEROGL_H #define GFX_THEBESLAYEROGL_H +#ifdef MOZ_IPC +# include "mozilla/layers/PLayers.h" +# include "mozilla/layers/ShadowLayers.h" +#endif + #include "Layers.h" #include "LayerManagerOGL.h" #include "gfxImageSurface.h" @@ -49,6 +54,7 @@ namespace layers { class ThebesLayerBufferOGL; class BasicBufferOGL; +class ShadowBufferOGL; class ThebesLayerOGL : public ThebesLayer, public LayerOGL @@ -80,6 +86,42 @@ private: nsRefPtr mBuffer; }; +#ifdef MOZ_IPC +class ShadowThebesLayerOGL : public ShadowThebesLayer, + public LayerOGL +{ +public: + ShadowThebesLayerOGL(LayerManagerOGL *aManager); + virtual ~ShadowThebesLayerOGL(); + + // ShadowThebesLayer impl + virtual void SetFrontBuffer(const ThebesBuffer& aNewFront, + const nsIntRegion& aValidRegion, + float aXResolution, float aYResolution); + virtual void + Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion, + ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion, + float* aNewXResolution, float* aNewYResolution); + virtual void DestroyFrontBuffer(); + + // LayerOGL impl + void Destroy(); + Layer* GetLayer(); + virtual PRBool IsEmpty(); + virtual void RenderLayer(int aPreviousFrameBuffer, + const nsIntPoint& aOffset); + +private: + nsRefPtr mBuffer; + + + // XXX FIXME TEMP: hold on to this so that we can free it in DestroyFrontBuffer() + SurfaceDescriptor mDeadweight; + + +}; +#endif // MOZ_IPC + } /* layers */ } /* mozilla */ #endif /* GFX_THEBESLAYEROGL_H */