mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
Merge mozilla-central to autoland. on a CLOSED TREE
This commit is contained in:
commit
851bd2386e
@ -1407,15 +1407,6 @@ bool CanvasRenderingContext2D::TrySharedTarget(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
// Bug 1285271 - Disable shared buffer provider on Windows with D2D due to
|
|
||||||
// instability
|
|
||||||
if (gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() ==
|
|
||||||
BackendType::DIRECT2D1_1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RefPtr<LayerManager> layerManager =
|
RefPtr<LayerManager> layerManager =
|
||||||
LayerManagerFromCanvasElement(mCanvasElement);
|
LayerManagerFromCanvasElement(mCanvasElement);
|
||||||
|
|
||||||
@ -1620,19 +1611,13 @@ UniquePtr<uint8_t[]> CanvasRenderingContext2D::GetImageBuffer(
|
|||||||
|
|
||||||
*aFormat = 0;
|
*aFormat = 0;
|
||||||
|
|
||||||
RefPtr<SourceSurface> snapshot;
|
if (!mBufferProvider) {
|
||||||
if (mTarget) {
|
if (!EnsureTarget()) {
|
||||||
snapshot = mTarget->Snapshot();
|
|
||||||
} else if (mBufferProvider) {
|
|
||||||
snapshot = mBufferProvider->BorrowSnapshot();
|
|
||||||
} else {
|
|
||||||
EnsureTarget();
|
|
||||||
if (!IsTargetValid()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
snapshot = mTarget->Snapshot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<SourceSurface> snapshot = mBufferProvider->BorrowSnapshot();
|
||||||
if (snapshot) {
|
if (snapshot) {
|
||||||
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
|
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
|
||||||
if (data && data->GetSize() == GetSize()) {
|
if (data && data->GetSize() == GetSize()) {
|
||||||
@ -1641,9 +1626,7 @@ UniquePtr<uint8_t[]> CanvasRenderingContext2D::GetImageBuffer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mTarget && mBufferProvider) {
|
mBufferProvider->ReturnSnapshot(snapshot.forget());
|
||||||
mBufferProvider->ReturnSnapshot(snapshot.forget());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1681,6 +1664,29 @@ CanvasRenderingContext2D::GetInputStream(const char* aMimeType,
|
|||||||
aStream);
|
aStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||||
|
CanvasRenderingContext2D::GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType) {
|
||||||
|
if (!mBufferProvider) {
|
||||||
|
if (!EnsureTarget()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<SourceSurface> snapshot = mBufferProvider->BorrowSnapshot();
|
||||||
|
if (!snapshot) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
|
||||||
|
mBufferProvider->ReturnSnapshot(snapshot.forget());
|
||||||
|
|
||||||
|
if (aOutAlphaType) {
|
||||||
|
*aOutAlphaType = (mOpaque ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataSurface.forget();
|
||||||
|
}
|
||||||
|
|
||||||
SurfaceFormat CanvasRenderingContext2D::GetSurfaceFormat() const {
|
SurfaceFormat CanvasRenderingContext2D::GetSurfaceFormat() const {
|
||||||
return mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
|
return mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
|
||||||
}
|
}
|
||||||
@ -4929,27 +4935,21 @@ nsresult CanvasRenderingContext2D::GetImageDataArray(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<DataSourceSurface> readback;
|
if (!mBufferProvider) {
|
||||||
DataSourceSurface::MappedSurface rawData;
|
if (!EnsureTarget()) {
|
||||||
RefPtr<SourceSurface> snapshot;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
if (!mTarget && mBufferProvider) {
|
|
||||||
snapshot = mBufferProvider->BorrowSnapshot();
|
|
||||||
} else {
|
|
||||||
EnsureTarget();
|
|
||||||
if (!IsTargetValid()) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
}
|
||||||
snapshot = mTarget->Snapshot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot) {
|
RefPtr<SourceSurface> snapshot = mBufferProvider->BorrowSnapshot();
|
||||||
readback = snapshot->GetDataSurface();
|
if (!snapshot) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mTarget && mBufferProvider) {
|
RefPtr<DataSourceSurface> readback = snapshot->GetDataSurface();
|
||||||
mBufferProvider->ReturnSnapshot(snapshot.forget());
|
mBufferProvider->ReturnSnapshot(snapshot.forget());
|
||||||
}
|
|
||||||
|
|
||||||
|
DataSourceSurface::MappedSurface rawData;
|
||||||
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
|
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -409,13 +409,7 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
|
|||||||
nsIInputStream** aStream) override;
|
nsIInputStream** aStream) override;
|
||||||
|
|
||||||
already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(
|
already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(
|
||||||
gfxAlphaType* aOutAlphaType = nullptr) override {
|
gfxAlphaType* aOutAlphaType = nullptr) override;
|
||||||
EnsureTarget();
|
|
||||||
if (aOutAlphaType) {
|
|
||||||
*aOutAlphaType = (mOpaque ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
|
|
||||||
}
|
|
||||||
return mTarget->Snapshot();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void SetOpaqueValueFromOpaqueAttr(bool aOpaqueAttrValue) override;
|
virtual void SetOpaqueValueFromOpaqueAttr(bool aOpaqueAttrValue) override;
|
||||||
bool GetIsOpaque() override { return mOpaque; }
|
bool GetIsOpaque() override { return mOpaque; }
|
||||||
|
@ -8632,7 +8632,7 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(usage >= 0);
|
MOZ_ASSERT(usage >= 0);
|
||||||
|
|
||||||
if (!aForGetUsage) {
|
if (!aForGetUsage) {
|
||||||
InitUsageForOrigin(aOrigin, usage);
|
InitUsageForOrigin(aOrigin, usage);
|
||||||
|
12
gfx/2d/2D.h
12
gfx/2d/2D.h
@ -61,6 +61,7 @@ struct ID3D11Texture2D;
|
|||||||
struct ID3D11Device;
|
struct ID3D11Device;
|
||||||
struct ID2D1Device;
|
struct ID2D1Device;
|
||||||
struct ID2D1DeviceContext;
|
struct ID2D1DeviceContext;
|
||||||
|
struct ID2D1Multithread;
|
||||||
struct IDWriteFactory;
|
struct IDWriteFactory;
|
||||||
struct IDWriteRenderingParams;
|
struct IDWriteRenderingParams;
|
||||||
struct IDWriteFontFace;
|
struct IDWriteFontFace;
|
||||||
@ -1871,6 +1872,17 @@ class GFX2D_API Factory {
|
|||||||
static DrawEventRecorder* mRecorder;
|
static DrawEventRecorder* mRecorder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MOZ_RAII AutoSerializeWithMoz2D final {
|
||||||
|
public:
|
||||||
|
explicit AutoSerializeWithMoz2D(BackendType aBackendType);
|
||||||
|
~AutoSerializeWithMoz2D();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if defined(WIN32)
|
||||||
|
RefPtr<ID2D1Multithread> mMT;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -45,16 +45,12 @@ void DrawEventRecorderPrivate::StoreSourceSurfaceRecording(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawEventRecorderFile::RecordEvent(const RecordedEvent& aEvent) {
|
void DrawEventRecorderFile::RecordEvent(const RecordedEvent& aEvent) {
|
||||||
WriteElement(mOutputStream, aEvent.mType);
|
|
||||||
|
|
||||||
aEvent.RecordToStream(mOutputStream);
|
aEvent.RecordToStream(mOutputStream);
|
||||||
|
|
||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawEventRecorderMemory::RecordEvent(const RecordedEvent& aEvent) {
|
void DrawEventRecorderMemory::RecordEvent(const RecordedEvent& aEvent) {
|
||||||
WriteElement(mOutputStream, aEvent.mType);
|
|
||||||
|
|
||||||
aEvent.RecordToStream(mOutputStream);
|
aEvent.RecordToStream(mOutputStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,23 +85,33 @@ class DataSourceSurfaceRecording : public DataSourceSurface {
|
|||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRecording, override)
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRecording, override)
|
||||||
DataSourceSurfaceRecording(UniquePtr<uint8_t[]> aData, IntSize aSize,
|
DataSourceSurfaceRecording(UniquePtr<uint8_t[]> aData, IntSize aSize,
|
||||||
int32_t aStride, SurfaceFormat aFormat)
|
int32_t aStride, SurfaceFormat aFormat,
|
||||||
|
DrawEventRecorderPrivate* aRecorder)
|
||||||
: mData(std::move(aData)),
|
: mData(std::move(aData)),
|
||||||
mSize(aSize),
|
mSize(aSize),
|
||||||
mStride(aStride),
|
mStride(aStride),
|
||||||
mFormat(aFormat) {}
|
mFormat(aFormat),
|
||||||
|
mRecorder(aRecorder) {
|
||||||
|
mRecorder->RecordEvent(RecordedSourceSurfaceCreation(
|
||||||
|
ReferencePtr(this), mData.get(), mStride, mSize, mFormat));
|
||||||
|
mRecorder->AddStoredObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
~DataSourceSurfaceRecording() {}
|
~DataSourceSurfaceRecording() {
|
||||||
|
mRecorder->RemoveStoredObject(this);
|
||||||
|
mRecorder->RecordEvent(
|
||||||
|
RecordedSourceSurfaceDestruction(ReferencePtr(this)));
|
||||||
|
}
|
||||||
|
|
||||||
static already_AddRefed<DataSourceSurface> Init(uint8_t* aData, IntSize aSize,
|
static already_AddRefed<DataSourceSurface> Init(
|
||||||
int32_t aStride,
|
uint8_t* aData, IntSize aSize, int32_t aStride, SurfaceFormat aFormat,
|
||||||
SurfaceFormat aFormat) {
|
DrawEventRecorderPrivate* aRecorder) {
|
||||||
// XXX: do we need to ensure any alignment here?
|
// XXX: do we need to ensure any alignment here?
|
||||||
auto data = MakeUnique<uint8_t[]>(aStride * aSize.height);
|
auto data = MakeUnique<uint8_t[]>(aStride * aSize.height);
|
||||||
if (data) {
|
if (data) {
|
||||||
memcpy(data.get(), aData, aStride * aSize.height);
|
memcpy(data.get(), aData, aStride * aSize.height);
|
||||||
RefPtr<DataSourceSurfaceRecording> surf = new DataSourceSurfaceRecording(
|
RefPtr<DataSourceSurfaceRecording> surf = new DataSourceSurfaceRecording(
|
||||||
std::move(data), aSize, aStride, aFormat);
|
std::move(data), aSize, aStride, aFormat, aRecorder);
|
||||||
return surf.forget();
|
return surf.forget();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -117,6 +127,7 @@ class DataSourceSurfaceRecording : public DataSourceSurface {
|
|||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
int32_t mStride;
|
int32_t mStride;
|
||||||
SurfaceFormat mFormat;
|
SurfaceFormat mFormat;
|
||||||
|
RefPtr<DrawEventRecorderPrivate> mRecorder;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GradientStopsRecording : public GradientStops {
|
class GradientStopsRecording : public GradientStops {
|
||||||
@ -368,7 +379,13 @@ already_AddRefed<SourceSurface> DrawTargetRecording::IntoLuminanceSource(
|
|||||||
return retSurf.forget();
|
return retSurf.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTargetRecording::DetachAllSnapshots() {}
|
void DrawTargetRecording::Flush() {
|
||||||
|
mRecorder->RecordEvent(RecordedFlush(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTargetRecording::DetachAllSnapshots() {
|
||||||
|
mRecorder->RecordEvent(RecordedDetachAllSnapshots(this));
|
||||||
|
}
|
||||||
|
|
||||||
void DrawTargetRecording::DrawSurface(SourceSurface* aSurface,
|
void DrawTargetRecording::DrawSurface(SourceSurface* aSurface,
|
||||||
const Rect& aDest, const Rect& aSource,
|
const Rect& aDest, const Rect& aSource,
|
||||||
@ -480,16 +497,9 @@ DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char* aData,
|
|||||||
const IntSize& aSize,
|
const IntSize& aSize,
|
||||||
int32_t aStride,
|
int32_t aStride,
|
||||||
SurfaceFormat aFormat) const {
|
SurfaceFormat aFormat) const {
|
||||||
RefPtr<SourceSurface> surf =
|
RefPtr<SourceSurface> surf = DataSourceSurfaceRecording::Init(
|
||||||
DataSourceSurfaceRecording::Init(aData, aSize, aStride, aFormat);
|
aData, aSize, aStride, aFormat, mRecorder);
|
||||||
|
return surf.forget();
|
||||||
RefPtr<SourceSurface> retSurf =
|
|
||||||
new SourceSurfaceRecording(aSize, aFormat, mRecorder);
|
|
||||||
|
|
||||||
mRecorder->RecordEvent(
|
|
||||||
RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
|
|
||||||
|
|
||||||
return retSurf.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<SourceSurface> DrawTargetRecording::OptimizeSourceSurface(
|
already_AddRefed<SourceSurface> DrawTargetRecording::OptimizeSourceSurface(
|
||||||
|
@ -37,11 +37,7 @@ class DrawTargetRecording : public DrawTarget {
|
|||||||
|
|
||||||
virtual IntSize GetSize() const override { return mSize; }
|
virtual IntSize GetSize() const override { return mSize; }
|
||||||
|
|
||||||
/* Ensure that the DrawTarget backend has flushed all drawing operations to
|
virtual void Flush() override;
|
||||||
* this draw target. This must be called before using the backing surface of
|
|
||||||
* this draw target outside of GFX 2D code.
|
|
||||||
*/
|
|
||||||
virtual void Flush() override { mFinalDT->Flush(); }
|
|
||||||
|
|
||||||
virtual void FlushItem(const IntRect& aBounds) override;
|
virtual void FlushItem(const IntRect& aBounds) override;
|
||||||
|
|
||||||
|
@ -738,6 +738,30 @@ FT_Error Factory::LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AutoSerializeWithMoz2D::AutoSerializeWithMoz2D(BackendType aBackendType) {
|
||||||
|
#ifdef WIN32
|
||||||
|
// We use a multi-threaded ID2D1Factory1, so that makes the calls through the
|
||||||
|
// Direct2D API thread-safe. However, if the Moz2D objects are using Direct3D
|
||||||
|
// resources we need to make sure that calls through the Direct3D or DXGI API
|
||||||
|
// use the Direct2D synchronization. It's possible that this should be pushed
|
||||||
|
// down into the TextureD3D11 objects, so that we always use this.
|
||||||
|
if (aBackendType == BackendType::DIRECT2D1_1 ||
|
||||||
|
aBackendType == BackendType::DIRECT2D) {
|
||||||
|
D2DFactory()->QueryInterface(
|
||||||
|
static_cast<ID2D1Multithread**>(getter_AddRefs(mMT)));
|
||||||
|
mMT->Enter();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoSerializeWithMoz2D::~AutoSerializeWithMoz2D() {
|
||||||
|
#ifdef WIN32
|
||||||
|
if (mMT) {
|
||||||
|
mMT->Leave();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
already_AddRefed<DrawTarget> Factory::CreateDrawTargetForD3D11Texture(
|
already_AddRefed<DrawTarget> Factory::CreateDrawTargetForD3D11Texture(
|
||||||
ID3D11Texture2D* aTexture, SurfaceFormat aFormat) {
|
ID3D11Texture2D* aTexture, SurfaceFormat aFormat) {
|
||||||
|
@ -69,7 +69,7 @@ bool InlineTranslator::TranslateRecording(char* aData, size_t aLen) {
|
|||||||
while (reader.good()) {
|
while (reader.good()) {
|
||||||
bool success = RecordedEvent::DoWithEvent(
|
bool success = RecordedEvent::DoWithEvent(
|
||||||
reader, static_cast<RecordedEvent::EventType>(eventType),
|
reader, static_cast<RecordedEvent::EventType>(eventType),
|
||||||
[&](RecordedEvent* recordedEvent) {
|
[&](RecordedEvent* recordedEvent) -> bool {
|
||||||
// Make sure that the whole event was read from the stream
|
// Make sure that the whole event was read from the stream
|
||||||
// successfully.
|
// successfully.
|
||||||
if (!reader.good()) {
|
if (!reader.good()) {
|
||||||
|
@ -126,13 +126,13 @@ class InlineTranslator : public Translator {
|
|||||||
mNativeFontResources.Put(aKey, aScaledFontResouce);
|
mNativeFontResources.Put(aKey, aScaledFontResouce);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveDrawTarget(ReferencePtr aRefPtr) final {
|
void RemoveDrawTarget(ReferencePtr aRefPtr) override {
|
||||||
mDrawTargets.Remove(aRefPtr);
|
mDrawTargets.Remove(aRefPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemovePath(ReferencePtr aRefPtr) final { mPaths.Remove(aRefPtr); }
|
void RemovePath(ReferencePtr aRefPtr) final { mPaths.Remove(aRefPtr); }
|
||||||
|
|
||||||
void RemoveSourceSurface(ReferencePtr aRefPtr) final {
|
void RemoveSourceSurface(ReferencePtr aRefPtr) override {
|
||||||
mSourceSurfaces.Remove(aRefPtr);
|
mSourceSurfaces.Remove(aRefPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ class InlineTranslator : public Translator {
|
|||||||
|
|
||||||
already_AddRefed<DrawTarget> CreateDrawTarget(
|
already_AddRefed<DrawTarget> CreateDrawTarget(
|
||||||
ReferencePtr aRefPtr, const gfx::IntSize& aSize,
|
ReferencePtr aRefPtr, const gfx::IntSize& aSize,
|
||||||
gfx::SurfaceFormat aFormat) final;
|
gfx::SurfaceFormat aFormat) override;
|
||||||
|
|
||||||
mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
|
mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
|
||||||
|
|
||||||
|
@ -135,7 +135,8 @@ enum class LogReason : int {
|
|||||||
NativeFontResourceNotFound,
|
NativeFontResourceNotFound,
|
||||||
UnscaledFontNotFound,
|
UnscaledFontNotFound,
|
||||||
ScaledFontNotFound,
|
ScaledFontNotFound,
|
||||||
InvalidLayerType,
|
InvalidLayerType, // 40
|
||||||
|
PlayEventFailed,
|
||||||
// End
|
// End
|
||||||
MustBeLessThanThis = 101,
|
MustBeLessThanThis = 101,
|
||||||
};
|
};
|
||||||
|
@ -123,7 +123,7 @@ inline void AcuteArcToBezier(T* aSink, const Point& aOrigin,
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void ArcToBezier(T* aSink, const Point& aOrigin, const Size& aRadius,
|
void ArcToBezier(T* aSink, const Point& aOrigin, const Size& aRadius,
|
||||||
float aStartAngle, float aEndAngle, bool aAntiClockwise,
|
float aStartAngle, float aEndAngle, bool aAntiClockwise,
|
||||||
float aRotation = 0.0f) {
|
float aRotation = 0.0f, const Matrix& aTransform = Matrix()) {
|
||||||
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
||||||
|
|
||||||
// Calculate the total arc we're going to sweep.
|
// Calculate the total arc we're going to sweep.
|
||||||
@ -148,6 +148,7 @@ void ArcToBezier(T* aSink, const Point& aOrigin, const Size& aRadius,
|
|||||||
transform *= Matrix::Rotation(aRotation);
|
transform *= Matrix::Rotation(aRotation);
|
||||||
}
|
}
|
||||||
transform.PostTranslate(aOrigin);
|
transform.PostTranslate(aOrigin);
|
||||||
|
transform *= aTransform;
|
||||||
aSink->LineTo(transform.TransformPoint(currentStartOffset));
|
aSink->LineTo(transform.TransformPoint(currentStartOffset));
|
||||||
|
|
||||||
while (arcSweepLeft > 0) {
|
while (arcSweepLeft > 0) {
|
||||||
|
@ -11,55 +11,183 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
|
#define NEXT_PARAMS(_type) \
|
||||||
|
const _type params = *reinterpret_cast<const _type*>(nextByte); \
|
||||||
|
nextByte += sizeof(_type);
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
bool PathOps::StreamToSink(PathSink& aPathSink) const {
|
||||||
|
if (mPathData.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* nextByte = mPathData.data();
|
||||||
|
const uint8_t* end = nextByte + mPathData.size();
|
||||||
|
while (nextByte < end) {
|
||||||
|
const OpType opType = *reinterpret_cast<const OpType*>(nextByte);
|
||||||
|
nextByte += sizeof(OpType);
|
||||||
|
switch (opType) {
|
||||||
|
case OpType::OP_MOVETO: {
|
||||||
|
NEXT_PARAMS(Point)
|
||||||
|
aPathSink.MoveTo(params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_LINETO: {
|
||||||
|
NEXT_PARAMS(Point)
|
||||||
|
aPathSink.LineTo(params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_BEZIERTO: {
|
||||||
|
NEXT_PARAMS(ThreePoints)
|
||||||
|
aPathSink.BezierTo(params.p1, params.p2, params.p3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_QUADRATICBEZIERTO: {
|
||||||
|
NEXT_PARAMS(TwoPoints)
|
||||||
|
aPathSink.QuadraticBezierTo(params.p1, params.p2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_ARC: {
|
||||||
|
NEXT_PARAMS(ArcParams)
|
||||||
|
aPathSink.Arc(params.origin, params.radius, params.startAngle,
|
||||||
|
params.endAngle, params.antiClockwise);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_CLOSE:
|
||||||
|
aPathSink.Close();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathOps PathOps::TransformedCopy(const Matrix& aTransform) const {
|
||||||
|
PathOps newPathOps;
|
||||||
|
const uint8_t* nextByte = mPathData.data();
|
||||||
|
const uint8_t* end = nextByte + mPathData.size();
|
||||||
|
while (nextByte < end) {
|
||||||
|
const OpType opType = *reinterpret_cast<const OpType*>(nextByte);
|
||||||
|
nextByte += sizeof(OpType);
|
||||||
|
switch (opType) {
|
||||||
|
case OpType::OP_MOVETO: {
|
||||||
|
NEXT_PARAMS(Point)
|
||||||
|
newPathOps.MoveTo(aTransform.TransformPoint(params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_LINETO: {
|
||||||
|
NEXT_PARAMS(Point)
|
||||||
|
newPathOps.LineTo(aTransform.TransformPoint(params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_BEZIERTO: {
|
||||||
|
NEXT_PARAMS(ThreePoints)
|
||||||
|
newPathOps.BezierTo(aTransform.TransformPoint(params.p1),
|
||||||
|
aTransform.TransformPoint(params.p2),
|
||||||
|
aTransform.TransformPoint(params.p3));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_QUADRATICBEZIERTO: {
|
||||||
|
NEXT_PARAMS(TwoPoints)
|
||||||
|
newPathOps.QuadraticBezierTo(aTransform.TransformPoint(params.p1),
|
||||||
|
aTransform.TransformPoint(params.p2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_ARC: {
|
||||||
|
NEXT_PARAMS(ArcParams)
|
||||||
|
ArcToBezier(&newPathOps, params.origin,
|
||||||
|
gfx::Size(params.radius, params.radius), params.startAngle,
|
||||||
|
params.endAngle, params.antiClockwise, 0.0f, aTransform);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::OP_CLOSE:
|
||||||
|
newPathOps.Close();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("We control mOpTypes, so this should never happen.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPathOps;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef NEXT_PARAMS
|
||||||
|
|
||||||
|
size_t PathOps::NumberOfOps() const {
|
||||||
|
size_t size = 0;
|
||||||
|
const uint8_t* nextByte = mPathData.data();
|
||||||
|
const uint8_t* end = nextByte + mPathData.size();
|
||||||
|
while (nextByte < end) {
|
||||||
|
size++;
|
||||||
|
const OpType opType = *reinterpret_cast<const OpType*>(nextByte);
|
||||||
|
nextByte += sizeof(OpType);
|
||||||
|
switch (opType) {
|
||||||
|
case OpType::OP_MOVETO:
|
||||||
|
nextByte += sizeof(Point);
|
||||||
|
break;
|
||||||
|
case OpType::OP_LINETO:
|
||||||
|
nextByte += sizeof(Point);
|
||||||
|
break;
|
||||||
|
case OpType::OP_BEZIERTO:
|
||||||
|
nextByte += sizeof(ThreePoints);
|
||||||
|
break;
|
||||||
|
case OpType::OP_QUADRATICBEZIERTO:
|
||||||
|
nextByte += sizeof(TwoPoints);
|
||||||
|
break;
|
||||||
|
case OpType::OP_ARC:
|
||||||
|
nextByte += sizeof(ArcParams);
|
||||||
|
break;
|
||||||
|
case OpType::OP_CLOSE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("We control mOpTypes, so this should never happen.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void PathBuilderRecording::MoveTo(const Point& aPoint) {
|
void PathBuilderRecording::MoveTo(const Point& aPoint) {
|
||||||
PathOp op;
|
mPathOps.MoveTo(aPoint);
|
||||||
op.mType = PathOp::OP_MOVETO;
|
|
||||||
op.mP1 = aPoint;
|
|
||||||
mPathOps.push_back(op);
|
|
||||||
mPathBuilder->MoveTo(aPoint);
|
mPathBuilder->MoveTo(aPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathBuilderRecording::LineTo(const Point& aPoint) {
|
void PathBuilderRecording::LineTo(const Point& aPoint) {
|
||||||
PathOp op;
|
mPathOps.LineTo(aPoint);
|
||||||
op.mType = PathOp::OP_LINETO;
|
|
||||||
op.mP1 = aPoint;
|
|
||||||
mPathOps.push_back(op);
|
|
||||||
mPathBuilder->LineTo(aPoint);
|
mPathBuilder->LineTo(aPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathBuilderRecording::BezierTo(const Point& aCP1, const Point& aCP2,
|
void PathBuilderRecording::BezierTo(const Point& aCP1, const Point& aCP2,
|
||||||
const Point& aCP3) {
|
const Point& aCP3) {
|
||||||
PathOp op;
|
mPathOps.BezierTo(aCP1, aCP2, aCP3);
|
||||||
op.mType = PathOp::OP_BEZIERTO;
|
|
||||||
op.mP1 = aCP1;
|
|
||||||
op.mP2 = aCP2;
|
|
||||||
op.mP3 = aCP3;
|
|
||||||
mPathOps.push_back(op);
|
|
||||||
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
|
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathBuilderRecording::QuadraticBezierTo(const Point& aCP1,
|
void PathBuilderRecording::QuadraticBezierTo(const Point& aCP1,
|
||||||
const Point& aCP2) {
|
const Point& aCP2) {
|
||||||
PathOp op;
|
mPathOps.QuadraticBezierTo(aCP1, aCP2);
|
||||||
op.mType = PathOp::OP_QUADRATICBEZIERTO;
|
|
||||||
op.mP1 = aCP1;
|
|
||||||
op.mP2 = aCP2;
|
|
||||||
mPathOps.push_back(op);
|
|
||||||
mPathBuilder->QuadraticBezierTo(aCP1, aCP2);
|
mPathBuilder->QuadraticBezierTo(aCP1, aCP2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathBuilderRecording::Close() {
|
void PathBuilderRecording::Close() {
|
||||||
PathOp op;
|
mPathOps.Close();
|
||||||
op.mType = PathOp::OP_CLOSE;
|
|
||||||
mPathOps.push_back(op);
|
|
||||||
mPathBuilder->Close();
|
mPathBuilder->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathBuilderRecording::Arc(const Point& aOrigin, float aRadius,
|
||||||
|
float aStartAngle, float aEndAngle,
|
||||||
|
bool aAntiClockwise) {
|
||||||
|
mPathOps.Arc(aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
|
||||||
|
mPathBuilder->Arc(aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<Path> PathBuilderRecording::Finish() {
|
already_AddRefed<Path> PathBuilderRecording::Finish() {
|
||||||
RefPtr<Path> path = mPathBuilder->Finish();
|
RefPtr<Path> path = mPathBuilder->Finish();
|
||||||
return MakeAndAddRef<PathRecording>(path, mPathOps, mFillRule, mCurrentPoint, mBeginPoint);
|
return MakeAndAddRef<PathRecording>(path, std::move(mPathOps), mFillRule,
|
||||||
|
mCurrentPoint, mBeginPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRecording::~PathRecording() {
|
PathRecording::~PathRecording() {
|
||||||
@ -73,8 +201,7 @@ already_AddRefed<PathBuilder> PathRecording::CopyToBuilder(
|
|||||||
FillRule aFillRule) const {
|
FillRule aFillRule) const {
|
||||||
RefPtr<PathBuilder> pathBuilder = mPath->CopyToBuilder(aFillRule);
|
RefPtr<PathBuilder> pathBuilder = mPath->CopyToBuilder(aFillRule);
|
||||||
RefPtr<PathBuilderRecording> recording =
|
RefPtr<PathBuilderRecording> recording =
|
||||||
new PathBuilderRecording(pathBuilder, aFillRule);
|
new PathBuilderRecording(pathBuilder, mPathOps, aFillRule);
|
||||||
recording->mPathOps = mPathOps;
|
|
||||||
recording->SetCurrentPoint(mCurrentPoint);
|
recording->SetCurrentPoint(mCurrentPoint);
|
||||||
recording->SetBeginPoint(mBeginPoint);
|
recording->SetBeginPoint(mBeginPoint);
|
||||||
return recording.forget();
|
return recording.forget();
|
||||||
@ -84,24 +211,8 @@ already_AddRefed<PathBuilder> PathRecording::TransformedCopyToBuilder(
|
|||||||
const Matrix& aTransform, FillRule aFillRule) const {
|
const Matrix& aTransform, FillRule aFillRule) const {
|
||||||
RefPtr<PathBuilder> pathBuilder =
|
RefPtr<PathBuilder> pathBuilder =
|
||||||
mPath->TransformedCopyToBuilder(aTransform, aFillRule);
|
mPath->TransformedCopyToBuilder(aTransform, aFillRule);
|
||||||
RefPtr<PathBuilderRecording> recording =
|
RefPtr<PathBuilderRecording> recording = new PathBuilderRecording(
|
||||||
new PathBuilderRecording(pathBuilder, aFillRule);
|
pathBuilder, mPathOps.TransformedCopy(aTransform), aFillRule);
|
||||||
typedef std::vector<PathOp> pathOpVec;
|
|
||||||
for (pathOpVec::const_iterator iter = mPathOps.begin();
|
|
||||||
iter != mPathOps.end(); iter++) {
|
|
||||||
PathOp newPathOp;
|
|
||||||
newPathOp.mType = iter->mType;
|
|
||||||
if (sPointCount[newPathOp.mType] >= 1) {
|
|
||||||
newPathOp.mP1 = aTransform.TransformPoint(iter->mP1);
|
|
||||||
}
|
|
||||||
if (sPointCount[newPathOp.mType] >= 2) {
|
|
||||||
newPathOp.mP2 = aTransform.TransformPoint(iter->mP2);
|
|
||||||
}
|
|
||||||
if (sPointCount[newPathOp.mType] >= 3) {
|
|
||||||
newPathOp.mP3 = aTransform.TransformPoint(iter->mP3);
|
|
||||||
}
|
|
||||||
recording->mPathOps.push_back(newPathOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
recording->SetCurrentPoint(aTransform.TransformPoint(mCurrentPoint));
|
recording->SetCurrentPoint(aTransform.TransformPoint(mCurrentPoint));
|
||||||
recording->SetBeginPoint(aTransform.TransformPoint(mBeginPoint));
|
recording->SetBeginPoint(aTransform.TransformPoint(mBeginPoint));
|
||||||
|
@ -12,123 +12,218 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include "PathHelpers.h"
|
#include "PathHelpers.h"
|
||||||
|
#include "RecordingTypes.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
|
class PathOps {
|
||||||
|
public:
|
||||||
|
PathOps() {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
explicit PathOps(S& aStream);
|
||||||
|
|
||||||
|
PathOps(PathOps&& aOther) : mPathData(std::move(aOther.mPathData)) {}
|
||||||
|
|
||||||
|
PathOps(const PathOps& aOther) : mPathData(aOther.mPathData) {}
|
||||||
|
|
||||||
|
PathOps& operator=(PathOps&& aOther) {
|
||||||
|
mPathData = std::move(aOther.mPathData);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
bool StreamToSink(PathSink& aPathSink) const;
|
||||||
|
|
||||||
|
PathOps TransformedCopy(const Matrix& aTransform) const;
|
||||||
|
|
||||||
|
size_t NumberOfOps() const;
|
||||||
|
|
||||||
|
void MoveTo(const Point& aPoint) { AppendPathOp(OpType::OP_MOVETO, aPoint); }
|
||||||
|
|
||||||
|
void LineTo(const Point& aPoint) { AppendPathOp(OpType::OP_LINETO, aPoint); }
|
||||||
|
|
||||||
|
void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) {
|
||||||
|
AppendPathOp(OpType::OP_BEZIERTO, ThreePoints{aCP1, aCP2, aCP3});
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) {
|
||||||
|
AppendPathOp(OpType::OP_QUADRATICBEZIERTO, TwoPoints{aCP1, aCP2});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
|
||||||
|
float aEndAngle, bool aAntiClockwise) {
|
||||||
|
AppendPathOp(OpType::OP_ARC, ArcParams{aOrigin, aRadius, aStartAngle,
|
||||||
|
aEndAngle, aAntiClockwise});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close() {
|
||||||
|
size_t oldSize = mPathData.size();
|
||||||
|
mPathData.resize(oldSize + sizeof(OpType));
|
||||||
|
*reinterpret_cast<OpType*>(mPathData.data() + oldSize) = OpType::OP_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void operator=(const PathOps&) = delete; // assign using std::move()!
|
||||||
|
|
||||||
|
enum class OpType : uint32_t {
|
||||||
|
OP_MOVETO = 0,
|
||||||
|
OP_LINETO,
|
||||||
|
OP_BEZIERTO,
|
||||||
|
OP_QUADRATICBEZIERTO,
|
||||||
|
OP_ARC,
|
||||||
|
OP_CLOSE,
|
||||||
|
OP_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void AppendPathOp(const OpType& aOpType, const T& aOpParams) {
|
||||||
|
size_t oldSize = mPathData.size();
|
||||||
|
mPathData.resize(oldSize + sizeof(OpType) + sizeof(T));
|
||||||
|
memcpy(mPathData.data() + oldSize, &aOpType, sizeof(OpType));
|
||||||
|
oldSize += sizeof(OpType);
|
||||||
|
memcpy(mPathData.data() + oldSize, &aOpParams, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TwoPoints {
|
||||||
|
Point p1;
|
||||||
|
Point p2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreePoints {
|
||||||
|
Point p1;
|
||||||
|
Point p2;
|
||||||
|
Point p3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArcParams {
|
||||||
|
Point origin;
|
||||||
|
float radius;
|
||||||
|
float startAngle;
|
||||||
|
float endAngle;
|
||||||
|
bool antiClockwise;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<uint8_t> mPathData;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
PathOps::PathOps(S& aStream) {
|
||||||
|
ReadVector(aStream, mPathData);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
inline void PathOps::Record(S& aStream) const {
|
||||||
|
WriteVector(aStream, mPathData);
|
||||||
|
}
|
||||||
|
|
||||||
class PathRecording;
|
class PathRecording;
|
||||||
class DrawEventRecorderPrivate;
|
class DrawEventRecorderPrivate;
|
||||||
|
|
||||||
class PathBuilderRecording : public PathBuilder {
|
class PathBuilderRecording final : public PathBuilder {
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderRecording, override)
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderRecording, override)
|
||||||
|
|
||||||
PathBuilderRecording(PathBuilder* aBuilder, FillRule aFillRule)
|
PathBuilderRecording(PathBuilder* aBuilder, FillRule aFillRule)
|
||||||
: mPathBuilder(aBuilder), mFillRule(aFillRule) {}
|
: mPathBuilder(aBuilder), mFillRule(aFillRule) {}
|
||||||
|
|
||||||
|
PathBuilderRecording(PathBuilder* aBuilder, const PathOps& aPathOps,
|
||||||
|
FillRule aFillRule)
|
||||||
|
: mPathBuilder(aBuilder), mFillRule(aFillRule), mPathOps(aPathOps) {}
|
||||||
|
|
||||||
/* Move the current point in the path, any figure currently being drawn will
|
/* Move the current point in the path, any figure currently being drawn will
|
||||||
* be considered closed during fill operations, however when stroking the
|
* be considered closed during fill operations, however when stroking the
|
||||||
* closing line segment will not be drawn.
|
* closing line segment will not be drawn.
|
||||||
*/
|
*/
|
||||||
virtual void MoveTo(const Point& aPoint) override;
|
void MoveTo(const Point& aPoint) final;
|
||||||
|
|
||||||
/* Add a linesegment to the current figure */
|
/* Add a linesegment to the current figure */
|
||||||
virtual void LineTo(const Point& aPoint) override;
|
void LineTo(const Point& aPoint) final;
|
||||||
|
|
||||||
/* Add a cubic bezier curve to the current figure */
|
/* Add a cubic bezier curve to the current figure */
|
||||||
virtual void BezierTo(const Point& aCP1, const Point& aCP2,
|
void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) final;
|
||||||
const Point& aCP3) override;
|
|
||||||
/* Add a quadratic bezier curve to the current figure */
|
/* Add a quadratic bezier curve to the current figure */
|
||||||
virtual void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) override;
|
void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) final;
|
||||||
|
|
||||||
/* Close the current figure, this will essentially generate a line segment
|
/* Close the current figure, this will essentially generate a line segment
|
||||||
* from the current point to the starting point for the current figure
|
* from the current point to the starting point for the current figure
|
||||||
*/
|
*/
|
||||||
virtual void Close() override;
|
void Close() final;
|
||||||
|
|
||||||
/* Add an arc to the current figure */
|
/* Add an arc to the current figure */
|
||||||
virtual void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
|
void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
|
||||||
float aEndAngle, bool aAntiClockwise) override {
|
float aEndAngle, bool aAntiClockwise) final;
|
||||||
ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
|
|
||||||
aAntiClockwise);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Point the current subpath is at - or where the next subpath will start
|
/* Point the current subpath is at - or where the next subpath will start
|
||||||
* if there is no active subpath.
|
* if there is no active subpath.
|
||||||
*/
|
*/
|
||||||
virtual Point CurrentPoint() const override {
|
Point CurrentPoint() const final {
|
||||||
return mPathBuilder->CurrentPoint();
|
return mPathBuilder->CurrentPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Point BeginPoint() const override {
|
Point BeginPoint() const final {
|
||||||
return mPathBuilder->BeginPoint();
|
return mPathBuilder->BeginPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetCurrentPoint(const Point& aPoint) override {
|
void SetCurrentPoint(const Point& aPoint) final {
|
||||||
mPathBuilder->SetCurrentPoint(aPoint);
|
mPathBuilder->SetCurrentPoint(aPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetBeginPoint(const Point& aPoint) override {
|
void SetBeginPoint(const Point& aPoint) final {
|
||||||
mPathBuilder->SetBeginPoint(aPoint);
|
mPathBuilder->SetBeginPoint(aPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual already_AddRefed<Path> Finish() override;
|
already_AddRefed<Path> Finish() final;
|
||||||
|
|
||||||
virtual BackendType GetBackendType() const override {
|
BackendType GetBackendType() const final { return BackendType::RECORDING; }
|
||||||
return BackendType::RECORDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class PathRecording;
|
|
||||||
|
|
||||||
RefPtr<PathBuilder> mPathBuilder;
|
RefPtr<PathBuilder> mPathBuilder;
|
||||||
FillRule mFillRule;
|
FillRule mFillRule;
|
||||||
std::vector<PathOp> mPathOps;
|
PathOps mPathOps;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PathRecording : public Path {
|
class PathRecording final : public Path {
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording, override)
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording, override)
|
||||||
|
|
||||||
PathRecording(Path* aPath, const std::vector<PathOp> aOps, FillRule aFillRule,
|
PathRecording(Path* aPath, PathOps&& aOps, FillRule aFillRule,
|
||||||
const Point& aCurrentPoint, const Point& aBeginPoint)
|
const Point& aCurrentPoint, const Point& aBeginPoint)
|
||||||
: mPath(aPath), mPathOps(aOps), mFillRule(aFillRule),
|
: mPath(aPath), mPathOps(std::move(aOps)), mFillRule(aFillRule),
|
||||||
mCurrentPoint(aCurrentPoint), mBeginPoint(aBeginPoint) {}
|
mCurrentPoint(aCurrentPoint), mBeginPoint(aBeginPoint) {}
|
||||||
|
|
||||||
~PathRecording();
|
~PathRecording();
|
||||||
|
|
||||||
virtual BackendType GetBackendType() const override {
|
BackendType GetBackendType() const final { return BackendType::RECORDING; }
|
||||||
return BackendType::RECORDING;
|
already_AddRefed<PathBuilder> CopyToBuilder(FillRule aFillRule) const final;
|
||||||
}
|
already_AddRefed<PathBuilder> TransformedCopyToBuilder(
|
||||||
virtual already_AddRefed<PathBuilder> CopyToBuilder(
|
const Matrix& aTransform, FillRule aFillRule) const final;
|
||||||
FillRule aFillRule) const override;
|
bool ContainsPoint(const Point& aPoint,
|
||||||
virtual already_AddRefed<PathBuilder> TransformedCopyToBuilder(
|
const Matrix& aTransform) const final {
|
||||||
const Matrix& aTransform, FillRule aFillRule) const override;
|
|
||||||
virtual bool ContainsPoint(const Point& aPoint,
|
|
||||||
const Matrix& aTransform) const override {
|
|
||||||
return mPath->ContainsPoint(aPoint, aTransform);
|
return mPath->ContainsPoint(aPoint, aTransform);
|
||||||
}
|
}
|
||||||
virtual bool StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
|
bool StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
|
||||||
const Point& aPoint,
|
const Point& aPoint,
|
||||||
const Matrix& aTransform) const override {
|
const Matrix& aTransform) const final {
|
||||||
return mPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform);
|
return mPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Rect GetBounds(const Matrix& aTransform = Matrix()) const override {
|
Rect GetBounds(const Matrix& aTransform = Matrix()) const final {
|
||||||
return mPath->GetBounds(aTransform);
|
return mPath->GetBounds(aTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Rect GetStrokedBounds(
|
Rect GetStrokedBounds(const StrokeOptions& aStrokeOptions,
|
||||||
const StrokeOptions& aStrokeOptions,
|
const Matrix& aTransform = Matrix()) const final {
|
||||||
const Matrix& aTransform = Matrix()) const override {
|
|
||||||
return mPath->GetStrokedBounds(aStrokeOptions, aTransform);
|
return mPath->GetStrokedBounds(aStrokeOptions, aTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void StreamToSink(PathSink* aSink) const override {
|
void StreamToSink(PathSink* aSink) const final { mPath->StreamToSink(aSink); }
|
||||||
mPath->StreamToSink(aSink);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual FillRule GetFillRule() const override { return mFillRule; }
|
FillRule GetFillRule() const final { return mFillRule; }
|
||||||
|
|
||||||
void StorePath(std::ostream& aStream) const;
|
|
||||||
static void ReadPathToBuilder(std::istream& aStream, PathBuilder* aBuilder);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DrawTargetWrapAndRecord;
|
friend class DrawTargetWrapAndRecord;
|
||||||
@ -136,7 +231,7 @@ class PathRecording : public Path {
|
|||||||
friend class RecordedPathCreation;
|
friend class RecordedPathCreation;
|
||||||
|
|
||||||
RefPtr<Path> mPath;
|
RefPtr<Path> mPath;
|
||||||
std::vector<PathOp> mPathOps;
|
PathOps mPathOps;
|
||||||
FillRule mFillRule;
|
FillRule mFillRule;
|
||||||
Point mCurrentPoint;
|
Point mCurrentPoint;
|
||||||
Point mBeginPoint;
|
Point mBeginPoint;
|
||||||
|
@ -19,14 +19,18 @@ namespace gfx {
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
RecordedEvent* RecordedEvent::LoadEventFromStream(std::istream& aStream,
|
/* static */
|
||||||
EventType aType) {
|
bool RecordedEvent::DoWithEventFromStream(
|
||||||
return LoadEvent(aStream, aType);
|
EventStream& aStream, EventType aType,
|
||||||
|
const std::function<bool(RecordedEvent*)>& aAction) {
|
||||||
|
return DoWithEvent(aStream, aType, aAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordedEvent* RecordedEvent::LoadEventFromStream(EventStream& aStream,
|
/* static */
|
||||||
EventType aType) {
|
bool RecordedEvent::DoWithEventFromStream(
|
||||||
return LoadEvent(aStream, aType);
|
EventRingBuffer& aStream, EventType aType,
|
||||||
|
const std::function<bool(RecordedEvent*)>& aAction) {
|
||||||
|
return DoWithEvent(aStream, aType, aAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
string RecordedEvent::GetEventName(EventType aType) {
|
string RecordedEvent::GetEventName(EventType aType) {
|
||||||
|
@ -13,12 +13,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "RecordingTypes.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
struct PathOp;
|
|
||||||
class PathRecording;
|
|
||||||
|
|
||||||
const uint32_t kMagicInt = 0xc001feed;
|
const uint32_t kMagicInt = 0xc001feed;
|
||||||
|
|
||||||
// A change in major revision means a change in event binary format, causing
|
// A change in major revision means a change in event binary format, causing
|
||||||
@ -169,6 +168,71 @@ struct MemWriter {
|
|||||||
char* mPtr;
|
char* mPtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is a simple interface for an EventRingBuffer, so we can use it in the
|
||||||
|
// RecordedEvent reading and writing machinery.
|
||||||
|
class EventRingBuffer {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Templated RecordEvent function so that when we have enough contiguous
|
||||||
|
* space we can record into the buffer quickly using MemWriter.
|
||||||
|
*
|
||||||
|
* @param aRecordedEvent the event to record
|
||||||
|
*/
|
||||||
|
template <class RE>
|
||||||
|
void RecordEvent(const RE* aRecordedEvent) {
|
||||||
|
SizeCollector size;
|
||||||
|
WriteElement(size, aRecordedEvent->GetType());
|
||||||
|
aRecordedEvent->Record(size);
|
||||||
|
if (size.mTotalSize > mAvailable) {
|
||||||
|
WaitForAndRecalculateAvailableSpace();
|
||||||
|
}
|
||||||
|
if (size.mTotalSize <= mAvailable) {
|
||||||
|
MemWriter writer(mBufPos);
|
||||||
|
WriteElement(writer, aRecordedEvent->GetType());
|
||||||
|
aRecordedEvent->Record(writer);
|
||||||
|
UpdateWriteTotalsBy(size.mTotalSize);
|
||||||
|
} else {
|
||||||
|
WriteElement(*this, aRecordedEvent->GetType());
|
||||||
|
aRecordedEvent->Record(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple write function required by WriteElement.
|
||||||
|
*
|
||||||
|
* @param aData the data to be written to the buffer
|
||||||
|
* @param aSize the number of chars to write
|
||||||
|
*/
|
||||||
|
virtual void write(const char* const aData, const size_t aSize) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple read function required by ReadElement.
|
||||||
|
*
|
||||||
|
* @param aOut the pointer to read into
|
||||||
|
* @param aSize the number of chars to read
|
||||||
|
*/
|
||||||
|
virtual void read(char* const aOut, const size_t aSize) = 0;
|
||||||
|
|
||||||
|
virtual bool good() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Wait until space is available for writing and then set mBufPos and
|
||||||
|
* mAvailable.
|
||||||
|
*/
|
||||||
|
virtual bool WaitForAndRecalculateAvailableSpace() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update write count, mBufPos and mAvailable.
|
||||||
|
*
|
||||||
|
* @param aCount number of bytes written
|
||||||
|
*/
|
||||||
|
virtual void UpdateWriteTotalsBy(uint32_t aCount) = 0;
|
||||||
|
|
||||||
|
char* mBufPos = nullptr;
|
||||||
|
uint32_t mAvailable = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct MemStream {
|
struct MemStream {
|
||||||
char* mData;
|
char* mData;
|
||||||
size_t mLength;
|
size_t mLength;
|
||||||
@ -199,6 +263,7 @@ class EventStream {
|
|||||||
public:
|
public:
|
||||||
virtual void write(const char* aData, size_t aSize) = 0;
|
virtual void write(const char* aData, size_t aSize) = 0;
|
||||||
virtual void read(char* aOut, size_t aSize) = 0;
|
virtual void read(char* aOut, size_t aSize) = 0;
|
||||||
|
virtual bool good() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RecordedEvent {
|
class RecordedEvent {
|
||||||
@ -249,9 +314,10 @@ class RecordedEvent {
|
|||||||
UNSCALEDFONTDESTRUCTION,
|
UNSCALEDFONTDESTRUCTION,
|
||||||
INTOLUMINANCE,
|
INTOLUMINANCE,
|
||||||
EXTERNALSURFACECREATION,
|
EXTERNALSURFACECREATION,
|
||||||
|
FLUSH,
|
||||||
|
DETACHALLSNAPSHOTS,
|
||||||
|
LAST,
|
||||||
};
|
};
|
||||||
static const uint32_t kTotalEventTypes =
|
|
||||||
RecordedEvent::FILTERNODESETINPUT + 1;
|
|
||||||
|
|
||||||
virtual ~RecordedEvent() = default;
|
virtual ~RecordedEvent() = default;
|
||||||
|
|
||||||
@ -272,6 +338,7 @@ class RecordedEvent {
|
|||||||
|
|
||||||
virtual void RecordToStream(std::ostream& aStream) const = 0;
|
virtual void RecordToStream(std::ostream& aStream) const = 0;
|
||||||
virtual void RecordToStream(EventStream& aStream) const = 0;
|
virtual void RecordToStream(EventStream& aStream) const = 0;
|
||||||
|
virtual void RecordToStream(EventRingBuffer& aStream) const = 0;
|
||||||
virtual void RecordToStream(MemStream& aStream) const = 0;
|
virtual void RecordToStream(MemStream& aStream) const = 0;
|
||||||
|
|
||||||
virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
|
virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
|
||||||
@ -290,25 +357,20 @@ class RecordedEvent {
|
|||||||
|
|
||||||
virtual std::string GetName() const = 0;
|
virtual std::string GetName() const = 0;
|
||||||
|
|
||||||
virtual ReferencePtr GetObjectRef() const = 0;
|
|
||||||
|
|
||||||
virtual ReferencePtr GetDestinedDT() { return nullptr; }
|
virtual ReferencePtr GetDestinedDT() { return nullptr; }
|
||||||
|
|
||||||
void OutputSimplePatternInfo(const PatternStorage& aStorage,
|
void OutputSimplePatternInfo(const PatternStorage& aStorage,
|
||||||
std::stringstream& aOutput) const;
|
std::stringstream& aOutput) const;
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
static RecordedEvent* LoadEvent(S& aStream, EventType aType);
|
static bool DoWithEvent(S& aStream, EventType aType,
|
||||||
static RecordedEvent* LoadEventFromStream(std::istream& aStream,
|
const std::function<bool(RecordedEvent*)>& aAction);
|
||||||
EventType aType);
|
static bool DoWithEventFromStream(
|
||||||
static RecordedEvent* LoadEventFromStream(EventStream& aStream,
|
EventStream& aStream, EventType aType,
|
||||||
EventType aType);
|
const std::function<bool(RecordedEvent*)>& aAction);
|
||||||
|
static bool DoWithEventFromStream(
|
||||||
// An alternative to LoadEvent that avoids a heap allocation for the event.
|
EventRingBuffer& aStream, EventType aType,
|
||||||
// This accepts a callable `f' that will take a RecordedEvent* as a single
|
const std::function<bool(RecordedEvent*)>& aAction);
|
||||||
// parameter
|
|
||||||
template <class S, class F>
|
|
||||||
static bool DoWithEvent(S& aStream, EventType aType, F f);
|
|
||||||
|
|
||||||
EventType GetType() const { return (EventType)mType; }
|
EventType GetType() const { return (EventType)mType; }
|
||||||
|
|
||||||
@ -329,6 +391,35 @@ class RecordedEvent {
|
|||||||
std::vector<Float> mDashPatternStorage;
|
std::vector<Float> mDashPatternStorage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
class RecordedEventDerived : public RecordedEvent {
|
||||||
|
using RecordedEvent::RecordedEvent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void RecordToStream(std::ostream& aStream) const override {
|
||||||
|
WriteElement(aStream, this->mType);
|
||||||
|
static_cast<const Derived*>(this)->Record(aStream);
|
||||||
|
}
|
||||||
|
void RecordToStream(EventStream& aStream) const override {
|
||||||
|
WriteElement(aStream, this->mType);
|
||||||
|
static_cast<const Derived*>(this)->Record(aStream);
|
||||||
|
}
|
||||||
|
void RecordToStream(EventRingBuffer& aStream) const final {
|
||||||
|
aStream.RecordEvent(static_cast<const Derived*>(this));
|
||||||
|
}
|
||||||
|
void RecordToStream(MemStream& aStream) const override {
|
||||||
|
SizeCollector size;
|
||||||
|
WriteElement(size, this->mType);
|
||||||
|
static_cast<const Derived*>(this)->Record(size);
|
||||||
|
|
||||||
|
aStream.Resize(aStream.mLength + size.mTotalSize);
|
||||||
|
|
||||||
|
MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
|
||||||
|
WriteElement(writer, this->mType);
|
||||||
|
static_cast<const Derived*>(this)->Record(writer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -20,26 +20,6 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
template <class Derived>
|
|
||||||
class RecordedEventDerived : public RecordedEvent {
|
|
||||||
using RecordedEvent::RecordedEvent;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void RecordToStream(std::ostream& aStream) const override {
|
|
||||||
static_cast<const Derived*>(this)->Record(aStream);
|
|
||||||
}
|
|
||||||
void RecordToStream(EventStream& aStream) const override {
|
|
||||||
static_cast<const Derived*>(this)->Record(aStream);
|
|
||||||
}
|
|
||||||
void RecordToStream(MemStream& aStream) const override {
|
|
||||||
SizeCollector size;
|
|
||||||
static_cast<const Derived*>(this)->Record(size);
|
|
||||||
aStream.Resize(aStream.mLength + size.mTotalSize);
|
|
||||||
MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
|
|
||||||
static_cast<const Derived*>(this)->Record(writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
class RecordedDrawingEvent : public RecordedEventDerived<Derived> {
|
class RecordedDrawingEvent : public RecordedEventDerived<Derived> {
|
||||||
public:
|
public:
|
||||||
@ -54,8 +34,6 @@ class RecordedDrawingEvent : public RecordedEventDerived<Derived> {
|
|||||||
template <class S>
|
template <class S>
|
||||||
void Record(S& aStream) const;
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
ReferencePtr GetObjectRef() const override;
|
|
||||||
|
|
||||||
ReferencePtr mDT;
|
ReferencePtr mDT;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,7 +60,6 @@ class RecordedDrawTargetCreation
|
|||||||
std::stringstream& aStringStream) const override;
|
std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "DrawTarget Creation"; }
|
std::string GetName() const override { return "DrawTarget Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
BackendType mBackendType;
|
BackendType mBackendType;
|
||||||
@ -113,7 +90,6 @@ class RecordedDrawTargetDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "DrawTarget Destruction"; }
|
std::string GetName() const override { return "DrawTarget Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
|
|
||||||
@ -144,7 +120,6 @@ class RecordedCreateSimilarDrawTarget
|
|||||||
std::stringstream& aStringStream) const override;
|
std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "CreateSimilarDrawTarget"; }
|
std::string GetName() const override { return "CreateSimilarDrawTarget"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
@ -177,7 +152,6 @@ class RecordedCreateClippedDrawTarget
|
|||||||
std::stringstream& aStringStream) const override;
|
std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "CreateClippedDrawTarget"; }
|
std::string GetName() const override { return "CreateClippedDrawTarget"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
IntSize mMaxSize;
|
IntSize mMaxSize;
|
||||||
@ -219,7 +193,6 @@ class RecordedCreateDrawTargetForFilter
|
|||||||
std::string GetName() const override {
|
std::string GetName() const override {
|
||||||
return "CreateSimilarDrawTargetForFilter";
|
return "CreateSimilarDrawTargetForFilter";
|
||||||
}
|
}
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
IntSize mMaxSize;
|
IntSize mMaxSize;
|
||||||
@ -836,7 +809,6 @@ class RecordedDrawFilter : public RecordedDrawingEvent<RecordedDrawFilter> {
|
|||||||
class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
|
class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
|
||||||
public:
|
public:
|
||||||
MOZ_IMPLICIT RecordedPathCreation(PathRecording* aPath);
|
MOZ_IMPLICIT RecordedPathCreation(PathRecording* aPath);
|
||||||
~RecordedPathCreation();
|
|
||||||
|
|
||||||
bool PlayEvent(Translator* aTranslator) const override;
|
bool PlayEvent(Translator* aTranslator) const override;
|
||||||
|
|
||||||
@ -845,14 +817,14 @@ class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "Path Creation"; }
|
std::string GetName() const override { return "Path Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
|
|
||||||
ReferencePtr mRefPtr;
|
ReferencePtr mRefPtr;
|
||||||
FillRule mFillRule;
|
FillRule mFillRule;
|
||||||
std::vector<PathOp> mPathOps;
|
RefPtr<PathRecording> mPath;
|
||||||
|
UniquePtr<PathOps> mPathOps;
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
MOZ_IMPLICIT RecordedPathCreation(S& aStream);
|
MOZ_IMPLICIT RecordedPathCreation(S& aStream);
|
||||||
@ -871,7 +843,6 @@ class RecordedPathDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "Path Destruction"; }
|
std::string GetName() const override { return "Path Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -905,7 +876,6 @@ class RecordedSourceSurfaceCreation
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "SourceSurface Creation"; }
|
std::string GetName() const override { return "SourceSurface Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -934,7 +904,6 @@ class RecordedSourceSurfaceDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "SourceSurface Destruction"; }
|
std::string GetName() const override { return "SourceSurface Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -964,7 +933,6 @@ class RecordedExternalSurfaceCreation
|
|||||||
virtual std::string GetName() const {
|
virtual std::string GetName() const {
|
||||||
return "SourceSurfaceSharedData Creation";
|
return "SourceSurfaceSharedData Creation";
|
||||||
}
|
}
|
||||||
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -993,7 +961,6 @@ class RecordedFilterNodeCreation
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "FilterNode Creation"; }
|
std::string GetName() const override { return "FilterNode Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1018,7 +985,6 @@ class RecordedFilterNodeDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "FilterNode Destruction"; }
|
std::string GetName() const override { return "FilterNode Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1050,7 +1016,6 @@ class RecordedGradientStopsCreation
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "GradientStops Creation"; }
|
std::string GetName() const override { return "GradientStops Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1078,7 +1043,6 @@ class RecordedGradientStopsDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "GradientStops Destruction"; }
|
std::string GetName() const override { return "GradientStops Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1089,6 +1053,48 @@ class RecordedGradientStopsDestruction
|
|||||||
MOZ_IMPLICIT RecordedGradientStopsDestruction(S& aStream);
|
MOZ_IMPLICIT RecordedGradientStopsDestruction(S& aStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RecordedFlush : public RecordedDrawingEvent<RecordedFlush> {
|
||||||
|
public:
|
||||||
|
explicit RecordedFlush(DrawTarget* aDT) : RecordedDrawingEvent(FLUSH, aDT) {}
|
||||||
|
|
||||||
|
bool PlayEvent(Translator* aTranslator) const final;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
virtual void OutputSimpleEventInfo(
|
||||||
|
std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
|
virtual std::string GetName() const override { return "Flush"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class RecordedEvent;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedFlush(S& aStream);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RecordedDetachAllSnapshots
|
||||||
|
: public RecordedDrawingEvent<RecordedDetachAllSnapshots> {
|
||||||
|
public:
|
||||||
|
explicit RecordedDetachAllSnapshots(DrawTarget* aDT)
|
||||||
|
: RecordedDrawingEvent(DETACHALLSNAPSHOTS, aDT) {}
|
||||||
|
|
||||||
|
bool PlayEvent(Translator* aTranslator) const final;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
virtual void OutputSimpleEventInfo(
|
||||||
|
std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
|
virtual std::string GetName() const override { return "DetachAllSnapshots"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class RecordedEvent;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedDetachAllSnapshots(S& aStream);
|
||||||
|
};
|
||||||
|
|
||||||
class RecordedSnapshot : public RecordedEventDerived<RecordedSnapshot> {
|
class RecordedSnapshot : public RecordedEventDerived<RecordedSnapshot> {
|
||||||
public:
|
public:
|
||||||
RecordedSnapshot(ReferencePtr aRefPtr, DrawTarget* aDT)
|
RecordedSnapshot(ReferencePtr aRefPtr, DrawTarget* aDT)
|
||||||
@ -1101,7 +1107,6 @@ class RecordedSnapshot : public RecordedEventDerived<RecordedSnapshot> {
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "Snapshot"; }
|
std::string GetName() const override { return "Snapshot"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1131,7 +1136,6 @@ class RecordedIntoLuminanceSource
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "IntoLuminanceSource"; }
|
std::string GetName() const override { return "IntoLuminanceSource"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1173,7 +1177,6 @@ class RecordedFontData : public RecordedEventDerived<RecordedFontData> {
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "Font Data"; }
|
std::string GetName() const override { return "Font Data"; }
|
||||||
ReferencePtr GetObjectRef() const override { return nullptr; };
|
|
||||||
|
|
||||||
void SetFontData(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
|
void SetFontData(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
|
||||||
|
|
||||||
@ -1220,7 +1223,6 @@ class RecordedFontDescriptor
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "Font Desc"; }
|
std::string GetName() const override { return "Font Desc"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1264,7 +1266,6 @@ class RecordedUnscaledFontCreation
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "UnscaledFont Creation"; }
|
std::string GetName() const override { return "UnscaledFont Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize);
|
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize);
|
||||||
|
|
||||||
@ -1292,7 +1293,6 @@ class RecordedUnscaledFontDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "UnscaledFont Destruction"; }
|
std::string GetName() const override { return "UnscaledFont Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1331,7 +1331,6 @@ class RecordedScaledFontCreation
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "ScaledFont Creation"; }
|
std::string GetName() const override { return "ScaledFont Creation"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize,
|
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize,
|
||||||
const FontVariation* aVariations,
|
const FontVariation* aVariations,
|
||||||
@ -1363,7 +1362,6 @@ class RecordedScaledFontDestruction
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "ScaledFont Destruction"; }
|
std::string GetName() const override { return "ScaledFont Destruction"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1454,7 +1452,6 @@ class RecordedFilterNodeSetAttribute
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "SetAttribute"; }
|
std::string GetName() const override { return "SetAttribute"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mNode; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1494,7 +1491,6 @@ class RecordedFilterNodeSetInput
|
|||||||
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
|
||||||
|
|
||||||
std::string GetName() const override { return "SetInput"; }
|
std::string GetName() const override { return "SetInput"; }
|
||||||
ReferencePtr GetObjectRef() const override { return mNode; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RecordedEvent;
|
friend class RecordedEvent;
|
||||||
@ -1735,11 +1731,6 @@ void RecordedDrawingEvent<T>::Record(S& aStream) const {
|
|||||||
WriteElement(aStream, mDT);
|
WriteElement(aStream, mDT);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
ReferencePtr RecordedDrawingEvent<T>::GetObjectRef() const {
|
|
||||||
return mDT;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool RecordedDrawTargetCreation::PlayEvent(
|
inline bool RecordedDrawTargetCreation::PlayEvent(
|
||||||
Translator* aTranslator) const {
|
Translator* aTranslator) const {
|
||||||
RefPtr<DrawTarget> newDT =
|
RefPtr<DrawTarget> newDT =
|
||||||
@ -2677,36 +2668,13 @@ inline RecordedPathCreation::RecordedPathCreation(PathRecording* aPath)
|
|||||||
: RecordedEventDerived(PATHCREATION),
|
: RecordedEventDerived(PATHCREATION),
|
||||||
mRefPtr(aPath),
|
mRefPtr(aPath),
|
||||||
mFillRule(aPath->mFillRule),
|
mFillRule(aPath->mFillRule),
|
||||||
mPathOps(aPath->mPathOps) {}
|
mPath(aPath) {}
|
||||||
|
|
||||||
inline RecordedPathCreation::~RecordedPathCreation() {}
|
|
||||||
|
|
||||||
inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
|
inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
|
||||||
RefPtr<PathBuilder> builder =
|
RefPtr<PathBuilder> builder =
|
||||||
aTranslator->GetReferenceDrawTarget()->CreatePathBuilder(mFillRule);
|
aTranslator->GetReferenceDrawTarget()->CreatePathBuilder(mFillRule);
|
||||||
|
if (!mPathOps->StreamToSink(*builder)) {
|
||||||
for (size_t i = 0; i < mPathOps.size(); i++) {
|
return false;
|
||||||
const PathOp& op = mPathOps[i];
|
|
||||||
switch (op.mType) {
|
|
||||||
case PathOp::OP_MOVETO:
|
|
||||||
builder->MoveTo(op.mP1);
|
|
||||||
break;
|
|
||||||
case PathOp::OP_LINETO:
|
|
||||||
builder->LineTo(op.mP1);
|
|
||||||
break;
|
|
||||||
case PathOp::OP_BEZIERTO:
|
|
||||||
builder->BezierTo(op.mP1, op.mP2, op.mP3);
|
|
||||||
break;
|
|
||||||
case PathOp::OP_QUADRATICBEZIERTO:
|
|
||||||
builder->QuadraticBezierTo(op.mP1, op.mP2);
|
|
||||||
break;
|
|
||||||
case PathOp::OP_ARC:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Recordings should not contain arc operations");
|
|
||||||
break;
|
|
||||||
case PathOp::OP_CLOSE:
|
|
||||||
builder->Close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Path> path = builder->Finish();
|
RefPtr<Path> path = builder->Finish();
|
||||||
@ -2717,54 +2685,24 @@ inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
|
|||||||
template <class S>
|
template <class S>
|
||||||
void RecordedPathCreation::Record(S& aStream) const {
|
void RecordedPathCreation::Record(S& aStream) const {
|
||||||
WriteElement(aStream, mRefPtr);
|
WriteElement(aStream, mRefPtr);
|
||||||
WriteElement(aStream, uint64_t(mPathOps.size()));
|
|
||||||
WriteElement(aStream, mFillRule);
|
WriteElement(aStream, mFillRule);
|
||||||
typedef std::vector<PathOp> pathOpVec;
|
mPath->mPathOps.Record(aStream);
|
||||||
for (pathOpVec::const_iterator iter = mPathOps.begin();
|
|
||||||
iter != mPathOps.end(); iter++) {
|
|
||||||
WriteElement(aStream, iter->mType);
|
|
||||||
if (sPointCount[iter->mType] >= 1) {
|
|
||||||
WriteElement(aStream, iter->mP1);
|
|
||||||
}
|
|
||||||
if (sPointCount[iter->mType] >= 2) {
|
|
||||||
WriteElement(aStream, iter->mP2);
|
|
||||||
}
|
|
||||||
if (sPointCount[iter->mType] >= 3) {
|
|
||||||
WriteElement(aStream, iter->mP3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
RecordedPathCreation::RecordedPathCreation(S& aStream)
|
RecordedPathCreation::RecordedPathCreation(S& aStream)
|
||||||
: RecordedEventDerived(PATHCREATION) {
|
: RecordedEventDerived(PATHCREATION) {
|
||||||
uint64_t size;
|
|
||||||
|
|
||||||
ReadElement(aStream, mRefPtr);
|
ReadElement(aStream, mRefPtr);
|
||||||
ReadElement(aStream, size);
|
|
||||||
ReadElement(aStream, mFillRule);
|
ReadElement(aStream, mFillRule);
|
||||||
|
mPathOps = MakeUnique<PathOps>(aStream);
|
||||||
for (uint64_t i = 0; i < size; i++) {
|
|
||||||
PathOp newPathOp;
|
|
||||||
ReadElement(aStream, newPathOp.mType);
|
|
||||||
if (sPointCount[newPathOp.mType] >= 1) {
|
|
||||||
ReadElement(aStream, newPathOp.mP1);
|
|
||||||
}
|
|
||||||
if (sPointCount[newPathOp.mType] >= 2) {
|
|
||||||
ReadElement(aStream, newPathOp.mP2);
|
|
||||||
}
|
|
||||||
if (sPointCount[newPathOp.mType] >= 3) {
|
|
||||||
ReadElement(aStream, newPathOp.mP3);
|
|
||||||
}
|
|
||||||
|
|
||||||
mPathOps.push_back(newPathOp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RecordedPathCreation::OutputSimpleEventInfo(
|
inline void RecordedPathCreation::OutputSimpleEventInfo(
|
||||||
std::stringstream& aStringStream) const {
|
std::stringstream& aStringStream) const {
|
||||||
aStringStream << "[" << mRefPtr
|
size_t numberOfOps =
|
||||||
<< "] Path created (OpCount: " << mPathOps.size() << ")";
|
mPath ? mPath->mPathOps.NumberOfOps() : mPathOps->NumberOfOps();
|
||||||
|
aStringStream << "[" << mRefPtr << "] Path created (OpCount: " << numberOfOps
|
||||||
|
<< ")";
|
||||||
}
|
}
|
||||||
inline bool RecordedPathDestruction::PlayEvent(Translator* aTranslator) const {
|
inline bool RecordedPathDestruction::PlayEvent(Translator* aTranslator) const {
|
||||||
aTranslator->RemovePath(mRefPtr);
|
aTranslator->RemovePath(mRefPtr);
|
||||||
@ -2812,9 +2750,10 @@ void RecordedSourceSurfaceCreation::Record(S& aStream) const {
|
|||||||
WriteElement(aStream, mSize);
|
WriteElement(aStream, mSize);
|
||||||
WriteElement(aStream, mFormat);
|
WriteElement(aStream, mFormat);
|
||||||
MOZ_ASSERT(mData);
|
MOZ_ASSERT(mData);
|
||||||
for (int y = 0; y < mSize.height; y++) {
|
size_t dataFormatWidth = BytesPerPixel(mFormat) * mSize.width;
|
||||||
aStream.write((const char*)mData + y * mStride,
|
const char* endSrc = (const char*)(mData + (mSize.height * mStride));
|
||||||
BytesPerPixel(mFormat) * mSize.width);
|
for (const char* src = (const char*)mData; src < endSrc; src += mStride) {
|
||||||
|
aStream.write(src, dataFormatWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3039,6 +2978,45 @@ inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
|
|||||||
<< ")";
|
<< ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
|
||||||
|
aTranslator->LookupDrawTarget(mDT)->Flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedFlush::Record(S& aStream) const {
|
||||||
|
RecordedDrawingEvent::Record(aStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedFlush::RecordedFlush(S& aStream)
|
||||||
|
: RecordedDrawingEvent(FLUSH, aStream) {}
|
||||||
|
|
||||||
|
inline void RecordedFlush::OutputSimpleEventInfo(
|
||||||
|
std::stringstream& aStringStream) const {
|
||||||
|
aStringStream << "[" << mDT << "] Flush";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RecordedDetachAllSnapshots::PlayEvent(
|
||||||
|
Translator* aTranslator) const {
|
||||||
|
aTranslator->LookupDrawTarget(mDT)->DetachAllSnapshots();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedDetachAllSnapshots::Record(S& aStream) const {
|
||||||
|
RecordedDrawingEvent::Record(aStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedDetachAllSnapshots::RecordedDetachAllSnapshots(S& aStream)
|
||||||
|
: RecordedDrawingEvent(DETACHALLSNAPSHOTS, aStream) {}
|
||||||
|
|
||||||
|
inline void RecordedDetachAllSnapshots::OutputSimpleEventInfo(
|
||||||
|
std::stringstream& aStringStream) const {
|
||||||
|
aStringStream << "[" << mDT << "] DetachAllSnapshots";
|
||||||
|
}
|
||||||
|
|
||||||
inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
|
inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
|
||||||
RefPtr<SourceSurface> src = aTranslator->LookupDrawTarget(mDT)->Snapshot();
|
RefPtr<SourceSurface> src = aTranslator->LookupDrawTarget(mDT)->Snapshot();
|
||||||
aTranslator->AddSourceSurface(mRefPtr, src);
|
aTranslator->AddSourceSurface(mRefPtr, src);
|
||||||
@ -3480,10 +3458,6 @@ inline void RecordedFilterNodeSetInput::OutputSimpleEventInfo(
|
|||||||
aStringStream << ")";
|
aStringStream << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_EVENT_TYPE(_typeenum, _class) \
|
|
||||||
case _typeenum: \
|
|
||||||
return new _class(aStream)
|
|
||||||
|
|
||||||
#define FOR_EACH_EVENT(f) \
|
#define FOR_EACH_EVENT(f) \
|
||||||
f(DRAWTARGETCREATION, RecordedDrawTargetCreation); \
|
f(DRAWTARGETCREATION, RecordedDrawTargetCreation); \
|
||||||
f(DRAWTARGETDESTRUCTION, RecordedDrawTargetDestruction); \
|
f(DRAWTARGETDESTRUCTION, RecordedDrawTargetDestruction); \
|
||||||
@ -3529,25 +3503,20 @@ inline void RecordedFilterNodeSetInput::OutputSimpleEventInfo(
|
|||||||
f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); \
|
f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); \
|
||||||
f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); \
|
f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); \
|
||||||
f(INTOLUMINANCE, RecordedIntoLuminanceSource); \
|
f(INTOLUMINANCE, RecordedIntoLuminanceSource); \
|
||||||
f(EXTERNALSURFACECREATION, RecordedExternalSurfaceCreation);
|
f(EXTERNALSURFACECREATION, RecordedExternalSurfaceCreation); \
|
||||||
|
f(FLUSH, RecordedFlush); \
|
||||||
template <class S>
|
f(DETACHALLSNAPSHOTS, RecordedDetachAllSnapshots);
|
||||||
RecordedEvent* RecordedEvent::LoadEvent(S& aStream, EventType aType) {
|
|
||||||
switch (aType) {
|
|
||||||
FOR_EACH_EVENT(LOAD_EVENT_TYPE)
|
|
||||||
default:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DO_WITH_EVENT_TYPE(_typeenum, _class) \
|
#define DO_WITH_EVENT_TYPE(_typeenum, _class) \
|
||||||
case _typeenum: { \
|
case _typeenum: { \
|
||||||
auto e = _class(aStream); \
|
auto e = _class(aStream); \
|
||||||
return f(&e); \
|
return aAction(&e); \
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class S, class F>
|
template <class S>
|
||||||
bool RecordedEvent::DoWithEvent(S& aStream, EventType aType, F f) {
|
bool RecordedEvent::DoWithEvent(
|
||||||
|
S& aStream, EventType aType,
|
||||||
|
const std::function<bool(RecordedEvent*)>& aAction) {
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
FOR_EACH_EVENT(DO_WITH_EVENT_TYPE)
|
FOR_EACH_EVENT(DO_WITH_EVENT_TYPE)
|
||||||
default:
|
default:
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define MOZILLA_GFX_RECORDINGTYPES_H_
|
#define MOZILLA_GFX_RECORDINGTYPES_H_
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
@ -27,9 +28,29 @@ void WriteElement(S& aStream, const T& aElement) {
|
|||||||
ElementStreamFormat<S, T>::Write(aStream, aElement);
|
ElementStreamFormat<S, T>::Write(aStream, aElement);
|
||||||
}
|
}
|
||||||
template <class S, class T>
|
template <class S, class T>
|
||||||
|
void WriteVector(S& aStream, const std::vector<T>& aVector) {
|
||||||
|
size_t size = aVector.size();
|
||||||
|
WriteElement(aStream, size);
|
||||||
|
if (size) {
|
||||||
|
aStream.write(reinterpret_cast<const char*>(aVector.data()),
|
||||||
|
sizeof(T) * size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <class S, class T>
|
||||||
void ReadElement(S& aStream, T& aElement) {
|
void ReadElement(S& aStream, T& aElement) {
|
||||||
ElementStreamFormat<S, T>::Read(aStream, aElement);
|
ElementStreamFormat<S, T>::Read(aStream, aElement);
|
||||||
}
|
}
|
||||||
|
template <class S, class T>
|
||||||
|
void ReadVector(S& aStream, std::vector<T>& aVector) {
|
||||||
|
size_t size;
|
||||||
|
ReadElement(aStream, size);
|
||||||
|
if (size) {
|
||||||
|
aVector.resize(size);
|
||||||
|
aStream.read(reinterpret_cast<char*>(aVector.data()), sizeof(T) * size);
|
||||||
|
} else {
|
||||||
|
aVector.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -50,7 +50,8 @@ class gfxVarReceiver;
|
|||||||
_(UseOMTP, bool, false) \
|
_(UseOMTP, bool, false) \
|
||||||
_(AllowD3D11KeyedMutex, bool, false) \
|
_(AllowD3D11KeyedMutex, bool, false) \
|
||||||
_(SystemTextQuality, int32_t, 5 /* CLEARTYPE_QUALITY */) \
|
_(SystemTextQuality, int32_t, 5 /* CLEARTYPE_QUALITY */) \
|
||||||
_(LayersWindowRecordingPath, nsCString, nsCString())
|
_(LayersWindowRecordingPath, nsCString, nsCString()) \
|
||||||
|
_(RemoteCanvasEnabled, bool, false) \
|
||||||
|
|
||||||
/* Add new entries above this line. */
|
/* Add new entries above this line. */
|
||||||
|
|
||||||
|
@ -205,7 +205,11 @@ mozilla::ipc::IPCResult GPUParent::RecvInit(
|
|||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
|
if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
|
||||||
DeviceManagerDx::Get()->CreateCompositorDevices();
|
if (DeviceManagerDx::Get()->CreateCompositorDevices() &&
|
||||||
|
gfxVars::RemoteCanvasEnabled()) {
|
||||||
|
MOZ_ALWAYS_TRUE(DeviceManagerDx::Get()->CreateCanvasDevice());
|
||||||
|
MOZ_ALWAYS_TRUE(Factory::EnsureDWriteFactory());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (gfxVars::UseWebRender()) {
|
if (gfxVars::UseWebRender()) {
|
||||||
DeviceManagerDx::Get()->CreateDirectCompositionDevice();
|
DeviceManagerDx::Get()->CreateDirectCompositionDevice();
|
||||||
|
455
gfx/layers/CanvasDrawEventRecorder.cpp
Normal file
455
gfx/layers/CanvasDrawEventRecorder.cpp
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "CanvasDrawEventRecorder.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
static const int32_t kCheckpointEventType = -1;
|
||||||
|
static const uint32_t kMaxSpinCount = 200;
|
||||||
|
|
||||||
|
// TODO: These timeouts are long because failure in the middle of writing or
|
||||||
|
// reading an event is probably going to be fatal to the GPU process. What we
|
||||||
|
// really need to know is whether the other process has died.
|
||||||
|
static const TimeDuration kWriterTimeout = TimeDuration::FromMilliseconds(1000);
|
||||||
|
static const TimeDuration kReaderTimeout = TimeDuration::FromMilliseconds(5000);
|
||||||
|
|
||||||
|
static const uint32_t kCacheLineSize = 64;
|
||||||
|
static const uint32_t kStreamSize = 64 * 1024;
|
||||||
|
static const uint32_t kShmemSize = kStreamSize + (2 * kCacheLineSize);
|
||||||
|
|
||||||
|
static_assert((static_cast<uint64_t>(UINT32_MAX) + 1) % kStreamSize == 0,
|
||||||
|
"kStreamSize must be a power of two.");
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::InitWriter(
|
||||||
|
base::ProcessId aOtherPid, ipc::SharedMemoryBasic::Handle* aReadHandle,
|
||||||
|
CrossProcessSemaphoreHandle* aReaderSem,
|
||||||
|
CrossProcessSemaphoreHandle* aWriterSem,
|
||||||
|
const std::function<void()>& aResumeReaderCallback) {
|
||||||
|
mSharedMemory = MakeAndAddRef<ipc::SharedMemoryBasic>();
|
||||||
|
if (NS_WARN_IF(!mSharedMemory->Create(kShmemSize)) ||
|
||||||
|
NS_WARN_IF(!mSharedMemory->Map(kShmemSize))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_WARN_IF(!mSharedMemory->ShareToProcess(aOtherPid, aReadHandle))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSharedMemory->CloseHandle();
|
||||||
|
|
||||||
|
mBuf = static_cast<char*>(mSharedMemory->memory());
|
||||||
|
mBufPos = mBuf;
|
||||||
|
mAvailable = kStreamSize;
|
||||||
|
|
||||||
|
static_assert(sizeof(ReadFooter) <= kCacheLineSize,
|
||||||
|
"ReadFooter must fit in kCacheLineSize.");
|
||||||
|
mRead = reinterpret_cast<ReadFooter*>(mBuf + kStreamSize);
|
||||||
|
mRead->count = 0;
|
||||||
|
mRead->returnCount = 0;
|
||||||
|
mRead->state = State::Processing;
|
||||||
|
|
||||||
|
static_assert(sizeof(WriteFooter) <= kCacheLineSize,
|
||||||
|
"WriteFooter must fit in kCacheLineSize.");
|
||||||
|
mWrite = reinterpret_cast<WriteFooter*>(mBuf + kStreamSize + kCacheLineSize);
|
||||||
|
mWrite->count = 0;
|
||||||
|
mWrite->returnCount = 0;
|
||||||
|
mWrite->requiredDifference = 0;
|
||||||
|
mWrite->state = State::Processing;
|
||||||
|
|
||||||
|
mReaderSemaphore.reset(
|
||||||
|
CrossProcessSemaphore::Create("SharedMemoryStreamParent", 0));
|
||||||
|
*aReaderSem = mReaderSemaphore->ShareToProcess(aOtherPid);
|
||||||
|
mReaderSemaphore->CloseHandle();
|
||||||
|
mWriterSemaphore.reset(
|
||||||
|
CrossProcessSemaphore::Create("SharedMemoryStreamChild", 0));
|
||||||
|
*aWriterSem = mWriterSemaphore->ShareToProcess(aOtherPid);
|
||||||
|
mWriterSemaphore->CloseHandle();
|
||||||
|
|
||||||
|
mResumeReaderCallback = aResumeReaderCallback;
|
||||||
|
|
||||||
|
mGood = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::InitReader(
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem) {
|
||||||
|
mSharedMemory = MakeAndAddRef<ipc::SharedMemoryBasic>();
|
||||||
|
if (NS_WARN_IF(!mSharedMemory->SetHandle(
|
||||||
|
aReadHandle, ipc::SharedMemory::RightsReadWrite)) ||
|
||||||
|
NS_WARN_IF(!mSharedMemory->Map(kShmemSize))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSharedMemory->CloseHandle();
|
||||||
|
|
||||||
|
mBuf = static_cast<char*>(mSharedMemory->memory());
|
||||||
|
mRead = reinterpret_cast<ReadFooter*>(mBuf + kStreamSize);
|
||||||
|
mWrite = reinterpret_cast<WriteFooter*>(mBuf + kStreamSize + kCacheLineSize);
|
||||||
|
mReaderSemaphore.reset(CrossProcessSemaphore::Create(aReaderSem));
|
||||||
|
mReaderSemaphore->CloseHandle();
|
||||||
|
mWriterSemaphore.reset(CrossProcessSemaphore::Create(aWriterSem));
|
||||||
|
mWriterSemaphore->CloseHandle();
|
||||||
|
mGood = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::WaitForAndRecalculateAvailableSpace() {
|
||||||
|
uint32_t bufPos = mOurCount % kStreamSize;
|
||||||
|
uint32_t maxToWrite = kStreamSize - bufPos;
|
||||||
|
mAvailable = std::min(maxToWrite, WaitForBytesToWrite());
|
||||||
|
if (!mAvailable) {
|
||||||
|
mGood = false;
|
||||||
|
mBufPos = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBufPos = mBuf + bufPos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::write(const char* const aData, const size_t aSize) {
|
||||||
|
const char* curDestPtr = aData;
|
||||||
|
size_t remainingToWrite = aSize;
|
||||||
|
if (remainingToWrite > mAvailable) {
|
||||||
|
if (!WaitForAndRecalculateAvailableSpace()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingToWrite <= mAvailable) {
|
||||||
|
memcpy(mBufPos, curDestPtr, remainingToWrite);
|
||||||
|
UpdateWriteTotalsBy(remainingToWrite);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
memcpy(mBufPos, curDestPtr, mAvailable);
|
||||||
|
IncrementWriteCountBy(mAvailable);
|
||||||
|
curDestPtr += mAvailable;
|
||||||
|
remainingToWrite -= mAvailable;
|
||||||
|
if (!WaitForAndRecalculateAvailableSpace()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (remainingToWrite > mAvailable);
|
||||||
|
|
||||||
|
memcpy(mBufPos, curDestPtr, remainingToWrite);
|
||||||
|
UpdateWriteTotalsBy(remainingToWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::IncrementWriteCountBy(uint32_t aCount) {
|
||||||
|
mOurCount += aCount;
|
||||||
|
mWrite->count = mOurCount;
|
||||||
|
if (mRead->state != State::Processing) {
|
||||||
|
CheckAndSignalReader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::UpdateWriteTotalsBy(uint32_t aCount) {
|
||||||
|
IncrementWriteCountBy(aCount);
|
||||||
|
mBufPos += aCount;
|
||||||
|
mAvailable -= aCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::WaitForAndRecalculateAvailableData() {
|
||||||
|
uint32_t bufPos = mOurCount % kStreamSize;
|
||||||
|
uint32_t maxToRead = kStreamSize - bufPos;
|
||||||
|
mAvailable = std::min(maxToRead, WaitForBytesToRead());
|
||||||
|
if (!mAvailable) {
|
||||||
|
mGood = false;
|
||||||
|
mBufPos = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBufPos = mBuf + bufPos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::read(char* const aOut, const size_t aSize) {
|
||||||
|
char* curSrcPtr = aOut;
|
||||||
|
size_t remainingToRead = aSize;
|
||||||
|
if (remainingToRead > mAvailable) {
|
||||||
|
if (!WaitForAndRecalculateAvailableData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingToRead <= mAvailable) {
|
||||||
|
memcpy(curSrcPtr, mBufPos, remainingToRead);
|
||||||
|
UpdateReadTotalsBy(remainingToRead);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
memcpy(curSrcPtr, mBufPos, mAvailable);
|
||||||
|
IncrementReadCountBy(mAvailable);
|
||||||
|
curSrcPtr += mAvailable;
|
||||||
|
remainingToRead -= mAvailable;
|
||||||
|
if (!WaitForAndRecalculateAvailableData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (remainingToRead > mAvailable);
|
||||||
|
|
||||||
|
memcpy(curSrcPtr, mBufPos, remainingToRead);
|
||||||
|
UpdateReadTotalsBy(remainingToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::IncrementReadCountBy(uint32_t aCount) {
|
||||||
|
mOurCount += aCount;
|
||||||
|
mRead->count = mOurCount;
|
||||||
|
if (mWrite->state != State::Processing) {
|
||||||
|
CheckAndSignalWriter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::UpdateReadTotalsBy(uint32_t aCount) {
|
||||||
|
IncrementReadCountBy(aCount);
|
||||||
|
mBufPos += aCount;
|
||||||
|
mAvailable -= aCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::CheckAndSignalReader() {
|
||||||
|
do {
|
||||||
|
switch (mRead->state) {
|
||||||
|
case State::Processing:
|
||||||
|
return;
|
||||||
|
case State::AboutToWait:
|
||||||
|
// The reader is making a decision about whether to wait. So, we must
|
||||||
|
// wait until it has decided to avoid races.
|
||||||
|
continue;
|
||||||
|
case State::Waiting:
|
||||||
|
if (mRead->count != mOurCount) {
|
||||||
|
// We have to use compareExchange here because the reader can change
|
||||||
|
// from Waiting to Stopped.
|
||||||
|
if (mRead->state.compareExchange(State::Waiting, State::Processing)) {
|
||||||
|
mReaderSemaphore->Signal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mRead->state == State::Stopped);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case State::Stopped:
|
||||||
|
if (mRead->count != mOurCount) {
|
||||||
|
mRead->state = State::Processing;
|
||||||
|
mResumeReaderCallback();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Invalid waiting state.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::HasDataToRead() {
|
||||||
|
return (mWrite->count != mOurCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::StopIfEmpty() {
|
||||||
|
// Double-check that the writer isn't waiting.
|
||||||
|
CheckAndSignalWriter();
|
||||||
|
mRead->state = State::AboutToWait;
|
||||||
|
if (HasDataToRead()) {
|
||||||
|
mRead->state = State::Processing;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRead->state = State::Stopped;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::WaitForDataToRead(TimeDuration aTimeout) {
|
||||||
|
uint32_t spinCount = kMaxSpinCount;
|
||||||
|
do {
|
||||||
|
if (HasDataToRead()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while (--spinCount != 0);
|
||||||
|
|
||||||
|
// Double-check that the writer isn't waiting.
|
||||||
|
CheckAndSignalWriter();
|
||||||
|
mRead->state = State::AboutToWait;
|
||||||
|
if (HasDataToRead()) {
|
||||||
|
mRead->state = State::Processing;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRead->state = State::Waiting;
|
||||||
|
if (!mReaderSemaphore->Wait(Some(aTimeout))) {
|
||||||
|
// We have to use compareExchange here because the writer can change our
|
||||||
|
// state if we are waiting.
|
||||||
|
if (!mRead->state.compareExchange(State::Waiting, State::Stopped)) {
|
||||||
|
MOZ_RELEASE_ASSERT(HasDataToRead());
|
||||||
|
MOZ_RELEASE_ASSERT(mRead->state == State::Processing);
|
||||||
|
// The writer has just signaled us, so consume it before returning
|
||||||
|
MOZ_ALWAYS_TRUE(mReaderSemaphore->Wait());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(HasDataToRead());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CanvasEventRingBuffer::ReadNextEvent() {
|
||||||
|
int32_t nextEvent;
|
||||||
|
ReadElement(*this, nextEvent);
|
||||||
|
while (nextEvent == kCheckpointEventType) {
|
||||||
|
ReadElement(*this, nextEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CanvasEventRingBuffer::CreateCheckpoint() {
|
||||||
|
WriteElement(*this, kCheckpointEventType);
|
||||||
|
return mOurCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::WaitForCheckpoint(uint32_t aCheckpoint,
|
||||||
|
TimeDuration aTimeout) {
|
||||||
|
return WaitForReadCount(aCheckpoint, aTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::CheckAndSignalWriter() {
|
||||||
|
do {
|
||||||
|
switch (mWrite->state) {
|
||||||
|
case State::Processing:
|
||||||
|
return;
|
||||||
|
case State::AboutToWait:
|
||||||
|
// The writer is making a decision about whether to wait. So, we must
|
||||||
|
// wait until it has decided to avoid races.
|
||||||
|
continue;
|
||||||
|
case State::Waiting:
|
||||||
|
if (mWrite->count - mOurCount <= mWrite->requiredDifference) {
|
||||||
|
mWrite->state = State::Processing;
|
||||||
|
mWriterSemaphore->Signal();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Invalid waiting state.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasEventRingBuffer::WaitForReadCount(uint32_t aReadCount,
|
||||||
|
TimeDuration aTimeout) {
|
||||||
|
uint32_t requiredDifference = mOurCount - aReadCount;
|
||||||
|
uint32_t spinCount = kMaxSpinCount;
|
||||||
|
do {
|
||||||
|
if (mOurCount - mRead->count <= requiredDifference) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while (--spinCount != 0);
|
||||||
|
|
||||||
|
// Double-check that the reader isn't waiting.
|
||||||
|
CheckAndSignalReader();
|
||||||
|
mWrite->state = State::AboutToWait;
|
||||||
|
if (mOurCount - mRead->count <= requiredDifference) {
|
||||||
|
mWrite->state = State::Processing;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWrite->requiredDifference = requiredDifference;
|
||||||
|
mWrite->state = State::Waiting;
|
||||||
|
|
||||||
|
uint32_t lastReadCount = mRead->count;
|
||||||
|
while (!mWriterSemaphore->Wait(Some(aTimeout))) {
|
||||||
|
if (NS_WARN_IF(mRead->count == lastReadCount)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lastReadCount = mRead->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mOurCount - mRead->count <= requiredDifference);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CanvasEventRingBuffer::WaitForBytesToWrite() {
|
||||||
|
uint32_t streamFullReadCount = mOurCount - kStreamSize;
|
||||||
|
if (!WaitForReadCount(streamFullReadCount + 1, kWriterTimeout)) {
|
||||||
|
mGood = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mRead->count - streamFullReadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CanvasEventRingBuffer::WaitForBytesToRead() {
|
||||||
|
if (!WaitForDataToRead(kReaderTimeout)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mWrite->count - mOurCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::ReturnWrite(const char* aData, size_t aSize) {
|
||||||
|
uint32_t writeCount = mRead->returnCount;
|
||||||
|
uint32_t bufPos = writeCount % kStreamSize;
|
||||||
|
uint32_t bufRemaining = kStreamSize - bufPos;
|
||||||
|
uint32_t availableToWrite =
|
||||||
|
std::min(bufRemaining, (mWrite->returnCount + kStreamSize - writeCount));
|
||||||
|
while (availableToWrite < aSize) {
|
||||||
|
if (availableToWrite) {
|
||||||
|
memcpy(mBuf + bufPos, aData, availableToWrite);
|
||||||
|
writeCount += availableToWrite;
|
||||||
|
mRead->returnCount = writeCount;
|
||||||
|
bufPos = writeCount % kStreamSize;
|
||||||
|
bufRemaining = kStreamSize - bufPos;
|
||||||
|
aData += availableToWrite;
|
||||||
|
aSize -= availableToWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
availableToWrite = std::min(
|
||||||
|
bufRemaining, (mWrite->returnCount + kStreamSize - writeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mBuf + bufPos, aData, aSize);
|
||||||
|
writeCount += aSize;
|
||||||
|
mRead->returnCount = writeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasEventRingBuffer::ReturnRead(char* aOut, size_t aSize) {
|
||||||
|
uint32_t readCount = mWrite->returnCount;
|
||||||
|
uint32_t bufPos = readCount % kStreamSize;
|
||||||
|
uint32_t bufRemaining = kStreamSize - bufPos;
|
||||||
|
uint32_t availableToRead =
|
||||||
|
std::min(bufRemaining, (mRead->returnCount - readCount));
|
||||||
|
while (availableToRead < aSize) {
|
||||||
|
if (availableToRead) {
|
||||||
|
memcpy(aOut, mBuf + bufPos, availableToRead);
|
||||||
|
readCount += availableToRead;
|
||||||
|
mWrite->returnCount = readCount;
|
||||||
|
bufPos = readCount % kStreamSize;
|
||||||
|
bufRemaining = kStreamSize - bufPos;
|
||||||
|
aOut += availableToRead;
|
||||||
|
aSize -= availableToRead;
|
||||||
|
} else {
|
||||||
|
// Double-check that the reader isn't waiting.
|
||||||
|
CheckAndSignalReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
availableToRead = std::min(bufRemaining, (mRead->returnCount - readCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(aOut, mBuf + bufPos, aSize);
|
||||||
|
readCount += aSize;
|
||||||
|
mWrite->returnCount = readCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
232
gfx/layers/CanvasDrawEventRecorder.h
Normal file
232
gfx/layers/CanvasDrawEventRecorder.h
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_CanvasDrawEventRecorder_h
|
||||||
|
#define mozilla_layers_CanvasDrawEventRecorder_h
|
||||||
|
|
||||||
|
#include "mozilla/gfx/DrawEventRecorder.h"
|
||||||
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/ipc/SharedMemoryBasic.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class CanvasEventRingBuffer final : public gfx::EventRingBuffer {
|
||||||
|
public:
|
||||||
|
CanvasEventRingBuffer() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the write side of a CanvasEventRingBuffer returning handles to
|
||||||
|
* the shared memory for the buffer and the two semaphores for waiting in the
|
||||||
|
* reader and the writer.
|
||||||
|
*
|
||||||
|
* @param aOtherPid process ID to share the handles to
|
||||||
|
* @param aReadHandle handle to the shared memory for the buffer
|
||||||
|
* @param aReaderSem reading blocked semaphore
|
||||||
|
* @param aWriterSem writing blocked semaphore
|
||||||
|
* @param aResumeReaderCallback callback to start the reader when it is has
|
||||||
|
* stopped
|
||||||
|
* @returns true if initialization succeeds
|
||||||
|
*/
|
||||||
|
bool InitWriter(base::ProcessId aOtherPid,
|
||||||
|
ipc::SharedMemoryBasic::Handle* aReadHandle,
|
||||||
|
CrossProcessSemaphoreHandle* aReaderSem,
|
||||||
|
CrossProcessSemaphoreHandle* aWriterSem,
|
||||||
|
const std::function<void()>& aResumeReaderCallback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the read side of a CanvasEventRingBuffer.
|
||||||
|
*
|
||||||
|
* @param aReadHandle handle to the shared memory for the buffer
|
||||||
|
* @param aReaderSem reading blocked semaphore
|
||||||
|
* @param aWriterSem writing blocked semaphore
|
||||||
|
* @returns true if initialization succeeds
|
||||||
|
*/
|
||||||
|
bool InitReader(const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem);
|
||||||
|
|
||||||
|
bool good() const final { return mGood; }
|
||||||
|
|
||||||
|
void write(const char* const aData, const size_t aSize) final;
|
||||||
|
|
||||||
|
bool HasDataToRead();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This will put the reader into a stopped state if there is no more data to
|
||||||
|
* read. If this returns false the caller is responsible for continuing
|
||||||
|
* translation at a later point. If it returns false the writer will start the
|
||||||
|
* translation again when more data is written.
|
||||||
|
*
|
||||||
|
* @returns true if stopped
|
||||||
|
*/
|
||||||
|
bool StopIfEmpty();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Waits for the given TimeDuration for data to become available.
|
||||||
|
*
|
||||||
|
* @returns true if data is available to read.
|
||||||
|
*/
|
||||||
|
bool WaitForDataToRead(TimeDuration aTimeout);
|
||||||
|
|
||||||
|
int32_t ReadNextEvent();
|
||||||
|
|
||||||
|
void read(char* const aOut, const size_t aSize) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a checkpoint event to the buffer.
|
||||||
|
*
|
||||||
|
* @returns the write count after the checkpoint has been written
|
||||||
|
*/
|
||||||
|
uint32_t CreateCheckpoint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits until the given checkpoint has been read from the buffer.
|
||||||
|
*
|
||||||
|
* @params aCheckpoint the checkpoint to wait for
|
||||||
|
* @params aTimeout duration to wait while reader is not active
|
||||||
|
* @returns true if the checkpoint was reached, false if the read count has
|
||||||
|
* not changed in the aTimeout duration.
|
||||||
|
*/
|
||||||
|
bool WaitForCheckpoint(uint32_t aCheckpoint, TimeDuration aTimeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to send data back to the writer. This is done through the same shared
|
||||||
|
* memory so the writer must wait and read the response after it has submitted
|
||||||
|
* the event that uses this.
|
||||||
|
*
|
||||||
|
* @param aData the data to be written back to the writer
|
||||||
|
* @param aSize the number of chars to write
|
||||||
|
*/
|
||||||
|
void ReturnWrite(const char* aData, size_t aSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to read data sent back from the reader via ReturnWrite. This is done
|
||||||
|
* through the same shared memory so the writer must wait until all expected
|
||||||
|
* data is read before writing new events to the buffer.
|
||||||
|
*
|
||||||
|
* @param aOut the pointer to read into
|
||||||
|
* @param aSize the number of chars to read
|
||||||
|
*/
|
||||||
|
void ReturnRead(char* aOut, size_t aSize);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool WaitForAndRecalculateAvailableSpace() final;
|
||||||
|
void UpdateWriteTotalsBy(uint32_t aCount) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class State : uint32_t {
|
||||||
|
Processing,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the important state to make sure the other side signals or starts
|
||||||
|
* us as soon as data or space is available. We set AboutToWait first and
|
||||||
|
* then re-check the condition. If we went straight to Waiting or Stopped
|
||||||
|
* then in between the last check and setting the state, the other side
|
||||||
|
* could have used all available data or space and never have signaled us
|
||||||
|
* because it didn't know we were about to wait, causing a deadlock.
|
||||||
|
* While we are in this state, the other side must wait until we resolve the
|
||||||
|
* AboutToWait state to one of the other states and then signal or start us
|
||||||
|
* if it needs to.
|
||||||
|
*/
|
||||||
|
AboutToWait,
|
||||||
|
Waiting,
|
||||||
|
Stopped
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReadFooter {
|
||||||
|
Atomic<uint32_t, ReleaseAcquire> count;
|
||||||
|
Atomic<uint32_t, ReleaseAcquire> returnCount;
|
||||||
|
Atomic<State, ReleaseAcquire> state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WriteFooter {
|
||||||
|
Atomic<uint32_t, ReleaseAcquire> count;
|
||||||
|
Atomic<uint32_t, ReleaseAcquire> returnCount;
|
||||||
|
Atomic<uint32_t, ReleaseAcquire> requiredDifference;
|
||||||
|
Atomic<State, ReleaseAcquire> state;
|
||||||
|
};
|
||||||
|
|
||||||
|
CanvasEventRingBuffer(const CanvasEventRingBuffer&) = delete;
|
||||||
|
void operator=(const CanvasEventRingBuffer&) = delete;
|
||||||
|
|
||||||
|
void IncrementWriteCountBy(uint32_t aCount);
|
||||||
|
|
||||||
|
bool WaitForReadCount(uint32_t aReadCount, TimeDuration aTimeout);
|
||||||
|
|
||||||
|
bool WaitForAndRecalculateAvailableData();
|
||||||
|
|
||||||
|
void UpdateReadTotalsBy(uint32_t aCount);
|
||||||
|
void IncrementReadCountBy(uint32_t aCount);
|
||||||
|
|
||||||
|
void CheckAndSignalReader();
|
||||||
|
|
||||||
|
void CheckAndSignalWriter();
|
||||||
|
|
||||||
|
uint32_t WaitForBytesToWrite();
|
||||||
|
|
||||||
|
uint32_t WaitForBytesToRead();
|
||||||
|
|
||||||
|
RefPtr<ipc::SharedMemoryBasic> mSharedMemory;
|
||||||
|
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
|
||||||
|
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
|
||||||
|
std::function<void()> mResumeReaderCallback;
|
||||||
|
char* mBuf = nullptr;
|
||||||
|
uint32_t mOurCount = 0;
|
||||||
|
WriteFooter* mWrite = nullptr;
|
||||||
|
ReadFooter* mRead = nullptr;
|
||||||
|
bool mGood = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate {
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final)
|
||||||
|
explicit CanvasDrawEventRecorder(){};
|
||||||
|
|
||||||
|
bool Init(base::ProcessId aOtherPid, ipc::SharedMemoryBasic::Handle* aHandle,
|
||||||
|
CrossProcessSemaphoreHandle* aReaderSem,
|
||||||
|
CrossProcessSemaphoreHandle* aWriterSem,
|
||||||
|
const std::function<void()>& aResumeReaderCallback) {
|
||||||
|
return mOutputStream.InitWriter(aOtherPid, aHandle, aReaderSem, aWriterSem,
|
||||||
|
aResumeReaderCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordEvent(const gfx::RecordedEvent& aEvent) final {
|
||||||
|
if (!mOutputStream.good()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aEvent.RecordToStream(mOutputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush() final {}
|
||||||
|
|
||||||
|
void ReturnRead(char* aOut, size_t aSize) {
|
||||||
|
mOutputStream.ReturnRead(aOut, aSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CreateCheckpoint() { return mOutputStream.CreateCheckpoint(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits until the given checkpoint has been read by the translator.
|
||||||
|
*
|
||||||
|
* @params aCheckpoint the checkpoint to wait for
|
||||||
|
* @params aTimeout duration to wait while translator is not actively reading
|
||||||
|
* @returns true if the checkpoint was reached, false if the translator has
|
||||||
|
* not been active in the aTimeout duration.
|
||||||
|
*/
|
||||||
|
bool WaitForCheckpoint(uint32_t aCheckpoint, TimeDuration aTimeout) {
|
||||||
|
return mOutputStream.WaitForCheckpoint(aCheckpoint, aTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CanvasEventRingBuffer mOutputStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_CanvasDrawEventRecorder_h
|
245
gfx/layers/CanvasTranslator.cpp
Normal file
245
gfx/layers/CanvasTranslator.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "CanvasTranslator.h"
|
||||||
|
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/gfx/Logging.h"
|
||||||
|
#include "RecordedCanvasEventImpl.h"
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
|
# include "mozilla/layers/TextureD3D11.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
// When in a transaction we wait for a short time because we're expecting more
|
||||||
|
// events from the content process. We don't want to wait for too long in case
|
||||||
|
// other content processes are waiting for events to process.
|
||||||
|
static const TimeDuration kReadEventTimeout = TimeDuration::FromMilliseconds(5);
|
||||||
|
|
||||||
|
static TextureData* CreateTextureData(TextureType aTextureType,
|
||||||
|
const gfx::IntSize& aSize,
|
||||||
|
gfx::SurfaceFormat aFormat) {
|
||||||
|
TextureData* textureData = nullptr;
|
||||||
|
switch (aTextureType) {
|
||||||
|
#ifdef XP_WIN
|
||||||
|
case TextureType::D3D11: {
|
||||||
|
RefPtr<ID3D11Device> device =
|
||||||
|
gfx::DeviceManagerDx::Get()->GetCanvasDevice();
|
||||||
|
MOZ_RELEASE_ASSERT(device, "Failed to get a device for canvas drawing.");
|
||||||
|
textureData =
|
||||||
|
D3D11TextureData::Create(aSize, aFormat, ALLOC_CLEAR_BUFFER, device);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unsupported TextureType for CanvasTranslator.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textureData) {
|
||||||
|
MOZ_CRASH("Failed to create TextureData.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return textureData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
UniquePtr<CanvasTranslator> CanvasTranslator::Create(
|
||||||
|
const TextureType& aTextureType,
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem) {
|
||||||
|
TextureData* textureData = CreateTextureData(aTextureType, gfx::IntSize(1, 1),
|
||||||
|
gfx::SurfaceFormat::B8G8R8A8);
|
||||||
|
textureData->Lock(OpenMode::OPEN_READ_WRITE);
|
||||||
|
RefPtr<gfx::DrawTarget> dt = textureData->BorrowDrawTarget();
|
||||||
|
return UniquePtr<CanvasTranslator>(new CanvasTranslator(
|
||||||
|
aTextureType, textureData, dt, aReadHandle, aReaderSem, aWriterSem));
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTranslator::CanvasTranslator(
|
||||||
|
const TextureType& aTextureType, TextureData* aTextureData,
|
||||||
|
gfx::DrawTarget* aDT, const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem)
|
||||||
|
: gfx::InlineTranslator(aDT),
|
||||||
|
mTextureType(aTextureType),
|
||||||
|
mReferenceTextureData(aTextureData) {
|
||||||
|
mStream.InitReader(aReadHandle, aReaderSem, aWriterSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTranslator::~CanvasTranslator() { mReferenceTextureData->Unlock(); }
|
||||||
|
|
||||||
|
bool CanvasTranslator::TranslateRecording() {
|
||||||
|
int32_t eventType = mStream.ReadNextEvent();
|
||||||
|
while (mStream.good()) {
|
||||||
|
bool success = RecordedEvent::DoWithEventFromStream(
|
||||||
|
mStream, static_cast<RecordedEvent::EventType>(eventType),
|
||||||
|
[&](RecordedEvent* recordedEvent) -> bool {
|
||||||
|
// Make sure that the whole event was read from the stream.
|
||||||
|
if (!mStream.good()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return recordedEvent->PlayEvent(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success && !HandleExtensionEvent(eventType)) {
|
||||||
|
gfxDevCrash(gfx::LogReason::PlayEventFailed)
|
||||||
|
<< "Failed to play canvas event type: " << eventType;
|
||||||
|
mIsValid = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mIsInTransaction) {
|
||||||
|
return mStream.StopIfEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mStream.HasDataToRead()) {
|
||||||
|
// We're going to wait for the next event, so take the opportunity to
|
||||||
|
// flush the rendering.
|
||||||
|
Flush();
|
||||||
|
if (!mStream.WaitForDataToRead(kReadEventTimeout)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventType = mStream.ReadNextEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsValid = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_AND_PLAY_CANVAS_EVENT_TYPE(_typeenum, _class) \
|
||||||
|
case _typeenum: { \
|
||||||
|
auto e = _class(mStream); \
|
||||||
|
if (!mStream.good()) { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
return e.PlayCanvasEvent(this); \
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanvasTranslator::HandleExtensionEvent(int32_t aType) {
|
||||||
|
// This is where we handle extensions to the Moz2D Recording events to handle
|
||||||
|
// canvas specific things.
|
||||||
|
switch (aType) {
|
||||||
|
FOR_EACH_CANVAS_EVENT(READ_AND_PLAY_CANVAS_EVENT_TYPE)
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::BeginTransaction() { mIsInTransaction = true; }
|
||||||
|
|
||||||
|
void CanvasTranslator::Flush() {
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
gfx::AutoSerializeWithMoz2D serializeWithMoz2D(
|
||||||
|
GetReferenceDrawTarget()->GetBackendType());
|
||||||
|
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetCanvasDevice();
|
||||||
|
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||||
|
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||||
|
deviceContext->Flush();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::EndTransaction() {
|
||||||
|
Flush();
|
||||||
|
mIsInTransaction = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::AddSurfaceDescriptor(gfx::ReferencePtr aRefPtr,
|
||||||
|
TextureData* aTextureData) {
|
||||||
|
UniquePtr<SurfaceDescriptor> descriptor = MakeUnique<SurfaceDescriptor>();
|
||||||
|
if (!aTextureData->Serialize(*descriptor)) {
|
||||||
|
MOZ_CRASH("Failed to serialize");
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock(mSurfaceDescriptorsMonitor);
|
||||||
|
mSurfaceDescriptors[aRefPtr] = std::move(descriptor);
|
||||||
|
mSurfaceDescriptorsMonitor.Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DrawTarget> CanvasTranslator::CreateDrawTarget(
|
||||||
|
gfx::ReferencePtr aRefPtr, const gfx::IntSize& aSize,
|
||||||
|
gfx::SurfaceFormat aFormat) {
|
||||||
|
gfx::AutoSerializeWithMoz2D serializeWithMoz2D(
|
||||||
|
GetReferenceDrawTarget()->GetBackendType());
|
||||||
|
TextureData* textureData = CreateTextureData(mTextureType, aSize, aFormat);
|
||||||
|
textureData->Lock(OpenMode::OPEN_READ_WRITE);
|
||||||
|
mTextureDatas[aRefPtr] = UniquePtr<TextureData>(textureData);
|
||||||
|
AddSurfaceDescriptor(aRefPtr, textureData);
|
||||||
|
RefPtr<gfx::DrawTarget> dt = textureData->BorrowDrawTarget();
|
||||||
|
AddDrawTarget(aRefPtr, dt);
|
||||||
|
|
||||||
|
return dt.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::RemoveDrawTarget(gfx::ReferencePtr aDrawTarget) {
|
||||||
|
InlineTranslator::RemoveDrawTarget(aDrawTarget);
|
||||||
|
gfx::AutoSerializeWithMoz2D serializeWithMoz2D(
|
||||||
|
GetReferenceDrawTarget()->GetBackendType());
|
||||||
|
mTextureDatas.erase(aDrawTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureData* CanvasTranslator::LookupTextureData(
|
||||||
|
gfx::ReferencePtr aDrawTarget) {
|
||||||
|
TextureMap::const_iterator result = mTextureDatas.find(aDrawTarget);
|
||||||
|
if (result == mTextureDatas.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return result->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<SurfaceDescriptor> CanvasTranslator::WaitForSurfaceDescriptor(
|
||||||
|
gfx::ReferencePtr aDrawTarget) {
|
||||||
|
MonitorAutoLock lock(mSurfaceDescriptorsMonitor);
|
||||||
|
DescriptorMap::iterator result;
|
||||||
|
while ((result = mSurfaceDescriptors.find(aDrawTarget)) ==
|
||||||
|
mSurfaceDescriptors.end()) {
|
||||||
|
mSurfaceDescriptorsMonitor.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<SurfaceDescriptor> descriptor = std::move(result->second);
|
||||||
|
mSurfaceDescriptors.erase(aDrawTarget);
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::DataSourceSurface* CanvasTranslator::LookupDataSurface(
|
||||||
|
gfx::ReferencePtr aRefPtr) {
|
||||||
|
return mDataSurfaces.GetWeak(aRefPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::AddDataSurface(
|
||||||
|
gfx::ReferencePtr aRefPtr, RefPtr<gfx::DataSourceSurface>&& aSurface) {
|
||||||
|
mDataSurfaces.Put(aRefPtr, aSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::RemoveDataSurface(gfx::ReferencePtr aRefPtr) {
|
||||||
|
mDataSurfaces.Remove(aRefPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasTranslator::SetPreparedMap(
|
||||||
|
gfx::ReferencePtr aSurface,
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> aMap) {
|
||||||
|
mMappedSurface = aSurface;
|
||||||
|
mPreparedMap = std::move(aMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> CanvasTranslator::GetPreparedMap(
|
||||||
|
gfx::ReferencePtr aSurface) {
|
||||||
|
MOZ_RELEASE_ASSERT(mMappedSurface == aSurface,
|
||||||
|
"aSurface must match previously stored surface.");
|
||||||
|
|
||||||
|
mMappedSurface = nullptr;
|
||||||
|
return std::move(mPreparedMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
216
gfx/layers/CanvasTranslator.h
Normal file
216
gfx/layers/CanvasTranslator.h
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_CanvasTranslator_h
|
||||||
|
#define mozilla_layers_CanvasTranslator_h
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mozilla/gfx/InlineTranslator.h"
|
||||||
|
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
||||||
|
#include "mozilla/layers/LayersSurfaces.h"
|
||||||
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class TextureData;
|
||||||
|
|
||||||
|
class CanvasTranslator final : public gfx::InlineTranslator {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a canvas translator for a particular TextureType, which translates
|
||||||
|
* events from a CanvasEventRingBuffer.
|
||||||
|
*
|
||||||
|
* @param aTextureType the TextureType the translator will create
|
||||||
|
* @param aReadHandle handle to the shared memory for the
|
||||||
|
* CanvasEventRingBuffer
|
||||||
|
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
|
||||||
|
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
|
||||||
|
* @returns the new CanvasTranslator
|
||||||
|
*/
|
||||||
|
static UniquePtr<CanvasTranslator> Create(
|
||||||
|
const TextureType& aTextureType,
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem);
|
||||||
|
|
||||||
|
~CanvasTranslator();
|
||||||
|
|
||||||
|
bool IsValid() { return mIsValid; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates events until no more are available or the end of a transaction
|
||||||
|
* If this returns false the caller of this is responsible for re-calling
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* @returns true if all events are processed and false otherwise.
|
||||||
|
*/
|
||||||
|
bool TranslateRecording();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the beginning of rendering for a transaction. While in a transaction
|
||||||
|
* the translator will wait for a short time for events before returning.
|
||||||
|
* When not in a transaction the translator will only translate one event at a
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
void BeginTransaction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the end of a transaction.
|
||||||
|
*/
|
||||||
|
void EndTransaction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes canvas drawing, for example to a device.
|
||||||
|
*/
|
||||||
|
void Flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to send data back to the writer. This is done through the same shared
|
||||||
|
* memory so the writer must wait and read the response after it has submitted
|
||||||
|
* the event that uses this.
|
||||||
|
*
|
||||||
|
* @param aData the data to be written back to the writer
|
||||||
|
* @param aSize the number of chars to write
|
||||||
|
*/
|
||||||
|
void ReturnWrite(const char* aData, size_t aSize) {
|
||||||
|
mStream.ReturnWrite(aData, aSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used during playback of events to create DrawTargets. For the
|
||||||
|
* CanvasTranslator this means creating TextureDatas and getting the
|
||||||
|
* DrawTargets from those.
|
||||||
|
*
|
||||||
|
* @param aRefPtr the key to store the created DrawTarget against
|
||||||
|
* @param aSize the size of the DrawTarget
|
||||||
|
* @param aFormat the surface format for the DrawTarget
|
||||||
|
* @returns the new DrawTarget
|
||||||
|
*/
|
||||||
|
already_AddRefed<gfx::DrawTarget> CreateDrawTarget(
|
||||||
|
gfx::ReferencePtr aRefPtr, const gfx::IntSize& aSize,
|
||||||
|
gfx::SurfaceFormat aFormat) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TextureData associated with a DrawTarget from another process.
|
||||||
|
*
|
||||||
|
* @param aDrawTarget the key used to find the TextureData
|
||||||
|
* @returns the TextureData found
|
||||||
|
*/
|
||||||
|
TextureData* LookupTextureData(gfx::ReferencePtr aDrawTarget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the SurfaceDescriptor associated with a DrawTarget from another
|
||||||
|
* process to be created and then returns it.
|
||||||
|
*
|
||||||
|
* @param aDrawTarget the key used to find the TextureData
|
||||||
|
* @returns the SurfaceDescriptor found
|
||||||
|
*/
|
||||||
|
UniquePtr<SurfaceDescriptor> WaitForSurfaceDescriptor(
|
||||||
|
gfx::ReferencePtr aDrawTarget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the DrawTarget and other objects associated with a DrawTarget from
|
||||||
|
* another process.
|
||||||
|
*
|
||||||
|
* @param aDrawTarget the key to the objects to remove
|
||||||
|
*/
|
||||||
|
void RemoveDrawTarget(gfx::ReferencePtr aDrawTarget) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the SourceSurface and other objects associated with a SourceSurface
|
||||||
|
* from another process.
|
||||||
|
*
|
||||||
|
* @param aRefPtr the key to the objects to remove
|
||||||
|
*/
|
||||||
|
void RemoveSourceSurface(gfx::ReferencePtr aRefPtr) final {
|
||||||
|
RemoveDataSurface(aRefPtr);
|
||||||
|
InlineTranslator::RemoveSourceSurface(aRefPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached DataSourceSurface, if it exists, associated with a
|
||||||
|
* SourceSurface from another process.
|
||||||
|
*
|
||||||
|
* @param aRefPtr the key used to find the DataSourceSurface
|
||||||
|
* @returns the DataSourceSurface or nullptr if not found
|
||||||
|
*/
|
||||||
|
gfx::DataSourceSurface* LookupDataSurface(gfx::ReferencePtr aRefPtr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to cache the DataSourceSurface from a SourceSurface associated with a
|
||||||
|
* SourceSurface from another process. This is to improve performance if we
|
||||||
|
* require the data for that SourceSurface.
|
||||||
|
*
|
||||||
|
* @param aRefPtr the key used to store the DataSourceSurface
|
||||||
|
* @param aSurface the DataSourceSurface to store
|
||||||
|
*/
|
||||||
|
void AddDataSurface(gfx::ReferencePtr aRefPtr,
|
||||||
|
RefPtr<gfx::DataSourceSurface>&& aSurface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached DataSourceSurface, if it exists, associated with a
|
||||||
|
* SourceSurface from another process.
|
||||||
|
*
|
||||||
|
* @param aRefPtr the key used to find the DataSourceSurface
|
||||||
|
* @returns the DataSourceSurface or nullptr if not found
|
||||||
|
*/
|
||||||
|
void RemoveDataSurface(gfx::ReferencePtr aRefPtr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a ScopedMap, to be used in a later event.
|
||||||
|
*
|
||||||
|
* @param aSurface the associated surface in the other process
|
||||||
|
* @param aMap the ScopedMap to store
|
||||||
|
*/
|
||||||
|
void SetPreparedMap(gfx::ReferencePtr aSurface,
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> aMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ScopedMap stored using SetPreparedMap.
|
||||||
|
*
|
||||||
|
* @param aSurface must match the surface from the SetPreparedMap call
|
||||||
|
* @returns the ScopedMap if aSurface matches otherwise nullptr
|
||||||
|
*/
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> GetPreparedMap(
|
||||||
|
gfx::ReferencePtr aSurface);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CanvasTranslator(const TextureType& aTextureType, TextureData* aTextureData,
|
||||||
|
gfx::DrawTarget* aDrawTarget,
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem);
|
||||||
|
|
||||||
|
void AddSurfaceDescriptor(gfx::ReferencePtr aRefPtr,
|
||||||
|
TextureData* atextureData);
|
||||||
|
|
||||||
|
bool HandleExtensionEvent(int32_t aType);
|
||||||
|
|
||||||
|
CanvasEventRingBuffer mStream;
|
||||||
|
TextureType mTextureType = TextureType::Unknown;
|
||||||
|
UniquePtr<TextureData> mReferenceTextureData;
|
||||||
|
typedef std::unordered_map<void*, UniquePtr<TextureData>> TextureMap;
|
||||||
|
TextureMap mTextureDatas;
|
||||||
|
nsRefPtrHashtable<nsPtrHashKey<void>, gfx::DataSourceSurface> mDataSurfaces;
|
||||||
|
gfx::ReferencePtr mMappedSurface;
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> mPreparedMap;
|
||||||
|
typedef std::unordered_map<void*, UniquePtr<SurfaceDescriptor>> DescriptorMap;
|
||||||
|
DescriptorMap mSurfaceDescriptors;
|
||||||
|
Monitor mSurfaceDescriptorsMonitor{
|
||||||
|
"CanvasTranslator::mSurfaceDescriptorsMonitor"};
|
||||||
|
bool mIsValid = true;
|
||||||
|
bool mIsInTransaction = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_CanvasTranslator_h
|
@ -155,6 +155,16 @@ enum class LayersBackend : int8_t {
|
|||||||
LAYERS_LAST
|
LAYERS_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TextureType : int8_t {
|
||||||
|
Unknown = 0,
|
||||||
|
D3D11,
|
||||||
|
DIB,
|
||||||
|
X11,
|
||||||
|
MacIOSurface,
|
||||||
|
AndroidNativeWindow,
|
||||||
|
Last
|
||||||
|
};
|
||||||
|
|
||||||
enum class BufferMode : int8_t { BUFFER_NONE, BUFFERED };
|
enum class BufferMode : int8_t { BUFFER_NONE, BUFFERED };
|
||||||
|
|
||||||
enum class DrawRegionClip : int8_t { DRAW, NONE };
|
enum class DrawRegionClip : int8_t { DRAW, NONE };
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "mozilla/layers/ShadowLayers.h"
|
#include "mozilla/layers/ShadowLayers.h"
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "pratom.h"
|
#include "pratom.h"
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
|
|
||||||
@ -103,6 +104,21 @@ PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!StaticPrefs::PersistentBufferProviderSharedEnabled()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
// Bug 1285271 - Disable shared buffer provider on Windows with D2D due to
|
||||||
|
// instability, unless we are remoting the canvas drawing to the GPU process.
|
||||||
|
if (gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() ==
|
||||||
|
BackendType::DIRECT2D1_1 &&
|
||||||
|
!TextureData::IsRemote(aKnowsCompositor->GetCompositorBackendType(),
|
||||||
|
BackendSelector::Canvas)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RefPtr<TextureClient> texture = TextureClient::CreateForDrawing(
|
RefPtr<TextureClient> texture = TextureClient::CreateForDrawing(
|
||||||
aKnowsCompositor, aFormat, aSize, BackendSelector::Canvas,
|
aKnowsCompositor, aFormat, aSize, BackendSelector::Canvas,
|
||||||
TextureFlags::DEFAULT | TextureFlags::NON_BLOCKING_READ_LOCK,
|
TextureFlags::DEFAULT | TextureFlags::NON_BLOCKING_READ_LOCK,
|
||||||
@ -332,18 +348,23 @@ PersistentBufferProviderShared::BorrowDrawTarget(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDrawTarget = tex->BorrowDrawTarget();
|
||||||
if (mBack != previousBackBuffer && !aPersistedRect.IsEmpty()) {
|
if (mBack != previousBackBuffer && !aPersistedRect.IsEmpty()) {
|
||||||
TextureClient* previous = GetTexture(previousBackBuffer);
|
if (mPreviousSnapshot) {
|
||||||
if (previous && previous->Lock(OpenMode::OPEN_READ)) {
|
mDrawTarget->CopySurface(mPreviousSnapshot, aPersistedRect,
|
||||||
DebugOnly<bool> success =
|
gfx::IntPoint(0, 0));
|
||||||
previous->CopyToTextureClient(tex, &aPersistedRect, nullptr);
|
} else {
|
||||||
MOZ_ASSERT(success);
|
TextureClient* previous = GetTexture(previousBackBuffer);
|
||||||
|
if (previous && previous->Lock(OpenMode::OPEN_READ)) {
|
||||||
|
DebugOnly<bool> success =
|
||||||
|
previous->CopyToTextureClient(tex, &aPersistedRect, nullptr);
|
||||||
|
MOZ_ASSERT(success);
|
||||||
|
|
||||||
previous->Unlock();
|
previous->Unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mPreviousSnapshot = nullptr;
|
||||||
mDrawTarget = tex->BorrowDrawTarget();
|
|
||||||
|
|
||||||
if (mDrawTarget) {
|
if (mDrawTarget) {
|
||||||
// This is simply to ensure the DrawTarget gets initialized, and will detect
|
// This is simply to ensure the DrawTarget gets initialized, and will detect
|
||||||
@ -366,12 +387,23 @@ bool PersistentBufferProviderShared::ReturnDrawTarget(
|
|||||||
// Can't change the current front buffer while its snapshot is borrowed!
|
// Can't change the current front buffer while its snapshot is borrowed!
|
||||||
MOZ_ASSERT(!mSnapshot);
|
MOZ_ASSERT(!mSnapshot);
|
||||||
|
|
||||||
mDrawTarget = nullptr;
|
|
||||||
dt = nullptr;
|
|
||||||
|
|
||||||
TextureClient* back = GetTexture(mBack);
|
TextureClient* back = GetTexture(mBack);
|
||||||
MOZ_ASSERT(back);
|
MOZ_ASSERT(back);
|
||||||
|
|
||||||
|
// If our TextureClients have internal synchronization then, if locks are
|
||||||
|
// needed for reading and writing, this can cause locking issues with the
|
||||||
|
// compositor. To prevent this we take a snapshot when the DrawTarget is
|
||||||
|
// returned, so this can be used when our own BorrowSnapshot is called and
|
||||||
|
// also for copying to the next TextureClient. Using this snapshot outside of
|
||||||
|
// the locks is safe, because the TextureClient calls DetachAllSnapshots on
|
||||||
|
// its DrawTarget when we Unlock below.
|
||||||
|
if (back->HasSynchronization()) {
|
||||||
|
mPreviousSnapshot = back->BorrowSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
mDrawTarget = nullptr;
|
||||||
|
dt = nullptr;
|
||||||
|
|
||||||
if (back) {
|
if (back) {
|
||||||
back->Unlock();
|
back->Unlock();
|
||||||
mFront = mBack;
|
mFront = mBack;
|
||||||
@ -393,7 +425,17 @@ TextureClient* PersistentBufferProviderShared::GetTextureClient() {
|
|||||||
|
|
||||||
already_AddRefed<gfx::SourceSurface>
|
already_AddRefed<gfx::SourceSurface>
|
||||||
PersistentBufferProviderShared::BorrowSnapshot() {
|
PersistentBufferProviderShared::BorrowSnapshot() {
|
||||||
MOZ_ASSERT(!mDrawTarget);
|
if (mPreviousSnapshot) {
|
||||||
|
mSnapshot = mPreviousSnapshot;
|
||||||
|
return do_AddRef(mSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDrawTarget) {
|
||||||
|
auto back = GetTexture(mBack);
|
||||||
|
MOZ_ASSERT(back && back->IsLocked());
|
||||||
|
mSnapshot = back->BorrowSnapshot();
|
||||||
|
return do_AddRef(mSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
auto front = GetTexture(mFront);
|
auto front = GetTexture(mFront);
|
||||||
if (!front || front->IsLocked()) {
|
if (!front || front->IsLocked()) {
|
||||||
@ -405,17 +447,9 @@ PersistentBufferProviderShared::BorrowSnapshot() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<DrawTarget> dt = front->BorrowDrawTarget();
|
mSnapshot = front->BorrowSnapshot();
|
||||||
|
|
||||||
if (!dt) {
|
return do_AddRef(mSnapshot);
|
||||||
front->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSnapshot = dt->Snapshot();
|
|
||||||
|
|
||||||
RefPtr<SourceSurface> snapshot = mSnapshot;
|
|
||||||
return snapshot.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersistentBufferProviderShared::ReturnSnapshot(
|
void PersistentBufferProviderShared::ReturnSnapshot(
|
||||||
@ -426,6 +460,10 @@ void PersistentBufferProviderShared::ReturnSnapshot(
|
|||||||
mSnapshot = nullptr;
|
mSnapshot = nullptr;
|
||||||
snapshot = nullptr;
|
snapshot = nullptr;
|
||||||
|
|
||||||
|
if (mPreviousSnapshot || mDrawTarget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto front = GetTexture(mFront);
|
auto front = GetTexture(mFront);
|
||||||
if (front) {
|
if (front) {
|
||||||
front->Unlock();
|
front->Unlock();
|
||||||
@ -461,6 +499,7 @@ void PersistentBufferProviderShared::ClearCachedResources() {
|
|||||||
|
|
||||||
void PersistentBufferProviderShared::Destroy() {
|
void PersistentBufferProviderShared::Destroy() {
|
||||||
mSnapshot = nullptr;
|
mSnapshot = nullptr;
|
||||||
|
mPreviousSnapshot = nullptr;
|
||||||
mDrawTarget = nullptr;
|
mDrawTarget = nullptr;
|
||||||
|
|
||||||
for (auto& mTexture : mTextures) {
|
for (auto& mTexture : mTextures) {
|
||||||
|
@ -180,6 +180,7 @@ class PersistentBufferProviderShared : public PersistentBufferProvider,
|
|||||||
|
|
||||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||||
RefPtr<gfx::SourceSurface> mSnapshot;
|
RefPtr<gfx::SourceSurface> mSnapshot;
|
||||||
|
RefPtr<gfx::SourceSurface> mPreviousSnapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AutoReturnSnapshot final {
|
struct AutoReturnSnapshot final {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "mozilla/layers/ProfilerScreenshots.h"
|
#include "mozilla/layers/ProfilerScreenshots.h"
|
||||||
|
|
||||||
|
#include "mozilla/SystemGroup.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::gfx;
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
|
|
||||||
ProfilerScreenshots::ProfilerScreenshots()
|
ProfilerScreenshots::ProfilerScreenshots()
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
|
|
||||||
@ -84,19 +87,19 @@ class ProfilerScreenshots final {
|
|||||||
* Returns null if the limit is reached.
|
* Returns null if the limit is reached.
|
||||||
* Can be called on any thread.
|
* Can be called on any thread.
|
||||||
*/
|
*/
|
||||||
already_AddRefed<DataSourceSurface> TakeNextSurface();
|
already_AddRefed<gfx::DataSourceSurface> TakeNextSurface();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return aSurface back into the mAvailableSurfaces pool. Can be called on
|
* Return aSurface back into the mAvailableSurfaces pool. Can be called on
|
||||||
* any thread.
|
* any thread.
|
||||||
*/
|
*/
|
||||||
void ReturnSurface(DataSourceSurface* aSurface);
|
void ReturnSurface(gfx::DataSourceSurface* aSurface);
|
||||||
|
|
||||||
// The thread on which encoding happens.
|
// The thread on which encoding happens.
|
||||||
nsCOMPtr<nsIThread> mThread;
|
nsCOMPtr<nsIThread> mThread;
|
||||||
// An array of surfaces ready to be recycled. Can be accessed from multiple
|
// An array of surfaces ready to be recycled. Can be accessed from multiple
|
||||||
// threads, protected by mMutex.
|
// threads, protected by mMutex.
|
||||||
nsTArray<RefPtr<DataSourceSurface>> mAvailableSurfaces;
|
nsTArray<RefPtr<gfx::DataSourceSurface>> mAvailableSurfaces;
|
||||||
// Protects mAvailableSurfaces.
|
// Protects mAvailableSurfaces.
|
||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
// The total number of surfaces created. If encoding is fast enough to happen
|
// The total number of surfaces created. If encoding is fast enough to happen
|
||||||
|
384
gfx/layers/RecordedCanvasEventImpl.h
Normal file
384
gfx/layers/RecordedCanvasEventImpl.h
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_RecordedCanvasEventImpl_h
|
||||||
|
#define mozilla_layers_RecordedCanvasEventImpl_h
|
||||||
|
|
||||||
|
#include "mozilla/gfx/RecordedEvent.h"
|
||||||
|
#include "mozilla/gfx/RecordingTypes.h"
|
||||||
|
#include "mozilla/layers/CanvasTranslator.h"
|
||||||
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
|
#include "mozilla/layers/TextureClient.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
using gfx::DrawTarget;
|
||||||
|
using gfx::IntSize;
|
||||||
|
using gfx::RecordedEvent;
|
||||||
|
using gfx::RecordedEventDerived;
|
||||||
|
using EventType = gfx::RecordedEvent::EventType;
|
||||||
|
using gfx::ReadElement;
|
||||||
|
using gfx::ReferencePtr;
|
||||||
|
using gfx::SurfaceFormat;
|
||||||
|
using gfx::WriteElement;
|
||||||
|
using ipc::SharedMemoryBasic;
|
||||||
|
|
||||||
|
const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST;
|
||||||
|
const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1);
|
||||||
|
const EventType CANVAS_FLUSH = EventType(EventType::LAST + 2);
|
||||||
|
const EventType TEXTURE_LOCK = EventType(EventType::LAST + 3);
|
||||||
|
const EventType TEXTURE_UNLOCK = EventType(EventType::LAST + 4);
|
||||||
|
const EventType CACHE_DATA_SURFACE = EventType(EventType::LAST + 5);
|
||||||
|
const EventType PREPARE_DATA_FOR_SURFACE = EventType(EventType::LAST + 6);
|
||||||
|
const EventType GET_DATA_FOR_SURFACE = EventType(EventType::LAST + 7);
|
||||||
|
|
||||||
|
class RecordedCanvasBeginTransaction final
|
||||||
|
: public RecordedEventDerived<RecordedCanvasBeginTransaction> {
|
||||||
|
public:
|
||||||
|
RecordedCanvasBeginTransaction()
|
||||||
|
: RecordedEventDerived(CANVAS_BEGIN_TRANSACTION) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedCanvasBeginTransaction(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedCanvasBeginTransaction"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedCanvasBeginTransaction::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
aTranslator->BeginTransaction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedCanvasBeginTransaction::Record(S& aStream) const {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedCanvasBeginTransaction::RecordedCanvasBeginTransaction(S& aStream)
|
||||||
|
: RecordedEventDerived(CANVAS_BEGIN_TRANSACTION) {}
|
||||||
|
|
||||||
|
class RecordedCanvasEndTransaction final
|
||||||
|
: public RecordedEventDerived<RecordedCanvasEndTransaction> {
|
||||||
|
public:
|
||||||
|
RecordedCanvasEndTransaction()
|
||||||
|
: RecordedEventDerived(CANVAS_END_TRANSACTION) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedCanvasEndTransaction(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedCanvasEndTransaction"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedCanvasEndTransaction::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
aTranslator->EndTransaction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedCanvasEndTransaction::Record(S& aStream) const {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedCanvasEndTransaction::RecordedCanvasEndTransaction(S& aStream)
|
||||||
|
: RecordedEventDerived(CANVAS_END_TRANSACTION) {}
|
||||||
|
|
||||||
|
class RecordedCanvasFlush final
|
||||||
|
: public RecordedEventDerived<RecordedCanvasFlush> {
|
||||||
|
public:
|
||||||
|
RecordedCanvasFlush() : RecordedEventDerived(CANVAS_FLUSH) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedCanvasFlush(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedCanvasFlush"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedCanvasFlush::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
aTranslator->Flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedCanvasFlush::Record(S& aStream) const {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedCanvasFlush::RecordedCanvasFlush(S& aStream)
|
||||||
|
: RecordedEventDerived(CANVAS_FLUSH) {}
|
||||||
|
|
||||||
|
class RecordedTextureLock final
|
||||||
|
: public RecordedEventDerived<RecordedTextureLock> {
|
||||||
|
public:
|
||||||
|
RecordedTextureLock(DrawTarget* aDT, const OpenMode aMode)
|
||||||
|
: RecordedEventDerived(TEXTURE_LOCK), mDT(aDT), mMode(aMode) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedTextureLock(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "TextureLock"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReferencePtr mDT;
|
||||||
|
OpenMode mMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedTextureLock::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
TextureData* textureData = aTranslator->LookupTextureData(mDT);
|
||||||
|
if (!textureData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::AutoSerializeWithMoz2D serializeWithMoz2D(
|
||||||
|
aTranslator->GetReferenceDrawTarget()->GetBackendType());
|
||||||
|
textureData->Lock(mMode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedTextureLock::Record(S& aStream) const {
|
||||||
|
WriteElement(aStream, mDT);
|
||||||
|
WriteElement(aStream, mMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedTextureLock::RecordedTextureLock(S& aStream)
|
||||||
|
: RecordedEventDerived(TEXTURE_LOCK) {
|
||||||
|
ReadElement(aStream, mDT);
|
||||||
|
ReadElement(aStream, mMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordedTextureUnlock final
|
||||||
|
: public RecordedEventDerived<RecordedTextureUnlock> {
|
||||||
|
public:
|
||||||
|
explicit RecordedTextureUnlock(DrawTarget* aDT)
|
||||||
|
: RecordedEventDerived(TEXTURE_UNLOCK), mDT(aDT) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedTextureUnlock(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "TextureUnlock"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReferencePtr mDT;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedTextureUnlock::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
TextureData* textureData = aTranslator->LookupTextureData(mDT);
|
||||||
|
if (!textureData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::AutoSerializeWithMoz2D serializeWithMoz2D(
|
||||||
|
aTranslator->GetReferenceDrawTarget()->GetBackendType());
|
||||||
|
textureData->Unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedTextureUnlock::Record(S& aStream) const {
|
||||||
|
WriteElement(aStream, mDT);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedTextureUnlock::RecordedTextureUnlock(S& aStream)
|
||||||
|
: RecordedEventDerived(TEXTURE_UNLOCK) {
|
||||||
|
ReadElement(aStream, mDT);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordedCacheDataSurface final
|
||||||
|
: public RecordedEventDerived<RecordedCacheDataSurface> {
|
||||||
|
public:
|
||||||
|
explicit RecordedCacheDataSurface(gfx::SourceSurface* aSurface)
|
||||||
|
: RecordedEventDerived(CACHE_DATA_SURFACE), mSurface(aSurface) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedCacheDataSurface(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedCacheDataSurface"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReferencePtr mSurface;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedCacheDataSurface::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
RefPtr<gfx::SourceSurface> surface =
|
||||||
|
aTranslator->LookupSourceSurface(mSurface);
|
||||||
|
|
||||||
|
RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
|
||||||
|
|
||||||
|
aTranslator->AddDataSurface(mSurface, std::move(dataSurface));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedCacheDataSurface::Record(S& aStream) const {
|
||||||
|
WriteElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedCacheDataSurface::RecordedCacheDataSurface(S& aStream)
|
||||||
|
: RecordedEventDerived(CACHE_DATA_SURFACE) {
|
||||||
|
ReadElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordedPrepareDataForSurface final
|
||||||
|
: public RecordedEventDerived<RecordedPrepareDataForSurface> {
|
||||||
|
public:
|
||||||
|
explicit RecordedPrepareDataForSurface(const gfx::SourceSurface* aSurface)
|
||||||
|
: RecordedEventDerived(PREPARE_DATA_FOR_SURFACE), mSurface(aSurface) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedPrepareDataForSurface(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedPrepareDataForSurface"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReferencePtr mSurface;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedPrepareDataForSurface::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
RefPtr<gfx::DataSourceSurface> dataSurface =
|
||||||
|
aTranslator->LookupDataSurface(mSurface);
|
||||||
|
if (!dataSurface) {
|
||||||
|
RefPtr<gfx::SourceSurface> surface =
|
||||||
|
aTranslator->LookupSourceSurface(mSurface);
|
||||||
|
if (!surface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSurface = surface->GetDataSurface();
|
||||||
|
if (!dataSurface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto preparedMap = MakeUnique<gfx::DataSourceSurface::ScopedMap>(
|
||||||
|
dataSurface, gfx::DataSourceSurface::READ);
|
||||||
|
aTranslator->SetPreparedMap(mSurface, std::move(preparedMap));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedPrepareDataForSurface::Record(S& aStream) const {
|
||||||
|
WriteElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedPrepareDataForSurface::RecordedPrepareDataForSurface(S& aStream)
|
||||||
|
: RecordedEventDerived(PREPARE_DATA_FOR_SURFACE) {
|
||||||
|
ReadElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordedGetDataForSurface final
|
||||||
|
: public RecordedEventDerived<RecordedGetDataForSurface> {
|
||||||
|
public:
|
||||||
|
explicit RecordedGetDataForSurface(const gfx::SourceSurface* aSurface)
|
||||||
|
: RecordedEventDerived(GET_DATA_FOR_SURFACE), mSurface(aSurface) {}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
MOZ_IMPLICIT RecordedGetDataForSurface(S& aStream);
|
||||||
|
|
||||||
|
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void Record(S& aStream) const;
|
||||||
|
|
||||||
|
std::string GetName() const final { return "RecordedGetDataForSurface"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReferencePtr mSurface;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool RecordedGetDataForSurface::PlayCanvasEvent(
|
||||||
|
CanvasTranslator* aTranslator) const {
|
||||||
|
RefPtr<gfx::SourceSurface> surface =
|
||||||
|
aTranslator->LookupSourceSurface(mSurface);
|
||||||
|
if (!surface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<gfx::DataSourceSurface::ScopedMap> map =
|
||||||
|
aTranslator->GetPreparedMap(mSurface);
|
||||||
|
|
||||||
|
gfx::IntSize ssSize = surface->GetSize();
|
||||||
|
size_t dataFormatWidth = ssSize.width * BytesPerPixel(surface->GetFormat());
|
||||||
|
int32_t srcStride = map->GetStride();
|
||||||
|
char* src = reinterpret_cast<char*>(map->GetData());
|
||||||
|
char* endSrc = src + (ssSize.height * srcStride);
|
||||||
|
while (src < endSrc) {
|
||||||
|
aTranslator->ReturnWrite(src, dataFormatWidth);
|
||||||
|
src += srcStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
void RecordedGetDataForSurface::Record(S& aStream) const {
|
||||||
|
WriteElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
RecordedGetDataForSurface::RecordedGetDataForSurface(S& aStream)
|
||||||
|
: RecordedEventDerived(GET_DATA_FOR_SURFACE) {
|
||||||
|
ReadElement(aStream, mSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOR_EACH_CANVAS_EVENT(f) \
|
||||||
|
f(CANVAS_BEGIN_TRANSACTION, RecordedCanvasBeginTransaction); \
|
||||||
|
f(CANVAS_END_TRANSACTION, RecordedCanvasEndTransaction); \
|
||||||
|
f(CANVAS_FLUSH, RecordedCanvasFlush); \
|
||||||
|
f(TEXTURE_LOCK, RecordedTextureLock); \
|
||||||
|
f(TEXTURE_UNLOCK, RecordedTextureUnlock); \
|
||||||
|
f(CACHE_DATA_SURFACE, RecordedCacheDataSurface); \
|
||||||
|
f(PREPARE_DATA_FOR_SURFACE, RecordedPrepareDataForSurface); \
|
||||||
|
f(GET_DATA_FOR_SURFACE, RecordedGetDataForSurface);
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_RecordedCanvasEventImpl_h
|
@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/layers/APZInputBridge.h" // for APZInputBridge
|
#include "mozilla/layers/APZInputBridge.h" // for APZInputBridge
|
||||||
#include "mozilla/layers/APZTestData.h" // for APZTestData
|
#include "mozilla/layers/APZTestData.h" // for APZTestData
|
||||||
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
|
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
|
||||||
|
#include "mozilla/layers/LayerAttributes.h"
|
||||||
#include "mozilla/layers/LayersTypes.h"
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
|
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
|
||||||
#include "mozilla/layers/TouchCounter.h" // for TouchCounter
|
#include "mozilla/layers/TouchCounter.h" // for TouchCounter
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "mozilla/gfx/ssse3-scaler.h"
|
#include "mozilla/gfx/ssse3-scaler.h"
|
||||||
#include "mozilla/layers/ImageDataSerializer.h"
|
#include "mozilla/layers/ImageDataSerializer.h"
|
||||||
#include "mozilla/SSE.h"
|
#include "mozilla/SSE.h"
|
||||||
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
#include "gfxUtils.h"
|
#include "gfxUtils.h"
|
||||||
#include "YCbCrUtils.h"
|
#include "YCbCrUtils.h"
|
||||||
|
@ -665,6 +665,8 @@ void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
|
|||||||
AUTO_PROFILER_TRACING("Paint", "ForwardTransaction", GRAPHICS);
|
AUTO_PROFILER_TRACING("Paint", "ForwardTransaction", GRAPHICS);
|
||||||
TimeStamp start = TimeStamp::Now();
|
TimeStamp start = TimeStamp::Now();
|
||||||
|
|
||||||
|
GetCompositorBridgeChild()->EndCanvasTransaction();
|
||||||
|
|
||||||
// Skip the synchronization for buffer since we also skip the painting during
|
// Skip the synchronization for buffer since we also skip the painting during
|
||||||
// device-reset status. With OMTP, we have to wait for async paints
|
// device-reset status. With OMTP, we have to wait for async paints
|
||||||
// before we synchronize and it's done on the paint thread.
|
// before we synchronize and it's done on the paint thread.
|
||||||
@ -862,8 +864,7 @@ ClientLayerManager::CreatePersistentBufferProvider(const gfx::IntSize& aSize,
|
|||||||
// because the canvas will most likely be flattened into a thebes layer
|
// because the canvas will most likely be flattened into a thebes layer
|
||||||
// instead of being sent to the compositor, in which case rendering into
|
// instead of being sent to the compositor, in which case rendering into
|
||||||
// shared memory is wasteful.
|
// shared memory is wasteful.
|
||||||
if (IsCompositingCheap() &&
|
if (IsCompositingCheap()) {
|
||||||
StaticPrefs::PersistentBufferProviderSharedEnabled()) {
|
|
||||||
RefPtr<PersistentBufferProvider> provider =
|
RefPtr<PersistentBufferProvider> provider =
|
||||||
PersistentBufferProviderShared::Create(aSize, aFormat,
|
PersistentBufferProviderShared::Create(aSize, aFormat,
|
||||||
AsShadowForwarder());
|
AsShadowForwarder());
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "Layers.h" // for Layer, etc
|
#include "Layers.h" // for Layer, etc
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "gfxPlatform.h" // for gfxPlatform
|
#include "gfxPlatform.h" // for gfxPlatform
|
||||||
|
#include "MainThreadUtils.h"
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/StaticPrefs.h"
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "mozilla/SystemGroup.h"
|
#include "mozilla/SystemGroup.h"
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#include "mozilla/layers/ImageDataSerializer.h"
|
#include "mozilla/layers/ImageDataSerializer.h"
|
||||||
#include "mozilla/layers/PaintThread.h"
|
#include "mozilla/layers/PaintThread.h"
|
||||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||||
|
#include "mozilla/layers/TextureRecorded.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
|
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
|
||||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||||
@ -235,6 +237,159 @@ class TextureChild final : PTextureChild {
|
|||||||
friend void DeallocateTextureClient(TextureDeallocParams params);
|
friend void DeallocateTextureClient(TextureDeallocParams params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline gfx::BackendType
|
||||||
|
BackendTypeForBackendSelector(LayersBackend aLayersBackend, BackendSelector aSelector)
|
||||||
|
{
|
||||||
|
switch (aSelector) {
|
||||||
|
case BackendSelector::Canvas:
|
||||||
|
return gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
|
||||||
|
case BackendSelector::Content:
|
||||||
|
return gfxPlatform::GetPlatform()->GetContentBackendFor(aLayersBackend);
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Unknown backend selector");
|
||||||
|
return gfx::BackendType::NONE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TextureType
|
||||||
|
GetTextureType(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
|
||||||
|
LayersBackend aLayersBackend, gfx::BackendType aBackendType,
|
||||||
|
int32_t aMaxTextureSize, TextureAllocationFlags aAllocFlags)
|
||||||
|
{
|
||||||
|
#ifdef XP_WIN
|
||||||
|
if ((aLayersBackend == LayersBackend::LAYERS_D3D11 ||
|
||||||
|
aLayersBackend == LayersBackend::LAYERS_WR) &&
|
||||||
|
(aBackendType == gfx::BackendType::DIRECT2D ||
|
||||||
|
aBackendType == gfx::BackendType::DIRECT2D1_1 ||
|
||||||
|
(!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) &&
|
||||||
|
DeviceManagerDx::Get()->GetContentDevice())) &&
|
||||||
|
aSize.width <= aMaxTextureSize &&
|
||||||
|
aSize.height <= aMaxTextureSize &&
|
||||||
|
!(aAllocFlags & ALLOC_UPDATE_FROM_SURFACE)) {
|
||||||
|
return TextureType::D3D11;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aLayersBackend != LayersBackend::LAYERS_WR &&
|
||||||
|
aFormat == SurfaceFormat::B8G8R8X8 &&
|
||||||
|
aBackendType == gfx::BackendType::CAIRO &&
|
||||||
|
NS_IsMainThread()) {
|
||||||
|
return TextureType::DIB;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_X11
|
||||||
|
gfxSurfaceType type =
|
||||||
|
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
|
||||||
|
|
||||||
|
if (aLayersBackend == LayersBackend::LAYERS_BASIC &&
|
||||||
|
aBackendType == gfx::BackendType::CAIRO &&
|
||||||
|
type == gfxSurfaceType::Xlib) {
|
||||||
|
return TextureType::X11;
|
||||||
|
}
|
||||||
|
if (aLayersBackend == LayersBackend::LAYERS_OPENGL &&
|
||||||
|
type == gfxSurfaceType::Xlib &&
|
||||||
|
aFormat != SurfaceFormat::A8 &&
|
||||||
|
gl::sGLXLibrary.UseTextureFromPixmap()) {
|
||||||
|
return TextureType::X11;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
if (StaticPrefs::UseIOSurfaceTextures()) {
|
||||||
|
return TextureType::MacIOSurface;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
if (StaticPrefs::UseSurfaceTextureTextures()) {
|
||||||
|
return TextureType::AndroidNativeWindow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TextureType::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ShouldRemoteTextureType(TextureType aTextureType, BackendSelector aSelector)
|
||||||
|
{
|
||||||
|
if (!XRE_IsContentProcess()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aSelector != BackendSelector::Canvas || !gfxVars::RemoteCanvasEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (aTextureType) {
|
||||||
|
case TextureType::D3D11:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
TextureData*
|
||||||
|
TextureData::Create(TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
|
||||||
|
gfx::IntSize aSize, LayersBackend aLayersBackend,
|
||||||
|
int32_t aMaxTextureSize, BackendSelector aSelector,
|
||||||
|
TextureFlags aTextureFlags,
|
||||||
|
TextureAllocationFlags aAllocFlags)
|
||||||
|
{
|
||||||
|
gfx::BackendType moz2DBackend =
|
||||||
|
BackendTypeForBackendSelector(aLayersBackend, aSelector);
|
||||||
|
|
||||||
|
TextureType textureType = GetTextureType(aFormat, aSize, aLayersBackend,
|
||||||
|
moz2DBackend, aMaxTextureSize,
|
||||||
|
aAllocFlags);
|
||||||
|
|
||||||
|
if (ShouldRemoteTextureType(textureType, aSelector)) {
|
||||||
|
RefPtr<CanvasChild> canvasChild = aAllocator->GetCanvasChild();
|
||||||
|
if (canvasChild) {
|
||||||
|
return new RecordedTextureData(canvasChild.forget(), aSize, aFormat,
|
||||||
|
textureType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(textureType) {
|
||||||
|
#ifdef XP_WIN
|
||||||
|
case TextureType::D3D11:
|
||||||
|
return D3D11TextureData::Create(aSize, aFormat, aAllocFlags);
|
||||||
|
case TextureType::DIB:
|
||||||
|
return DIBTextureData::Create(aSize, aFormat, aAllocator);
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_X11
|
||||||
|
case TextureType::X11:
|
||||||
|
return X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
|
||||||
|
#endif
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
case TextureType::MacIOSurface:
|
||||||
|
return MacIOSurfaceTextureData::Create(aSize, aFormat, moz2DBackend);
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
case TextureType::AndroidNativeWindow:
|
||||||
|
return AndroidNativeWindowTextureData::Create(aSize, aFormat);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
TextureData::IsRemote(LayersBackend aLayersBackend, BackendSelector aSelector)
|
||||||
|
{
|
||||||
|
gfx::BackendType moz2DBackend =
|
||||||
|
BackendTypeForBackendSelector(aLayersBackend, aSelector);
|
||||||
|
|
||||||
|
TextureType textureType =
|
||||||
|
GetTextureType(gfx::SurfaceFormat::UNKNOWN, gfx::IntSize(1,1),
|
||||||
|
aLayersBackend, moz2DBackend, INT32_MAX,
|
||||||
|
TextureAllocationFlags::ALLOC_DEFAULT);
|
||||||
|
|
||||||
|
return ShouldRemoteTextureType(textureType, aSelector);
|
||||||
|
}
|
||||||
|
|
||||||
static void DestroyTextureData(TextureData* aTextureData,
|
static void DestroyTextureData(TextureData* aTextureData,
|
||||||
LayersIPCChannel* aAllocator, bool aDeallocate,
|
LayersIPCChannel* aAllocator, bool aDeallocate,
|
||||||
bool aMainThreadOnly) {
|
bool aMainThreadOnly) {
|
||||||
@ -686,6 +841,17 @@ gfx::DrawTarget* TextureClient::BorrowDrawTarget() {
|
|||||||
return mBorrowedDrawTarget;
|
return mBorrowedDrawTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::SourceSurface> TextureClient::BorrowSnapshot() {
|
||||||
|
MOZ_ASSERT(mIsLocked);
|
||||||
|
|
||||||
|
RefPtr<gfx::SourceSurface> surface = mData->BorrowSnapshot();
|
||||||
|
if (!surface) {
|
||||||
|
surface = BorrowDrawTarget()->Snapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface.forget();
|
||||||
|
}
|
||||||
|
|
||||||
bool TextureClient::BorrowMappedData(MappedTextureData& aMap) {
|
bool TextureClient::BorrowMappedData(MappedTextureData& aMap) {
|
||||||
MOZ_ASSERT(IsValid());
|
MOZ_ASSERT(IsValid());
|
||||||
|
|
||||||
@ -996,19 +1162,6 @@ bool TextureClient::InitIPDLActor(KnowsCompositor* aKnowsCompositor) {
|
|||||||
|
|
||||||
PTextureChild* TextureClient::GetIPDLActor() { return mActor; }
|
PTextureChild* TextureClient::GetIPDLActor() { return mActor; }
|
||||||
|
|
||||||
static inline gfx::BackendType BackendTypeForBackendSelector(
|
|
||||||
LayersBackend aLayersBackend, BackendSelector aSelector) {
|
|
||||||
switch (aSelector) {
|
|
||||||
case BackendSelector::Canvas:
|
|
||||||
return gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
|
|
||||||
case BackendSelector::Content:
|
|
||||||
return gfxPlatform::GetPlatform()->GetContentBackendFor(aLayersBackend);
|
|
||||||
default:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Unknown backend selector");
|
|
||||||
return gfx::BackendType::NONE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
|
already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
|
||||||
KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
|
KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
|
||||||
@ -1043,53 +1196,9 @@ already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureData* data = nullptr;
|
TextureData* data =
|
||||||
|
TextureData::Create(aAllocator, aFormat, aSize, aLayersBackend,
|
||||||
#ifdef XP_WIN
|
aMaxTextureSize, aSelector, aTextureFlags, aAllocFlags);
|
||||||
if ((aLayersBackend == LayersBackend::LAYERS_D3D11 ||
|
|
||||||
aLayersBackend == LayersBackend::LAYERS_WR) &&
|
|
||||||
(moz2DBackend == gfx::BackendType::DIRECT2D ||
|
|
||||||
moz2DBackend == gfx::BackendType::DIRECT2D1_1 ||
|
|
||||||
(!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) &&
|
|
||||||
DeviceManagerDx::Get()->GetContentDevice())) &&
|
|
||||||
aSize.width <= aMaxTextureSize && aSize.height <= aMaxTextureSize &&
|
|
||||||
!(aAllocFlags & ALLOC_UPDATE_FROM_SURFACE)) {
|
|
||||||
data = D3D11TextureData::Create(aSize, aFormat, aAllocFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aLayersBackend != LayersBackend::LAYERS_WR && !data &&
|
|
||||||
aFormat == SurfaceFormat::B8G8R8X8 &&
|
|
||||||
moz2DBackend == gfx::BackendType::CAIRO && NS_IsMainThread()) {
|
|
||||||
data = DIBTextureData::Create(aSize, aFormat, aAllocator);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_X11
|
|
||||||
gfxSurfaceType type =
|
|
||||||
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
|
|
||||||
|
|
||||||
if (!data && aLayersBackend == LayersBackend::LAYERS_BASIC &&
|
|
||||||
moz2DBackend == gfx::BackendType::CAIRO && type == gfxSurfaceType::Xlib) {
|
|
||||||
data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
|
|
||||||
}
|
|
||||||
if (!data && aLayersBackend == LayersBackend::LAYERS_OPENGL &&
|
|
||||||
type == gfxSurfaceType::Xlib && aFormat != SurfaceFormat::A8 &&
|
|
||||||
gl::sGLXLibrary.UseTextureFromPixmap()) {
|
|
||||||
data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
if (!data && StaticPrefs::UseIOSurfaceTextures()) {
|
|
||||||
data = MacIOSurfaceTextureData::Create(aSize, aFormat, moz2DBackend);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
|
||||||
if (!data && StaticPrefs::UseSurfaceTextureTextures()) {
|
|
||||||
data = AndroidNativeWindowTextureData::Create(aSize, aFormat);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
||||||
|
@ -245,7 +245,16 @@ class TextureData {
|
|||||||
canConcurrentlyReadLock(true) {}
|
canConcurrentlyReadLock(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
TextureData() { MOZ_COUNT_CTOR(TextureData); }
|
static TextureData* Create(TextureForwarder* aAllocator,
|
||||||
|
gfx::SurfaceFormat aFormat,
|
||||||
|
gfx::IntSize aSize,
|
||||||
|
LayersBackend aLayersBackend,
|
||||||
|
int32_t aMaxTextureSize,
|
||||||
|
BackendSelector aSelector,
|
||||||
|
TextureFlags aTextureFlags,
|
||||||
|
TextureAllocationFlags aAllocFlags);
|
||||||
|
|
||||||
|
static bool IsRemote(LayersBackend aLayersBackend, BackendSelector aSelector);
|
||||||
|
|
||||||
virtual ~TextureData() { MOZ_COUNT_DTOR(TextureData); }
|
virtual ~TextureData() { MOZ_COUNT_DTOR(TextureData); }
|
||||||
|
|
||||||
@ -259,6 +268,10 @@ class TextureData {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
|
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
|
||||||
|
|
||||||
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
|
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
|
||||||
@ -300,6 +313,9 @@ class TextureData {
|
|||||||
virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
|
virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
|
||||||
|
|
||||||
virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
|
virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextureData() { MOZ_COUNT_CTOR(TextureData); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -430,6 +446,8 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
|
|||||||
*/
|
*/
|
||||||
gfx::DrawTarget* BorrowDrawTarget();
|
gfx::DrawTarget* BorrowDrawTarget();
|
||||||
|
|
||||||
|
already_AddRefed<gfx::SourceSurface> BorrowSnapshot();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to BorrowDrawTarget but provides direct access to the texture's
|
* Similar to BorrowDrawTarget but provides direct access to the texture's
|
||||||
* bits instead of a DrawTarget.
|
* bits instead of a DrawTarget.
|
||||||
|
110
gfx/layers/client/TextureRecorded.cpp
Normal file
110
gfx/layers/client/TextureRecorded.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "TextureRecorded.h"
|
||||||
|
|
||||||
|
#include "RecordedCanvasEventImpl.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceCanvasRecording, final)
|
||||||
|
|
||||||
|
SourceSurfaceCanvasRecording(RefPtr<gfx::SourceSurface>& aRecordedSuface,
|
||||||
|
RefPtr<CanvasChild>& aCanvasChild)
|
||||||
|
: mRecordedSurface(aRecordedSuface), mCanvasChild(aCanvasChild) {}
|
||||||
|
|
||||||
|
gfx::SurfaceType GetType() const final { return mRecordedSurface->GetType(); }
|
||||||
|
|
||||||
|
gfx::IntSize GetSize() const final { return mRecordedSurface->GetSize(); }
|
||||||
|
|
||||||
|
gfx::SurfaceFormat GetFormat() const final {
|
||||||
|
return mRecordedSurface->GetFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DataSourceSurface> GetDataSurface() final {
|
||||||
|
if (!mDataSourceSurface) {
|
||||||
|
mDataSourceSurface = mCanvasChild->GetDataSurface(mRecordedSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(mDataSourceSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<gfx::SourceSurface> mRecordedSurface;
|
||||||
|
RefPtr<CanvasChild> mCanvasChild;
|
||||||
|
RefPtr<gfx::DataSourceSurface> mDataSourceSurface;
|
||||||
|
};
|
||||||
|
|
||||||
|
RecordedTextureData::RecordedTextureData(
|
||||||
|
already_AddRefed<CanvasChild> aCanvasChild, gfx::IntSize aSize,
|
||||||
|
gfx::SurfaceFormat aFormat, TextureType aTextureType)
|
||||||
|
: mCanvasChild(aCanvasChild), mSize(aSize), mFormat(aFormat) {
|
||||||
|
mCanvasChild->EnsureRecorder(aTextureType);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordedTextureData::~RecordedTextureData() {}
|
||||||
|
|
||||||
|
void RecordedTextureData::FillInfo(TextureData::Info& aInfo) const {
|
||||||
|
aInfo.size = mSize;
|
||||||
|
aInfo.format = mFormat;
|
||||||
|
aInfo.supportsMoz2D = true;
|
||||||
|
aInfo.hasIntermediateBuffer = false;
|
||||||
|
aInfo.hasSynchronization = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecordedTextureData::Lock(OpenMode aMode) {
|
||||||
|
mCanvasChild->EnsureBeginTransaction();
|
||||||
|
if (!mDT) {
|
||||||
|
mDT = mCanvasChild->CreateDrawTarget(mSize, mFormat);
|
||||||
|
|
||||||
|
// We lock the TextureData when we create it to get the remote DrawTarget.
|
||||||
|
mCanvasChild->OnTextureWriteLock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCanvasChild->RecordEvent(RecordedTextureLock(mDT.get(), aMode));
|
||||||
|
if (aMode & OpenMode::OPEN_WRITE) {
|
||||||
|
mCanvasChild->OnTextureWriteLock();
|
||||||
|
mSnapshot = nullptr;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordedTextureData::Unlock() {
|
||||||
|
mCanvasChild->RecordEvent(RecordedTextureUnlock(mDT.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DrawTarget> RecordedTextureData::BorrowDrawTarget() {
|
||||||
|
return do_AddRef(mDT);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::SourceSurface> RecordedTextureData::BorrowSnapshot() {
|
||||||
|
MOZ_ASSERT(mDT);
|
||||||
|
|
||||||
|
mSnapshot = mDT->Snapshot();
|
||||||
|
return MakeAndAddRef<SourceSurfaceCanvasRecording>(mSnapshot, mCanvasChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordedTextureData::Deallocate(LayersIPCChannel* aAllocator) {}
|
||||||
|
|
||||||
|
bool RecordedTextureData::Serialize(SurfaceDescriptor& aDescriptor) {
|
||||||
|
SurfaceDescriptorRecorded descriptor;
|
||||||
|
descriptor.drawTarget() = reinterpret_cast<uintptr_t>(mDT.get());
|
||||||
|
aDescriptor = std::move(descriptor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordedTextureData::OnForwardedToHost() {
|
||||||
|
mCanvasChild->OnTextureForwarded();
|
||||||
|
if (mSnapshot && mCanvasChild->ShouldCacheDataSurface()) {
|
||||||
|
mCanvasChild->RecordEvent(RecordedCacheDataSurface(mSnapshot.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
53
gfx/layers/client/TextureRecorded.h
Normal file
53
gfx/layers/client/TextureRecorded.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_TextureRecorded_h
|
||||||
|
#define mozilla_layers_TextureRecorded_h
|
||||||
|
|
||||||
|
#include "TextureClient.h"
|
||||||
|
#include "mozilla/layers/CanvasChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class RecordedTextureData final : public TextureData {
|
||||||
|
public:
|
||||||
|
RecordedTextureData(already_AddRefed<CanvasChild> aCanvasChild,
|
||||||
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||||
|
TextureType aTextureType);
|
||||||
|
|
||||||
|
void FillInfo(TextureData::Info& aInfo) const final;
|
||||||
|
|
||||||
|
bool Lock(OpenMode aMode) final;
|
||||||
|
|
||||||
|
void Unlock() final;
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() final;
|
||||||
|
|
||||||
|
already_AddRefed<gfx::SourceSurface> BorrowSnapshot() final;
|
||||||
|
|
||||||
|
void Deallocate(LayersIPCChannel* aAllocator) final;
|
||||||
|
|
||||||
|
bool Serialize(SurfaceDescriptor& aDescriptor) final;
|
||||||
|
|
||||||
|
void OnForwardedToHost() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(RecordedTextureData);
|
||||||
|
|
||||||
|
~RecordedTextureData() override;
|
||||||
|
|
||||||
|
RefPtr<CanvasChild> mCanvasChild;
|
||||||
|
gfx::IntSize mSize;
|
||||||
|
gfx::SurfaceFormat mFormat;
|
||||||
|
RefPtr<gfx::DrawTarget> mDT;
|
||||||
|
RefPtr<gfx::SourceSurface> mSnapshot;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_TextureRecorded_h
|
@ -11,6 +11,7 @@
|
|||||||
#include "Effects.h" // for EffectMask, Effect, etc
|
#include "Effects.h" // for EffectMask, Effect, etc
|
||||||
#include "gfxUtils.h"
|
#include "gfxUtils.h"
|
||||||
#include "ImageHost.h" // for ImageHostBuffered, etc
|
#include "ImageHost.h" // for ImageHostBuffered, etc
|
||||||
|
#include "Layers.h"
|
||||||
#include "TiledContentHost.h" // for TiledContentHost
|
#include "TiledContentHost.h" // for TiledContentHost
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
|
#include "mozilla/layers/Compositor.h"
|
||||||
#include "mozilla/layers/ProfilerScreenshots.h"
|
#include "mozilla/layers/ProfilerScreenshots.h"
|
||||||
|
#include "mozilla/layers/TextureHost.h"
|
||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
class Compositor;
|
||||||
class CompositorScreenshotGrabberImpl;
|
class CompositorScreenshotGrabberImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,6 +216,16 @@ already_AddRefed<TextureHost> TextureHost::Create(
|
|||||||
result = CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
|
result = CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case SurfaceDescriptor::TSurfaceDescriptorRecorded: {
|
||||||
|
const SurfaceDescriptorRecorded& desc =
|
||||||
|
aDesc.get_SurfaceDescriptorRecorded();
|
||||||
|
UniquePtr<SurfaceDescriptor> realDesc =
|
||||||
|
aDeallocator->AsCompositorBridgeParentBase()
|
||||||
|
->LookupSurfaceDescriptorForClientDrawTarget(desc.drawTarget());
|
||||||
|
result = TextureHost::Create(*realDesc, aReadLock, aDeallocator, aBackend,
|
||||||
|
aFlags, aExternalImageId);
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("GFX: Unsupported Surface type host");
|
MOZ_CRASH("GFX: Unsupported Surface type host");
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc
|
#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc
|
||||||
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
|
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
|
||||||
|
#include "mozilla/layers/PTextureParent.h"
|
||||||
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
|
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
|
||||||
#ifdef XP_DARWIN
|
#ifdef XP_DARWIN
|
||||||
# include "mozilla/layers/TextureSync.h" // for TextureSync
|
# include "mozilla/layers/TextureSync.h" // for TextureSync
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "mozilla/gfx/GPUParent.h"
|
#include "mozilla/gfx/GPUParent.h"
|
||||||
#include "mozilla/gfx/StackArray.h"
|
#include "mozilla/gfx/StackArray.h"
|
||||||
#include "mozilla/layers/DiagnosticsD3D11.h"
|
#include "mozilla/layers/DiagnosticsD3D11.h"
|
||||||
|
#include "mozilla/layers/HelpersD3D11.h"
|
||||||
#include "mozilla/layers/LayerMLGPU.h"
|
#include "mozilla/layers/LayerMLGPU.h"
|
||||||
#include "mozilla/layers/MemoryReportingMLGPU.h"
|
#include "mozilla/layers/MemoryReportingMLGPU.h"
|
||||||
#include "mozilla/layers/ShaderDefinitionsMLGPU.h"
|
#include "mozilla/layers/ShaderDefinitionsMLGPU.h"
|
||||||
@ -18,6 +19,7 @@
|
|||||||
#include "mozilla/widget/CompositorWidget.h"
|
#include "mozilla/widget/CompositorWidget.h"
|
||||||
#include "mozilla/widget/WinCompositorWidget.h"
|
#include "mozilla/widget/WinCompositorWidget.h"
|
||||||
#include "MLGShaders.h"
|
#include "MLGShaders.h"
|
||||||
|
#include "LayersLogging.h"
|
||||||
#include "TextureD3D11.h"
|
#include "TextureD3D11.h"
|
||||||
#include "gfxConfig.h"
|
#include "gfxConfig.h"
|
||||||
#include "mozilla/StaticPrefs.h"
|
#include "mozilla/StaticPrefs.h"
|
||||||
|
@ -13,11 +13,13 @@
|
|||||||
#include "gfxContext.h"
|
#include "gfxContext.h"
|
||||||
#include "mozilla/StaticPrefs.h"
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "gfxWindowsPlatform.h"
|
#include "gfxWindowsPlatform.h"
|
||||||
|
#include "MainThreadUtils.h"
|
||||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||||
|
#include "mozilla/Telemetry.h"
|
||||||
#include "mozilla/webrender/RenderD3D11TextureHostOGL.h"
|
#include "mozilla/webrender/RenderD3D11TextureHostOGL.h"
|
||||||
#include "mozilla/webrender/RenderThread.h"
|
#include "mozilla/webrender/RenderThread.h"
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
@ -726,7 +728,8 @@ already_AddRefed<TextureHost> CreateTextureHostD3D11(
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<DrawTarget> D3D11TextureData::BorrowDrawTarget() {
|
already_AddRefed<DrawTarget> D3D11TextureData::BorrowDrawTarget() {
|
||||||
MOZ_ASSERT(NS_IsMainThread() || PaintThread::IsOnPaintThread());
|
MOZ_ASSERT(NS_IsMainThread() || PaintThread::IsOnPaintThread() ||
|
||||||
|
NS_IsInCanvasThread());
|
||||||
|
|
||||||
if (!mDrawTarget && mTexture) {
|
if (!mDrawTarget && mTexture) {
|
||||||
// This may return a null DrawTarget
|
// This may return a null DrawTarget
|
||||||
|
150
gfx/layers/ipc/CanvasChild.cpp
Normal file
150
gfx/layers/ipc/CanvasChild.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "CanvasChild.h"
|
||||||
|
|
||||||
|
#include "MainThreadUtils.h"
|
||||||
|
#include "mozilla/gfx/DrawTargetRecording.h"
|
||||||
|
#include "mozilla/gfx/Tools.h"
|
||||||
|
#include "mozilla/layers/CanvasDrawEventRecorder.h"
|
||||||
|
#include "RecordedCanvasEventImpl.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
static const TimeDuration kLockWaitTimeout =
|
||||||
|
TimeDuration::FromMilliseconds(100);
|
||||||
|
static const TimeDuration kGetDataTimeout = TimeDuration::FromMilliseconds(500);
|
||||||
|
|
||||||
|
CanvasChild::CanvasChild(Endpoint<PCanvasChild>&& aEndpoint) {
|
||||||
|
aEndpoint.Bind(this);
|
||||||
|
mCanSend = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasChild::~CanvasChild() {}
|
||||||
|
|
||||||
|
void CanvasChild::EnsureRecorder(TextureType aTextureType) {
|
||||||
|
if (!mRecorder) {
|
||||||
|
MOZ_ASSERT(mTextureType == TextureType::Unknown);
|
||||||
|
mTextureType = aTextureType;
|
||||||
|
mRecorder = MakeAndAddRef<CanvasDrawEventRecorder>();
|
||||||
|
SharedMemoryBasic::Handle handle;
|
||||||
|
CrossProcessSemaphoreHandle readerSem;
|
||||||
|
CrossProcessSemaphoreHandle writerSem;
|
||||||
|
RefPtr<CanvasChild> thisRef = this;
|
||||||
|
mRecorder->Init(OtherPid(), &handle, &readerSem, &writerSem,
|
||||||
|
[cc = std::move(thisRef)] { cc->ResumeTranslation(); });
|
||||||
|
|
||||||
|
if (mCanSend) {
|
||||||
|
Unused << SendCreateTranslator(mTextureType, handle, readerSem,
|
||||||
|
writerSem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mTextureType == aTextureType,
|
||||||
|
"We only support one remote TextureType currently.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||||
|
mCanSend = false;
|
||||||
|
|
||||||
|
// Explicitly drop our reference to the recorder, because it holds a reference
|
||||||
|
// to us via the ResumeTranslation callback.
|
||||||
|
mRecorder = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::ResumeTranslation() {
|
||||||
|
if (mCanSend) {
|
||||||
|
SendResumeTranslation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::Destroy() { Close(); }
|
||||||
|
|
||||||
|
void CanvasChild::OnTextureWriteLock() {
|
||||||
|
mHasOutstandingWriteLock = true;
|
||||||
|
mLastWriteLockCheckpoint = mRecorder->CreateCheckpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::OnTextureForwarded() {
|
||||||
|
if (mHasOutstandingWriteLock) {
|
||||||
|
mRecorder->RecordEvent(RecordedCanvasFlush());
|
||||||
|
if (!mRecorder->WaitForCheckpoint(mLastWriteLockCheckpoint,
|
||||||
|
kLockWaitTimeout)) {
|
||||||
|
gfxWarning() << "Timed out waiting for last write lock to be processed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
mHasOutstandingWriteLock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::EnsureBeginTransaction() {
|
||||||
|
if (!mIsInTransaction) {
|
||||||
|
mRecorder->RecordEvent(RecordedCanvasBeginTransaction());
|
||||||
|
mIsInTransaction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::EndTransaction() {
|
||||||
|
if (mIsInTransaction) {
|
||||||
|
mRecorder->RecordEvent(RecordedCanvasEndTransaction());
|
||||||
|
mIsInTransaction = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
++mTransactionsSinceGetDataSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DrawTarget> CanvasChild::CreateDrawTarget(
|
||||||
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
|
||||||
|
MOZ_ASSERT(mRecorder);
|
||||||
|
|
||||||
|
RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(
|
||||||
|
gfx::BackendType::SKIA, gfx::IntSize(1, 1), aFormat);
|
||||||
|
RefPtr<gfx::DrawTarget> dt =
|
||||||
|
MakeAndAddRef<gfx::DrawTargetRecording>(mRecorder, dummyDt, aSize);
|
||||||
|
return dt.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasChild::RecordEvent(const gfx::RecordedEvent& aEvent) {
|
||||||
|
mRecorder->RecordEvent(aEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
|
||||||
|
const gfx::SourceSurface* aSurface) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(aSurface);
|
||||||
|
|
||||||
|
mTransactionsSinceGetDataSurface = 0;
|
||||||
|
EnsureBeginTransaction();
|
||||||
|
mRecorder->RecordEvent(RecordedPrepareDataForSurface(aSurface));
|
||||||
|
uint32_t checkpoint = mRecorder->CreateCheckpoint();
|
||||||
|
|
||||||
|
gfx::IntSize ssSize = aSurface->GetSize();
|
||||||
|
gfx::SurfaceFormat ssFormat = aSurface->GetFormat();
|
||||||
|
size_t dataFormatWidth = ssSize.width * BytesPerPixel(ssFormat);
|
||||||
|
RefPtr<gfx::DataSourceSurface> dataSurface =
|
||||||
|
gfx::Factory::CreateDataSourceSurfaceWithStride(ssSize, ssFormat,
|
||||||
|
dataFormatWidth);
|
||||||
|
if (!dataSurface) {
|
||||||
|
gfxWarning() << "Failed to create DataSourceSurface.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
gfx::DataSourceSurface::ScopedMap map(dataSurface,
|
||||||
|
gfx::DataSourceSurface::READ_WRITE);
|
||||||
|
char* dest = reinterpret_cast<char*>(map.GetData());
|
||||||
|
if (!mRecorder->WaitForCheckpoint(checkpoint, kGetDataTimeout)) {
|
||||||
|
gfxWarning() << "Timed out preparing data for DataSourceSurface.";
|
||||||
|
return dataSurface.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
mRecorder->RecordEvent(RecordedGetDataForSurface(aSurface));
|
||||||
|
mRecorder->ReturnRead(dest, ssSize.height * dataFormatWidth);
|
||||||
|
|
||||||
|
return dataSurface.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
117
gfx/layers/ipc/CanvasChild.h
Normal file
117
gfx/layers/ipc/CanvasChild.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_CanvasChild_h
|
||||||
|
#define mozilla_layers_CanvasChild_h
|
||||||
|
|
||||||
|
#include "mozilla/gfx/RecordedEvent.h"
|
||||||
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/layers/PCanvasChild.h"
|
||||||
|
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class SourceSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace layers {
|
||||||
|
class CanvasDrawEventRecorder;
|
||||||
|
|
||||||
|
class CanvasChild final : public PCanvasChild {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(CanvasChild)
|
||||||
|
|
||||||
|
explicit CanvasChild(Endpoint<PCanvasChild>&& aEndpoint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the DrawEventRecorder has been created.
|
||||||
|
*
|
||||||
|
* @params aTextureType the TextureType to create in the CanvasTranslator.
|
||||||
|
*/
|
||||||
|
void EnsureRecorder(TextureType aTextureType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a messsage to our CanvasParent to resume translation.
|
||||||
|
*/
|
||||||
|
void ResumeTranslation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up IPDL actor.
|
||||||
|
*/
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a RecordedTextureData is write locked.
|
||||||
|
*/
|
||||||
|
void OnTextureWriteLock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a RecordedTextureData is forwarded to the compositor.
|
||||||
|
*/
|
||||||
|
void OnTextureForwarded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if we should be caching data surfaces in the GPU process.
|
||||||
|
*/
|
||||||
|
bool ShouldCacheDataSurface() const {
|
||||||
|
return mTransactionsSinceGetDataSurface < kCacheDataSurfaceThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that we have sent a begin transaction event, since the last
|
||||||
|
* end transaction.
|
||||||
|
*/
|
||||||
|
void EnsureBeginTransaction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an end transaction event to indicate the end of events for this frame.
|
||||||
|
*/
|
||||||
|
void EndTransaction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DrawTargetRecording for a canvas texture.
|
||||||
|
* @param aSize size for the DrawTarget
|
||||||
|
* @param aFormat SurfaceFormat for the DrawTarget
|
||||||
|
* @returns newly created DrawTargetRecording
|
||||||
|
*/
|
||||||
|
already_AddRefed<gfx::DrawTarget> CreateDrawTarget(
|
||||||
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record an event for processing by the CanvasParent's CanvasTranslator.
|
||||||
|
* @param aEvent the event to record
|
||||||
|
*/
|
||||||
|
void RecordEvent(const gfx::RecordedEvent& aEvent);
|
||||||
|
|
||||||
|
already_AddRefed<gfx::DataSourceSurface> GetDataSurface(
|
||||||
|
const gfx::SourceSurface* aSurface);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ActorDestroy(ActorDestroyReason aWhy) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CanvasChild);
|
||||||
|
|
||||||
|
~CanvasChild() final;
|
||||||
|
|
||||||
|
static const uint32_t kCacheDataSurfaceThreshold = 10;
|
||||||
|
|
||||||
|
RefPtr<CanvasDrawEventRecorder> mRecorder;
|
||||||
|
TextureType mTextureType = TextureType::Unknown;
|
||||||
|
uint32_t mLastWriteLockCheckpoint = 0;
|
||||||
|
uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold;
|
||||||
|
bool mCanSend = false;
|
||||||
|
bool mIsInTransaction = false;
|
||||||
|
bool mHasOutstandingWriteLock = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_CanvasChild_h
|
159
gfx/layers/ipc/CanvasParent.cpp
Normal file
159
gfx/layers/ipc/CanvasParent.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "CanvasParent.h"
|
||||||
|
|
||||||
|
#include "base/thread.h"
|
||||||
|
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
||||||
|
#include "mozilla/layers/TextureClient.h"
|
||||||
|
#include "mozilla/SharedThreadPool.h"
|
||||||
|
#include "prsystem.h"
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
|
# include "mozilla/layers/DeviceAttachmentsD3D11.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool NS_IsInCanvasThread() {
|
||||||
|
return mozilla::layers::CanvasParent::IsInCanvasThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
static base::Thread* sCanvasThread = nullptr;
|
||||||
|
static StaticRefPtr<nsIThreadPool> sCanvasWorkers;
|
||||||
|
static bool sShuttingDown = false;
|
||||||
|
|
||||||
|
static MessageLoop* CanvasPlaybackLoop() {
|
||||||
|
if (!sCanvasThread && !sShuttingDown) {
|
||||||
|
MOZ_ASSERT(NS_IsInCompositorThread());
|
||||||
|
base::Thread* canvasThread = new base::Thread("Canvas");
|
||||||
|
if (canvasThread->Start()) {
|
||||||
|
sCanvasThread = canvasThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sCanvasThread ? sCanvasThread->message_loop() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<CanvasParent> CanvasParent::Create(
|
||||||
|
ipc::Endpoint<PCanvasParent>&& aEndpoint) {
|
||||||
|
MOZ_ASSERT(NS_IsInCompositorThread());
|
||||||
|
|
||||||
|
if (sShuttingDown) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<CanvasParent> canvasParent = new CanvasParent();
|
||||||
|
if (CanvasPlaybackLoop()->IsAcceptingTasks()) {
|
||||||
|
RefPtr<Runnable> runnable = NewRunnableMethod<Endpoint<PCanvasParent>&&>(
|
||||||
|
"CanvasParent::Bind", canvasParent, &CanvasParent::Bind,
|
||||||
|
std::move(aEndpoint));
|
||||||
|
CanvasPlaybackLoop()->PostTask(runnable.forget());
|
||||||
|
}
|
||||||
|
return do_AddRef(canvasParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool CanvasParent::IsInCanvasThread() {
|
||||||
|
return (sCanvasWorkers && sCanvasWorkers->IsOnCurrentThread()) ||
|
||||||
|
(sCanvasThread &&
|
||||||
|
sCanvasThread->thread_id() == PlatformThread::CurrentId());
|
||||||
|
}
|
||||||
|
|
||||||
|
static already_AddRefed<nsIThreadPool> GetCanvasWorkers() {
|
||||||
|
if (!sCanvasWorkers && !sShuttingDown) {
|
||||||
|
// Given that the canvas workers are receiving instructions from content
|
||||||
|
// processes, it probably doesn't make sense to have more than half the
|
||||||
|
// number of processors doing canvas drawing. We set the lower limit to 2,
|
||||||
|
// so that even on single processor systems, if there is more than one
|
||||||
|
// window with canvas drawing, the OS can manage the load between them.
|
||||||
|
uint32_t threadLimit = std::max(2, PR_GetNumberOfProcessors() / 2);
|
||||||
|
sCanvasWorkers =
|
||||||
|
SharedThreadPool::Get(NS_LITERAL_CSTRING("CanvasWorkers"), threadLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(sCanvasWorkers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void CanvasParent::Shutdown() {
|
||||||
|
sShuttingDown = true;
|
||||||
|
|
||||||
|
if (sCanvasThread) {
|
||||||
|
sCanvasThread->Stop();
|
||||||
|
delete sCanvasThread;
|
||||||
|
sCanvasThread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCanvasWorkers) {
|
||||||
|
sCanvasWorkers->Shutdown();
|
||||||
|
sCanvasWorkers = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasParent::CanvasParent() {}
|
||||||
|
|
||||||
|
CanvasParent::~CanvasParent() {}
|
||||||
|
|
||||||
|
void CanvasParent::Bind(Endpoint<PCanvasParent>&& aEndpoint) {
|
||||||
|
if (!aEndpoint.Bind(this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelfRef = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult CanvasParent::RecvCreateTranslator(
|
||||||
|
const TextureType& aTextureType,
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem) {
|
||||||
|
mTranslator = CanvasTranslator::Create(aTextureType, aReadHandle, aReaderSem,
|
||||||
|
aWriterSem);
|
||||||
|
return RecvResumeTranslation();
|
||||||
|
}
|
||||||
|
|
||||||
|
ipc::IPCResult CanvasParent::RecvResumeTranslation() {
|
||||||
|
MOZ_ASSERT(mTranslator);
|
||||||
|
|
||||||
|
if (!mTranslator->IsValid()) {
|
||||||
|
return IPC_FAIL(this, "Canvas Translation failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PostStartTranslationTask(nsIThread::DISPATCH_NORMAL);
|
||||||
|
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasParent::PostStartTranslationTask(uint32_t aDispatchFlags) {
|
||||||
|
if (sShuttingDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<nsIThreadPool> canvasWorkers = GetCanvasWorkers();
|
||||||
|
RefPtr<Runnable> runnable = NewRunnableMethod(
|
||||||
|
"CanvasParent::StartTranslation", this, &CanvasParent::StartTranslation);
|
||||||
|
canvasWorkers->Dispatch(runnable.forget(), aDispatchFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasParent::StartTranslation() {
|
||||||
|
if (!mTranslator->TranslateRecording()) {
|
||||||
|
PostStartTranslationTask(nsIThread::DISPATCH_AT_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<SurfaceDescriptor>
|
||||||
|
CanvasParent::LookupSurfaceDescriptorForClientDrawTarget(
|
||||||
|
const uintptr_t aDrawTarget) {
|
||||||
|
return mTranslator->WaitForSurfaceDescriptor(
|
||||||
|
reinterpret_cast<void*>(aDrawTarget));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasParent::DeallocPCanvasParent() { mSelfRef = nullptr; }
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
97
gfx/layers/ipc/CanvasParent.h
Normal file
97
gfx/layers/ipc/CanvasParent.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_layers_CanvasParent_h
|
||||||
|
#define mozilla_layers_CanvasParent_h
|
||||||
|
|
||||||
|
#include "mozilla/ipc/CrossProcessSemaphore.h"
|
||||||
|
#include "mozilla/layers/CanvasTranslator.h"
|
||||||
|
#include "mozilla/layers/PCanvasParent.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
class TextureData;
|
||||||
|
|
||||||
|
class CanvasParent final : public PCanvasParent {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CanvasParent)
|
||||||
|
|
||||||
|
friend class PProtocolParent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a CanvasParent and bind it to the given endpoint on the
|
||||||
|
* CanvasPlaybackLoop.
|
||||||
|
*
|
||||||
|
* @params aEndpoint the endpoint to bind to
|
||||||
|
* @returns the new CanvasParent
|
||||||
|
*/
|
||||||
|
static already_AddRefed<CanvasParent> Create(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint);
|
||||||
|
|
||||||
|
static bool IsInCanvasThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the canvas thread.
|
||||||
|
*/
|
||||||
|
static void Shutdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a canvas translator for a particular TextureType, which translates
|
||||||
|
* events from a CanvasEventRingBuffer.
|
||||||
|
*
|
||||||
|
* @param aTextureType the TextureType the translator will create
|
||||||
|
* @param aReadHandle handle to the shared memory for the
|
||||||
|
* CanvasEventRingBuffer
|
||||||
|
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
|
||||||
|
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
|
||||||
|
*/
|
||||||
|
ipc::IPCResult RecvCreateTranslator(
|
||||||
|
const TextureType& aTextureType,
|
||||||
|
const ipc::SharedMemoryBasic::Handle& aReadHandle,
|
||||||
|
const CrossProcessSemaphoreHandle& aReaderSem,
|
||||||
|
const CrossProcessSemaphoreHandle& aWriterSem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to tell the CanvasTranslator to start translating again after it has
|
||||||
|
* stopped due to a timeout waiting for events.
|
||||||
|
*/
|
||||||
|
ipc::IPCResult RecvResumeTranslation();
|
||||||
|
|
||||||
|
void ActorDestroy(ActorDestroyReason why) final {}
|
||||||
|
|
||||||
|
void DeallocPCanvasParent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the compositor thread to get the SurfaceDescriptor associated with
|
||||||
|
* the DrawTarget from another process.
|
||||||
|
*
|
||||||
|
* @param aDrawTarget the key to find the TextureData
|
||||||
|
* @returns the SurfaceDescriptor associated with the key
|
||||||
|
*/
|
||||||
|
UniquePtr<SurfaceDescriptor> LookupSurfaceDescriptorForClientDrawTarget(
|
||||||
|
const uintptr_t aDrawTarget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CanvasParent();
|
||||||
|
~CanvasParent() final;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CanvasParent);
|
||||||
|
|
||||||
|
void Bind(Endpoint<PCanvasParent>&& aEndpoint);
|
||||||
|
|
||||||
|
void PostStartTranslationTask(uint32_t aDispatchFlags);
|
||||||
|
|
||||||
|
void StartTranslation();
|
||||||
|
|
||||||
|
RefPtr<CanvasParent> mSelfRef;
|
||||||
|
UniquePtr<CanvasTranslator> mTranslator;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_layers_CanvasParent_h
|
@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/layers/APZChild.h"
|
#include "mozilla/layers/APZChild.h"
|
||||||
#include "mozilla/layers/IAPZCTreeManager.h"
|
#include "mozilla/layers/IAPZCTreeManager.h"
|
||||||
#include "mozilla/layers/APZCTreeManagerChild.h"
|
#include "mozilla/layers/APZCTreeManagerChild.h"
|
||||||
|
#include "mozilla/layers/CanvasChild.h"
|
||||||
#include "mozilla/layers/LayerTransactionChild.h"
|
#include "mozilla/layers/LayerTransactionChild.h"
|
||||||
#include "mozilla/layers/PaintThread.h"
|
#include "mozilla/layers/PaintThread.h"
|
||||||
#include "mozilla/layers/PLayerTransactionChild.h"
|
#include "mozilla/layers/PLayerTransactionChild.h"
|
||||||
@ -117,6 +118,10 @@ void CompositorBridgeChild::AfterDestroy() {
|
|||||||
mActorDestroyed = true;
|
mActorDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCanvasChild) {
|
||||||
|
mCanvasChild->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
if (sCompositorBridge == this) {
|
if (sCompositorBridge == this) {
|
||||||
sCompositorBridge = nullptr;
|
sCompositorBridge = nullptr;
|
||||||
}
|
}
|
||||||
@ -245,6 +250,18 @@ void CompositorBridgeChild::InitForContent(uint32_t aNamespace) {
|
|||||||
|
|
||||||
mCanSend = true;
|
mCanSend = true;
|
||||||
mIdNamespace = aNamespace;
|
mIdNamespace = aNamespace;
|
||||||
|
|
||||||
|
if (gfx::gfxVars::RemoteCanvasEnabled()) {
|
||||||
|
ipc::Endpoint<PCanvasParent> parentEndpoint;
|
||||||
|
ipc::Endpoint<PCanvasChild> childEndpoint;
|
||||||
|
nsresult rv = PCanvas::CreateEndpoints(OtherPid(), base::GetCurrentProcId(),
|
||||||
|
&parentEndpoint, &childEndpoint);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
Unused << SendInitPCanvasParent(std::move(parentEndpoint));
|
||||||
|
mCanvasChild = new CanvasChild(std::move(childEndpoint));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sCompositorBridge = this;
|
sCompositorBridge = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,6 +935,16 @@ PTextureChild* CompositorBridgeChild::CreateTexture(
|
|||||||
LayersId{0} /* FIXME? */, aSerial, aExternalImageId);
|
LayersId{0} /* FIXME? */, aSerial, aExternalImageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<CanvasChild> CompositorBridgeChild::GetCanvasChild() {
|
||||||
|
return do_AddRef(mCanvasChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositorBridgeChild::EndCanvasTransaction() {
|
||||||
|
if (mCanvasChild) {
|
||||||
|
mCanvasChild->EndTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CompositorBridgeChild::AllocUnsafeShmem(
|
bool CompositorBridgeChild::AllocUnsafeShmem(
|
||||||
size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
|
size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
|
||||||
ipc::Shmem* aShmem) {
|
ipc::Shmem* aShmem) {
|
||||||
|
@ -41,6 +41,7 @@ using mozilla::dom::BrowserChild;
|
|||||||
|
|
||||||
class IAPZCTreeManager;
|
class IAPZCTreeManager;
|
||||||
class APZCTreeManagerChild;
|
class APZCTreeManagerChild;
|
||||||
|
class CanvasChild;
|
||||||
class ClientLayerManager;
|
class ClientLayerManager;
|
||||||
class CompositorBridgeParent;
|
class CompositorBridgeParent;
|
||||||
class CompositorManagerChild;
|
class CompositorManagerChild;
|
||||||
@ -122,6 +123,10 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
|
|||||||
wr::MaybeExternalImageId& aExternalImageId,
|
wr::MaybeExternalImageId& aExternalImageId,
|
||||||
nsIEventTarget* aTarget) override;
|
nsIEventTarget* aTarget) override;
|
||||||
|
|
||||||
|
already_AddRefed<CanvasChild> GetCanvasChild() final;
|
||||||
|
|
||||||
|
void EndCanvasTransaction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that the parent tell us when graphics are ready on GPU.
|
* Request that the parent tell us when graphics are ready on GPU.
|
||||||
* When we get that message, we bounce it to the BrowserParent via
|
* When we get that message, we bounce it to the BrowserParent via
|
||||||
@ -391,6 +396,8 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
|
|||||||
|
|
||||||
uintptr_t mSlowFlushCount;
|
uintptr_t mSlowFlushCount;
|
||||||
uintptr_t mTotalFlushCount;
|
uintptr_t mTotalFlushCount;
|
||||||
|
|
||||||
|
RefPtr<CanvasChild> mCanvasChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
@ -1871,7 +1871,7 @@ Maybe<TimeStamp> CompositorBridgeParent::GetTestingTimeStamp() const {
|
|||||||
return mTestTime;
|
return mTestTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EraseLayerState(LayersId aId) {
|
void EraseLayerState(LayersId aId) {
|
||||||
RefPtr<APZUpdater> apz;
|
RefPtr<APZUpdater> apz;
|
||||||
|
|
||||||
{ // scope lock
|
{ // scope lock
|
||||||
@ -2189,8 +2189,8 @@ void CompositorBridgeParent::InvalidateRemoteLayers() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateIndirectTree(LayersId aId, Layer* aRoot,
|
void UpdateIndirectTree(LayersId aId, Layer* aRoot,
|
||||||
const TargetConfig& aTargetConfig) {
|
const TargetConfig& aTargetConfig) {
|
||||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||||
sIndirectLayerTrees[aId].mRoot = aRoot;
|
sIndirectLayerTrees[aId].mRoot = aRoot;
|
||||||
sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
|
sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
|
||||||
@ -2283,6 +2283,11 @@ bool CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor) {
|
|||||||
return TextureHost::DestroyIPDLActor(actor);
|
return TextureHost::DestroyIPDLActor(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvInitPCanvasParent(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint) {
|
||||||
|
MOZ_CRASH("PCanvasParent shouldn't be created via CompositorBridgeParent.");
|
||||||
|
}
|
||||||
|
|
||||||
bool CompositorBridgeParent::IsSameProcess() const {
|
bool CompositorBridgeParent::IsSameProcess() const {
|
||||||
return OtherPid() == base::GetCurrentProcId();
|
return OtherPid() == base::GetCurrentProcId();
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ class PAPZParent;
|
|||||||
class ContentCompositorBridgeParent;
|
class ContentCompositorBridgeParent;
|
||||||
class CompositorThreadHolder;
|
class CompositorThreadHolder;
|
||||||
class InProcessCompositorSession;
|
class InProcessCompositorSession;
|
||||||
|
class TextureData;
|
||||||
class WebRenderBridgeParent;
|
class WebRenderBridgeParent;
|
||||||
|
|
||||||
struct ScopedLayerTreeRegistration {
|
struct ScopedLayerTreeRegistration {
|
||||||
@ -188,6 +189,11 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
|
|||||||
|
|
||||||
virtual bool IsRemote() const { return false; }
|
virtual bool IsRemote() const { return false; }
|
||||||
|
|
||||||
|
virtual UniquePtr<SurfaceDescriptor>
|
||||||
|
LookupSurfaceDescriptorForClientDrawTarget(const uintptr_t aDrawTarget) {
|
||||||
|
MOZ_CRASH("Should only be called on ContentCompositorBridgeParent.");
|
||||||
|
}
|
||||||
|
|
||||||
virtual void ForceComposeToTarget(gfx::DrawTarget* aTarget,
|
virtual void ForceComposeToTarget(gfx::DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect = nullptr) {
|
const gfx::IntRect* aRect = nullptr) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
@ -265,6 +271,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
|
|||||||
const uint32_t& startIndex, nsTArray<float>* intervals) = 0;
|
const uint32_t& startIndex, nsTArray<float>* intervals) = 0;
|
||||||
virtual mozilla::ipc::IPCResult RecvCheckContentOnlyTDR(
|
virtual mozilla::ipc::IPCResult RecvCheckContentOnlyTDR(
|
||||||
const uint32_t& sequenceNum, bool* isContentOnlyTDR) = 0;
|
const uint32_t& sequenceNum, bool* isContentOnlyTDR) = 0;
|
||||||
|
virtual mozilla::ipc::IPCResult RecvInitPCanvasParent(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint) = 0;
|
||||||
|
|
||||||
bool mCanSend;
|
bool mCanSend;
|
||||||
|
|
||||||
@ -388,6 +396,9 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
|||||||
const wr::MaybeExternalImageId& aExternalImageId) override;
|
const wr::MaybeExternalImageId& aExternalImageId) override;
|
||||||
bool DeallocPTextureParent(PTextureParent* actor) override;
|
bool DeallocPTextureParent(PTextureParent* actor) override;
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvInitPCanvasParent(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint) final;
|
||||||
|
|
||||||
bool IsSameProcess() const override;
|
bool IsSameProcess() const override;
|
||||||
|
|
||||||
void NotifyWebRenderContextPurge();
|
void NotifyWebRenderContextPurge();
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "CompositorBridgeParent.h"
|
#include "CompositorBridgeParent.h"
|
||||||
|
#include "mozilla/layers/CanvasParent.h"
|
||||||
#include "mozilla/layers/CompositorManagerParent.h"
|
#include "mozilla/layers/CompositorManagerParent.h"
|
||||||
#include "mozilla/layers/ImageBridgeParent.h"
|
#include "mozilla/layers/ImageBridgeParent.h"
|
||||||
#include "mozilla/media/MediaSystemResourceService.h"
|
#include "mozilla/media/MediaSystemResourceService.h"
|
||||||
@ -127,6 +128,7 @@ void CompositorThreadHolder::Shutdown() {
|
|||||||
gfx::ReleaseVRManagerParentSingleton();
|
gfx::ReleaseVRManagerParentSingleton();
|
||||||
MediaSystemResourceService::Shutdown();
|
MediaSystemResourceService::Shutdown();
|
||||||
CompositorManagerParent::Shutdown();
|
CompositorManagerParent::Shutdown();
|
||||||
|
CanvasParent::Shutdown();
|
||||||
|
|
||||||
sCompositorThreadHolder = nullptr;
|
sCompositorThreadHolder = nullptr;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "base/message_loop.h" // for MessageLoop
|
#include "base/message_loop.h" // for MessageLoop
|
||||||
#include "base/task.h" // for CancelableTask, etc
|
#include "base/task.h" // for CancelableTask, etc
|
||||||
#include "base/thread.h" // for Thread
|
#include "base/thread.h" // for Thread
|
||||||
|
#include "gfxUtils.h"
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
# include "mozilla/gfx/DeviceManagerDx.h" // for DeviceManagerDx
|
# include "mozilla/gfx/DeviceManagerDx.h" // for DeviceManagerDx
|
||||||
#endif
|
#endif
|
||||||
@ -21,6 +22,7 @@
|
|||||||
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
|
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
|
||||||
#include "mozilla/layers/APZUpdater.h" // for APZUpdater
|
#include "mozilla/layers/APZUpdater.h" // for APZUpdater
|
||||||
#include "mozilla/layers/AsyncCompositionManager.h"
|
#include "mozilla/layers/AsyncCompositionManager.h"
|
||||||
|
#include "mozilla/layers/CanvasParent.h"
|
||||||
#include "mozilla/layers/CompositorOptions.h"
|
#include "mozilla/layers/CompositorOptions.h"
|
||||||
#include "mozilla/layers/CompositorThread.h"
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
#include "mozilla/layers/LayerManagerComposite.h"
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
@ -35,7 +37,10 @@
|
|||||||
#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
|
#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "gfxUtils.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -306,12 +311,12 @@ mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvCheckContentOnlyTDR(
|
|||||||
const uint32_t& sequenceNum, bool* isContentOnlyTDR) {
|
const uint32_t& sequenceNum, bool* isContentOnlyTDR) {
|
||||||
*isContentOnlyTDR = false;
|
*isContentOnlyTDR = false;
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
ContentDeviceData compositor;
|
gfx::ContentDeviceData compositor;
|
||||||
|
|
||||||
DeviceManagerDx* dm = DeviceManagerDx::Get();
|
gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get();
|
||||||
|
|
||||||
// Check that the D3D11 device sequence numbers match.
|
// Check that the D3D11 device sequence numbers match.
|
||||||
D3D11DeviceStatus status;
|
gfx::D3D11DeviceStatus status;
|
||||||
dm->ExportDeviceInfo(&status);
|
dm->ExportDeviceInfo(&status);
|
||||||
|
|
||||||
if (sequenceNum == status.sequenceNumber() && !dm->HasDeviceReset()) {
|
if (sequenceNum == status.sequenceNumber() && !dm->HasDeviceReset()) {
|
||||||
@ -610,6 +615,22 @@ bool ContentCompositorBridgeParent::DeallocPTextureParent(
|
|||||||
return TextureHost::DestroyIPDLActor(actor);
|
return TextureHost::DestroyIPDLActor(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvInitPCanvasParent(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint) {
|
||||||
|
MOZ_RELEASE_ASSERT(!mCanvasParent,
|
||||||
|
"Canvas Parent should only be created once per "
|
||||||
|
"CrossProcessCompositorBridgeParent.");
|
||||||
|
|
||||||
|
mCanvasParent = CanvasParent::Create(std::move(aEndpoint));
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<SurfaceDescriptor>
|
||||||
|
ContentCompositorBridgeParent::LookupSurfaceDescriptorForClientDrawTarget(
|
||||||
|
const uintptr_t aDrawTarget) {
|
||||||
|
return mCanvasParent->LookupSurfaceDescriptorForClientDrawTarget(aDrawTarget);
|
||||||
|
}
|
||||||
|
|
||||||
bool ContentCompositorBridgeParent::IsSameProcess() const {
|
bool ContentCompositorBridgeParent::IsSameProcess() const {
|
||||||
return OtherPid() == base::GetCurrentProcId();
|
return OtherPid() == base::GetCurrentProcId();
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
|
|
||||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||||
#include "mozilla/layers/CompositorThread.h"
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
class CanvasParent;
|
||||||
class CompositorOptions;
|
class CompositorOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,6 +155,9 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
|
|||||||
|
|
||||||
bool DeallocPTextureParent(PTextureParent* actor) override;
|
bool DeallocPTextureParent(PTextureParent* actor) override;
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvInitPCanvasParent(
|
||||||
|
Endpoint<PCanvasParent>&& aEndpoint) final;
|
||||||
|
|
||||||
bool IsSameProcess() const override;
|
bool IsSameProcess() const override;
|
||||||
|
|
||||||
PCompositorWidgetParent* AllocPCompositorWidgetParent(
|
PCompositorWidgetParent* AllocPCompositorWidgetParent(
|
||||||
@ -188,6 +193,9 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
|
|||||||
|
|
||||||
bool IsRemote() const override { return true; }
|
bool IsRemote() const override { return true; }
|
||||||
|
|
||||||
|
UniquePtr<SurfaceDescriptor> LookupSurfaceDescriptorForClientDrawTarget(
|
||||||
|
const uintptr_t aDrawTarget) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Private destructor, to discourage deletion outside of Release():
|
// Private destructor, to discourage deletion outside of Release():
|
||||||
virtual ~ContentCompositorBridgeParent();
|
virtual ~ContentCompositorBridgeParent();
|
||||||
@ -203,6 +211,8 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
|
|||||||
// transaction is received
|
// transaction is received
|
||||||
bool mNotifyAfterRemotePaint;
|
bool mNotifyAfterRemotePaint;
|
||||||
bool mDestroyCalled;
|
bool mDestroyCalled;
|
||||||
|
|
||||||
|
RefPtr<CanvasParent> mCanvasParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
|
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
|
||||||
#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
|
#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
|
||||||
#include "mozilla/ipc/Transport.h" // for Transport
|
#include "mozilla/ipc/Transport.h" // for Transport
|
||||||
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "mozilla/layers/AsyncCanvasRenderer.h"
|
#include "mozilla/layers/AsyncCanvasRenderer.h"
|
||||||
#include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
|
#include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
|
||||||
|
@ -82,6 +82,13 @@ struct ParamTraits<mozilla::layers::LayersBackend>
|
|||||||
mozilla::layers::LayersBackend::LAYERS_NONE,
|
mozilla::layers::LayersBackend::LAYERS_NONE,
|
||||||
mozilla::layers::LayersBackend::LAYERS_LAST> {};
|
mozilla::layers::LayersBackend::LAYERS_LAST> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::layers::TextureType>
|
||||||
|
: public ContiguousEnumSerializer<
|
||||||
|
mozilla::layers::TextureType,
|
||||||
|
mozilla::layers::TextureType::Unknown,
|
||||||
|
mozilla::layers::TextureType::Last> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::layers::ScaleMode>
|
struct ParamTraits<mozilla::layers::ScaleMode>
|
||||||
: public ContiguousEnumSerializerInclusive<
|
: public ContiguousEnumSerializerInclusive<
|
||||||
|
@ -133,6 +133,10 @@ struct SurfaceDescriptorShared
|
|||||||
Handle handle;
|
Handle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceDescriptorRecorded {
|
||||||
|
uintptr_t drawTarget;
|
||||||
|
};
|
||||||
|
|
||||||
union SurfaceDescriptor {
|
union SurfaceDescriptor {
|
||||||
SurfaceDescriptorBuffer;
|
SurfaceDescriptorBuffer;
|
||||||
SurfaceDescriptorDIB;
|
SurfaceDescriptorDIB;
|
||||||
@ -145,6 +149,7 @@ union SurfaceDescriptor {
|
|||||||
SurfaceDescriptorMacIOSurface;
|
SurfaceDescriptorMacIOSurface;
|
||||||
SurfaceDescriptorSharedGLTexture;
|
SurfaceDescriptorSharedGLTexture;
|
||||||
SurfaceDescriptorGPUVideo;
|
SurfaceDescriptorGPUVideo;
|
||||||
|
SurfaceDescriptorRecorded;
|
||||||
null_t;
|
null_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
37
gfx/layers/ipc/PCanvas.ipdl
Normal file
37
gfx/layers/ipc/PCanvas.ipdl
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* vim: sw=2 ts=8 et : */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
|
||||||
|
using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h";
|
||||||
|
using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PCanvas is the IPDL for recorded Canvas drawing.
|
||||||
|
*/
|
||||||
|
sync protocol PCanvas {
|
||||||
|
parent:
|
||||||
|
/**
|
||||||
|
* Create a CanvasTranslator for a particular TextureType, which translates
|
||||||
|
* events from a CanvasEventRingBuffer. aReadHandle is the shared memory
|
||||||
|
* handle for the ring buffer. aReaderSem and aWriterSem are handles for the
|
||||||
|
* semaphores to handle waiting on either side.
|
||||||
|
*/
|
||||||
|
async CreateTranslator(TextureType aTextureType, Handle aReadHandle,
|
||||||
|
CrossProcessSemaphoreHandle aReaderSem,
|
||||||
|
CrossProcessSemaphoreHandle aWriterSem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to tell the CanvasTranslator to start translating again after it has
|
||||||
|
* stopped due to a timeout waiting for events.
|
||||||
|
*/
|
||||||
|
async ResumeTranslation();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // layers
|
||||||
|
} // mozilla
|
@ -11,6 +11,7 @@ include PlatformWidgetTypes;
|
|||||||
include protocol PAPZ;
|
include protocol PAPZ;
|
||||||
include protocol PAPZCTreeManager;
|
include protocol PAPZCTreeManager;
|
||||||
include protocol PBrowser;
|
include protocol PBrowser;
|
||||||
|
include protocol PCanvas;
|
||||||
include protocol PCompositorManager;
|
include protocol PCompositorManager;
|
||||||
include protocol PCompositorWidget;
|
include protocol PCompositorWidget;
|
||||||
include protocol PLayerTransaction;
|
include protocol PLayerTransaction;
|
||||||
@ -255,6 +256,8 @@ parent:
|
|||||||
|
|
||||||
async PTexture(SurfaceDescriptor aSharedData, ReadLockDescriptor aReadLock, LayersBackend aBackend, TextureFlags aTextureFlags, LayersId id, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
|
async PTexture(SurfaceDescriptor aSharedData, ReadLockDescriptor aReadLock, LayersBackend aBackend, TextureFlags aTextureFlags, LayersId id, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
|
||||||
|
|
||||||
|
async InitPCanvasParent(Endpoint<PCanvasParent> aEndpoint);
|
||||||
|
|
||||||
sync SyncWithCompositor();
|
sync SyncWithCompositor();
|
||||||
|
|
||||||
// The pipelineId is the same as the layersId
|
// The pipelineId is the same as the layersId
|
||||||
|
@ -19,6 +19,7 @@ namespace ipc {
|
|||||||
class IShmemAllocator;
|
class IShmemAllocator;
|
||||||
}
|
}
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
class CanvasChild;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract interface for classes that implement the autogenerated
|
* An abstract interface for classes that implement the autogenerated
|
||||||
@ -78,6 +79,11 @@ class TextureForwarder : public LayersIPCChannel {
|
|||||||
LayersBackend aLayersBackend, TextureFlags aFlags, uint64_t aSerial,
|
LayersBackend aLayersBackend, TextureFlags aFlags, uint64_t aSerial,
|
||||||
wr::MaybeExternalImageId& aExternalImageId,
|
wr::MaybeExternalImageId& aExternalImageId,
|
||||||
nsIEventTarget* aTarget = nullptr) = 0;
|
nsIEventTarget* aTarget = nullptr) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the CanvasChild for this TextureForwarder.
|
||||||
|
*/
|
||||||
|
virtual already_AddRefed<CanvasChild> GetCanvasChild() { return nullptr; };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
|
|
||||||
#if defined(MOZ_WIDGET_ANDROID)
|
#if defined(MOZ_WIDGET_ANDROID)
|
||||||
# include "apz/src/APZCTreeManager.h"
|
# include "apz/src/APZCTreeManager.h"
|
||||||
|
# include "mozilla/layers/AsyncCompositionManager.h"
|
||||||
#endif
|
#endif
|
||||||
#include "mozilla/layers/Compositor.h"
|
#include "mozilla/layers/Compositor.h"
|
||||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||||
#include "mozilla/layers/CompositorThread.h"
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
#include "mozilla/layers/LayerManagerComposite.h"
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
|
#include "mozilla/layers/UiCompositorControllerMessageTypes.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
@ -130,7 +130,9 @@ EXPORTS.mozilla.layers += [
|
|||||||
'basic/TextureHostBasic.h',
|
'basic/TextureHostBasic.h',
|
||||||
'BSPTree.h',
|
'BSPTree.h',
|
||||||
'BufferTexture.h',
|
'BufferTexture.h',
|
||||||
|
'CanvasDrawEventRecorder.h',
|
||||||
'CanvasRenderer.h',
|
'CanvasRenderer.h',
|
||||||
|
'CanvasTranslator.h',
|
||||||
'client/CanvasClient.h',
|
'client/CanvasClient.h',
|
||||||
'client/CompositableClient.h',
|
'client/CompositableClient.h',
|
||||||
'client/ContentClient.h',
|
'client/ContentClient.h',
|
||||||
@ -142,6 +144,7 @@ EXPORTS.mozilla.layers += [
|
|||||||
'client/TextureClientPool.h',
|
'client/TextureClientPool.h',
|
||||||
'client/TextureClientRecycleAllocator.h',
|
'client/TextureClientRecycleAllocator.h',
|
||||||
'client/TextureClientSharedSurface.h',
|
'client/TextureClientSharedSurface.h',
|
||||||
|
'client/TextureRecorded.h',
|
||||||
'client/TiledContentClient.h',
|
'client/TiledContentClient.h',
|
||||||
'composite/AsyncCompositionManager.h',
|
'composite/AsyncCompositionManager.h',
|
||||||
'composite/CanvasLayerComposite.h',
|
'composite/CanvasLayerComposite.h',
|
||||||
@ -176,6 +179,8 @@ EXPORTS.mozilla.layers += [
|
|||||||
'ipc/APZCTreeManagerParent.h',
|
'ipc/APZCTreeManagerParent.h',
|
||||||
'ipc/APZInputBridgeChild.h',
|
'ipc/APZInputBridgeChild.h',
|
||||||
'ipc/APZInputBridgeParent.h',
|
'ipc/APZInputBridgeParent.h',
|
||||||
|
'ipc/CanvasChild.h',
|
||||||
|
'ipc/CanvasParent.h',
|
||||||
'ipc/CompositableForwarder.h',
|
'ipc/CompositableForwarder.h',
|
||||||
'ipc/CompositableTransactionParent.h',
|
'ipc/CompositableTransactionParent.h',
|
||||||
'ipc/CompositorBridgeChild.h',
|
'ipc/CompositorBridgeChild.h',
|
||||||
@ -371,7 +376,9 @@ UNIFIED_SOURCES += [
|
|||||||
'basic/TextureHostBasic.cpp',
|
'basic/TextureHostBasic.cpp',
|
||||||
'BSPTree.cpp',
|
'BSPTree.cpp',
|
||||||
'BufferTexture.cpp',
|
'BufferTexture.cpp',
|
||||||
|
'CanvasDrawEventRecorder.cpp',
|
||||||
'CanvasRenderer.cpp',
|
'CanvasRenderer.cpp',
|
||||||
|
'CanvasTranslator.cpp',
|
||||||
'client/CanvasClient.cpp',
|
'client/CanvasClient.cpp',
|
||||||
'client/ClientCanvasLayer.cpp',
|
'client/ClientCanvasLayer.cpp',
|
||||||
'client/ClientCanvasRenderer.cpp',
|
'client/ClientCanvasRenderer.cpp',
|
||||||
@ -391,6 +398,7 @@ UNIFIED_SOURCES += [
|
|||||||
'client/TextureClientPool.cpp',
|
'client/TextureClientPool.cpp',
|
||||||
'client/TextureClientRecycleAllocator.cpp',
|
'client/TextureClientRecycleAllocator.cpp',
|
||||||
'client/TextureClientSharedSurface.cpp',
|
'client/TextureClientSharedSurface.cpp',
|
||||||
|
'client/TextureRecorded.cpp',
|
||||||
'client/TiledContentClient.cpp',
|
'client/TiledContentClient.cpp',
|
||||||
'composite/AsyncCompositionManager.cpp',
|
'composite/AsyncCompositionManager.cpp',
|
||||||
'composite/CanvasLayerComposite.cpp',
|
'composite/CanvasLayerComposite.cpp',
|
||||||
@ -424,6 +432,8 @@ UNIFIED_SOURCES += [
|
|||||||
'ipc/APZCTreeManagerParent.cpp',
|
'ipc/APZCTreeManagerParent.cpp',
|
||||||
'ipc/APZInputBridgeChild.cpp',
|
'ipc/APZInputBridgeChild.cpp',
|
||||||
'ipc/APZInputBridgeParent.cpp',
|
'ipc/APZInputBridgeParent.cpp',
|
||||||
|
'ipc/CanvasChild.cpp',
|
||||||
|
'ipc/CanvasParent.cpp',
|
||||||
'ipc/CompositableTransactionParent.cpp',
|
'ipc/CompositableTransactionParent.cpp',
|
||||||
'ipc/CompositorBench.cpp',
|
'ipc/CompositorBench.cpp',
|
||||||
'ipc/CompositorBridgeChild.cpp',
|
'ipc/CompositorBridgeChild.cpp',
|
||||||
@ -540,6 +550,7 @@ IPDL_SOURCES += [
|
|||||||
'ipc/PAPZ.ipdl',
|
'ipc/PAPZ.ipdl',
|
||||||
'ipc/PAPZCTreeManager.ipdl',
|
'ipc/PAPZCTreeManager.ipdl',
|
||||||
'ipc/PAPZInputBridge.ipdl',
|
'ipc/PAPZInputBridge.ipdl',
|
||||||
|
'ipc/PCanvas.ipdl',
|
||||||
'ipc/PCompositorBridge.ipdl',
|
'ipc/PCompositorBridge.ipdl',
|
||||||
'ipc/PCompositorManager.ipdl',
|
'ipc/PCompositorManager.ipdl',
|
||||||
'ipc/PImageBridge.ipdl',
|
'ipc/PImageBridge.ipdl',
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "mozilla/layers/RenderRootStateManager.h"
|
#include "mozilla/layers/RenderRootStateManager.h"
|
||||||
|
|
||||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||||
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "CompositableHost.h" // for CompositableHost, ImageCompositeNotificationInfo
|
#include "CompositableHost.h" // for CompositableHost, ImageCompositeNotificationInfo
|
||||||
#include "GLContextProvider.h"
|
#include "GLContextProvider.h"
|
||||||
|
#include "Layers.h"
|
||||||
#include "mozilla/layers/CompositableTransactionParent.h"
|
#include "mozilla/layers/CompositableTransactionParent.h"
|
||||||
#include "mozilla/layers/CompositorTypes.h"
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
#include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
|
#include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
|
#include "mozilla/layers/AnimationHelper.h"
|
||||||
#include "mozilla/layers/ClipManager.h"
|
#include "mozilla/layers/ClipManager.h"
|
||||||
#include "mozilla/layers/ImageClient.h"
|
#include "mozilla/layers/ImageClient.h"
|
||||||
#include "mozilla/layers/RenderRootStateManager.h"
|
#include "mozilla/layers/RenderRootStateManager.h"
|
||||||
|
@ -245,6 +245,8 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetCompositorBridgeChild()->EndCanvasTransaction();
|
||||||
|
|
||||||
AutoTArray<RenderRootUpdates, wr::kRenderRootCount> renderRootUpdates;
|
AutoTArray<RenderRootUpdates, wr::kRenderRootCount> renderRootUpdates;
|
||||||
for (auto& stateManager : mStateManagers) {
|
for (auto& stateManager : mStateManagers) {
|
||||||
auto renderRoot = stateManager.GetRenderRoot();
|
auto renderRoot = stateManager.GetRenderRoot();
|
||||||
@ -428,6 +430,8 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetCompositorBridgeChild()->EndCanvasTransaction();
|
||||||
|
|
||||||
{
|
{
|
||||||
AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction", GRAPHICS);
|
AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction", GRAPHICS);
|
||||||
InfallibleTArray<RenderRootDisplayListData> renderRootDLs;
|
InfallibleTArray<RenderRootDisplayListData> renderRootDLs;
|
||||||
@ -734,14 +738,13 @@ WebRenderLayerManager::CreatePersistentBufferProvider(
|
|||||||
// initialized with WebRender to reduce memory usage.
|
// initialized with WebRender to reduce memory usage.
|
||||||
gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
|
gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
|
||||||
|
|
||||||
if (StaticPrefs::PersistentBufferProviderSharedEnabled()) {
|
RefPtr<PersistentBufferProvider> provider =
|
||||||
RefPtr<PersistentBufferProvider> provider =
|
PersistentBufferProviderShared::Create(aSize, aFormat,
|
||||||
PersistentBufferProviderShared::Create(aSize, aFormat,
|
AsKnowsCompositor());
|
||||||
AsKnowsCompositor());
|
if (provider) {
|
||||||
if (provider) {
|
return provider.forget();
|
||||||
return provider.forget();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return LayerManager::CreatePersistentBufferProvider(aSize, aFormat);
|
return LayerManager::CreatePersistentBufferProvider(aSize, aFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +267,44 @@ bool DeviceManagerDx::CreateVRDevice() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DeviceManagerDx::CreateCanvasDevice() {
|
||||||
|
MOZ_ASSERT(ProcessOwnsCompositor());
|
||||||
|
|
||||||
|
if (mCanvasDevice) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LoadD3D11()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||||
|
if (!adapter) {
|
||||||
|
NS_WARNING("Failed to acquire a DXGI adapter for Canvas");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
if (!CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, flags, hr,
|
||||||
|
mCanvasDevice)) {
|
||||||
|
gfxCriticalError() << "Crash during D3D11 device creation for Canvas";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr) || !mCanvasDevice) {
|
||||||
|
NS_WARNING("Failed to acquire a D3D11 device for Canvas");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XRE_IsGPUProcess()) {
|
||||||
|
Factory::SetDirect3D11Device(mCanvasDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceManagerDx::CreateDirectCompositionDevice() {
|
void DeviceManagerDx::CreateDirectCompositionDevice() {
|
||||||
if (!gfxVars::UseWebRenderDCompWin()) {
|
if (!gfxVars::UseWebRenderDCompWin()) {
|
||||||
return;
|
return;
|
||||||
@ -866,6 +904,7 @@ void DeviceManagerDx::ResetDevices() {
|
|||||||
mMLGDevice = nullptr;
|
mMLGDevice = nullptr;
|
||||||
mCompositorDevice = nullptr;
|
mCompositorDevice = nullptr;
|
||||||
mContentDevice = nullptr;
|
mContentDevice = nullptr;
|
||||||
|
mCanvasDevice = nullptr;
|
||||||
mImageDevice = nullptr;
|
mImageDevice = nullptr;
|
||||||
mDeviceStatus = Nothing();
|
mDeviceStatus = Nothing();
|
||||||
mDeviceResetReason = Nothing();
|
mDeviceResetReason = Nothing();
|
||||||
@ -888,6 +927,7 @@ bool DeviceManagerDx::MaybeResetAndReacquireDevices() {
|
|||||||
|
|
||||||
bool createCompositorDevice = !!mCompositorDevice;
|
bool createCompositorDevice = !!mCompositorDevice;
|
||||||
bool createContentDevice = !!mContentDevice;
|
bool createContentDevice = !!mContentDevice;
|
||||||
|
bool createCanvasDevice = !!mCanvasDevice;
|
||||||
|
|
||||||
ResetDevices();
|
ResetDevices();
|
||||||
|
|
||||||
@ -898,6 +938,9 @@ bool DeviceManagerDx::MaybeResetAndReacquireDevices() {
|
|||||||
if (createContentDevice) {
|
if (createContentDevice) {
|
||||||
CreateContentDevices();
|
CreateContentDevices();
|
||||||
}
|
}
|
||||||
|
if (createCanvasDevice) {
|
||||||
|
CreateCanvasDevice();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -986,7 +1029,8 @@ bool DeviceManagerDx::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason) {
|
|||||||
mDeviceLock.AssertCurrentThreadOwns();
|
mDeviceLock.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
if (DidDeviceReset(mCompositorDevice, aOutReason) ||
|
if (DidDeviceReset(mCompositorDevice, aOutReason) ||
|
||||||
DidDeviceReset(mContentDevice, aOutReason)) {
|
DidDeviceReset(mContentDevice, aOutReason) ||
|
||||||
|
DidDeviceReset(mCanvasDevice, aOutReason)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,6 +1113,14 @@ RefPtr<ID3D11Device> DeviceManagerDx::GetVRDevice() {
|
|||||||
return mVRDevice;
|
return mVRDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<ID3D11Device> DeviceManagerDx::GetCanvasDevice() {
|
||||||
|
MutexAutoLock lock(mDeviceLock);
|
||||||
|
if (!mCanvasDevice) {
|
||||||
|
CreateCanvasDevice();
|
||||||
|
}
|
||||||
|
return mCanvasDevice;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<IDCompositionDevice> DeviceManagerDx::GetDirectCompositionDevice() {
|
RefPtr<IDCompositionDevice> DeviceManagerDx::GetDirectCompositionDevice() {
|
||||||
MutexAutoLock lock(mDeviceLock);
|
MutexAutoLock lock(mDeviceLock);
|
||||||
return mDirectCompositionDevice;
|
return mDirectCompositionDevice;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include <dxgi1_6.h>
|
#include <dxgi1_6.h>
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ class DeviceManagerDx final {
|
|||||||
|
|
||||||
RefPtr<ID3D11Device> GetCompositorDevice();
|
RefPtr<ID3D11Device> GetCompositorDevice();
|
||||||
RefPtr<ID3D11Device> GetContentDevice();
|
RefPtr<ID3D11Device> GetContentDevice();
|
||||||
|
RefPtr<ID3D11Device> GetCanvasDevice();
|
||||||
RefPtr<ID3D11Device> GetImageDevice();
|
RefPtr<ID3D11Device> GetImageDevice();
|
||||||
RefPtr<IDCompositionDevice> GetDirectCompositionDevice();
|
RefPtr<IDCompositionDevice> GetDirectCompositionDevice();
|
||||||
RefPtr<ID3D11Device> GetVRDevice();
|
RefPtr<ID3D11Device> GetVRDevice();
|
||||||
@ -88,6 +90,7 @@ class DeviceManagerDx final {
|
|||||||
bool CreateCompositorDevices();
|
bool CreateCompositorDevices();
|
||||||
void CreateContentDevices();
|
void CreateContentDevices();
|
||||||
void CreateDirectCompositionDevice();
|
void CreateDirectCompositionDevice();
|
||||||
|
bool CreateCanvasDevice();
|
||||||
|
|
||||||
void GetCompositorDevices(
|
void GetCompositorDevices(
|
||||||
RefPtr<ID3D11Device>* aOutDevice,
|
RefPtr<ID3D11Device>* aOutDevice,
|
||||||
@ -165,6 +168,7 @@ class DeviceManagerDx final {
|
|||||||
RefPtr<IDXGIAdapter1> mAdapter;
|
RefPtr<IDXGIAdapter1> mAdapter;
|
||||||
RefPtr<ID3D11Device> mCompositorDevice;
|
RefPtr<ID3D11Device> mCompositorDevice;
|
||||||
RefPtr<ID3D11Device> mContentDevice;
|
RefPtr<ID3D11Device> mContentDevice;
|
||||||
|
RefPtr<ID3D11Device> mCanvasDevice;
|
||||||
RefPtr<ID3D11Device> mImageDevice;
|
RefPtr<ID3D11Device> mImageDevice;
|
||||||
RefPtr<ID3D11Device> mVRDevice;
|
RefPtr<ID3D11Device> mVRDevice;
|
||||||
RefPtr<ID3D11Device> mDecoderDevice;
|
RefPtr<ID3D11Device> mDecoderDevice;
|
||||||
|
@ -2423,6 +2423,9 @@ void gfxPlatform::InitAcceleration() {
|
|||||||
VideoDecodingFailedChangedCallback,
|
VideoDecodingFailedChangedCallback,
|
||||||
"media.hardware-video-decoding.failed");
|
"media.hardware-video-decoding.failed");
|
||||||
InitGPUProcessPrefs();
|
InitGPUProcessPrefs();
|
||||||
|
|
||||||
|
gfxVars::SetRemoteCanvasEnabled(StaticPrefs::CanvasRemote() &&
|
||||||
|
gfxConfig::IsEnabled(Feature::GPU_PROCESS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3394,6 +3397,8 @@ void gfxPlatform::NotifyGPUProcessDisabled() {
|
|||||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
|
NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
|
||||||
gfxVars::SetUseWebRender(false);
|
gfxVars::SetUseWebRender(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxVars::SetRemoteCanvasEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfxPlatform::FetchAndImportContentDeviceData() {
|
void gfxPlatform::FetchAndImportContentDeviceData() {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "mozilla/layers/SyncObject.h"
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "mozilla/layers/WebRenderCompositionRecorder.h"
|
#include "mozilla/layers/WebRenderCompositionRecorder.h"
|
||||||
#include "mozilla/Range.h"
|
#include "mozilla/Range.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/webrender/webrender_ffi.h"
|
#include "mozilla/webrender/webrender_ffi.h"
|
||||||
#include "mozilla/webrender/WebRenderTypes.h"
|
#include "mozilla/webrender/WebRenderTypes.h"
|
||||||
#include "GLTypes.h"
|
#include "GLTypes.h"
|
||||||
|
@ -3750,7 +3750,7 @@ nsDocumentViewer::GetCurrentPrintSettings(
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocumentViewer::Cancel() {
|
nsDocumentViewer::Cancel() {
|
||||||
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
|
||||||
return mPrintJob->Cancelled();
|
return mPrintJob->Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -7435,7 +7435,7 @@ nsLayoutUtils::SurfaceFromOffscreenCanvas(OffscreenCanvas* aOffscreenCanvas,
|
|||||||
RefPtr<DrawTarget>& aTarget) {
|
RefPtr<DrawTarget>& aTarget) {
|
||||||
SurfaceFromElementResult result;
|
SurfaceFromElementResult result;
|
||||||
|
|
||||||
nsIntSize size = aOffscreenCanvas->GetWidthHeight();
|
IntSize size = aOffscreenCanvas->GetWidthHeight();
|
||||||
|
|
||||||
result.mSourceSurface =
|
result.mSourceSurface =
|
||||||
aOffscreenCanvas->GetSurfaceSnapshot(&result.mAlphaType);
|
aOffscreenCanvas->GetSurfaceSnapshot(&result.mAlphaType);
|
||||||
@ -7447,10 +7447,12 @@ nsLayoutUtils::SurfaceFromOffscreenCanvas(OffscreenCanvas* aOffscreenCanvas,
|
|||||||
RefPtr<DrawTarget> ref =
|
RefPtr<DrawTarget> ref =
|
||||||
aTarget ? aTarget
|
aTarget ? aTarget
|
||||||
: gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
: gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
||||||
RefPtr<DrawTarget> dt = ref->CreateSimilarDrawTarget(
|
if (ref->CanCreateSimilarDrawTarget(size, SurfaceFormat::B8G8R8A8)) {
|
||||||
IntSize(size.width, size.height), SurfaceFormat::B8G8R8A8);
|
RefPtr<DrawTarget> dt =
|
||||||
if (dt) {
|
ref->CreateSimilarDrawTarget(size, SurfaceFormat::B8G8R8A8);
|
||||||
result.mSourceSurface = dt->Snapshot();
|
if (dt) {
|
||||||
|
result.mSourceSurface = dt->Snapshot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (aTarget) {
|
} else if (aTarget) {
|
||||||
RefPtr<SourceSurface> opt =
|
RefPtr<SourceSurface> opt =
|
||||||
@ -7618,10 +7620,12 @@ nsLayoutUtils::SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
|||||||
RefPtr<DrawTarget> ref =
|
RefPtr<DrawTarget> ref =
|
||||||
aTarget ? aTarget
|
aTarget ? aTarget
|
||||||
: gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
: gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
||||||
RefPtr<DrawTarget> dt = ref->CreateSimilarDrawTarget(
|
if (ref->CanCreateSimilarDrawTarget(size, SurfaceFormat::B8G8R8A8)) {
|
||||||
IntSize(size.width, size.height), SurfaceFormat::B8G8R8A8);
|
RefPtr<DrawTarget> dt =
|
||||||
if (dt) {
|
ref->CreateSimilarDrawTarget(size, SurfaceFormat::B8G8R8A8);
|
||||||
result.mSourceSurface = dt->Snapshot();
|
if (dt) {
|
||||||
|
result.mSourceSurface = dt->Snapshot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (aTarget) {
|
} else if (aTarget) {
|
||||||
RefPtr<SourceSurface> opt =
|
RefPtr<SourceSurface> opt =
|
||||||
|
@ -11,8 +11,6 @@ namespace layout {
|
|||||||
|
|
||||||
void DrawEventRecorderPRFileDesc::RecordEvent(
|
void DrawEventRecorderPRFileDesc::RecordEvent(
|
||||||
const gfx::RecordedEvent& aEvent) {
|
const gfx::RecordedEvent& aEvent) {
|
||||||
WriteElement(mOutputStream, aEvent.GetType());
|
|
||||||
|
|
||||||
aEvent.RecordToStream(mOutputStream);
|
aEvent.RecordToStream(mOutputStream);
|
||||||
|
|
||||||
Flush();
|
Flush();
|
||||||
|
@ -105,7 +105,7 @@ class PRFileDescStream final : public mozilla::gfx::EventStream {
|
|||||||
mGood = res >= 0 && (static_cast<size_t>(res) == aSize);
|
mGood = res >= 0 && (static_cast<size_t>(res) == aSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool good() { return mGood; }
|
bool good() final { return mGood; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t AvailableBufferSpace() { return kBufferSize - mBufferPos; }
|
size_t AvailableBufferSpace() { return kBufferSize - mBufferPos; }
|
||||||
|
@ -46,15 +46,18 @@ bool PrintTranslator::TranslateRecording(PRFileDescStream& aRecording) {
|
|||||||
int32_t eventType;
|
int32_t eventType;
|
||||||
ReadElement(aRecording, eventType);
|
ReadElement(aRecording, eventType);
|
||||||
while (aRecording.good()) {
|
while (aRecording.good()) {
|
||||||
UniquePtr<RecordedEvent> recordedEvent(RecordedEvent::LoadEventFromStream(
|
bool success = RecordedEvent::DoWithEventFromStream(
|
||||||
aRecording, static_cast<RecordedEvent::EventType>(eventType)));
|
aRecording, static_cast<RecordedEvent::EventType>(eventType),
|
||||||
|
[&](RecordedEvent* recordedEvent) -> bool {
|
||||||
|
// Make sure that the whole event was read from the stream.
|
||||||
|
if (!aRecording.good()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the whole event was read from the stream successfully.
|
return recordedEvent->PlayEvent(this);
|
||||||
if (!aRecording.good() || !recordedEvent) {
|
});
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!recordedEvent->PlayEvent(this)) {
|
if (!success) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,16 +451,12 @@ static void MapContentToWebShells(const UniquePtr<nsPrintObject>& aRootPO,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively builds the static clone document tree.
|
|
||||||
* XXXjwatt - uh, CreateStaticClone already takes care of recursively creating
|
|
||||||
* subdocs (in-process, at least). nsPrintObject::Init creating a static clone
|
|
||||||
* for subdocs is...broken, surely.
|
|
||||||
* The outparam aDocList returns a (depth first) flat list of all the
|
* The outparam aDocList returns a (depth first) flat list of all the
|
||||||
* nsPrintObjects created.
|
* nsPrintObjects created.
|
||||||
*/
|
*/
|
||||||
static void BuildDocTree(BrowsingContext* aBrowsingContext,
|
static void BuildNestedPrintObjects(BrowsingContext* aBrowsingContext,
|
||||||
const UniquePtr<nsPrintObject>& aPO,
|
const UniquePtr<nsPrintObject>& aPO,
|
||||||
nsTArray<nsPrintObject*>* aDocList) {
|
nsTArray<nsPrintObject*>* aDocList) {
|
||||||
MOZ_ASSERT(aBrowsingContext, "Pointer is null!");
|
MOZ_ASSERT(aBrowsingContext, "Pointer is null!");
|
||||||
MOZ_ASSERT(aDocList, "Pointer is null!");
|
MOZ_ASSERT(aDocList, "Pointer is null!");
|
||||||
MOZ_ASSERT(aPO, "Pointer is null!");
|
MOZ_ASSERT(aPO, "Pointer is null!");
|
||||||
@ -472,15 +468,14 @@ static void BuildDocTree(BrowsingContext* aBrowsingContext,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto childPO = MakeUnique<nsPrintObject>();
|
auto childPO = MakeUnique<nsPrintObject>();
|
||||||
childPO->mParent = aPO.get();
|
nsresult rv = childPO->InitAsNestedObject(
|
||||||
nsresult rv = childPO->Init(childBC->GetDocShell(), window->GetExtantDoc(),
|
childBC->GetDocShell(), window->GetExtantDoc(), aPO.get());
|
||||||
aPO->mPrintPreview);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
MOZ_ASSERT_UNREACHABLE("Init failed?");
|
MOZ_ASSERT_UNREACHABLE("Init failed?");
|
||||||
}
|
}
|
||||||
aPO->mKids.AppendElement(std::move(childPO));
|
aPO->mKids.AppendElement(std::move(childPO));
|
||||||
aDocList->AppendElement(aPO->mKids.LastElement().get());
|
aDocList->AppendElement(aPO->mKids.LastElement().get());
|
||||||
BuildDocTree(childBC, aPO->mKids.LastElement(), aDocList);
|
BuildNestedPrintObjects(childBC, aPO->mKids.LastElement(), aDocList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,7 +640,7 @@ bool nsPrintJob::CheckBeforeDestroy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
nsresult nsPrintJob::Cancelled() {
|
nsresult nsPrintJob::Cancel() {
|
||||||
if (mPrt && mPrt->mPrintSettings) {
|
if (mPrt && mPrt->mPrintSettings) {
|
||||||
return mPrt->mPrintSettings->SetIsCancelled(true);
|
return mPrt->mPrintSettings->SetIsCancelled(true);
|
||||||
}
|
}
|
||||||
@ -840,7 +835,8 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
|
|||||||
|
|
||||||
nsAutoScriptBlocker scriptBlocker;
|
nsAutoScriptBlocker scriptBlocker;
|
||||||
printData->mPrintObject = MakeUnique<nsPrintObject>();
|
printData->mPrintObject = MakeUnique<nsPrintObject>();
|
||||||
rv = printData->mPrintObject->Init(docShell, aSourceDoc, aIsPrintPreview);
|
rv = printData->mPrintObject->InitAsRootObject(docShell, aSourceDoc,
|
||||||
|
aIsPrintPreview);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
NS_ENSURE_TRUE(
|
NS_ENSURE_TRUE(
|
||||||
@ -851,10 +847,9 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
|
|||||||
printData->mPrintObject->mFrameType =
|
printData->mPrintObject->mFrameType =
|
||||||
printData->mIsParentAFrameSet ? eFrameSet : eDoc;
|
printData->mIsParentAFrameSet ? eFrameSet : eDoc;
|
||||||
|
|
||||||
// Builds the static clone doc tree and the "tree" of PrintObjects
|
BuildNestedPrintObjects(nsDocShell::Cast(printData->mPrintObject->mDocShell)
|
||||||
BuildDocTree(nsDocShell::Cast(printData->mPrintObject->mDocShell)
|
->GetBrowsingContext(),
|
||||||
->GetBrowsingContext(),
|
printData->mPrintObject, &printData->mPrintDocList);
|
||||||
printData->mPrintObject, &printData->mPrintDocList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The nsAutoScriptBlocker above will now have been destroyed, which may
|
// The nsAutoScriptBlocker above will now have been destroyed, which may
|
||||||
|
@ -209,7 +209,7 @@ class nsPrintJob final : public nsIObserver,
|
|||||||
eDocTitleDefault aDefType);
|
eDocTitleDefault aDefType);
|
||||||
|
|
||||||
bool CheckBeforeDestroy();
|
bool CheckBeforeDestroy();
|
||||||
nsresult Cancelled();
|
nsresult Cancel();
|
||||||
|
|
||||||
mozilla::PresShell* GetPrintPreviewPresShell() {
|
mozilla::PresShell* GetPrintPreviewPresShell() {
|
||||||
return mPrtPreview->mPrintObject->mPresShell;
|
return mPrtPreview->mPrintObject->mPresShell;
|
||||||
|
@ -38,7 +38,6 @@ nsPrintObject::nsPrintObject()
|
|||||||
mDontPrint(true),
|
mDontPrint(true),
|
||||||
mPrintAsIs(false),
|
mPrintAsIs(false),
|
||||||
mInvisible(false),
|
mInvisible(false),
|
||||||
mPrintPreview(false),
|
|
||||||
mDidCreateDocShell(false),
|
mDidCreateDocShell(false),
|
||||||
mShrinkRatio(1.0),
|
mShrinkRatio(1.0),
|
||||||
mZoomRatio(1.0) {
|
mZoomRatio(1.0) {
|
||||||
@ -60,16 +59,16 @@ nsPrintObject::~nsPrintObject() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
nsresult nsPrintObject::Init(nsIDocShell* aDocShell, Document* aDoc,
|
nsresult nsPrintObject::InitAsRootObject(nsIDocShell* aDocShell, Document* aDoc,
|
||||||
bool aPrintPreview) {
|
bool aForPrintPreview) {
|
||||||
|
NS_ENSURE_STATE(aDocShell);
|
||||||
NS_ENSURE_STATE(aDoc);
|
NS_ENSURE_STATE(aDoc);
|
||||||
|
|
||||||
mPrintPreview = aPrintPreview;
|
if (aForPrintPreview) {
|
||||||
|
|
||||||
if (mPrintPreview || mParent) {
|
|
||||||
mDocShell = aDocShell;
|
mDocShell = aDocShell;
|
||||||
} else {
|
} else {
|
||||||
mTreeOwner = do_GetInterface(aDocShell);
|
// When doing an actual print, we create a BrowsingContext/nsDocShell that
|
||||||
|
// is detached from any browser window or tab.
|
||||||
|
|
||||||
// Create a new BrowsingContext to create our DocShell in.
|
// Create a new BrowsingContext to create our DocShell in.
|
||||||
RefPtr<BrowsingContext> bc = BrowsingContext::Create(
|
RefPtr<BrowsingContext> bc = BrowsingContext::Create(
|
||||||
@ -85,31 +84,38 @@ nsresult nsPrintObject::Init(nsIDocShell* aDocShell, Document* aDoc,
|
|||||||
|
|
||||||
mDidCreateDocShell = true;
|
mDidCreateDocShell = true;
|
||||||
MOZ_ASSERT(mDocShell->ItemType() == aDocShell->ItemType());
|
MOZ_ASSERT(mDocShell->ItemType() == aDocShell->ItemType());
|
||||||
|
|
||||||
|
mTreeOwner = do_GetInterface(aDocShell);
|
||||||
mDocShell->SetTreeOwner(mTreeOwner);
|
mDocShell->SetTreeOwner(mTreeOwner);
|
||||||
}
|
|
||||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
// Keep the document related to this docshell alive
|
// Make sure nsDocShell::EnsureContentViewer() is called:
|
||||||
nsCOMPtr<Document> dummy = do_GetInterface(mDocShell);
|
mozilla::Unused << nsDocShell::Cast(mDocShell)->GetDocument();
|
||||||
mozilla::Unused << dummy;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContentViewer> viewer;
|
|
||||||
mDocShell->GetContentViewer(getter_AddRefs(viewer));
|
|
||||||
NS_ENSURE_STATE(viewer);
|
|
||||||
|
|
||||||
if (mParent) {
|
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> window = aDoc->GetWindow();
|
|
||||||
if (window) {
|
|
||||||
mContent = window->GetFrameElementInternal();
|
|
||||||
}
|
|
||||||
mDocument = aDoc;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mDocument = aDoc->CreateStaticClone(mDocShell);
|
mDocument = aDoc->CreateStaticClone(mDocShell);
|
||||||
NS_ENSURE_STATE(mDocument);
|
NS_ENSURE_STATE(mDocument);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContentViewer> viewer;
|
||||||
|
mDocShell->GetContentViewer(getter_AddRefs(viewer));
|
||||||
|
NS_ENSURE_STATE(viewer);
|
||||||
viewer->SetDocument(mDocument);
|
viewer->SetDocument(mDocument);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult nsPrintObject::InitAsNestedObject(nsIDocShell* aDocShell,
|
||||||
|
Document* aDoc,
|
||||||
|
nsPrintObject* aParent) {
|
||||||
|
NS_ENSURE_STATE(aDocShell);
|
||||||
|
NS_ENSURE_STATE(aDoc);
|
||||||
|
|
||||||
|
mParent = aParent;
|
||||||
|
mDocShell = aDocShell;
|
||||||
|
mDocument = aDoc;
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowOuter> window = aDoc->GetWindow();
|
||||||
|
mContent = window->GetFrameElementInternal();
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +33,12 @@ class nsPrintObject {
|
|||||||
nsPrintObject();
|
nsPrintObject();
|
||||||
~nsPrintObject(); // non-virtual
|
~nsPrintObject(); // non-virtual
|
||||||
|
|
||||||
// Methods
|
nsresult InitAsRootObject(nsIDocShell* aDocShell,
|
||||||
nsresult Init(nsIDocShell* aDocShell, mozilla::dom::Document* aDoc,
|
mozilla::dom::Document* aDoc,
|
||||||
bool aPrintPreview);
|
bool aForPrintPreview);
|
||||||
|
nsresult InitAsNestedObject(nsIDocShell* aDocShell,
|
||||||
|
mozilla::dom::Document* aDoc,
|
||||||
|
nsPrintObject* aParent);
|
||||||
|
|
||||||
bool IsPrintable() { return !mDontPrint; }
|
bool IsPrintable() { return !mDontPrint; }
|
||||||
void DestroyPresentation();
|
void DestroyPresentation();
|
||||||
@ -58,7 +61,6 @@ class nsPrintObject {
|
|||||||
bool mDontPrint;
|
bool mDontPrint;
|
||||||
bool mPrintAsIs;
|
bool mPrintAsIs;
|
||||||
bool mInvisible; // Indicates PO is set to not visible by CSS
|
bool mInvisible; // Indicates PO is set to not visible by CSS
|
||||||
bool mPrintPreview;
|
|
||||||
bool mDidCreateDocShell;
|
bool mDidCreateDocShell;
|
||||||
float mShrinkRatio;
|
float mShrinkRatio;
|
||||||
float mZoomRatio;
|
float mZoomRatio;
|
||||||
|
@ -2525,6 +2525,13 @@ VARCACHE_PREF(
|
|||||||
RelaxedAtomicInt32, 0x7fff
|
RelaxedAtomicInt32, 0x7fff
|
||||||
)
|
)
|
||||||
|
|
||||||
|
VARCACHE_PREF(
|
||||||
|
Live,
|
||||||
|
"gfx.canvas.remote",
|
||||||
|
CanvasRemote,
|
||||||
|
RelaxedAtomicBool, false
|
||||||
|
)
|
||||||
|
|
||||||
VARCACHE_PREF(
|
VARCACHE_PREF(
|
||||||
Live,
|
Live,
|
||||||
"gfx.color_management.enablev4",
|
"gfx.color_management.enablev4",
|
||||||
|
@ -844,6 +844,7 @@ pref("gfx.font_ahem_antialias_none", false);
|
|||||||
// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
|
// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
|
||||||
pref("gfx.canvas.azure.backends", "direct2d1.1,skia,cairo");
|
pref("gfx.canvas.azure.backends", "direct2d1.1,skia,cairo");
|
||||||
pref("gfx.content.azure.backends", "direct2d1.1,skia,cairo");
|
pref("gfx.content.azure.backends", "direct2d1.1,skia,cairo");
|
||||||
|
pref("gfx.canvas.remote", false);
|
||||||
#else
|
#else
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
pref("gfx.content.azure.backends", "skia");
|
pref("gfx.content.azure.backends", "skia");
|
||||||
|
@ -8396,15 +8396,6 @@
|
|||||||
"n_buckets": 15,
|
"n_buckets": 15,
|
||||||
"description": "Time (ms) it takes to figure out extension last modified time"
|
"description": "Time (ms) it takes to figure out extension last modified time"
|
||||||
},
|
},
|
||||||
"TELEMETRY_MEMORY_REPORTER_MS": {
|
|
||||||
"record_in_processes": ["main", "content"],
|
|
||||||
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
|
|
||||||
"expires_in_version": "never",
|
|
||||||
"kind": "exponential",
|
|
||||||
"high": 5000,
|
|
||||||
"n_buckets": 10,
|
|
||||||
"description": "Time (ms) it takes to run memory reporters when sending a telemetry ping"
|
|
||||||
},
|
|
||||||
"SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX" : {
|
"SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX" : {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"alert_emails": ["seceng-telemetry@mozilla.com"],
|
"alert_emails": ["seceng-telemetry@mozilla.com"],
|
||||||
|
@ -1053,7 +1053,6 @@
|
|||||||
"TELEMETRY_DISCARDED_PENDING_PINGS_SIZE_MB",
|
"TELEMETRY_DISCARDED_PENDING_PINGS_SIZE_MB",
|
||||||
"TELEMETRY_DISCARDED_SEND_PINGS_SIZE_MB",
|
"TELEMETRY_DISCARDED_SEND_PINGS_SIZE_MB",
|
||||||
"TELEMETRY_INVALID_PING_TYPE_SUBMITTED",
|
"TELEMETRY_INVALID_PING_TYPE_SUBMITTED",
|
||||||
"TELEMETRY_MEMORY_REPORTER_MS",
|
|
||||||
"TELEMETRY_PENDING_CHECKING_OVER_QUOTA_MS",
|
"TELEMETRY_PENDING_CHECKING_OVER_QUOTA_MS",
|
||||||
"TELEMETRY_PENDING_EVICTING_OVER_QUOTA_MS",
|
"TELEMETRY_PENDING_EVICTING_OVER_QUOTA_MS",
|
||||||
"TELEMETRY_PENDING_LOAD_FAILURE_PARSE",
|
"TELEMETRY_PENDING_LOAD_FAILURE_PARSE",
|
||||||
|
@ -231,8 +231,6 @@ nsresult MemoryTelemetry::GatherReports(
|
|||||||
MOZ_DIAGNOSTIC_ASSERT(mgr);
|
MOZ_DIAGNOSTIC_ASSERT(mgr);
|
||||||
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
auto startTime = TimeStamp::Now();
|
|
||||||
|
|
||||||
#define RECORD(id, metric, units) \
|
#define RECORD(id, metric, units) \
|
||||||
do { \
|
do { \
|
||||||
int64_t amt; \
|
int64_t amt; \
|
||||||
@ -332,9 +330,6 @@ nsresult MemoryTelemetry::GatherReports(
|
|||||||
mTotalMemoryGatherer->Begin(mThreadPool);
|
mTotalMemoryGatherer->Begin(mThreadPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
Telemetry::AccumulateTimeDelta(
|
|
||||||
Telemetry::HistogramID::TELEMETRY_MEMORY_REPORTER_MS, startTime,
|
|
||||||
TimeStamp::Now());
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,6 +369,8 @@ bool SpinEventLoopUntil(Pred&& aPredicate, nsIThread* aThread = nullptr) {
|
|||||||
*/
|
*/
|
||||||
extern bool NS_IsInCompositorThread();
|
extern bool NS_IsInCompositorThread();
|
||||||
|
|
||||||
|
extern bool NS_IsInCanvasThread();
|
||||||
|
|
||||||
extern bool NS_IsInVRThread();
|
extern bool NS_IsInVRThread();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user