Bug 363861. Part 1: Introduce gfxContext::PushGroupAndCopyBackground and use it to create opaque temporary surfaces for opacity groups which will be composited onto opaque surfaces. r=jrmuizel,sr=vlad,a=blocking

This commit is contained in:
Robert O'Callahan 2011-01-03 14:48:08 +13:00
parent fed25cbda0
commit a5295c29ab
3 changed files with 34 additions and 2 deletions

View File

@ -488,7 +488,7 @@ BasicThebesLayer::Paint(gfxContext* aContext,
target->Save();
gfxUtils::ClipToRegionSnapped(target, toDraw);
if (opacity != 1.0) {
target->PushGroup(contentType);
target->PushGroupAndCopyBackground(contentType);
}
aCallback(this, target, toDraw, nsIntRegion(), aCallbackData);
if (opacity != 1.0) {
@ -1306,7 +1306,7 @@ BasicLayerManager::PaintLayer(Layer* aLayer,
gfxASurface::gfxContentType type = aLayer->CanUseOpaqueSurface()
? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
mTarget->PushGroup(type);
mTarget->PushGroupAndCopyBackground(type);
}
/* Only paint ourself, or our children - This optimization relies on this! */

View File

@ -746,6 +746,26 @@ gfxContext::PushGroup(gfxASurface::gfxContentType content)
cairo_push_group_with_content(mCairo, (cairo_content_t) content);
}
void
gfxContext::PushGroupAndCopyBackground(gfxASurface::gfxContentType content)
{
if (content == gfxASurface::CONTENT_COLOR_ALPHA) {
cairo_surface_t *s = cairo_get_group_target(mCairo);
if (cairo_surface_get_content(s) == CAIRO_CONTENT_COLOR) {
cairo_push_group_with_content(mCairo, CAIRO_CONTENT_COLOR);
cairo_surface_t *d = cairo_get_group_target(mCairo);
cairo_t *cr = cairo_create(d);
cairo_set_source_surface(cr, s, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_destroy(cr);
return;
}
}
cairo_push_group_with_content(mCairo, (cairo_content_t) content);
}
already_AddRefed<gfxPattern>
gfxContext::PopGroup()
{

View File

@ -595,6 +595,18 @@ public:
* Groups
*/
void PushGroup(gfxASurface::gfxContentType content = gfxASurface::CONTENT_COLOR);
/**
* Like PushGroup, but if the current surface is CONTENT_COLOR and
* content is CONTENT_COLOR_ALPHA, makes the pushed surface CONTENT_COLOR
* instead and copies the contents of the current surface to the pushed
* surface. This is good for pushing opacity groups, since blending the
* group back to the current surface with some alpha applied will give
* the correct results and using an opaque pushed surface gives better
* quality and performance.
* This API really only makes sense if you do a PopGroupToSource and
* immediate Paint with OPERATOR_OVER.
*/
void PushGroupAndCopyBackground(gfxASurface::gfxContentType content = gfxASurface::CONTENT_COLOR);
already_AddRefed<gfxPattern> PopGroup();
void PopGroupToSource();