app_server: Implemented caching and updating the alpha mask.

This commit is contained in:
Stephan Aßmus
2014-01-28 23:57:26 +01:00
parent 215119a1e7
commit ad17bccf31
3 changed files with 61 additions and 38 deletions
+43 -30
View File
@@ -4,6 +4,7 @@
*
* Authors:
* Adrien Destugues <[email protected]>
* Stephan Aßmus <[email protected]>
*/
@@ -11,20 +12,27 @@
#include "BitmapHWInterface.h"
#include "BitmapManager.h"
#include "DrawingContext.h"
#include "DrawingEngine.h"
#include "DrawState.h"
#include "ServerBitmap.h"
#include "View.h"
#include "ServerPicture.h"
AlphaMask::AlphaMask(View* view, ServerPicture* picture, bool inverse,
BPoint origin)
AlphaMask::AlphaMask(ServerPicture* picture, bool inverse, BPoint origin,
const DrawState& drawState)
:
fPicture(picture),
fInverse(inverse),
fOrigin(origin),
fView(view),
fDrawState(drawState),
fViewBounds(),
fViewOffset(),
fCachedBitmap(NULL),
fCachedBounds(),
fCachedOffset(),
fBuffer(),
fCachedMask(),
fScanline(fCachedMask)
@@ -41,21 +49,32 @@ AlphaMask::~AlphaMask()
}
void
AlphaMask::Update(BRect bounds, BPoint offset)
{
fViewBounds = bounds;
fViewOffset = offset;
}
scanline_unpacked_masked_type*
AlphaMask::Generate()
{
// if (fCachedBitmap != NULL) {
// // TODO: See if cached bitmap can actually be used. Don't use it
// // when view scrolling offset has changed, for example. Generate()
// // could be passed a current offset
// return &fScanline;
// }
if (fPicture == NULL || !fViewBounds.IsValid())
return NULL;
// See if a cached bitmap can be used. Don't use it when the view offset
// or bounds have changed.
if (fCachedBitmap != NULL
&& fViewBounds == fCachedBounds && fViewOffset == fCachedOffset) {
return &fScanline;
}
if (fCachedBitmap != NULL)
fCachedBitmap->ReleaseReference();
// If rendering the picture fails, we will draw without any clipping.
ServerBitmap* bitmap = _RenderPicture(fPicture, fInverse);
ServerBitmap* bitmap = _RenderPicture();
if (bitmap == NULL) {
fCachedBitmap = NULL;
fBuffer.attach(NULL, 0, 0, 0);
@@ -63,29 +82,26 @@ AlphaMask::Generate()
}
fCachedBitmap = bitmap;
fCachedBounds = fViewBounds;
fCachedOffset = fViewOffset;
fBuffer.attach(fCachedBitmap->Bits(), fCachedBitmap->Width(),
fCachedBitmap->Height(), fCachedBitmap->BytesPerRow());
BPoint offset(B_ORIGIN);
fView->ConvertToScreen(&offset);
fCachedMask.attach(fBuffer, offset.x + fOrigin.x, offset.y + fOrigin.y,
fInverse ? 255 : 0);
fCachedMask.attach(fBuffer, fViewOffset.x + fOrigin.x,
fViewOffset.y + fOrigin.y, fInverse ? 255 : 0);
return &fScanline;
}
ServerBitmap*
AlphaMask::_RenderPicture(ServerPicture* picture, bool inverse) const
AlphaMask::_RenderPicture() const
{
BRect bounds(fView->Bounds());
// TODO: Only the alpha channel is relevant, but there is no B_ALPHA8
// color space, so we use 300% more memory than needed.
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds, B_RGBA32,
0);
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(fViewBounds,
B_RGBA32, 0);
if (bitmap == NULL)
return NULL;
@@ -100,31 +116,28 @@ AlphaMask::_RenderPicture(ServerPicture* picture, bool inverse) const
return NULL;
}
// Copy the current state of the client view, so we draw with the right
// font, color and everything
DrawState drawState(*fView->CurrentState());
engine->SetDrawState(&drawState);
engine->SetDrawState(&fDrawState);
OffscreenContext context(engine);
if (engine->LockParallelAccess()) {
// FIXME ConstrainClippingRegion docs says passing NULL disables
// all clipping. This doesn't work and will crash in Painter.
BRegion clipping;
clipping.Include(bounds);
clipping.Include(fViewBounds);
engine->ConstrainClippingRegion(&clipping);
picture->Play(&context);
fPicture->Play(&context);
engine->UnlockParallelAccess();
}
delete engine;
if (!inverse)
if (!fInverse)
return bitmap;
// Compute the inverse of our bitmap. There probably is a better way.
uint32 size = bitmap->BitsLength();
uint8* bits = (uint8*)bitmap->Bits();
for(uint32 i = 0; i < size; i++)
for (uint32 i = 3; i < size; i += 4)
bits[i] = 255 - bits[i];
return bitmap;
+14 -6
View File
@@ -8,35 +8,43 @@
#include "agg_clipped_alpha_mask.h"
#include "ServerBitmap.h"
#include "ServerPicture.h"
#include "DrawState.h"
#include "drawing/Painter/defines.h"
class ServerBitmap;
class ServerPicture;
class AlphaMask {
public:
AlphaMask(View* view, ServerPicture* mask,
bool inverse, BPoint origin);
AlphaMask(ServerPicture* mask, bool inverse,
BPoint origin, const DrawState& drawState);
~AlphaMask();
void Update(BRect bounds, BPoint offset);
scanline_unpacked_masked_type* Generate();
private:
ServerBitmap* _RenderPicture(ServerPicture* picture,
bool inverse) const;
ServerBitmap* _RenderPicture() const;
private:
ServerPicture* fPicture;
const bool fInverse;
BPoint fOrigin;
View* fView;
DrawState fDrawState;
BRect fViewBounds;
BPoint fViewOffset;
ServerBitmap* fCachedBitmap;
BRect fCachedBounds;
BPoint fCachedOffset;
agg::rendering_buffer fBuffer;
agg::clipped_alpha_mask fCachedMask;
scanline_unpacked_masked_type fScanline;
+4 -2
View File
@@ -1884,7 +1884,7 @@ fDesktop->LockSingleWindow();
break;
fCurrentView->SetAlphaMask(new(std::nothrow) AlphaMask(
fCurrentView, picture, inverse, where));
picture, inverse, where, *fCurrentView->CurrentState()));
_UpdateDrawState(fCurrentView);
picture->ReleaseReference();
@@ -3624,9 +3624,11 @@ ServerWindow::_UpdateDrawState(View* view)
// is being drawn? probably not... otherwise the
// "offsets" passed below would need to be updated again
DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
if (view && drawingEngine) {
if (view != NULL && drawingEngine != NULL) {
BPoint leftTop(0, 0);
view->ConvertToScreenForDrawing(&leftTop);
if (view->GetAlphaMask() != NULL)
view->GetAlphaMask()->Update(view->Bounds(), leftTop);
drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
}
}