Bug 602428, part 4: Implement HW-decelerating ShadowThebesLayerOGL. r=vlad

This commit is contained in:
Chris Jones 2010-10-13 17:55:45 -05:00
parent 063cfb2b8c
commit 05cdadbe85
3 changed files with 215 additions and 6 deletions

View File

@ -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);

View File

@ -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<TextureImage> 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<gfxContext> 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<LayerOGL*>(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<gfxASurface> 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<gfxASurface> 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 */

View File

@ -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<Buffer> 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<ShadowBufferOGL> 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 */