app_server: Make use of BReferenceable in AlphaMask.

Extracted from https://review.haiku-os.org/c/haiku/+/2695
with a few minor tweaks.

May help with #16246, but I could only reproduce it intermittently.
This commit is contained in:
Augustin Cavalier 2020-06-20 20:02:35 -04:00
parent 67ace0bfab
commit 176d0e1041
2 changed files with 18 additions and 30 deletions

View File

@ -75,7 +75,6 @@ AlphaMask::AlphaMask(AlphaMask* previousMask, AlphaMask* other)
if (previousMask != NULL) if (previousMask != NULL)
atomic_add(&previousMask->fNextMaskCount, 1); atomic_add(&previousMask->fNextMaskCount, 1);
fBits->AcquireReference();
} }
@ -102,8 +101,6 @@ AlphaMask::AlphaMask(uint8 backgroundOpacity)
AlphaMask::~AlphaMask() AlphaMask::~AlphaMask()
{ {
if (fBits != NULL)
fBits->ReleaseReference();
if (fPreviousMask.Get() != NULL) if (fPreviousMask.Get() != NULL)
atomic_add(&fPreviousMask->fNextMaskCount, -1); atomic_add(&fPreviousMask->fNextMaskCount, -1);
@ -153,19 +150,17 @@ AlphaMask::BitmapSize() const
ServerBitmap* ServerBitmap*
AlphaMask::_CreateTemporaryBitmap(BRect bounds) const AlphaMask::_CreateTemporaryBitmap(BRect bounds) const
{ {
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds, BReference<UtilityBitmap> bitmap(new(std::nothrow) UtilityBitmap(bounds,
B_RGBA32, 0); B_RGBA32, 0), true);
if (bitmap == NULL) if (bitmap == NULL)
return NULL; return NULL;
if (!bitmap->IsValid()) { if (!bitmap->IsValid())
delete bitmap;
return NULL; return NULL;
}
memset(bitmap->Bits(), fBackgroundOpacity, bitmap->BitsLength()); memset(bitmap->Bits(), fBackgroundOpacity, bitmap->BitsLength());
return bitmap; return bitmap.Detach();
} }
@ -184,9 +179,7 @@ AlphaMask::_Generate()
return; return;
} }
if (fBits != NULL) fBits.SetTo(new(std::nothrow) UtilityBitmap(fBounds, B_GRAY8, 0), true);
fBits->ReleaseReference();
fBits = new(std::nothrow) UtilityBitmap(fBounds, B_GRAY8, 0);
if (fBits == NULL) if (fBits == NULL)
return; return;
@ -339,17 +332,16 @@ VectorAlphaMask<VectorMaskType>::_RenderSource(const IntRect& canvasBounds)
if (!fBounds.IsValid()) if (!fBounds.IsValid())
return NULL; return NULL;
ServerBitmap* bitmap = _CreateTemporaryBitmap(fBounds); BReference<ServerBitmap> bitmap(_CreateTemporaryBitmap(fBounds), true);
if (bitmap == NULL) if (bitmap == NULL)
return NULL; return NULL;
// Render the picture to the bitmap // Render the picture to the bitmap
BitmapHWInterface interface(bitmap); BitmapHWInterface interface(bitmap);
DrawingEngine* engine = interface.CreateDrawingEngine(); DrawingEngine* engine = interface.CreateDrawingEngine();
if (engine == NULL) { if (engine == NULL)
bitmap->ReleaseReference();
return NULL; return NULL;
}
engine->SetRendererOffset(fBounds.left, fBounds.top); engine->SetRendererOffset(fBounds.left, fBounds.top);
OffscreenCanvas canvas(engine, OffscreenCanvas canvas(engine,
@ -374,7 +366,7 @@ VectorAlphaMask<VectorMaskType>::_RenderSource(const IntRect& canvasBounds)
canvas.PopState(); canvas.PopState();
delete engine; delete engine;
return bitmap; return bitmap.Detach();
} }
@ -458,7 +450,7 @@ ShapeAlphaMask::ShapeAlphaMask(AlphaMask* previousMask,
const shape_data& shape, BPoint where, bool inverse) const shape_data& shape, BPoint where, bool inverse)
: :
VectorAlphaMask<ShapeAlphaMask>(previousMask, where, inverse), VectorAlphaMask<ShapeAlphaMask>(previousMask, where, inverse),
fShape(new(std::nothrow) shape_data(shape)) fShape(new(std::nothrow) shape_data(shape), true)
{ {
if (fDrawState == NULL) if (fDrawState == NULL)
fDrawState = new(std::nothrow) DrawState(); fDrawState = new(std::nothrow) DrawState();
@ -474,13 +466,11 @@ ShapeAlphaMask::ShapeAlphaMask(AlphaMask* previousMask,
fShape(other->fShape), fShape(other->fShape),
fShapeBounds(other->fShapeBounds) fShapeBounds(other->fShapeBounds)
{ {
fShape->AcquireReference();
} }
ShapeAlphaMask::~ShapeAlphaMask() ShapeAlphaMask::~ShapeAlphaMask()
{ {
fShape->ReleaseReference();
} }
@ -489,25 +479,23 @@ ShapeAlphaMask::Create(AlphaMask* previousMask, const shape_data& shape,
BPoint where, bool inverse) BPoint where, bool inverse)
{ {
// Look if we have a suitable cached mask // Look if we have a suitable cached mask
ShapeAlphaMask* mask = AlphaMaskCache::Default()->Get(shape, previousMask, BReference<ShapeAlphaMask> mask(AlphaMaskCache::Default()->Get(shape,
inverse); previousMask, inverse), true);
if (mask == NULL) { if (mask == NULL) {
// No cached mask, create new one // No cached mask, create new one
mask = new(std::nothrow) ShapeAlphaMask(previousMask, shape, mask.SetTo(new(std::nothrow) ShapeAlphaMask(previousMask, shape,
BPoint(0, 0), inverse); BPoint(0, 0), inverse), true);
} else { } else {
// Create new mask which reuses the parameters and the mask bitmap // Create new mask which reuses the parameters and the mask bitmap
// of the cache entry // of the cache entry
// TODO: don't make a new mask if the cache entry has no drawstate // TODO: don't make a new mask if the cache entry has no drawstate
// using it anymore, because then we ca just immediately reuse it // using it anymore, because then we ca just immediately reuse it
AlphaMask* cachedMask = mask;
RecursiveLocker locker(mask->fLock); RecursiveLocker locker(mask->fLock);
mask = new(std::nothrow) ShapeAlphaMask(previousMask, mask); mask.SetTo(new(std::nothrow) ShapeAlphaMask(previousMask, mask), true);
cachedMask->ReleaseReference();
} }
return mask; return mask.Detach();
} }

View File

@ -82,7 +82,7 @@ private:
// one in the cache, without being // one in the cache, without being
// in the cache itself // in the cache itself
UtilityBitmap* fBits; BReference<UtilityBitmap> fBits;
agg::rendering_buffer fBuffer; agg::rendering_buffer fBuffer;
agg::clipped_alpha_mask fMask; agg::clipped_alpha_mask fMask;
scanline_unpacked_masked_type fScanline; scanline_unpacked_masked_type fScanline;
@ -172,7 +172,7 @@ private:
private: private:
friend class AlphaMaskCache; friend class AlphaMaskCache;
shape_data* fShape; BReference<shape_data> fShape;
BRect fShapeBounds; BRect fShapeBounds;
static DrawState* fDrawState; static DrawState* fDrawState;
}; };