Bug 940455 - Add LayerManager functonality to clear out a portion of the window for the OS to paint. r=roc,Bas

This commit is contained in:
Matt Woodrow 2014-02-13 13:20:41 +13:00
parent b14644234b
commit e638200a0e
16 changed files with 6449 additions and 5692 deletions

View File

@ -596,12 +596,19 @@ public:
bool IsInTransaction() const { return mInTransaction; }
virtual void SetRegionToClear(const nsIntRegion& aRegion)
{
mRegionToClear = aRegion;
}
protected:
nsRefPtr<Layer> mRoot;
gfx::UserData mUserData;
bool mDestroyed;
bool mSnapEffectiveTransforms;
nsIntRegion mRegionToClear;
// Print interesting information about this into aTo. Internally
// used to implement Dump*() and Log*().
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
@ -1335,6 +1342,7 @@ public:
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
void Mutated()
{
mManager->Mutated(this);

View File

@ -625,6 +625,16 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
}
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
if (!mRegionToClear.IsEmpty()) {
AutoSetOperator op(mTarget, gfxContext::OPERATOR_CLEAR);
nsIntRegionRectIterator iter(mRegionToClear);
const nsIntRect *r;
while ((r = iter.Next())) {
mTarget->NewPath();
mTarget->Rectangle(gfxRect(r->x, r->y, r->width, r->height));
mTarget->Fill();
}
}
if (mWidget) {
FlashWidgetUpdateArea(mTarget);
}

View File

@ -709,6 +709,30 @@ LayerManagerD3D10::Render(EndTransactionFlags aFlags)
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
if (!mRegionToClear.IsEmpty()) {
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
gfx::Matrix4x4 transform;
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64);
effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer");
nsIntRegionRectIterator iter(mRegionToClear);
const nsIntRect *r;
while ((r = iter.Next())) {
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
ShaderConstantRectD3D10(
(float)r->x,
(float)r->y,
(float)r->width,
(float)r->height)
);
technique->GetPassByIndex(0)->Apply(0);
device()->Draw(4, 0);
}
}
// See bug 630197 - we have some reasons to believe if an earlier call
// returned an error, the upcoming present call may raise an exception.
// This will check if any of the calls done recently has returned an error

View File

@ -448,6 +448,18 @@ technique10 RenderSolidColorLayer
}
}
technique10 RenderClearLayer
{
pass P0
{
SetRasterizerState( LayerRast );
SetBlendState( NoBlendDual, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
}
}
technique10 PrepareAlphaExtractionTextures
{
pass P0

File diff suppressed because it is too large Load Diff

View File

@ -261,6 +261,25 @@ LayerManagerD3D9::Render()
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
if (!mRegionToClear.IsEmpty()) {
D3DRECT* rects = new D3DRECT[mRegionToClear.GetNumRects()];
nsIntRegionRectIterator iter(mRegionToClear);
const nsIntRect *r;
size_t i = 0;
while ((r = iter.Next())) {
rects[i].x1 = r->x;
rects[i].y1 = r->y;
rects[i].x2 = r->x + r->width;
rects[i].y2 = r->y + r->height;
i++;
}
device()->Clear(i, rects, D3DCLEAR_TARGET,
0x00000000, 0, 0);
delete [] rects;
}
device()->EndScene();
if (!mTarget) {

View File

@ -16,6 +16,7 @@
struct nsRect;
struct nsIntRect;
struct nsIntSize;
class nsIntRegion;
struct nsFont;
struct nsIntMargin;
class nsPresContext;
@ -29,8 +30,8 @@ class nsIWidget;
// IID for the nsITheme interface
// {b0f3efe9-0bd4-4f6b-8daa-0ec7f6006822}
#define NS_ITHEME_IID \
{ 0x3ca584e6, 0xdcd6, 0x485b, \
{ 0x88, 0x8c, 0xe3, 0x47, 0x3d, 0xe4, 0xd9, 0x58 } }
{ 0x2e49c679, 0x2130, 0x432c, \
{ 0x92, 0xcb, 0xd4, 0x8e, 0x9a, 0xe2, 0x34, 0x75 } }
// {D930E29B-6909-44e5-AB4B-AF10D6923705}
#define NS_THEMERENDERER_CID \
{ 0x9020805b, 0x14a3, 0x4125, \
@ -62,7 +63,8 @@ public:
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect) = 0;
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear = nullptr) = 0;
/**
* Get the computed CSS border for the widget, in pixels.

View File

@ -3761,6 +3761,9 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
rc->Init(presContext->DeviceContext(), aContext);
nsIntRegion temp = builder->GetRegionToClear();
builder->ResetRegionToClear();
if (shouldDrawRectsSeparately) {
nsIntRegionRectIterator it(aRegionToDraw);
while (const nsIntRect* iterRect = it.Next()) {
@ -3802,6 +3805,12 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
if (!aRegionToInvalidate.IsEmpty()) {
aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
}
if (!builder->GetRegionToClear().IsEmpty()) {
aLayer->Manager()->SetRegionToClear(builder->GetRegionToClear());
}
builder->ResetRegionToClear();
builder->AddRegionToClear(temp);
}
bool

View File

@ -2431,6 +2431,7 @@ nsDisplayThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
PaintInternal(aBuilder, aCtx, mVisibleRect, nullptr);
}
void
nsDisplayThemedBackground::PaintInternal(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx, const nsRect& aBounds,
@ -2444,7 +2445,11 @@ nsDisplayThemedBackground::PaintInternal(nsDisplayListBuilder* aBuilder,
theme->GetWidgetOverflow(presContext->DeviceContext(), mFrame, mAppearance,
&drawing);
drawing.IntersectRect(drawing, aBounds);
theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing);
nsIntRegion clear;
theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing, &clear);
MOZ_ASSERT(clear.IsEmpty() || ReferenceFrame() == aBuilder->RootReferenceFrame(),
"Can't add to clear region if we're transformed!");
aBuilder->AddRegionToClear(clear);
}
bool nsDisplayThemedBackground::IsWindowActive()

View File

@ -641,6 +641,10 @@ public:
DisplayListClipState& ClipState() { return mClipState; }
void AddRegionToClear(const nsIntRegion& aRegion) { mRegionToClear.Or(mRegionToClear, aRegion); }
const nsIntRegion& GetRegionToClear() { return mRegionToClear; }
void ResetRegionToClear() { mRegionToClear.SetEmpty(); }
private:
void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aDirtyRect);
@ -674,6 +678,8 @@ private:
const nsIFrame* mCachedReferenceFrame;
nsPoint mCachedOffset;
nsRegion mExcludedGlassRegion;
// Area of the window (in pixels) to clear so the OS can draw them.
nsIntRegion mRegionToClear;
// The display item for the Windows window glass background, if any
nsDisplayItem* mGlassDisplayItem;
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;

View File

@ -34,7 +34,8 @@ public:
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect);
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear);
NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,

View File

@ -2080,7 +2080,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect)
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;

View File

@ -752,7 +752,8 @@ nsNativeThemeGTK::DrawWidgetBackground(nsRenderingContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect)
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear)
{
GtkWidgetState state;
GtkThemeWidgetType gtkWidgetType;

View File

@ -24,7 +24,8 @@ public:
NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext,
nsIFrame* aFrame, uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect);
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear);
NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
uint8_t aWidgetType, nsIntMargin* aResult);

View File

@ -1536,7 +1536,8 @@ nsNativeThemeWin::DrawWidgetBackground(nsRenderingContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect)
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear)
{
HANDLE theme = GetTheme(aWidgetType);
if (!theme)
@ -1905,35 +1906,13 @@ RENDER_AGAIN:
{
// The caption buttons are drawn by the DWM, we just need to clear the area where they
// are because we might have drawn something above them (like a background-image).
ctx->Save();
ctx->ResetClip();
ctx->Translate(dr.TopLeft());
// Create a rounded rectangle to follow the buttons' look.
gfxRect buttonbox1(0.0, 0.0, dr.Width(), dr.Height() - 2.0);
gfxRect buttonbox2(1.0, dr.Height() - 2.0, dr.Width() - 1.0, 1.0);
gfxRect buttonbox3(2.0, dr.Height() - 1.0, dr.Width() - 3.0, 1.0);
gfxContext::GraphicsOperator currentOp = ctx->CurrentOperator();
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
// Each rectangle is drawn individually because OPERATOR_CLEAR takes
// the fallback path to cairo_d2d_acquire_dest if the area to fill
// is a complex region.
ctx->NewPath();
ctx->Rectangle(buttonbox1, true);
ctx->Fill();
ctx->NewPath();
ctx->Rectangle(buttonbox2, true);
ctx->Fill();
ctx->NewPath();
ctx->Rectangle(buttonbox3, true);
ctx->Fill();
ctx->Restore();
ctx->SetOperator(currentOp);
NS_ASSERTION(aRegionToClear, "Must have a clear region to set!");
if (aRegionToClear) {
// Create a rounded rectangle to follow the buttons' look.
*aRegionToClear = nsIntRect(dr.X(), dr.Y(), dr.Width(), dr.Height() - 2.0);
aRegionToClear->Or(*aRegionToClear, nsIntRect(dr.X() + 1.0, dr.YMost() - 2.0, dr.Width() - 1.0, 1.0));
aRegionToClear->Or(*aRegionToClear, nsIntRect(dr.X() + 2.0, dr.YMost() - 1.0, dr.Width() - 3.0, 1.0));
}
}
nativeDrawing.EndNativeDrawing();

View File

@ -31,7 +31,8 @@ public:
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect);
const nsRect& aDirtyRect,
nsIntRegion* aRegionToClear);
NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext,
nsIFrame* aFrame,