Workaround for PowerVR clear issue.

BUG=skia:

Review URL: https://codereview.chromium.org/701573002
This commit is contained in:
bsalomon 2014-11-05 07:05:34 -08:00 committed by Commit bot
parent 0737922ca2
commit 63b2196286
12 changed files with 100 additions and 47 deletions

View File

@ -546,6 +546,31 @@ void GrDrawTarget::drawPaths(const GrPathRange* pathRange,
dstCopy.texture() ? &dstCopy : NULL); dstCopy.texture() ? &dstCopy : NULL);
} }
void GrDrawTarget::clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) {
if (fCaps->useDrawInsteadOfClear()) {
// This works around a driver bug with clear by drawing a rect instead.
// The driver will ignore a clear if it is the only thing rendered to a
// target before the target is read.
SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) {
rect = &rtRect;
// We first issue a discard() since that may help tilers.
this->discard(renderTarget);
}
AutoStateRestore asr(this, kReset_ASRInit, &SkMatrix::I());
this->drawState()->setColor(color);
this->drawState()->disableState(GrDrawState::kClip_StateBit);
this->drawState()->disableState(GrDrawState::kHWAntialias_StateBit);
this->drawState()->setRenderTarget(renderTarget);
this->drawSimpleRect(*rect);
} else {
this->onClear(rect, color, canIgnoreRect, renderTarget);
}
}
typedef GrTraceMarkerSet::Iter TMIter; typedef GrTraceMarkerSet::Iter TMIter;
void GrDrawTarget::saveActiveTraceMarkers() { void GrDrawTarget::saveActiveTraceMarkers() {
if (this->caps()->gpuTracingSupport()) { if (this->caps()->gpuTracingSupport()) {
@ -969,6 +994,8 @@ void GrDrawTargetCaps::reset() {
fGpuTracingSupport = false; fGpuTracingSupport = false;
fCompressedTexSubImageSupport = false; fCompressedTexSubImageSupport = false;
fUseDrawInsteadOfClear = false;
fMapBufferFlags = kNone_MapFlags; fMapBufferFlags = kNone_MapFlags;
fMaxRenderTargetSize = 0; fMaxRenderTargetSize = 0;
@ -995,6 +1022,8 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
fGpuTracingSupport = other.fGpuTracingSupport; fGpuTracingSupport = other.fGpuTracingSupport;
fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport; fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport;
fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear;
fMapBufferFlags = other.fMapBufferFlags; fMapBufferFlags = other.fMapBufferFlags;
fMaxRenderTargetSize = other.fMaxRenderTargetSize; fMaxRenderTargetSize = other.fMaxRenderTargetSize;
@ -1030,25 +1059,29 @@ static SkString map_flags_to_string(uint32_t flags) {
SkString GrDrawTargetCaps::dump() const { SkString GrDrawTargetCaps::dump() const {
SkString r; SkString r;
static const char* gNY[] = {"NO", "YES"}; static const char* gNY[] = {"NO", "YES"};
r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]);
r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]); r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]);
r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]);
r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]);
r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]);
r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str()); r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
r.appendf("Map Buffer Support : %s\n",
map_flags_to_string(fMapBufferFlags).c_str());
static const char* kConfigNames[] = { static const char* kConfigNames[] = {
"Unknown", // kUnknown_GrPixelConfig "Unknown", // kUnknown_GrPixelConfig

View File

@ -395,8 +395,8 @@ public:
* rect is NULL, otherwise just the rect. If canIgnoreRect is set then the entire render target * rect is NULL, otherwise just the rect. If canIgnoreRect is set then the entire render target
* can be optionally cleared. * can be optionally cleared.
*/ */
virtual void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect, void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) = 0; GrRenderTarget* renderTarget);
/** /**
* Discards the contents render target. * Discards the contents render target.
@ -855,6 +855,10 @@ private:
const float transforms[], PathTransformType, const float transforms[], PathTransformType,
GrPathRendering::FillType, const GrDeviceCoordTexture*) = 0; GrPathRendering::FillType, const GrDeviceCoordTexture*) = 0;
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) = 0;
virtual void didAddGpuTraceMarker() = 0; virtual void didAddGpuTraceMarker() = 0;
virtual void didRemoveGpuTraceMarker() = 0; virtual void didRemoveGpuTraceMarker() = 0;

View File

@ -46,6 +46,8 @@ public:
bool gpuTracingSupport() const { return fGpuTracingSupport; } bool gpuTracingSupport() const { return fGpuTracingSupport; }
bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; } bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; }
bool useDrawInsteadOfClear() const { return fUseDrawInsteadOfClear; }
/** /**
* Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and * Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
* textures allows partial mappings or full mappings. * textures allows partial mappings or full mappings.
@ -104,6 +106,9 @@ protected:
bool fGpuTracingSupport : 1; bool fGpuTracingSupport : 1;
bool fCompressedTexSubImageSupport : 1; bool fCompressedTexSubImageSupport : 1;
// Driver workaround
bool fUseDrawInsteadOfClear : 1;
uint32_t fMapBufferFlags; uint32_t fMapBufferFlags;
int fMaxRenderTargetSize; int fMaxRenderTargetSize;

View File

@ -194,13 +194,13 @@ GrIndexBuffer* GrGpu::createInstancedIndexBuffer(const uint16_t* pattern,
return buffer; return buffer;
} }
void GrGpu::clear(const SkIRect* rect, void GrGpu::onClear(const SkIRect* rect,
GrColor color, GrColor color,
bool canIgnoreRect, bool canIgnoreRect,
GrRenderTarget* renderTarget) { GrRenderTarget* renderTarget) {
SkASSERT(renderTarget); SkASSERT(renderTarget);
this->handleDirtyContext(); this->handleDirtyContext();
this->onClear(renderTarget, rect, color, canIgnoreRect); this->onGpuClear(renderTarget, rect, color, canIgnoreRect);
} }
void GrGpu::clearStencilClip(const SkIRect& rect, void GrGpu::clearStencilClip(const SkIRect& rect,

View File

@ -266,9 +266,6 @@ public:
size_t rowBytes); size_t rowBytes);
// GrDrawTarget overrides // GrDrawTarget overrides
virtual void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) SK_OVERRIDE;
virtual void clearStencilClip(const SkIRect& rect, virtual void clearStencilClip(const SkIRect& rect,
bool insideClip, bool insideClip,
GrRenderTarget* renderTarget = NULL) SK_OVERRIDE; GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
@ -374,7 +371,8 @@ private:
virtual void releaseReservedIndexSpace() SK_OVERRIDE; virtual void releaseReservedIndexSpace() SK_OVERRIDE;
virtual void geometrySourceWillPush() SK_OVERRIDE; virtual void geometrySourceWillPush() SK_OVERRIDE;
virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE; virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) SK_OVERRIDE;
// called when the 3D context state is unknown. Subclass should emit any // called when the 3D context state is unknown. Subclass should emit any
// assumed 3D context state and dirty any state cache. // assumed 3D context state and dirty any state cache.
@ -391,11 +389,9 @@ private:
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0; virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0; virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0;
// overridden by backend-specific derived class to perform the clear and // overridden by backend-specific derived class to perform the clear.
// clearRect. NULL rect means clear whole target. If canIgnoreRect is virtual void onGpuClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
// true, it is okay to perform a full clear instead of a partial clear bool canIgnoreRect) = 0;
virtual void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
bool canIgnoreRect) = 0;
// Overridden by backend specific classes to perform a clear of the stencil clip bits. This is // Overridden by backend specific classes to perform a clear of the stencil clip bits. This is

View File

@ -414,8 +414,8 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
this->recordTraceMarkersIfNecessary(); this->recordTraceMarkersIfNecessary();
} }
void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color, void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
bool canIgnoreRect, GrRenderTarget* renderTarget) { bool canIgnoreRect, GrRenderTarget* renderTarget) {
SkIRect r; SkIRect r;
if (NULL == renderTarget) { if (NULL == renderTarget) {
renderTarget = this->drawState()->getRenderTarget(); renderTarget = this->drawState()->getRenderTarget();

View File

@ -86,11 +86,6 @@ public:
const SkIRect& srcRect, const SkIRect& srcRect,
const SkIPoint& dstPoint) SK_OVERRIDE; const SkIPoint& dstPoint) SK_OVERRIDE;
virtual void clear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
GrRenderTarget* renderTarget) SK_OVERRIDE;
virtual void clearStencilClip(const SkIRect& rect, virtual void clearStencilClip(const SkIRect& rect,
bool insideClip, bool insideClip,
GrRenderTarget* renderTarget) SK_OVERRIDE; GrRenderTarget* renderTarget) SK_OVERRIDE;
@ -274,6 +269,10 @@ private:
const uint32_t indices[], int count, const uint32_t indices[], int count,
const float transforms[], PathTransformType, const float transforms[], PathTransformType,
GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE; GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
virtual void onClear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
GrRenderTarget* renderTarget) SK_OVERRIDE;
virtual bool onReserveVertexSpace(size_t vertexSize, virtual bool onReserveVertexSpace(size_t vertexSize,
int vertexCount, int vertexCount,

View File

@ -380,6 +380,11 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount); GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount);
} }
if (kPowerVR54x_GrGLRenderer == ctxInfo.renderer() ||
kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) {
fUseDrawInsteadOfClear = true;
}
this->initConfigTexturableTable(ctxInfo, gli); this->initConfigTexturableTable(ctxInfo, gli);
this->initConfigRenderableTable(ctxInfo); this->initConfigRenderableTable(ctxInfo);

View File

@ -191,7 +191,7 @@ GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
return kQualcomm_GrGLVendor; return kQualcomm_GrGLVendor;
} }
if (0 == strcmp(vendorString, "NVIDIA Corporation")) { if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
return kNVIDIA_GrGLVendor; return kNVIDIA_GrGLVendor;
} }
} }
return kOther_GrGLVendor; return kOther_GrGLVendor;
@ -204,6 +204,16 @@ GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
} else if (0 == strcmp(rendererString, "NVIDIA Tegra")) { } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
return kTegra2_GrGLRenderer; return kTegra2_GrGLRenderer;
} }
int lastDigit;
int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
return kPowerVR54x_GrGLRenderer;
}
static const char kPowerVRRogueStr[] = "PowerVR Rogue";
if (0 == strncmp(rendererString, kPowerVRRogueStr,
SK_ARRAY_COUNT(kPowerVRRogueStr)-1)) {
return kPowerVRRogue_GrGLRenderer;
}
} }
return kOther_GrGLRenderer; return kOther_GrGLRenderer;
} }

View File

@ -43,7 +43,8 @@ enum GrGLVendor {
enum GrGLRenderer { enum GrGLRenderer {
kTegra2_GrGLRenderer, kTegra2_GrGLRenderer,
kTegra3_GrGLRenderer, kTegra3_GrGLRenderer,
kPowerVR54x_GrGLRenderer,
kPowerVRRogue_GrGLRenderer,
kOther_GrGLRenderer kOther_GrGLRenderer
}; };

View File

@ -1356,8 +1356,8 @@ void GrGpuGL::disableScissor() {
} }
} }
void GrGpuGL::onClear(GrRenderTarget* target, const SkIRect* rect, GrColor color, void GrGpuGL::onGpuClear(GrRenderTarget* target, const SkIRect* rect, GrColor color,
bool canIgnoreRect) { bool canIgnoreRect) {
// parent class should never let us get here with no RT // parent class should never let us get here with no RT
SkASSERT(target); SkASSERT(target);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);

View File

@ -134,8 +134,8 @@ private:
GrStencilBuffer* sb, GrStencilBuffer* sb,
GrRenderTarget* rt) SK_OVERRIDE; GrRenderTarget* rt) SK_OVERRIDE;
virtual void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color, virtual void onGpuClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
bool canIgnoreRect) SK_OVERRIDE; bool canIgnoreRect) SK_OVERRIDE;
virtual void onClearStencilClip(GrRenderTarget*, virtual void onClearStencilClip(GrRenderTarget*,
const SkIRect& rect, const SkIRect& rect,