Add per-vertex coverage field, use in AA rects when alpha tweak is not valid, add relevant sample/gm
Review URL: http://codereview.appspot.com/5181044/ git-svn-id: http://skia.googlecode.com/svn/trunk@2440 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f12449b5d2
commit
a310826855
157
gm/aarectmodes.cpp
Normal file
157
gm/aarectmodes.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
static SkCanvas* create_canvas(int w, int h) {
|
||||
SkBitmap bm;
|
||||
bm.setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
bm.allocPixels();
|
||||
bm.eraseColor(0);
|
||||
return new SkCanvas(bm);
|
||||
}
|
||||
|
||||
static const SkBitmap& extract_bitmap(SkCanvas* canvas) {
|
||||
return canvas->getDevice()->accessBitmap(false);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
SkXfermode::Mode fMode;
|
||||
const char* fLabel;
|
||||
} gModes[] = {
|
||||
{ SkXfermode::kClear_Mode, "Clear" },
|
||||
{ SkXfermode::kSrc_Mode, "Src" },
|
||||
{ SkXfermode::kDst_Mode, "Dst" },
|
||||
{ SkXfermode::kSrcOver_Mode, "SrcOver" },
|
||||
{ SkXfermode::kDstOver_Mode, "DstOver" },
|
||||
{ SkXfermode::kSrcIn_Mode, "SrcIn" },
|
||||
{ SkXfermode::kDstIn_Mode, "DstIn" },
|
||||
{ SkXfermode::kSrcOut_Mode, "SrcOut" },
|
||||
{ SkXfermode::kDstOut_Mode, "DstOut" },
|
||||
{ SkXfermode::kSrcATop_Mode, "SrcATop" },
|
||||
{ SkXfermode::kDstATop_Mode, "DstATop" },
|
||||
{ SkXfermode::kXor_Mode, "Xor" },
|
||||
};
|
||||
|
||||
const int gWidth = 64;
|
||||
const int gHeight = 64;
|
||||
const SkScalar W = SkIntToScalar(gWidth);
|
||||
const SkScalar H = SkIntToScalar(gHeight);
|
||||
|
||||
static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode,
|
||||
SkAlpha a0, SkAlpha a1) {
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
SkRect r = SkRect::MakeWH(W, H);
|
||||
r.inset(W/10, H/10);
|
||||
|
||||
paint.setColor(SK_ColorBLUE);
|
||||
paint.setAlpha(a0);
|
||||
canvas->drawOval(r, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setAlpha(a1);
|
||||
paint.setXfermode(mode);
|
||||
|
||||
SkScalar offset = SK_Scalar1 / 3;
|
||||
SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
|
||||
H / 4 + offset,
|
||||
W / 2, H / 2);
|
||||
canvas->drawRect(rect, paint);
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
static SkShader* make_bg_shader() {
|
||||
SkBitmap bm;
|
||||
bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
|
||||
bm.allocPixels();
|
||||
*bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
|
||||
*bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
|
||||
0xCC, 0xCC);
|
||||
|
||||
SkShader* s = SkShader::CreateBitmapShader(bm,
|
||||
SkShader::kRepeat_TileMode,
|
||||
SkShader::kRepeat_TileMode);
|
||||
|
||||
SkMatrix m;
|
||||
m.setScale(SkIntToScalar(6), SkIntToScalar(6));
|
||||
s->setLocalMatrix(m);
|
||||
return s;
|
||||
}
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
class AARectModesGM : public GM {
|
||||
SkPaint fBGPaint;
|
||||
public:
|
||||
AARectModesGM () {
|
||||
fBGPaint.setShader(make_bg_shader())->unref();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual SkString onShortName() {
|
||||
return SkString("aarectmodes");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() { return make_isize(640, 480); }
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
|
||||
const SkRect bounds = SkRect::MakeWH(W, H);
|
||||
static const SkAlpha gAlphaValue[] = { 0xFF, 0x88, 0x88 };
|
||||
|
||||
canvas->translate(SkIntToScalar(4), SkIntToScalar(4));
|
||||
|
||||
for (int alpha = 0; alpha < 4; ++alpha) {
|
||||
canvas->save();
|
||||
canvas->save();
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); ++i) {
|
||||
if (6 == i) {
|
||||
canvas->restore();
|
||||
canvas->translate(W * 5, 0);
|
||||
canvas->save();
|
||||
}
|
||||
SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
|
||||
|
||||
canvas->drawRect(bounds, fBGPaint);
|
||||
canvas->saveLayer(&bounds, NULL);
|
||||
SkScalar dy = drawCell(canvas, mode,
|
||||
gAlphaValue[alpha & 1],
|
||||
gAlphaValue[alpha & 2]);
|
||||
canvas->restore();
|
||||
|
||||
canvas->translate(0, dy * 5 / 4);
|
||||
SkSafeUnref(mode);
|
||||
}
|
||||
canvas->restore();
|
||||
canvas->restore();
|
||||
canvas->translate(W * 5 / 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// disable pdf for now, since it crashes on mac
|
||||
virtual uint32_t onGetFlags() const { return kSkipPDF_Flag; }
|
||||
|
||||
private:
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static GM* MyFactory(void*) { return new AARectModesGM; }
|
||||
static GMRegistry reg(MyFactory);
|
||||
|
||||
}
|
||||
|
@ -563,13 +563,13 @@ private:
|
||||
GrContext(GrGpu* gpu);
|
||||
|
||||
void fillAARect(GrDrawTarget* target,
|
||||
const GrPaint& paint,
|
||||
const GrRect& devRect);
|
||||
const GrRect& devRect,
|
||||
bool useVertexCoverage);
|
||||
|
||||
void strokeAARect(GrDrawTarget* target,
|
||||
const GrPaint& paint,
|
||||
const GrRect& devRect,
|
||||
const GrVec& devStrokeSize);
|
||||
const GrVec& devStrokeSize,
|
||||
bool useVertexCoverage);
|
||||
|
||||
inline int aaFillRectIndexCount() const;
|
||||
GrIndexBuffer* aaFillRectIndexBuffer();
|
||||
|
@ -677,6 +677,7 @@ bool GrContext::doOffscreenAA(GrDrawTarget* target,
|
||||
return false;
|
||||
}
|
||||
if (disable_coverage_aa_for_blend(target)) {
|
||||
GrPrintf("Turning off AA to correctly apply blend.\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -937,18 +938,6 @@ static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
|
||||
verts[9] = verts[1];
|
||||
}
|
||||
|
||||
static GrColor getColorForMesh(const GrPaint& paint) {
|
||||
// FIXME: This was copied from SkGpuDevice, seems like
|
||||
// we should have already smeared a in caller if that
|
||||
// is what is desired.
|
||||
if (paint.hasTexture()) {
|
||||
unsigned a = GrColorUnpackA(paint.fColor);
|
||||
return GrColorPackRGBA(a, a, a, a);
|
||||
} else {
|
||||
return paint.fColor;
|
||||
}
|
||||
}
|
||||
|
||||
static void setInsetFan(GrPoint* pts, size_t stride,
|
||||
const GrRect& r, GrScalar dx, GrScalar dy) {
|
||||
pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
|
||||
@ -1019,11 +1008,26 @@ GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
|
||||
return fAAStrokeRectIndexBuffer;
|
||||
}
|
||||
|
||||
static GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
|
||||
bool useCoverage) {
|
||||
GrVertexLayout layout = 0;
|
||||
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
|
||||
if (NULL != target->getTexture(s)) {
|
||||
layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
|
||||
}
|
||||
}
|
||||
if (useCoverage) {
|
||||
layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
|
||||
} else {
|
||||
layout |= GrDrawTarget::kColor_VertexLayoutBit;
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
void GrContext::fillAARect(GrDrawTarget* target,
|
||||
const GrPaint& paint,
|
||||
const GrRect& devRect) {
|
||||
GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
|
||||
GrDrawTarget::kColor_VertexLayoutBit;
|
||||
const GrRect& devRect,
|
||||
bool useVertexCoverage) {
|
||||
GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
|
||||
|
||||
size_t vsize = GrDrawTarget::VertexSize(layout);
|
||||
|
||||
@ -1051,7 +1055,13 @@ void GrContext::fillAARect(GrDrawTarget* target,
|
||||
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
|
||||
}
|
||||
|
||||
GrColor innerColor = getColorForMesh(paint);
|
||||
GrColor innerColor;
|
||||
if (useVertexCoverage) {
|
||||
innerColor = GrColorPackRGBA(0,0,0,0xff);
|
||||
} else {
|
||||
innerColor = target->getColor();
|
||||
}
|
||||
|
||||
verts += 4 * vsize;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
|
||||
@ -1063,16 +1073,15 @@ void GrContext::fillAARect(GrDrawTarget* target,
|
||||
0, 8, this->aaFillRectIndexCount());
|
||||
}
|
||||
|
||||
void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
|
||||
const GrRect& devRect, const GrVec& devStrokeSize) {
|
||||
void GrContext::strokeAARect(GrDrawTarget* target,
|
||||
const GrRect& devRect,
|
||||
const GrVec& devStrokeSize,
|
||||
bool useVertexCoverage) {
|
||||
const GrScalar& dx = devStrokeSize.fX;
|
||||
const GrScalar& dy = devStrokeSize.fY;
|
||||
const GrScalar rx = GrMul(dx, GR_ScalarHalf);
|
||||
const GrScalar ry = GrMul(dy, GR_ScalarHalf);
|
||||
|
||||
GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
|
||||
GrDrawTarget::kColor_VertexLayoutBit;
|
||||
|
||||
GrScalar spare;
|
||||
{
|
||||
GrScalar w = devRect.width() - dx;
|
||||
@ -1083,10 +1092,10 @@ void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
|
||||
if (spare <= 0) {
|
||||
GrRect r(devRect);
|
||||
r.inset(-rx, -ry);
|
||||
fillAARect(target, paint, r);
|
||||
fillAARect(target, r, useVertexCoverage);
|
||||
return;
|
||||
}
|
||||
|
||||
GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
|
||||
size_t vsize = GrDrawTarget::VertexSize(layout);
|
||||
|
||||
GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
|
||||
@ -1117,7 +1126,12 @@ void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
|
||||
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
|
||||
}
|
||||
|
||||
GrColor innerColor = getColorForMesh(paint);
|
||||
GrColor innerColor;
|
||||
if (useVertexCoverage) {
|
||||
innerColor = GrColorPackRGBA(0,0,0,0xff);
|
||||
} else {
|
||||
innerColor = target->getColor();
|
||||
}
|
||||
verts += 4 * vsize;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
|
||||
@ -1146,7 +1160,8 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
|
||||
GrScalar width,
|
||||
const GrMatrix* matrix,
|
||||
GrMatrix* combinedMatrix,
|
||||
GrRect* devRect) {
|
||||
GrRect* devRect,
|
||||
bool* useVertexCoverage) {
|
||||
// we use a simple alpha ramp to do aa on axis-aligned rects
|
||||
// do AA with alpha ramp if the caller requested AA, the rect
|
||||
// will be axis-aligned,the render target is not
|
||||
@ -1156,8 +1171,22 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
|
||||
return false;
|
||||
}
|
||||
|
||||
// we are keeping around the "tweak the alpha" trick because
|
||||
// it is our only hope for the fixed-pipe implementation.
|
||||
// In a shader implementation we can give a separate coverage input
|
||||
*useVertexCoverage = false;
|
||||
if (!target->canTweakAlphaForCoverage()) {
|
||||
return false;
|
||||
if (target->getCaps().fSupportPerVertexCoverage) {
|
||||
if (disable_coverage_aa_for_blend(target)) {
|
||||
GrPrintf("Turning off AA to correctly apply blend.\n");
|
||||
return false;
|
||||
} else {
|
||||
*useVertexCoverage = true;
|
||||
}
|
||||
} else {
|
||||
GrPrintf("Rect AA dropped because no support for coverage.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (target->getRenderTarget()->isMultisampled()) {
|
||||
@ -1204,8 +1233,9 @@ void GrContext::drawRect(const GrPaint& paint,
|
||||
|
||||
GrRect devRect = rect;
|
||||
GrMatrix combinedMatrix;
|
||||
bool useVertexCoverage;
|
||||
bool doAA = apply_aa_to_rect(target, rect, width, matrix,
|
||||
&combinedMatrix, &devRect);
|
||||
&combinedMatrix, &devRect, &useVertexCoverage);
|
||||
|
||||
if (doAA) {
|
||||
GrDrawTarget::AutoViewMatrixRestore avm(target);
|
||||
@ -1225,9 +1255,9 @@ void GrContext::drawRect(const GrPaint& paint,
|
||||
} else {
|
||||
strokeSize.set(GR_Scalar1, GR_Scalar1);
|
||||
}
|
||||
strokeAARect(target, paint, devRect, strokeSize);
|
||||
strokeAARect(target, devRect, strokeSize, useVertexCoverage);
|
||||
} else {
|
||||
fillAARect(target, paint, devRect);
|
||||
fillAARect(target, devRect, useVertexCoverage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1406,12 +1436,11 @@ void GrContext::drawVertices(const GrPaint& paint,
|
||||
}
|
||||
int texOffsets[GrDrawTarget::kMaxTexCoords];
|
||||
int colorOffset;
|
||||
int edgeOffset;
|
||||
GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
|
||||
texOffsets,
|
||||
&colorOffset,
|
||||
&edgeOffset);
|
||||
GrAssert(-1 == edgeOffset);
|
||||
NULL,
|
||||
NULL);
|
||||
void* curVertex = geo.vertices();
|
||||
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
@ -1462,6 +1491,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
|
||||
// aa. If we have some future driver-mojo path AA that can do the right
|
||||
// thing WRT to the blend then we'll need some query on the PR.
|
||||
if (disable_coverage_aa_for_blend(target)) {
|
||||
GrPrintf("Turning off AA to correctly apply blend.\n");
|
||||
target->disableState(GrDrawTarget::kAntialias_StateBit);
|
||||
}
|
||||
|
||||
|
@ -88,12 +88,30 @@ size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
|
||||
if (vertexLayout & kColor_VertexLayoutBit) {
|
||||
size += sizeof(GrColor);
|
||||
}
|
||||
if (vertexLayout & kCoverage_VertexLayoutBit) {
|
||||
size += sizeof(GrColor);
|
||||
}
|
||||
if (vertexLayout & kEdge_VertexLayoutBit) {
|
||||
size += 4 * sizeof(GrScalar);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Functions for computing offsets of various components from the layout
|
||||
* bitfield.
|
||||
*
|
||||
* Order of vertex components:
|
||||
* Position
|
||||
* Tex Coord 0
|
||||
* ...
|
||||
* Tex Coord kMaxTexCoords-1
|
||||
* Color
|
||||
* Coverage
|
||||
*/
|
||||
|
||||
int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
|
||||
@ -121,7 +139,6 @@ int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout)
|
||||
int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
|
||||
// color is after the pos and tex coords
|
||||
if (vertexLayout & kColor_VertexLayoutBit) {
|
||||
int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
|
||||
sizeof(GrGpuTextVertex) :
|
||||
@ -131,6 +148,23 @@ int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
|
||||
if (vertexLayout & kCoverage_VertexLayoutBit) {
|
||||
int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
|
||||
sizeof(GrGpuTextVertex) :
|
||||
sizeof(GrPoint);
|
||||
|
||||
int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
|
||||
if (vertexLayout & kColor_VertexLayoutBit) {
|
||||
offset += sizeof(GrColor);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
|
||||
@ -143,21 +177,21 @@ int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
|
||||
if (vertexLayout & kColor_VertexLayoutBit) {
|
||||
offset += sizeof(GrColor);
|
||||
}
|
||||
if (vertexLayout & kCoverage_VertexLayoutBit) {
|
||||
offset += sizeof(GrColor);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
|
||||
int texCoordOffsetsByIdx[kMaxTexCoords],
|
||||
int* colorOffset,
|
||||
int* edgeOffset) {
|
||||
int texCoordOffsetsByIdx[kMaxTexCoords],
|
||||
int* colorOffset,
|
||||
int* coverageOffset,
|
||||
int* edgeOffset) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
|
||||
GrAssert(NULL != texCoordOffsetsByIdx);
|
||||
GrAssert(NULL != colorOffset);
|
||||
GrAssert(NULL != edgeOffset);
|
||||
|
||||
int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
|
||||
sizeof(GrGpuTextVertex) :
|
||||
sizeof(GrPoint);
|
||||
@ -165,23 +199,45 @@ int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
|
||||
|
||||
for (int t = 0; t < kMaxTexCoords; ++t) {
|
||||
if (tex_coord_idx_mask(t) & vertexLayout) {
|
||||
texCoordOffsetsByIdx[t] = size;
|
||||
if (NULL != texCoordOffsetsByIdx) {
|
||||
texCoordOffsetsByIdx[t] = size;
|
||||
}
|
||||
size += vecSize;
|
||||
} else {
|
||||
texCoordOffsetsByIdx[t] = -1;
|
||||
if (NULL != texCoordOffsetsByIdx) {
|
||||
texCoordOffsetsByIdx[t] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (kColor_VertexLayoutBit & vertexLayout) {
|
||||
*colorOffset = size;
|
||||
if (NULL != colorOffset) {
|
||||
*colorOffset = size;
|
||||
}
|
||||
size += sizeof(GrColor);
|
||||
} else {
|
||||
*colorOffset = -1;
|
||||
if (NULL != colorOffset) {
|
||||
*colorOffset = -1;
|
||||
}
|
||||
}
|
||||
if (kCoverage_VertexLayoutBit & vertexLayout) {
|
||||
if (NULL != coverageOffset) {
|
||||
*coverageOffset = size;
|
||||
}
|
||||
size += sizeof(GrColor);
|
||||
} else {
|
||||
if (NULL != coverageOffset) {
|
||||
*coverageOffset = -1;
|
||||
}
|
||||
}
|
||||
if (kEdge_VertexLayoutBit & vertexLayout) {
|
||||
*edgeOffset = size;
|
||||
if (NULL != edgeOffset) {
|
||||
*edgeOffset = size;
|
||||
}
|
||||
size += 4 * sizeof(GrScalar);
|
||||
} else {
|
||||
*edgeOffset = -1;
|
||||
if (NULL != edgeOffset) {
|
||||
*edgeOffset = -1;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@ -189,31 +245,35 @@ int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
|
||||
int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
|
||||
int texCoordOffsetsByStage[kNumStages],
|
||||
int* colorOffset,
|
||||
int* coverageOffset,
|
||||
int* edgeOffset) {
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
|
||||
GrAssert(NULL != texCoordOffsetsByStage);
|
||||
GrAssert(NULL != colorOffset);
|
||||
GrAssert(NULL != edgeOffset);
|
||||
|
||||
int texCoordOffsetsByIdx[kMaxTexCoords];
|
||||
int size = VertexSizeAndOffsetsByIdx(vertexLayout,
|
||||
texCoordOffsetsByIdx,
|
||||
(NULL == texCoordOffsetsByStage) ?
|
||||
NULL :
|
||||
texCoordOffsetsByIdx,
|
||||
colorOffset,
|
||||
coverageOffset,
|
||||
edgeOffset);
|
||||
for (int s = 0; s < kNumStages; ++s) {
|
||||
int tcIdx;
|
||||
if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
|
||||
texCoordOffsetsByStage[s] = 0;
|
||||
} else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
|
||||
texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
|
||||
} else {
|
||||
texCoordOffsetsByStage[s] = -1;
|
||||
if (NULL != texCoordOffsetsByStage) {
|
||||
for (int s = 0; s < kNumStages; ++s) {
|
||||
int tcIdx;
|
||||
if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
|
||||
texCoordOffsetsByStage[s] = 0;
|
||||
} else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
|
||||
texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
|
||||
} else {
|
||||
texCoordOffsetsByStage[s] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
|
||||
GrAssert(stage < kNumStages);
|
||||
GrAssert(check_layout(vertexLayout));
|
||||
@ -241,6 +301,8 @@ int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrDrawTarget::VertexLayoutUnitTest() {
|
||||
// not necessarily exhaustive
|
||||
static bool run;
|
||||
@ -286,9 +348,11 @@ void GrDrawTarget::VertexLayoutUnitTest() {
|
||||
}
|
||||
GrAssert(-1 == VertexEdgeOffset(tcMask));
|
||||
GrAssert(-1 == VertexColorOffset(tcMask));
|
||||
GrAssert(-1 == VertexCoverageOffset(tcMask));
|
||||
#if GR_DEBUG
|
||||
GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
|
||||
#endif
|
||||
GrAssert(-1 == VertexCoverageOffset(withColor));
|
||||
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
|
||||
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
|
||||
#if GR_DEBUG
|
||||
@ -303,6 +367,19 @@ void GrDrawTarget::VertexLayoutUnitTest() {
|
||||
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
|
||||
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
|
||||
GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
|
||||
#if GR_DEBUG
|
||||
GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
|
||||
#endif
|
||||
GrAssert(-1 == VertexColorOffset(withCoverage));
|
||||
GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
|
||||
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
|
||||
#if GR_DEBUG
|
||||
GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
|
||||
kColor_VertexLayoutBit;
|
||||
#endif
|
||||
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
|
||||
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
|
||||
GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
|
||||
}
|
||||
GrAssert(tex_coord_idx_mask(t) == tcMask);
|
||||
GrAssert(check_layout(tcMask));
|
||||
@ -310,10 +387,13 @@ void GrDrawTarget::VertexLayoutUnitTest() {
|
||||
int stageOffsets[kNumStages];
|
||||
int colorOffset;
|
||||
int edgeOffset;
|
||||
int coverageOffset;
|
||||
int size;
|
||||
size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset, &edgeOffset);
|
||||
size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset,
|
||||
&coverageOffset, &edgeOffset);
|
||||
GrAssert(2*sizeof(GrPoint) == size);
|
||||
GrAssert(-1 == colorOffset);
|
||||
GrAssert(-1 == coverageOffset);
|
||||
GrAssert(-1 == edgeOffset);
|
||||
for (int s = 0; s < kNumStages; ++s) {
|
||||
GrAssert(VertexUsesStage(s, tcMask));
|
||||
@ -765,8 +845,9 @@ bool GrDrawTarget::CanTweakAlphaForCoverage(GrBlendCoeff dstCoeff) {
|
||||
bool GrDrawTarget::CanDisableBlend(GrVertexLayout layout, const DrState& state) {
|
||||
// If we compute a coverage value (using edge AA or a coverage stage) then
|
||||
// we can't force blending off.
|
||||
if (state.fEdgeAANumEdges > 0 ||
|
||||
layout & kEdge_VertexLayoutBit) {
|
||||
if (state.fEdgeAANumEdges > 0 ||
|
||||
(layout & kEdge_VertexLayoutBit) ||
|
||||
(layout & kCoverage_VertexLayoutBit)) {
|
||||
return false;
|
||||
}
|
||||
for (int s = state.fFirstCoverageStage; s < kNumStages; ++s) {
|
||||
@ -910,14 +991,10 @@ void GrDrawTarget::SetRectVertices(const GrRect& rect,
|
||||
#endif
|
||||
|
||||
int stageOffsets[kNumStages];
|
||||
int colorOffset;
|
||||
int edgeOffset;
|
||||
int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
|
||||
&colorOffset, &edgeOffset);
|
||||
GrAssert(-1 == colorOffset);
|
||||
GrAssert(-1 == edgeOffset);
|
||||
int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
|
||||
GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
|
||||
rect.fRight, rect.fBottom,
|
||||
vsize);
|
||||
if (NULL != matrix) {
|
||||
@ -926,10 +1003,10 @@ void GrDrawTarget::SetRectVertices(const GrRect& rect,
|
||||
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
if (stageOffsets[i] > 0) {
|
||||
GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
|
||||
GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
|
||||
stageOffsets[i]);
|
||||
coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
|
||||
srcRects[i]->fRight, srcRects[i]->fBottom,
|
||||
srcRects[i]->fRight, srcRects[i]->fBottom,
|
||||
vsize);
|
||||
if (NULL != srcMatrices && NULL != srcMatrices[i]) {
|
||||
srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
bool fFSAASupport : 1;
|
||||
bool fDualSourceBlendingSupport : 1;
|
||||
bool fBufferLockSupport : 1;
|
||||
bool fSupportPerVertexCoverage : 1;
|
||||
int fMinRenderTargetWidth;
|
||||
int fMinRenderTargetHeight;
|
||||
int fMaxRenderTargetSize;
|
||||
@ -407,6 +408,12 @@ public:
|
||||
*/
|
||||
void setColor(GrColor);
|
||||
|
||||
/**
|
||||
* Gets the currently set color.
|
||||
* @return the current color.
|
||||
*/
|
||||
GrColor getColor() const { return fCurrDrawState.fColor; }
|
||||
|
||||
/**
|
||||
* Add a color filter that can be represented by a color and a mode.
|
||||
*/
|
||||
@ -516,77 +523,6 @@ public:
|
||||
*/
|
||||
GrColor getBlendConstant() const { return fCurrDrawState.fBlendConstant; }
|
||||
|
||||
/**
|
||||
* Used to save and restore the GrGpu's drawing state
|
||||
*/
|
||||
struct SavedDrawState {
|
||||
private:
|
||||
DrState fState;
|
||||
friend class GrDrawTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the current draw state. The state can be restored at a later time
|
||||
* with restoreDrawState.
|
||||
*
|
||||
* See also AutoStateRestore class.
|
||||
*
|
||||
* @param state will hold the state after the function returns.
|
||||
*/
|
||||
void saveCurrentDrawState(SavedDrawState* state) const;
|
||||
|
||||
/**
|
||||
* Restores previously saved draw state. The client guarantees that state
|
||||
* was previously passed to saveCurrentDrawState and that the rendertarget
|
||||
* and texture set at save are still valid.
|
||||
*
|
||||
* See also AutoStateRestore class.
|
||||
*
|
||||
* @param state the previously saved state to restore.
|
||||
*/
|
||||
void restoreDrawState(const SavedDrawState& state);
|
||||
|
||||
/**
|
||||
* Copies the draw state from another target to this target.
|
||||
*
|
||||
* @param srcTarget draw target used as src of the draw state.
|
||||
*/
|
||||
void copyDrawState(const GrDrawTarget& srcTarget);
|
||||
|
||||
/**
|
||||
* The format of vertices is represented as a bitfield of flags.
|
||||
* Flags that indicate the layout of vertex data. Vertices always contain
|
||||
* positions and may also contain up to kMaxTexCoords sets of 2D texture
|
||||
* coordinates and per-vertex colors. Each stage can use any of the texture
|
||||
* coordinates as its input texture coordinates or it may use the positions.
|
||||
*
|
||||
* If no texture coordinates are specified for a stage then the stage is
|
||||
* disabled.
|
||||
*
|
||||
* Only one type of texture coord can be specified per stage. For
|
||||
* example StageTexCoordVertexLayoutBit(0, 2) and
|
||||
* StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
|
||||
*
|
||||
* The order in memory is always (position, texture coord 0, ..., color)
|
||||
* with any unused fields omitted. Note that this means that if only texture
|
||||
* coordinates 1 is referenced then there is no texture coordinates 0 and
|
||||
* the order would be (position, texture coordinate 1[, color]).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates a bit indicating that a texture stage uses texture coordinates
|
||||
*
|
||||
* @param stage the stage that will use texture coordinates.
|
||||
* @param texCoordIdx the index of the texture coordinates to use
|
||||
*
|
||||
* @return the bit to add to a GrVertexLayout bitfield.
|
||||
*/
|
||||
static int StageTexCoordVertexLayoutBit(int stage, int texCoordIdx) {
|
||||
GrAssert(stage < kNumStages);
|
||||
GrAssert(texCoordIdx < kMaxTexCoords);
|
||||
return 1 << (stage + (texCoordIdx * kNumStages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if blend is effectively disabled.
|
||||
*
|
||||
@ -642,6 +578,79 @@ public:
|
||||
*/
|
||||
void setEdgeAAData(const Edge* edges, int numEdges);
|
||||
|
||||
/**
|
||||
* Used to save and restore the GrGpu's drawing state
|
||||
*/
|
||||
struct SavedDrawState {
|
||||
private:
|
||||
DrState fState;
|
||||
friend class GrDrawTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the current draw state. The state can be restored at a later time
|
||||
* with restoreDrawState.
|
||||
*
|
||||
* See also AutoStateRestore class.
|
||||
*
|
||||
* @param state will hold the state after the function returns.
|
||||
*/
|
||||
void saveCurrentDrawState(SavedDrawState* state) const;
|
||||
|
||||
/**
|
||||
* Restores previously saved draw state. The client guarantees that state
|
||||
* was previously passed to saveCurrentDrawState and that the rendertarget
|
||||
* and texture set at save are still valid.
|
||||
*
|
||||
* See also AutoStateRestore class.
|
||||
*
|
||||
* @param state the previously saved state to restore.
|
||||
*/
|
||||
void restoreDrawState(const SavedDrawState& state);
|
||||
|
||||
/**
|
||||
* Copies the draw state from another target to this target.
|
||||
*
|
||||
* @param srcTarget draw target used as src of the draw state.
|
||||
*/
|
||||
void copyDrawState(const GrDrawTarget& srcTarget);
|
||||
|
||||
/**
|
||||
* The format of vertices is represented as a bitfield of flags.
|
||||
* Flags that indicate the layout of vertex data. Vertices always contain
|
||||
* positions and may also contain up to kMaxTexCoords sets of 2D texture
|
||||
* coordinates, per-vertex colors, and per-vertex coverage. Each stage can
|
||||
* use any of the texture coordinates as its input texture coordinates or it
|
||||
* may use the positions as texture coordinates.
|
||||
*
|
||||
* If no texture coordinates are specified for a stage then the stage is
|
||||
* disabled.
|
||||
*
|
||||
* Only one type of texture coord can be specified per stage. For
|
||||
* example StageTexCoordVertexLayoutBit(0, 2) and
|
||||
* StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
|
||||
*
|
||||
* The order in memory is always (position, texture coord 0, ..., color,
|
||||
* coverage) with any unused fields omitted. Note that this means that if
|
||||
* only texture coordinates 1 is referenced then there is no texture
|
||||
* coordinates 0 and the order would be (position, texture coordinate 1
|
||||
* [, color][, coverage]).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates a bit indicating that a texture stage uses texture coordinates
|
||||
*
|
||||
* @param stage the stage that will use texture coordinates.
|
||||
* @param texCoordIdx the index of the texture coordinates to use
|
||||
*
|
||||
* @return the bit to add to a GrVertexLayout bitfield.
|
||||
*/
|
||||
static int StageTexCoordVertexLayoutBit(int stage, int texCoordIdx) {
|
||||
GrAssert(stage < kNumStages);
|
||||
GrAssert(texCoordIdx < kMaxTexCoords);
|
||||
return 1 << (stage + (texCoordIdx * kNumStages));
|
||||
}
|
||||
|
||||
private:
|
||||
static const int TEX_COORD_BIT_CNT = kNumStages*kMaxTexCoords;
|
||||
public:
|
||||
@ -658,6 +667,7 @@ public:
|
||||
GrAssert(stage < kNumStages);
|
||||
return (1 << (TEX_COORD_BIT_CNT + stage));
|
||||
}
|
||||
|
||||
private:
|
||||
static const int STAGE_BIT_CNT = TEX_COORD_BIT_CNT + kNumStages;
|
||||
|
||||
@ -667,14 +677,15 @@ public:
|
||||
* Additional Bits that can be specified in GrVertexLayout.
|
||||
*/
|
||||
enum VertexLayoutBits {
|
||||
/* vertices have colors */
|
||||
/* vertices have colors (GrColor) */
|
||||
kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0),
|
||||
|
||||
/* vertices have coverage (GrColor where only the alpha chan is used */
|
||||
kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
|
||||
/* Use text vertices. (Pos and tex coords may be a different type for
|
||||
text [GrGpuTextVertex vs GrPoint].) */
|
||||
kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
|
||||
kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2),
|
||||
|
||||
kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2),
|
||||
kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 3),
|
||||
// for below assert
|
||||
kDummyVertexLayoutBit,
|
||||
kHighVertexLayoutBit = kDummyVertexLayoutBit - 1
|
||||
@ -1121,6 +1132,13 @@ public:
|
||||
*/
|
||||
static int VertexColorOffset(GrVertexLayout vertexLayout);
|
||||
|
||||
/**
|
||||
* Helper function to compute the offset of the coverage in a vertex
|
||||
* @return offset of coverage in vertex layout or -1 if the
|
||||
* layout has no coverage.
|
||||
*/
|
||||
static int VertexCoverageOffset(GrVertexLayout vertexLayout);
|
||||
|
||||
/**
|
||||
* Helper function to compute the offset of the edge pts in a vertex
|
||||
* @return offset of edge in vertex layout or -1 if the
|
||||
@ -1162,12 +1180,24 @@ public:
|
||||
* @param vertexLayout the layout to query
|
||||
* @param texCoordOffsetsByIdx after return it is the offset of each
|
||||
* tex coord index in the vertex or -1 if
|
||||
* index isn't used.
|
||||
* index isn't used. (optional)
|
||||
* @param colorOffset after return it is the offset of the
|
||||
* color field in each vertex, or -1 if
|
||||
* there aren't per-vertex colors. (optional)
|
||||
* @param coverageOffset after return it is the offset of the
|
||||
* coverage field in each vertex, or -1 if
|
||||
* there aren't per-vertex coeverages.
|
||||
* (optional)
|
||||
* @param edgeOffset after return it is the offset of the
|
||||
* edge eq field in each vertex, or -1 if
|
||||
* there aren't per-vertex edge equations.
|
||||
* (optional)
|
||||
* @return size of a single vertex
|
||||
*/
|
||||
static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
|
||||
int texCoordOffsetsByIdx[kMaxTexCoords],
|
||||
int *colorOffset,
|
||||
int *coverageOffset,
|
||||
int* edgeOffset);
|
||||
|
||||
/**
|
||||
@ -1180,12 +1210,25 @@ public:
|
||||
* @param vertexLayout the layout to query
|
||||
* @param texCoordOffsetsByStage after return it is the offset of each
|
||||
* tex coord index in the vertex or -1 if
|
||||
* index isn't used.
|
||||
* index isn't used. (optional)
|
||||
* @param colorOffset after return it is the offset of the
|
||||
* color field in each vertex, or -1 if
|
||||
* there aren't per-vertex colors.
|
||||
* (optional)
|
||||
* @param coverageOffset after return it is the offset of the
|
||||
* coverage field in each vertex, or -1 if
|
||||
* there aren't per-vertex coeverages.
|
||||
* (optional)
|
||||
* @param edgeOffset after return it is the offset of the
|
||||
* edge eq field in each vertex, or -1 if
|
||||
* there aren't per-vertex edge equations.
|
||||
* (optional)
|
||||
* @return size of a single vertex
|
||||
*/
|
||||
static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
|
||||
int texCoordOffsetsByStage[kNumStages],
|
||||
int *colorOffset,
|
||||
int *coverageOffset,
|
||||
int* edgeOffset);
|
||||
|
||||
/**
|
||||
|
@ -81,6 +81,7 @@ struct ShaderCodeSegments {
|
||||
|
||||
#define POS_ATTR_NAME "aPosition"
|
||||
#define COL_ATTR_NAME "aColor"
|
||||
#define COV_ATTR_NAME "aCoverage"
|
||||
#define EDGE_ATTR_NAME "aEdge"
|
||||
#define COL_UNI_NAME "uColor"
|
||||
#define EDGES_UNI_NAME "uEdges"
|
||||
@ -751,6 +752,23 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
|
||||
// get edge AA coverage and use it as inCoverage to first coverage stage
|
||||
this->genEdgeCoverage(gl, layout, programData, &inCoverage, &segments);
|
||||
|
||||
// include explicit per-vertex coverage if we have it
|
||||
if (GrDrawTarget::kCoverage_VertexLayoutBit & layout) {
|
||||
segments.fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
|
||||
COV_ATTR_NAME);
|
||||
const char *vsName, *fsName;
|
||||
append_varying(GrGLShaderVar::kFloat_Type, "Coverage",
|
||||
&segments, &vsName, &fsName);
|
||||
segments.fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
|
||||
if (inCoverage.size()) {
|
||||
segments.fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
|
||||
fsName, inCoverage.c_str());
|
||||
inCoverage = "edgeAndAttrCov";
|
||||
} else {
|
||||
inCoverage = fsName;
|
||||
}
|
||||
}
|
||||
|
||||
GrStringBuilder outCoverage;
|
||||
const int& startStage = fProgramDesc.fFirstCoverageStage;
|
||||
for (int s = startStage; s < GrDrawTarget::kNumStages; ++s) {
|
||||
@ -1100,6 +1118,8 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(
|
||||
|
||||
GR_GL_CALL(gl, BindAttribLocation(progID, ColorAttributeIdx(),
|
||||
COL_ATTR_NAME));
|
||||
GR_GL_CALL(gl, BindAttribLocation(progID, CoverageAttributeIdx(),
|
||||
COV_ATTR_NAME));
|
||||
GR_GL_CALL(gl, BindAttribLocation(progID, EdgeAttributeIdx(),
|
||||
EDGE_ATTR_NAME));
|
||||
|
||||
|
@ -66,7 +66,10 @@ public:
|
||||
static int PositionAttributeIdx() { return 0; }
|
||||
static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
|
||||
static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; }
|
||||
static int EdgeAttributeIdx() { return 2 + GrDrawTarget::kMaxTexCoords; }
|
||||
static int CoverageAttributeIdx() {
|
||||
return 2 + GrDrawTarget::kMaxTexCoords;
|
||||
}
|
||||
static int EdgeAttributeIdx() { return 3 + GrDrawTarget::kMaxTexCoords; }
|
||||
|
||||
static int ViewMatrixAttributeIdx() {
|
||||
return 2 + GrDrawTarget::kMaxTexCoords;
|
||||
|
@ -272,23 +272,29 @@ void GrGpuGLFixed::setupGeometry(int* startVertex,
|
||||
int indexCount) {
|
||||
|
||||
int newColorOffset;
|
||||
int newCoverageOffset;
|
||||
int newTexCoordOffsets[kNumStages];
|
||||
int newEdgeOffset;
|
||||
|
||||
GrGLsizei newStride = VertexSizeAndOffsetsByStage(this->getGeomSrc().fVertexLayout,
|
||||
newTexCoordOffsets,
|
||||
&newColorOffset,
|
||||
&newCoverageOffset,
|
||||
&newEdgeOffset);
|
||||
GrAssert(-1 == newEdgeOffset); // not supported by fixed pipe
|
||||
GrAssert(-1 == newCoverageOffset); // not supported by fixed pipe
|
||||
|
||||
int oldColorOffset;
|
||||
int oldCoverageOffset;
|
||||
int oldTexCoordOffsets[kNumStages];
|
||||
int oldEdgeOffset;
|
||||
GrGLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
|
||||
oldTexCoordOffsets,
|
||||
&oldColorOffset,
|
||||
&oldCoverageOffset,
|
||||
&oldEdgeOffset);
|
||||
GrAssert(-1 == oldEdgeOffset);
|
||||
GrAssert(-1 == oldCoverageOffset);
|
||||
|
||||
bool indexed = NULL != startIndex;
|
||||
|
||||
|
@ -219,6 +219,10 @@ bool GrGpuGLShaders::programUnitTest() {
|
||||
idx = (int)(random.nextF() * (kNumStages+1));
|
||||
pdesc.fFirstCoverageStage = idx;
|
||||
|
||||
pdesc.fVertexLayout |= (random.nextF() > .5f) ?
|
||||
GrDrawTarget::kCoverage_VertexLayoutBit :
|
||||
0;
|
||||
|
||||
#if GR_GL_EXPERIMENTAL_GS
|
||||
pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport &&
|
||||
random.nextF() > .5f;
|
||||
@ -238,8 +242,8 @@ bool GrGpuGLShaders::programUnitTest() {
|
||||
}
|
||||
pdesc.fEdgeAANumEdges = 0;
|
||||
} else {
|
||||
pdesc.fEdgeAANumEdges = SkToS8(1 + random.nextF() *
|
||||
this->getMaxEdges());
|
||||
pdesc.fEdgeAANumEdges = static_cast<int>(1 + random.nextF() *
|
||||
this->getMaxEdges());
|
||||
pdesc.fEdgeAAConcave = random.nextF() > .5f;
|
||||
}
|
||||
} else {
|
||||
@ -312,6 +316,7 @@ GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
|
||||
|
||||
// Enable supported shader-releated caps
|
||||
fCaps.fShaderSupport = true;
|
||||
fCaps.fSupportPerVertexCoverage = true;
|
||||
if (kDesktop_GrGLBinding == this->glBinding()) {
|
||||
fCaps.fDualSourceBlendingSupport =
|
||||
this->glVersion() >= GR_GL_VER(3,3) ||
|
||||
@ -700,6 +705,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
|
||||
int indexCount) {
|
||||
|
||||
int newColorOffset;
|
||||
int newCoverageOffset;
|
||||
int newTexCoordOffsets[kMaxTexCoords];
|
||||
int newEdgeOffset;
|
||||
|
||||
@ -707,8 +713,10 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
|
||||
this->getGeomSrc().fVertexLayout,
|
||||
newTexCoordOffsets,
|
||||
&newColorOffset,
|
||||
&newCoverageOffset,
|
||||
&newEdgeOffset);
|
||||
int oldColorOffset;
|
||||
int oldCoverageOffset;
|
||||
int oldTexCoordOffsets[kMaxTexCoords];
|
||||
int oldEdgeOffset;
|
||||
|
||||
@ -716,6 +724,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
|
||||
fHWGeometryState.fVertexLayout,
|
||||
oldTexCoordOffsets,
|
||||
&oldColorOffset,
|
||||
&oldCoverageOffset,
|
||||
&oldEdgeOffset);
|
||||
bool indexed = NULL != startIndex;
|
||||
|
||||
@ -792,6 +801,23 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
|
||||
GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
|
||||
}
|
||||
|
||||
if (newCoverageOffset > 0) {
|
||||
// bind just alpha channel.
|
||||
GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset +
|
||||
GrColor_INDEX_A);
|
||||
int idx = GrGLProgram::CoverageAttributeIdx();
|
||||
if (oldCoverageOffset <= 0) {
|
||||
GL_CALL(EnableVertexAttribArray(idx));
|
||||
GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
|
||||
true, newStride, coverageOffset));
|
||||
} else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
|
||||
GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE,
|
||||
true, newStride, coverageOffset));
|
||||
}
|
||||
} else if (oldCoverageOffset > 0) {
|
||||
GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
|
||||
}
|
||||
|
||||
if (newEdgeOffset > 0) {
|
||||
GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
|
||||
int idx = GrGLProgram::EdgeAttributeIdx();
|
||||
@ -954,13 +980,30 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
|
||||
desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport;
|
||||
#endif
|
||||
|
||||
// use canonical value when coverage/color distinction won't affect
|
||||
// generated code to prevent duplicate programs.
|
||||
// we want to avoid generating programs with different "first cov stage"
|
||||
// values when they would compute the same result.
|
||||
// We set field in the desc to kNumStages when either there are no
|
||||
// coverage stages or the distinction between coverage and color is
|
||||
// immaterial.
|
||||
int firstCoverageStage = kNumStages;
|
||||
desc.fFirstCoverageStage = kNumStages;
|
||||
if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
|
||||
bool hasCoverage = fCurrDrawState.fFirstCoverageStage <= lastEnabledStage;
|
||||
if (hasCoverage) {
|
||||
firstCoverageStage = fCurrDrawState.fFirstCoverageStage;
|
||||
}
|
||||
|
||||
// other coverage inputs
|
||||
if (!hasCoverage) {
|
||||
hasCoverage =
|
||||
desc.fEdgeAANumEdges ||
|
||||
(desc.fVertexLayout & GrDrawTarget::kCoverage_VertexLayoutBit) ||
|
||||
(desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
|
||||
}
|
||||
|
||||
if (hasCoverage) {
|
||||
// color filter is applied between color/coverage computation
|
||||
if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
|
||||
desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
|
||||
desc.fFirstCoverageStage = firstCoverageStage;
|
||||
}
|
||||
|
||||
// We could consider cases where the final color is solid (0xff alpha)
|
||||
@ -972,17 +1015,17 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
|
||||
if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
|
||||
// write the coverage value to second color
|
||||
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
|
||||
desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
|
||||
desc.fFirstCoverageStage = firstCoverageStage;
|
||||
} else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
|
||||
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
||||
// cover
|
||||
desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
|
||||
desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
|
||||
desc.fFirstCoverageStage = firstCoverageStage;
|
||||
} else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
|
||||
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
||||
// cover
|
||||
desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
|
||||
desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
|
||||
desc.fFirstCoverageStage = firstCoverageStage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
'../samplecode/OverView.cpp',
|
||||
'../samplecode/Sample2PtRadial.cpp',
|
||||
'../samplecode/SampleAARects.cpp',
|
||||
'../samplecode/SampleAARectModes.cpp',
|
||||
'../samplecode/SampleAll.cpp',
|
||||
'../samplecode/SampleAnimator.cpp',
|
||||
'../samplecode/SampleApp.cpp',
|
||||
|
@ -9,6 +9,7 @@
|
||||
'target_name': 'gm',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'../gm/aarectmodes.cpp',
|
||||
'../gm/bitmapfilters.cpp',
|
||||
'../gm/bitmapscroll.cpp',
|
||||
'../gm/blurs.cpp',
|
||||
|
152
samplecode/SampleAARectModes.cpp
Normal file
152
samplecode/SampleAARectModes.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SampleCode.h"
|
||||
#include "SkView.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
static SkCanvas* create_canvas(int w, int h) {
|
||||
SkBitmap bm;
|
||||
bm.setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
bm.allocPixels();
|
||||
bm.eraseColor(0);
|
||||
return new SkCanvas(bm);
|
||||
}
|
||||
|
||||
static const SkBitmap& extract_bitmap(SkCanvas* canvas) {
|
||||
return canvas->getDevice()->accessBitmap(false);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
SkXfermode::Mode fMode;
|
||||
const char* fLabel;
|
||||
} gModes[] = {
|
||||
{ SkXfermode::kClear_Mode, "Clear" },
|
||||
{ SkXfermode::kSrc_Mode, "Src" },
|
||||
{ SkXfermode::kDst_Mode, "Dst" },
|
||||
{ SkXfermode::kSrcOver_Mode, "SrcOver" },
|
||||
{ SkXfermode::kDstOver_Mode, "DstOver" },
|
||||
{ SkXfermode::kSrcIn_Mode, "SrcIn" },
|
||||
{ SkXfermode::kDstIn_Mode, "DstIn" },
|
||||
{ SkXfermode::kSrcOut_Mode, "SrcOut" },
|
||||
{ SkXfermode::kDstOut_Mode, "DstOut" },
|
||||
{ SkXfermode::kSrcATop_Mode, "SrcATop" },
|
||||
{ SkXfermode::kDstATop_Mode, "DstATop" },
|
||||
{ SkXfermode::kXor_Mode, "Xor" },
|
||||
};
|
||||
|
||||
const int gWidth = 64;
|
||||
const int gHeight = 64;
|
||||
const SkScalar W = SkIntToScalar(gWidth);
|
||||
const SkScalar H = SkIntToScalar(gHeight);
|
||||
|
||||
static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode,
|
||||
SkAlpha a0, SkAlpha a1) {
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
SkRect r = SkRect::MakeWH(W, H);
|
||||
r.inset(W/10, H/10);
|
||||
|
||||
paint.setColor(SK_ColorBLUE);
|
||||
paint.setAlpha(a0);
|
||||
canvas->drawOval(r, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setAlpha(a1);
|
||||
paint.setXfermode(mode);
|
||||
|
||||
SkScalar offset = SK_Scalar1 / 3;
|
||||
SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
|
||||
H / 4 + offset,
|
||||
W / 2, H / 2);
|
||||
canvas->drawRect(rect, paint);
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
static SkShader* make_bg_shader() {
|
||||
SkBitmap bm;
|
||||
bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
|
||||
bm.allocPixels();
|
||||
*bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
|
||||
*bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
|
||||
0xCC, 0xCC);
|
||||
|
||||
SkShader* s = SkShader::CreateBitmapShader(bm,
|
||||
SkShader::kRepeat_TileMode,
|
||||
SkShader::kRepeat_TileMode);
|
||||
|
||||
SkMatrix m;
|
||||
m.setScale(SkIntToScalar(6), SkIntToScalar(6));
|
||||
s->setLocalMatrix(m);
|
||||
return s;
|
||||
}
|
||||
|
||||
class AARectsModesView : public SampleView {
|
||||
SkPaint fBGPaint;
|
||||
public:
|
||||
AARectsModesView () {
|
||||
fBGPaint.setShader(make_bg_shader())->unref();
|
||||
}
|
||||
|
||||
protected:
|
||||
// overrides from SkEventSink
|
||||
virtual bool onQuery(SkEvent* evt) {
|
||||
if (SampleCode::TitleQ(*evt)) {
|
||||
SampleCode::TitleR(evt, "AARectsModes");
|
||||
return true;
|
||||
}
|
||||
return this->INHERITED::onQuery(evt);
|
||||
}
|
||||
|
||||
virtual void onDrawContent(SkCanvas* canvas) {
|
||||
const SkRect bounds = SkRect::MakeWH(W, H);
|
||||
static const SkAlpha gAlphaValue[] = { 0xFF, 0x88, 0x88 };
|
||||
|
||||
canvas->translate(SkIntToScalar(4), SkIntToScalar(4));
|
||||
|
||||
for (int alpha = 0; alpha < 4; ++alpha) {
|
||||
canvas->save();
|
||||
canvas->save();
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); ++i) {
|
||||
if (6 == i) {
|
||||
canvas->restore();
|
||||
canvas->translate(W * 5, 0);
|
||||
canvas->save();
|
||||
}
|
||||
SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
|
||||
|
||||
canvas->drawRect(bounds, fBGPaint);
|
||||
canvas->saveLayer(&bounds, NULL);
|
||||
SkScalar dy = drawCell(canvas, mode,
|
||||
gAlphaValue[alpha & 1],
|
||||
gAlphaValue[alpha & 2]);
|
||||
canvas->restore();
|
||||
|
||||
canvas->translate(0, dy * 5 / 4);
|
||||
SkSafeUnref(mode);
|
||||
}
|
||||
canvas->restore();
|
||||
canvas->restore();
|
||||
canvas->translate(W * 5 / 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SampleView INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkView* MyFactory() { return new AARectsModesView; }
|
||||
static SkViewRegister reg(MyFactory);
|
||||
|
Loading…
Reference in New Issue
Block a user