Bug 1383916 Prep a DrawTarget to be drawn to on the paint thread. r=dvander
This commit is contained in:
@@ -113,12 +113,33 @@ PaintThread::IsOnPaintThread()
|
|||||||
void
|
void
|
||||||
PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
|
PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
|
||||||
gfx::DrawTargetCapture* aCapture,
|
gfx::DrawTargetCapture* aCapture,
|
||||||
gfx::DrawTarget* aTarget)
|
CapturedPaintState* aState,
|
||||||
|
PrepDrawTargetForPaintingCallback aCallback)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsOnPaintThread());
|
MOZ_ASSERT(IsOnPaintThread());
|
||||||
|
MOZ_ASSERT(aCapture);
|
||||||
|
MOZ_ASSERT(aState);
|
||||||
|
|
||||||
|
DrawTarget* target = aState->mTarget;
|
||||||
|
|
||||||
|
Matrix oldTransform = target->GetTransform();
|
||||||
|
target->SetTransform(aState->mTargetTransform);
|
||||||
|
|
||||||
|
if (!aCallback(aState)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw all the things into the actual dest target.
|
// Draw all the things into the actual dest target.
|
||||||
aTarget->DrawCapturedDT(aCapture, Matrix());
|
target->DrawCapturedDT(aCapture, Matrix());
|
||||||
|
target->SetTransform(oldTransform);
|
||||||
|
|
||||||
|
// Textureclient forces a flush once we "end paint", so
|
||||||
|
// users of this texture expect all the drawing to be complete.
|
||||||
|
// Force a flush now.
|
||||||
|
// TODO: This might be a performance bottleneck because
|
||||||
|
// main thread painting only does one flush at the end of all paints
|
||||||
|
// whereas we force a flush after each draw target paint.
|
||||||
|
target->Flush();
|
||||||
|
|
||||||
if (aBridge) {
|
if (aBridge) {
|
||||||
aBridge->NotifyFinishedAsyncPaint();
|
aBridge->NotifyFinishedAsyncPaint();
|
||||||
@@ -127,9 +148,12 @@ PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
|
|||||||
|
|
||||||
void
|
void
|
||||||
PaintThread::PaintContents(DrawTargetCapture* aCapture,
|
PaintThread::PaintContents(DrawTargetCapture* aCapture,
|
||||||
DrawTarget* aTarget)
|
CapturedPaintState* aState,
|
||||||
|
PrepDrawTargetForPaintingCallback aCallback)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(aCapture);
|
||||||
|
MOZ_ASSERT(aState);
|
||||||
|
|
||||||
// If painting asynchronously, we need to acquire the compositor bridge which
|
// If painting asynchronously, we need to acquire the compositor bridge which
|
||||||
// owns the underlying MessageChannel. Otherwise we leave it null and use
|
// owns the underlying MessageChannel. Otherwise we leave it null and use
|
||||||
@@ -140,13 +164,15 @@ PaintThread::PaintContents(DrawTargetCapture* aCapture,
|
|||||||
cbc->NotifyBeginAsyncPaint();
|
cbc->NotifyBeginAsyncPaint();
|
||||||
}
|
}
|
||||||
RefPtr<DrawTargetCapture> capture(aCapture);
|
RefPtr<DrawTargetCapture> capture(aCapture);
|
||||||
RefPtr<DrawTarget> target(aTarget);
|
RefPtr<CapturedPaintState> state(aState);
|
||||||
|
|
||||||
RefPtr<PaintThread> self = this;
|
RefPtr<PaintThread> self = this;
|
||||||
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
|
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
|
||||||
[self, cbc, capture, target]() -> void
|
[self, cbc, capture, state, aCallback]() -> void
|
||||||
{
|
{
|
||||||
self->PaintContentsAsync(cbc, capture, target);
|
self->PaintContentsAsync(cbc, capture,
|
||||||
|
state,
|
||||||
|
aCallback);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cbc) {
|
if (cbc) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define MOZILLA_LAYERS_PAINTTHREAD_H
|
#define MOZILLA_LAYERS_PAINTTHREAD_H
|
||||||
|
|
||||||
#include "base/platform_thread.h"
|
#include "base/platform_thread.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
@@ -20,6 +21,38 @@ class DrawTargetCapture;
|
|||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
// Holds the key parts from a RotatedBuffer::PaintState
|
||||||
|
// required to draw the captured paint state
|
||||||
|
class CapturedPaintState {
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CapturedPaintState)
|
||||||
|
public:
|
||||||
|
CapturedPaintState(nsIntRegion& aRegionToDraw,
|
||||||
|
gfx::DrawTarget* aTarget,
|
||||||
|
gfx::DrawTarget* aTargetOnWhite,
|
||||||
|
gfx::Matrix aTargetTransform,
|
||||||
|
SurfaceMode aSurfaceMode,
|
||||||
|
gfxContentType aContentType)
|
||||||
|
: mRegionToDraw(aRegionToDraw)
|
||||||
|
, mTarget(aTarget)
|
||||||
|
, mTargetOnWhite(aTargetOnWhite)
|
||||||
|
, mTargetTransform(aTargetTransform)
|
||||||
|
, mSurfaceMode(aSurfaceMode)
|
||||||
|
, mContentType(aContentType)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsIntRegion mRegionToDraw;
|
||||||
|
RefPtr<gfx::DrawTarget> mTarget;
|
||||||
|
RefPtr<gfx::DrawTarget> mTargetOnWhite;
|
||||||
|
gfx::Matrix mTargetTransform;
|
||||||
|
SurfaceMode mSurfaceMode;
|
||||||
|
gfxContentType mContentType;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~CapturedPaintState() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState* aPaintState);
|
||||||
|
|
||||||
class CompositorBridgeChild;
|
class CompositorBridgeChild;
|
||||||
|
|
||||||
class PaintThread final
|
class PaintThread final
|
||||||
@@ -31,7 +64,8 @@ public:
|
|||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static PaintThread* Get();
|
static PaintThread* Get();
|
||||||
void PaintContents(gfx::DrawTargetCapture* aCapture,
|
void PaintContents(gfx::DrawTargetCapture* aCapture,
|
||||||
gfx::DrawTarget* aTarget);
|
CapturedPaintState* aState,
|
||||||
|
PrepDrawTargetForPaintingCallback aCallback);
|
||||||
|
|
||||||
// Sync Runnables need threads to be ref counted,
|
// Sync Runnables need threads to be ref counted,
|
||||||
// But this thread lives through the whole process.
|
// But this thread lives through the whole process.
|
||||||
@@ -49,7 +83,8 @@ private:
|
|||||||
void InitOnPaintThread();
|
void InitOnPaintThread();
|
||||||
void PaintContentsAsync(CompositorBridgeChild* aBridge,
|
void PaintContentsAsync(CompositorBridgeChild* aBridge,
|
||||||
gfx::DrawTargetCapture* aCapture,
|
gfx::DrawTargetCapture* aCapture,
|
||||||
gfx::DrawTarget* aTarget);
|
CapturedPaintState* aState,
|
||||||
|
PrepDrawTargetForPaintingCallback aCallback);
|
||||||
|
|
||||||
static StaticAutoPtr<PaintThread> sSingleton;
|
static StaticAutoPtr<PaintThread> sSingleton;
|
||||||
static StaticRefPtr<nsIThread> sThread;
|
static StaticRefPtr<nsIThread> sThread;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "mozilla/gfx/Point.h" // for IntSize
|
#include "mozilla/gfx/Point.h" // for IntSize
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "nsLayoutUtils.h" // for invalidation debugging
|
#include "nsLayoutUtils.h" // for invalidation debugging
|
||||||
|
#include "PaintThread.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
@@ -730,6 +731,77 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawTarget*
|
||||||
|
RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||||
|
DrawIterator* aIter /* = nullptr */)
|
||||||
|
{
|
||||||
|
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(),
|
||||||
|
BUFFER_BOTH, aIter);
|
||||||
|
if (!result) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static */ bool
|
||||||
|
RotatedContentBuffer::PrepareDrawTargetForPainting(CapturedPaintState* aState)
|
||||||
|
{
|
||||||
|
RefPtr<DrawTarget> target = aState->mTarget;
|
||||||
|
RefPtr<DrawTarget> whiteTarget = aState->mTargetOnWhite;
|
||||||
|
|
||||||
|
if (aState->mSurfaceMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
||||||
|
if (!target || !target->IsValid() ||
|
||||||
|
!aState->mTargetOnWhite || !aState->mTargetOnWhite->IsValid()) {
|
||||||
|
// This can happen in release builds if allocating one of the two buffers
|
||||||
|
// failed. This in turn can happen if unreasonably large textures are
|
||||||
|
// requested.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto iter = aState->mRegionToDraw.RectIter(); !iter.Done(); iter.Next()) {
|
||||||
|
const IntRect& rect = iter.Get();
|
||||||
|
target->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||||
|
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
|
||||||
|
whiteTarget->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||||
|
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
|
||||||
|
}
|
||||||
|
} else if (aState->mContentType == gfxContentType::COLOR_ALPHA &&
|
||||||
|
target->IsValid()) {
|
||||||
|
// HaveBuffer() => we have an existing buffer that we must clear
|
||||||
|
for (auto iter = aState->mRegionToDraw.RectIter(); !iter.Done(); iter.Next()) {
|
||||||
|
const IntRect& rect = iter.Get();
|
||||||
|
target->ClearRect(Rect(rect.x, rect.y, rect.width, rect.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RotatedContentBuffer::ExpandDrawRegion(PaintState& aPaintState,
|
||||||
|
DrawIterator* aIter,
|
||||||
|
BackendType aBackendType)
|
||||||
|
{
|
||||||
|
nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
|
||||||
|
if (aIter) {
|
||||||
|
// The iterators draw region currently only contains the bounds of the region,
|
||||||
|
// this makes it the precise region.
|
||||||
|
aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw);
|
||||||
|
drawPtr = &aIter->mDrawRegion;
|
||||||
|
}
|
||||||
|
if (aBackendType == BackendType::DIRECT2D ||
|
||||||
|
aBackendType == BackendType::DIRECT2D1_1) {
|
||||||
|
// Simplify the draw region to avoid hitting expensive drawing paths
|
||||||
|
// for complex regions.
|
||||||
|
drawPtr->SimplifyOutwardByArea(100 * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawTarget*
|
DrawTarget*
|
||||||
RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
|
RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
|
||||||
DrawIterator* aIter /* = nullptr */)
|
DrawIterator* aIter /* = nullptr */)
|
||||||
@@ -744,41 +816,22 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
|
ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
|
||||||
if (aIter) {
|
|
||||||
// The iterators draw region currently only contains the bounds of the region,
|
|
||||||
// this makes it the precise region.
|
|
||||||
aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw);
|
|
||||||
drawPtr = &aIter->mDrawRegion;
|
|
||||||
}
|
|
||||||
if (result->GetBackendType() == BackendType::DIRECT2D ||
|
|
||||||
result->GetBackendType() == BackendType::DIRECT2D1_1) {
|
|
||||||
// Simplify the draw region to avoid hitting expensive drawing paths
|
|
||||||
// for complex regions.
|
|
||||||
drawPtr->SimplifyOutwardByArea(100 * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
nsIntRegion regionToDraw = aIter ? aIter->mDrawRegion
|
||||||
if (!mDTBuffer || !mDTBuffer->IsValid() ||
|
: aPaintState.mRegionToDraw;
|
||||||
!mDTBufferOnWhite || !mDTBufferOnWhite->IsValid()) {
|
|
||||||
// This can happen in release builds if allocating one of the two buffers
|
// Can't stack allocate refcounted objects.
|
||||||
// failed. This in turn can happen if unreasonably large textures are
|
RefPtr<CapturedPaintState> capturedPaintState =
|
||||||
// requested.
|
MakeAndAddRef<CapturedPaintState>(regionToDraw,
|
||||||
return nullptr;
|
mDTBuffer,
|
||||||
}
|
mDTBufferOnWhite,
|
||||||
for (auto iter = drawPtr->RectIter(); !iter.Done(); iter.Next()) {
|
Matrix(),
|
||||||
const IntRect& rect = iter.Get();
|
aPaintState.mMode,
|
||||||
mDTBuffer->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
aPaintState.mContentType);
|
||||||
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
|
|
||||||
mDTBufferOnWhite->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
if (!RotatedContentBuffer::PrepareDrawTargetForPainting(capturedPaintState)) {
|
||||||
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
|
return nullptr;
|
||||||
}
|
|
||||||
} else if (aPaintState.mContentType == gfxContentType::COLOR_ALPHA && HaveBuffer()) {
|
|
||||||
// HaveBuffer() => we have an existing buffer that we must clear
|
|
||||||
for (auto iter = drawPtr->RectIter(); !iter.Done(); iter.Next()) {
|
|
||||||
const IntRect& rect = iter.Get();
|
|
||||||
result->ClearRect(Rect(rect.x, rect.y, rect.width, rect.height));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
class CapturedPaintState;
|
||||||
|
|
||||||
|
typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*);
|
||||||
|
|
||||||
class TextureClient;
|
class TextureClient;
|
||||||
class PaintedLayer;
|
class PaintedLayer;
|
||||||
|
|
||||||
@@ -293,6 +297,14 @@ public:
|
|||||||
gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
|
gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
|
||||||
DrawIterator* aIter = nullptr);
|
DrawIterator* aIter = nullptr);
|
||||||
|
|
||||||
|
gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||||
|
DrawIterator* aIter = nullptr);
|
||||||
|
|
||||||
|
void ExpandDrawRegion(PaintState& aPaintState,
|
||||||
|
DrawIterator* aIter,
|
||||||
|
gfx::BackendType aBackendType);
|
||||||
|
|
||||||
|
static bool PrepareDrawTargetForPainting(CapturedPaintState*);
|
||||||
enum {
|
enum {
|
||||||
BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
|
BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
|
||||||
// component alpha.
|
// component alpha.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||||
#include "PaintThread.h"
|
#include "PaintThread.h"
|
||||||
#include "ReadbackProcessor.h"
|
#include "ReadbackProcessor.h"
|
||||||
|
#include "RotatedBuffer.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
@@ -188,6 +189,29 @@ ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* If we can, let's paint this ClientPaintedLayer's contents off the main thread.
|
||||||
|
* The essential idea is that we ask the ContentClient for a DrawTarget and record
|
||||||
|
* the moz2d commands. On the Paint Thread, we replay those commands to the
|
||||||
|
* destination draw target. There are a couple of lifetime issues here though:
|
||||||
|
*
|
||||||
|
* 1) TextureClient owns the underlying buffer and DrawTarget. Because of this
|
||||||
|
* we have to keep the TextureClient and DrawTarget alive but trick the
|
||||||
|
* TextureClient into thinking it's already returned the DrawTarget
|
||||||
|
* since we iterate through different Rects to get DrawTargets*. If
|
||||||
|
* the TextureClient goes away, the DrawTarget and thus buffer can too.
|
||||||
|
* 2) When ContentClient::EndPaint happens, it flushes the DrawTarget. We have
|
||||||
|
* to Reflush on the Paint Thread
|
||||||
|
* 3) DrawTarget API is NOT thread safe. We get around this by recording
|
||||||
|
* on the main thread and painting on the paint thread. Logically,
|
||||||
|
* ClientLayerManager will force a flushed paint and block the main thread
|
||||||
|
* if we have another transaction. Thus we have a gap between when the main
|
||||||
|
* thread records, the paint thread paints, and we block the main thread
|
||||||
|
* from trying to paint again. The underlying API however is NOT thread safe.
|
||||||
|
* 4) We have both "sync" and "async" OMTP. Sync OMTP means we paint on the main thread
|
||||||
|
* but block the main thread while the paint thread paints. Async OMTP doesn't block
|
||||||
|
* the main thread. Sync OMTP is only meant to be used as a debugging tool.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
ClientPaintedLayer::PaintOffMainThread()
|
ClientPaintedLayer::PaintOffMainThread()
|
||||||
{
|
{
|
||||||
@@ -202,7 +226,8 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||||||
|
|
||||||
bool didUpdate = false;
|
bool didUpdate = false;
|
||||||
RotatedContentBuffer::DrawIterator iter;
|
RotatedContentBuffer::DrawIterator iter;
|
||||||
while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
|
// Debug Protip: Change to BorrowDrawTargetForPainting if using sync OMTP.
|
||||||
|
while (DrawTarget* target = mContentClient->BorrowDrawTargetForRecording(state, &iter)) {
|
||||||
if (!target || !target->IsValid()) {
|
if (!target || !target->IsValid()) {
|
||||||
if (target) {
|
if (target) {
|
||||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||||
@@ -210,14 +235,15 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't clear the rect here like WRPaintedBlobLayers do
|
|
||||||
// because ContentClient already clears the surface for us during BeginPaint.
|
|
||||||
RefPtr<DrawTargetCapture> captureDT =
|
RefPtr<DrawTargetCapture> captureDT =
|
||||||
Factory::CreateCaptureDrawTarget(target->GetBackendType(),
|
Factory::CreateCaptureDrawTarget(target->GetBackendType(),
|
||||||
target->GetSize(),
|
target->GetSize(),
|
||||||
target->GetFormat());
|
target->GetFormat());
|
||||||
captureDT->SetTransform(target->GetTransform());
|
|
||||||
|
|
||||||
|
Matrix capturedTransform = target->GetTransform();
|
||||||
|
captureDT->SetTransform(capturedTransform);
|
||||||
|
|
||||||
|
// TODO: Capture AA Flags and reset them in PaintThread
|
||||||
SetAntialiasingFlags(this, captureDT);
|
SetAntialiasingFlags(this, captureDT);
|
||||||
SetAntialiasingFlags(this, target);
|
SetAntialiasingFlags(this, target);
|
||||||
|
|
||||||
@@ -234,12 +260,23 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||||||
|
|
||||||
ctx = nullptr;
|
ctx = nullptr;
|
||||||
|
|
||||||
PaintThread::Get()->PaintContents(captureDT, target);
|
// TODO: Fixup component alpha
|
||||||
|
DrawTarget* targetOnWhite = nullptr;
|
||||||
|
RefPtr<CapturedPaintState> capturedState
|
||||||
|
= MakeAndAddRef<CapturedPaintState>(state.mRegionToDraw,
|
||||||
|
target, targetOnWhite,
|
||||||
|
capturedTransform,
|
||||||
|
state.mMode,
|
||||||
|
state.mContentType);
|
||||||
|
|
||||||
|
PaintThread::Get()->PaintContents(captureDT,
|
||||||
|
capturedState,
|
||||||
|
RotatedContentBuffer::PrepareDrawTargetForPainting);
|
||||||
|
|
||||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||||
|
|
||||||
didUpdate = true;
|
didUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mContentClient->EndPaint(nullptr);
|
mContentClient->EndPaint(nullptr);
|
||||||
|
|
||||||
if (didUpdate) {
|
if (didUpdate) {
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ public:
|
|||||||
virtual gfx::DrawTarget* BorrowDrawTargetForPainting(RotatedContentBuffer::PaintState& aPaintState,
|
virtual gfx::DrawTarget* BorrowDrawTargetForPainting(RotatedContentBuffer::PaintState& aPaintState,
|
||||||
RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
|
RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
|
||||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
|
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
|
||||||
|
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(RotatedContentBuffer::PaintState& aPaintState,
|
||||||
|
RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
|
||||||
// Called as part of the layers transation reply. Conveys data about our
|
// Called as part of the layers transation reply. Conveys data about our
|
||||||
// buffer(s) from the compositor. If appropriate we should swap references
|
// buffer(s) from the compositor. If appropriate we should swap references
|
||||||
// to our buffers.
|
// to our buffers.
|
||||||
@@ -151,6 +152,11 @@ public:
|
|||||||
{
|
{
|
||||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
||||||
}
|
}
|
||||||
|
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||||
|
RotatedContentBuffer::DrawIterator* aIter = nullptr) override
|
||||||
|
{
|
||||||
|
return RotatedContentBuffer::BorrowDrawTargetForRecording(aPaintState, aIter);
|
||||||
|
}
|
||||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
||||||
{
|
{
|
||||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||||
@@ -234,6 +240,11 @@ public:
|
|||||||
{
|
{
|
||||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
||||||
}
|
}
|
||||||
|
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||||
|
RotatedContentBuffer::DrawIterator* aIter = nullptr) override
|
||||||
|
{
|
||||||
|
return RotatedContentBuffer::BorrowDrawTargetForRecording(aPaintState, aIter);
|
||||||
|
}
|
||||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
||||||
{
|
{
|
||||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||||
|
|||||||
@@ -5856,3 +5856,6 @@ pref("toolkit.crashreporter.include_context_heap", true);
|
|||||||
|
|
||||||
// Open noopener links in a new process
|
// Open noopener links in a new process
|
||||||
pref("dom.noopener.newprocess.enabled", true);
|
pref("dom.noopener.newprocess.enabled", true);
|
||||||
|
|
||||||
|
pref("layers.omtp.enabled", false);
|
||||||
|
pref("layers.omtp.force-sync", false);
|
||||||
Reference in New Issue
Block a user