app_server: Implemented caching and updating the alpha mask.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user