Back out bug 622072 because it caused bug 645987

This commit is contained in:
Ehsan Akhgari 2011-03-29 14:31:53 -04:00
parent 4ca813ae6e
commit 931bd6ee19
22 changed files with 165 additions and 225 deletions

View File

@ -43,15 +43,14 @@
#include "nsIDocShell.h"
#include "gfxPattern.h"
// {EC90F32E-7848-4819-A1E3-02E64C682A72}
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
{ 0xffb42d3c, 0x8281, 0x44c8, \
{ 0xac, 0xba, 0x73, 0x15, 0x31, 0xaa, 0xe5, 0x07 } }
{ 0xec90f32e, 0x7848, 0x4819, { 0xa1, 0xe3, 0x2, 0xe6, 0x4c, 0x68, 0x2a, 0x72 } }
class nsHTMLCanvasElement;
class gfxContext;
class gfxASurface;
class nsIPropertyBag;
class nsDisplayListBuilder;
namespace mozilla {
namespace layers {
@ -109,8 +108,7 @@ public:
// Return the CanvasLayer for this context, creating
// one for the given layer manager if not available.
virtual already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
virtual already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager) = 0;
virtual void MarkContextClean() = 0;

View File

@ -58,7 +58,6 @@
#include "gfxUtils.h"
#include "CanvasUtils.h"
#include "nsDisplayList.h"
#include "GLContextProvider.h"
@ -248,9 +247,6 @@ WebGLContext::DestroyResourcesAndContext()
void
WebGLContext::Invalidate()
{
if (mInvalidated)
return;
if (!mCanvasElement)
return;
@ -258,6 +254,9 @@ WebGLContext::Invalidate()
nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
#endif
if (mInvalidated)
return;
mInvalidated = PR_TRUE;
HTMLCanvasElement()->InvalidateFrame();
}
@ -620,27 +619,18 @@ WebGLContext::GetThebesSurface(gfxASurface **surface)
static PRUint8 gWebGLLayerUserData;
class WebGLContextUserData : public LayerUserData {
public:
WebGLContextUserData(nsHTMLCanvasElement *aContent)
: mContent(aContent) {}
static void DidTransactionCallback(void* aData)
{
static_cast<WebGLContextUserData*>(aData)->mContent->MarkContextClean();
}
private:
nsRefPtr<nsHTMLCanvasElement> mContent;
};
already_AddRefed<layers::CanvasLayer>
WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (!mResetLayer && aOldLayer &&
aOldLayer->HasUserData(&gWebGLLayerUserData)) {
NS_ADDREF(aOldLayer);
if (mInvalidated) {
aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
mInvalidated = PR_FALSE;
HTMLCanvasElement()->GetPrimaryCanvasFrame()->MarkLayersActive();
}
return aOldLayer;
}
@ -649,25 +639,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
NS_WARNING("CreateCanvasLayer returned null!");
return nsnull;
}
WebGLContextUserData *userData = nsnull;
if (aBuilder->IsPaintingToWindow()) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new WebGLContextUserData(HTMLCanvasElement());
canvasLayer->SetDidTransactionCallback(
WebGLContextUserData::DidTransactionCallback, userData);
}
canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull);
CanvasLayer::Data data;
@ -689,8 +661,9 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
canvasLayer->Initialize(data);
PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0;
canvasLayer->SetContentFlags(flags);
canvasLayer->Updated();
canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
mInvalidated = PR_FALSE;
mResetLayer = PR_FALSE;
return canvasLayer.forget().get();

View File

@ -368,10 +368,9 @@ public:
: mBoundCubeMapTextures[mActiveTexture];
}
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager);
void MarkContextClean() { mInvalidated = PR_FALSE; }
void MarkContextClean() { }
// a number that increments every time we have an event that causes
// all context resources to be lost.

View File

@ -96,7 +96,6 @@
#include "nsIDocShellTreeNode.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsDisplayList.h"
#include "nsTArray.h"
@ -408,8 +407,7 @@ public:
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
NS_IMETHOD SetIsOpaque(PRBool isOpaque);
NS_IMETHOD Reset();
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager);
void MarkContextClean();
NS_IMETHOD SetIsIPC(PRBool isIPC);
@ -457,6 +455,7 @@ public:
friend class PathAutoSaveRestore;
protected:
/**
* The number of living nsCanvasRenderingContexts. When this goes down to
* 0, we free the premultiply and unpremultiply tables, if they exist.
@ -4100,22 +4099,8 @@ nsCanvasRenderingContext2D::SetMozImageSmoothingEnabled(PRBool val)
static PRUint8 g2DContextLayerUserData;
class CanvasRenderingContext2DUserData : public LayerUserData {
public:
CanvasRenderingContext2DUserData(nsHTMLCanvasElement *aContent)
: mContent(aContent) {}
static void DidTransactionCallback(void* aData)
{
static_cast<CanvasRenderingContext2DUserData*>(aData)->mContent->MarkContextClean();
}
private:
nsRefPtr<nsHTMLCanvasElement> mContent;
};
already_AddRefed<CanvasLayer>
nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (!mValid)
@ -4124,6 +4109,14 @@ nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
if (!mResetLayer && aOldLayer &&
aOldLayer->HasUserData(&g2DContextLayerUserData)) {
NS_ADDREF(aOldLayer);
if (mIsEntireFrameInvalid || mInvalidateCount > 0) {
// XXX Need to just update the changed area here; we should keep track
// of the rectangle based on Redraw args.
aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
MarkContextClean();
HTMLCanvasElement()->GetPrimaryCanvasFrame()->MarkLayersActive();
}
return aOldLayer;
}
@ -4132,25 +4125,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
NS_WARNING("CreateCanvasLayer returned null!");
return nsnull;
}
CanvasRenderingContext2DUserData *userData = nsnull;
if (aBuilder->IsPaintingToWindow()) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new CanvasRenderingContext2DUserData(HTMLCanvasElement());
canvasLayer->SetDidTransactionCallback(
CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
}
canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull);
CanvasLayer::Data data;
@ -4160,11 +4135,13 @@ nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
canvasLayer->Initialize(data);
PRUint32 flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
canvasLayer->SetContentFlags(flags);
canvasLayer->Updated();
canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
mResetLayer = PR_FALSE;
return canvasLayer.forget();
MarkContextClean();
return canvasLayer.forget().get();
}
void

View File

@ -157,12 +157,12 @@ public:
* Helpers called by various users of Canvas
*/
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager);
// Any invalidates requested by the context have been processed by updating
// the window. Future changes to the canvas need to trigger more invalidation.
// Tell the Context that all the current rendering that it's
// invalidated has been displayed to the screen, so that it should
// start requesting invalidates again as needed.
void MarkContextClean();
virtual nsXPCClassInfo* GetClassInfo();

View File

@ -648,11 +648,8 @@ nsHTMLCanvasElement::InvalidateFrame(const gfxRect* damageRect)
if (!frame)
return;
frame->MarkLayersActive();
nsRect invalRect;
nsRect contentArea = frame->GetContentRect();
if (damageRect) {
nsRect contentArea(frame->GetContentRect());
nsIntSize size = GetWidthHeight();
// damageRect and size are in CSS pixels; contentArea is in appunits
@ -664,16 +661,16 @@ nsHTMLCanvasElement::InvalidateFrame(const gfxRect* damageRect)
realRect.RoundOut();
// then make it a nsRect
invalRect = nsRect(realRect.X(), realRect.Y(),
realRect.Width(), realRect.Height());
} else {
invalRect = nsRect(nsPoint(0, 0), contentArea.Size());
}
invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
nsRect invalRect(realRect.X(), realRect.Y(),
realRect.Width(), realRect.Height());
Layer* layer = frame->InvalidateLayer(invalRect, nsDisplayItem::TYPE_CANVAS);
if (layer) {
static_cast<CanvasLayer*>(layer)->Updated();
// account for border/padding
invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
frame->InvalidateLayer(invalRect, nsDisplayItem::TYPE_CANVAS);
} else {
nsRect r(frame->GetContentRect() - frame->GetPosition());
frame->InvalidateLayer(r, nsDisplayItem::TYPE_CANVAS);
}
}
@ -702,14 +699,13 @@ nsHTMLCanvasElement::GetIsOpaque()
}
already_AddRefed<CanvasLayer>
nsHTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
nsHTMLCanvasElement::GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (!mCurrentContext)
return nsnull;
return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
return mCurrentContext->GetCanvasLayer(aOldLayer, aManager);
}
void

View File

@ -1176,20 +1176,13 @@ public:
virtual void Initialize(const Data& aData) = 0;
/**
* Notify this CanvasLayer that the canvas surface contents have
* changed (or will change) before the next transaction.
* CONSTRUCTION PHASE ONLY
* Notify this CanvasLayer that the rectangle given by aRect
* has been updated, and any work that needs to be done
* to bring the contents from the Surface/GLContext to the
* Layer in preparation for compositing should be performed.
*/
void Updated() { mDirty = PR_TRUE; }
/**
* Register a callback to be called at the end of each transaction.
*/
typedef void (* DidTransactionCallback)(void* aClosureData);
void SetDidTransactionCallback(DidTransactionCallback aCallback, void* aClosureData)
{
mCallback = aCallback;
mCallbackData = aClosureData;
}
virtual void Updated(const nsIntRect& aRect) = 0;
/**
* CONSTRUCTION PHASE ONLY
@ -1214,30 +1207,15 @@ public:
protected:
CanvasLayer(LayerManager* aManager, void* aImplData)
: Layer(aManager, aImplData),
mCallback(nsnull), mCallbackData(nsnull), mFilter(gfxPattern::FILTER_GOOD),
mDirty(PR_FALSE) {}
: Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {}
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
void FireDidTransactionCallback()
{
if (mCallback) {
mCallback(mCallbackData);
}
}
/**
* 0, 0, canvaswidth, canvasheight
*/
nsIntRect mBounds;
DidTransactionCallback mCallback;
void* mCallbackData;
gfxPattern::GraphicsFilter mFilter;
/**
* Set to true in Updated(), cleared during a transaction.
*/
PRPackedBool mDirty;
};
}

View File

@ -893,6 +893,7 @@ public:
}
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect);
virtual void Paint(gfxContext* aContext);
virtual void PaintWithOpacity(gfxContext* aContext,
@ -903,12 +904,13 @@ protected:
{
return static_cast<BasicLayerManager*>(mManager);
}
void UpdateSurface();
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<mozilla::gl::GLContext> mGLContext;
PRUint32 mCanvasFramebuffer;
nsIntRect mUpdatedRect;
PRPackedBool mGLBufferIsPremultiplied;
PRPackedBool mNeedsYFlip;
};
@ -918,6 +920,8 @@ BasicCanvasLayer::Initialize(const Data& aData)
{
NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
mUpdatedRect.Empty();
if (aData.mSurface) {
mSurface = aData.mSurface;
NS_ASSERTION(aData.mGLContext == nsnull,
@ -937,11 +941,12 @@ BasicCanvasLayer::Initialize(const Data& aData)
}
void
BasicCanvasLayer::UpdateSurface()
BasicCanvasLayer::Updated(const nsIntRect& aRect)
{
if (!mDirty)
return;
mDirty = PR_FALSE;
NS_ASSERTION(mUpdatedRect.IsEmpty(),
"CanvasLayer::Updated called more than once in a transaction!");
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
if (mGLContext) {
nsRefPtr<gfxImageSurface> isurf =
@ -971,6 +976,9 @@ BasicCanvasLayer::UpdateSurface()
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.
mGLContext->ReadPixelsIntoImageSurface(0, 0,
mBounds.width, mBounds.height,
isurf);
@ -989,13 +997,15 @@ BasicCanvasLayer::UpdateSurface()
// stick our surface into mSurface, so that the Paint() path is the same
mSurface = isurf;
}
// sanity
NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect),
"CanvasLayer: Updated rect bigger than bounds!");
}
void
BasicCanvasLayer::Paint(gfxContext* aContext)
{
UpdateSurface();
FireDidTransactionCallback();
PaintWithOpacity(aContext, GetEffectiveOpacity());
}
@ -1027,6 +1037,8 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
if (mNeedsYFlip) {
aContext->SetMatrix(m);
}
mUpdatedRect.Empty();
}
class BasicReadbackLayer : public ReadbackLayer,
@ -2545,6 +2557,9 @@ public:
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect)
{}
virtual already_AddRefed<gfxSharedImageSurface>
Swap(gfxSharedImageSurface* newFront);

View File

@ -114,12 +114,8 @@ CanvasLayerD3D10::Initialize(const Data& aData)
}
void
CanvasLayerD3D10::UpdateSurface()
CanvasLayerD3D10::Updated(const nsIntRect& aRect)
{
if (!mDirty)
return;
mDirty = PR_FALSE;
if (mIsD2DTexture) {
mSurface->Flush();
return;
@ -165,6 +161,9 @@ CanvasLayerD3D10::UpdateSurface()
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.
nsRefPtr<gfxImageSurface> tmpSurface =
new gfxImageSurface(destination,
gfxIntSize(mBounds.width, mBounds.height),
@ -190,10 +189,10 @@ CanvasLayerD3D10::UpdateSurface()
mTexture->Unmap(0);
} else if (mSurface) {
RECT r;
r.left = 0;
r.top = 0;
r.right = mBounds.width;
r.bottom = mBounds.height;
r.left = aRect.x;
r.top = aRect.y;
r.right = aRect.XMost();
r.bottom = aRect.YMost();
D3D10_MAPPED_TEXTURE2D map;
HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
@ -203,13 +202,17 @@ CanvasLayerD3D10::UpdateSurface()
return;
}
PRUint8 *startBits;
PRUint32 sourceStride;
nsRefPtr<gfxImageSurface> dstSurface;
dstSurface = new gfxImageSurface((unsigned char*)map.pData,
gfxIntSize(mBounds.width, mBounds.height),
gfxIntSize(aRect.width, aRect.height),
map.RowPitch,
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(dstSurface);
ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mSurface);
ctx->Paint();
@ -227,11 +230,9 @@ CanvasLayerD3D10::GetLayer()
void
CanvasLayerD3D10::RenderLayer()
{
UpdateSurface();
FireDidTransactionCallback();
if (!mTexture)
if (!mTexture) {
return;
}
nsIntRect visibleRect = mVisibleRegion.GetBounds();

View File

@ -64,6 +64,7 @@ public:
// CanvasLayer implementation
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect);
// LayerD3D10 implementation
virtual Layer* GetLayer();
@ -72,8 +73,6 @@ public:
private:
typedef mozilla::gl::GLContext GLContext;
void UpdateSurface();
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<GLContext> mGLContext;
nsRefPtr<ID3D10Texture2D> mTexture;

View File

@ -79,12 +79,8 @@ CanvasLayerD3D9::Initialize(const Data& aData)
}
void
CanvasLayerD3D9::UpdateSurface()
CanvasLayerD3D9::Updated(const nsIntRect& aRect)
{
if (!mDirty)
return;
mDirty = PR_FALSE;
if (!mTexture) {
CreateTexture();
NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
@ -121,6 +117,9 @@ CanvasLayerD3D9::UpdateSurface()
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.
nsRefPtr<gfxImageSurface> tmpSurface =
new gfxImageSurface(destination,
gfxIntSize(mBounds.width, mBounds.height),
@ -146,10 +145,10 @@ CanvasLayerD3D9::UpdateSurface()
mTexture->UnlockRect(0);
} else if (mSurface) {
RECT r;
r.left = mBounds.x;
r.top = mBounds.y;
r.right = mBounds.XMost();
r.bottom = mBounds.YMost();
r.left = aRect.x;
r.top = aRect.y;
r.right = aRect.XMost();
r.bottom = aRect.YMost();
D3DLOCKED_RECT lockedRect;
HRESULT hr = mTexture->LockRect(0, &lockedRect, &r, 0);
@ -159,10 +158,16 @@ CanvasLayerD3D9::UpdateSurface()
return;
}
PRUint8 *startBits;
PRUint32 sourceStride;
nsRefPtr<gfxImageSurface> sourceSurface;
if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
sourceSurface = mSurface->GetAsImageSurface();
startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
aRect.x * 4;
sourceStride = sourceSurface->Stride();
} else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
@ -171,28 +176,31 @@ CanvasLayerD3D9::UpdateSurface()
mTexture->UnlockRect(0);
return;
}
startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
aRect.x * 4;
sourceStride = sourceSurface->Stride();
} else {
sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
sourceSurface = new gfxImageSurface(gfxIntSize(aRect.width, aRect.height),
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mSurface);
ctx->Paint();
startBits = sourceSurface->Data();
sourceStride = sourceSurface->Stride();
}
PRUint8 *startBits = sourceSurface->Data();
PRUint32 sourceStride = sourceSurface->Stride();
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32) {
mHasAlpha = false;
} else {
mHasAlpha = true;
}
for (int y = 0; y < mBounds.height; y++) {
for (int y = 0; y < aRect.height; y++) {
memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
startBits + sourceStride * y,
mBounds.width * 4);
aRect.width * 4);
}
mTexture->UnlockRect(0);
@ -208,11 +216,9 @@ CanvasLayerD3D9::GetLayer()
void
CanvasLayerD3D9::RenderLayer()
{
UpdateSurface();
FireDidTransactionCallback();
if (!mTexture)
return;
if (!mTexture) {
Updated(mBounds);
}
/*
* We flip the Y axis here, note we can only do this because we are in

View File

@ -66,6 +66,7 @@ public:
// CanvasLayer implementation
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect);
// LayerD3D9 implementation
virtual Layer* GetLayer();
@ -78,8 +79,6 @@ public:
protected:
typedef mozilla::gl::GLContext GLContext;
void UpdateSurface();
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<GLContext> mGLContext;
nsRefPtr<IDirect3DTexture9> mTexture;

View File

@ -172,6 +172,7 @@ struct OpPaintThebesBuffer {
struct OpPaintCanvas {
PLayer layer;
nsIntRect updated;
Shmem newFrontBuffer;
};

View File

@ -301,6 +301,7 @@ ShadowLayerForwarder::PaintedCanvas(ShadowableLayer* aCanvas,
gfxSharedImageSurface* aNewFrontSurface)
{
mTxn->AddPaint(OpPaintCanvas(NULL, Shadow(aCanvas),
nsIntRect(),
aNewFrontSurface->GetShmem()));
}

View File

@ -422,7 +422,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
newFront.forget();
}
canvas->Updated();
canvas->Updated(op.updated());
replyv.push_back(OpBufferSwap(shadow, NULL,
newBack->GetShmem()));

View File

@ -135,18 +135,19 @@ CanvasLayerOGL::MakeTexture()
}
void
CanvasLayerOGL::UpdateSurface()
CanvasLayerOGL::Updated(const nsIntRect& aRect)
{
if (!mDirty)
return;
mDirty = PR_FALSE;
if (mDestroyed || mDelayedUpdates) {
return;
}
NS_ASSERTION(mUpdatedRect.IsEmpty(),
"CanvasLayer::Updated called more than once during a transaction!");
mOGLManager->MakeCurrent();
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
if (mCanvasGLContext &&
mCanvasGLContext->GetContextType() == gl()->GetContextType())
{
@ -156,36 +157,41 @@ CanvasLayerOGL::UpdateSurface()
MakeTexture();
}
} else {
if (!mTexture) {
mUpdatedRect = mBounds;
}
nsRefPtr<gfxASurface> updatedAreaSurface;
if (mCanvasSurface) {
updatedAreaSurface = mCanvasSurface;
} else if (mCanvasGLContext) {
nsRefPtr<gfxImageSurface> updatedAreaImageSurface =
new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
gfxASurface::ImageFormatARGB32);
mCanvasGLContext->ReadPixelsIntoImageSurface(0, 0,
mBounds.width,
mBounds.height,
mCanvasGLContext->ReadPixelsIntoImageSurface(mUpdatedRect.x, mUpdatedRect.y,
mUpdatedRect.width,
mUpdatedRect.height,
updatedAreaImageSurface);
updatedAreaSurface = updatedAreaImageSurface;
}
mLayerProgram =
gl()->UploadSurfaceToTexture(updatedAreaSurface,
mBounds,
mUpdatedRect,
mTexture,
false,
nsIntPoint(0, 0));
mUpdatedRect.TopLeft());
}
// sanity
NS_ASSERTION(mBounds.Contains(mUpdatedRect),
"CanvasLayer: Updated rect bigger than bounds!");
}
void
CanvasLayerOGL::RenderLayer(int aPreviousDestination,
const nsIntPoint& aOffset)
{
UpdateSurface();
FireDidTransactionCallback();
mOGLManager->MakeCurrent();
// XXX We're going to need a different program depending on if
@ -242,6 +248,8 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
if (useGLContext) {
gl()->UnbindTex2DOffscreen(mCanvasGLContext);
}
mUpdatedRect.Empty();
}

View File

@ -66,6 +66,7 @@ public:
// CanvasLayer implementation
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect);
// LayerOGL implementation
virtual void Destroy();
@ -74,8 +75,6 @@ public:
const nsIntPoint& aOffset);
protected:
void UpdateSurface();
nsRefPtr<gfxASurface> mCanvasSurface;
nsRefPtr<GLContext> mCanvasGLContext;
gl::ShaderProgramType mLayerProgram;
@ -83,6 +82,8 @@ protected:
void MakeTexture();
GLuint mTexture;
nsIntRect mUpdatedRect;
PRPackedBool mDelayedUpdates;
PRPackedBool mGLBufferIsPremultiplied;
PRPackedBool mNeedsYFlip;

View File

@ -1744,12 +1744,12 @@ FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
}
/* static */
Layer*
FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
PRBool
FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
{
void* propValue = aFrame->Properties().Get(DisplayItemDataProperty());
if (!propValue)
return nsnull;
return PR_FALSE;
nsTArray<DisplayItemData>* array =
(reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
@ -1759,10 +1759,10 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
if (!layer->HasUserData(&gColorLayerUserData) &&
!layer->HasUserData(&gImageLayerUserData) &&
!layer->HasUserData(&gThebesDisplayItemLayerUserData))
return layer;
return PR_TRUE;
}
}
return nsnull;
return PR_FALSE;
}
/* static */ void

View File

@ -191,10 +191,9 @@ public:
/**
* Call this to determine if a frame has a dedicated (non-Thebes) layer
* for the given display item key. If there isn't one, we return null,
* otherwise we return the layer.
* for the given display item key.
*/
static Layer* GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
static PRBool HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
/**
* This callback must be provided to EndTransaction. The callback data

View File

@ -131,7 +131,6 @@
#include "CSSCalc.h"
using namespace mozilla;
using namespace mozilla::layers;
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
@ -3946,26 +3945,23 @@ nsIFrame::IsLeaf() const
return PR_TRUE;
}
Layer*
void
nsIFrame::InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey)
{
NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
if (!layer) {
if (!FrameLayerBuilder::HasDedicatedLayer(this, aDisplayItemKey)) {
Invalidate(aDamageRect);
return nsnull;
return;
}
PRUint32 flags = INVALIDATE_NO_THEBES_LAYERS;
if (aDisplayItemKey == nsDisplayItem::TYPE_VIDEO ||
aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN ||
aDisplayItemKey == nsDisplayItem::TYPE_CANVAS) {
aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN) {
flags |= INVALIDATE_NO_UPDATE_LAYER_TREE;
}
InvalidateWithFlags(aDamageRect, flags);
return layer;
}
void
@ -3974,7 +3970,7 @@ nsIFrame::InvalidateTransformLayer()
NS_ASSERTION(mParent, "How can a viewport frame have a transform?");
PRBool hasLayer =
FrameLayerBuilder::GetDedicatedLayer(this, nsDisplayItem::TYPE_TRANSFORM) != nsnull;
FrameLayerBuilder::HasDedicatedLayer(this, nsDisplayItem::TYPE_TRANSFORM);
// Invalidate post-transform area in the parent. We have to invalidate
// in the parent because our transform style may have changed from what was
// used to paint this frame.

View File

@ -275,10 +275,12 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer* oldLayer = static_cast<CanvasLayer*>
(aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
nsRefPtr<CanvasLayer> layer = element->GetCanvasLayer(aBuilder, oldLayer, aManager);
nsRefPtr<CanvasLayer> layer = element->GetCanvasLayer(oldLayer, aManager);
if (!layer)
return nsnull;
element->MarkContextClean();
nsPresContext* presContext = PresContext();
gfxRect r = gfxRect(presContext->AppUnitsToGfxUnits(area.x),
presContext->AppUnitsToGfxUnits(area.y),

View File

@ -111,12 +111,6 @@ struct nsSize;
struct nsMargin;
struct CharacterDataChangeInfo;
namespace mozilla {
namespace layers {
class Layer;
}
}
typedef class nsIFrame nsIBox;
/**
@ -524,7 +518,6 @@ class nsIFrame : public nsQueryFrame
public:
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
typedef mozilla::FrameProperties FrameProperties;
typedef mozilla::layers::Layer Layer;
NS_DECL_QUERYFRAME_TARGET(nsIFrame)
@ -2022,12 +2015,10 @@ public:
* As Invalidate above, except that this should be called when the
* rendering that has changed is performed using layers so we can avoid
* updating the contents of ThebesLayers.
* If the frame has a dedicated layer rendering this display item, we
* return that layer.
* @param aDisplayItemKey must not be zero; indicates the kind of display
* item that is being invalidated.
*/
Layer* InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey);
void InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey);
/**
* Invalidate the area of the parent that's covered by the transformed