mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1042291 - Implement a better heuristic for when to use HW accelerated <canvas> r=snorp
This commit is contained in:
parent
4d3fe6fe9f
commit
677c5c8d14
@ -724,6 +724,9 @@ public:
|
|||||||
static_cast<CanvasRenderingContext2DUserData*>(aData);
|
static_cast<CanvasRenderingContext2DUserData*>(aData);
|
||||||
if (self->mContext) {
|
if (self->mContext) {
|
||||||
self->mContext->MarkContextClean();
|
self->mContext->MarkContextClean();
|
||||||
|
if (self->mContext->mDrawObserver) {
|
||||||
|
self->mContext->mDrawObserver->FrameEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool IsForContext(CanvasRenderingContext2D *aContext)
|
bool IsForContext(CanvasRenderingContext2D *aContext)
|
||||||
@ -826,6 +829,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
|||||||
, mResetLayer(true)
|
, mResetLayer(true)
|
||||||
, mIPC(false)
|
, mIPC(false)
|
||||||
, mStream(nullptr)
|
, mStream(nullptr)
|
||||||
|
, mDrawObserver(nullptr)
|
||||||
, mIsEntireFrameInvalid(false)
|
, mIsEntireFrameInvalid(false)
|
||||||
, mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
|
, mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
|
||||||
, mInvalidateCount(0)
|
, mInvalidateCount(0)
|
||||||
@ -838,6 +842,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
|||||||
mRenderingMode = RenderingMode::SoftwareBackendMode;
|
mRenderingMode = RenderingMode::SoftwareBackendMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDrawObserver = new CanvasDrawObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||||
@ -3816,6 +3821,10 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
|||||||
uint8_t optional_argc,
|
uint8_t optional_argc,
|
||||||
ErrorResult& error)
|
ErrorResult& error)
|
||||||
{
|
{
|
||||||
|
if (mDrawObserver) {
|
||||||
|
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::DrawImage);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
||||||
|
|
||||||
RefPtr<SourceSurface> srcSurf;
|
RefPtr<SourceSurface> srcSurf;
|
||||||
@ -4332,6 +4341,10 @@ CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
|
|||||||
double aSy, double aSw,
|
double aSy, double aSw,
|
||||||
double aSh, ErrorResult& error)
|
double aSh, ErrorResult& error)
|
||||||
{
|
{
|
||||||
|
if (mDrawObserver) {
|
||||||
|
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData);
|
||||||
|
}
|
||||||
|
|
||||||
EnsureTarget();
|
EnsureTarget();
|
||||||
if (!IsTargetValid()) {
|
if (!IsTargetValid()) {
|
||||||
error.Throw(NS_ERROR_FAILURE);
|
error.Throw(NS_ERROR_FAILURE);
|
||||||
@ -4412,6 +4425,10 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
|||||||
uint32_t aHeight,
|
uint32_t aHeight,
|
||||||
JSObject** aRetval)
|
JSObject** aRetval)
|
||||||
{
|
{
|
||||||
|
if (mDrawObserver) {
|
||||||
|
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(aWidth && aHeight);
|
MOZ_ASSERT(aWidth && aHeight);
|
||||||
|
|
||||||
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
|
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
|
||||||
@ -4585,6 +4602,10 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
|
|||||||
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
|
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
|
||||||
int32_t dirtyWidth, int32_t dirtyHeight)
|
int32_t dirtyWidth, int32_t dirtyHeight)
|
||||||
{
|
{
|
||||||
|
if (mDrawObserver) {
|
||||||
|
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::PutImageData);
|
||||||
|
}
|
||||||
|
|
||||||
if (w == 0 || h == 0) {
|
if (w == 0 || h == 0) {
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "mozilla/dom/CanvasPattern.h"
|
#include "mozilla/dom/CanvasPattern.h"
|
||||||
#include "mozilla/gfx/Rect.h"
|
#include "mozilla/gfx/Rect.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "imgIEncoder.h"
|
#include "imgIEncoder.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
@ -115,6 +116,7 @@ private:
|
|||||||
|
|
||||||
struct CanvasBidiProcessor;
|
struct CanvasBidiProcessor;
|
||||||
class CanvasRenderingContext2DUserData;
|
class CanvasRenderingContext2DUserData;
|
||||||
|
class CanvasDrawObserver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** CanvasRenderingContext2D
|
** CanvasRenderingContext2D
|
||||||
@ -767,6 +769,11 @@ protected:
|
|||||||
|
|
||||||
RefPtr<gl::SurfaceStream> mStream;
|
RefPtr<gl::SurfaceStream> mStream;
|
||||||
|
|
||||||
|
// This observes our draw calls at the beginning of the canvas
|
||||||
|
// lifetime and switches to software or GPU mode depending on
|
||||||
|
// what it thinks is best
|
||||||
|
CanvasDrawObserver *mDrawObserver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
|
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
|
||||||
* Redraw is called, reset to false when Render is called.
|
* Redraw is called, reset to false when Render is called.
|
||||||
@ -1081,6 +1088,73 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend struct CanvasBidiProcessor;
|
friend struct CanvasBidiProcessor;
|
||||||
|
friend class CanvasDrawObserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CanvasDrawObserver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CanvasDrawObserver(CanvasRenderingContext2D* aCanvasContext)
|
||||||
|
: mCanvasContext(aCanvasContext)
|
||||||
|
, mDisabled(false)
|
||||||
|
, mSoftwarePreferredCalls(0)
|
||||||
|
, mGPUPreferredCalls(0)
|
||||||
|
, mFramesRendered(0)
|
||||||
|
, mCreationTime(TimeStamp::NowLoRes())
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Only enumerate draw calls that could affect the heuristic
|
||||||
|
enum DrawCallType {
|
||||||
|
PutImageData,
|
||||||
|
GetImageData,
|
||||||
|
DrawImage
|
||||||
|
};
|
||||||
|
|
||||||
|
void DidDrawCall(DrawCallType aType) {
|
||||||
|
if (mDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (aType) {
|
||||||
|
case PutImageData:
|
||||||
|
case GetImageData:
|
||||||
|
mSoftwarePreferredCalls++;
|
||||||
|
break;
|
||||||
|
case DrawImage:
|
||||||
|
mGPUPreferredCalls++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameEnd() {
|
||||||
|
if (mDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFramesRendered++;
|
||||||
|
|
||||||
|
TimeDuration timeElapsed = TimeStamp::NowLoRes() - mCreationTime;
|
||||||
|
|
||||||
|
// We log the first 30 frames of any canvas object then make a
|
||||||
|
// call to determine whether it should be GPU or CPU backed
|
||||||
|
if (mFramesRendered >= 30 || timeElapsed.ToSeconds() >= 5.0) {
|
||||||
|
if (mGPUPreferredCalls >= mSoftwarePreferredCalls) {
|
||||||
|
mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::OpenGLBackendMode);
|
||||||
|
} else {
|
||||||
|
mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::SoftwareBackendMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDisabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CanvasRenderingContext2D* mCanvasContext;
|
||||||
|
bool mDisabled;
|
||||||
|
unsigned int mSoftwarePreferredCalls;
|
||||||
|
unsigned int mGPUPreferredCalls;
|
||||||
|
unsigned int mFramesRendered;
|
||||||
|
TimeStamp mCreationTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType)
|
MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType)
|
||||||
|
Loading…
Reference in New Issue
Block a user