Rev the GrContext interface. Context has draw* functions that take a new GrPaint object. Removed many of the lower-level GrGpu function call-throughs on context.
Remove unused/unsupported point size (we don't draw non-hairline points using GL points).
Change current* getter functions to get* for consistency.
Fix bounds when drawing inverse-filled paths.
git-svn-id: http://skia.googlecode.com/svn/trunk@718 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index ee78848..5e6b824 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -138,17 +138,17 @@
GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
if (NULL != texture) {
- GrGpu::AutoStateRestore asr(fGpu);
+ GrDrawTarget::AutoStateRestore asr(fGpu);
fGpu->setRenderTarget(texture->asRenderTarget());
fGpu->setTexture(0, clampEntry->texture());
- fGpu->setStencilPass(GrGpu::kNone_StencilPass);
+ fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);
fGpu->setTextureMatrix(0, GrMatrix::I());
fGpu->setViewMatrix(GrMatrix::I());
fGpu->setAlpha(0xff);
- fGpu->setBlendFunc(GrGpu::kOne_BlendCoeff, GrGpu::kZero_BlendCoeff);
- fGpu->disableState(GrGpu::kDither_StateBit |
- GrGpu::kClip_StateBit |
- GrGpu::kAntialias_StateBit);
+ fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff, GrDrawTarget::kZero_BlendCoeff);
+ fGpu->disableState(GrDrawTarget::kDither_StateBit |
+ GrDrawTarget::kClip_StateBit |
+ GrDrawTarget::kAntialias_StateBit);
GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
sampler.isFilter());
@@ -171,7 +171,7 @@
clampTexture->contentHeight() /
clampTexture->allocHeight());
verts[1].setRectFan(0, 0, tw, th, 2*sizeof(GrPoint));
- fGpu->drawNonIndexed(GrGpu::kTriangleFan_PrimitiveType,
+ fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
0, 4);
entry = fTextureCache->createAndLock(*key, texture);
}
@@ -275,11 +275,24 @@
////////////////////////////////////////////////////////////////////////////////
+void GrContext::setClip(const GrClip& clip) {
+ fGpu->setClip(clip);
+ fGpu->enableState(GrDrawTarget::kClip_StateBit);
+}
+
+void GrContext::setClip(const GrIRect& rect) {
+ GrClip clip;
+ clip.setRect(rect);
+ fGpu->setClip(clip);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
void GrContext::eraseColor(GrColor color) {
fGpu->eraseColor(color);
}
-void GrContext::drawFull(bool useTexture) {
+void GrContext::drawPaint(const GrPaint& paint) {
// set rect to be big enough to fill the space, but not super-huge, so we
// don't overflow fixed-point implementations
GrRect r(fGpu->getClip().getBounds());
@@ -289,8 +302,7 @@
} else {
GrPrintf("---- fGpu->getViewInverse failed\n");
}
-
- this->fillRect(r, useTexture);
+ this->drawRect(paint, r);
}
/* create a triangle strip that strokes the specified triangle. There are 8
@@ -314,8 +326,11 @@
verts[9] = verts[1];
}
-void GrContext::drawRect(const GrRect& rect, bool useTexture, GrScalar width) {
- GrVertexLayout layout = useTexture ?
+void GrContext::drawRect(const GrPaint& paint,
+ const GrRect& rect,
+ GrScalar width) {
+
+ GrVertexLayout layout = (NULL != paint.getTexture()) ?
GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
0;
@@ -325,21 +340,21 @@
return;
}
- this->flushText();
+ this->prepareToDraw(paint);
int vertCount;
- GrGpu::PrimitiveType primType;
+ GrDrawTarget::PrimitiveType primType;
GrPoint* vertex = geo.positions();
if (width >= 0) {
if (width > 0) {
vertCount = 10;
- primType = GrGpu::kTriangleStrip_PrimitiveType;
+ primType = GrDrawTarget::kTriangleStrip_PrimitiveType;
setStrokeRectStrip(vertex, rect, width);
} else {
// hairline
vertCount = 5;
- primType = GrGpu::kLineStrip_PrimitiveType;
+ primType = GrDrawTarget::kLineStrip_PrimitiveType;
vertex[0].set(rect.fLeft, rect.fTop);
vertex[1].set(rect.fRight, rect.fTop);
vertex[2].set(rect.fRight, rect.fBottom);
@@ -348,13 +363,111 @@
}
} else {
vertCount = 4;
- primType = GrGpu::kTriangleFan_PrimitiveType;
+ primType = GrDrawTarget::kTriangleFan_PrimitiveType;
vertex->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
}
fGpu->drawNonIndexed(primType, 0, vertCount);
}
+void GrContext::drawRectToRect(const GrPaint& paint,
+ const GrRect& dstRect,
+ const GrRect& srcRect) {
+
+ if (NULL == paint.getTexture()) {
+ drawRect(paint, dstRect);
+ return;
+ }
+
+ GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+ static const int VCOUNT = 4;
+
+ GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
+ if (!geo.succeeded()) {
+ return;
+ }
+
+ this->prepareToDraw(paint);
+
+ GrPoint* vertex = (GrPoint*) geo.vertices();
+
+ vertex[0].setRectFan(dstRect.fLeft, dstRect.fTop,
+ dstRect.fRight, dstRect.fBottom,
+ 2 * sizeof(GrPoint));
+ vertex[1].setRectFan(srcRect.fLeft, srcRect.fTop,
+ srcRect.fRight, srcRect.fBottom,
+ 2 * sizeof(GrPoint));
+
+ fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);
+}
+
+void GrContext::drawVertices(const GrPaint& paint,
+ GrDrawTarget::PrimitiveType primitiveType,
+ int vertexCount,
+ const GrPoint positions[],
+ const GrPoint texCoords[],
+ const GrColor colors[],
+ const uint16_t indices[],
+ int indexCount) {
+ GrVertexLayout layout = 0;
+ bool interLeave = false;
+
+ GrDrawTarget::AutoReleaseGeometry geo;
+
+ this->prepareToDraw(paint);
+
+ if (NULL != paint.getTexture()) {
+ if (NULL == texCoords) {
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+ } else {
+ layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+ interLeave = true;
+ }
+ }
+
+ if (NULL != colors) {
+ layout |= GrDrawTarget::kColor_VertexLayoutBit;
+ }
+
+ static const GrVertexLayout interleaveMask =
+ (GrDrawTarget::StageTexCoordVertexLayoutBit(0,0) |
+ GrDrawTarget::kColor_VertexLayoutBit);
+ if (interleaveMask & layout) {
+ if (!geo.set(fGpu, layout, vertexCount, 0)) {
+ GrPrintf("Failed to get space for vertices!");
+ return;
+ }
+ int texOffsets[GrDrawTarget::kMaxTexCoords];
+ int colorOffset;
+ int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
+ texOffsets,
+ &colorOffset);
+ void* curVertex = geo.vertices();
+
+ for (int i = 0; i < vertexCount; ++i) {
+ *((GrPoint*)curVertex) = positions[i];
+
+ if (texOffsets[0] > 0) {
+ *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
+ }
+ if (colorOffset > 0) {
+ *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
+ }
+ curVertex = (void*)((intptr_t)curVertex + vsize);
+ }
+ } else {
+ fGpu->setVertexSourceToArray(positions, layout);
+ }
+
+ if (NULL != indices) {
+ fGpu->setIndexSourceToArray(indices);
+ fGpu->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ } else {
+ fGpu->drawNonIndexed(primitiveType, 0, vertexCount);
+ }
+}
+
+
////////////////////////////////////////////////////////////////////////////////
#define NEW_EVAL 1 // Use adaptive path tesselation
@@ -533,7 +646,6 @@
static inline bool single_pass_path(const GrPathIter& path,
GrContext::PathFills fill,
- bool useTex,
const GrGpu& gpu) {
#if STENCIL_OFF
return true;
@@ -554,16 +666,18 @@
#endif
}
-void GrContext::drawPath(GrPathIter* path, PathFills fill,
- bool useTexture, const GrPoint* translate) {
+void GrContext::drawPath(const GrPaint& paint,
+ GrPathIter* path,
+ PathFills fill,
+ const GrPoint* translate) {
- flushText();
- GrGpu::AutoStateRestore asr(fGpu);
+ this->prepareToDraw(paint);
+
+ GrDrawTarget::AutoStateRestore asr(fGpu);
#if NEW_EVAL
- GrMatrix viewM;
- fGpu->getViewMatrix(&viewM);
+ GrMatrix viewM = fGpu->getViewMatrix();
// In order to tesselate the path we get a bound on how much the matrix can
// stretch when mapping to screen coordinates.
GrScalar stretch = viewM.getMaxStretch();
@@ -594,7 +708,8 @@
#endif
tol);
GrVertexLayout layout = 0;
- if (useTexture) {
+
+ if (NULL != paint.getTexture()) {
layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
}
// add 4 to hold the bounding rect
@@ -609,20 +724,20 @@
path->rewind();
// TODO: use primitve restart if available rather than multiple draws
- GrGpu::PrimitiveType type;
+ GrDrawTarget::PrimitiveType type;
int passCount = 0;
- GrGpu::StencilPass passes[3];
+ GrDrawTarget::StencilPass passes[3];
bool reverse = false;
if (kHairLine_PathFill == fill) {
- type = GrGpu::kLineStrip_PrimitiveType;
+ type = GrDrawTarget::kLineStrip_PrimitiveType;
passCount = 1;
- passes[0] = GrGpu::kNone_StencilPass;
+ passes[0] = GrDrawTarget::kNone_StencilPass;
} else {
- type = GrGpu::kTriangleFan_PrimitiveType;
- if (single_pass_path(*path, fill, useTexture, *fGpu)) {
+ type = GrDrawTarget::kTriangleFan_PrimitiveType;
+ if (single_pass_path(*path, fill, *fGpu)) {
passCount = 1;
- passes[0] = GrGpu::kNone_StencilPass;
+ passes[0] = GrDrawTarget::kNone_StencilPass;
} else {
switch (fill) {
case kInverseEvenOdd_PathFill:
@@ -630,21 +745,21 @@
// fallthrough
case kEvenOdd_PathFill:
passCount = 2;
- passes[0] = GrGpu::kEvenOddStencil_StencilPass;
- passes[1] = GrGpu::kEvenOddColor_StencilPass;
+ passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;
+ passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;
break;
case kInverseWinding_PathFill:
reverse = true;
// fallthrough
case kWinding_PathFill:
- passes[0] = GrGpu::kWindingStencil1_StencilPass;
+ passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;
if (fGpu->supportsSingleStencilPassWinding()) {
- passes[1] = GrGpu::kWindingColor_StencilPass;
+ passes[1] = GrDrawTarget::kWindingColor_StencilPass;
passCount = 2;
} else {
- passes[1] = GrGpu::kWindingStencil2_StencilPass;
- passes[2] = GrGpu::kWindingColor_StencilPass;
+ passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;
+ passes[2] = GrDrawTarget::kWindingColor_StencilPass;
passCount = 3;
}
break;
@@ -752,11 +867,15 @@
if (useBounds) {
GrRect bounds;
if (reverse) {
- GrAssert(NULL != fGpu->currentRenderTarget());
+ GrAssert(NULL != fGpu->getRenderTarget());
// draw over the whole world.
bounds.setLTRB(0, 0,
- GrIntToScalar(fGpu->currentRenderTarget()->width()),
- GrIntToScalar(fGpu->currentRenderTarget()->height()));
+ GrIntToScalar(fGpu->getRenderTarget()->width()),
+ GrIntToScalar(fGpu->getRenderTarget()->height()));
+ GrMatrix vmi;
+ if (fGpu->getViewInverse(&vmi)) {
+ vmi.mapRect(&bounds);
+ }
} else {
bounds.setBounds((GrPoint*)base, vert - base);
}
@@ -766,10 +885,11 @@
for (int p = 0; p < passCount; ++p) {
fGpu->setStencilPass(passes[p]);
- if (useBounds && (GrGpu::kEvenOddColor_StencilPass == passes[p] ||
- GrGpu::kWindingColor_StencilPass == passes[p])) {
- fGpu->drawNonIndexed(GrGpu::kTriangleFan_PrimitiveType,
+ if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||
+ GrDrawTarget::kWindingColor_StencilPass == passes[p])) {
+ fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
maxPts, 4);
+
} else {
int baseVertex = 0;
for (int sp = 0; sp < subpathCnt; ++sp) {
@@ -782,6 +902,8 @@
}
}
+////////////////////////////////////////////////////////////////////////////////
+
void GrContext::flush(bool flushRenderTarget) {
flushText();
if (flushRenderTarget) {
@@ -803,6 +925,10 @@
void GrContext::writePixels(int left, int top, int width, int height,
GrTexture::PixelConfig config, const void* buffer,
size_t stride) {
+
+ // TODO: when underlying api has a direct way to do this we should use it
+ // (e.g. glDrawPixels on desktop GL).
+
const GrGpu::TextureDesc desc = {
0, GrGpu::kNone_AALevel, width, height, config
};
@@ -830,126 +956,72 @@
fGpu->setTexture(0, texture);
fGpu->setSamplerState(0, GrSamplerState::ClampNoFilter());
- this->fillRect(GrRect(0, 0, GrIntToScalar(width), GrIntToScalar(height)),
- true);
+ GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+ static const int VCOUNT = 4;
+
+ GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
+ if (!geo.succeeded()) {
+ return;
+ }
+ ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
+ fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);
+}
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
+ target->setTexture(0, paint.getTexture());
+ target->setTextureMatrix(0, paint.fTextureMatrix);
+ target->setSamplerState(0, paint.fSampler);
+ target->setColor(paint.fColor);
+
+ if (paint.fDither) {
+ target->enableState(GrDrawTarget::kDither_StateBit);
+ } else {
+ target->disableState(GrDrawTarget::kDither_StateBit);
+ }
+ if (paint.fAntiAlias) {
+ target->enableState(GrDrawTarget::kAntialias_StateBit);
+ } else {
+ target->disableState(GrDrawTarget::kAntialias_StateBit);
+ }
+ target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
+}
+
+void GrContext::prepareToDraw(const GrPaint& paint) {
+
+ flushText();
+ SetPaint(paint, fGpu);
}
////////////////////////////////////////////////////////////////////////////////
-
-/* -------------------------------------------------------
- * Mimicking the GrGpu interface for now
- * TODO: define appropriate higher-level API for context
- */
-
void GrContext::resetContext() {
fGpu->resetContext();
}
-GrVertexBuffer* GrContext::createVertexBuffer(uint32_t size, bool dynamic) {
- return fGpu->createVertexBuffer(size, dynamic);
-}
-
-GrIndexBuffer* GrContext::createIndexBuffer(uint32_t size, bool dynamic) {
- return fGpu->createIndexBuffer(size, dynamic);
-}
-
-void GrContext::setTexture(int stage, GrTexture* texture) {
- fGpu->setTexture(stage, texture);
-}
-
void GrContext::setRenderTarget(GrRenderTarget* target) {
flushText();
fGpu->setRenderTarget(target);
}
-GrRenderTarget* GrContext::currentRenderTarget() const {
- return fGpu->currentRenderTarget();
+GrRenderTarget* GrContext::getRenderTarget() {
+ return fGpu->getRenderTarget();
}
-void GrContext::setSamplerState(int stage, const GrSamplerState& samplerState) {
- fGpu->setSamplerState(stage, samplerState);
+const GrRenderTarget* GrContext::getRenderTarget() const {
+ return fGpu->getRenderTarget();
}
-void GrContext::setTextureMatrix(int stage, const GrMatrix& m) {
- fGpu->setTextureMatrix(stage, m);
+const GrMatrix& GrContext::getMatrix() const {
+ return fGpu->getViewMatrix();
}
-void GrContext::getViewMatrix(GrMatrix* m) const {
- fGpu->getViewMatrix(m);
-}
-
-void GrContext::setViewMatrix(const GrMatrix& m) {
+void GrContext::setMatrix(const GrMatrix& m) {
fGpu->setViewMatrix(m);
}
-bool GrContext::reserveAndLockGeometry(GrVertexLayout vertexLayout,
- uint32_t vertexCount,
- uint32_t indexCount,
- void** vertices,
- void** indices) {
- return fGpu->reserveAndLockGeometry(vertexLayout,
- vertexCount,
- indexCount,
- vertices,
- indices);
-}
-
-void GrContext::drawIndexed(GrGpu::PrimitiveType type,
- uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
- flushText();
- fGpu->drawIndexed(type,
- startVertex,
- startIndex,
- vertexCount,
- indexCount);
-}
-
-void GrContext::drawNonIndexed(GrGpu::PrimitiveType type,
- uint32_t startVertex,
- uint32_t vertexCount) {
- flushText();
- fGpu->drawNonIndexed(type,
- startVertex,
- vertexCount);
-}
-
-void GrContext::setVertexSourceToArray(const void* array,
- GrVertexLayout vertexLayout) {
- fGpu->setVertexSourceToArray(array, vertexLayout);
-}
-
-void GrContext::setIndexSourceToArray(const void* array) {
- fGpu->setIndexSourceToArray(array);
-}
-
-void GrContext::setVertexSourceToBuffer(GrVertexBuffer* buffer,
- GrVertexLayout vertexLayout) {
- fGpu->setVertexSourceToBuffer(buffer, vertexLayout);
-}
-
-void GrContext::setIndexSourceToBuffer(GrIndexBuffer* buffer) {
- fGpu->setIndexSourceToBuffer(buffer);
-}
-
-void GrContext::releaseReservedGeometry() {
- fGpu->releaseReservedGeometry();
-}
-
-void GrContext::setClip(const GrClip& clip) {
- fGpu->setClip(clip);
- fGpu->enableState(GrDrawTarget::kClip_StateBit);
-}
-
-void GrContext::setAlpha(uint8_t alpha) {
- fGpu->setAlpha(alpha);
-}
-
-void GrContext::setColor(GrColor color) {
- fGpu->setColor(color);
+void GrContext::concatMatrix(const GrMatrix& m) const {
+ fGpu->concatViewMatrix(m);
}
static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
@@ -962,34 +1034,6 @@
return bits;
}
-void GrContext::setAntiAlias(bool aa) {
- if (aa) {
- fGpu->enableState(GrGpu::kAntialias_StateBit);
- } else {
- fGpu->disableState(GrGpu::kAntialias_StateBit);
- }
-}
-
-void GrContext::setDither(bool dither) {
- // hack for now, since iPad dither is hella-slow
- dither = false;
-
- if (dither) {
- fGpu->enableState(GrGpu::kDither_StateBit);
- } else {
- fGpu->disableState(GrGpu::kDither_StateBit);
- }
-}
-
-void GrContext::setPointSize(float size) {
- fGpu->setPointSize(size);
-}
-
-void GrContext::setBlendFunc(GrGpu::BlendCoeff srcCoef,
- GrGpu::BlendCoeff dstCoef) {
- fGpu->setBlendFunc(srcCoef, dstCoef);
-}
-
void GrContext::resetStats() {
fGpu->resetStats();
}
@@ -1031,13 +1075,16 @@
return 0 != bits;
}
-GrDrawTarget* GrContext::getTextTarget() {
+GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
+ GrDrawTarget* target;
#if DEFER_TEXT_RENDERING
fTextDrawBuffer.initializeDrawStateAndClip(*fGpu);
- return &fTextDrawBuffer;
+ target = &fTextDrawBuffer;
#else
- return fGpu;
+ target = fGpu;
#endif
+ SetPaint(paint, target);
+ return target;
}
const GrIndexBuffer* GrContext::quadIndexBuffer() const {
@@ -1050,4 +1097,3 @@
-