diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 8444bbfa14e..46e7cdc4c27 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -2795,7 +2795,7 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext, Visual* visual = DefaultVisualOfScreen(screen); renderer.Draw(aContext, nsIntSize(window->width, window->height), - rendererFlags, screen, visual, nullptr); + rendererFlags, screen, visual); } nsresult nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface, diff --git a/gfx/thebes/gfxGdkNativeRenderer.cpp b/gfx/thebes/gfxGdkNativeRenderer.cpp index e3cfd0c72c5..c4d5397ff11 100644 --- a/gfx/thebes/gfxGdkNativeRenderer.cpp +++ b/gfx/thebes/gfxGdkNativeRenderer.cpp @@ -59,7 +59,7 @@ gfxGdkNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, Screen* screen = gdk_x11_screen_get_xscreen(gdk_colormap_get_screen(colormap)); - gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual, nullptr); + gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual); } #else diff --git a/gfx/thebes/gfxQtNativeRenderer.cpp b/gfx/thebes/gfxQtNativeRenderer.cpp index bfc32abcd8a..1f5e63afa47 100644 --- a/gfx/thebes/gfxQtNativeRenderer.cpp +++ b/gfx/thebes/gfxQtNativeRenderer.cpp @@ -9,8 +9,7 @@ nsresult gfxQtNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* output) + uint32_t flags, Screen* screen, Visual* visual) { Display *dpy = DisplayOfScreen(screen); bool isOpaque = (flags & DRAW_IS_OPAQUE) ? true : false; diff --git a/gfx/thebes/gfxQtNativeRenderer.h b/gfx/thebes/gfxQtNativeRenderer.h index bb55012fa22..8fb095a9a50 100644 --- a/gfx/thebes/gfxQtNativeRenderer.h +++ b/gfx/thebes/gfxQtNativeRenderer.h @@ -54,13 +54,6 @@ public: DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20 }; - struct DrawOutput { - nsRefPtr mSurface; - bool mUniformAlpha; - bool mUniformColor; - gfxRGBA mColor; - }; - /** * @param flags see above * @param size Draw()'s drawing is guaranteed to be restricted to @@ -72,8 +65,7 @@ public: * otherwise *resultSurface is set to nullptr. */ nsresult Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* output); + uint32_t flags, Screen* screen, Visual* visual); }; #endif /*GFXQTNATIVERENDER_H_*/ diff --git a/gfx/thebes/gfxXlibNativeRenderer.cpp b/gfx/thebes/gfxXlibNativeRenderer.cpp index 3368e50d133..61fae5fd2d2 100644 --- a/gfx/thebes/gfxXlibNativeRenderer.cpp +++ b/gfx/thebes/gfxXlibNativeRenderer.cpp @@ -13,6 +13,7 @@ #include "cairo-xlib.h" #include "cairo-xlib-xrender.h" #include "mozilla/gfx/BorrowedContext.h" +#include "gfx2DGlue.h" using namespace mozilla; using namespace mozilla::gfx; @@ -308,31 +309,34 @@ enum DrawingMethod { eAlphaExtraction }; -static already_AddRefed -CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, +static cairo_surface_t* +CreateTempXlibSurface (cairo_surface_t* cairoTarget, + DrawTarget* drawTarget, + nsIntSize size, bool canDrawOverBackground, uint32_t flags, Screen *screen, Visual *visual, DrawingMethod *method) { + NS_ASSERTION(cairoTarget || drawTarget, "Must have some type"); + bool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0; bool supportsAlternateVisual = (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0; bool supportsAlternateScreen = supportsAlternateVisual && (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN); - cairo_surface_t *target = destination->CairoSurface(); - cairo_surface_type_t target_type = cairo_surface_get_type (target); - cairo_content_t target_content = cairo_surface_get_content (target); + cairo_surface_type_t cairoTargetType = + cairoTarget ? cairo_surface_get_type (cairoTarget) : (cairo_surface_type_t)0xFF; - Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ? - cairo_xlib_surface_get_screen (target) : screen; + Screen *target_screen = cairoTargetType == CAIRO_SURFACE_TYPE_XLIB ? + cairo_xlib_surface_get_screen (cairoTarget) : screen; // When the background has an alpha channel, we need to draw with an alpha // channel anyway, so there is no need to copy the background. If // doCopyBackground is set here, we'll also need to check below that the // background can copied without any loss in format conversions. bool doCopyBackground = !drawIsOpaque && canDrawOverBackground && - target_content == CAIRO_CONTENT_COLOR; + cairoTarget && cairo_surface_get_content (cairoTarget) == CAIRO_CONTENT_COLOR; if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) { // Prefer a visual on the target screen. @@ -346,14 +350,13 @@ CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, // opaque drawing. Visual *target_visual = nullptr; XRenderPictFormat *target_format = nullptr; - switch (target_type) { - case CAIRO_SURFACE_TYPE_XLIB: - target_visual = cairo_xlib_surface_get_visual (target); - target_format = cairo_xlib_surface_get_xrender_format (target); - break; - case CAIRO_SURFACE_TYPE_IMAGE: { + if (cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) { + target_visual = cairo_xlib_surface_get_visual (cairoTarget); + target_format = cairo_xlib_surface_get_xrender_format (cairoTarget); + } else if (cairoTargetType == CAIRO_SURFACE_TYPE_IMAGE || drawTarget) { gfxImageFormat imageFormat = - static_cast(destination)->Format(); + drawTarget ? SurfaceFormatToImageFormat(drawTarget->GetFormat()) : + (gfxImageFormat)cairo_image_surface_get_format(cairoTarget); target_visual = gfxXlibSurface::FindVisual(screen, imageFormat); Display *dpy = DisplayOfScreen(screen); if (target_visual) { @@ -362,10 +365,6 @@ CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, target_format = gfxXlibSurface::FindRenderFormat(dpy, imageFormat); } - break; - } - default: - break; } if (supportsAlternateVisual && @@ -412,16 +411,19 @@ CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, } Drawable drawable = - (screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ? - cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen); + (screen == target_screen && cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) ? + cairo_xlib_surface_get_drawable (cairoTarget) : RootWindowOfScreen(screen); - nsRefPtr surface = - gfxXlibSurface::Create(screen, visual, - gfxIntSize(size.width, size.height), - drawable); + cairo_surface_t *surface = + gfxXlibSurface::CreateCairoSurface(screen, visual, + gfxIntSize(size.width, size.height), + drawable); + if (!surface) { + return nullptr; + } if (drawIsOpaque || - surface->GetContentType() == GFX_CONTENT_COLOR_ALPHA) { + cairo_surface_get_content(surface) == CAIRO_CONTENT_COLOR_ALPHA) { NATIVE_DRAWING_NOTE(drawIsOpaque ? ", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA"); *method = eSimple; @@ -433,47 +435,41 @@ CreateTempXlibSurface (gfxASurface *destination, nsIntSize size, *method = eAlphaExtraction; } - return surface.forget(); + return surface; } bool -gfxXlibNativeRenderer::DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface, +gfxXlibNativeRenderer::DrawOntoTempSurface(cairo_surface_t *tempXlibSurface, nsIntPoint offset) { - tempXlibSurface->Flush(); + cairo_surface_flush(tempXlibSurface); /* no clipping is needed because the callback can't draw outside the native surface anyway */ - nsresult rv = DrawWithXlib(tempXlibSurface->CairoSurface(), offset, nullptr, 0); - tempXlibSurface->MarkDirty(); + nsresult rv = DrawWithXlib(tempXlibSurface, offset, nullptr, 0); + cairo_surface_mark_dirty(tempXlibSurface); return NS_SUCCEEDED(rv); } static already_AddRefed -CopyXlibSurfaceToImage(gfxXlibSurface *tempXlibSurface, +CopyXlibSurfaceToImage(cairo_surface_t *tempXlibSurface, + gfxIntSize size, gfxImageFormat format) { - nsRefPtr result = - new gfxImageSurface(tempXlibSurface->GetSize(), format); + nsRefPtr result = new gfxImageSurface(size, format); - gfxContext copyCtx(result); - copyCtx.SetSource(tempXlibSurface); - copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE); - copyCtx.Paint(); + cairo_t* copyCtx = cairo_create(result->CairoSurface()); + cairo_set_source_surface(copyCtx, tempXlibSurface, 0, 0); + cairo_set_operator(copyCtx, CAIRO_OPERATOR_SOURCE); + cairo_paint(copyCtx); + cairo_destroy(copyCtx); return result.forget(); } void gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen *screen, Visual *visual, - DrawOutput* result) + uint32_t flags, Screen *screen, Visual *visual) { - if (result) { - result->mSurface = nullptr; - result->mUniformAlpha = false; - result->mUniformColor = false; - } - gfxMatrix matrix = ctx->CurrentMatrix(); // We can only draw direct or onto a copied background if pixels align and @@ -530,149 +526,110 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size, int32_t(clipExtents.Height())); drawingRect.IntersectRect(drawingRect, intExtents); - if (ctx->IsCairo()) { - nsRefPtr target(ctx->CurrentSurface()); - DrawFallback(nullptr, ctx, target, size, drawingRect, canDrawOverBackground, - flags, screen, visual, result); - } else { - DrawTarget* drawTarget = ctx->GetDrawTarget(); - if (!drawTarget) { - return; - } - - nsRefPtr target = gfxPlatform::GetPlatform()-> - GetThebesSurfaceForDrawTarget(drawTarget); - if (!target) { - return; - } - DrawFallback(drawTarget, ctx, target, size, drawingRect, canDrawOverBackground, - flags, screen, visual, result); - } -} - -void -gfxXlibNativeRenderer::DrawFallback(DrawTarget* drawTarget, gfxContext* ctx, gfxASurface* target, - nsIntSize& size, nsIntRect& drawingRect, - bool canDrawOverBackground, uint32_t flags, - Screen* screen, Visual* visual, DrawOutput* result) -{ gfxPoint offset(drawingRect.x, drawingRect.y); DrawingMethod method; - nsRefPtr tempXlibSurface = - CreateTempXlibSurface(target, drawingRect.Size(), + cairo_surface_t* cairoTarget = nullptr; + DrawTarget* drawTarget = nullptr; + if (ctx->IsCairo()) { + cairoTarget = cairo_get_group_target(ctx->GetCairo()); + } else { + drawTarget = ctx->GetDrawTarget(); + cairoTarget = static_cast + (drawTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE)); + } + + cairo_surface_t* tempXlibSurface = + CreateTempXlibSurface(cairoTarget, drawTarget, size, canDrawOverBackground, flags, screen, visual, &method); if (!tempXlibSurface) return; - if (drawingRect.Size() != size || method == eCopyBackground) { - // Only drawing a portion, or copying background, - // so won't return a result. - result = nullptr; - } - - nsRefPtr tmpCtx; bool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0; if (!drawIsOpaque) { - tmpCtx = new gfxContext(tempXlibSurface); + cairo_t* tmpCtx = cairo_create(tempXlibSurface); if (method == eCopyBackground) { - tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpCtx->SetSource(target, -(offset + ctx->CurrentMatrix().GetTranslation())); + NS_ASSERTION(cairoTarget, "eCopyBackground only used when there's a cairoTarget"); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE); + gfxPoint pt = -(offset + ctx->CurrentMatrix().GetTranslation()); + cairo_set_source_surface(tmpCtx, cairoTarget, pt.x, pt.y); // The copy from the tempXlibSurface to the target context should // use operator SOURCE, but that would need a mask to bound the // operation. Here we only copy opaque backgrounds so operator // OVER will behave like SOURCE masked by the surface. - NS_ASSERTION(tempXlibSurface->GetContentType() - == GFX_CONTENT_COLOR, + NS_ASSERTION(cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR, "Don't copy background with a transparent surface"); } else { - tmpCtx->SetOperator(gfxContext::OPERATOR_CLEAR); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_CLEAR); } - tmpCtx->Paint(); + cairo_paint(tmpCtx); + cairo_destroy(tmpCtx); } if (!DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft())) { + cairo_surface_destroy(tempXlibSurface); return; } + SurfaceFormat moz2DFormat = + cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR ? + FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8; if (method != eAlphaExtraction) { if (drawTarget) { - RefPtr sourceSurface = gfxPlatform::GetPlatform()-> - GetSourceSurfaceForSurface(drawTarget, tempXlibSurface); - drawTarget->DrawSurface(sourceSurface, - Rect(offset.x, offset.y, size.width, size.height), - Rect(0, 0, size.width, size.height)); + // It doesn't matter if moz2DFormat doesn't exactly match the format + // of tempXlibSurface, since this DrawTarget just wraps the cairo + // drawing. + RefPtr sourceSurface = + Factory::CreateSourceSurfaceForCairoSurface(tempXlibSurface, + moz2DFormat); + if (sourceSurface) { + drawTarget->DrawSurface(sourceSurface, + Rect(offset.x, offset.y, size.width, size.height), + Rect(0, 0, size.width, size.height)); + } } else { - ctx->SetSource(tempXlibSurface, offset); + nsRefPtr tmpSurf = gfxASurface::Wrap(tempXlibSurface); + ctx->SetSource(tmpSurf, offset); ctx->Paint(); } - if (result) { - result->mSurface = tempXlibSurface; - /* fill in the result with what we know, which is really just what our - assumption was */ - result->mUniformAlpha = true; - result->mColor.a = 1.0; - } + cairo_surface_destroy(tempXlibSurface); return; } nsRefPtr blackImage = - CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatARGB32); + CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatARGB32); - tmpCtx->SetDeviceColor(gfxRGBA(1.0, 1.0, 1.0)); - tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpCtx->Paint(); + cairo_t* tmpCtx = cairo_create(tempXlibSurface); + cairo_set_source_rgba(tmpCtx, 1.0, 1.0, 1.0, 1.0); + cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE); + cairo_paint(tmpCtx); + cairo_destroy(tmpCtx); DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft()); nsRefPtr whiteImage = - CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatRGB24); + CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatRGB24); if (blackImage->CairoStatus() == CAIRO_STATUS_SUCCESS && whiteImage->CairoStatus() == CAIRO_STATUS_SUCCESS) { - gfxAlphaRecovery::Analysis analysis; - if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage, - result ? &analysis : nullptr)) + if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage, nullptr)) { + cairo_surface_destroy(tempXlibSurface); return; + } gfxASurface* paintSurface = blackImage; - /* if the caller wants to retrieve the rendered image, put it into - a 'similar' surface, and use that as the source for the drawing right - now. This means we always return a surface similar to the surface - used for 'cr', which is ideal if it's going to be cached and reused. - We do not return an image if the result has uniform color (including - alpha). */ - if (result) { - if (analysis.uniformAlpha) { - result->mUniformAlpha = true; - result->mColor.a = analysis.alpha; - } - if (analysis.uniformColor) { - result->mUniformColor = true; - result->mColor.r = analysis.r; - result->mColor.g = analysis.g; - result->mColor.b = analysis.b; - } else { - result->mSurface = target-> - CreateSimilarSurface(GFX_CONTENT_COLOR_ALPHA, - gfxIntSize(size.width, size.height)); - - gfxContext copyCtx(result->mSurface); - copyCtx.SetSource(blackImage); - copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE); - copyCtx.Paint(); - - paintSurface = result->mSurface; - } - } if (drawTarget) { - RefPtr sourceSurface = gfxPlatform::GetPlatform()-> - GetSourceSurfaceForSurface(drawTarget, paintSurface); - drawTarget->DrawSurface(sourceSurface, - Rect(offset.x, offset.y, size.width, size.height), - Rect(0, 0, size.width, size.height)); + RefPtr sourceSurface = + Factory::CreateSourceSurfaceForCairoSurface(paintSurface->CairoSurface(), + moz2DFormat); + if (sourceSurface) { + drawTarget->DrawSurface(sourceSurface, + Rect(offset.x, offset.y, size.width, size.height), + Rect(0, 0, size.width, size.height)); + } } else { ctx->SetSource(paintSurface, offset); ctx->Paint(); } } + cairo_surface_destroy(tempXlibSurface); } diff --git a/gfx/thebes/gfxXlibNativeRenderer.h b/gfx/thebes/gfxXlibNativeRenderer.h index 6ed662540fa..a6e816b5710 100644 --- a/gfx/thebes/gfxXlibNativeRenderer.h +++ b/gfx/thebes/gfxXlibNativeRenderer.h @@ -6,8 +6,8 @@ #ifndef GFXXLIBNATIVERENDER_H_ #define GFXXLIBNATIVERENDER_H_ -#include "gfxColor.h" -#include "nsAutoPtr.h" +#include "nsPoint.h" +#include "nsRect.h" #include namespace mozilla { @@ -17,12 +17,12 @@ namespace gfx { } class gfxASurface; -class gfxXlibSurface; class gfxContext; struct nsIntRect; struct nsIntPoint; struct nsIntSize; typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; /** * This class lets us take code that draws into an X drawable and lets us @@ -70,13 +70,6 @@ public: DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20 }; - struct DrawOutput { - nsRefPtr mSurface; - bool mUniformAlpha; - bool mUniformColor; - gfxRGBA mColor; - }; - /** * @param flags see above * @param size the size of the rectangle being drawn; @@ -90,8 +83,7 @@ public: * otherwise *resultSurface is set to nullptr. */ void Draw(gfxContext* ctx, nsIntSize size, - uint32_t flags, Screen *screen, Visual *visual, - DrawOutput* result); + uint32_t flags, Screen *screen, Visual *visual); private: bool DrawDirect(gfxContext *ctx, nsIntSize bounds, @@ -103,10 +95,9 @@ private: void DrawFallback(mozilla::gfx::DrawTarget* dt, gfxContext* ctx, gfxASurface* aSurface, nsIntSize& size, nsIntRect& drawingRect, bool canDrawOverBackground, - uint32_t flags, Screen* screen, Visual* visual, - DrawOutput* result); + uint32_t flags, Screen* screen, Visual* visual); - bool DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface, + bool DrawOntoTempSurface(cairo_surface_t *tempXlibSurface, nsIntPoint offset); };