mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 22:04:36 +00:00
Bug 1083101 - Implement gfx::DrawingJob. r=jrmuizel
This commit is contained in:
parent
dbac937791
commit
9a89fcdfb3
@ -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;
|
||||
}
|
||||
}
|
||||
|
120
gfx/2d/DrawingJob.cpp
Normal file
120
gfx/2d/DrawingJob.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/* -*- 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 "DrawingJob.h"
|
||||
#include "JobScheduler.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
DrawingJobBuilder::DrawingJobBuilder()
|
||||
{}
|
||||
|
||||
DrawingJobBuilder::~DrawingJobBuilder()
|
||||
{
|
||||
MOZ_ASSERT(!mDrawTarget);
|
||||
}
|
||||
|
||||
void
|
||||
DrawingJob::Clear()
|
||||
{
|
||||
mCommandBuffer = nullptr;
|
||||
mCursor = 0;
|
||||
}
|
||||
|
||||
void
|
||||
DrawingJobBuilder::BeginDrawingJob(DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart)
|
||||
{
|
||||
MOZ_ASSERT(mCommandOffsets.empty());
|
||||
MOZ_ASSERT(aTarget);
|
||||
mDrawTarget = aTarget;
|
||||
mOffset = aOffset;
|
||||
mStart = aStart;
|
||||
}
|
||||
|
||||
DrawingJob*
|
||||
DrawingJobBuilder::EndDrawingJob(CommandBuffer* aCmdBuffer,
|
||||
SyncObject* aCompletion,
|
||||
WorkerThread* aPinToWorker)
|
||||
{
|
||||
MOZ_ASSERT(mDrawTarget);
|
||||
DrawingJob* task = new DrawingJob(mDrawTarget, mOffset, mStart, aCompletion, aPinToWorker);
|
||||
task->mCommandBuffer = aCmdBuffer;
|
||||
task->mCommandOffsets = Move(mCommandOffsets);
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
mOffset = IntPoint();
|
||||
mStart = nullptr;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
DrawingJob::DrawingJob(DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart, SyncObject* aCompletion,
|
||||
WorkerThread* aPinToWorker)
|
||||
: Job(aStart, aCompletion, aPinToWorker)
|
||||
, mCommandBuffer(nullptr)
|
||||
, mCursor(0)
|
||||
, mDrawTarget(aTarget)
|
||||
, mOffset(aOffset)
|
||||
{
|
||||
mCommandOffsets.reserve(64);
|
||||
}
|
||||
|
||||
JobStatus
|
||||
DrawingJob::Run()
|
||||
{
|
||||
while (mCursor < mCommandOffsets.size()) {
|
||||
|
||||
DrawingCommand* cmd = mCommandBuffer->GetDrawingCommand(mCommandOffsets[mCursor]);
|
||||
|
||||
if (!cmd) {
|
||||
return JobStatus::Error;
|
||||
}
|
||||
|
||||
cmd->ExecuteOnDT(mDrawTarget);
|
||||
|
||||
++mCursor;
|
||||
}
|
||||
|
||||
return JobStatus::Complete;
|
||||
}
|
||||
|
||||
DrawingJob::~DrawingJob()
|
||||
{
|
||||
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
|
157
gfx/2d/DrawingJob.h
Normal file
157
gfx/2d/DrawingJob.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* -*- 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/JobScheduler.h"
|
||||
#include "mozilla/gfx/IterableArena.h"
|
||||
#include "DrawCommand.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class DrawingCommand;
|
||||
class PrintCommand;
|
||||
class SignalCommand;
|
||||
class DrawingJob;
|
||||
class WaitCommand;
|
||||
|
||||
class SyncObject;
|
||||
class MultiThreadedJobQueue;
|
||||
|
||||
class DrawTarget;
|
||||
|
||||
class DrawingJobBuilder;
|
||||
class CommandBufferBuilder;
|
||||
|
||||
/// Contains a sequence of immutable drawing commands that are typically used by
|
||||
/// several DrawingJobs.
|
||||
///
|
||||
/// 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:
|
||||
explicit 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 DrawingJob : public Job {
|
||||
public:
|
||||
~DrawingJob();
|
||||
|
||||
virtual JobStatus Run() override;
|
||||
|
||||
protected:
|
||||
DrawingJob(DrawTarget* aTarget,
|
||||
IntPoint aOffset,
|
||||
SyncObject* aStart,
|
||||
SyncObject* aCompletion,
|
||||
WorkerThread* aPinToWorker = nullptr);
|
||||
|
||||
/// 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 DrawingJobBuilder;
|
||||
};
|
||||
|
||||
/// Generates DrawingJob objects.
|
||||
///
|
||||
/// The builder is a separate object to ensure that commands are not added to a
|
||||
/// submitted DrawingJob.
|
||||
class DrawingJobBuilder {
|
||||
public:
|
||||
DrawingJobBuilder();
|
||||
|
||||
~DrawingJobBuilder();
|
||||
|
||||
/// Allocates a DrawingJob.
|
||||
///
|
||||
/// call this method before starting to add commands.
|
||||
void BeginDrawingJob(DrawTarget* aTarget, IntPoint aOffset,
|
||||
SyncObject* aStart = nullptr);
|
||||
|
||||
/// Build the DrawingJob, command after command.
|
||||
/// This must be used between BeginDrawingJob and EndDrawingJob.
|
||||
void AddCommand(ptrdiff_t offset)
|
||||
{
|
||||
mCommandOffsets.push_back(offset);
|
||||
}
|
||||
|
||||
/// Finalizes and returns the drawing task.
|
||||
///
|
||||
/// 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.
|
||||
DrawingJob* EndDrawingJob(CommandBuffer* aCmdBuffer,
|
||||
SyncObject* aCompletion = nullptr,
|
||||
WorkerThread* aPinToWorker = nullptr);
|
||||
|
||||
/// Returns true between BeginDrawingJob and EndDrawingJob, false otherwise.
|
||||
bool HasDrawingJob() const { return !!mDrawTarget; }
|
||||
|
||||
protected:
|
||||
std::vector<ptrdiff_t> mCommandOffsets;
|
||||
RefPtr<DrawTarget> mDrawTarget;
|
||||
IntPoint mOffset;
|
||||
RefPtr<SyncObject> mStart;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -127,6 +127,7 @@ UNIFIED_SOURCES += [
|
||||
'DataSourceSurface.cpp',
|
||||
'DataSurfaceHelpers.cpp',
|
||||
'DrawEventRecorder.cpp',
|
||||
'DrawingJob.cpp',
|
||||
'DrawTarget.cpp',
|
||||
'DrawTargetCairo.cpp',
|
||||
'DrawTargetCapture.cpp',
|
||||
|
Loading…
x
Reference in New Issue
Block a user