Per-draw super sampling. Disabled, path only, 2x2 only
Review URL: http://codereview.appspot.com/4452048/
git-svn-id: http://skia.googlecode.com/svn/trunk@1186 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 52db9c3..8acb3dc 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -26,6 +26,8 @@
#include "GrBufferAllocPool.h"
#include "GrPathRenderer.h"
+#define ENABLE_SSAA 0
+
#define DEFER_TEXT_RENDERING 1
#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
@@ -105,7 +107,6 @@
////////////////////////////////////////////////////////////////////////////////
-
enum {
kNPOTBit = 0x1,
kFilterBit = 0x2,
@@ -415,6 +416,97 @@
////////////////////////////////////////////////////////////////////////////////
+struct GrContext::OffscreenRecord {
+ OffscreenRecord() { fEntry = NULL; }
+ ~OffscreenRecord() { GrAssert(NULL == fEntry); }
+
+ GrTextureEntry* fEntry;
+ GrDrawTarget::SavedDrawState fSavedState;
+};
+
+bool GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
+ bool requireStencil,
+ OffscreenRecord* record) {
+#if !ENABLE_SSAA
+ return false;
+#endif
+
+ GrAssert(NULL == record->fEntry);
+
+ int width = this->getRenderTarget()->width();
+ int height = this->getRenderTarget()->height();
+
+ GrTextureDesc desc;
+ desc.fAALevel = kNone_GrAALevel;
+ if (requireStencil) {
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ } else {
+ desc.fFlags = kRenderTarget_GrTextureFlagBit |
+ kNoStencil_GrTextureFlagBit;
+ }
+
+ desc.fWidth = 2 * width;
+ desc.fHeight = 2 * height;
+ desc.fFormat = kRGBA_8888_GrPixelConfig;
+
+ record->fEntry = this->lockKeylessTexture(desc);
+ if (NULL == record->fEntry) {
+ return false;
+ }
+ GrRenderTarget* offscreen = record->fEntry->texture()->asRenderTarget();
+ GrAssert(NULL != offscreen);
+
+ target->saveCurrentDrawState(&record->fSavedState);
+
+ GrPaint tempPaint;
+ tempPaint.reset();
+ SetPaint(tempPaint, target);
+ target->setRenderTarget(offscreen);
+
+ GrMatrix scaleM;
+ scaleM.setScale(2 * GR_Scalar1, 2 * GR_Scalar1);
+ target->postConcatViewMatrix(scaleM);
+
+ // clip gets applied in second pass
+ target->disableState(GrDrawTarget::kClip_StateBit);
+
+ target->clear(0x0);
+ return true;
+}
+
+void GrContext::setupOffscreenAAPass2(GrDrawTarget* target,
+ const GrPaint& paint,
+ OffscreenRecord* record) {
+
+ GrAssert(NULL != record->fEntry);
+ GrTexture* offscreen = record->fEntry->texture();
+ GrAssert(NULL != offscreen);
+
+ 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());
+
+ // use bilinear filtering to get downsample
+ GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
+ GrSamplerState::kClamp_WrapMode,
+ scaleM, true);
+ target->setSamplerState(kOffscreenStage, sampler);
+}
+
+void GrContext::endOffscreenAA(GrDrawTarget* target, OffscreenRecord* record) {
+ this->unlockTexture(record->fEntry);
+ record->fEntry = NULL;
+
+ target->restoreDrawState(record->fSavedState);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
/* create a triangle strip that strokes the specified triangle. There are 8
unique vertices, but we repreat the last 2 to close up. Alternatively we
could use an indices array, and then only send 8 verts, but not sure that
@@ -899,24 +991,45 @@
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
void GrContext::drawPath(const GrPaint& paint,
GrPathIter* path,
GrPathFill fill,
const GrPoint* translate) {
-
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+ GrPathRenderer* pr = this->getPathRenderer(target, path, fill);
+ if (paint.fAntiAlias &&
+ !this->getRenderTarget()->isMultisampled() &&
+ !pr->supportsAA()) {
+
+ OffscreenRecord record;
+ bool needsStencil = pr->requiresStencilPass(target, path, fill);
+ if (this->setupOffscreenAAPass1(target, needsStencil, &record)) {
+ pr->drawPath(target, 0, path, fill, translate);
+
+ this->setupOffscreenAAPass2(target, paint, &record);
+
+ 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);
+
+ this->endOffscreenAA(target, &record);
+ return;
+ }
+ }
GrDrawTarget::StageBitfield enabledStages = 0;
if (NULL != paint.getTexture()) {
enabledStages |= 1;
}
- GrPathRenderer* pr = getPathRenderer(target, path, fill);
+
pr->drawPath(target, enabledStages, path, fill, translate);
}
-
void GrContext::drawPath(const GrPaint& paint,
const GrPath& path,
GrPathFill fill,
@@ -1205,3 +1318,4 @@
return &fDefaultPathRenderer;
}
}
+