Bug 717921. Only have one thebes surface. r=bas

This commit is contained in:
Jeff Muizelaar 2012-01-13 09:48:29 -05:00
parent 6b29881ab3
commit 8369528d31
4 changed files with 73 additions and 24 deletions

View File

@ -532,9 +532,26 @@ DataSourceSurfaceDestroy(void *dataSourceSurface)
static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
}
void DestroyThebesSurface(void *data)
{
gfxASurface *surface = static_cast<gfxASurface*>(data);
surface->Release();
}
UserDataKey ThebesSurfaceKey;
// The semantics of this function are sort of weird. We snapshot the first
// time and then return the snapshotted surface for the lifetime of the
// draw target
already_AddRefed<gfxASurface>
gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
void *surface = aTarget->GetUserData(&ThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
return surf.forget();
}
RefPtr<SourceSurface> source = aTarget->Snapshot();
RefPtr<DataSourceSurface> data = source->GetDataSurface();
@ -545,12 +562,18 @@ gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
IntSize size = data->GetSize();
gfxASurface::gfxImageFormat format = gfxASurface::FormatFromContent(ContentForFormat(data->GetFormat()));
nsRefPtr<gfxImageSurface> image =
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
data->Stride(), format);
image->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
return image.forget();
surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
// add a reference to be held by the drawTarget
// careful, the reference graph is getting complicated here
surf->AddRef();
aTarget->AddUserData(&ThebesSurfaceKey, surf.get(), DestroyThebesSurface);
return surf.forget();
}
RefPtr<DrawTarget>

View File

@ -71,6 +71,9 @@ class gfxTextRun;
class nsIURI;
class nsIAtom;
extern mozilla::gfx::UserDataKey ThebesSurfaceKey;
void DestroyThebesSurface(void *data);
extern cairo_user_data_key_t kDrawTarget;
// pref lang id's for font prefs

View File

@ -303,16 +303,26 @@ already_AddRefed<gfxASurface>
gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
void *surface = aTarget->GetUserData(&ThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
return surf.forget();
} else {
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);
return surf.forget();
// add a reference to be held by the drawTarget
surf->AddRef();
aTarget->AddUserData(&ThebesSurfaceKey, surf.get(), DestroyThebesSurface);
return surf.forget();
}
}
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);

View File

@ -507,22 +507,35 @@ gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
#ifdef XP_WIN
if (aTarget->GetType() == BACKEND_DIRECT2D) {
RefPtr<ID3D10Texture2D> texture =
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
void *surface = aTarget->GetUserData(&ThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
return surf.forget();
} else {
RefPtr<ID3D10Texture2D> texture =
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
if (!texture) {
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
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(&ThebesSurfaceKey, 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();
}
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