Bug 740200 - Azure content rendering on Linux; r=roc

This commit is contained in:
Anthony Jones 2013-09-19 16:29:51 +12:00
parent a26b4bab6d
commit 991b6d7e94
2 changed files with 95 additions and 14 deletions

View File

@ -8,10 +8,14 @@
#include "gfxXlibSurface.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxAlphaRecovery.h"
#include "cairo-xlib.h"
#include "cairo-xlib-xrender.h"
using namespace mozilla;
using namespace mozilla::gfx;
#if 0
#include <stdio.h>
#define NATIVE_DRAWING_NOTE(m) fprintf(stderr, m)
@ -134,8 +138,28 @@ gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
uint32_t flags,
Screen *screen, Visual *visual)
{
cairo_t *cr = ctx->GetCairo();
if (ctx->IsCairo()) {
return DrawCairo(ctx->GetCairo(), size, flags, screen, visual);
}
// We need to actually borrow the context because we want to read out the
// clip rectangles.
BorrowedCairoContext borrowed(ctx->GetDrawTarget());
if (!borrowed.mCairo) {
return false;
}
bool direct = DrawCairo(borrowed.mCairo, size, flags, screen, visual);
borrowed.Finish();
return direct;
}
bool
gfxXlibNativeRenderer::DrawCairo(cairo_t* cr, nsIntSize size,
uint32_t flags,
Screen *screen, Visual *visual)
{
/* Check that the target surface is an xlib surface. */
cairo_surface_t *target = cairo_get_group_target (cr);
if (cairo_surface_get_type (target) != CAIRO_SURFACE_TYPE_XLIB) {
@ -450,7 +474,6 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
result->mUniformColor = false;
}
bool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0;
gfxMatrix matrix = ctx->CurrentMatrix();
// We can only draw direct or onto a copied background if pixels align and
@ -488,7 +511,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
if (canDrawOverBackground &&
DrawDirect(ctx, size, flags, screen, visual))
return;
return;
}
nsIntRect drawingRect(nsIntPoint(0, 0), size);
@ -506,29 +529,56 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
int32_t(clipExtents.Width()),
int32_t(clipExtents.Height()));
drawingRect.IntersectRect(drawingRect, intExtents);
if (ctx->IsCairo()) {
nsRefPtr<gfxASurface> target(ctx->CurrentSurface());
DrawFallback(nullptr, ctx, target, size, drawingRect, canDrawOverBackground,
flags, screen, visual, result);
} else {
DrawTarget* drawTarget = ctx->GetDrawTarget();
if (!drawTarget) {
return;
}
nsRefPtr<gfxASurface> 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<gfxASurface> target = ctx->CurrentSurface();
nsRefPtr<gfxXlibSurface> tempXlibSurface =
CreateTempXlibSurface(target, drawingRect.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<gfxContext> tmpCtx;
bool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0;
if (!drawIsOpaque) {
tmpCtx = new gfxContext(tempXlibSurface);
if (method == eCopyBackground) {
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->SetSource(target, -(offset + matrix.GetTranslation()));
tmpCtx->SetSource(target, -(offset + ctx->CurrentMatrix().GetTranslation()));
// 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
@ -547,8 +597,16 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
}
if (method != eAlphaExtraction) {
ctx->SetSource(tempXlibSurface, offset);
ctx->Paint();
if (drawTarget) {
RefPtr<SourceSurface> 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));
} else {
ctx->SetSource(tempXlibSurface, offset);
ctx->Paint();
}
if (result) {
result->mSurface = tempXlibSurface;
/* fill in the result with what we know, which is really just what our
@ -576,8 +634,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
result ? &analysis : nullptr))
return;
ctx->SetSource(blackImage, offset);
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
@ -604,10 +661,18 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
copyCtx.Paint();
ctx->SetSource(result->mSurface);
paintSurface = result->mSurface;
}
}
ctx->Paint();
if (drawTarget) {
RefPtr<SourceSurface> 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));
} else {
ctx->SetSource(paintSurface, offset);
ctx->Paint();
}
}
}

View File

@ -10,12 +10,19 @@
#include "nsAutoPtr.h"
#include <X11/Xlib.h>
namespace mozilla {
namespace gfx {
class DrawTarget;
}
}
class gfxASurface;
class gfxXlibSurface;
class gfxContext;
struct nsIntRect;
struct nsIntPoint;
struct nsIntSize;
typedef struct _cairo cairo_t;
/**
* This class lets us take code that draws into an X drawable and lets us
@ -91,6 +98,15 @@ private:
bool DrawDirect(gfxContext *ctx, nsIntSize bounds,
uint32_t flags, Screen *screen, Visual *visual);
bool DrawCairo(cairo_t* cr, nsIntSize size,
uint32_t flags, Screen *screen, Visual *visual);
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);
bool DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface,
nsIntPoint offset);