Fixed two bugs in SW-only clip mask generation

http://codereview.appspot.com/6306086/



git-svn-id: http://skia.googlecode.com/svn/trunk@4290 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2012-06-21 20:15:48 +00:00
Родитель 7aa876bfbf
Коммит c82a8b7aa4
11 изменённых файлов: 96 добавлений и 43 удалений

Просмотреть файл

@ -342,8 +342,11 @@ public:
* Clear the entire or rect of the render target, ignoring any clips. * Clear the entire or rect of the render target, ignoring any clips.
* @param rect the rect to clear or the whole thing if rect is NULL. * @param rect the rect to clear or the whole thing if rect is NULL.
* @param color the color to clear to. * @param color the color to clear to.
* @param target if non-NULL, the render target to clear otherwise clear
* the current render target
*/ */
void clear(const GrIRect* rect, GrColor color); void clear(const GrIRect* rect, GrColor color,
GrRenderTarget* target = NULL);
/** /**
* Draw everywhere (respecting the clip) with the paint. * Draw everywhere (respecting the clip) with the paint.

Просмотреть файл

@ -427,21 +427,6 @@ void GrClipMaskManager::drawTexture(GrTexture* target,
drawState->setTexture(0, NULL); drawState->setTexture(0, NULL);
} }
namespace {
void clear(GrGpu* gpu,
GrTexture* target,
GrColor color) {
GrDrawState* drawState = gpu->drawState();
GrAssert(NULL != drawState);
// zap entire target to specified color
drawState->setRenderTarget(target->asRenderTarget());
gpu->clear(NULL, color);
}
}
// get a texture to act as a temporary buffer for AA clip boolean operations // get a texture to act as a temporary buffer for AA clip boolean operations
// TODO: given the expense of createTexture we may want to just cache this too // TODO: given the expense of createTexture we may want to just cache this too
void GrClipMaskManager::getTemp(const GrIRect& bounds, void GrClipMaskManager::getTemp(const GrIRect& bounds,
@ -577,7 +562,9 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
&clearToInside, &clearToInside,
&startOp); &startOp);
clear(fGpu, accum, clearToInside ? 0xffffffff : 0x00000000); fGpu->clear(NULL,
clearToInside ? 0xffffffff : 0x00000000,
accum->asRenderTarget());
GrAutoScratchTexture temp; GrAutoScratchTexture temp;
@ -592,7 +579,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
// replace ops and alter GrClip to allow them through // replace ops and alter GrClip to allow them through
// clear the accumulator and draw the new object directly into it // clear the accumulator and draw the new object directly into it
clear(fGpu, accum, 0x00000000); fGpu->clear(NULL, 0x00000000, accum->asRenderTarget());
setup_boolean_blendcoeffs(drawState, op); setup_boolean_blendcoeffs(drawState, op);
this->drawClipShape(accum, clipIn, c); this->drawClipShape(accum, clipIn, c);
@ -613,7 +600,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
} }
// clear the temp target & draw into it // clear the temp target & draw into it
clear(fGpu, temp.texture(), 0x00000000); fGpu->clear(NULL, 0x00000000, temp.texture()->asRenderTarget());
setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
this->drawClipShape(temp.texture(), clipIn, c); this->drawClipShape(temp.texture(), clipIn, c);
@ -1146,11 +1133,11 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClip& clipIn,
GrDrawState* drawState = fGpu->drawState(); GrDrawState* drawState = fGpu->drawState();
GrAssert(NULL != drawState); GrAssert(NULL != drawState);
GrRenderTarget* temp = drawState->getRenderTarget(); GrRenderTarget* temp = drawState->getRenderTarget();
clear(fGpu, accum, 0x00000000); fGpu->clear(NULL, 0x00000000, accum->asRenderTarget());
// can't leave the accum bound as a rendertarget // can't leave the accum bound as a rendertarget
drawState->setRenderTarget(temp); drawState->setRenderTarget(temp);
helper.toTexture(accum); helper.toTexture(accum, clearToInside);
*result = accum; *result = accum;

Просмотреть файл

@ -605,9 +605,11 @@ void GrContext::setClip(const GrIRect& rect) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void GrContext::clear(const GrIRect* rect, const GrColor color) { void GrContext::clear(const GrIRect* rect,
const GrColor color,
GrRenderTarget* target) {
this->flush(); this->flush();
fGpu->clear(rect, color); fGpu->clear(rect, color, target);
} }
void GrContext::drawPaint(const GrPaint& paint) { void GrContext::drawPaint(const GrPaint& paint) {

Просмотреть файл

@ -546,11 +546,13 @@ public:
} }
/** /**
* Clear the render target. Ignores the clip and all other draw state * Clear the current render target if one isn't passed in. Ignores the
* (blend mode, stages, etc). Clears the whole thing if rect is NULL, * clip and all other draw state (blend mode, stages, etc). Clears the
* otherwise just the rect. * whole thing if rect is NULL, otherwise just the rect.
*/ */
virtual void clear(const GrIRect* rect, GrColor color) = 0; virtual void clear(const GrIRect* rect,
GrColor color,
GrRenderTarget* renderTarget = NULL) = 0;
/** /**
* Release any resources that are cached but not currently in use. This * Release any resources that are cached but not currently in use. This

Просмотреть файл

@ -233,12 +233,25 @@ GrPath* GrGpu::createPath(const SkPath& path) {
return this->onCreatePath(path); return this->onCreatePath(path);
} }
void GrGpu::clear(const GrIRect* rect, GrColor color) { void GrGpu::clear(const GrIRect* rect,
GrColor color,
GrRenderTarget* renderTarget) {
GrRenderTarget* oldRT = NULL;
if (NULL != renderTarget &&
renderTarget != this->drawState()->getRenderTarget()) {
oldRT = this->drawState()->getRenderTarget();
this->drawState()->setRenderTarget(renderTarget);
}
if (NULL == this->getDrawState().getRenderTarget()) { if (NULL == this->getDrawState().getRenderTarget()) {
return; return;
} }
this->handleDirtyContext(); this->handleDirtyContext();
this->onClear(rect, color); this->onClear(rect, color);
if (NULL != oldRT) {
this->drawState()->setRenderTarget(oldRT);
}
} }
void GrGpu::forceRenderTargetFlush() { void GrGpu::forceRenderTargetFlush() {

Просмотреть файл

@ -290,7 +290,9 @@ public:
void removeResource(GrResource* resource); void removeResource(GrResource* resource);
// GrDrawTarget overrides // GrDrawTarget overrides
virtual void clear(const GrIRect* rect, GrColor color) SK_OVERRIDE; virtual void clear(const GrIRect* rect,
GrColor color,
GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
virtual void purgeResources() SK_OVERRIDE { virtual void purgeResources() SK_OVERRIDE {
// The clip mask manager can rebuild all its clip masks so just // The clip mask manager can rebuild all its clip masks so just

Просмотреть файл

@ -25,7 +25,8 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
, fLastRectVertexLayout(0) , fLastRectVertexLayout(0)
, fQuadIndexBuffer(NULL) , fQuadIndexBuffer(NULL)
, fMaxQuads(0) , fMaxQuads(0)
, fCurrQuad(0) { , fCurrQuad(0)
, fFlushing(false) {
fCaps = gpu->getCaps(); fCaps = gpu->getCaps();
@ -443,7 +444,9 @@ void GrInOrderDrawBuffer::onStencilPath(const GrPath&, GrPathFill) {
GrCrash("Not implemented yet. Should not get here."); GrCrash("Not implemented yet. Should not get here.");
} }
void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) { void GrInOrderDrawBuffer::clear(const GrIRect* rect,
GrColor color,
GrRenderTarget* renderTarget) {
GrIRect r; GrIRect r;
if (NULL == rect) { if (NULL == rect) {
// We could do something smart and remove previous draws and clears to // We could do something smart and remove previous draws and clears to
@ -458,6 +461,8 @@ void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
clr.fColor = color; clr.fColor = color;
clr.fBeforeDrawIdx = fDraws.count(); clr.fBeforeDrawIdx = fDraws.count();
clr.fRect = *rect; clr.fRect = *rect;
clr.fRenderTarget = renderTarget;
GrSafeRef(clr.fRenderTarget);
} }
void GrInOrderDrawBuffer::reset() { void GrInOrderDrawBuffer::reset() {
@ -522,7 +527,9 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
for (int i = 0; i < numDraws; ++i) { for (int i = 0; i < numDraws; ++i) {
while (currClear < fClears.count() && while (currClear < fClears.count() &&
i == fClears[currClear].fBeforeDrawIdx) { i == fClears[currClear].fBeforeDrawIdx) {
target->clear(&fClears[currClear].fRect, fClears[currClear].fColor); target->clear(&fClears[currClear].fRect,
fClears[currClear].fColor,
fClears[currClear].fRenderTarget);
++currClear; ++currClear;
} }
@ -556,7 +563,9 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
} }
while (currClear < fClears.count()) { while (currClear < fClears.count()) {
GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx); GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
target->clear(&fClears[currClear].fRect, fClears[currClear].fColor); target->clear(&fClears[currClear].fRect,
fClears[currClear].fColor,
fClears[currClear].fRenderTarget);
++currClear; ++currClear;
} }
target->setDrawState(prevDrawState); target->setDrawState(prevDrawState);

Просмотреть файл

@ -81,8 +81,18 @@ public:
* constraints and side-effects or playback() and reset apply(). * constraints and side-effects or playback() and reset apply().
*/ */
void flushTo(GrDrawTarget* target) { void flushTo(GrDrawTarget* target) {
if (fFlushing) {
// When creating SW-only clip masks, the GrClipMaskManager can
// cause a GrContext::flush (when copying the mask results back
// to the GPU). Without a guard this results in a recursive call
// to this method.
return;
}
fFlushing = true;
this->playback(target); this->playback(target);
this->reset(); this->reset();
fFlushing = false;
} }
/** /**
@ -112,7 +122,9 @@ public:
int* vertexCount, int* vertexCount,
int* indexCount) const SK_OVERRIDE; int* indexCount) const SK_OVERRIDE;
virtual void clear(const GrIRect* rect, GrColor color) SK_OVERRIDE; virtual void clear(const GrIRect* rect,
GrColor color,
GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
protected: protected:
virtual void willReserveVertexAndIndexSpace(GrVertexLayout vertexLayout, virtual void willReserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
@ -133,9 +145,13 @@ private:
}; };
struct Clear { struct Clear {
int fBeforeDrawIdx; Clear() : fRenderTarget(NULL) {}
GrIRect fRect; ~Clear() { GrSafeUnref(fRenderTarget); }
GrColor fColor;
int fBeforeDrawIdx;
GrIRect fRect;
GrColor fColor;
GrRenderTarget* fRenderTarget;
}; };
// overrides from GrDrawTarget // overrides from GrDrawTarget
@ -226,6 +242,8 @@ private:
}; };
SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack; SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
bool fFlushing;
typedef GrDrawTarget INHERITED; typedef GrDrawTarget INHERITED;
}; };

Просмотреть файл

@ -13,6 +13,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "SkDraw.h" #include "SkDraw.h"
#include "SkRasterClip.h" #include "SkRasterClip.h"
#include "GrGpu.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path, bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
@ -222,8 +223,26 @@ bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* tex) {
/** /**
* Move the result of the software mask generation back to the gpu * Move the result of the software mask generation back to the gpu
*/ */
void GrSWMaskHelper::toTexture(GrTexture *texture) { void GrSWMaskHelper::toTexture(GrTexture *texture, bool clearToWhite) {
SkAutoLockPixels alp(fBM); SkAutoLockPixels alp(fBM);
// The destination texture is almost always larger than "fBM". Clear
// it appropriately so we don't get mask artifacts outside of the path's
// bounding box
// "texture" needs to be installed as the render target for the clear
// and the texture upload but cannot remain the render target upon
// returned. Callers typically use it as a texture and it would then
// be both source and dest.
GrDrawState::AutoRenderTargetRestore artr(fContext->getGpu()->drawState(),
texture->asRenderTarget());
if (clearToWhite) {
fContext->getGpu()->clear(NULL, SK_ColorWHITE);
} else {
fContext->getGpu()->clear(NULL, 0x00000000);
}
texture->writePixels(0, 0, fBM.width(), fBM.height(), texture->writePixels(0, 0, fBM.width(), fBM.height(),
kAlpha_8_GrPixelConfig, kAlpha_8_GrPixelConfig,
fBM.getPixels(), fBM.rowBytes()); fBM.getPixels(), fBM.rowBytes());
@ -255,7 +274,7 @@ bool sw_draw_path_to_mask_texture(const SkPath& clientPath,
return false; return false;
} }
helper.toTexture(tex->texture()); helper.toTexture(tex->texture(), false);
return true; return true;
} }

Просмотреть файл

@ -40,7 +40,7 @@ public:
bool getTexture(GrAutoScratchTexture* tex); bool getTexture(GrAutoScratchTexture* tex);
void toTexture(GrTexture* texture); void toTexture(GrTexture* texture, bool clearToWhite);
void clear(GrColor color) { void clear(GrColor color) {
fBM.eraseColor(color); fBM.eraseColor(color);

Просмотреть файл

@ -592,10 +592,8 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::clear(SkColor color) { void SkGpuDevice::clear(SkColor color) {
fContext->setRenderTarget(fRenderTarget); fContext->clear(NULL, color, fRenderTarget);
fContext->clear(NULL, color);
} }
void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {