SSSA for drawVerts, cleanup determination of when stage is enabled
Review URL: http://codereview.appspot.com/4430066/
git-svn-id: http://skia.googlecode.com/svn/trunk@1195 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 495eff4..3112112 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -619,6 +619,8 @@
// sets up target to sample coverage of supersampled render target back
// to the main render target using stage kOffscreenStage.
+ // caller should set view matrix to matrix used for this pass prior to
+ // calling.
void setupOffscreenAAPass2(GrDrawTarget* target,
const GrPaint& paint,
OffscreenRecord* record);
diff --git a/gpu/include/GrContext_impl.h b/gpu/include/GrContext_impl.h
index fdcb2b1..b0faa2c 100644
--- a/gpu/include/GrContext_impl.h
+++ b/gpu/include/GrContext_impl.h
@@ -17,6 +17,14 @@
#ifndef GrContext_impl_DEFINED
#define GrContext_impl_DEFINED
+struct GrContext::OffscreenRecord {
+ OffscreenRecord() { fEntry = NULL; }
+ ~OffscreenRecord() { GrAssert(NULL == fEntry); }
+
+ GrTextureEntry* fEntry;
+ GrDrawTarget::SavedDrawState fSavedState;
+};
+
template <typename POS_SRC, typename TEX_SRC,
typename COL_SRC, typename IDX_SRC>
inline void GrContext::drawCustomVertices(const GrPaint& paint,
@@ -44,6 +52,16 @@
layout |= GrDrawTarget::kColor_VertexLayoutBit;
}
+ bool doOffscreenAA = false;
+ OffscreenRecord record;
+ if (paint.fAntiAlias &&
+ !this->getRenderTarget()->isMultisampled() &&
+ !(GrIsPrimTypeLines(primitiveType) && fGpu->supportsAALines()) &&
+ this->setupOffscreenAAPass1(target, false, &record)) {
+ doOffscreenAA = true;
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(kOffscreenStage);
+ }
+
int vertexCount = posSrc.count();
int indexCount = (NULL != idxSrc) ? idxSrc->count() : 0;
@@ -81,6 +99,47 @@
} else {
target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
}
+
+ if (doOffscreenAA) {
+ // draw to the offscreen
+ if (NULL != indices) {
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+ // When there are custom texture coordinates we can't just draw
+ // a quad to sample the offscreen. Instead we redraw the geometry to
+ // specify the texture coords. This isn't quite right either, primitives
+ // will only be eroded at the edges, not expanded into partial pixels.
+ bool useRect = 0 == (layout & GrDrawTarget::StageTexCoordVertexLayoutBit(0,0));
+ if (useRect) {
+ target->setViewMatrix(GrMatrix::I());
+ }
+ this->setupOffscreenAAPass2(target, paint, &record);
+ if (useRect) {
+ geo.set(NULL, 0, 0, 0);
+ int stages = (NULL != paint.getTexture()) ? 0x1 : 0x0;
+ stages |= (1 << kOffscreenStage);
+ GrRect dstRect(0, 0,
+ target->getRenderTarget()->width(),
+ target->getRenderTarget()->height());
+ target->drawSimpleRect(dstRect, NULL, stages);
+ target->drawSimpleRect(dstRect, NULL, stages);
+ } else {
+ if (NULL != indices) {
+ target->drawIndexed (primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+ }
+ this->endOffscreenAA(target, &record);
+ } else {
+ if (NULL != indices) {
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+ }
}
class GrNullTexCoordSource {
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index e021a93..cb36d3c 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -797,20 +797,16 @@
GrVertexLayout vertexLayout,
uint32_t vertexCount,
uint32_t indexCount) {
- fTarget = target;
- fSuccess = fTarget->reserveAndLockGeometry(vertexLayout,
- vertexCount,
- indexCount,
- &fVertices,
- &fIndices);
+ fTarget = NULL;
+ this->set(target, vertexLayout, vertexCount, indexCount);
}
AutoReleaseGeometry() {
- fSuccess = false;
+ fTarget = NULL;
}
~AutoReleaseGeometry() {
- if (fSuccess) {
+ if (NULL != fTarget) {
fTarget->releaseReservedGeometry();
}
}
@@ -819,19 +815,23 @@
GrVertexLayout vertexLayout,
uint32_t vertexCount,
uint32_t indexCount) {
- if (fSuccess) {
+ if (NULL != fTarget) {
fTarget->releaseReservedGeometry();
}
fTarget = target;
- fSuccess = fTarget->reserveAndLockGeometry(vertexLayout,
- vertexCount,
- indexCount,
- &fVertices,
- &fIndices);
- return fSuccess;
+ if (NULL != fTarget) {
+ if (!fTarget->reserveAndLockGeometry(vertexLayout,
+ vertexCount,
+ indexCount,
+ &fVertices,
+ &fIndices)) {
+ fTarget = NULL;
+ }
+ }
+ return NULL != fTarget;
}
- bool succeeded() const { return fSuccess; }
+ bool succeeded() const { return NULL != fTarget; }
void* vertices() const { return fVertices; }
void* indices() const { return fIndices; }
@@ -841,7 +841,6 @@
private:
GrDrawTarget* fTarget;
- bool fSuccess;
void* fVertices;
void* fIndices;
};
@@ -1020,6 +1019,15 @@
static void VertexLayoutUnitTest();
protected:
+ // given a vertex layout and a draw state, will a stage be used?
+ static bool StageWillBeUsed(int stage, GrVertexLayout layout,
+ const DrState& state) {
+ return NULL != state.fTextures[stage] && VertexUsesStage(stage, layout);
+ }
+
+ bool isStageEnabled(int stage) const {
+ return StageWillBeUsed(stage, fGeometrySrc.fVertexLayout, fCurrDrawState);
+ }
// Helpers for GrDrawTarget subclasses that won't have private access to
// SavedDrawState but need to peek at the state values.
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 8acb3dc..0584e4b 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -416,14 +416,6 @@
////////////////////////////////////////////////////////////////////////////////
-struct GrContext::OffscreenRecord {
- OffscreenRecord() { fEntry = NULL; }
- ~OffscreenRecord() { GrAssert(NULL == fEntry); }
-
- GrTextureEntry* fEntry;
- GrDrawTarget::SavedDrawState fSavedState;
-};
-
bool GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
bool requireStencil,
OffscreenRecord* record) {
@@ -484,17 +476,16 @@
target->restoreDrawState(record->fSavedState);
- target->setViewMatrix(GrMatrix::I());
target->setTexture(kOffscreenStage, offscreen);
- GrMatrix scaleM;
-
- scaleM.setScale(GR_Scalar1 / target->getRenderTarget()->width(),
- GR_Scalar1 / target->getRenderTarget()->height());
+ GrMatrix sampleM;
+ sampleM.setScale(GR_Scalar1 / target->getRenderTarget()->width(),
+ GR_Scalar1 / target->getRenderTarget()->height());
+ sampleM.preConcat(target->getViewMatrix());
// use bilinear filtering to get downsample
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
- scaleM, true);
+ sampleM, true);
target->setSamplerState(kOffscreenStage, sampler);
}
@@ -955,6 +946,16 @@
vertexSize += sizeof(GrColor);
}
+ bool doOffscreenAA = false;
+ OffscreenRecord record;
+ if (paint.fAntiAlias &&
+ !this->getRenderTarget()->isMultisampled() &&
+ !(GrIsPrimTypeLines(primitiveType) && fGpu->supportsAALines()) &&
+ this->setupOffscreenAAPass1(target, false, &record)) {
+ doOffscreenAA = true;
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(kOffscreenStage);
+ }
+
if (sizeof(GrPoint) != vertexSize) {
if (!geo.set(target, layout, vertexCount, 0)) {
GrPrintf("Failed to get space for vertices!");
@@ -984,9 +985,47 @@
if (NULL != indices) {
target->setIndexSourceToArray(indices, indexCount);
- target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ }
+
+ if (doOffscreenAA) {
+ // draw to the offscreen
+ if (NULL != indices) {
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+ // When there are custom texture coordinates we can't just draw
+ // a quad to sample the offscreen. Instead we redraw the geometry to
+ // specify the texture coords. This isn't quite right either, primitives
+ // will only be eroded at the edges, not expanded into partial pixels.
+ bool useRect = 0 == (layout & GrDrawTarget::StageTexCoordVertexLayoutBit(0,0));
+ if (useRect) {
+ target->setViewMatrix(GrMatrix::I());
+ }
+ this->setupOffscreenAAPass2(target, paint, &record);
+ if (useRect) {
+ geo.set(NULL, 0, 0, 0);
+ int stages = (NULL != paint.getTexture()) ? 0x1 : 0x0;
+ stages |= (1 << kOffscreenStage);
+ GrRect dstRect(0, 0,
+ target->getRenderTarget()->width(),
+ target->getRenderTarget()->height());
+ target->drawSimpleRect(dstRect, NULL, stages);
+ target->drawSimpleRect(dstRect, NULL, stages);
+ } else {
+ if (NULL != indices) {
+ target->drawIndexed (primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+ }
+ this->endOffscreenAA(target, &record);
} else {
- target->drawNonIndexed(primitiveType, 0, vertexCount);
+ if (NULL != indices) {
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
}
}
@@ -1010,8 +1049,9 @@
if (this->setupOffscreenAAPass1(target, needsStencil, &record)) {
pr->drawPath(target, 0, path, fill, translate);
+ target->setViewMatrix(GrMatrix::I());
this->setupOffscreenAAPass2(target, paint, &record);
-
+
int stages = (NULL != paint.getTexture()) ? 0x1 : 0x0;
stages |= (1 << kOffscreenStage);
GrRect dstRect(0, 0,
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index c33f15c..1ac02f2 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -494,12 +494,12 @@
// ...and there isn't a texture with an alpha channel...
for (int s = 0; s < kNumStages; ++s) {
- if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
+ if (this->isStageEnabled(s)) {
GrAssert(NULL != fCurrDrawState.fTextures[s]);
+
GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
- if (kRGB_565_GrPixelConfig != config &&
- kRGBX_8888_GrPixelConfig != config) {
+ if (!GrPixelConfigIsOpaque(config)) {
return false;
}
}
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 0ea83a8..4bdf10e 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -1704,75 +1704,70 @@
GrAssert(NULL != fCurrDrawState.fRenderTarget);
for (int s = 0; s < kNumStages; ++s) {
- bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
-
// bind texture and set sampler state
- if (usingTexture) {
+ if (this->isStageEnabled(s)) {
GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
- if (NULL != nextTexture) {
- // if we created a rt/tex and rendered to it without using a
- // texture and now we're texuring from the rt it will still be
- // the last bound texture, but it needs resolving. So keep this
- // out of the "last != next" check.
- GrGLRenderTarget* texRT =
- static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
- if (NULL != texRT) {
- resolveRenderTarget(texRT);
- }
-
- if (fHWDrawState.fTextures[s] != nextTexture) {
- setTextureUnit(s);
- GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
- #if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
- #endif
- //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
- fHWDrawState.fTextures[s] = nextTexture;
- }
-
- const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
- const GrGLTexture::TexParams& oldTexParams =
- nextTexture->getTexParams();
- GrGLTexture::TexParams newTexParams;
-
- newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
- GR_GL_NEAREST;
- newTexParams.fWrapS =
- GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
- newTexParams.fWrapT =
- GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
-
- if (newTexParams.fFilter != oldTexParams.fFilter) {
- setTextureUnit(s);
- GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MAG_FILTER,
- newTexParams.fFilter));
- GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MIN_FILTER,
- newTexParams.fFilter));
- }
- if (newTexParams.fWrapS != oldTexParams.fWrapS) {
- setTextureUnit(s);
- GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_S,
- newTexParams.fWrapS));
- }
- if (newTexParams.fWrapT != oldTexParams.fWrapT) {
- setTextureUnit(s);
- GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_T,
- newTexParams.fWrapT));
- }
- nextTexture->setTexParams(newTexParams);
-
- // The texture matrix has to compensate for texture width/height
- // and NPOT-embedded-in-POT
- fDirtyFlags.fTextureChangedMask |= (1 << s);
- } else {
- GrAssert(!"Rendering with texture vert flag set but no texture");
- return false;
+ // true for now, but maybe not with GrEffect.
+ GrAssert(NULL != nextTexture);
+ // if we created a rt/tex and rendered to it without using a
+ // texture and now we're texuring from the rt it will still be
+ // the last bound texture, but it needs resolving. So keep this
+ // out of the "last != next" check.
+ GrGLRenderTarget* texRT =
+ static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
+ if (NULL != texRT) {
+ resolveRenderTarget(texRT);
}
+
+ if (fHWDrawState.fTextures[s] != nextTexture) {
+ setTextureUnit(s);
+ GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
+ #if GR_COLLECT_STATS
+ ++fStats.fTextureChngCnt;
+ #endif
+ //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
+ fHWDrawState.fTextures[s] = nextTexture;
+ }
+
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+ const GrGLTexture::TexParams& oldTexParams =
+ nextTexture->getTexParams();
+ GrGLTexture::TexParams newTexParams;
+
+ newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
+ GR_GL_NEAREST;
+ newTexParams.fWrapS =
+ GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
+ newTexParams.fWrapT =
+ GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
+
+ if (newTexParams.fFilter != oldTexParams.fFilter) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MAG_FILTER,
+ newTexParams.fFilter));
+ GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MIN_FILTER,
+ newTexParams.fFilter));
+ }
+ if (newTexParams.fWrapS != oldTexParams.fWrapS) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_S,
+ newTexParams.fWrapS));
+ }
+ if (newTexParams.fWrapT != oldTexParams.fWrapT) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_T,
+ newTexParams.fWrapT));
+ }
+ nextTexture->setTexParams(newTexParams);
+
+ // The texture matrix has to compensate for texture width/height
+ // and NPOT-embedded-in-POT
+ fDirtyFlags.fTextureChangedMask |= (1 << s);
}
}
@@ -1822,7 +1817,7 @@
#if GR_DEBUG
// check for circular rendering
for (int s = 0; s < kNumStages; ++s) {
- GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
+ GrAssert(!this->isStageEnabled(s) ||
NULL == fCurrDrawState.fRenderTarget ||
NULL == fCurrDrawState.fTextures[s] ||
fCurrDrawState.fTextures[s]->asRenderTarget() !=
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 446949f..4440bcd 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -127,8 +127,7 @@
bool usingTextures[kNumStages];
for (int s = 0; s < kNumStages; ++s) {
- usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
-
+ usingTextures[s] = this->isStageEnabled(s);
if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
unimpl("Fixed pipe doesn't support radial/sweep gradients");
return false;
@@ -152,7 +151,7 @@
}
for (int s = 0; s < kNumStages; ++s) {
- bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
+ bool wasUsingTexture = StageWillBeUsed(s, fHWGeometryState.fVertexLayout, fHWDrawState);
if (usingTextures[s] != wasUsingTexture) {
setTextureUnit(s);
if (usingTextures[s]) {
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 66056c9..ff9f3a4 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -515,7 +515,7 @@
for (int s = 0; s < kNumStages; ++s) {
GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
- stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
+ stage.fEnabled = this->isStageEnabled(s);
if (stage.fEnabled) {
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index 851732e..ab8a4bb 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -1044,7 +1044,7 @@
for (int s = 0; s < kNumStages; ++s) {
StageDesc& stage = desc->fStages[s];
- stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
+ stage.fEnabled = this->isStageEnabled(s);
if (stage.fEnabled) {
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];