mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1057894 (Part 2) - Add RAII smart handles for imgFrame locking. r=tn
This commit is contained in:
parent
3fa8c4b046
commit
53036348cb
@ -312,6 +312,18 @@ nsresult imgFrame::Optimize()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DrawableFrameRef
|
||||
imgFrame::DrawableRef()
|
||||
{
|
||||
return DrawableFrameRef(this);
|
||||
}
|
||||
|
||||
RawAccessFrameRef
|
||||
imgFrame::RawAccessRef()
|
||||
{
|
||||
return RawAccessFrameRef(this);
|
||||
}
|
||||
|
||||
imgFrame::SurfaceWithFormat
|
||||
imgFrame::SurfaceForDrawing(bool aDoPadding,
|
||||
bool aDoPartialDecode,
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define imgFrame_h
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/VolatileBuffer.h"
|
||||
#include "gfxDrawable.h"
|
||||
@ -17,6 +18,8 @@ namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
class ImageRegion;
|
||||
class DrawableFrameRef;
|
||||
class RawAccessFrameRef;
|
||||
|
||||
class imgFrame
|
||||
{
|
||||
@ -36,6 +39,9 @@ public:
|
||||
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, SurfaceFormat aFormat, uint8_t aPaletteDepth = 0);
|
||||
nsresult Optimize();
|
||||
|
||||
DrawableFrameRef DrawableRef();
|
||||
RawAccessFrameRef RawAccessRef();
|
||||
|
||||
bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
const nsIntMargin& aPadding, GraphicsFilter aFilter,
|
||||
uint32_t aImageFlags);
|
||||
@ -165,32 +171,166 @@ private: // data
|
||||
|
||||
/** Have we called DiscardTracker::InformAllocation()? */
|
||||
bool mInformedDiscardTracker;
|
||||
|
||||
friend class DrawableFrameRef;
|
||||
friend class RawAccessFrameRef;
|
||||
};
|
||||
|
||||
// An RAII class to ensure it's easy to balance locks and unlocks on
|
||||
// imgFrames.
|
||||
class AutoFrameLocker
|
||||
{
|
||||
public:
|
||||
explicit AutoFrameLocker(imgFrame* frame)
|
||||
: mFrame(frame)
|
||||
, mSucceeded(NS_SUCCEEDED(frame->LockImageData()))
|
||||
{}
|
||||
/**
|
||||
* A reference to an imgFrame that holds the imgFrame's surface in memory,
|
||||
* allowing drawing. If you have a DrawableFrameRef |ref| and |if (ref)| returns
|
||||
* true, then calls to Draw() and GetSurface() are guaranteed to succeed.
|
||||
*/
|
||||
class DrawableFrameRef MOZ_FINAL
|
||||
{
|
||||
// Implementation details for safe boolean conversion.
|
||||
typedef void (DrawableFrameRef::* ConvertibleToBool)(float*****, double*****);
|
||||
void nonNull(float*****, double*****) {}
|
||||
|
||||
~AutoFrameLocker()
|
||||
{
|
||||
if (mSucceeded) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
public:
|
||||
DrawableFrameRef() { }
|
||||
|
||||
explicit DrawableFrameRef(imgFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mRef(aFrame->mVBuf)
|
||||
{
|
||||
if (mRef.WasBufferPurged()) {
|
||||
mFrame = nullptr;
|
||||
mRef = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DrawableFrameRef(DrawableFrameRef&& aOther)
|
||||
: mFrame(aOther.mFrame.forget())
|
||||
, mRef(Move(aOther.mRef))
|
||||
{ }
|
||||
|
||||
DrawableFrameRef& operator=(DrawableFrameRef&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
|
||||
mFrame = aOther.mFrame.forget();
|
||||
mRef = Move(aOther.mRef);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ConvertibleToBool() const
|
||||
{
|
||||
return bool(mFrame) ? &DrawableFrameRef::nonNull : 0;
|
||||
}
|
||||
|
||||
imgFrame* operator->()
|
||||
{
|
||||
MOZ_ASSERT(mFrame);
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
const imgFrame* operator->() const
|
||||
{
|
||||
MOZ_ASSERT(mFrame);
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
imgFrame* get() { return mFrame; }
|
||||
const imgFrame* get() const { return mFrame; }
|
||||
|
||||
void reset()
|
||||
{
|
||||
mFrame = nullptr;
|
||||
mRef = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<imgFrame> mFrame;
|
||||
VolatileBufferPtr<uint8_t> mRef;
|
||||
};
|
||||
|
||||
/**
|
||||
* A reference to an imgFrame that holds the imgFrame's surface in memory in a
|
||||
* format appropriate for access as raw data. If you have a RawAccessFrameRef
|
||||
* |ref| and |if (ref)| is true, then calls to GetImageData(), GetPaletteData(),
|
||||
* and GetDrawTarget() are guaranteed to succeed. This guarantee is stronger
|
||||
* than DrawableFrameRef, so everything that a valid DrawableFrameRef guarantees
|
||||
* is also guaranteed by a valid RawAccessFrameRef.
|
||||
*
|
||||
* This may be considerably more expensive than is necessary just for drawing,
|
||||
* so only use this when you need to read or write the raw underlying image data
|
||||
* that the imgFrame holds.
|
||||
*/
|
||||
class RawAccessFrameRef MOZ_FINAL
|
||||
{
|
||||
// Implementation details for safe boolean conversion.
|
||||
typedef void (RawAccessFrameRef::* ConvertibleToBool)(float*****, double*****);
|
||||
void nonNull(float*****, double*****) {}
|
||||
|
||||
public:
|
||||
RawAccessFrameRef() { }
|
||||
|
||||
explicit RawAccessFrameRef(imgFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
{
|
||||
MOZ_ASSERT(mFrame, "Need a frame");
|
||||
|
||||
if (NS_FAILED(mFrame->LockImageData())) {
|
||||
mFrame->UnlockImageData();
|
||||
mFrame = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RawAccessFrameRef(RawAccessFrameRef&& aOther)
|
||||
: mFrame(aOther.mFrame.forget())
|
||||
{ }
|
||||
|
||||
~RawAccessFrameRef()
|
||||
{
|
||||
if (mFrame) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
}
|
||||
|
||||
RawAccessFrameRef& operator=(RawAccessFrameRef&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
|
||||
|
||||
if (mFrame) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
|
||||
// Whether the lock request succeeded.
|
||||
bool Succeeded() { return mSucceeded; }
|
||||
mFrame = aOther.mFrame.forget();
|
||||
|
||||
private:
|
||||
nsRefPtr<imgFrame> mFrame;
|
||||
bool mSucceeded;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ConvertibleToBool() const
|
||||
{
|
||||
return bool(mFrame) ? &RawAccessFrameRef::nonNull : 0;
|
||||
}
|
||||
|
||||
imgFrame* operator->()
|
||||
{
|
||||
MOZ_ASSERT(mFrame);
|
||||
return mFrame.get();
|
||||
}
|
||||
|
||||
const imgFrame* operator->() const
|
||||
{
|
||||
MOZ_ASSERT(mFrame);
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
imgFrame* get() { return mFrame; }
|
||||
const imgFrame* get() const { return mFrame; }
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (mFrame) {
|
||||
mFrame->UnlockImageData();
|
||||
}
|
||||
mFrame = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<imgFrame> mFrame;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user