mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out bug 622072 because it caused bug 645987
This commit is contained in:
parent
4ca813ae6e
commit
931bd6ee19
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -172,6 +172,7 @@ struct OpPaintThebesBuffer {
|
||||
|
||||
struct OpPaintCanvas {
|
||||
PLayer layer;
|
||||
nsIntRect updated;
|
||||
Shmem newFrontBuffer;
|
||||
};
|
||||
|
||||
|
@ -301,6 +301,7 @@ ShadowLayerForwarder::PaintedCanvas(ShadowableLayer* aCanvas,
|
||||
gfxSharedImageSurface* aNewFrontSurface)
|
||||
{
|
||||
mTxn->AddPaint(OpPaintCanvas(NULL, Shadow(aCanvas),
|
||||
nsIntRect(),
|
||||
aNewFrontSurface->GetShmem()));
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user