hrev46786 adds 1 changeset to branch 'master' old head: 215119a1e73029a7165a1c01dfa3ceb4a90d44bf new head: ad17bccf31f7fd7c9538a2915dff7314b077fc3c overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=ad17bcc+%5E215119a ---------------------------------------------------------------------------- ad17bcc: app_server: Implemented caching and updating the alpha mask. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev46786 Commit: ad17bccf31f7fd7c9538a2915dff7314b077fc3c URL: http://cgit.haiku-os.org/haiku/commit/?id=ad17bcc Author: Stephan Aßmus <superstippi@xxxxxx> Date: Tue Jan 28 22:57:26 2014 UTC ---------------------------------------------------------------------------- 3 files changed, 61 insertions(+), 38 deletions(-) src/servers/app/AlphaMask.cpp | 73 +++++++++++++++++++++--------------- src/servers/app/AlphaMask.h | 20 +++++++--- src/servers/app/ServerWindow.cpp | 6 ++- ---------------------------------------------------------------------------- diff --git a/src/servers/app/AlphaMask.cpp b/src/servers/app/AlphaMask.cpp index 80a7fc6..6cf33d9 100644 --- a/src/servers/app/AlphaMask.cpp +++ b/src/servers/app/AlphaMask.cpp @@ -4,6 +4,7 @@ * * Authors: * Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> + * Stephan Aßmus <superstippi@xxxxxx> */ @@ -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; diff --git a/src/servers/app/AlphaMask.h b/src/servers/app/AlphaMask.h index 1b31891..9521262 100644 --- a/src/servers/app/AlphaMask.h +++ b/src/servers/app/AlphaMask.h @@ -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; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 03354a8..81f0cca 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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); } }