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