app_server: Clip alpha masks to canvas size
* Making the alpha masks independent of view size is a good thing, however it turns out that I was too optimistic about the consequences: webkit sometimes sets masks for the whole page, not just the currently visible area. E.g. on Github diff views, it was seen to set a clipping path which is about 1,000 x 10,000 pixels in size. Generating these huge masks eats up lots of memory and time. * We now clip the alpha masks to the current view size. This introduces a dependency between mask and view again, however a weaker one than it used to be before the mask rework. When the view is enlarged, and the alpha mask was previously clipped during rendering, we regenerate it at the new size. When the view is shrunk however, we don't do anything and just keep the now larger than necessary mask around (so we don't have to regenerate again when the view is subsequently enlarged again -- except if it then becomes even larger than it used to be). Changing the view origin is unaffected and still doesn't cause a regenerate.
This commit is contained in:
parent
c37db53b57
commit
e718dc9178
@ -289,10 +289,11 @@ Canvas::BlendLayer(Layer* layer)
|
||||
|
||||
|
||||
OffscreenCanvas::OffscreenCanvas(DrawingEngine* engine,
|
||||
const DrawState& state)
|
||||
const DrawState& state, const IntRect& bounds)
|
||||
:
|
||||
Canvas(state),
|
||||
fDrawingEngine(engine)
|
||||
fDrawingEngine(engine),
|
||||
fBounds(bounds)
|
||||
{
|
||||
ResyncDrawState();
|
||||
}
|
||||
@ -313,3 +314,10 @@ OffscreenCanvas::UpdateCurrentDrawingRegion()
|
||||
fDrawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IntRect
|
||||
OffscreenCanvas::Bounds() const
|
||||
{
|
||||
return fBounds;
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
void SetAlphaMask(AlphaMask* mask);
|
||||
AlphaMask* GetAlphaMask() const;
|
||||
|
||||
virtual IntRect Bounds() const = 0;
|
||||
|
||||
SimpleTransform LocalToScreenTransform() const;
|
||||
SimpleTransform ScreenToLocalTransform() const;
|
||||
SimpleTransform PenToScreenTransform() const;
|
||||
@ -88,7 +90,7 @@ protected:
|
||||
class OffscreenCanvas : public Canvas {
|
||||
public:
|
||||
OffscreenCanvas(DrawingEngine* engine,
|
||||
const DrawState& state);
|
||||
const DrawState& state, const IntRect& bounds);
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; }
|
||||
|
||||
@ -97,6 +99,7 @@ public:
|
||||
virtual void UpdateCurrentDrawingRegion();
|
||||
virtual ServerPicture* GetPicture(int32 token) const
|
||||
{ /* TODO */ return NULL; }
|
||||
virtual IntRect Bounds() const;
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(SimpleTransform&) const {}
|
||||
@ -105,6 +108,7 @@ protected:
|
||||
private:
|
||||
DrawingEngine* fDrawingEngine;
|
||||
BRegion fCurrentDrawingRegion;
|
||||
IntRect fBounds;
|
||||
};
|
||||
|
||||
|
||||
|
@ -60,6 +60,11 @@ public:
|
||||
fDrawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
|
||||
}
|
||||
|
||||
virtual IntRect Bounds() const
|
||||
{
|
||||
return fBitmapBounds;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(SimpleTransform&) const
|
||||
{
|
||||
@ -142,7 +147,7 @@ Layer::RenderToBitmap(Canvas* canvas)
|
||||
IntPoint oldOffset;
|
||||
if (mask != NULL) {
|
||||
// Move alpha mask to bitmap origin
|
||||
oldOffset = mask->SetViewOrigin(IntPoint(0, 0));
|
||||
oldOffset = mask->SetCanvasGeometry(IntPoint(0, 0), boundingBox);
|
||||
}
|
||||
|
||||
canvas->CurrentState()->SetDrawingMode(B_OP_ALPHA);
|
||||
@ -164,7 +169,8 @@ Layer::RenderToBitmap(Canvas* canvas)
|
||||
// Note: this needs to be adapted if setting alpha masks is
|
||||
// implemented as BPicture command (the mask now might be a different
|
||||
// one than before).
|
||||
mask->SetViewOrigin(oldOffset);
|
||||
layerCanvas.CurrentState()->CombinedTransform().Apply(oldOffset);
|
||||
mask->SetCanvasGeometry(oldOffset, boundingBox);
|
||||
layerCanvas.ResyncDrawState();
|
||||
}
|
||||
|
||||
|
@ -799,8 +799,11 @@ clip_to_rect(void* _canvas, const BRect& rect, bool inverse)
|
||||
{
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
bool needDrawStateUpdate = canvas->ClipToRect(rect, inverse);
|
||||
if (needDrawStateUpdate)
|
||||
if (needDrawStateUpdate) {
|
||||
canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
|
||||
canvas->Bounds());
|
||||
canvas->ResyncDrawState();
|
||||
}
|
||||
canvas->UpdateCurrentDrawingRegion();
|
||||
}
|
||||
|
||||
@ -824,6 +827,8 @@ clip_to_shape(void* _canvas, int32 opCount, const uint32 opList[],
|
||||
shapeData.ptSize = ptCount * sizeof(BPoint);
|
||||
|
||||
canvas->ClipToShape(&shapeData, inverse);
|
||||
canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
|
||||
canvas->Bounds());
|
||||
canvas->ResyncDrawState();
|
||||
|
||||
free(shapeData.opList);
|
||||
|
@ -3983,7 +3983,7 @@ ServerWindow::_UpdateDrawState(View* view)
|
||||
BPoint leftTop(0, 0);
|
||||
if (view->GetAlphaMask() != NULL) {
|
||||
view->LocalToScreenTransform().Apply(&leftTop);
|
||||
view->GetAlphaMask()->SetViewOrigin(leftTop);
|
||||
view->GetAlphaMask()->SetCanvasGeometry(leftTop, view->Bounds());
|
||||
leftTop = BPoint(0, 0);
|
||||
}
|
||||
view->PenToScreenTransform().Apply(&leftTop);
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
|
||||
IntRect Frame() const
|
||||
{ return fFrame; }
|
||||
IntRect Bounds() const;
|
||||
virtual IntRect Bounds() const;
|
||||
|
||||
void SetResizeMode(uint32 resizeMode)
|
||||
{ fResizeMode = resizeMode; }
|
||||
|
@ -29,7 +29,9 @@ AlphaMask::AlphaMask(AlphaMask* previousMask, bool inverse)
|
||||
:
|
||||
fPreviousMask(previousMask),
|
||||
fBounds(),
|
||||
fViewOrigin(),
|
||||
fClippedToCanvas(true),
|
||||
fCanvasOrigin(),
|
||||
fCanvasBounds(),
|
||||
fInverse(inverse),
|
||||
fBackgroundOpacity(0),
|
||||
fBits(NULL),
|
||||
@ -44,7 +46,9 @@ AlphaMask::AlphaMask(uint8 backgroundOpacity)
|
||||
:
|
||||
fPreviousMask(),
|
||||
fBounds(),
|
||||
fViewOrigin(),
|
||||
fClippedToCanvas(true),
|
||||
fCanvasOrigin(),
|
||||
fCanvasBounds(),
|
||||
fInverse(false),
|
||||
fBackgroundOpacity(backgroundOpacity),
|
||||
fBits(NULL),
|
||||
@ -62,18 +66,30 @@ AlphaMask::~AlphaMask()
|
||||
|
||||
|
||||
IntPoint
|
||||
AlphaMask::SetViewOrigin(IntPoint viewOrigin)
|
||||
AlphaMask::SetCanvasGeometry(IntPoint origin, IntRect bounds)
|
||||
{
|
||||
if (viewOrigin == fViewOrigin)
|
||||
return fViewOrigin;
|
||||
if (origin == fCanvasOrigin && bounds.Width() == fCanvasBounds.Width()
|
||||
&& bounds.Height() == fCanvasBounds.Height())
|
||||
return fCanvasOrigin;
|
||||
|
||||
IntPoint oldOrigin = fViewOrigin;
|
||||
fViewOrigin = viewOrigin;
|
||||
IntPoint oldOrigin = fCanvasOrigin;
|
||||
fCanvasOrigin = origin;
|
||||
IntRect oldBounds = fCanvasBounds;
|
||||
fCanvasBounds = IntRect(0, 0, bounds.Width(), bounds.Height());
|
||||
|
||||
if (fClippedToCanvas && (fCanvasBounds.Width() > oldBounds.Width()
|
||||
|| fCanvasBounds.Height() > oldBounds.Height())) {
|
||||
// The canvas is now larger than before and we previously
|
||||
// drew the alpha mask clipped to the (old) bounds of the
|
||||
// canvas. So we now have to redraw the alpha mask with the
|
||||
// new size.
|
||||
_Generate();
|
||||
}
|
||||
|
||||
_AttachMaskToBuffer();
|
||||
|
||||
if (fPreviousMask != NULL)
|
||||
fPreviousMask->SetViewOrigin(viewOrigin);
|
||||
fPreviousMask->SetCanvasGeometry(origin, bounds);
|
||||
|
||||
return oldOrigin;
|
||||
}
|
||||
@ -101,7 +117,7 @@ AlphaMask::_CreateTemporaryBitmap(BRect bounds) const
|
||||
void
|
||||
AlphaMask::_Generate()
|
||||
{
|
||||
ServerBitmap* const bitmap = _RenderSource();
|
||||
ServerBitmap* const bitmap = _RenderSource(fCanvasBounds);
|
||||
BReference<ServerBitmap> bitmapRef(bitmap, true);
|
||||
if (bitmap == NULL) {
|
||||
_SetNoClipping();
|
||||
@ -156,6 +172,13 @@ AlphaMask::_SetNoClipping()
|
||||
}
|
||||
|
||||
|
||||
const IntRect&
|
||||
AlphaMask::_PreviousMaskBounds() const
|
||||
{
|
||||
return fPreviousMask->fBounds;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::_AttachMaskToBuffer()
|
||||
{
|
||||
@ -172,8 +195,8 @@ AlphaMask::_AttachMaskToBuffer()
|
||||
}
|
||||
|
||||
const IntPoint maskOffset = _Offset();
|
||||
const int32 offsetX = fBounds.left + maskOffset.x + fViewOrigin.x;
|
||||
const int32 offsetY = fBounds.top + maskOffset.y + fViewOrigin.y;
|
||||
const int32 offsetX = fBounds.left + maskOffset.x + fCanvasOrigin.x;
|
||||
const int32 offsetY = fBounds.top + maskOffset.y + fCanvasOrigin.y;
|
||||
|
||||
fMask.attach(fBuffer, offsetX, offsetY, outsideOpacity);
|
||||
}
|
||||
@ -192,7 +215,7 @@ UniformAlphaMask::UniformAlphaMask(uint8 opacity)
|
||||
|
||||
|
||||
ServerBitmap*
|
||||
UniformAlphaMask::_RenderSource()
|
||||
UniformAlphaMask::_RenderSource(const IntRect&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -220,11 +243,19 @@ VectorAlphaMask<VectorMaskType>::VectorAlphaMask(AlphaMask* previousMask,
|
||||
|
||||
template<class VectorMaskType>
|
||||
ServerBitmap*
|
||||
VectorAlphaMask<VectorMaskType>::_RenderSource()
|
||||
VectorAlphaMask<VectorMaskType>::_RenderSource(const IntRect& canvasBounds)
|
||||
{
|
||||
fBounds = static_cast<VectorMaskType*>(this)->DetermineBoundingBox();
|
||||
|
||||
if (fBounds.Width() > canvasBounds.Width()
|
||||
|| fBounds.Height() > canvasBounds.Height()) {
|
||||
fBounds = fBounds & canvasBounds;
|
||||
fClippedToCanvas = true;
|
||||
} else
|
||||
fClippedToCanvas = false;
|
||||
|
||||
if (fPreviousMask != NULL)
|
||||
fBounds = fBounds & fPreviousMask->fBounds;
|
||||
fBounds = fBounds & _PreviousMaskBounds();
|
||||
if (!fBounds.IsValid())
|
||||
return NULL;
|
||||
|
||||
@ -242,7 +273,7 @@ VectorAlphaMask<VectorMaskType>::_RenderSource()
|
||||
engine->SetRendererOffset(fBounds.left, fBounds.top);
|
||||
|
||||
OffscreenCanvas canvas(engine,
|
||||
static_cast<VectorMaskType*>(this)->GetDrawState());
|
||||
static_cast<VectorMaskType*>(this)->GetDrawState(), fBounds);
|
||||
|
||||
DrawState* const drawState = canvas.CurrentState();
|
||||
drawState->SetDrawingMode(B_OP_ALPHA);
|
||||
@ -286,7 +317,6 @@ PictureAlphaMask::PictureAlphaMask(AlphaMask* previousMask,
|
||||
fPicture(picture),
|
||||
fDrawState(new DrawState(drawState))
|
||||
{
|
||||
_Generate();
|
||||
}
|
||||
|
||||
|
||||
@ -340,8 +370,7 @@ ShapeAlphaMask::ShapeAlphaMask(AlphaMask* previousMask,
|
||||
fShape(shape),
|
||||
fDrawState()
|
||||
{
|
||||
fBounds = fShape.DetermineBoundingBox();
|
||||
_Generate();
|
||||
fShapeBounds = fShape.DetermineBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
@ -358,7 +387,7 @@ ShapeAlphaMask::DrawVectors(Canvas* canvas)
|
||||
BRect
|
||||
ShapeAlphaMask::DetermineBoundingBox() const
|
||||
{
|
||||
return fBounds;
|
||||
return fShapeBounds;
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
AlphaMask(uint8 backgroundOpacity);
|
||||
virtual ~AlphaMask();
|
||||
|
||||
IntPoint SetViewOrigin(IntPoint viewOrigin);
|
||||
IntPoint SetCanvasGeometry(IntPoint origin,
|
||||
IntRect bounds);
|
||||
|
||||
scanline_unpacked_masked_type* Scanline()
|
||||
{ return &fScanline; }
|
||||
@ -44,19 +45,22 @@ protected:
|
||||
ServerBitmap* _CreateTemporaryBitmap(BRect bounds) const;
|
||||
void _Generate();
|
||||
void _SetNoClipping();
|
||||
const IntRect& _PreviousMaskBounds() const;
|
||||
|
||||
private:
|
||||
virtual ServerBitmap* _RenderSource() = 0;
|
||||
virtual ServerBitmap* _RenderSource(const IntRect& canvasBounds) = 0;
|
||||
virtual IntPoint _Offset() = 0;
|
||||
|
||||
void _AttachMaskToBuffer();
|
||||
|
||||
public:
|
||||
protected:
|
||||
BReference<AlphaMask> fPreviousMask;
|
||||
IntRect fBounds;
|
||||
bool fClippedToCanvas;
|
||||
|
||||
private:
|
||||
IntPoint fViewOrigin;
|
||||
IntPoint fCanvasOrigin;
|
||||
IntRect fCanvasBounds;
|
||||
const bool fInverse;
|
||||
uint8 fBackgroundOpacity;
|
||||
|
||||
@ -72,7 +76,7 @@ public:
|
||||
UniformAlphaMask(uint8 opacity);
|
||||
|
||||
private:
|
||||
virtual ServerBitmap* _RenderSource();
|
||||
virtual ServerBitmap* _RenderSource(const IntRect& canvasBounds);
|
||||
virtual IntPoint _Offset();
|
||||
};
|
||||
|
||||
@ -87,7 +91,7 @@ public:
|
||||
BPoint where, bool inverse);
|
||||
|
||||
private:
|
||||
virtual ServerBitmap* _RenderSource();
|
||||
virtual ServerBitmap* _RenderSource(const IntRect& canvasBounds);
|
||||
virtual IntPoint _Offset();
|
||||
|
||||
protected:
|
||||
@ -131,7 +135,7 @@ public:
|
||||
|
||||
private:
|
||||
const shape_data& fShape;
|
||||
BRect fBounds;
|
||||
BRect fShapeBounds;
|
||||
DrawState fDrawState;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user