зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1083101 - Implement gfx::DrawingTask. r=jrmuizel
This commit is contained in:
Родитель
6c5cc2c997
Коммит
3ef74569e7
|
@ -39,7 +39,7 @@ class DrawingCommand
|
|||
public:
|
||||
virtual ~DrawingCommand() {}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix& aTransform) = 0;
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix* aTransform = nullptr) = 0;
|
||||
|
||||
protected:
|
||||
explicit DrawingCommand(CommandType aType)
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->DrawSurface(mSurface, mDest, mSource, mSurfOptions, mOptions);
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->DrawFilter(mFilter, mSourceRect, mDestPoint, mOptions);
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->ClearRect(mRect);
|
||||
}
|
||||
|
@ -197,11 +197,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix& aTransform)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix* aTransform)
|
||||
{
|
||||
MOZ_ASSERT(!aTransform.HasNonIntegerTranslation());
|
||||
MOZ_ASSERT(!aTransform || !aTransform->HasNonIntegerTranslation());
|
||||
Point dest(Float(mDestination.x), Float(mDestination.y));
|
||||
dest = aTransform * dest;
|
||||
if (aTransform) {
|
||||
dest = (*aTransform) * dest;
|
||||
}
|
||||
aDT->CopySurface(mSurface, mSourceRect, IntPoint(uint32_t(dest.x), uint32_t(dest.y)));
|
||||
}
|
||||
|
||||
|
@ -224,7 +226,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->FillRect(mRect, mPattern, mOptions);
|
||||
}
|
||||
|
@ -250,7 +252,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->StrokeRect(mRect, mPattern, mStrokeOptions, mOptions);
|
||||
}
|
||||
|
@ -279,7 +281,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->StrokeLine(mStart, mEnd, mPattern, mStrokeOptions, mOptions);
|
||||
}
|
||||
|
@ -305,7 +307,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->Fill(mPath, mPattern, mOptions);
|
||||
}
|
||||
|
@ -331,7 +333,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->Stroke(mPath, mPattern, mStrokeOptions, mOptions);
|
||||
}
|
||||
|
@ -361,7 +363,7 @@ public:
|
|||
memcpy(&mGlyphs.front(), aBuffer.mGlyphs, sizeof(Glyph) * aBuffer.mNumGlyphs);
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
GlyphBuffer buf;
|
||||
buf.mNumGlyphs = mGlyphs.size();
|
||||
|
@ -390,7 +392,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->Mask(mSource, mMask, mOptions);
|
||||
}
|
||||
|
@ -416,7 +418,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->MaskSurface(mSource, mMask, mOffset, mOptions);
|
||||
}
|
||||
|
@ -437,7 +439,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->PushClip(mPath);
|
||||
}
|
||||
|
@ -455,7 +457,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->PushClipRect(mRect);
|
||||
}
|
||||
|
@ -472,7 +474,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix&)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
|
||||
{
|
||||
aDT->PopClip();
|
||||
}
|
||||
|
@ -487,11 +489,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix& aMatrix)
|
||||
virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix* aMatrix)
|
||||
{
|
||||
Matrix transform = mTransform;
|
||||
transform *= aMatrix;
|
||||
aDT->SetTransform(transform);
|
||||
if (aMatrix) {
|
||||
aDT->SetTransform(mTransform * (*aMatrix));
|
||||
} else {
|
||||
aDT->SetTransform(mTransform);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -188,7 +188,7 @@ DrawTargetCaptureImpl::ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransf
|
|||
uint8_t* current = start;
|
||||
|
||||
while (current < start + mDrawCommandStorage.size()) {
|
||||
reinterpret_cast<DrawingCommand*>(current + sizeof(uint32_t))->ExecuteOnDT(aDT, aTransform);
|
||||
reinterpret_cast<DrawingCommand*>(current + sizeof(uint32_t))->ExecuteOnDT(aDT, &aTransform);
|
||||
current += *(uint32_t*)current;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "DrawingTask.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
DrawingTaskBuilder::DrawingTaskBuilder()
|
||||
: mTask(nullptr)
|
||||
{}
|
||||
|
||||
DrawingTaskBuilder::~DrawingTaskBuilder()
|
||||
{
|
||||
if (mTask) {
|
||||
delete mTask;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawingTask::Clear()
|
||||
{
|
||||
mCommandBuffer = nullptr;
|
||||
mCursor = 0;
|
||||
}
|
||||
|
||||
void
|
||||
DrawingTaskBuilder::BeginDrawingTask(MultiThreadedTaskQueue* aTaskQueue,
|
||||
DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart)
|
||||
{
|
||||
MOZ_ASSERT(!mTask);
|
||||
MOZ_ASSERT(aTaskQueue);
|
||||
mTask = new DrawingTask(aTaskQueue, aTarget, aOffset, aStart);
|
||||
}
|
||||
|
||||
DrawingTask*
|
||||
DrawingTaskBuilder::EndDrawingTask(CommandBuffer* aCmdBuffer, SyncObject* aCompletion)
|
||||
{
|
||||
MOZ_ASSERT(mTask);
|
||||
mTask->mCompletionSync = aCompletion;
|
||||
mTask->mCommandBuffer = aCmdBuffer;
|
||||
DrawingTask* task = mTask;
|
||||
mTask = nullptr;
|
||||
return task;
|
||||
}
|
||||
|
||||
DrawingTask::DrawingTask(MultiThreadedTaskQueue* aTaskQueue,
|
||||
DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart)
|
||||
: Task(aTaskQueue, aStart, nullptr)
|
||||
, mCommandBuffer(nullptr)
|
||||
, mCursor(0)
|
||||
, mDrawTarget(aTarget)
|
||||
, mOffset(aOffset)
|
||||
{
|
||||
mCommandOffsets.reserve(64);
|
||||
}
|
||||
|
||||
TaskStatus
|
||||
DrawingTask::Run()
|
||||
{
|
||||
while (mCursor < mCommandOffsets.size()) {
|
||||
|
||||
DrawingCommand* cmd = mCommandBuffer->GetDrawingCommand(mCommandOffsets[mCursor]);
|
||||
|
||||
if (!cmd) {
|
||||
return TaskStatus::Error;
|
||||
}
|
||||
|
||||
cmd->ExecuteOnDT(mDrawTarget);
|
||||
|
||||
++mCursor;
|
||||
}
|
||||
|
||||
return TaskStatus::Complete;
|
||||
}
|
||||
|
||||
DrawingTask::~DrawingTask()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
DrawingCommand*
|
||||
CommandBuffer::GetDrawingCommand(ptrdiff_t aId)
|
||||
{
|
||||
return static_cast<DrawingCommand*>(mStorage.GetStorage(aId));
|
||||
}
|
||||
|
||||
CommandBuffer::~CommandBuffer()
|
||||
{
|
||||
mStorage.ForEach([](void* item){
|
||||
static_cast<DrawingCommand*>(item)->~DrawingCommand();
|
||||
});
|
||||
mStorage.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
CommandBufferBuilder::BeginCommandBuffer(size_t aBufferSize)
|
||||
{
|
||||
MOZ_ASSERT(!mCommands);
|
||||
mCommands = new CommandBuffer(aBufferSize);
|
||||
}
|
||||
|
||||
already_AddRefed<CommandBuffer>
|
||||
CommandBufferBuilder::EndCommandBuffer()
|
||||
{
|
||||
return mCommands.forget();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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_GFX_COMMANDBUFFER_H_
|
||||
#define MOZILLA_GFX_COMMANDBUFFER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "mozilla/gfx/TaskScheduler.h"
|
||||
#include "mozilla/gfx/IterableArena.h"
|
||||
#include "DrawCommand.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class DrawingCommand;
|
||||
class PrintCommand;
|
||||
class SignalCommand;
|
||||
class DrawingTask;
|
||||
class WaitCommand;
|
||||
|
||||
class SyncObject;
|
||||
class MultiThreadedTaskQueue;
|
||||
|
||||
class DrawTarget;
|
||||
|
||||
class DrawingTaskBuilder;
|
||||
class CommandBufferBuilder;
|
||||
|
||||
/// Contains a sequence of immutable drawing commands that are typically used by
|
||||
/// several DrawingTasks.
|
||||
///
|
||||
/// CommandBuffer objects are built using CommandBufferBuilder.
|
||||
class CommandBuffer : public external::AtomicRefCounted<CommandBuffer>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(CommandBuffer)
|
||||
|
||||
~CommandBuffer();
|
||||
|
||||
DrawingCommand* GetDrawingCommand(ptrdiff_t aId);
|
||||
|
||||
protected:
|
||||
CommandBuffer(size_t aSize = 256)
|
||||
: mStorage(IterableArena::GROWABLE, aSize)
|
||||
{}
|
||||
|
||||
IterableArena mStorage;
|
||||
friend class CommandBufferBuilder;
|
||||
};
|
||||
|
||||
/// Generates CommandBuffer objects.
|
||||
///
|
||||
/// The builder is a separate object to ensure that commands are not added to a
|
||||
/// submitted CommandBuffer.
|
||||
class CommandBufferBuilder
|
||||
{
|
||||
public:
|
||||
void BeginCommandBuffer(size_t aBufferSize = 256);
|
||||
|
||||
already_AddRefed<CommandBuffer> EndCommandBuffer();
|
||||
|
||||
/// Build the CommandBuffer, command after command.
|
||||
/// This must be used between BeginCommandBuffer and EndCommandBuffer.
|
||||
template<typename T, typename... Args>
|
||||
ptrdiff_t AddCommand(Args&&... aArgs)
|
||||
{
|
||||
static_assert(IsBaseOf<DrawingCommand, T>::value,
|
||||
"T must derive from DrawingCommand");
|
||||
return mCommands->mStorage.Alloc<T>(Forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
bool HasCommands() const { return !!mCommands; }
|
||||
|
||||
protected:
|
||||
RefPtr<CommandBuffer> mCommands;
|
||||
};
|
||||
|
||||
/// Stores multiple commands to be executed sequencially.
|
||||
class DrawingTask : public Task {
|
||||
public:
|
||||
DrawingTask(MultiThreadedTaskQueue* aTaskQueue,
|
||||
DrawTarget* aTarget,
|
||||
IntPoint aOffset,
|
||||
SyncObject* aStart);
|
||||
|
||||
~DrawingTask();
|
||||
|
||||
virtual TaskStatus Run() override;
|
||||
|
||||
protected:
|
||||
/// Runs the tasks's destructors and resets the buffer.
|
||||
void Clear();
|
||||
|
||||
std::vector<ptrdiff_t> mCommandOffsets;
|
||||
RefPtr<CommandBuffer> mCommandBuffer;
|
||||
uint32_t mCursor;
|
||||
|
||||
RefPtr<DrawTarget> mDrawTarget;
|
||||
IntPoint mOffset;
|
||||
|
||||
friend class DrawingTaskBuilder;
|
||||
};
|
||||
|
||||
/// Generates DrawingTask objects.
|
||||
///
|
||||
/// The builder is a separate object to ensure that commands are not added to a
|
||||
/// submitted DrawingTask.
|
||||
class DrawingTaskBuilder {
|
||||
public:
|
||||
DrawingTaskBuilder();
|
||||
|
||||
~DrawingTaskBuilder();
|
||||
|
||||
/// Allocates a DrawingTask.
|
||||
///
|
||||
/// call this method before starting to add commands.
|
||||
void BeginDrawingTask(MultiThreadedTaskQueue* aTaskQueue,
|
||||
DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart = nullptr);
|
||||
|
||||
/// Build the DrawingTask, command after command.
|
||||
/// This must be used between BeginDrawingTask and EndDrawingTask.
|
||||
void AddCommand(ptrdiff_t offset)
|
||||
{
|
||||
MOZ_ASSERT(mTask);
|
||||
mTask->mCommandOffsets.push_back(offset);
|
||||
}
|
||||
|
||||
/// Finalizes and returns the command buffer.
|
||||
///
|
||||
/// If aCompletion is not null, the sync object will be signaled after the
|
||||
/// task buffer is destroyed (and after the destructor of the tasks have run).
|
||||
/// In most cases this means after the completion of all tasks in the task buffer,
|
||||
/// but also when the task buffer is destroyed due to an error.
|
||||
DrawingTask* EndDrawingTask(CommandBuffer* aCmdBuffer, SyncObject* aCompletion = nullptr);
|
||||
|
||||
/// Returns true between BeginDrawingTask and EndDrawingTask, false otherwise.
|
||||
bool HasDrawingTask() const { return !!mTask; }
|
||||
|
||||
protected:
|
||||
DrawingTask* mTask;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -127,6 +127,7 @@ UNIFIED_SOURCES += [
|
|||
'DataSourceSurface.cpp',
|
||||
'DataSurfaceHelpers.cpp',
|
||||
'DrawEventRecorder.cpp',
|
||||
'DrawingTask.cpp',
|
||||
'DrawTarget.cpp',
|
||||
'DrawTargetCairo.cpp',
|
||||
'DrawTargetCapture.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче