mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-09 08:48:07 +00:00
Bug 746883; fix the bustage possibly caused by 746896. r=mattwoodrow
This commit is contained in:
parent
952f2e4661
commit
3e80396ca2
@ -32,6 +32,7 @@ CanvasLayerD3D9::Initialize(const Data& aData)
|
||||
|
||||
if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
mNeedsYFlip = false;
|
||||
mDataIsPremultiplied = true;
|
||||
} else if (aData.mSurface) {
|
||||
@ -139,18 +140,11 @@ CanvasLayerD3D9::UpdateSurface()
|
||||
D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
|
||||
|
||||
nsRefPtr<gfxImageSurface> sourceSurface;
|
||||
nsRefPtr<gfxASurface> tempSurface;
|
||||
if (mDrawTarget) {
|
||||
tempSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
}
|
||||
else {
|
||||
tempSurface = mSurface;
|
||||
}
|
||||
|
||||
if (tempSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = tempSurface->GetAsImageSurface();
|
||||
} else if (tempSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
sourceSurface = static_cast<gfxImageSurface*>(tempSurface.get());
|
||||
if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = mSurface->GetAsImageSurface();
|
||||
} else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
|
||||
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
@ -161,7 +155,7 @@ CanvasLayerD3D9::UpdateSurface()
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(tempSurface);
|
||||
ctx->SetSource(mSurface);
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
||||
|
||||
if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
mNeedsYFlip = false;
|
||||
} else if (aData.mSurface) {
|
||||
mCanvasSurface = aData.mSurface;
|
||||
@ -162,11 +163,7 @@ CanvasLayerOGL::UpdateSurface()
|
||||
} else {
|
||||
nsRefPtr<gfxASurface> updatedAreaSurface;
|
||||
|
||||
if (mDrawTarget) {
|
||||
// TODO: This is suboptimal - We should have direct handling for the surface types instead of
|
||||
// going via a gfxASurface.
|
||||
updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
} else if (mCanvasSurface) {
|
||||
if (mCanvasSurface) {
|
||||
updatedAreaSurface = mCanvasSurface;
|
||||
} else if (mCanvasGLContext) {
|
||||
gfxIntSize size(mBounds.width, mBounds.height);
|
||||
@ -226,13 +223,8 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
|
||||
drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
|
||||
|
||||
nsRefPtr<gfxASurface> surf = mCanvasSurface;
|
||||
if (mDrawTarget) {
|
||||
surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
}
|
||||
|
||||
mLayerProgram =
|
||||
gl()->UploadSurfaceToTexture(surf,
|
||||
gl()->UploadSurfaceToTexture(mCanvasSurface,
|
||||
nsIntRect(0, 0, drawRect.width, drawRect.height),
|
||||
mTexture,
|
||||
true,
|
||||
|
@ -615,57 +615,53 @@ gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
return scaledFont;
|
||||
}
|
||||
|
||||
UserDataKey kThebesSurfaceKey;
|
||||
void
|
||||
DestroyThebesSurface(void *data)
|
||||
cairo_user_data_key_t kDrawSourceSurface;
|
||||
static void
|
||||
DataSourceSurfaceDestroy(void *dataSourceSurface)
|
||||
{
|
||||
gfxASurface *surface = static_cast<gfxASurface*>(data);
|
||||
surface->Release();
|
||||
static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
|
||||
}
|
||||
|
||||
cairo_user_data_key_t kDrawTargetForSurface;
|
||||
static void
|
||||
DataDrawTargetDestroy(void *aTarget)
|
||||
{
|
||||
static_cast<DrawTarget*>(aTarget)->Release();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
// If we have already created a thebes surface, we can just return it.
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
cairo_surface_t* csurf =
|
||||
static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
|
||||
surf = gfxASurface::Wrap(csurf);
|
||||
} else {
|
||||
// The semantics of this part of the function are sort of weird. If we
|
||||
// don't have direct support for the backend, we snapshot the first time
|
||||
// and then return the snapshotted surface for the lifetime of the draw
|
||||
// target. Sometimes it seems like this works out, but it seems like it
|
||||
// might result in no updates ever.
|
||||
RefPtr<SourceSurface> source = aTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> data = source->GetDataSurface();
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntSize size = data->GetSize();
|
||||
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
|
||||
|
||||
// We need to make a copy here because data might change its data under us
|
||||
nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
|
||||
|
||||
bool resultOfCopy = imageSurf->CopyFrom(source);
|
||||
NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
|
||||
surf = imageSurf;
|
||||
return gfxASurface::Wrap(csurf);
|
||||
}
|
||||
|
||||
// add a reference to be held by the drawTarget
|
||||
// careful, the reference graph is getting complicated here
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
// The semantics of this part of the function are sort of weird. If we
|
||||
// don't have direct support for the backend, we snapshot the first time
|
||||
// and then return the snapshotted surface for the lifetime of the draw
|
||||
// target. Sometimes it seems like this works out, but it seems like it
|
||||
// might result in no updates ever.
|
||||
RefPtr<SourceSurface> source = aTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> data = source->GetDataSurface();
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntSize size = data->GetSize();
|
||||
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
|
||||
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
|
||||
data->Stride(), format);
|
||||
|
||||
surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
|
||||
// keep the draw target alive as long as we need its data
|
||||
aTarget->AddRef();
|
||||
surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
|
||||
|
||||
return surf.forget();
|
||||
}
|
||||
|
@ -38,9 +38,6 @@ class gfxTextRun;
|
||||
class nsIURI;
|
||||
class nsIAtom;
|
||||
|
||||
extern mozilla::gfx::UserDataKey kThebesSurfaceKey;
|
||||
void DestroyThebesSurface(void *data);
|
||||
|
||||
extern cairo_user_data_key_t kDrawTarget;
|
||||
|
||||
// pref lang id's for font prefs
|
||||
@ -175,9 +172,12 @@ public:
|
||||
CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize);
|
||||
|
||||
/*
|
||||
* Creates a SourceSurface for a gfxASurface. This surface should -not- be
|
||||
* held around by the user after the underlying gfxASurface has been
|
||||
* destroyed as a copy of the data is not guaranteed.
|
||||
* Creates a SourceSurface for a gfxASurface. This function does no caching,
|
||||
* so the caller should cache the gfxASurface if it will be used frequently.
|
||||
* The returned surface keeps a reference to aTarget, so it is OK to keep the
|
||||
* surface, even if aTarget changes.
|
||||
* aTarget should not keep a reference to the returned surface because that
|
||||
* will cause a cycle.
|
||||
*/
|
||||
virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
|
||||
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
|
||||
|
@ -380,26 +380,16 @@ already_AddRefed<gfxASurface>
|
||||
gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
|
||||
return surf.forget();
|
||||
} else {
|
||||
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
|
||||
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
|
||||
|
||||
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
|
||||
IntSize intSize = aTarget->GetSize();
|
||||
gfxIntSize size(intSize.width, intSize.height);
|
||||
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
|
||||
IntSize intSize = aTarget->GetSize();
|
||||
gfxIntSize size(intSize.width, intSize.height);
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxQuartzSurface(cg, size);
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxQuartzSurface(cg, size);
|
||||
|
||||
// add a reference to be held by the drawTarget
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
|
||||
return surf.forget();
|
||||
}
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
|
@ -809,40 +809,26 @@ gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
if (aTarget->GetType() == BACKEND_DIRECT2D) {
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
|
||||
return surf.forget();
|
||||
} else {
|
||||
if (!GetD2DDevice()) {
|
||||
// We no longer have a D2D device, can't do this.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Texture2D> texture =
|
||||
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
|
||||
|
||||
if (!texture) {
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
}
|
||||
|
||||
aTarget->Flush();
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
|
||||
|
||||
// add a reference to be held by the drawTarget
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
/* "It might be worth it to clear cairo surfaces associated with a drawtarget.
|
||||
The strong reference means for example for D2D that cairo's scratch surface
|
||||
will be kept alive (well after a user being done) and consume extra VRAM.
|
||||
We can deal with this in a follow-up though." */
|
||||
|
||||
// shouldn't this hold a reference?
|
||||
surf->SetData(&kDrawTarget, aTarget, NULL);
|
||||
return surf.forget();
|
||||
if (!GetD2DDevice()) {
|
||||
// We no longer have a D2D device, can't do this.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Texture2D> texture =
|
||||
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
|
||||
|
||||
if (!texture) {
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
}
|
||||
|
||||
aTarget->Flush();
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
|
||||
|
||||
// shouldn't this hold a reference?
|
||||
surf->SetData(&kDrawTarget, aTarget, NULL);
|
||||
return surf.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user