aboutsummaryrefslogtreecommitdiffstats
path: root/gpu/src
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/src')
-rw-r--r--gpu/src/GrAtlas.cpp6
-rw-r--r--gpu/src/GrBufferAllocPool.cpp8
-rw-r--r--gpu/src/GrClip.cpp18
-rw-r--r--gpu/src/GrContext.cpp726
-rw-r--r--gpu/src/GrDrawTarget.cpp56
-rw-r--r--gpu/src/GrGLEffect.h12
-rw-r--r--gpu/src/GrGLInterface.cpp243
-rw-r--r--gpu/src/GrGLProgram.cpp837
-rw-r--r--gpu/src/GrGLProgram.h107
-rw-r--r--gpu/src/GrGLTexture.cpp1
-rw-r--r--gpu/src/GrGLUtil.cpp9
-rw-r--r--gpu/src/GrGpu.cpp22
-rw-r--r--gpu/src/GrGpuFactory.cpp31
-rw-r--r--gpu/src/GrGpuGL.cpp239
-rw-r--r--gpu/src/GrGpuGL.h16
-rw-r--r--gpu/src/GrGpuGLFixed.cpp24
-rw-r--r--gpu/src/GrGpuGLShaders.cpp559
-rw-r--r--gpu/src/GrGpuGLShaders.h9
-rw-r--r--gpu/src/GrGpuGLShaders2.cpp1416
-rw-r--r--gpu/src/GrGpuGLShaders2.h102
-rw-r--r--gpu/src/GrInOrderDrawBuffer.cpp53
-rw-r--r--gpu/src/GrMatrix.cpp59
-rw-r--r--gpu/src/GrPath.cpp51
-rw-r--r--gpu/src/GrPathUtils.cpp18
-rw-r--r--gpu/src/GrPathUtils.h3
-rw-r--r--gpu/src/GrStencil.cpp2
-rw-r--r--gpu/src/GrTesselatedPathRenderer.cpp113
-rw-r--r--gpu/src/GrTextContext.cpp9
-rw-r--r--gpu/src/GrTexture.cpp25
-rw-r--r--gpu/src/gr_files.mk1
-rw-r--r--gpu/src/gr_unittests.cpp1
-rw-r--r--gpu/src/mac/GrGLDefaultInterface_mac.cpp21
-rw-r--r--gpu/src/unix/GrGLDefaultInterface_unix.cpp183
-rw-r--r--gpu/src/win/GrGLDefaultInterface_win.cpp21
34 files changed, 2608 insertions, 2393 deletions
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index dfc0a69..e577beb 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -175,9 +175,9 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
GrAssert(0 == kA8_GrMaskFormat);
GrAssert(1 == kA565_GrMaskFormat);
if (NULL == fTexture[format]) {
- GrGpu::TextureDesc desc = {
- GrGpu::kDynamicUpdate_TextureFlag,
- GrGpu::kNone_AALevel,
+ GrTextureDesc desc = {
+ kDynamicUpdate_GrTextureFlagBit,
+ kNone_GrAALevel,
GR_ATLAS_TEXTURE_WIDTH,
GR_ATLAS_TEXTURE_HEIGHT,
maskformat2pixelconfig(format)
diff --git a/gpu/src/GrBufferAllocPool.cpp b/gpu/src/GrBufferAllocPool.cpp
index 0db12fe..d786b02 100644
--- a/gpu/src/GrBufferAllocPool.cpp
+++ b/gpu/src/GrBufferAllocPool.cpp
@@ -346,8 +346,8 @@ void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
GrAssert(NULL != startVertex);
size_t vSize = GrDrawTarget::VertexSize(layout);
- size_t offset;
- const GrGeometryBuffer* geomBuffer;
+ size_t offset = 0; // assign to suppress warning
+ const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
void* ptr = INHERITED::makeSpace(vSize * vertexCount,
vSize,
&geomBuffer,
@@ -405,8 +405,8 @@ void* GrIndexBufferAllocPool::makeSpace(int indexCount,
GrAssert(NULL != buffer);
GrAssert(NULL != startIndex);
- size_t offset;
- const GrGeometryBuffer* geomBuffer;
+ size_t offset = 0; // assign to suppress warning
+ const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
sizeof(uint16_t),
&geomBuffer,
diff --git a/gpu/src/GrClip.cpp b/gpu/src/GrClip.cpp
index e8da3d1..2d1680c 100644
--- a/gpu/src/GrClip.cpp
+++ b/gpu/src/GrClip.cpp
@@ -18,29 +18,29 @@
#include "GrClip.h"
GrClip::GrClip()
- : fList(fListMemory, kPreAllocElements) {
+ : fList(&fListStorage) {
fConservativeBounds.setEmpty();
fConservativeBoundsValid = true;
}
GrClip::GrClip(const GrClip& src)
- : fList(fListMemory, kPreAllocElements) {
+ : fList(&fListStorage) {
*this = src;
}
GrClip::GrClip(const GrIRect& rect)
- : fList(fListMemory, kPreAllocElements) {
+ : fList(&fListStorage) {
this->setFromIRect(rect);
}
GrClip::GrClip(const GrRect& rect)
- : fList(fListMemory, kPreAllocElements) {
+ : fList(&fListStorage) {
this->setFromRect(rect);
}
GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
const GrRect* bounds)
- : fList(fListMemory, kPreAllocElements) {
+ : fList(&fListStorage) {
this->setFromIterator(iter, tx, ty, bounds);
}
@@ -87,6 +87,12 @@ void GrClip::setFromIRect(const GrIRect& r) {
}
}
+static void intersectWith(SkRect* dst, const SkRect& src) {
+ if (!dst->intersect(src)) {
+ dst->setEmpty();
+ }
+}
+
void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
const GrRect* conservativeBounds) {
fList.reset();
@@ -118,7 +124,7 @@ void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
rectCount = 1;
fList.pop_back();
GrAssert(kRect_ClipType == fList.back().fType);
- fList.back().fRect.intersectWith(e.fRect);
+ intersectWith(&fList.back().fRect, e.fRect);
}
} else {
isectRectValid = false;
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 8017f73..8cb932b 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -15,7 +15,7 @@
*/
#include "GrContext.h"
-#include "GrTypes.h"
+#include "GrGpu.h"
#include "GrTextureCache.h"
#include "GrTextStrike.h"
#include "GrMemory.h"
@@ -26,6 +26,8 @@
#include "GrBufferAllocPool.h"
#include "GrPathRenderer.h"
+#define ENABLE_OFFSCREEN_AA 0
+
#define DEFER_TEXT_RENDERING 1
#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
@@ -41,8 +43,8 @@ static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
-GrContext* GrContext::Create(GrGpu::Engine engine,
- GrGpu::Platform3DContext context3D) {
+GrContext* GrContext::Create(GrEngine engine,
+ GrPlatform3DContext context3D) {
GrContext* ctx = NULL;
GrGpu* fGpu = GrGpu::Create(engine, context3D);
if (NULL != fGpu) {
@@ -53,34 +55,43 @@ GrContext* GrContext::Create(GrGpu::Engine engine,
}
GrContext* GrContext::CreateGLShaderContext() {
- return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
+ return GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
}
GrContext::~GrContext() {
this->flush();
- fGpu->unref();
delete fTextureCache;
delete fFontCache;
delete fDrawBuffer;
delete fDrawBufferVBAllocPool;
delete fDrawBufferIBAllocPool;
GrSafeUnref(fCustomPathRenderer);
+ GrSafeUnref(fAAFillRectIndexBuffer);
+ GrSafeUnref(fAAStrokeRectIndexBuffer);
+ fGpu->unref();
}
void GrContext::contextLost() {
+ // abandon first to so destructors
+ // don't try to free the resources in the API.
+ fGpu->abandonResources();
+
delete fDrawBuffer;
fDrawBuffer = NULL;
+
delete fDrawBufferVBAllocPool;
fDrawBufferVBAllocPool = NULL;
+
delete fDrawBufferIBAllocPool;
fDrawBufferIBAllocPool = NULL;
+ GrSafeSetNull(fAAFillRectIndexBuffer);
+ GrSafeSetNull(fAAStrokeRectIndexBuffer);
+
fTextureCache->removeAll();
fFontCache->freeAll();
fGpu->markContextDirty();
- fGpu->abandonResources();
-
this->setupDrawBuffer();
}
@@ -94,9 +105,45 @@ void GrContext::freeGpuResources() {
fFontCache->freeAll();
}
+////////////////////////////////////////////////////////////////////////////////
+
+enum {
+ kNPOTBit = 0x1,
+ kFilterBit = 0x2,
+ kKeylessBit = 0x4,
+};
+
+bool GrContext::finalizeTextureKey(GrTextureKey* key,
+ const GrSamplerState& sampler,
+ bool keyless) const {
+ uint32_t bits = 0;
+ uint16_t width = key->width();
+ uint16_t height = key->height();
+
+ if (!fGpu->npotTextureTileSupport()) {
+ bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+
+ bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
+ (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
+
+ if (tiled && !isPow2) {
+ bits |= kNPOTBit;
+ if (GrSamplerState::kNearest_Filter != sampler.getFilter()) {
+ bits |= kFilterBit;
+ }
+ }
+ }
+
+ if (keyless) {
+ bits |= kKeylessBit;
+ }
+ key->finalize(bits);
+ return 0 != bits;
+}
+
GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
const GrSamplerState& sampler) {
- finalizeTextureKey(key, sampler);
+ finalizeTextureKey(key, sampler, false);
return fTextureCache->findAndLock(*key);
}
@@ -129,7 +176,7 @@ static void stretchImage(void* dst,
GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
const GrSamplerState& sampler,
- const GrGpu::TextureDesc& desc,
+ const GrTextureDesc& desc,
void* srcData, size_t rowBytes) {
GrAssert(key->width() == desc.fWidth);
GrAssert(key->height() == desc.fHeight);
@@ -139,7 +186,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
#endif
GrTextureEntry* entry = NULL;
- bool special = finalizeTextureKey(key, sampler);
+ bool special = finalizeTextureKey(key, sampler, false);
if (special) {
GrTextureEntry* clampEntry;
GrTextureKey clampKey(*key);
@@ -154,9 +201,10 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
return NULL;
}
}
- GrGpu::TextureDesc rtDesc = desc;
- rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
- GrGpu::kNoStencil_TextureFlag;
+ GrTextureDesc rtDesc = desc;
+ rtDesc.fFlags = rtDesc.fFlags |
+ kRenderTarget_GrTextureFlagBit |
+ kNoStencil_GrTextureFlagBit;
rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
fGpu->minRenderTargetWidth()));
rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
@@ -175,9 +223,18 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
fGpu->disableState(GrDrawTarget::kDither_StateBit |
GrDrawTarget::kClip_StateBit |
GrDrawTarget::kAntialias_StateBit);
+ GrSamplerState::Filter filter;
+ // if filtering is not desired then we want to ensure all
+ // texels in the resampled image are copies of texels from
+ // the original.
+ if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
+ filter = GrSamplerState::kNearest_Filter;
+ } else {
+ filter = GrSamplerState::kBilinear_Filter;
+ }
GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
- sampler.isFilter());
+ filter);
fGpu->setSamplerState(0, stretchSampler);
static const GrVertexLayout layout =
@@ -202,7 +259,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
// not. Either implement filtered stretch blit on CPU or just create
// one when FBO case fails.
- rtDesc.fFlags = 0;
+ rtDesc.fFlags = kNone_GrTextureFlags;
// no longer need to clamp at min RT size.
rtDesc.fWidth = GrNextPow2(desc.fWidth);
rtDesc.fHeight = GrNextPow2(desc.fHeight);
@@ -234,19 +291,37 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
return entry;
}
-void GrContext::unlockTexture(GrTextureEntry* entry) {
- fTextureCache->unlock(entry);
-}
-
-void GrContext::detachCachedTexture(GrTextureEntry* entry) {
- fTextureCache->detach(entry);
+GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc) {
+ uint32_t p0 = desc.fFormat;
+ uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
+ GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
+ this->finalizeTextureKey(&key, GrSamplerState::ClampNoFilter(), true);
+
+ GrTextureEntry* entry = fTextureCache->findAndLock(key);
+ if (NULL == entry) {
+ GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
+ if (NULL != texture) {
+ entry = fTextureCache->createAndLock(key, texture);
+ }
+ }
+ // If the caller gives us the same desc/sampler twice we don't want
+ // to return the same texture the second time (unless it was previously
+ // released). So we detach the entry from the cache and reattach at release.
+ if (NULL != entry) {
+ fTextureCache->detach(entry);
+ }
+ return entry;
}
-void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
- fTextureCache->reattachAndUnlock(entry);
+void GrContext::unlockTexture(GrTextureEntry* entry) {
+ if (kKeylessBit & entry->key().getPrivateBits()) {
+ fTextureCache->reattachAndUnlock(entry);
+ } else {
+ fTextureCache->unlock(entry);
+ }
}
-GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
+GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
void* srcData,
size_t rowBytes) {
return fGpu->createTexture(desc, srcData, rowBytes);
@@ -285,6 +360,25 @@ GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc)
return fGpu->createPlatformSurface(desc);
}
+GrRenderTarget* GrContext::createPlatformRenderTarget(intptr_t platformRenderTarget,
+ int stencilBits,
+ bool isMultisampled,
+ int width, int height) {
+#if GR_DEBUG
+ GrPrintf("Using deprecated createPlatformRenderTarget API.");
+#endif
+ return fGpu->createPlatformRenderTarget(platformRenderTarget,
+ stencilBits, isMultisampled,
+ width, height);
+}
+
+GrRenderTarget* GrContext::createRenderTargetFrom3DApiState() {
+#if GR_DEBUG
+ GrPrintf("Using deprecated createRenderTargetFrom3DApiState API.");
+#endif
+ return fGpu->createRenderTargetFrom3DApiState();
+}
+
///////////////////////////////////////////////////////////////////////////////
bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
@@ -312,6 +406,8 @@ bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
////////////////////////////////////////////////////////////////////////////////
+const GrClip& GrContext::getClip() const { return fGpu->getClip(); }
+
void GrContext::setClip(const GrClip& clip) {
fGpu->setClip(clip);
fGpu->enableState(GrDrawTarget::kClip_StateBit);
@@ -325,8 +421,9 @@ void GrContext::setClip(const GrIRect& rect) {
////////////////////////////////////////////////////////////////////////////////
-void GrContext::eraseColor(GrColor color) {
- fGpu->eraseColor(color);
+void GrContext::clear(const GrIRect* rect, const GrColor color) {
+ this->flush();
+ fGpu->clear(rect, color);
}
void GrContext::drawPaint(const GrPaint& paint) {
@@ -345,14 +442,212 @@ void GrContext::drawPaint(const GrPaint& paint) {
this->drawRect(paint, r);
}
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrContext::doOffscreenAA(GrDrawTarget* target,
+ const GrPaint& paint,
+ bool isLines) const {
+#if !ENABLE_OFFSCREEN_AA
+ return false;
+#else
+ if (!paint.fAntiAlias) {
+ return false;
+ }
+ if (isLines && fGpu->supportsAALines()) {
+ return false;
+ }
+ if (target->getRenderTarget()->isMultisampled()) {
+ return false;
+ }
+ // we have to be sure that the blend equation is expressible
+ // as simple src / dst coeffecients when the source
+ // is already modulated by the coverage fraction.
+ // We could use dual-source blending to get the correct per-pixel
+ // dst coeffecient for the remaining cases.
+ if (kISC_BlendCoeff != paint.fDstBlendCoeff &&
+ kOne_BlendCoeff != paint.fDstBlendCoeff &&
+ kISA_BlendCoeff != paint.fDstBlendCoeff) {
+ return false;
+ }
+ return true;
+#endif
+}
+
+bool GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
+ bool requireStencil,
+ const GrIRect& boundRect,
+ OffscreenRecord* record) {
+ GrAssert(ENABLE_OFFSCREEN_AA);
+
+ GrAssert(NULL == record->fEntry0);
+ GrAssert(NULL == record->fEntry1);
+
+ int boundW = boundRect.width();
+ int boundH = boundRect.height();
+ int size = GrMax(64, (int)GrNextPow2(GrMax(boundW, boundH)));
+
+ GrTextureDesc desc;
+ if (requireStencil) {
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ } else {
+ desc.fFlags = kRenderTarget_GrTextureFlagBit |
+ kNoStencil_GrTextureFlagBit;
+ }
+
+ desc.fFormat = kRGBA_8888_GrPixelConfig;
+
+ int scale;
+ // Using MSAA seems to be slower for some yet unknown reason.
+ if (false && fGpu->supportsFullsceneAA()) {
+ record->fDownsample = OffscreenRecord::kFSAA_Downsample;
+ scale = GR_Scalar1;
+ desc.fAALevel = kMed_GrAALevel;
+ } else {
+ record->fDownsample = (fGpu->supports4x4DownsampleFilter()) ?
+ OffscreenRecord::k4x4SinglePass_Downsample :
+ OffscreenRecord::k4x4TwoPass_Downsample;
+ scale = 4;
+ desc.fAALevel = kNone_GrAALevel;
+ }
+
+ desc.fWidth = scale * size;
+ desc.fHeight = scale * size;
+
+ record->fEntry0 = this->lockKeylessTexture(desc);
+
+ if (NULL == record->fEntry0) {
+ return false;
+ }
+
+ if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
+ desc.fWidth /= 2;
+ desc.fHeight /= 2;
+ record->fEntry1 = this->lockKeylessTexture(desc);
+ if (NULL == record->fEntry1) {
+ this->unlockTexture(record->fEntry0);
+ record->fEntry0 = NULL;
+ return false;
+ }
+ }
+
+ GrRenderTarget* offRT0 = record->fEntry0->texture()->asRenderTarget();
+ GrAssert(NULL != offRT0);
+
+ target->saveCurrentDrawState(&record->fSavedState);
+
+ GrPaint tempPaint;
+ tempPaint.reset();
+ SetPaint(tempPaint, target);
+ target->setRenderTarget(offRT0);
+
+ GrMatrix transM;
+ transM.setTranslate(-boundRect.fLeft, -boundRect.fTop);
+ target->postConcatViewMatrix(transM);
+ GrMatrix scaleM;
+ scaleM.setScale(scale * GR_Scalar1, scale * GR_Scalar1);
+ target->postConcatViewMatrix(scaleM);
+
+ // clip gets applied in second pass
+ target->disableState(GrDrawTarget::kClip_StateBit);
+
+ GrIRect clear = SkIRect::MakeWH(scale * boundW, scale * boundH);
+ target->clear(&clear, 0x0);
+
+ return true;
+}
+
+void GrContext::offscreenAAPass2(GrDrawTarget* target,
+ const GrPaint& paint,
+ const GrIRect& boundRect,
+ OffscreenRecord* record) {
+
+ GrAssert(NULL != record->fEntry0);
+
+ GrSamplerState::Filter filter;
+ if (OffscreenRecord::k4x4SinglePass_Downsample == record->fDownsample) {
+ filter = GrSamplerState::k4x4Downsample_Filter;
+ } else {
+ filter = GrSamplerState::kBilinear_Filter;
+ }
+
+ GrMatrix sampleM;
+ GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
+ GrSamplerState::kClamp_WrapMode, filter);
+
+ GrTexture* src = record->fEntry0->texture();
+ int scale;
+
+ if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
+ GrAssert(NULL != record->fEntry1);
+ scale = 2;
+ GrRenderTarget* dst = record->fEntry1->texture()->asRenderTarget();
+
+ // Do 2x2 downsample from first to second
+ target->setTexture(kOffscreenStage, src);
+ target->setRenderTarget(dst);
+ target->setViewMatrix(GrMatrix::I());
+ sampleM.setScale(scale * GR_Scalar1 / src->width(),
+ scale * GR_Scalar1 / src->height());
+ sampler.setMatrix(sampleM);
+ target->setSamplerState(kOffscreenStage, sampler);
+ GrRect rect = SkRect::MakeWH(scale * boundRect.width(),
+ scale * boundRect.height());
+ target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
+
+ src = record->fEntry1->texture();
+ } else if (OffscreenRecord::kFSAA_Downsample == record->fDownsample) {
+ scale = 1;
+ GrIRect rect = SkIRect::MakeWH(boundRect.width(), boundRect.height());
+ src->asRenderTarget()->overrideResolveRect(rect);
+ } else {
+ GrAssert(OffscreenRecord::k4x4SinglePass_Downsample ==
+ record->fDownsample);
+ scale = 4;
+ }
+
+ // setup for draw back to main RT
+ target->restoreDrawState(record->fSavedState);
+ if (NULL != paint.getTexture()) {
+ GrMatrix invVM;
+ if (target->getViewInverse(&invVM)) {
+ target->preConcatSamplerMatrix(0, invVM);
+ }
+ }
+ target->setViewMatrix(GrMatrix::I());
+
+ target->setTexture(kOffscreenStage, src);
+ sampleM.setScale(scale * GR_Scalar1 / src->width(),
+ scale * GR_Scalar1 / src->height());
+ sampler.setMatrix(sampleM);
+ sampleM.setTranslate(-boundRect.fLeft, -boundRect.fTop);
+ sampler.preConcatMatrix(sampleM);
+ target->setSamplerState(kOffscreenStage, sampler);
+
+ GrRect dstRect;
+ int stages = (1 << kOffscreenStage) | (NULL == paint.getTexture() ? 0 : 1);
+ dstRect.set(boundRect);
+ target->drawSimpleRect(dstRect, NULL, stages);
+
+ this->unlockTexture(record->fEntry0);
+ record->fEntry0 = NULL;
+ if (NULL != record->fEntry1) {
+ this->unlockTexture(record->fEntry1);
+ record->fEntry1 = 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
would be faster.
*/
-static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
+static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
GrScalar width) {
const GrScalar rad = GrScalarHalf(width);
+ rect.sort();
verts[0].set(rect.fLeft + rad, rect.fTop + rad);
verts[1].set(rect.fLeft - rad, rect.fTop - rad);
@@ -366,6 +661,243 @@ static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
verts[9] = verts[1];
}
+static GrColor getColorForMesh(const GrPaint& paint) {
+ if (NULL == paint.getTexture()) {
+ return paint.fColor;
+ } else {
+ unsigned a = GrColorUnpackA(paint.fColor);
+ return GrColorPackRGBA(a, a, a, a);
+ }
+}
+
+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);
+}
+
+static const uint16_t gFillAARectIdx[] = {
+ 0, 1, 5, 5, 4, 0,
+ 1, 2, 6, 6, 5, 1,
+ 2, 3, 7, 7, 6, 2,
+ 3, 0, 4, 4, 7, 3,
+ 4, 5, 6, 6, 7, 4,
+};
+
+int GrContext::aaFillRectIndexCount() const {
+ return GR_ARRAY_COUNT(gFillAARectIdx);
+}
+
+GrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
+ if (NULL == fAAFillRectIndexBuffer) {
+ fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
+ false);
+ GrAssert(NULL != fAAFillRectIndexBuffer);
+#if GR_DEBUG
+ bool updated =
+#endif
+ fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
+ sizeof(gFillAARectIdx));
+ GR_DEBUGASSERT(updated);
+ }
+ return fAAFillRectIndexBuffer;
+}
+
+static const uint16_t gStrokeAARectIdx[] = {
+ 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
+ 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
+ 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
+ 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
+
+ 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
+ 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
+ 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
+ 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
+
+ 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
+ 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
+ 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
+ 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
+};
+
+int GrContext::aaStrokeRectIndexCount() const {
+ return GR_ARRAY_COUNT(gStrokeAARectIdx);
+}
+
+GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
+ if (NULL == fAAStrokeRectIndexBuffer) {
+ fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
+ false);
+ GrAssert(NULL != fAAStrokeRectIndexBuffer);
+#if GR_DEBUG
+ bool updated =
+#endif
+ fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
+ sizeof(gStrokeAARectIdx));
+ GR_DEBUGASSERT(updated);
+ }
+ return fAAStrokeRectIndexBuffer;
+}
+
+void GrContext::fillAARect(GrDrawTarget* target,
+ const GrPaint& paint,
+ const GrRect& devRect) {
+
+ GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
+ if (NULL != paint.getTexture()) {
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+ }
+
+ size_t vsize = GrDrawTarget::VertexSize(layout);
+
+ GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
+
+ intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
+
+ GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
+ GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
+
+ setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
+ setInsetFan(fan1Pos, vsize, devRect, GR_ScalarHalf, GR_ScalarHalf);
+
+ verts += sizeof(GrPoint);
+ for (int i = 0; i < 4; ++i) {
+ *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+ }
+
+ GrColor innerColor = getColorForMesh(paint);
+ verts += 4 * vsize;
+ for (int i = 0; i < 4; ++i) {
+ *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
+ }
+
+ target->setIndexSourceToBuffer(this->aaFillRectIndexBuffer());
+
+ target->drawIndexed(kTriangles_PrimitiveType, 0,
+ 0, 8, this->aaFillRectIndexCount());
+}
+
+void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
+ const GrRect& devRect, const GrVec& devStrokeSize) {
+ 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 = GrDrawTarget::kColor_VertexLayoutBit;
+
+ if (NULL != paint.getTexture()) {
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+ }
+
+ GrScalar spare;
+ {
+ GrScalar w = devRect.width() - dx;
+ GrScalar h = devRect.height() - dy;
+ spare = GrMin(w, h);
+ }
+
+ if (spare <= 0) {
+ GrRect r(devRect);
+ r.inset(-rx, -ry);
+ fillAARect(target, paint, r);
+ return;
+ }
+
+ size_t vsize = GrDrawTarget::VertexSize(layout);
+
+ GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
+
+ intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
+
+ GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
+ GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
+ GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
+ GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
+
+ setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
+ setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
+ setInsetFan(fan2Pos, vsize, devRect, rx - GR_ScalarHalf, ry - GR_ScalarHalf);
+ setInsetFan(fan3Pos, vsize, devRect, rx + GR_ScalarHalf, ry + GR_ScalarHalf);
+
+ verts += sizeof(GrPoint);
+ for (int i = 0; i < 4; ++i) {
+ *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+ }
+
+ GrColor innerColor = getColorForMesh(paint);
+ verts += 4 * vsize;
+ for (int i = 0; i < 8; ++i) {
+ *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
+ }
+
+ verts += 8 * vsize;
+ for (int i = 0; i < 8; ++i) {
+ *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+ }
+
+ target->setIndexSourceToBuffer(aaStrokeRectIndexBuffer());
+ target->drawIndexed(kTriangles_PrimitiveType,
+ 0, 0, 16, aaStrokeRectIndexCount());
+}
+
+/**
+ * Returns true if the rects edges are integer-aligned.
+ */
+static bool isIRect(const GrRect& r) {
+ return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
+ GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
+}
+
+static bool apply_aa_to_rect(GrDrawTarget* target,
+ GrGpu* gpu,
+ const GrPaint& paint,
+ const GrRect& rect,
+ GrScalar width,
+ const GrMatrix* matrix,
+ GrMatrix* combinedMatrix,
+ GrRect* devRect) {
+ // 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
+ // multisampled, and the rect won't land on integer coords.
+
+ if (!paint.fAntiAlias) {
+ return false;
+ }
+
+ if (target->getRenderTarget()->isMultisampled()) {
+ return false;
+ }
+
+ if (0 == width && gpu->supportsAALines()) {
+ return false;
+ }
+
+ if (!target->getViewMatrix().preservesAxisAlignment()) {
+ return false;
+ }
+
+ if (NULL != matrix &&
+ !matrix->preservesAxisAlignment()) {
+ return false;
+ }
+
+ *combinedMatrix = target->getViewMatrix();
+ if (NULL != matrix) {
+ combinedMatrix->preConcat(*matrix);
+ GrAssert(combinedMatrix->preservesAxisAlignment());
+ }
+
+ combinedMatrix->mapRect(devRect, rect);
+ devRect->sort();
+
+ if (width < 0) {
+ return !isIRect(*devRect);
+ } else {
+ return true;
+ }
+}
+
void GrContext::drawRect(const GrPaint& paint,
const GrRect& rect,
GrScalar width,
@@ -375,13 +907,43 @@ void GrContext::drawRect(const GrPaint& paint,
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+ GrRect devRect = rect;
+ GrMatrix combinedMatrix;
+ bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix,
+ &combinedMatrix, &devRect);
+
+ if (doAA) {
+ GrDrawTarget::AutoViewMatrixRestore avm(target);
+ if (textured) {
+ GrMatrix inv;
+ if (combinedMatrix.invert(&inv)) {
+ target->preConcatSamplerMatrix(0, inv);
+ }
+ }
+ target->setViewMatrix(GrMatrix::I());
+ if (width >= 0) {
+ GrVec strokeSize;;
+ if (width > 0) {
+ strokeSize.set(width, width);
+ combinedMatrix.mapVectors(&strokeSize, 1);
+ strokeSize.setAbs(strokeSize);
+ } else {
+ strokeSize.set(GR_Scalar1, GR_Scalar1);
+ }
+ strokeAARect(target, paint, devRect, strokeSize);
+ } else {
+ fillAARect(target, paint, devRect);
+ }
+ return;
+ }
+
if (width >= 0) {
// TODO: consider making static vertex buffers for these cases.
// Hairline could be done by just adding closing vertex to
// unitSquareVertexBuffer()
- GrVertexLayout layout = (textured) ?
- GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
- 0;
+ GrVertexLayout layout = textured ?
+ GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
+ 0;
static const int worstCaseVertCount = 10;
GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
@@ -412,7 +974,9 @@ void GrContext::drawRect(const GrPaint& paint,
if (NULL != matrix) {
avmr.set(target);
target->preConcatViewMatrix(*matrix);
- target->preConcatSamplerMatrix(0, *matrix);
+ if (textured) {
+ target->preConcatSamplerMatrix(0, *matrix);
+ }
}
target->drawNonIndexed(primType, 0, vertCount);
@@ -425,9 +989,9 @@ void GrContext::drawRect(const GrPaint& paint,
fGpu->getUnitSquareVertexBuffer());
GrDrawTarget::AutoViewMatrixRestore avmr(target);
GrMatrix m;
- m.setAll(rect.width(), 0, rect.fLeft,
- 0, rect.height(), rect.fTop,
- 0, 0, GrMatrix::I()[8]);
+ m.setAll(rect.width(), 0, rect.fLeft,
+ 0, rect.height(), rect.fTop,
+ 0, 0, GrMatrix::I()[8]);
if (NULL != matrix) {
m.postConcat(*matrix);
@@ -531,6 +1095,10 @@ void GrContext::drawVertices(const GrPaint& paint,
vertexSize += sizeof(GrColor);
}
+ bool doAA = false;
+ OffscreenRecord record;
+ GrIRect bounds;
+
if (sizeof(GrPoint) != vertexSize) {
if (!geo.set(target, layout, vertexCount, 0)) {
GrPrintf("Failed to get space for vertices!");
@@ -555,33 +1123,84 @@ void GrContext::drawVertices(const GrPaint& paint,
curVertex = (void*)((intptr_t)curVertex + vsize);
}
} else {
+ // we don't do offscreen AA when we have per-vertex tex coords or colors
+ if (this->doOffscreenAA(target, paint, GrIsPrimTypeLines(primitiveType))) {
+ GrRect b;
+ b.setBounds(positions, vertexCount);
+ target->getViewMatrix().mapRect(&b);
+ b.roundOut(&bounds);
+
+ if (this->setupOffscreenAAPass1(target, false, bounds, &record)) {
+ doAA = true;
+ }
+ }
target->setVertexSourceToArray(layout, positions, vertexCount);
}
if (NULL != indices) {
target->setIndexSourceToArray(indices, indexCount);
+ }
+
+ if (NULL != indices) {
target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
} else {
target->drawNonIndexed(primitiveType, 0, vertexCount);
}
+
+ if (doAA) {
+ this->offscreenAAPass2(target, paint, bounds, &record);
+ }
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
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 (!IsFillInverted(fill) && // will be relaxed soon
+ !pr->supportsAA(target, path, fill) &&
+ this->doOffscreenAA(target, paint, kHairLine_PathFill == fill)) {
+
+ OffscreenRecord record;
+ bool needsStencil = pr->requiresStencilPass(target, path, fill);
+
+ // compute bounds as intersection of rt size, clip, and path
+ GrIRect bound = SkIRect::MakeWH(target->getRenderTarget()->width(),
+ target->getRenderTarget()->height());
+ if (target->getClip().hasConservativeBounds()) {
+ GrIRect clipIBounds;
+ target->getClip().getConservativeBounds().roundOut(&clipIBounds);
+ if (!bound.intersect(clipIBounds)) {
+ return;
+ }
+ }
+ GrRect pathBounds;
+ if (path->getConservativeBounds(&pathBounds)) {
+ GrIRect pathIBounds;
+ target->getViewMatrix().mapRect(&pathBounds, pathBounds);
+ pathBounds.roundOut(&pathIBounds);
+ if (!bound.intersect(pathIBounds)) {
+ return;
+ }
+ }
+ if (this->setupOffscreenAAPass1(target, needsStencil, bound, &record)) {
+ pr->drawPath(target, 0, path, fill, translate);
+ this->offscreenAAPass2(target, paint, bound, &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);
}
@@ -659,8 +1278,8 @@ void GrContext::writePixels(int left, int top, int width, int height,
// 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
+ const GrTextureDesc desc = {
+ kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
};
GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
if (NULL == texture) {
@@ -716,6 +1335,7 @@ void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
target->disableState(GrDrawTarget::kAntialias_StateBit);
}
target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
+ target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
}
GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
@@ -787,7 +1407,7 @@ void GrContext::resetStats() {
fGpu->resetStats();
}
-const GrGpu::Stats& GrContext::getStats() const {
+const GrGpuStats& GrContext::getStats() const {
return fGpu->getStats();
}
@@ -816,6 +1436,9 @@ GrContext::GrContext(GrGpu* gpu) :
fDrawBufferVBAllocPool = NULL;
fDrawBufferIBAllocPool = NULL;
+ fAAFillRectIndexBuffer = NULL;
+ fAAStrokeRectIndexBuffer = NULL;
+
this->setupDrawBuffer();
}
@@ -844,28 +1467,6 @@ void GrContext::setupDrawBuffer() {
#endif
}
-bool GrContext::finalizeTextureKey(GrTextureKey* key,
- const GrSamplerState& sampler) const {
- uint32_t bits = 0;
- uint16_t width = key->width();
- uint16_t height = key->height();
-
-
- if (!fGpu->npotTextureTileSupport()) {
- bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
-
- bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
- (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
-
- if (tiled && !isPow2) {
- bits |= 1;
- bits |= sampler.isFilter() ? 2 : 0;
- }
- }
- key->finalize(bits);
- return 0 != bits;
-}
-
GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
GrDrawTarget* target;
#if DEFER_TEXT_RENDERING
@@ -892,3 +1493,4 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
return &fDefaultPathRenderer;
}
}
+
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 1413c6d..518b4ee 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -22,7 +22,7 @@
// recursive helper for creating mask with all the tex coord bits set for
// one stage
template <int N>
-static int stage_mask_recur(int stage) {
+int stage_mask_recur(int stage) {
return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
stage_mask_recur<N+1>(stage);
}
@@ -43,7 +43,7 @@ static int stage_mask(int stage) {
// recursive helper for creating mask of with all bits set relevant to one
// texture coordinate index
template <int N>
-static int tex_coord_mask_recur(int texCoordIdx) {
+int tex_coord_mask_recur(int texCoordIdx) {
return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
tex_coord_mask_recur<N+1>(texCoordIdx);
}
@@ -335,6 +335,10 @@ void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
fCurrDrawState.fViewMatrix.preConcat(matrix);
}
+void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
+ fCurrDrawState.fViewMatrix.postConcat(matrix);
+}
+
const GrMatrix& GrDrawTarget::getViewMatrix() const {
return fCurrDrawState.fViewMatrix;
}
@@ -376,6 +380,11 @@ void GrDrawTarget::setColor(GrColor c) {
fCurrDrawState.fColor = c;
}
+void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
+ fCurrDrawState.fColorFilterColor = c;
+ fCurrDrawState.fColorFilterXfermode = mode;
+}
+
void GrDrawTarget::setAlpha(uint8_t a) {
this->setColor((a << 24) | (a << 16) | (a << 8) | a);
}
@@ -409,9 +418,13 @@ bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout,
if (vertexCount) {
fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
fGeometrySrc.fVertexLayout = vertexLayout;
+ } else if (NULL != vertices) {
+ *vertices = NULL;
}
if (indexCount) {
fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
+ } else if (NULL != indices) {
+ *indices = NULL;
}
}
return fReservedGeometry.fLocked;
@@ -465,6 +478,11 @@ void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
///////////////////////////////////////////////////////////////////////////////
bool GrDrawTarget::canDisableBlend() const {
+ // If we're using edge antialiasing, we can't force blend off.
+ if (fCurrDrawState.fFlagBits & kEdgeAA_StateBit) {
+ return false;
+ }
+
if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
(kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
return true;
@@ -490,20 +508,34 @@ bool GrDrawTarget::canDisableBlend() const {
// ...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;
}
}
}
+ // ...and there isn't an interesting color filter...
+ // TODO: Consider being more aggressive with regards to disabling
+ // blending when a color filter is used.
+ if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
+ return false;
+ }
+
// ...then we disable blend.
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////
+void GrDrawTarget::setEdgeAAData(const float edges[18]) {
+ memcpy(fCurrDrawState.fEdgeAAEdges, edges, sizeof(fCurrDrawState.fEdgeAAEdges));
+}
+
+
///////////////////////////////////////////////////////////////////////////////
void GrDrawTarget::drawRect(const GrRect& rect,
const GrMatrix* matrix,
@@ -581,6 +613,9 @@ void GrDrawTarget::SetRectVertices(const GrRect& rect,
}
///////////////////////////////////////////////////////////////////////////////
+GrDrawTarget::AutoStateRestore::AutoStateRestore() {
+ fDrawTarget = NULL;
+}
GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
fDrawTarget = target;
@@ -595,3 +630,14 @@ GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
}
}
+void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
+ if (target != fDrawTarget) {
+ if (NULL != fDrawTarget) {
+ fDrawTarget->restoreDrawState(fDrawState);
+ }
+ if (NULL != target) {
+ fDrawTarget->saveCurrentDrawState(&fDrawState);
+ }
+ fDrawTarget = target;
+ }
+}
diff --git a/gpu/src/GrGLEffect.h b/gpu/src/GrGLEffect.h
index 7c85b6d..ef00df8 100644
--- a/gpu/src/GrGLEffect.h
+++ b/gpu/src/GrGLEffect.h
@@ -23,12 +23,12 @@
class GrEffect;
struct ShaderCodeSegments {
- GrSStringBuilder<256> fVSUnis;
- GrSStringBuilder<256> fVSAttrs;
- GrSStringBuilder<256> fVaryings;
- GrSStringBuilder<256> fFSUnis;
- GrSStringBuilder<512> fVSCode;
- GrSStringBuilder<512> fFSCode;
+ GrStringBuilder fVSUnis;
+ GrStringBuilder fVSAttrs;
+ GrStringBuilder fVaryings;
+ GrStringBuilder fFSUnis;
+ GrStringBuilder fVSCode;
+ GrStringBuilder fFSCode;
};
/**
diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp
index 5dfc03c..0825a3f 100644
--- a/gpu/src/GrGLInterface.cpp
+++ b/gpu/src/GrGLInterface.cpp
@@ -93,3 +93,246 @@ void gl_version(int* major, int* minor) {
GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
gl_version_from_string(major, minor, v);
}
+
+bool GrGLInterface::validateShaderFunctions() const {
+ // required for GrGpuGLShaders
+ if (NULL == fAttachShader ||
+ NULL == fBindAttribLocation ||
+ NULL == fCompileShader ||
+ NULL == fCreateProgram ||
+ NULL == fCreateShader ||
+ NULL == fDeleteProgram ||
+ NULL == fDeleteShader ||
+ NULL == fDisableVertexAttribArray ||
+ NULL == fEnableVertexAttribArray ||
+ NULL == fGetProgramInfoLog ||
+ NULL == fGetProgramiv ||
+ NULL == fGetShaderInfoLog ||
+ NULL == fGetShaderiv ||
+ NULL == fGetUniformLocation ||
+ NULL == fLinkProgram ||
+ NULL == fShaderSource ||
+ NULL == fUniform1f ||
+ NULL == fUniform1i ||
+ NULL == fUniform1fv ||
+ NULL == fUniform1iv ||
+ NULL == fUniform2f ||
+ NULL == fUniform2i ||
+ NULL == fUniform2fv ||
+ NULL == fUniform2iv ||
+ NULL == fUniform3f ||
+ NULL == fUniform3i ||
+ NULL == fUniform3fv ||
+ NULL == fUniform3iv ||
+ NULL == fUniform4f ||
+ NULL == fUniform4i ||
+ NULL == fUniform4fv ||
+ NULL == fUniform4iv ||
+ NULL == fUniformMatrix2fv ||
+ NULL == fUniformMatrix3fv ||
+ NULL == fUniformMatrix4fv ||
+ NULL == fUseProgram ||
+ NULL == fVertexAttrib4fv ||
+ NULL == fVertexAttribPointer) {
+ return false;
+ }
+ return true;
+}
+
+bool GrGLInterface::validateFixedFunctions() const {
+ if (NULL == fClientActiveTexture ||
+ NULL == fColor4ub ||
+ NULL == fColorPointer ||
+ NULL == fDisableClientState ||
+ NULL == fEnableClientState ||
+ NULL == fLoadMatrixf ||
+ NULL == fMatrixMode ||
+ NULL == fPointSize ||
+ NULL == fShadeModel ||
+ NULL == fTexCoordPointer ||
+ NULL == fTexEnvi ||
+ NULL == fVertexPointer) {
+ return false;
+ }
+ return true;
+}
+
+bool GrGLInterface::validate(GrEngine engine) const {
+
+ bool isDesktop = kDesktop_GrGLBinding == fBindingsExported;
+
+ // ES1 and 2 can be supported in the same interface
+ bool isES = ((kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported &&
+ !(~(kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported));
+
+ if (!isDesktop && !isES) {
+ return false;
+ }
+
+ // functions that are always required
+ if (NULL == fActiveTexture ||
+ NULL == fBindBuffer ||
+ NULL == fBindTexture ||
+ NULL == fBlendFunc ||
+ NULL == fBufferData ||
+ NULL == fBufferSubData ||
+ NULL == fClear ||
+ NULL == fClearColor ||
+ NULL == fClearStencil ||
+ NULL == fColorMask ||
+ NULL == fCullFace ||
+ NULL == fDeleteBuffers ||
+ NULL == fDeleteTextures ||
+ NULL == fDepthMask ||
+ NULL == fDisable ||
+ NULL == fDrawArrays ||
+ NULL == fDrawElements ||
+ NULL == fEnable ||
+ NULL == fFrontFace ||
+ NULL == fGenBuffers ||
+ NULL == fGenTextures ||
+ NULL == fGetBufferParameteriv ||
+ NULL == fGetError ||
+ NULL == fGetIntegerv ||
+ NULL == fGetString ||
+ NULL == fPixelStorei ||
+ NULL == fReadPixels ||
+ NULL == fScissor ||
+ NULL == fStencilFunc ||
+ NULL == fStencilMask ||
+ NULL == fStencilOp ||
+ NULL == fTexImage2D ||
+ NULL == fTexParameteri ||
+ NULL == fTexSubImage2D ||
+ NULL == fViewport ||
+ NULL == fBindFramebuffer ||
+ NULL == fBindRenderbuffer ||
+ NULL == fCheckFramebufferStatus ||
+ NULL == fDeleteFramebuffers ||
+ NULL == fDeleteRenderbuffers ||
+ NULL == fFramebufferRenderbuffer ||
+ NULL == fFramebufferTexture2D ||
+ NULL == fGenFramebuffers ||
+ NULL == fGenRenderbuffers ||
+ NULL == fRenderbufferStorage) {
+ return false;
+ }
+
+ switch (engine) {
+ case kOpenGL_Shaders_GrEngine:
+ if (kES1_GrGLBinding == fBindingsExported) {
+ return false;
+ }
+ if (!this->validateShaderFunctions()) {
+ return false;
+ }
+ break;
+ case kOpenGL_Fixed_GrEngine:
+ if (kES1_GrGLBinding == fBindingsExported) {
+ return false;
+ }
+ if (!this->validateFixedFunctions()) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ int major, minor;
+ const char* ext;
+
+ gl_version(&major, &minor);
+ ext = (const char*)fGetString(GR_GL_EXTENSIONS);
+
+ // Now check that baseline ES/Desktop fns not covered above are present
+ // and that we have fn pointers for any advertised extensions that we will
+ // try to use.
+
+ // these functions are part of ES2, we assume they are available
+ // On the desktop we assume they are available if the extension
+ // is present or GL version is high enough.
+ if ((kES2_GrGLBinding & fBindingsExported)) {
+ if (NULL == fBlendColor ||
+ NULL == fStencilFuncSeparate ||
+ NULL == fStencilMaskSeparate ||
+ NULL == fStencilOpSeparate) {
+ return false;
+ }
+ } else if (kDesktop_GrGLBinding == fBindingsExported) {
+ if (major >= 2) {
+ if (NULL == fStencilFuncSeparate ||
+ NULL == fStencilMaskSeparate ||
+ NULL == fStencilOpSeparate) {
+ return false;
+ }
+ }
+ if (1 < major || (1 == major && 4 <= minor) ||
+ has_gl_extension_from_string("GL_EXT_blend_color", ext)) {
+ if (NULL == fBlendColor) {
+ return false;
+ }
+ }
+ }
+
+ // optional function on desktop before 1.3
+ if (kDesktop_GrGLBinding != fBindingsExported ||
+ (1 < major || (1 == major && 3 <= minor)) ||
+ has_gl_extension_from_string("GL_ARB_texture_compression", ext)) {
+ if (NULL == fCompressedTexImage2D) {
+ return false;
+ }
+ }
+
+ // part of desktop GL
+ if (kDesktop_GrGLBinding == fBindingsExported &&
+ NULL == fLineWidth) {
+ return false;
+ }
+ // FBO MSAA
+ if (kDesktop_GrGLBinding == fBindingsExported) {
+ // GL 3.0 and the ARB extension have multisample + blit
+ if ((major >= 3) || has_gl_extension_from_string("GL_ARB_framebuffer_object", ext)) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ } else {
+ if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", ext) &&
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", ext) &&
+ NULL == fRenderbufferStorageMultisample) {
+ return false;
+ }
+ }
+ } else {
+ if (has_gl_extension_from_string("GL_CHROMIUM_framebuffer_multisample", ext)) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ }
+ if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample", ext)) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fResolveMultisampleFramebuffer) {
+ return false;
+ }
+ }
+ }
+
+ // On ES buffer mapping is an extension. On Desktop
+ // buffer mapping was part of original VBO extension
+ // which we require.
+ if (kDesktop_GrGLBinding == fBindingsExported ||
+ has_gl_extension_from_string("GL_OES_mapbuffer", ext)) {
+ if (NULL == fMapBuffer ||
+ NULL == fUnmapBuffer) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index 5dd09f0..5d2d8b3 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -20,7 +20,8 @@
#include "GrGLConfig.h"
#include "GrGLEffect.h"
#include "GrMemory.h"
-#include "GrStringBuilder.h"
+
+#include "SkXfermode.h"
namespace {
@@ -28,7 +29,7 @@ const char* GrPrecision() {
if (GR_GL_SUPPORT_ES2) {
return "mediump";
} else {
- return "";
+ return " ";
}
}
@@ -42,7 +43,9 @@ const char* GrShaderPrecision() {
} // namespace
-#if ATTRIBUTE_MATRIX
+#define PRINT_SHADERS 0
+
+#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
#else
#define VIEW_MATRIX_NAME "uViewM"
@@ -50,13 +53,13 @@ const char* GrShaderPrecision() {
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
-
-// for variable names etc
-typedef GrSStringBuilder<16> GrTokenString;
+#define COL_UNI_NAME "uColor"
+#define EDGES_UNI_NAME "uEdges"
+#define COL_FILTER_UNI_NAME "uColorFilter"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
*s = "aTexCoord";
- s->appendInt(coordIdx);
+ s->appendS32(coordIdx);
}
static inline const char* float_vector_type(int count) {
@@ -84,32 +87,37 @@ static inline const char* vector_all_coords(int count) {
}
static void tex_matrix_name(int stage, GrStringBuilder* s) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
*s = "aTexM";
#else
*s = "uTexM";
#endif
- s->appendInt(stage);
+ s->appendS32(stage);
+}
+
+static void normalized_texel_size_name(int stage, GrStringBuilder* s) {
+ *s = "uTexelSize";
+ s->appendS32(stage);
}
static void sampler_name(int stage, GrStringBuilder* s) {
*s = "uSampler";
- s->appendInt(stage);
+ s->appendS32(stage);
}
static void stage_varying_name(int stage, GrStringBuilder* s) {
*s = "vStage";
- s->appendInt(stage);
+ s->appendS32(stage);
}
static void radial2_param_name(int stage, GrStringBuilder* s) {
*s = "uRadial2Params";
- s->appendInt(stage);
+ s->appendS32(stage);
}
static void radial2_varying_name(int stage, GrStringBuilder* s) {
*s = "vB";
- s->appendInt(stage);
+ s->appendS32(stage);
}
GrGLProgram::GrGLProgram() {
@@ -119,7 +127,6 @@ GrGLProgram::GrGLProgram() {
}
GrGLProgram::~GrGLProgram() {
-
}
void GrGLProgram::buildKey(GrBinHashKeyBuilder& key) const {
@@ -171,156 +178,272 @@ void GrGLProgram::doGLPost() const {
}
}
-void GrGLProgram::genProgram(GrGLProgram::CachedData* programData,
- const GrDrawTarget* target) const {
+/**
+ * Create a text coefficient to be used in fragment shader code.
+ */
+static void coefficientString(GrStringBuilder* str, SkXfermode::Coeff coeff,
+ const char* src, const char* dst) {
+ switch (coeff) {
+ case SkXfermode::kZero_Coeff: /** 0 */
+ *str = "0.0";
+ break;
+ case SkXfermode::kOne_Coeff: /** 1 */
+ *str = "1.0";
+ break;
+ case SkXfermode::kSA_Coeff: /** src alpha */
+ str->appendf("%s.a", src);
+ break;
+ case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
+ str->appendf("(1.0 - %s.a)", src);
+ break;
+ case SkXfermode::kDA_Coeff: /** dst alpha */
+ str->appendf("%s.a", dst);
+ break;
+ case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
+ str->appendf("(1.0 - %s.a)", dst);
+ break;
+ case SkXfermode::kSC_Coeff:
+ str->append(src);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Adds a line to the fragment shader code which modifies the color by
+ * the specified color filter.
+ */
+static void addColorFilter(GrStringBuilder* FSCode, const char * outputVar,
+ SkXfermode::Mode colorFilterXfermode, const char* dstColor) {
+ SkXfermode::Coeff srcCoeff, dstCoeff;
+ SkDEBUGCODE(bool success =)
+ SkXfermode::ModeAsCoeff(colorFilterXfermode, &srcCoeff, &dstCoeff);
+ // We currently do not handle modes that cannot be represented as
+ // coefficients.
+ GrAssert(success);
+ GrStringBuilder srcCoeffStr, dstCoeffStr;
+ coefficientString(&srcCoeffStr, srcCoeff, COL_FILTER_UNI_NAME, dstColor);
+ coefficientString(&dstCoeffStr, dstCoeff, COL_FILTER_UNI_NAME, dstColor);
+ FSCode->appendf("\t%s = %s*%s + %s*%s;\n", outputVar, srcCoeffStr.c_str(),
+ COL_FILTER_UNI_NAME, dstCoeffStr.c_str(), dstColor);
+}
+
+bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
ShaderCodeSegments segments;
const uint32_t& layout = fProgramDesc.fVertexLayout;
- memset(&programData->fUniLocations, 0, sizeof(UniLocations));
+ programData->fUniLocations.reset();
- bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
- fProgramDesc.fOptFlags);
-
-#if ATTRIBUTE_MATRIX
- segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
+#if GR_GL_ATTRIBUTE_MATRICES
+ segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
+ programData->fUniLocations.fViewMatrixUni = kSetAsAttribute;
#else
- segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
- segments.fVSAttrs = "";
+ segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
+ programData->fUniLocations.fViewMatrixUni = kUseUniform;
#endif
segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
- if (haveColor) {
- segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
- segments.fVaryings = "varying vec4 vColor;\n";
- } else {
- segments.fVaryings = "";
+
+ segments.fVSCode.append(
+ "void main() {\n"
+ "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3("POS_ATTR_NAME", 1);\n"
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n");
+
+ // incoming color to current stage being processed.
+ GrStringBuilder inColor;
+
+ switch (fProgramDesc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ segments.fVSAttrs.append( "attribute vec4 " COL_ATTR_NAME ";\n");
+ segments.fVaryings.append("varying vec4 vColor;\n");
+ segments.fVSCode.append( "\tvColor = " COL_ATTR_NAME ";\n");
+ inColor = "vColor";
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ segments.fFSUnis.append( "uniform vec4 " COL_UNI_NAME ";\n");
+ programData->fUniLocations.fColorUni = kUseUniform;
+ inColor = COL_UNI_NAME;
+ break;
+ case ProgramDesc::kNone_ColorType:
+ inColor = "";
+ break;
}
- segments.fVSCode = "void main() {\n"
- "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
- if (haveColor) {
- segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
+ if (fProgramDesc.fUsesEdgeAA) {
+ segments.fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[6];\n");
}
- if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) {
- segments.fVSCode += "\tgl_PointSize = 1.0;\n";
+ if (fProgramDesc.fEmitsPointSize){
+ segments.fVSCode.append("\tgl_PointSize = 1.0;\n");
}
- segments.fFSCode = "void main() {\n";
+
+ segments.fFSCode.append("void main() {\n");
// add texture coordinates that are used to the list of vertex attr decls
- GrTokenString texCoordAttrs[GrDrawTarget::kMaxTexCoords];
+ GrStringBuilder texCoordAttrs[GrDrawTarget::kMaxTexCoords];
for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
- if (target->VertexUsesTexCoordIdx(t, layout)) {
+ if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
tex_attr_name(t, texCoordAttrs + t);
-
- segments.fVSAttrs += "attribute vec2 ";
- segments.fVSAttrs += texCoordAttrs[t];
- segments.fVSAttrs += ";\n";
+ segments.fVSAttrs.appendf("attribute vec2 %s;\n", texCoordAttrs[t].c_str());
}
}
+ bool useColorFilter =
+ // The rest of transfer mode color filters have not been implemented
+ fProgramDesc.fColorFilterXfermode <= SkXfermode::kMultiply_Mode
+ // This mode has no effect.
+ && fProgramDesc.fColorFilterXfermode != SkXfermode::kDst_Mode;
+ bool onlyUseColorFilter = useColorFilter
+ && (fProgramDesc.fColorFilterXfermode == SkXfermode::kClear_Mode
+ || fProgramDesc.fColorFilterXfermode == SkXfermode::kSrc_Mode);
+ if (useColorFilter) {
+ // Set up a uniform for the color
+ segments.fFSUnis.append( "uniform vec4 " COL_FILTER_UNI_NAME ";\n");
+ programData->fUniLocations.fColorFilterUni = kUseUniform;
+ }
+
// for each enabled stage figure out what the input coordinates are
// and count the number of stages in use.
const char* stageInCoords[GrDrawTarget::kNumStages];
int numActiveStages = 0;
- for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
- if (fProgramDesc.fStages[s].fEnabled) {
- if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
- stageInCoords[s] = POS_ATTR_NAME;
- } else {
- int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
- // we better have input tex coordinates if stage is enabled.
- GrAssert(tcIdx >= 0);
- GrAssert(texCoordAttrs[tcIdx].length());
- stageInCoords[s] = texCoordAttrs[tcIdx].cstr();
+ if (!onlyUseColorFilter) {
+ for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+ if (fProgramDesc.fStages[s].fEnabled) {
+ if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
+ stageInCoords[s] = POS_ATTR_NAME;
+ } else {
+ int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
+ // we better have input tex coordinates if stage is enabled.
+ GrAssert(tcIdx >= 0);
+ GrAssert(texCoordAttrs[tcIdx].size());
+ stageInCoords[s] = texCoordAttrs[tcIdx].c_str();
+ }
+ ++numActiveStages;
}
- ++numActiveStages;
}
}
- GrTokenString inColor = "vColor";
-
// if we have active stages string them together, feeding the output color
// of each to the next and generating code for each stage.
if (numActiveStages) {
int currActiveStage = 0;
+ GrStringBuilder outColor;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
if (fProgramDesc.fStages[s].fEnabled) {
- GrTokenString outColor;
- if (currActiveStage < (numActiveStages - 1)) {
+ if (currActiveStage < (numActiveStages - 1) || useColorFilter) {
outColor = "color";
- outColor.appendInt(currActiveStage);
- segments.fFSCode += "\tvec4 ";
- segments.fFSCode += outColor;
- segments.fFSCode += ";\n";
+ outColor.appendS32(currActiveStage);
+ segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
} else {
outColor = "gl_FragColor";
}
genStageCode(s,
fProgramDesc.fStages[s],
- haveColor ? inColor.cstr() : NULL,
- outColor.cstr(),
+ inColor.size() ? inColor.c_str() : NULL,
+ outColor.c_str(),
stageInCoords[s],
&segments,
&programData->fUniLocations.fStages[s]);
++currActiveStage;
inColor = outColor;
- haveColor = true;
}
}
+ if (useColorFilter) {
+ addColorFilter(&segments.fFSCode, "gl_FragColor",
+ fProgramDesc.fColorFilterXfermode, outColor.c_str());
+ }
+
} else {
- segments.fFSCode += "\tgl_FragColor = ";
- if (haveColor) {
- segments.fFSCode += inColor;
+ if (fProgramDesc.fUsesEdgeAA) {
+ // FIXME: put the a's in a loop
+ segments.fFSCode.append(
+ "\tvec3 pos = vec3(gl_FragCoord.xy, 1);\n"
+ "\tfloat a0 = clamp(dot(uEdges[0], pos), 0.0, 1.0);\n"
+ "\tfloat a1 = clamp(dot(uEdges[1], pos), 0.0, 1.0);\n"
+ "\tfloat a2 = clamp(dot(uEdges[2], pos), 0.0, 1.0);\n"
+ "\tfloat a3 = clamp(dot(uEdges[3], pos), 0.0, 1.0);\n"
+ "\tfloat a4 = clamp(dot(uEdges[4], pos), 0.0, 1.0);\n"
+ "\tfloat a5 = clamp(dot(uEdges[5], pos), 0.0, 1.0);\n"
+ "\tfloat edgeAlpha = min(min(a0 * a1, a2 * a3), a4 * a5);\n");
+ if (inColor.size()) {
+ inColor.append(" * edgeAlpha");
+ } else {
+ inColor = "vec4(edgeAlpha)";
+ }
+ }
+ // we may not have any incoming color
+ const char * incomingColor = (inColor.size() ? inColor.c_str()
+ : "vec4(1,1,1,1)");
+ if (useColorFilter) {
+ addColorFilter(&segments.fFSCode, "gl_FragColor",
+ fProgramDesc.fColorFilterXfermode, incomingColor);
} else {
- segments.fFSCode += "vec4(1,1,1,1)";
+ segments.fFSCode.appendf("\tgl_FragColor = %s;\n", incomingColor);
}
- segments.fFSCode += ";\n";
}
- segments.fFSCode += "}\n";
- segments.fVSCode += "}\n";
+ segments.fVSCode.append("}\n");
+ segments.fFSCode.append("}\n");
+
+ if (!CompileFSAndVS(segments, programData)) {
+ return false;
+ }
+
+ if (!this->bindAttribsAndLinkProgram(texCoordAttrs, programData)) {
+ return false;
+ }
+
+ this->getUniformLocationsAndInitCache(programData);
+
+ return true;
+}
+bool GrGLProgram::CompileFSAndVS(const ShaderCodeSegments& segments,
+ CachedData* programData) {
const char* strings[4];
int lengths[4];
int stringCnt = 0;
- if (segments.fVSUnis.length()) {
- strings[stringCnt] = segments.fVSUnis.cstr();
- lengths[stringCnt] = segments.fVSUnis.length();
+ if (segments.fVSUnis.size()) {
+ strings[stringCnt] = segments.fVSUnis.c_str();
+ lengths[stringCnt] = segments.fVSUnis.size();
++stringCnt;
}
- if (segments.fVSAttrs.length()) {
- strings[stringCnt] = segments.fVSAttrs.cstr();
- lengths[stringCnt] = segments.fVSAttrs.length();
+ if (segments.fVSAttrs.size()) {
+ strings[stringCnt] = segments.fVSAttrs.c_str();
+ lengths[stringCnt] = segments.fVSAttrs.size();
++stringCnt;
}
- if (segments.fVaryings.length()) {
- strings[stringCnt] = segments.fVaryings.cstr();
- lengths[stringCnt] = segments.fVaryings.length();
+ if (segments.fVaryings.size()) {
+ strings[stringCnt] = segments.fVaryings.c_str();
+ lengths[stringCnt] = segments.fVaryings.size();
++stringCnt;
}
- GrAssert(segments.fVSCode.length());
- strings[stringCnt] = segments.fVSCode.cstr();
- lengths[stringCnt] = segments.fVSCode.length();
+ GrAssert(segments.fVSCode.size());
+ strings[stringCnt] = segments.fVSCode.c_str();
+ lengths[stringCnt] = segments.fVSCode.size();
++stringCnt;
#if PRINT_SHADERS
- GrPrintf("%s%s%s%s\n",
- segments.fVSUnis.cstr(),
- segments.fVSAttrs.cstr(),
- segments.fVaryings.cstr(),
- segments.fVSCode.cstr());
+ GrPrintf(segments.fVSUnis.c_str());
+ GrPrintf(segments.fVSAttrs.c_str());
+ GrPrintf(segments.fVaryings.c_str());
+ GrPrintf(segments.fVSCode.c_str());
+ GrPrintf("\n");
#endif
programData->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER,
stringCnt,
strings,
lengths);
+ if (!programData->fVShaderID) {
+ return false;
+ }
+
stringCnt = 0;
if (strlen(GrShaderPrecision()) > 1) {
@@ -328,73 +451,117 @@ void GrGLProgram::genProgram(GrGLProgram::CachedData* programData,
lengths[stringCnt] = strlen(GrShaderPrecision());
++stringCnt;
}
- if (segments.fFSUnis.length()) {
- strings[stringCnt] = segments.fFSUnis.cstr();
- lengths[stringCnt] = segments.fFSUnis.length();
+ if (segments.fFSUnis.size()) {
+ strings[stringCnt] = segments.fFSUnis.c_str();
+ lengths[stringCnt] = segments.fFSUnis.size();
++stringCnt;
}
- if (segments.fVaryings.length()) {
- strings[stringCnt] = segments.fVaryings.cstr();
- lengths[stringCnt] = segments.fVaryings.length();
+ if (segments.fVaryings.size()) {
+ strings[stringCnt] = segments.fVaryings.c_str();
+ lengths[stringCnt] = segments.fVaryings.size();
++stringCnt;
}
- GrAssert(segments.fFSCode.length());
- strings[stringCnt] = segments.fFSCode.cstr();
- lengths[stringCnt] = segments.fFSCode.length();
+ GrAssert(segments.fFSCode.size());
+ strings[stringCnt] = segments.fFSCode.c_str();
+ lengths[stringCnt] = segments.fFSCode.size();
++stringCnt;
#if PRINT_SHADERS
- GrPrintf("%s%s%s%s\n",
- GR_SHADER_PRECISION,
- segments.fFSUnis.cstr(),
- segments.fVaryings.cstr(),
- segments.fFSCode.cstr());
+ GrPrintf(GrShaderPrecision());
+ GrPrintf(segments.fFSUnis.c_str());
+ GrPrintf(segments.fVaryings.c_str());
+ GrPrintf(segments.fFSCode.c_str());
+ GrPrintf("\n");
#endif
programData->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER,
stringCnt,
strings,
lengths);
+ if (!programData->fFShaderID) {
+ return false;
+ }
+ return true;
+}
+
+GrGLuint GrGLProgram::CompileShader(GrGLenum type,
+ int stringCnt,
+ const char** strings,
+ int* stringLengths) {
+ GrGLuint shader = GR_GL(CreateShader(type));
+ if (0 == shader) {
+ return 0;
+ }
+
+ GrGLint compiled = GR_GL_INIT_ZERO;
+ GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
+ GR_GL(CompileShader(shader));
+ GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
+
+ if (!compiled) {
+ GrGLint infoLen = GR_GL_INIT_ZERO;
+ GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
+ GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
+ if (infoLen > 0) {
+ GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
+ for (int i = 0; i < stringCnt; ++i) {
+ if (NULL == stringLengths || stringLengths[i] < 0) {
+ GrPrintf(strings[i]);
+ } else {
+ GrPrintf("%.*s", stringLengths[i], strings[i]);
+ }
+ }
+ GrPrintf("\n%s", log.get());
+ }
+ GrAssert(!"Shader compilation failed!");
+ GR_GL(DeleteShader(shader));
+ return 0;
+ }
+ return shader;
+}
+
+bool GrGLProgram::bindAttribsAndLinkProgram(GrStringBuilder texCoordAttrNames[],
+ CachedData* programData) const {
programData->fProgramID = GR_GL(CreateProgram());
+ if (!programData->fProgramID) {
+ return false;
+ }
const GrGLint& progID = programData->fProgramID;
GR_GL(AttachShader(progID, programData->fVShaderID));
GR_GL(AttachShader(progID, programData->fFShaderID));
// Bind the attrib locations to same values for all shaders
- GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
+ GR_GL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME));
for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
- if (texCoordAttrs[t].length()) {
+ if (texCoordAttrNames[t].size()) {
GR_GL(BindAttribLocation(progID,
- TEX_ATTR_LOCATION(t),
- texCoordAttrs[t].cstr()));
+ TexCoordAttributeIdx(t),
+ texCoordAttrNames[t].c_str()));
}
}
-#if ATTRIBUTE_MATRIX
- // set unis to a bogus value so that checks against -1 before
- // flushing will pass.
- GR_GL(BindAttribLocation(progID,
- VIEWMAT_ATTR_LOCATION,
- VIEW_MATRIX_NAME));
- program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
+ if (kSetAsAttribute == programData->fUniLocations.fViewMatrixUni) {
+ GR_GL(BindAttribLocation(progID,
+ ViewMatrixAttributeIdx(),
+ VIEW_MATRIX_NAME));
+ }
- for (int s = 0; s < kNumStages; ++s) {
- if (fProgramDesc.fStages[s].fEnabled) {
+ for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+ const StageUniLocations& unis = programData->fUniLocations.fStages[s];
+ if (kSetAsAttribute == unis.fTextureMatrixUni) {
GrStringBuilder matName;
tex_matrix_name(s, &matName);
GR_GL(BindAttribLocation(progID,
- TEXMAT_ATTR_LOCATION(s),
- matName.cstr()));
- program->fUniLocations.fStages[s].fTextureMatrixUni =
- BOGUS_MATRIX_UNI_LOCATION;
+ TextureMatrixAttributeIdx(s),
+ matName.c_str()));
}
}
-#endif
- GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME));
+
+ GR_GL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME));
GR_GL(LinkProgram(progID));
@@ -414,107 +581,93 @@ void GrGLProgram::genProgram(GrGLProgram::CachedData* programData,
GrAssert(!"Error linking program");
GR_GL(DeleteProgram(progID));
programData->fProgramID = 0;
- return;
+ return false;
+ }
+ return true;
+}
+
+void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const {
+ const GrGLint& progID = programData->fProgramID;
+
+ if (kUseUniform == programData->fUniLocations.fViewMatrixUni) {
+ programData->fUniLocations.fViewMatrixUni =
+ GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
+ }
+ if (kUseUniform == programData->fUniLocations.fColorUni) {
+ programData->fUniLocations.fColorUni =
+ GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
+ }
+ if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
+ programData->fUniLocations.fColorFilterUni =
+ GR_GL(GetUniformLocation(progID, COL_FILTER_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
+ }
+
+ if (fProgramDesc.fUsesEdgeAA) {
+ programData->fUniLocations.fEdgesUni =
+ GR_GL(GetUniformLocation(progID, EDGES_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni);
+ } else {
+ programData->fUniLocations.fEdgesUni = kUnusedUniform;
}
- // Get uniform locations
-#if !ATTRIBUTE_MATRIX
- programData->fUniLocations.fViewMatrixUni =
- GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
- GrAssert(-1 != programData->fUniLocations.fViewMatrixUni);
-#endif
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
StageUniLocations& locations = programData->fUniLocations.fStages[s];
if (fProgramDesc.fStages[s].fEnabled) {
-#if !ATTRIBUTE_MATRIX
- if (locations.fTextureMatrixUni) {
- GrTokenString texMName;
+ if (kUseUniform == locations.fTextureMatrixUni) {
+ GrStringBuilder texMName;
tex_matrix_name(s, &texMName);
locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
progID,
- texMName.cstr()));
- GrAssert(-1 != locations.fTextureMatrixUni);
- } else {
- locations.fTextureMatrixUni = -1;
-
+ texMName.c_str()));
+ GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
}
-#endif
- if (locations.fSamplerUni) {
- GrTokenString samplerName;
+ if (kUseUniform == locations.fSamplerUni) {
+ GrStringBuilder samplerName;
sampler_name(s, &samplerName);
locations.fSamplerUni = GR_GL(GetUniformLocation(
progID,
- samplerName.cstr()));
- GrAssert(-1 != locations.fSamplerUni);
- } else {
- locations.fSamplerUni = -1;
+ samplerName.c_str()));
+ GrAssert(kUnusedUniform != locations.fSamplerUni);
+ }
+
+ if (kUseUniform == locations.fNormalizedTexelSizeUni) {
+ GrStringBuilder texelSizeName;
+ normalized_texel_size_name(s, &texelSizeName);
+ locations.fNormalizedTexelSizeUni =
+ GR_GL(GetUniformLocation(progID, texelSizeName.c_str()));
+ GrAssert(kUnusedUniform != locations.fNormalizedTexelSizeUni);
}
- if (locations.fRadial2Uni) {
- GrTokenString radial2ParamName;
+ if (kUseUniform == locations.fRadial2Uni) {
+ GrStringBuilder radial2ParamName;
radial2_param_name(s, &radial2ParamName);
locations.fRadial2Uni = GR_GL(GetUniformLocation(
progID,
- radial2ParamName.cstr()));
- GrAssert(-1 != locations.fRadial2Uni);
- } else {
- locations.fRadial2Uni = -1;
+ radial2ParamName.c_str()));
+ GrAssert(kUnusedUniform != locations.fRadial2Uni);
}
- } else {
- locations.fSamplerUni = -1;
- locations.fRadial2Uni = -1;
- locations.fTextureMatrixUni = -1;
}
}
GR_GL(UseProgram(progID));
// init sampler unis and set bogus values for state tracking
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
- if (-1 != programData->fUniLocations.fStages[s].fSamplerUni) {
+ if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) {
GR_GL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s));
}
programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
programData->fRadial2CenterX1[s] = GR_ScalarMax;
programData->fRadial2Radius0[s] = -GR_ScalarMax;
+ programData->fTextureWidth[s] = -1;
+ programData->fTextureHeight[s] = -1;
}
programData->fViewMatrix = GrMatrix::InvalidMatrix();
-}
-
-GrGLuint GrGLProgram::CompileShader(GrGLenum type,
- int stringCnt,
- const char** strings,
- int* stringLengths) {
- GrGLuint shader = GR_GL(CreateShader(type));
- if (0 == shader) {
- return 0;
- }
-
- GrGLint compiled = GR_GL_INIT_ZERO;
- GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
- GR_GL(CompileShader(shader));
- GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
-
- if (!compiled) {
- GrGLint infoLen = GR_GL_INIT_ZERO;
- GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
- GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
- if (infoLen > 0) {
- GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
- for (int i = 0; i < stringCnt; ++i) {
- if (NULL == stringLengths || stringLengths[i] < 0) {
- GrPrintf(strings[i]);
- } else {
- GrPrintf("%.*s", stringLengths[i], strings[i]);
- }
- }
- GrPrintf("\n%s", log.get());
- }
- GrAssert(!"Shader compilation failed!");
- GR_GL(DeleteShader(shader));
- return 0;
- }
- return shader;
+ programData->fColor = GrColor_ILLEGAL;
+ programData->fColorFilterColor = GrColor_ILLEGAL;
}
//============================================================================
@@ -522,16 +675,16 @@ GrGLuint GrGLProgram::CompileShader(GrGLenum type,
//============================================================================
void GrGLProgram::genStageCode(int stageNum,
- const GrGLProgram::ProgramDesc::StageDesc& desc,
- const char* fsInColor, // NULL means no incoming color
- const char* fsOutColor,
- const char* vsInCoord,
- ShaderCodeSegments* segments,
- StageUniLocations* locations) const {
+ const GrGLProgram::ProgramDesc::StageDesc& desc,
+ const char* fsInColor, // NULL means no incoming color
+ const char* fsOutColor,
+ const char* vsInCoord,
+ ShaderCodeSegments* segments,
+ StageUniLocations* locations) const {
GrAssert(stageNum >= 0 && stageNum <= 9);
- GrTokenString varyingName;
+ GrStringBuilder varyingName;
stage_varying_name(stageNum, &varyingName);
// First decide how many coords are needed to access the texture
@@ -543,20 +696,17 @@ void GrGLProgram::genStageCode(int stageNum,
// decide whether we need a matrix to transform texture coords
// and whether the varying needs a perspective coord.
- GrTokenString texMName;
+ GrStringBuilder texMName;
tex_matrix_name(stageNum, &texMName);
if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
- #if ATTRIBUTE_MATRIX
- segments->fVSAttrs += "attribute mat3 ";
- segments->fVSAttrs += texMName;
- segments->fVSAttrs += ";\n";
+ #if GR_GL_ATTRIBUTE_MATRICES
+ segments->fVSAttrs.appendf("attribute mat3 %s;\n", texMName.c_str());
+ locations->fTextureMatrixUni = kSetAsAttribute;
#else
- segments->fVSUnis += "uniform mat3 ";
- segments->fVSUnis += texMName;
- segments->fVSUnis += ";\n";
- locations->fTextureMatrixUni = 1;
+ segments->fVSUnis.appendf("uniform mat3 %s;\n", texMName.c_str());
+ locations->fTextureMatrixUni = kUseUniform;
#endif
if (desc.fOptFlags & ProgramDesc::StageDesc::kNoPerspective_OptFlagBit) {
varyingDims = coordDims;
@@ -565,217 +715,182 @@ void GrGLProgram::genStageCode(int stageNum,
}
}
- GrTokenString samplerName;
+ GrStringBuilder samplerName;
sampler_name(stageNum, &samplerName);
- segments->fFSUnis += "uniform sampler2D ";
- segments->fFSUnis += samplerName;
- segments->fFSUnis += ";\n";
- locations->fSamplerUni = 1;
+ segments->fFSUnis.appendf("uniform sampler2D %s;\n", samplerName.c_str());
+ locations->fSamplerUni = kUseUniform;
+
+ GrStringBuilder texelSizeName;
+ if (ProgramDesc::StageDesc::k2x2_FetchMode == desc.fFetchMode) {
+ normalized_texel_size_name(stageNum, &texelSizeName);
+ segments->fFSUnis.appendf("uniform vec2 %s;\n", texelSizeName.c_str());
+ }
- segments->fVaryings += "varying ";
- segments->fVaryings += float_vector_type(varyingDims);
- segments->fVaryings += " ";
- segments->fVaryings += varyingName;
- segments->fVaryings += ";\n";
+ segments->fVaryings.appendf("varying %s %s;\n",
+ float_vector_type(varyingDims), varyingName.c_str());
if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
GrAssert(varyingDims == coordDims);
- segments->fVSCode += "\t";
- segments->fVSCode += varyingName;
- segments->fVSCode += " = ";
- segments->fVSCode += vsInCoord;
- segments->fVSCode += ";\n";
+ segments->fVSCode.appendf("\t%s = %s;\n", varyingName.c_str(), vsInCoord);
} else {
- segments->fVSCode += "\t";
- segments->fVSCode += varyingName;
- segments->fVSCode += " = (";
- segments->fVSCode += texMName;
- segments->fVSCode += " * vec3(";
- segments->fVSCode += vsInCoord;
- segments->fVSCode += ", 1))";
- segments->fVSCode += vector_all_coords(varyingDims);
- segments->fVSCode += ";\n";
- }
-
- GrTokenString radial2ParamsName;
+ // varying = texMatrix * texCoord
+ segments->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
+ varyingName.c_str(), texMName.c_str(),
+ vsInCoord, vector_all_coords(varyingDims));
+ }
+
+ GrStringBuilder radial2ParamsName;
radial2_param_name(stageNum, &radial2ParamsName);
// for radial grads without perspective we can pass the linear
// part of the quadratic as a varying.
- GrTokenString radial2VaryingName;
+ GrStringBuilder radial2VaryingName;
radial2_varying_name(stageNum, &radial2VaryingName);
if (ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
- segments->fVSUnis += "uniform ";
- segments->fVSUnis += GrPrecision();
- segments->fVSUnis += " float ";
- segments->fVSUnis += radial2ParamsName;
- segments->fVSUnis += "[6];\n";
-
- segments->fFSUnis += "uniform ";
- segments->fFSUnis += GrPrecision();
- segments->fFSUnis += " float ";
- segments->fFSUnis += radial2ParamsName;
- segments->fFSUnis += "[6];\n";
- locations->fRadial2Uni = 1;
+ segments->fVSUnis.appendf("uniform %s float %s[6];\n",
+ GrPrecision(), radial2ParamsName.c_str());
+ segments->fFSUnis.appendf("uniform float %s[6];\n",
+ radial2ParamsName.c_str());
+ locations->fRadial2Uni = kUseUniform;
// if there is perspective we don't interpolate this
if (varyingDims == coordDims) {
GrAssert(2 == coordDims);
- segments->fVaryings += "varying float ";
- segments->fVaryings += radial2VaryingName;
- segments->fVaryings += ";\n";
-
- segments->fVSCode += "\t";
- segments->fVSCode += radial2VaryingName;
- segments->fVSCode += " = 2.0 * (";
- segments->fVSCode += radial2ParamsName;
- segments->fVSCode += "[2] * ";
- segments->fVSCode += varyingName;
- segments->fVSCode += ".x ";
- segments->fVSCode += " - ";
- segments->fVSCode += radial2ParamsName;
- segments->fVSCode += "[3]);\n";
+ segments->fVaryings.appendf("varying float %s;\n", radial2VaryingName.c_str());
+
+ // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
+ segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
+ radial2VaryingName.c_str(), radial2ParamsName.c_str(),
+ varyingName.c_str(), radial2ParamsName.c_str());
}
}
/// Fragment Shader Stuff
- GrTokenString fsCoordName;
+ GrStringBuilder fsCoordName;
// function used to access the shader, may be made projective
- GrTokenString texFunc("texture2D");
+ GrStringBuilder texFunc("texture2D");
if (desc.fOptFlags & (ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit |
ProgramDesc::StageDesc::kNoPerspective_OptFlagBit)) {
GrAssert(varyingDims == coordDims);
fsCoordName = varyingName;
} else {
- // if we have to do some non-matrix op on the varyings to get
+ // if we have to do some special op on the varyings to get
// our final tex coords then when in perspective we have to
- // do an explicit divide
- if (ProgramDesc::StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) {
- texFunc += "Proj";
+ // do an explicit divide. Otherwise, we can use a Proj func.
+ if (ProgramDesc::StageDesc::kIdentity_CoordMapping == desc.fCoordMapping &&
+ ProgramDesc::StageDesc::kSingle_FetchMode == desc.fFetchMode) {
+ texFunc.append("Proj");
fsCoordName = varyingName;
} else {
- fsCoordName = "tCoord";
- fsCoordName.appendInt(stageNum);
-
- segments->fFSCode += "\t";
- segments->fFSCode += float_vector_type(coordDims);
- segments->fFSCode += " ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += " = ";
- segments->fFSCode += varyingName;
- segments->fFSCode += vector_nonhomog_coords(varyingDims);
- segments->fFSCode += " / ";
- segments->fFSCode += varyingName;
- segments->fFSCode += vector_homog_coord(varyingDims);
- segments->fFSCode += ";\n";
+ fsCoordName = "inCoord";
+ fsCoordName.appendS32(stageNum);
+ segments->fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
+ float_vector_type(coordDims),
+ fsCoordName.c_str(),
+ varyingName.c_str(),
+ vector_nonhomog_coords(varyingDims),
+ varyingName.c_str(),
+ vector_homog_coord(varyingDims));
}
}
- GrSStringBuilder<96> sampleCoords;
+ GrStringBuilder sampleCoords;
+ bool complexCoord = false;
switch (desc.fCoordMapping) {
case ProgramDesc::StageDesc::kIdentity_CoordMapping:
sampleCoords = fsCoordName;
break;
case ProgramDesc::StageDesc::kSweepGradient_CoordMapping:
- sampleCoords = "vec2(atan(-";
- sampleCoords += fsCoordName;
- sampleCoords += ".y, -";
- sampleCoords += fsCoordName;
- sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)";
+ sampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", fsCoordName.c_str(), fsCoordName.c_str());
+ complexCoord = true;
break;
case ProgramDesc::StageDesc::kRadialGradient_CoordMapping:
- sampleCoords = "vec2(length(";
- sampleCoords += fsCoordName;
- sampleCoords += ".xy), 0.5)";
+ sampleCoords.printf("vec2(length(%s.xy), 0.5)", fsCoordName.c_str());
+ complexCoord = true;
break;
case ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping: {
- GrTokenString cName = "c";
- GrTokenString ac4Name = "ac4";
- GrTokenString rootName = "root";
+ GrStringBuilder cName("c");
+ GrStringBuilder ac4Name("ac4");
+ GrStringBuilder rootName("root");
- cName.appendInt(stageNum);
- ac4Name.appendInt(stageNum);
- rootName.appendInt(stageNum);
+ cName.appendS32(stageNum);
+ ac4Name.appendS32(stageNum);
+ rootName.appendS32(stageNum);
- GrTokenString bVar;
+ // if we were able to interpolate the linear component bVar is the varying
+ // otherwise compute it
+ GrStringBuilder bVar;
if (coordDims == varyingDims) {
bVar = radial2VaryingName;
GrAssert(2 == varyingDims);
} else {
GrAssert(3 == varyingDims);
bVar = "b";
- bVar.appendInt(stageNum);
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += bVar;
- segments->fFSCode += " = 2.0 * (";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[2] * ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ".x ";
- segments->fFSCode += " - ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[3]);\n";
+ bVar.appendS32(stageNum);
+ segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
+ bVar.c_str(), radial2ParamsName.c_str(),
+ fsCoordName.c_str(), radial2ParamsName.c_str());
}
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += cName;
- segments->fFSCode += " = dot(";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ", ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ") + ";
- segments->fFSCode += " - ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[4];\n";
-
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += ac4Name;
- segments->fFSCode += " = ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[0] * 4.0 * ";
- segments->fFSCode += cName;
- segments->fFSCode += ";\n";
-
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += rootName;
- segments->fFSCode += " = sqrt(abs(";
- segments->fFSCode += bVar;
- segments->fFSCode += " * ";
- segments->fFSCode += bVar;
- segments->fFSCode += " - ";
- segments->fFSCode += ac4Name;
- segments->fFSCode += "));\n";
-
- sampleCoords = "vec2((-";
- sampleCoords += bVar;
- sampleCoords += " + ";
- sampleCoords += radial2ParamsName;
- sampleCoords += "[5] * ";
- sampleCoords += rootName;
- sampleCoords += ") * ";
- sampleCoords += radial2ParamsName;
- sampleCoords += "[1], 0.5)\n";
+ // c = (x^2)+(y^2) - params[4]
+ segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
+ cName.c_str(), fsCoordName.c_str(),
+ fsCoordName.c_str(),
+ radial2ParamsName.c_str());
+ // ac4 = 4.0 * params[0] * c
+ segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n",
+ ac4Name.c_str(), radial2ParamsName.c_str(),
+ cName.c_str());
+
+ // root = sqrt(b^2-4ac)
+ // (abs to avoid exception due to fp precision)
+ segments->fFSCode.appendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n",
+ rootName.c_str(), bVar.c_str(), bVar.c_str(),
+ ac4Name.c_str());
+
+ // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
+ // y coord is 0.5 (texture is effectively 1D)
+ sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)",
+ bVar.c_str(), radial2ParamsName.c_str(),
+ rootName.c_str(), radial2ParamsName.c_str());
+ complexCoord = true;
break;}
};
- segments->fFSCode += "\t";
- segments->fFSCode += fsOutColor;
- segments->fFSCode += " = ";
- if (NULL != fsInColor) {
- segments->fFSCode += fsInColor;
- segments->fFSCode += " * ";
- }
- segments->fFSCode += texFunc;
- segments->fFSCode += "(";
- segments->fFSCode += samplerName;
- segments->fFSCode += ", ";
- segments->fFSCode += sampleCoords;
- segments->fFSCode += ")";
+ const char* smear;
if (desc.fModulation == ProgramDesc::StageDesc::kAlpha_Modulation) {
- segments->fFSCode += ".aaaa";
+ smear = ".aaaa";
+ } else {
+ smear = "";
+ }
+ GrStringBuilder modulate;
+ if (NULL != fsInColor) {
+ modulate.printf(" * %s", fsInColor);
+ }
+
+ if (ProgramDesc::StageDesc::k2x2_FetchMode == desc.fFetchMode) {
+ locations->fNormalizedTexelSizeUni = kUseUniform;
+ if (complexCoord) {
+ // assign the coord to a var rather than compute 4x.
+ GrStringBuilder coordVar("tCoord");
+ coordVar.appendS32(stageNum);
+ segments->fFSCode.appendf("\t%s %s = %s;\n",
+ float_vector_type(coordDims),
+ coordVar.c_str(), sampleCoords.c_str());
+ sampleCoords = coordVar;
+ }
+ GrAssert(2 == coordDims);
+ GrStringBuilder accumVar("accum");
+ accumVar.appendS32(stageNum);
+ segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+ segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+ segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+ segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+ segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
+ } else {
+ segments->fFSCode.appendf("\t%s = %s(%s, %s)%s %s;\n", fsOutColor, texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), smear, modulate.c_str());
}
- segments->fFSCode += ";\n";
if(fStageEffects[stageNum]) {
fStageEffects[stageNum]->genShaderCode(segments);
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index 1a15953..1611ca2 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -18,13 +18,11 @@
#define GrGLProgram_DEFINED
#include "GrGLInterface.h"
-
-#define POS_ATTR_LOCATION 0
-#define TEX_ATTR_LOCATION(X) (1 + (X))
-#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
-
+#include "GrStringBuilder.h"
#include "GrDrawTarget.h"
+#include "SkXfermode.h"
+
class GrBinHashKeyBuilder;
class GrGLEffect;
struct ShaderCodeSegments;
@@ -58,7 +56,7 @@ public:
* The result of heavy init is not stored in datamembers of GrGLProgam,
* but in a separate cacheable container.
*/
- void genProgram(CachedData* programData, const GrDrawTarget* target) const;
+ bool genProgram(CachedData* programData) const;
/**
* Routine that is called before rendering. Sets-up all the state and
@@ -80,20 +78,39 @@ public:
*/
void buildFromTarget(const GrDrawTarget* target);
+ static int PositionAttributeIdx() { return 0; }
+ static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
+ static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; }
+ static int ViewMatrixAttributeIdx() {
+ return 2 + GrDrawTarget::kMaxTexCoords;
+ }
+ static int TextureMatrixAttributeIdx(int stage) {
+ return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage;
+ }
+
private:
//Parameters that affect code generation
struct ProgramDesc {
+ ProgramDesc() {
+ // since we use this as part of a key we can't have any unitialized
+ // padding
+ memset(this, 0, sizeof(ProgramDesc));
+ }
+
+ // stripped of bits that don't affect prog generation
GrVertexLayout fVertexLayout;
enum {
- kNotPoints_OptFlagBit = 0x1,
- kVertexColorAllOnes_OptFlagBit = 0x2,
- };
- // we're assuming optflags and layout pack into 32 bits
- // VS 2010 seems to require short rather than just unsigned
- // for this to pack
- unsigned short fOptFlags : 16;
+ kNone_ColorType = 0,
+ kAttribute_ColorType = 1,
+ kUniform_ColorType = 2,
+ } fColorType;
+
+ bool fEmitsPointSize;
+ bool fUsesEdgeAA;
+
+ SkXfermode::Mode fColorFilterXfermode;
struct StageDesc {
enum OptFlagBits {
@@ -101,33 +118,64 @@ private:
kIdentityMatrix_OptFlagBit = 0x2
};
- unsigned fOptFlags : 8;
- unsigned fEnabled : 8;
+ unsigned fOptFlags;
+ bool fEnabled;
enum Modulation {
kColor_Modulation,
kAlpha_Modulation
- } fModulation : 8;
+ } fModulation;
+
+ enum FetchMode {
+ kSingle_FetchMode,
+ k2x2_FetchMode
+ } fFetchMode;
enum CoordMapping {
kIdentity_CoordMapping,
kRadialGradient_CoordMapping,
kSweepGradient_CoordMapping,
kRadial2Gradient_CoordMapping
- } fCoordMapping : 8;
+ } fCoordMapping;
} fStages[GrDrawTarget::kNumStages];
} fProgramDesc;
+ const ProgramDesc& getDesc() { return fProgramDesc; }
+
public:
+ enum {
+ kUnusedUniform = -1,
+ kSetAsAttribute = 1000,
+ };
+
struct StageUniLocations {
GrGLint fTextureMatrixUni;
+ GrGLint fNormalizedTexelSizeUni;
GrGLint fSamplerUni;
GrGLint fRadial2Uni;
+ void reset() {
+ fTextureMatrixUni = kUnusedUniform;
+ fNormalizedTexelSizeUni = kUnusedUniform;
+ fSamplerUni = kUnusedUniform;
+ fRadial2Uni = kUnusedUniform;
+ }
};
struct UniLocations {
GrGLint fViewMatrixUni;
+ GrGLint fColorUni;
+ GrGLint fEdgesUni;
+ GrGLint fColorFilterUni;
StageUniLocations fStages[GrDrawTarget::kNumStages];
+ void reset() {
+ fViewMatrixUni = kUnusedUniform;
+ fColorUni = kUnusedUniform;
+ fEdgesUni = kUnusedUniform;
+ fColorFilterUni = kUnusedUniform;
+ for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+ fStages[s].reset();
+ }
+ }
};
class CachedData : public ::GrNoncopyable {
@@ -142,7 +190,7 @@ public:
}
void copyAndTakeOwnership(CachedData& other) {
- memcpy(this, &other, sizeof(this));
+ memcpy(this, &other, sizeof(*this));
other.fEffectUniLocationsExtended = NULL; // ownership transfer
GR_DEBUGCODE(other.fEffectUniCount = 0;)
}
@@ -177,7 +225,12 @@ public:
// these reflect the current values of uniforms
// (GL uniform values travel with program)
+ GrColor fColor;
+ GrColor fColorFilterColor;
GrMatrix fTextureMatrices[GrDrawTarget::kNumStages];
+ // width and height used for normalized texel size
+ int fTextureWidth[GrDrawTarget::kNumStages];
+ int fTextureHeight[GrDrawTarget::kNumStages];
GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages];
GrScalar fRadial2Radius0[GrDrawTarget::kNumStages];
bool fRadial2PosRoot[GrDrawTarget::kNumStages];
@@ -195,6 +248,12 @@ public:
GrGLEffect* fStageEffects[GrDrawTarget::kNumStages];
private:
+ enum {
+ kUseUniform = 2000
+ };
+
+ // should set all fields in locations var to kUseUniform if the
+ // corresponding uniform is required for the program.
void genStageCode(int stageNum,
const ProgramDesc::StageDesc& desc,
const char* fsInColor, // NULL means no incoming color
@@ -203,12 +262,24 @@ private:
ShaderCodeSegments* segments,
StageUniLocations* locations) const;
+ static bool CompileFSAndVS(const ShaderCodeSegments& segments,
+ CachedData* programData);
+
// Compiles a GL shader, returns shader ID or 0 if failed
// params have same meaning as glShaderSource
static GrGLuint CompileShader(GrGLenum type, int stringCnt,
const char** strings,
int* stringLengths);
+ // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
+ // links the program
+ bool bindAttribsAndLinkProgram(GrStringBuilder texCoordAttrNames[GrDrawTarget::kMaxTexCoords],
+ CachedData* programData) const;
+
+ // Gets locations for all uniforms set to kUseUniform and initializes cache
+ // to invalid values.
+ void getUniformLocationsAndInitCache(CachedData* programData) const;
+
friend class GrGpuGLShaders;
};
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index 3c6504d..d3ccfa6 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -33,7 +33,6 @@ GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
fTexFBOID = ids.fTexFBOID;
fStencilRenderbufferID = ids.fStencilRenderbufferID;
fMSColorRenderbufferID = ids.fMSColorRenderbufferID;
- fNeedsResolve = false;
fViewport = viewport;
fOwnIDs = ids.fOwnIDs;
fTexIDObj = texID;
diff --git a/gpu/src/GrGLUtil.cpp b/gpu/src/GrGLUtil.cpp
index 5234453..04e25fd 100644
--- a/gpu/src/GrGLUtil.cpp
+++ b/gpu/src/GrGLUtil.cpp
@@ -43,6 +43,11 @@ void GrGLRestoreResetRowLength() {
///////////////////////////////////////////////////////////////////////////////
-bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
+#if GR_GL_LOG_CALLS
+ bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
+#endif
+
+#if GR_GL_CHECK_ERROR
+ bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
+#endif
-bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 43fe648..9950afd 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -136,7 +136,7 @@ void GrGpu::unimpl(const char msg[]) {
////////////////////////////////////////////////////////////////////////////////
-GrTexture* GrGpu::createTexture(const TextureDesc& desc,
+GrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
const void* srcData, size_t rowBytes) {
this->handleDirtyContext();
return this->onCreateTexture(desc, srcData, rowBytes);
@@ -173,9 +173,9 @@ GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
return this->onCreateIndexBuffer(size, dynamic);
}
-void GrGpu::eraseColor(GrColor color) {
+void GrGpu::clear(const GrIRect* rect, GrColor color) {
this->handleDirtyContext();
- this->onEraseColor(color);
+ this->onClear(rect, color);
}
void GrGpu::forceRenderTargetFlush() {
@@ -238,10 +238,16 @@ const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
if (NULL == fUnitSquareVertexBuffer) {
static const GrPoint DATA[] = {
+ { 0, 0 },
+ { GR_Scalar1, 0 },
+ { GR_Scalar1, GR_Scalar1 },
+ { 0, GR_Scalar1 }
+#if 0
GrPoint(0, 0),
GrPoint(GR_Scalar1,0),
GrPoint(GR_Scalar1,GR_Scalar1),
GrPoint(0, GR_Scalar1)
+#endif
};
static const size_t SIZE = sizeof(DATA);
@@ -393,7 +399,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
if (fClip.hasConservativeBounds()) {
bounds = fClip.getConservativeBounds();
- bounds.intersectWith(rtRect);
+ if (!bounds.intersect(rtRect)) {
+ bounds.setEmpty();
+ }
} else {
bounds = rtRect;
}
@@ -423,7 +431,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
AutoInternalDrawGeomRestore aidgr(this);
this->setViewMatrix(GrMatrix::I());
- this->eraseStencilClip(clipRect);
+ this->clearStencilClip(clipRect);
this->flushScissor(NULL);
#if !VISUALIZE_COMPLEX_CLIP
this->enableState(kNoColorWrites_StateBit);
@@ -725,7 +733,7 @@ void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) {
////////////////////////////////////////////////////////////////////////////////
-const GrGpu::Stats& GrGpu::getStats() const {
+const GrGpuStats& GrGpu::getStats() const {
return fStats;
}
@@ -755,7 +763,7 @@ const GrSamplerState GrSamplerState::gClampNoFilter(
GrSamplerState::kClamp_WrapMode,
GrSamplerState::kNormal_SampleMode,
GrMatrix::I(),
- false);
+ GrSamplerState::kNearest_Filter);
diff --git a/gpu/src/GrGpuFactory.cpp b/gpu/src/GrGpuFactory.cpp
index 1715333..38c07b7 100644
--- a/gpu/src/GrGpuFactory.cpp
+++ b/gpu/src/GrGpuFactory.cpp
@@ -26,12 +26,11 @@
#include "GrGpu.h"
#include "GrGpuGLFixed.h"
#include "GrGpuGLShaders.h"
-#include "GrGpuGLShaders2.h"
-GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) {
+GrGpu* GrGpu::Create(GrEngine engine, GrPlatform3DContext context3D) {
- if (kOpenGL_Shaders_Engine == engine ||
- kOpenGL_Fixed_Engine == engine) {
+ if (kOpenGL_Shaders_GrEngine == engine ||
+ kOpenGL_Fixed_GrEngine == engine) {
// If no GL bindings have been installed, fall-back to calling the
// GL functions that have been linked with the executable.
if (!GrGLGetGLInterface()) {
@@ -41,27 +40,33 @@ GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) {
return NULL;
}
}
+ if (!GrGLGetGLInterface()->validate(engine)) {
+#if GR_DEBUG
+ GrPrintf("Failed GL interface validation!");
+#endif
+ return NULL;
+ }
}
GrGpu* gpu = NULL;
switch (engine) {
- case kOpenGL_Shaders_Engine:
- GrAssert(NULL == context3D);
+ case kOpenGL_Shaders_GrEngine:
+ GrAssert(NULL == (void*)context3D);
{
-#if GR_USE_NEW_GLSHADERS
- gpu = new GrGpuGLShaders;
-#else
+#if 0 // old code path, will be removed soon
gpu = new GrGpuGLShaders2;
+#else
+ gpu = new GrGpuGLShaders;
#endif
}
break;
- case kOpenGL_Fixed_Engine:
- GrAssert(NULL == context3D);
+ case kOpenGL_Fixed_GrEngine:
+ GrAssert(NULL == (void*)context3D);
gpu = new GrGpuGLFixed;
break;
- case kDirect3D9_Engine:
- GrAssert(NULL != context3D);
+ case kDirect3D9_GrEngine:
+ GrAssert(NULL != (void*)context3D);
#if GR_WIN32_BUILD
// gpu = new GrGpuD3D9((IDirect3DDevice9*)context3D);
#endif
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index fe461cc..e8c7afb 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -223,10 +223,10 @@ GrGpuGL::GrGpuGL() {
GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
}
- GR_STATIC_ASSERT(0 == kNone_AALevel);
- GR_STATIC_ASSERT(1 == kLow_AALevel);
- GR_STATIC_ASSERT(2 == kMed_AALevel);
- GR_STATIC_ASSERT(3 == kHigh_AALevel);
+ GR_STATIC_ASSERT(0 == kNone_GrAALevel);
+ GR_STATIC_ASSERT(1 == kLow_GrAALevel);
+ GR_STATIC_ASSERT(2 == kMed_GrAALevel);
+ GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
memset(fAASamples, 0, sizeof(fAASamples));
fMSFBOType = kNone_MSFBO;
@@ -268,19 +268,20 @@ GrGpuGL::GrGpuGL() {
GrGLint maxSamples;
GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
if (maxSamples > 1 ) {
- fAASamples[kNone_AALevel] = 0;
- fAASamples[kLow_AALevel] = GrMax(2,
- GrFixedFloorToInt((GR_FixedHalf) *
- maxSamples));
- fAASamples[kMed_AALevel] = GrMax(2,
- GrFixedFloorToInt(((GR_Fixed1*3)/4) *
- maxSamples));
- fAASamples[kHigh_AALevel] = maxSamples;
+ fAASamples[kNone_GrAALevel] = 0;
+ fAASamples[kLow_GrAALevel] = GrMax(2,
+ GrFixedFloorToInt((GR_FixedHalf) *
+ maxSamples));
+ fAASamples[kMed_GrAALevel] = GrMax(2,
+ GrFixedFloorToInt(((GR_Fixed1*3)/4) *
+ maxSamples));
+ fAASamples[kHigh_GrAALevel] = maxSamples;
}
if (gPrintStartupSpew) {
GrPrintf("\tMax Samples: %d\n", maxSamples);
}
}
+ fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
if (GR_GL_SUPPORT_DESKTOP) {
fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
@@ -361,6 +362,8 @@ GrGpuGL::GrGpuGL() {
}
}
+ fAALineSupport = GR_GL_SUPPORT_DESKTOP;
+
////////////////////////////////////////////////////////////////////////////
// Experiments to determine limitations that can't be queried. TODO: Make
// these a preprocess that generate some compile time constants.
@@ -527,8 +530,7 @@ void GrGpuGL::resetContext() {
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.fVertexBuffer = NULL;
- GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
- GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
+
fHWGeometryState.fArrayPtrsDirty = true;
GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
@@ -699,7 +701,7 @@ static size_t as_size_t(int x) {
}
#endif
-GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
+GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) {
@@ -726,7 +728,7 @@ GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
glDesc.fFormat = desc.fFormat;
glDesc.fOwnsID = true;
- bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
+ bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
if (!canBeTexture(desc.fFormat,
&internalFormat,
&glDesc.fUploadFormat,
@@ -736,7 +738,7 @@ GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
GrGLint samples = fAASamples[desc.fAALevel];
- if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
+ if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
GrPrintf("AA RT requested but not supported on this platform.");
}
@@ -813,7 +815,7 @@ GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
GrAssert(desc.fWidth == glDesc.fAllocWidth);
GrAssert(desc.fHeight == glDesc.fAllocHeight);
GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
- kColorTableSize;
+ kGrColorTableSize;
GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
glDesc.fAllocWidth, glDesc.fAllocHeight,
0, imageSize, srcData));
@@ -930,7 +932,7 @@ GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
} else {
rtIDs.fRTFBOID = rtIDs.fTexFBOID;
}
- if (!(kNoStencil_TextureFlag & desc.fFlags)) {
+ if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
GrAssert(0 != rtIDs.fStencilRenderbufferID);
}
@@ -1077,10 +1079,10 @@ GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
fHWDrawState.fRenderTarget = NULL;
// clear the new stencil buffer if we have one
- if (!(desc.fFlags & kNoStencil_TextureFlag)) {
+ if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
fCurrDrawState.fRenderTarget = rt;
- eraseStencil(0, ~0);
+ this->clearStencil(0, ~0);
fCurrDrawState.fRenderTarget = rtSave;
}
}
@@ -1165,15 +1167,24 @@ void GrGpuGL::flushScissor(const GrIRect* rect) {
}
}
-void GrGpuGL::onEraseColor(GrColor color) {
+void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
if (NULL == fCurrDrawState.fRenderTarget) {
return;
}
- flushRenderTarget();
- if (fHWBounds.fScissorEnabled) {
- GR_GL(Disable(GR_GL_SCISSOR_TEST));
- fHWBounds.fScissorEnabled = false;
+ GrIRect r;
+ if (NULL != rect) {
+ // flushScissor expects rect to be clipped to the target.
+ r = *rect;
+ GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
+ fCurrDrawState.fRenderTarget->height());
+ if (r.intersect(rtRect)) {
+ rect = &r;
+ } else {
+ return;
+ }
}
+ this->flushRenderTarget(rect);
+ this->flushScissor(rect);
GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
@@ -1183,11 +1194,13 @@ void GrGpuGL::onEraseColor(GrColor color) {
GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
}
-void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
+void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
if (NULL == fCurrDrawState.fRenderTarget) {
return;
}
- flushRenderTarget();
+
+ this->flushRenderTarget(&GrIRect::EmptyIRect());
+
if (fHWBounds.fScissorEnabled) {
GR_GL(Disable(GR_GL_SCISSOR_TEST));
fHWBounds.fScissorEnabled = false;
@@ -1198,7 +1211,7 @@ void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
fHWDrawState.fStencilSettings.invalidate();
}
-void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
+void GrGpuGL::clearStencilClip(const GrIRect& rect) {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
#if 0
GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
@@ -1212,7 +1225,7 @@ void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
// zero the client's clip bits. So we just clear the whole thing.
static const GrGLint clipStencilMask = ~0;
#endif
- flushRenderTarget();
+ this->flushRenderTarget(&GrIRect::EmptyIRect());
flushScissor(&rect);
GR_GL(StencilMask(clipStencilMask));
GR_GL(ClearStencil(0));
@@ -1221,7 +1234,7 @@ void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
}
void GrGpuGL::onForceRenderTargetFlush() {
- flushRenderTarget();
+ this->flushRenderTarget(&GrIRect::EmptyIRect());
}
bool GrGpuGL::onReadPixels(GrRenderTarget* target,
@@ -1241,10 +1254,10 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
case GrGLRenderTarget::kAutoResolves_ResolveType:
autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
fCurrDrawState.fRenderTarget = target;
- flushRenderTarget();
+ this->flushRenderTarget(&GrIRect::EmptyIRect());
break;
case GrGLRenderTarget::kCanResolve_ResolveType:
- resolveRenderTarget(tgt);
+ this->resolveRenderTarget(tgt);
// we don't track the state of the READ FBO ID.
GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
break;
@@ -1282,17 +1295,16 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
return true;
}
-void GrGpuGL::flushRenderTarget() {
+void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
+ GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
- GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
#if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt;
#endif
- rt->flagAsNeedingResolve();
#if GR_DEBUG
GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
@@ -1307,6 +1319,9 @@ void GrGpuGL::flushRenderTarget() {
fHWBounds.fViewportRect = vp;
}
}
+ if (NULL == bound || !bound->isEmpty()) {
+ rt->flagAsNeedingResolve(bound);
+ }
}
GrGLenum gPrimitiveType2GLMode[] = {
@@ -1416,12 +1431,16 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
// the bound DRAW FBO ID.
fHWDrawState.fRenderTarget = NULL;
const GrGLIRect& vp = rt->getViewport();
+ const GrIRect dirtyRect = rt->getResolveRect();
+ GrGLIRect r;
+ r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
+ dirtyRect.width(), dirtyRect.height());
if (kAppleES_MSFBO == fMSFBOType) {
// Apple's extension uses the scissor as the blit bounds.
GR_GL(Enable(GR_GL_SCISSOR_TEST));
- GR_GL(Scissor(vp.fLeft, vp.fBottom,
- vp.fWidth, vp.fHeight));
+ GR_GL(Scissor(r.fLeft, r.fBottom,
+ r.fWidth, r.fHeight));
GR_GL(ResolveMultisampleFramebuffer());
fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = true;
@@ -1431,10 +1450,10 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
flushScissor(NULL);
}
- int right = vp.fLeft + vp.fWidth;
- int top = vp.fBottom + vp.fHeight;
- GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
- vp.fLeft, vp.fBottom, right, top,
+ int right = r.fLeft + r.fWidth;
+ int top = r.fBottom + r.fHeight;
+ GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
+ r.fLeft, r.fBottom, right, top,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
}
rt->flagAsResolved();
@@ -1703,81 +1722,87 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
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);
- }
+ // 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;
- }
+ 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);
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+ const GrGLTexture::TexParams& oldTexParams =
+ nextTexture->getTexParams();
+ GrGLTexture::TexParams newTexParams;
- // The texture matrix has to compensate for texture width/height
- // and NPOT-embedded-in-POT
- fDirtyFlags.fTextureChangedMask |= (1 << s);
+ if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
+ newTexParams.fFilter = GR_GL_NEAREST;
} else {
- GrAssert(!"Rendering with texture vert flag set but no texture");
- return false;
+ newTexParams.fFilter = GR_GL_LINEAR;
+ }
+
+ 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);
}
}
- flushRenderTarget();
- flushAAState(type);
- flushBlend(type);
+ GrIRect* rect = NULL;
+ GrIRect clipBounds;
+ if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
+ fClip.hasConservativeBounds()) {
+ fClip.getConservativeBounds().roundOut(&clipBounds);
+ rect = &clipBounds;
+ }
+ this->flushRenderTarget(rect);
+ this->flushAAState(type);
+ this->flushBlend(type);
if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
(fHWDrawState.fFlagBits & kDither_StateBit)) {
@@ -1821,7 +1846,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
#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/GrGpuGL.h b/gpu/src/GrGpuGL.h
index eaeec5e..da955cf 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -27,10 +27,11 @@
class GrGpuGL : public GrGpu {
public:
- GrGpuGL();
virtual ~GrGpuGL();
protected:
+ GrGpuGL();
+
struct {
size_t fVertexOffset;
GrVertexLayout fVertexLayout;
@@ -72,7 +73,7 @@ protected:
// overrides from GrGpu
virtual void resetContext();
- virtual GrTexture* onCreateTexture(const TextureDesc& desc,
+ virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes);
virtual GrVertexBuffer* onCreateVertexBuffer(uint32_t size,
@@ -87,7 +88,7 @@ protected:
int width, int height);
virtual GrRenderTarget* onCreateRenderTargetFrom3DApiState();
- virtual void onEraseColor(GrColor color);
+ virtual void onClear(const GrIRect* rect, GrColor color);
virtual void onForceRenderTargetFlush();
@@ -104,8 +105,8 @@ protected:
uint32_t vertexCount,
uint32_t numVertices);
virtual void flushScissor(const GrIRect* rect);
- void eraseStencil(uint32_t value, uint32_t mask);
- virtual void eraseStencilClip(const GrIRect& rect);
+ void clearStencil(uint32_t value, uint32_t mask);
+ virtual void clearStencilClip(const GrIRect& rect);
// binds texture unit in GL
void setTextureUnit(int unitIdx);
@@ -140,6 +141,7 @@ protected:
static bool BlendCoefReferencesConstant(GrBlendCoeff coeff);
private:
+
// notify callbacks to update state tracking when related
// objects are bound to GL or deleted outside of the class
void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
@@ -153,7 +155,9 @@ private:
bool useSmoothLines();
- void flushRenderTarget();
+ // bound is region that may be modified and therefore has to be resolved.
+ // NULL means whole target. Can be an empty rect.
+ void flushRenderTarget(const GrIRect* bound);
void flushStencil();
void flushAAState(GrPrimitiveType type);
void flushBlend(GrPrimitiveType type);
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 446949f..e197a82 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -32,17 +32,17 @@ struct GrGpuMatrix {
void set(const GrMatrix& m) {
Gr_bzero(fMat, sizeof(fMat));
- fMat[0] = GrScalarToFloat(m[GrMatrix::kScaleX]);
- fMat[4] = GrScalarToFloat(m[GrMatrix::kSkewX]);
- fMat[12] = GrScalarToFloat(m[GrMatrix::kTransX]);
+ fMat[0] = GrScalarToFloat(m[GrMatrix::kMScaleX]);
+ fMat[4] = GrScalarToFloat(m[GrMatrix::kMSkewX]);
+ fMat[12] = GrScalarToFloat(m[GrMatrix::kMTransX]);
- fMat[1] = GrScalarToFloat(m[GrMatrix::kSkewY]);
- fMat[5] = GrScalarToFloat(m[GrMatrix::kScaleY]);
- fMat[13] = GrScalarToFloat(m[GrMatrix::kTransY]);
+ fMat[1] = GrScalarToFloat(m[GrMatrix::kMSkewY]);
+ fMat[5] = GrScalarToFloat(m[GrMatrix::kMScaleY]);
+ fMat[13] = GrScalarToFloat(m[GrMatrix::kMTransY]);
- fMat[3] = GrScalarToFloat(m[GrMatrix::kPersp0]);
- fMat[7] = GrScalarToFloat(m[GrMatrix::kPersp1]);
- fMat[15] = GrScalarToFloat(m[GrMatrix::kPersp2]);
+ fMat[3] = GrScalarToFloat(m[GrMatrix::kMPersp0]);
+ fMat[7] = GrScalarToFloat(m[GrMatrix::kMPersp1]);
+ fMat[15] = GrScalarToFloat(m[GrMatrix::kMPersp2]);
fMat[10] = 1.f; // z-scale
}
@@ -56,6 +56,7 @@ static const GrGLenum gMatrixMode2Enum[] = {
///////////////////////////////////////////////////////////////////////////////
GrGpuGLFixed::GrGpuGLFixed() {
+ f4X4DownsampleFilterSupport = false;
}
GrGpuGLFixed::~GrGpuGLFixed() {
@@ -127,8 +128,7 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
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 +152,7 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
}
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 b34fc33..8965b06 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -22,18 +22,11 @@
#include "GrMemory.h"
#include "GrNoncopyable.h"
#include "GrStringBuilder.h"
+#include "GrRandom.h"
-#define ATTRIBUTE_MATRIX 0
-#define PRINT_SHADERS 0
#define SKIP_CACHE_CHECK true
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
-#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
-#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
-#define BOGUS_MATRIX_UNI_LOCATION 1000
-#endif
-
#include "GrTHashCache.h"
class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable {
@@ -43,17 +36,16 @@ private:
#if GR_DEBUG
typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug
#else
- typedef GrBinHashKey<Entry, 32> ProgramHashKey;
+ typedef GrBinHashKey<Entry, 64> ProgramHashKey;
#endif
class Entry : public ::GrNoncopyable {
public:
Entry() {}
- private:
void copyAndTakeOwnership(Entry& entry) {
fProgramData.copyAndTakeOwnership(entry.fProgramData);
fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer
- fLRUStamp = entry.fLRUStamp;
+ fLRUStamp = entry.fLRUStamp;
}
public:
@@ -67,6 +59,8 @@ private:
GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
+ // We may have kMaxEntries+1 shaders in the GL context because
+ // we create a new shader before evicting from the cache.
enum {
kMaxEntries = 32
};
@@ -97,14 +91,16 @@ public:
}
}
- GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc,
- const GrDrawTarget* target) {
- ProgramHashKey key;
- while (key.doPass()) {
- desc.buildKey(key);
+ GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) {
+ Entry newEntry;
+ while (newEntry.fKey.doPass()) {
+ desc.buildKey(newEntry.fKey);
}
- Entry* entry = fHashCache.find(key);
+ Entry* entry = fHashCache.find(newEntry.fKey);
if (NULL == entry) {
+ if (!desc.genProgram(&newEntry.fProgramData)) {
+ return NULL;
+ }
if (fCount < kMaxEntries) {
entry = fEntries + fCount;
++fCount;
@@ -119,8 +115,7 @@ public:
fHashCache.remove(entry->fKey, entry);
GrGpuGLShaders::DeleteProgram(&entry->fProgramData);
}
- entry->fKey.copyAndTakeOwnership(key);
- desc.genProgram(&entry->fProgramData, target);
+ entry->copyAndTakeOwnership(newEntry);
fHashCache.insert(entry->fKey, entry);
}
@@ -143,13 +138,99 @@ void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) {
GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));)
}
+void GrGpuGLShaders::ProgramUnitTest() {
+
+ static const int STAGE_OPTS[] = {
+ 0,
+ GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit,
+ GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping
+ };
+ static const GrGLProgram::ProgramDesc::StageDesc::Modulation STAGE_MODULATES[] = {
+ GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation,
+ GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation
+ };
+ static const GrGLProgram::ProgramDesc::StageDesc::CoordMapping STAGE_COORD_MAPPINGS[] = {
+ GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping,
+ GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping,
+ GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping,
+ GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping
+ };
+ static const GrGLProgram::ProgramDesc::StageDesc::FetchMode FETCH_MODES[] = {
+ GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode,
+ GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode,
+ };
+ GrGLProgram program;
+ GrGLProgram::ProgramDesc& pdesc = program.fProgramDesc;
+
+ static const int NUM_TESTS = 512;
+
+ // GrRandoms nextU() values have patterns in the low bits
+ // So using nextU() % array_count might never take some values.
+ GrRandom random;
+ for (int t = 0; t < NUM_TESTS; ++t) {
+
+ pdesc.fVertexLayout = 0;
+ pdesc.fEmitsPointSize = random.nextF() > .5f;
+ float colorType = random.nextF();
+ if (colorType < 1.f / 3.f) {
+ pdesc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
+ } else if (colorType < 2.f / 3.f) {
+ pdesc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
+ } else {
+ pdesc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
+ }
+ for (int s = 0; s < kNumStages; ++s) {
+ // enable the stage?
+ if (random.nextF() > .5f) {
+ // use separate tex coords?
+ if (random.nextF() > .5f) {
+ int t = (int)(random.nextF() * kMaxTexCoords);
+ pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
+ } else {
+ pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
+ }
+ }
+ // use text-formatted verts?
+ if (random.nextF() > .5f) {
+ pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
+ }
+ }
+
+ for (int s = 0; s < kNumStages; ++s) {
+ int x;
+ pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
+ x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
+ pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
+ x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
+ pdesc.fStages[s].fModulation = STAGE_MODULATES[x];
+ x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
+ pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[x];
+ x = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES));
+ pdesc.fStages[s].fFetchMode = FETCH_MODES[x];
+ }
+ GrGLProgram::CachedData cachedData;
+ program.genProgram(&cachedData);
+ DeleteProgram(&cachedData);
+ bool again = false;
+ if (again) {
+ program.genProgram(&cachedData);
+ DeleteProgram(&cachedData);
+ }
+ }
+}
+
GrGpuGLShaders::GrGpuGLShaders() {
resetContext();
+ f4X4DownsampleFilterSupport = true;
fProgramData = NULL;
fProgramCache = new ProgramCache();
+
+#if 0
+ ProgramUnitTest();
+#endif
}
GrGpuGLShaders::~GrGpuGLShaders() {
@@ -157,21 +238,24 @@ GrGpuGLShaders::~GrGpuGLShaders() {
}
const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
-#if ATTRIBUTE_MATRIX
- return fHWDrawState.fSamplerStates[stage].getMatrix();
-#else
GrAssert(fProgramData);
- return fProgramData->fTextureMatrices[stage];
-#endif
+
+ if (GrGLProgram::kSetAsAttribute ==
+ fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
+ return fHWDrawState.fSamplerStates[stage].getMatrix();
+ } else {
+ return fProgramData->fTextureMatrices[stage];
+ }
}
void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
-#if ATTRIBUTE_MATRIX
- fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
-#else
GrAssert(fProgramData);
- fProgramData->fTextureMatrices[stage] = matrix;
-#endif
+ if (GrGLProgram::kSetAsAttribute ==
+ fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
+ fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
+ } else {
+ fProgramData->fTextureMatrices[stage] = matrix;
+ }
}
void GrGpuGLShaders::resetContext() {
@@ -179,18 +263,19 @@ void GrGpuGLShaders::resetContext() {
fHWGeometryState.fVertexLayout = 0;
fHWGeometryState.fVertexOffset = ~0;
- GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
+ GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
for (int t = 0; t < kMaxTexCoords; ++t) {
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
+ GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
}
- GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
+ GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
fHWProgramID = 0;
}
void GrGpuGLShaders::flushViewMatrix() {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
- GrMatrix m (
+ GrMatrix m;
+ m.setAll(
GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
@@ -199,80 +284,187 @@ void GrGpuGLShaders::flushViewMatrix() {
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
+ m[GrMatrix::kMScaleX],
+ m[GrMatrix::kMSkewY],
+ m[GrMatrix::kMPersp0],
+ m[GrMatrix::kMSkewX],
+ m[GrMatrix::kMScaleY],
+ m[GrMatrix::kMPersp1],
+ m[GrMatrix::kMTransX],
+ m[GrMatrix::kMTransY],
+ m[GrMatrix::kMPersp2]
};
-#if ATTRIBUTE_MATRIX
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
-#else
- GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,1,false,mt));
-#endif
+
+ if (GrGLProgram::kSetAsAttribute ==
+ fProgramData->fUniLocations.fViewMatrixUni) {
+ int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
+ GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
+ GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
+ GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
+ } else {
+ GrAssert(GrGLProgram::kUnusedUniform !=
+ fProgramData->fUniLocations.fViewMatrixUni);
+ GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
+ 1, false, mt));
+ }
}
-void GrGpuGLShaders::flushTextureMatrix(int stage) {
- GrAssert(NULL != fCurrDrawState.fTextures[stage]);
+void GrGpuGLShaders::flushTextureMatrix(int s) {
+ const int& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+ if (NULL != texture) {
+ if (GrGLProgram::kUnusedUniform != uni &&
+ (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
+ getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[stage];
+ GrAssert(NULL != fCurrDrawState.fTextures[s]);
- GrMatrix m = getSamplerMatrix(stage);
- GrSamplerState::SampleMode mode =
- fCurrDrawState.fSamplerStates[0].getSampleMode();
- AdjustTextureMatrix(texture, mode, &m);
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
- // ES doesn't allow you to pass true to the transpose param,
- // so do our own transpose
- GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
- };
-#if ATTRIBUTE_MATRIX
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
-#else
- GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni,
- 1, false, mt));
-#endif
+ GrMatrix m = getSamplerMatrix(s);
+ GrSamplerState::SampleMode mode =
+ fCurrDrawState.fSamplerStates[s].getSampleMode();
+ AdjustTextureMatrix(texture, mode, &m);
+
+ // ES doesn't allow you to pass true to the transpose param,
+ // so do our own transpose
+ GrScalar mt[] = {
+ m[GrMatrix::kMScaleX],
+ m[GrMatrix::kMSkewY],
+ m[GrMatrix::kMPersp0],
+ m[GrMatrix::kMSkewX],
+ m[GrMatrix::kMScaleY],
+ m[GrMatrix::kMPersp1],
+ m[GrMatrix::kMTransX],
+ m[GrMatrix::kMTransY],
+ m[GrMatrix::kMPersp2]
+ };
+ if (GrGLProgram::kSetAsAttribute ==
+ fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
+ int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s);
+ GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
+ GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
+ GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
+ } else {
+ GR_GL(UniformMatrix3fv(uni, 1, false, mt));
+ }
+ recordHWSamplerMatrix(s, getSamplerMatrix(s));
+ }
+ }
}
-void GrGpuGLShaders::flushRadial2(int stage) {
+void GrGpuGLShaders::flushRadial2(int s) {
+
+ const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+ if (GrGLProgram::kUnusedUniform != uni &&
+ (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
+ fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
+ fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
+
+ GrScalar centerX1 = sampler.getRadial2CenterX1();
+ GrScalar radius0 = sampler.getRadial2Radius0();
+
+ GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
+
+ float values[6] = {
+ GrScalarToFloat(a),
+ 1 / (2.f * values[0]),
+ GrScalarToFloat(centerX1),
+ GrScalarToFloat(radius0),
+ GrScalarToFloat(GrMul(radius0, radius0)),
+ sampler.isRadial2PosRoot() ? 1.f : -1.f
+ };
+ GR_GL(Uniform1fv(uni, 6, values));
+ fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
+ fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0();
+ fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
+ }
+}
- const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage];
+void GrGpuGLShaders::flushTexelSize(int s) {
+ const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
+ if (GrGLProgram::kUnusedUniform != uni) {
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+ if (texture->allocWidth() != fProgramData->fTextureWidth[s] ||
+ texture->allocHeight() != fProgramData->fTextureWidth[s]) {
- GrScalar centerX1 = sampler.getRadial2CenterX1();
- GrScalar radius0 = sampler.getRadial2Radius0();
+ float texelSize[] = {1.f / texture->allocWidth(),
+ 1.f / texture->allocHeight()};
+ GR_GL(Uniform2fv(uni, 1, texelSize));
+ }
+ }
+}
- GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
+void GrGpuGLShaders::flushEdgeAAData() {
+ const int& uni = fProgramData->fUniLocations.fEdgesUni;
+ if (GrGLProgram::kUnusedUniform != uni) {
+ float edges[18];
+ memcpy(edges, fCurrDrawState.fEdgeAAEdges, sizeof(edges));
+ // Flip the edges in Y
+ float height = fCurrDrawState.fRenderTarget->height();
+ for (int i = 0; i < 6; ++i) {
+ float b = edges[i * 3 + 1];
+ edges[i * 3 + 1] = -b;
+ edges[i * 3 + 2] += b * height;
+ }
+ GR_GL(Uniform3fv(uni, 6, edges));
+ }
+}
- float unis[6] = {
- GrScalarToFloat(a),
- 1 / (2.f * unis[0]),
- GrScalarToFloat(centerX1),
- GrScalarToFloat(radius0),
- GrScalarToFloat(GrMul(radius0, radius0)),
- sampler.isRadial2PosRoot() ? 1.f : -1.f
- };
- GR_GL(Uniform1fv(fProgramData->fUniLocations.fStages[stage].fRadial2Uni,
- 6,
- unis));
+static const float ONE_OVER_255 = 1.f / 255.f;
+
+#define GR_COLOR_TO_VEC4(color) {\
+ GrColorUnpackR(color) * ONE_OVER_255,\
+ GrColorUnpackG(color) * ONE_OVER_255,\
+ GrColorUnpackB(color) * ONE_OVER_255,\
+ GrColorUnpackA(color) * ONE_OVER_255 \
+}
+
+void GrGpuGLShaders::flushColor() {
+ const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc();
+ if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
+ // color will be specified per-vertex as an attribute
+ // invalidate the const vertex attrib color
+ fHWDrawState.fColor = GrColor_ILLEGAL;
+ } else {
+ switch (desc.fColorType) {
+ case GrGLProgram::ProgramDesc::kAttribute_ColorType:
+ if (fHWDrawState.fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
+ GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
+ fHWDrawState.fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case GrGLProgram::ProgramDesc::kUniform_ColorType:
+ if (fProgramData->fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
+ GrAssert(GrGLProgram::kUnusedUniform !=
+ fProgramData->fUniLocations.fColorUni);
+ GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
+ fProgramData->fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case GrGLProgram::ProgramDesc::kNone_ColorType:
+ GrAssert(0xffffffff == fCurrDrawState.fColor);
+ break;
+ default:
+ GrCrash("Unknown color type.");
+ }
+ }
+ if (fProgramData->fUniLocations.fColorFilterUni
+ != GrGLProgram::kUnusedUniform
+ && fProgramData->fColorFilterColor
+ != fCurrDrawState.fColorFilterColor) {
+ float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
+ GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
+ fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
+ }
}
+
bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (!flushGLStateCommon(type)) {
return false;
@@ -281,33 +473,17 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (fDirtyFlags.fRenderTargetChanged) {
// our coords are in pixel space and the GL matrices map to NDC
// so if the viewport changed, our matrix is now wrong.
-#if ATTRIBUTE_MATRIX
fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
-#else
// we assume all shader matrices may be wrong after viewport changes
fProgramCache->invalidateViewMatrices();
-#endif
- }
-
- if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
- // invalidate the immediate mode color
- fHWDrawState.fColor = GrColor_ILLEGAL;
- } else {
- if (fHWDrawState.fColor != fCurrDrawState.fColor) {
- // OpenGL ES only supports the float varities of glVertexAttrib
- float c[] = {
- GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackA(fCurrDrawState.fColor) / 255.f
- };
- GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
- fHWDrawState.fColor = fCurrDrawState.fColor;
- }
}
buildProgram(type);
- fProgramData = fProgramCache->getProgramData(fCurrentProgram, this);
+ fProgramData = fProgramCache->getProgramData(fCurrentProgram);
+ if (NULL == fProgramData) {
+ GrAssert(!"Failed to create program!");
+ return false;
+ }
if (fHWProgramID != fProgramData->fProgramID) {
GR_GL(UseProgram(fProgramData->fProgramID));
@@ -318,41 +494,29 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
return false;
}
-#if ATTRIBUTE_MATRIX
- GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
-#else
- GrMatrix& currViewMatrix = fProgramData->fViewMatrix;
-#endif
+ this->flushColor();
- if (currViewMatrix != fCurrDrawState.fViewMatrix) {
+ GrMatrix* currViewMatrix;
+ if (GrGLProgram::kSetAsAttribute ==
+ fProgramData->fUniLocations.fViewMatrixUni) {
+ currViewMatrix = &fHWDrawState.fViewMatrix;
+ } else {
+ currViewMatrix = &fProgramData->fViewMatrix;
+ }
+
+ if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
flushViewMatrix();
- currViewMatrix = fCurrDrawState.fViewMatrix;
+ *currViewMatrix = fCurrDrawState.fViewMatrix;
}
for (int s = 0; s < kNumStages; ++s) {
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
- if (NULL != texture) {
- if (-1 != fProgramData->fUniLocations.fStages[s].fTextureMatrixUni &&
- (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
- getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
- flushTextureMatrix(s);
- recordHWSamplerMatrix(s, getSamplerMatrix(s));
- }
- }
+ this->flushTextureMatrix(s);
- const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
- if (-1 != fProgramData->fUniLocations.fStages[s].fRadial2Uni &&
- (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
- fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
- fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
+ this->flushRadial2(s);
- flushRadial2(s);
-
- fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
- fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0();
- fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
- }
+ this->flushTexelSize(s);
}
+ this->flushEdgeAAData();
resetDirtyFlags();
return true;
}
@@ -413,42 +577,43 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
fGeometrySrc.fVertexLayout)));
if (posAndTexChange) {
- GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
- false, newStride, (GrGLvoid*)vertexOffset));
+ int idx = GrGLProgram::PositionAttributeIdx();
+ GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
+ (GrGLvoid*)vertexOffset));
fHWGeometryState.fVertexOffset = vertexOffset;
}
for (int t = 0; t < kMaxTexCoords; ++t) {
if (newTexCoordOffsets[t] > 0) {
GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
+ int idx = GrGLProgram::TexCoordAttributeIdx(t);
if (oldTexCoordOffsets[t] <= 0) {
- GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordOffset));
+ GR_GL(EnableVertexAttribArray(idx));
+ GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
+ newStride, texCoordOffset));
} else if (posAndTexChange ||
newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordOffset));
+ GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
+ newStride, texCoordOffset));
}
} else if (oldTexCoordOffsets[t] > 0) {
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
+ GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
}
}
if (newColorOffset > 0) {
GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
+ int idx = GrGLProgram::ColorAttributeIdx();
if (oldColorOffset <= 0) {
- GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
- GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
- GR_GL_UNSIGNED_BYTE,
+ GR_GL(EnableVertexAttribArray(idx));
+ GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, colorOffset));
} else if (allOffsetsChange || newColorOffset != oldColorOffset) {
- GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
- GR_GL_UNSIGNED_BYTE,
+ GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, colorOffset));
}
} else if (oldColorOffset > 0) {
- GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
+ GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
}
fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
@@ -456,24 +621,40 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
}
void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
+ GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc;
+
// Must initialize all fields or cache will have false negatives!
- fCurrentProgram.fProgramDesc.fVertexLayout = fGeometrySrc.fVertexLayout;
+ desc.fVertexLayout = fGeometrySrc.fVertexLayout;
+
+ desc.fEmitsPointSize = kPoints_PrimitiveType == type;
+
+ bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
+ // fColorType records how colors are specified for the program. Strip
+ // the bit from the layout to avoid false negatives when searching for an
+ // existing program in the cache.
+ desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
- fCurrentProgram.fProgramDesc.fOptFlags = 0;
- if (kPoints_PrimitiveType != type) {
- fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kNotPoints_OptFlagBit;
- }
#if GR_AGGRESSIVE_SHADER_OPTS
- if (!(fCurrentProgram.fProgramDesc.fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
+ if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
+ desc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
+ } else
#endif
+#if GR_GL_NO_CONSTANT_ATTRIBUTES
+ if (!requiresAttributeColors) {
+ desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
+ } else
+#endif
+ {
+ if (requiresAttributeColors) {} // suppress unused var warning
+ desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
+ }
+
+ desc.fUsesEdgeAA = fCurrDrawState.fFlagBits & kEdgeAA_StateBit;
for (int s = 0; s < kNumStages; ++s) {
- GrGLProgram::ProgramDesc::StageDesc& stage = fCurrentProgram.fProgramDesc.fStages[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];
@@ -488,21 +669,36 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
stage.fOptFlags = 0;
}
switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
- case GrSamplerState::kNormal_SampleMode:
- stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping;
- break;
- case GrSamplerState::kRadial_SampleMode:
- stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping;
- break;
- case GrSamplerState::kRadial2_SampleMode:
- stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping;
- break;
- case GrSamplerState::kSweep_SampleMode:
- stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping;
- break;
- default:
- GrAssert(!"Unexpected sample mode!");
- break;
+ case GrSamplerState::kNormal_SampleMode:
+ stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping;
+ break;
+ case GrSamplerState::kRadial_SampleMode:
+ stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping;
+ break;
+ case GrSamplerState::kRadial2_SampleMode:
+ stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping;
+ break;
+ case GrSamplerState::kSweep_SampleMode:
+ stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping;
+ break;
+ default:
+ GrCrash("Unexpected sample mode!");
+ break;
+ }
+
+ switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
+ // these both can use a regular texture2D()
+ case GrSamplerState::kNearest_Filter:
+ case GrSamplerState::kBilinear_Filter:
+ stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode;
+ break;
+ // performs 4 texture2D()s
+ case GrSamplerState::k4x4Downsample_Filter:
+ stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode;
+ break;
+ default:
+ GrCrash("Unexpected filter!");
+ break;
}
if (GrPixelConfigIsAlphaOnly(texture->config())) {
@@ -524,6 +720,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
fCurrentProgram.fStageEffects[s] = NULL;
}
}
+ desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
}
diff --git a/gpu/src/GrGpuGLShaders.h b/gpu/src/GrGpuGLShaders.h
index ee29533..bb3024f 100644
--- a/gpu/src/GrGpuGLShaders.h
+++ b/gpu/src/GrGpuGLShaders.h
@@ -51,12 +51,21 @@ private:
// sets the texture matrix uniform for currently bound program
void flushTextureMatrix(int stage);
+ // sets the color specified by GrDrawTarget::setColor()
+ void flushColor();
+
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix();
// flushes the parameters to two point radial gradient
void flushRadial2(int stage);
+ // flushes the normalized texel size
+ void flushTexelSize(int stage);
+
+ // flushes the edges for edge AA
+ void flushEdgeAAData();
+
static void DeleteProgram(GrGLProgram::CachedData* programData);
void ProgramUnitTest();
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
deleted file mode 100644
index 4deecd4..0000000
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ /dev/null
@@ -1,1416 +0,0 @@
-/*
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-
-#include "GrGLConfig.h"
-
-#include "GrGpuGLShaders2.h"
-#include "GrGpuVertex.h"
-#include "GrMemory.h"
-#include "GrStringBuilder.h"
-
-
-#define ATTRIBUTE_MATRIX 0
-
-#define PRINT_SHADERS 0
-
-#define SKIP_CACHE_CHECK true
-
-#define POS_ATTR_LOCATION 0
-#define TEX_ATTR_LOCATION(X) (1 + X)
-#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
-#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
-#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
-#define BOGUS_MATRIX_UNI_LOCATION 1000
-#endif
-
-#define GR_UINT32_MAX static_cast<uint32_t>(-1)
-
-namespace {
-
-const char* GrPrecision() {
- if (GR_GL_SUPPORT_ES2) {
- return "mediump";
- } else {
- return "";
- }
-}
-
-const char* GrShaderPrecision() {
- if (GR_GL_SUPPORT_ES2) {
- return "precision mediump float;\n";
- } else {
- return "";
- }
-}
-
-} // namespace
-
-struct GrGpuGLShaders2::StageUniLocations {
- GrGLint fTextureMatrixUni;
- GrGLint fSamplerUni;
- GrGLint fRadial2Uni;
-};
-
-struct GrGpuGLShaders2::UniLocations {
- GrGLint fViewMatrixUni;
- StageUniLocations fStages[kNumStages];
-};
-
-// Records per-program information
-// we can specify the attribute locations so that they are constant
-// across our shaders. But the driver determines the uniform locations
-// at link time. We don't need to remember the sampler uniform location
-// because we will bind a texture slot to it and never change it
-// Uniforms are program-local so we can't rely on fHWState to hold the
-// previous uniform state after a program change.
-struct GrGpuGLShaders2::Program {
- // IDs
- GrGLuint fVShaderID;
- GrGLuint fFShaderID;
- GrGLuint fProgramID;
-
- // shader uniform locations (-1 if shader doesn't use them)
- UniLocations fUniLocations;
-
- // these reflect the current values of uniforms
- // (GL uniform values travel with program)
- GrMatrix fViewMatrix;
- GrMatrix fTextureMatrices[kNumStages];
- GrScalar fRadial2CenterX1[kNumStages];
- GrScalar fRadial2Radius0[kNumStages];
- bool fRadial2PosRoot[kNumStages];
-
-};
-
-// must be tightly packed
-struct GrGpuGLShaders2::StageDesc {
- enum OptFlagBits {
- kNoPerspective_OptFlagBit = 0x1,
- kIdentityMatrix_OptFlagBit = 0x2,
- };
- unsigned fOptFlags : 8;
-
- unsigned fEnabled : 8;
-
- enum Modulation {
- kColor_Modulation,
- kAlpha_Modulation,
- } fModulation : 8;
-
- enum CoordMapping {
- kIdentity_CoordMapping,
- kRadialGradient_CoordMapping,
- kSweepGradient_CoordMapping,
- kRadial2Gradient_CoordMapping,
- } fCoordMapping : 8;
-};
-
-// must be tightly packed
-struct GrGpuGLShaders2::ProgramDesc {
- GrVertexLayout fVertexLayout;
- GR_STATIC_ASSERT(2 == sizeof(GrVertexLayout)); // pack with next field
-
- enum {
- kNotPoints_OptFlagBit = 0x1,
- kVertexColorAllOnes_OptFlagBit = 0x2,
- };
- // we're assuming optflags and layout pack into 32 bits
- // VS 2010 seems to require short rather than just unsigned
- // for this to pack
- unsigned short fOptFlags : 16;
-
- StageDesc fStages[kNumStages];
-
- bool operator == (const ProgramDesc& desc) const {
- // keep 4-byte aligned and tightly packed
- GR_STATIC_ASSERT(4 == sizeof(StageDesc));
- GR_STATIC_ASSERT(2 + 2 + 4 * kNumStages == sizeof(ProgramDesc));
- return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
- }
-};
-
-#include "GrTHashCache.h"
-
-class GrGpuGLShaders2::ProgramCache : public ::GrNoncopyable {
-private:
- struct Entry;
- class HashKey {
- public:
- HashKey();
- HashKey(const ProgramDesc& desc);
- static const HashKey& GetKey(const Entry&);
- static bool EQ(const Entry&, const HashKey&);
- static bool LT(const Entry&, const HashKey&);
- bool operator <(const HashKey& key) const;
- bool operator ==(const HashKey& key) const;
- uint32_t getHash() const;
- private:
- ProgramDesc fDesc;
- uint32_t fHash;
- };
-
- struct Entry {
- Program fProgram;
- HashKey fKey;
- uint32_t fLRUStamp;
- };
-
- // if hash bits is changed, need to change hash function
- GrTHashTable<Entry, HashKey, 8> fHashCache;
-
- static const int MAX_ENTRIES = 16;
- Entry fEntries[MAX_ENTRIES];
- int fCount;
- uint32_t fCurrLRUStamp;
-
-public:
- ProgramCache() {
- fCount = 0;
- fCurrLRUStamp = 0;
- }
-
- ~ProgramCache() {
- for (int i = 0; i < fCount; ++i) {
- GrGpuGLShaders2::DeleteProgram(&fEntries[i].fProgram);
- }
- }
-
- void abandon() {
- fCount = 0;
- }
-
- void invalidateViewMatrices() {
- for (int i = 0; i < fCount; ++i) {
- // set to illegal matrix
- fEntries[i].fProgram.fViewMatrix = GrMatrix::InvalidMatrix();
- }
- }
-
- Program* getProgram(const ProgramDesc& desc) {
- HashKey key(desc);
- Entry* entry = fHashCache.find(key);
- if (NULL == entry) {
- if (fCount < MAX_ENTRIES) {
- entry = fEntries + fCount;
- ++fCount;
- } else {
- GrAssert(MAX_ENTRIES == fCount);
- entry = fEntries;
- for (int i = 1; i < MAX_ENTRIES; ++i) {
- if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
- entry = fEntries + i;
- }
- }
- fHashCache.remove(entry->fKey, entry);
- GrGpuGLShaders2::DeleteProgram(&entry->fProgram);
- }
- entry->fKey = key;
- GrGpuGLShaders2::GenProgram(desc, &entry->fProgram);
- fHashCache.insert(entry->fKey, entry);
- }
-
- entry->fLRUStamp = fCurrLRUStamp;
- if (GR_UINT32_MAX == fCurrLRUStamp) {
- // wrap around! just trash our LRU, one time hit.
- for (int i = 0; i < fCount; ++i) {
- fEntries[i].fLRUStamp = 0;
- }
- }
- ++fCurrLRUStamp;
- return &entry->fProgram;
- }
-};
-
-GrGpuGLShaders2::ProgramCache::HashKey::HashKey() {
-}
-
-static uint32_t ror(uint32_t x) {
- return (x >> 8) | (x << 24);
-}
-
-static uint32_t rol(uint32_t x) {
- return (x << 8) | (x >> 24);
-}
-
-GrGpuGLShaders2::ProgramCache::HashKey::HashKey(const ProgramDesc& desc) {
- fDesc = desc;
- // if you change the size of the desc, need to update the hash function
- GR_STATIC_ASSERT(12 == sizeof(ProgramDesc));
-
- uint32_t* d = GrTCast<uint32_t*>(&fDesc);
- fHash = d[0] ^ ror(d[1]) ^ rol(d[2]);
-}
-
-bool GrGpuGLShaders2::ProgramCache::HashKey::EQ(const Entry& entry,
- const HashKey& key) {
- return entry.fKey == key;
-}
-
-bool GrGpuGLShaders2::ProgramCache::HashKey::LT(const Entry& entry,
- const HashKey& key) {
- return entry.fKey < key;
-}
-
-bool GrGpuGLShaders2::ProgramCache::HashKey::operator ==(const HashKey& key) const {
- return fDesc == key.fDesc;
-}
-
-bool GrGpuGLShaders2::ProgramCache::HashKey::operator <(const HashKey& key) const {
- return memcmp(&fDesc, &key.fDesc, sizeof(HashKey)) < 0;
-}
-
-uint32_t GrGpuGLShaders2::ProgramCache::HashKey::getHash() const {
- return fHash;
-}
-
-struct GrGpuGLShaders2::ShaderCodeSegments {
- GrSStringBuilder<256> fVSUnis;
- GrSStringBuilder<256> fVSAttrs;
- GrSStringBuilder<256> fVaryings;
- GrSStringBuilder<256> fFSUnis;
- GrSStringBuilder<512> fVSCode;
- GrSStringBuilder<512> fFSCode;
-};
-// for variable names etc
-typedef GrSStringBuilder<16> GrTokenString;
-
-#if ATTRIBUTE_MATRIX
- #define VIEW_MATRIX_NAME "aViewM"
-#else
- #define VIEW_MATRIX_NAME "uViewM"
-#endif
-
-#define POS_ATTR_NAME "aPosition"
-#define COL_ATTR_NAME "aColor"
-
-static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
- *s = "aTexCoord";
- s->appendInt(coordIdx);
-}
-
-static inline const char* float_vector_type(int count) {
- static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
- GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS));
- return FLOAT_VECS[count];
-}
-
-static inline const char* vector_homog_coord(int count) {
- static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
- GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
- return HOMOGS[count];
-}
-
-static inline const char* vector_nonhomog_coords(int count) {
- static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
- GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
- return NONHOMOGS[count];
-}
-
-static inline const char* vector_all_coords(int count) {
- static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
- GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
- return ALL[count];
-}
-
-static void tex_matrix_name(int stage, GrStringBuilder* s) {
-#if ATTRIBUTE_MATRIX
- *s = "aTexM";
-#else
- *s = "uTexM";
-#endif
- s->appendInt(stage);
-}
-
-static void sampler_name(int stage, GrStringBuilder* s) {
- *s = "uSampler";
- s->appendInt(stage);
-}
-
-static void stage_varying_name(int stage, GrStringBuilder* s) {
- *s = "vStage";
- s->appendInt(stage);
-}
-
-static void radial2_param_name(int stage, GrStringBuilder* s) {
- *s = "uRadial2Params";
- s->appendInt(stage);
-}
-
-static void radial2_varying_name(int stage, GrStringBuilder* s) {
- *s = "vB";
- s->appendInt(stage);
-}
-
-#include "GrRandom.h"
-
-void GrGpuGLShaders2::ProgramUnitTest() {
- static const int PROG_OPTS[] = {
- 0,
- ProgramDesc::kNotPoints_OptFlagBit,
- ProgramDesc::kVertexColorAllOnes_OptFlagBit,
- ProgramDesc::kNotPoints_OptFlagBit | ProgramDesc::kVertexColorAllOnes_OptFlagBit
- };
- static const int STAGE_OPTS[] = {
- 0,
- StageDesc::kNoPerspective_OptFlagBit,
- StageDesc::kIdentity_CoordMapping
- };
- static const int STAGE_MODULATES[] = {
- StageDesc::kColor_Modulation,
- StageDesc::kAlpha_Modulation
- };
- static const int STAGE_COORD_MAPPINGS[] = {
- StageDesc::kIdentity_CoordMapping,
- StageDesc::kRadialGradient_CoordMapping,
- StageDesc::kSweepGradient_CoordMapping,
- StageDesc::kRadial2Gradient_CoordMapping
- };
- ProgramDesc pdesc;
- memset(&pdesc, 0, sizeof(pdesc));
-
- static const int NUM_TESTS = 512;
-
- // GrRandoms nextU() values have patterns in the low bits
- // So using nextU() % array_count might never take some values.
- GrRandom random;
- for (int t = 0; t < NUM_TESTS; ++t) {
-
- pdesc.fVertexLayout = 0;
- for (int s = 0; s < kNumStages; ++s) {
- // enable the stage?
- if (random.nextF() > .5f) {
- // use separate tex coords?
- if (random.nextF() > .5f) {
- int t = (int)(random.nextF() * kMaxTexCoords);
- pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
- } else {
- pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
- }
- }
- // use text-formatted verts?
- if (random.nextF() > .5f) {
- pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
- }
- }
-
- int x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
- pdesc.fOptFlags = PROG_OPTS[x];
- for (int s = 0; s < kNumStages; ++s) {
- pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
- x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
- pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
- x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
- pdesc.fStages[s].fModulation = (StageDesc::Modulation) STAGE_MODULATES[x];
- x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
- pdesc.fStages[s].fCoordMapping = (StageDesc::CoordMapping) STAGE_COORD_MAPPINGS[x];
- }
- Program program;
- GenProgram(pdesc, &program);
- DeleteProgram(&program);
- }
-}
-
-void GrGpuGLShaders2::GenStageCode(int stageNum,
- const StageDesc& desc,
- const char* fsInColor, // NULL means no incoming color
- const char* fsOutColor,
- const char* vsInCoord,
- ShaderCodeSegments* segments,
- StageUniLocations* locations) {
-
- GrAssert(stageNum >= 0 && stageNum <= 9);
-
- GrTokenString varyingName;
- stage_varying_name(stageNum, &varyingName);
-
- // First decide how many coords are needed to access the texture
- // Right now it's always 2 but we could start using 1D textures for
- // gradients.
- static const int coordDims = 2;
- int varyingDims;
- /// Vertex Shader Stuff
-
- // decide whether we need a matrix to transform texture coords
- // and whether the varying needs a perspective coord.
- GrTokenString texMName;
- tex_matrix_name(stageNum, &texMName);
- if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
- varyingDims = coordDims;
- } else {
- #if ATTRIBUTE_MATRIX
- segments->fVSAttrs += "attribute mat3 ";
- segments->fVSAttrs += texMName;
- segments->fVSAttrs += ";\n";
- #else
- segments->fVSUnis += "uniform mat3 ";
- segments->fVSUnis += texMName;
- segments->fVSUnis += ";\n";
- locations->fTextureMatrixUni = 1;
- #endif
- if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
- varyingDims = coordDims;
- } else {
- varyingDims = coordDims + 1;
- }
- }
-
- GrTokenString samplerName;
- sampler_name(stageNum, &samplerName);
- segments->fFSUnis += "uniform sampler2D ";
- segments->fFSUnis += samplerName;
- segments->fFSUnis += ";\n";
- locations->fSamplerUni = 1;
-
- segments->fVaryings += "varying ";
- segments->fVaryings += float_vector_type(varyingDims);
- segments->fVaryings += " ";
- segments->fVaryings += varyingName;
- segments->fVaryings += ";\n";
-
- if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
- GrAssert(varyingDims == coordDims);
- segments->fVSCode += "\t";
- segments->fVSCode += varyingName;
- segments->fVSCode += " = ";
- segments->fVSCode += vsInCoord;
- segments->fVSCode += ";\n";
- } else {
- segments->fVSCode += "\t";
- segments->fVSCode += varyingName;
- segments->fVSCode += " = (";
- segments->fVSCode += texMName;
- segments->fVSCode += " * vec3(";
- segments->fVSCode += vsInCoord;
- segments->fVSCode += ", 1))";
- segments->fVSCode += vector_all_coords(varyingDims);
- segments->fVSCode += ";\n";
- }
-
- GrTokenString radial2ParamsName;
- radial2_param_name(stageNum, &radial2ParamsName);
- // for radial grads without perspective we can pass the linear
- // part of the quadratic as a varying.
- GrTokenString radial2VaryingName;
- radial2_varying_name(stageNum, &radial2VaryingName);
-
- if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
-
- segments->fVSUnis += "uniform ";
- segments->fVSUnis += GrPrecision();
- segments->fVSUnis += " float ";
- segments->fVSUnis += radial2ParamsName;
- segments->fVSUnis += "[6];\n";
-
- segments->fFSUnis += "uniform ";
- segments->fFSUnis += GrPrecision();
- segments->fFSUnis += " float ";
- segments->fFSUnis += radial2ParamsName;
- segments->fFSUnis += "[6];\n";
- locations->fRadial2Uni = 1;
-
- // if there is perspective we don't interpolate this
- if (varyingDims == coordDims) {
- GrAssert(2 == coordDims);
- segments->fVaryings += "varying float ";
- segments->fVaryings += radial2VaryingName;
- segments->fVaryings += ";\n";
-
- segments->fVSCode += "\t";
- segments->fVSCode += radial2VaryingName;
- segments->fVSCode += " = 2.0 * (";
- segments->fVSCode += radial2ParamsName;
- segments->fVSCode += "[2] * ";
- segments->fVSCode += varyingName;
- segments->fVSCode += ".x ";
- segments->fVSCode += " - ";
- segments->fVSCode += radial2ParamsName;
- segments->fVSCode += "[3]);\n";
- }
- }
-
- /// Fragment Shader Stuff
- GrTokenString fsCoordName;
- // function used to access the shader, may be made projective
- GrTokenString texFunc("texture2D");
- if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
- StageDesc::kNoPerspective_OptFlagBit)) {
- GrAssert(varyingDims == coordDims);
- fsCoordName = varyingName;
- } else {
- // if we have to do some non-matrix op on the varyings to get
- // our final tex coords then when in perspective we have to
- // do an explicit divide
- if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) {
- texFunc += "Proj";
- fsCoordName = varyingName;
- } else {
- fsCoordName = "tCoord";
- fsCoordName.appendInt(stageNum);
-
- segments->fFSCode += "\t";
- segments->fFSCode += float_vector_type(coordDims);
- segments->fFSCode += " ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += " = ";
- segments->fFSCode += varyingName;
- segments->fFSCode += vector_nonhomog_coords(varyingDims);
- segments->fFSCode += " / ";
- segments->fFSCode += varyingName;
- segments->fFSCode += vector_homog_coord(varyingDims);
- segments->fFSCode += ";\n";
- }
- }
-
- GrSStringBuilder<96> sampleCoords;
- switch (desc.fCoordMapping) {
- case StageDesc::kIdentity_CoordMapping:
- sampleCoords = fsCoordName;
- break;
- case StageDesc::kSweepGradient_CoordMapping:
- sampleCoords = "vec2(atan(-";
- sampleCoords += fsCoordName;
- sampleCoords += ".y, -";
- sampleCoords += fsCoordName;
- sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)";
- break;
- case StageDesc::kRadialGradient_CoordMapping:
- sampleCoords = "vec2(length(";
- sampleCoords += fsCoordName;
- sampleCoords += ".xy), 0.5)";
- break;
- case StageDesc::kRadial2Gradient_CoordMapping: {
- GrTokenString cName = "c";
- GrTokenString ac4Name = "ac4";
- GrTokenString rootName = "root";
-
- cName.appendInt(stageNum);
- ac4Name.appendInt(stageNum);
- rootName.appendInt(stageNum);
-
- GrTokenString bVar;
- if (coordDims == varyingDims) {
- bVar = radial2VaryingName;
- GrAssert(2 == varyingDims);
- } else {
- GrAssert(3 == varyingDims);
- bVar = "b";
- bVar.appendInt(stageNum);
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += bVar;
- segments->fFSCode += " = 2.0 * (";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[2] * ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ".x ";
- segments->fFSCode += " - ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[3]);\n";
- }
-
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += cName;
- segments->fFSCode += " = dot(";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ", ";
- segments->fFSCode += fsCoordName;
- segments->fFSCode += ") + ";
- segments->fFSCode += " - ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[4];\n";
-
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += ac4Name;
- segments->fFSCode += " = ";
- segments->fFSCode += radial2ParamsName;
- segments->fFSCode += "[0] * 4.0 * ";
- segments->fFSCode += cName;
- segments->fFSCode += ";\n";
-
- segments->fFSCode += "\tfloat ";
- segments->fFSCode += rootName;
- segments->fFSCode += " = sqrt(abs(";
- segments->fFSCode += bVar;
- segments->fFSCode += " * ";
- segments->fFSCode += bVar;
- segments->fFSCode += " - ";
- segments->fFSCode += ac4Name;
- segments->fFSCode += "));\n";
-
- sampleCoords = "vec2((-";
- sampleCoords += bVar;
- sampleCoords += " + ";
- sampleCoords += radial2ParamsName;
- sampleCoords += "[5] * ";
- sampleCoords += rootName;
- sampleCoords += ") * ";
- sampleCoords += radial2ParamsName;
- sampleCoords += "[1], 0.5)\n";
- break;}
- };
-
- segments->fFSCode += "\t";
- segments->fFSCode += fsOutColor;
- segments->fFSCode += " = ";
- if (NULL != fsInColor) {
- segments->fFSCode += fsInColor;
- segments->fFSCode += " * ";
- }
- segments->fFSCode += texFunc;
- segments->fFSCode += "(";
- segments->fFSCode += samplerName;
- segments->fFSCode += ", ";
- segments->fFSCode += sampleCoords;
- segments->fFSCode += ")";
- if (desc.fModulation == StageDesc::kAlpha_Modulation) {
- segments->fFSCode += ".aaaa";
- }
- segments->fFSCode += ";\n";
-
-}
-
-void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
- Program* program) {
-
- ShaderCodeSegments segments;
- const uint32_t& layout = desc.fVertexLayout;
-
- memset(&program->fUniLocations, 0, sizeof(UniLocations));
-
- bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
- desc.fOptFlags);
-
-#if ATTRIBUTE_MATRIX
- segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
-#else
- segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
- segments.fVSAttrs = "";
-#endif
- segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
- if (haveColor) {
- segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
- segments.fVaryings = "varying vec4 vColor;\n";
- } else {
- segments.fVaryings = "";
- }
-
- segments.fVSCode = "void main() {\n"
- "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
- if (haveColor) {
- segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
- }
-
- if (!(desc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)){
- segments.fVSCode += "\tgl_PointSize = 1.0;\n";
- }
- segments.fFSCode = "void main() {\n";
-
- // add texture coordinates that are used to the list of vertex attr decls
- GrTokenString texCoordAttrs[kMaxTexCoords];
- for (int t = 0; t < kMaxTexCoords; ++t) {
- if (VertexUsesTexCoordIdx(t, layout)) {
- tex_attr_name(t, texCoordAttrs + t);
-
- segments.fVSAttrs += "attribute vec2 ";
- segments.fVSAttrs += texCoordAttrs[t];
- segments.fVSAttrs += ";\n";
- }
- }
-
- // for each enabled stage figure out what the input coordinates are
- // and count the number of stages in use.
- const char* stageInCoords[kNumStages];
- int numActiveStages = 0;
-
- for (int s = 0; s < kNumStages; ++s) {
- if (desc.fStages[s].fEnabled) {
- if (StagePosAsTexCoordVertexLayoutBit(s) & layout) {
- stageInCoords[s] = POS_ATTR_NAME;
- } else {
- int tcIdx = VertexTexCoordsForStage(s, layout);
- // we better have input tex coordinates if stage is enabled.
- GrAssert(tcIdx >= 0);
- GrAssert(texCoordAttrs[tcIdx].length());
- stageInCoords[s] = texCoordAttrs[tcIdx].cstr();
- }
- ++numActiveStages;
- }
- }
-
- GrTokenString inColor = "vColor";
-
- // if we have active stages string them together, feeding the output color
- // of each to the next and generating code for each stage.
- if (numActiveStages) {
- int currActiveStage = 0;
- for (int s = 0; s < kNumStages; ++s) {
- if (desc.fStages[s].fEnabled) {
- GrTokenString outColor;
- if (currActiveStage < (numActiveStages - 1)) {
- outColor = "color";
- outColor.appendInt(currActiveStage);
- segments.fFSCode += "\tvec4 ";
- segments.fFSCode += outColor;
- segments.fFSCode += ";\n";
- } else {
- outColor = "gl_FragColor";
- }
- GenStageCode(s,
- desc.fStages[s],
- haveColor ? inColor.cstr() : NULL,
- outColor.cstr(),
- stageInCoords[s],
- &segments,
- &program->fUniLocations.fStages[s]);
- ++currActiveStage;
- inColor = outColor;
- haveColor = true;
- }
- }
- } else {
- segments.fFSCode += "\tgl_FragColor = ";
- if (haveColor) {
- segments.fFSCode += inColor;
- } else {
- segments.fFSCode += "vec4(1,1,1,1)";
- }
- segments.fFSCode += ";\n";
- }
- segments.fFSCode += "}\n";
- segments.fVSCode += "}\n";
-
-
- const char* strings[4];
- int lengths[4];
- int stringCnt = 0;
-
- if (segments.fVSUnis.length()) {
- strings[stringCnt] = segments.fVSUnis.cstr();
- lengths[stringCnt] = segments.fVSUnis.length();
- ++stringCnt;
- }
- if (segments.fVSAttrs.length()) {
- strings[stringCnt] = segments.fVSAttrs.cstr();
- lengths[stringCnt] = segments.fVSAttrs.length();
- ++stringCnt;
- }
- if (segments.fVaryings.length()) {
- strings[stringCnt] = segments.fVaryings.cstr();
- lengths[stringCnt] = segments.fVaryings.length();
- ++stringCnt;
- }
-
- GrAssert(segments.fVSCode.length());
- strings[stringCnt] = segments.fVSCode.cstr();
- lengths[stringCnt] = segments.fVSCode.length();
- ++stringCnt;
-
-#if PRINT_SHADERS
- GrPrintf("%s%s%s%s\n",
- segments.fVSUnis.cstr(),
- segments.fVSAttrs.cstr(),
- segments.fVaryings.cstr(),
- segments.fVSCode.cstr());
-#endif
- program->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER,
- stringCnt,
- strings,
- lengths);
-
- stringCnt = 0;
-
- if (strlen(GrShaderPrecision()) > 1) {
- strings[stringCnt] = GrShaderPrecision();
- lengths[stringCnt] = strlen(GrShaderPrecision());
- ++stringCnt;
- }
- if (segments.fFSUnis.length()) {
- strings[stringCnt] = segments.fFSUnis.cstr();
- lengths[stringCnt] = segments.fFSUnis.length();
- ++stringCnt;
- }
- if (segments.fVaryings.length()) {
- strings[stringCnt] = segments.fVaryings.cstr();
- lengths[stringCnt] = segments.fVaryings.length();
- ++stringCnt;
- }
-
- GrAssert(segments.fFSCode.length());
- strings[stringCnt] = segments.fFSCode.cstr();
- lengths[stringCnt] = segments.fFSCode.length();
- ++stringCnt;
-
-#if PRINT_SHADERS
- GrPrintf("%s%s%s%s\n",
- GrShaderPrecision(),
- segments.fFSUnis.cstr(),
- segments.fVaryings.cstr(),
- segments.fFSCode.cstr());
-#endif
- program->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER,
- stringCnt,
- strings,
- lengths);
-
- program->fProgramID = GR_GL(CreateProgram());
- const GrGLint& progID = program->fProgramID;
-
- GR_GL(AttachShader(progID, program->fVShaderID));
- GR_GL(AttachShader(progID, program->fFShaderID));
-
- // Bind the attrib locations to same values for all shaders
- GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
- for (int t = 0; t < kMaxTexCoords; ++t) {
- if (texCoordAttrs[t].length()) {
- GR_GL(BindAttribLocation(progID,
- TEX_ATTR_LOCATION(t),
- texCoordAttrs[t].cstr()));
- }
- }
-
-#if ATTRIBUTE_MATRIX
- // set unis to a bogus value so that checks against -1 before
- // flushing will pass.
- GR_GL(BindAttribLocation(progID,
- VIEWMAT_ATTR_LOCATION,
- VIEW_MATRIX_NAME));
-
- program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
-
- for (int s = 0; s < kNumStages; ++s) {
- if (desc.fStages[s].fEnabled) {
- GrStringBuilder matName;
- tex_matrix_name(s, &matName);
- GR_GL(BindAttribLocation(progID,
- TEXMAT_ATTR_LOCATION(s),
- matName.cstr()));
- program->fUniLocations.fStages[s].fTextureMatrixUni =
- BOGUS_MATRIX_UNI_LOCATION;
- }
- }
-#endif
-
- GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME));
-
- GR_GL(LinkProgram(progID));
-
- GrGLint linked = GR_GL_INIT_ZERO;
- GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
- if (!linked) {
- GrGLint infoLen = GR_GL_INIT_ZERO;
- GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
- GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
- if (infoLen > 0) {
- GR_GL(GetProgramInfoLog(progID,
- infoLen+1,
- NULL,
- (char*)log.get()));
- GrPrintf((char*)log.get());
- }
- GrAssert(!"Error linking program");
- GR_GL(DeleteProgram(progID));
- program->fProgramID = 0;
- return;
- }
-
- // Get uniform locations
-#if !ATTRIBUTE_MATRIX
- program->fUniLocations.fViewMatrixUni =
- GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
- GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
-#endif
- for (int s = 0; s < kNumStages; ++s) {
- StageUniLocations& locations = program->fUniLocations.fStages[s];
- if (desc.fStages[s].fEnabled) {
-#if !ATTRIBUTE_MATRIX
- if (locations.fTextureMatrixUni) {
- GrTokenString texMName;
- tex_matrix_name(s, &texMName);
- locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
- progID,
- texMName.cstr()));
- GrAssert(-1 != locations.fTextureMatrixUni);
- } else {
- locations.fTextureMatrixUni = -1;
-
- }
-#endif
-
- if (locations.fSamplerUni) {
- GrTokenString samplerName;
- sampler_name(s, &samplerName);
- locations.fSamplerUni = GR_GL(GetUniformLocation(
- progID,
- samplerName.cstr()));
- GrAssert(-1 != locations.fSamplerUni);
- } else {
- locations.fSamplerUni = -1;
- }
-
- if (locations.fRadial2Uni) {
- GrTokenString radial2ParamName;
- radial2_param_name(s, &radial2ParamName);
- locations.fRadial2Uni = GR_GL(GetUniformLocation(
- progID,
- radial2ParamName.cstr()));
- GrAssert(-1 != locations.fRadial2Uni);
- } else {
- locations.fRadial2Uni = -1;
- }
- } else {
- locations.fSamplerUni = -1;
- locations.fRadial2Uni = -1;
- locations.fTextureMatrixUni = -1;
- }
- }
- GR_GL(UseProgram(progID));
-
- // init sampler unis and set bogus values for state tracking
- for (int s = 0; s < kNumStages; ++s) {
- if (-1 != program->fUniLocations.fStages[s].fSamplerUni) {
- GR_GL(Uniform1i(program->fUniLocations.fStages[s].fSamplerUni, s));
- }
- program->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
- program->fRadial2CenterX1[s] = GR_ScalarMax;
- program->fRadial2Radius0[s] = -GR_ScalarMax;
- }
- program->fViewMatrix = GrMatrix::InvalidMatrix();
-}
-
-void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc) {
-
- // Must initialize all fields or cache will have false negatives!
- desc->fVertexLayout = fGeometrySrc.fVertexLayout;
-
- desc->fOptFlags = 0;
- if (kPoints_PrimitiveType != primType) {
- desc->fOptFlags |= ProgramDesc::kNotPoints_OptFlagBit;
- }
-#if GR_AGGRESSIVE_SHADER_OPTS
- if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
-#endif
-
- for (int s = 0; s < kNumStages; ++s) {
- StageDesc& stage = desc->fStages[s];
-
- stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
-
- if (stage.fEnabled) {
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
- GrAssert(NULL != texture);
- // we matrix to invert when orientation is TopDown, so make sure
- // we aren't in that case before flagging as identity.
- if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
- stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
- } else if (!getSamplerMatrix(s).hasPerspective()) {
- stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
- } else {
- stage.fOptFlags = 0;
- }
- switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
- case GrSamplerState::kNormal_SampleMode:
- stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
- break;
- case GrSamplerState::kRadial_SampleMode:
- stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
- break;
- case GrSamplerState::kRadial2_SampleMode:
- stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
- break;
- case GrSamplerState::kSweep_SampleMode:
- stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
- break;
- default:
- GrAssert(!"Unexpected sample mode!");
- break;
- }
- if (GrPixelConfigIsAlphaOnly(texture->config())) {
- stage.fModulation = StageDesc::kAlpha_Modulation;
- } else {
- stage.fModulation = StageDesc::kColor_Modulation;
- }
- } else {
- stage.fOptFlags = 0;
- stage.fCoordMapping = (StageDesc::CoordMapping)0;
- stage.fModulation = (StageDesc::Modulation)0;
- }
- }
-}
-
-GrGLuint GrGpuGLShaders2::CompileShader(GrGLenum type,
- int stringCnt,
- const char** strings,
- int* stringLengths) {
- GrGLuint shader = GR_GL(CreateShader(type));
- if (0 == shader) {
- return 0;
- }
-
- GrGLint compiled = GR_GL_INIT_ZERO;
- GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
- GR_GL(CompileShader(shader));
- GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
-
- if (!compiled) {
- GrGLint infoLen = GR_GL_INIT_ZERO;
- GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
- GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
- if (infoLen > 0) {
- GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
- for (int i = 0; i < stringCnt; ++i) {
- if (NULL == stringLengths || stringLengths[i] < 0) {
- GrPrintf(strings[i]);
- } else {
- GrPrintf("%.*s", stringLengths[i], strings[i]);
- }
- }
- GrPrintf("\n%s", log.get());
- }
- GrAssert(!"Shader compilation failed!");
- GR_GL(DeleteShader(shader));
- return 0;
- }
- return shader;
-}
-
-void GrGpuGLShaders2::DeleteProgram(Program* program) {
- GR_GL(DeleteShader(program->fVShaderID));
- GR_GL(DeleteShader(program->fFShaderID));
- GR_GL(DeleteProgram(program->fProgramID));
- GR_DEBUGCODE(memset(program, 0, sizeof(Program)));
-}
-
-
-GrGpuGLShaders2::GrGpuGLShaders2() {
-
- fProgram = NULL;
- fProgramCache = new ProgramCache();
-
-#if 0
- ProgramUnitTest();
-#endif
-}
-
-GrGpuGLShaders2::~GrGpuGLShaders2() {
- delete fProgramCache;
-}
-
-const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
-#if ATTRIBUTE_MATRIX
- return fHWDrawState.fSamplerStates[stage].getMatrix();
-#else
- return fProgram->fTextureMatrices[stage];
-#endif
-}
-
-void GrGpuGLShaders2::recordHWSamplerMatrix(int stage, const GrMatrix& matrix){
-#if ATTRIBUTE_MATRIX
- fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
-#else
- fProgram->fTextureMatrices[stage] = matrix;
-#endif
-}
-
-void GrGpuGLShaders2::resetContext() {
-
- INHERITED::resetContext();
-
- fHWGeometryState.fVertexLayout = 0;
- fHWGeometryState.fVertexOffset = ~0;
- GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
- for (int t = 0; t < kMaxTexCoords; ++t) {
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
- }
- GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
-
- fHWProgramID = 0;
-}
-
-void GrGpuGLShaders2::flushViewMatrix() {
- GrAssert(NULL != fCurrDrawState.fRenderTarget);
- GrMatrix m (
- GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
- 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
- 0, 0, GrMatrix::I()[8]);
- m.setConcat(m, fCurrDrawState.fViewMatrix);
-
- // ES doesn't allow you to pass true to the transpose param,
- // so do our own transpose
- GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
- };
-#if ATTRIBUTE_MATRIX
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
- GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
-#else
- GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fViewMatrixUni,1,false,mt));
-#endif
-}
-
-void GrGpuGLShaders2::flushTextureMatrix(int stage) {
- GrAssert(NULL != fCurrDrawState.fTextures[stage]);
-
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[stage];
-
- GrMatrix m = getSamplerMatrix(stage);
- GrSamplerState::SampleMode mode =
- fCurrDrawState.fSamplerStates[0].getSampleMode();
- AdjustTextureMatrix(texture, mode, &m);
-
- // ES doesn't allow you to pass true to the transpose param,
- // so do our own transpose
- GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
- };
-#if ATTRIBUTE_MATRIX
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
- GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
-#else
- GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[stage].fTextureMatrixUni,
- 1, false, mt));
-#endif
-}
-
-void GrGpuGLShaders2::flushRadial2(int stage) {
-
- const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage];
-
- GrScalar centerX1 = sampler.getRadial2CenterX1();
- GrScalar radius0 = sampler.getRadial2Radius0();
-
- GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
-
- float unis[6] = {
- GrScalarToFloat(a),
- 1 / (2.f * unis[0]),
- GrScalarToFloat(centerX1),
- GrScalarToFloat(radius0),
- GrScalarToFloat(GrMul(radius0, radius0)),
- sampler.isRadial2PosRoot() ? 1.f : -1.f
- };
- GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[stage].fRadial2Uni,
- 6,
- unis));
-}
-
-void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) {
- ProgramDesc desc;
- getProgramDesc(type, &desc);
- fProgram = fProgramCache->getProgram(desc);
-
- if (fHWProgramID != fProgram->fProgramID) {
- GR_GL(UseProgram(fProgram->fProgramID));
- fHWProgramID = fProgram->fProgramID;
-#if GR_COLLECT_STATS
- ++fStats.fProgChngCnt;
-#endif
- }
-}
-
-bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
-
- if (!flushGLStateCommon(type)) {
- return false;
- }
-
- if (fDirtyFlags.fRenderTargetChanged) {
- // our coords are in pixel space and the GL matrices map to NDC
- // so if the viewport changed, our matrix is now wrong.
-#if ATTRIBUTE_MATRIX
- fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
-#else
- // we assume all shader matrices may be wrong after viewport changes
- fProgramCache->invalidateViewMatrices();
-#endif
- }
-
- flushProgram(type);
-
- if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
- // invalidate the immediate mode color
- fHWDrawState.fColor = GrColor_ILLEGAL;
- } else {
- if (fHWDrawState.fColor != fCurrDrawState.fColor &&
- (!GR_AGGRESSIVE_SHADER_OPTS || 0xffffffff != fCurrDrawState.fColor)) {
- // avoid pushing the color attrib if the shader will optimize it out
-
- // OpenGL ES only supports the float varities of glVertexAttrib
- float c[] = {
- GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackA(fCurrDrawState.fColor) / 255.f
- };
- GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
- fHWDrawState.fColor = fCurrDrawState.fColor;
- }
- }
-
-#if ATTRIBUTE_MATRIX
- GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
-#else
- GrMatrix& currViewMatrix = fProgram->fViewMatrix;
-#endif
-
- if (currViewMatrix != fCurrDrawState.fViewMatrix) {
- flushViewMatrix();
- currViewMatrix = fCurrDrawState.fViewMatrix;
- }
-
- for (int s = 0; s < kNumStages; ++s) {
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
- if (NULL != texture) {
- if (-1 != fProgram->fUniLocations.fStages[s].fTextureMatrixUni &&
- (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
- getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
- flushTextureMatrix(s);
- recordHWSamplerMatrix(s, getSamplerMatrix(s));
- }
- }
-
- const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
- if (-1 != fProgram->fUniLocations.fStages[s].fRadial2Uni &&
- (fProgram->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
- fProgram->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
- fProgram->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
-
- flushRadial2(s);
-
- fProgram->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
- fProgram->fRadial2Radius0[s] = sampler.getRadial2Radius0();
- fProgram->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
- }
- }
- resetDirtyFlags();
- return true;
-}
-
-void GrGpuGLShaders2::setupGeometry(int* startVertex,
- int* startIndex,
- int vertexCount,
- int indexCount) {
-
- int newColorOffset;
- int newTexCoordOffsets[kMaxTexCoords];
-
- GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
- newTexCoordOffsets,
- &newColorOffset);
- int oldColorOffset;
- int oldTexCoordOffsets[kMaxTexCoords];
- GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
- oldTexCoordOffsets,
- &oldColorOffset);
- bool indexed = NULL != startIndex;
-
- int extraVertexOffset;
- int extraIndexOffset;
- setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
-
- GrGLenum scalarType;
- bool texCoordNorm;
- if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
- scalarType = GrGLTextType;
- texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
- } else {
- scalarType = GrGLType;
- texCoordNorm = false;
- }
-
- size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
- *startVertex = 0;
- if (indexed) {
- *startIndex += extraIndexOffset;
- }
-
- // all the Pointers must be set if any of these are true
- bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
- vertexOffset != fHWGeometryState.fVertexOffset ||
- newStride != oldStride;
-
- // position and tex coord offsets change if above conditions are true
- // or the type/normalization changed based on text vs nontext type coords.
- bool posAndTexChange = allOffsetsChange ||
- (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
- (kTextFormat_VertexLayoutBit &
- (fHWGeometryState.fVertexLayout ^
- fGeometrySrc.fVertexLayout)));
-
- if (posAndTexChange) {
- GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
- false, newStride, (GrGLvoid*)vertexOffset));
- fHWGeometryState.fVertexOffset = vertexOffset;
- }
-
- for (int t = 0; t < kMaxTexCoords; ++t) {
- if (newTexCoordOffsets[t] > 0) {
- GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
- if (oldTexCoordOffsets[t] <= 0) {
- GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordOffset));
- } else if (posAndTexChange ||
- newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordOffset));
- }
- } else if (oldTexCoordOffsets[t] > 0) {
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
- }
- }
-
- if (newColorOffset > 0) {
- GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
- if (oldColorOffset <= 0) {
- GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
- GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
- GR_GL_UNSIGNED_BYTE,
- true, newStride, colorOffset));
- } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
- GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
- GR_GL_UNSIGNED_BYTE,
- true, newStride, colorOffset));
- }
- } else if (oldColorOffset > 0) {
- GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
- }
-
- fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
- fHWGeometryState.fArrayPtrsDirty = false;
-}
diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h
deleted file mode 100644
index b9a019b..0000000
--- a/gpu/src/GrGpuGLShaders2.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-
-#ifndef GrGpuGLShaders2_DEFINED
-#define GrGpuGLShaders2_DEFINED
-
-#include "GrGpuGL.h"
-
-// Programmable OpenGL or OpenGL ES 2.0
-class GrGpuGLShaders2 : public GrGpuGL {
-public:
- GrGpuGLShaders2();
- virtual ~GrGpuGLShaders2();
-
-protected:
- // overrides from GrGpu
- virtual bool flushGraphicsState(GrPrimitiveType type);
- virtual void setupGeometry(int* startVertex,
- int* startIndex,
- int vertexCount,
- int indexCount);
-
-private:
-
- virtual void resetContext();
-
- // Helpers to make code more readable
- const GrMatrix& getHWSamplerMatrix(int stage);
- void recordHWSamplerMatrix(int stage, const GrMatrix& matrix);
-
- // sets the texture matrix uniform for currently bound program
- void flushTextureMatrix(int stage);
-
- // sets the MVP matrix uniform for currently bound program
- void flushViewMatrix();
-
- // flushes the parameters to two point radial gradient
- void flushRadial2(int stage);
-
- // called at flush time to setup the appropriate program
- void flushProgram(GrPrimitiveType type);
-
- struct Program;
-
- struct StageDesc;
- struct ProgramDesc;
-
- struct UniLocations;
- struct StageUniLocations;
-
- struct ShaderCodeSegments;
-
- class ProgramCache;
-
- // gets a description of needed shader
- void getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc);
-
- // generates and compiles a program from a description and vertex layout
- // will change GL's bound program
- static void GenProgram(const ProgramDesc& desc, Program* program);
-
- // generates code for a stage of the shader
- static void GenStageCode(int stageNum,
- const StageDesc& desc,
- const char* psInColor,
- const char* psOutColor,
- const char* vsInCoord,
- ShaderCodeSegments* segments,
- StageUniLocations* locations);
-
- // Compiles a GL shader, returns shader ID or 0 if failed
- // params have same meaning as glShaderSource
- static GrGLuint CompileShader(GrGLenum type, int stringCnt,
- const char** strings,
- int* stringLengths);
- static void DeleteProgram(Program* program);
-
- void ProgramUnitTest();
-
- ProgramCache* fProgramCache;
- Program* fProgram;
- GrGLuint fHWProgramID;
-
- typedef GrGpuGL INHERITED;
-};
-
-#endif
-
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index be4db99..7df1f23 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -24,9 +24,10 @@
GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
GrIndexBufferAllocPool* indexPool) :
- fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage),
- fStates(STATES_BLOCK_SIZE, fStatesStorage),
- fClips(CLIPS_BLOCK_SIZE, fClipsStorage),
+ fDraws(&fDrawStorage),
+ fStates(&fStateStorage),
+ fClears(&fClearStorage),
+ fClips(&fClipStorage),
fClipSet(true),
fLastRectVertexLayout(0),
@@ -149,7 +150,12 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
GrAssert(0 == lastDraw.fIndexCount % 6);
GrAssert(0 == lastDraw.fStartIndex);
- appendToPreviousDraw = lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
+ bool clearSinceLastDraw =
+ fClears.count() &&
+ fClears.back().fBeforeDrawIdx == fDraws.count();
+
+ appendToPreviousDraw = !clearSinceLastDraw &&
+ lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
(fCurrQuad * 4 + lastDraw.fStartVertex) == fCurrPoolStartVertex;
if (appendToPreviousDraw) {
lastDraw.fVertexCount += 4;
@@ -287,6 +293,23 @@ void GrInOrderDrawBuffer::drawNonIndexed(GrPrimitiveType primitiveType,
draw.fIndexBuffer = NULL;
}
+void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
+ GrIRect r;
+ if (NULL == rect) {
+ // We could do something smart and remove previous draws and clears to
+ // the current render target. If we get that smart we have to make sure
+ // those draws aren't read before this clear (render-to-texture).
+ r.setLTRB(0, 0,
+ this->getRenderTarget()->width(),
+ this->getRenderTarget()->height());
+ rect = &r;
+ }
+ Clear& clr = fClears.push_back();
+ clr.fColor = color;
+ clr.fBeforeDrawIdx = fDraws.count();
+ clr.fRect = *rect;
+}
+
void GrInOrderDrawBuffer::reset() {
GrAssert(!fReservedGeometry.fLocked);
uint32_t numStates = fStates.count();
@@ -307,6 +330,8 @@ void GrInOrderDrawBuffer::reset() {
fDraws.reset();
fStates.reset();
+ fClears.reset();
+
fVertexPool.reset();
fIndexPool.reset();
@@ -320,7 +345,7 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
GrAssert(NULL != target);
GrAssert(target != this); // not considered and why?
- uint32_t numDraws = fDraws.count();
+ int numDraws = fDraws.count();
if (!numDraws) {
return;
}
@@ -334,10 +359,17 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
// on the stack.
GrDrawTarget::AutoGeometrySrcRestore agsr(target);
- uint32_t currState = ~0;
- uint32_t currClip = ~0;
+ int currState = ~0;
+ int currClip = ~0;
+ int currClear = 0;
+
+ for (int i = 0; i < numDraws; ++i) {
+ while (currClear < fClears.count() &&
+ i == fClears[currClear].fBeforeDrawIdx) {
+ target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
+ ++currClear;
+ }
- for (uint32_t i = 0; i < numDraws; ++i) {
const Draw& draw = fDraws[i];
if (draw.fStateChanged) {
++currState;
@@ -366,6 +398,11 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
draw.fVertexCount);
}
}
+ while (currClear < fClears.count()) {
+ GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
+ target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
+ ++currClear;
+ }
}
bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
diff --git a/gpu/src/GrMatrix.cpp b/gpu/src/GrMatrix.cpp
index 0a2d1b2..476d9a2 100644
--- a/gpu/src/GrMatrix.cpp
+++ b/gpu/src/GrMatrix.cpp
@@ -19,6 +19,7 @@
#include "GrRect.h"
#include <stddef.h>
+#if 0
#if GR_SCALAR_IS_FLOAT
const GrScalar GrMatrix::gRESCALE(GR_Scalar1);
#else
@@ -259,6 +260,26 @@ bool GrMatrix::isIdentity() const {
}
+bool GrMatrix::preservesAxisAlignment() const {
+
+ // check if matrix is trans and scale only
+ static const int gAllowedMask1 = kScale_TypeBit | kTranslate_TypeBit;
+
+ if (!(~gAllowedMask1 & fTypeMask)) {
+ return true;
+ }
+
+ // check matrix is trans and skew only (0 scale)
+ static const int gAllowedMask2 = kScale_TypeBit | kSkew_TypeBit |
+ kTranslate_TypeBit | kZeroScale_TypeBit;
+
+ if (!(~gAllowedMask2 & fTypeMask) && (kZeroScale_TypeBit & fTypeMask)) {
+ return true;
+ }
+
+ return false;
+}
+
GrScalar GrMatrix::getMaxStretch() const {
if (fTypeMask & kPerspective_TypeBit) {
@@ -611,7 +632,7 @@ void GrMatrix::UnitTest() {
if (maxStretch > 0) {
maxStretch = GrMul(GR_Scalar1 + GR_Scalar1 / 100, maxStretch);
}
- GrPoint origin = a.mapPoint(GrPoint(0,0));
+ GrPoint origin = a.mapPoint(GrPoint::Make(0,0));
for (int j = 0; j < 9; ++j) {
int mask, origMask = a.fTypeMask;
@@ -648,8 +669,8 @@ void GrMatrix::UnitTest() {
a.mapPerspective(&t2, &pt, 1); // full mult
GrAssert(t0 == t1 && t1 == t2);
if (maxStretch >= 0.f) {
- GrVec vec;
- vec.setBetween(t0, origin);
+ GrVec vec = origin - t0;
+// vec.setBetween(t0, origin);
GrScalar stretch = vec.length() / pt.distanceToOrigin();
GrAssert(stretch <= maxStretch);
}
@@ -668,6 +689,7 @@ void GrMatrix::UnitTest() {
}
///////////////////////////////////////////////////////////////////////////////
+#endif
int Gr_clz(uint32_t n) {
if (0 == n) {
@@ -696,34 +718,3 @@ int Gr_clz(uint32_t n) {
}
return count;
}
-
-///////////////////////////////////////////////////////////////////////////////
-#include "GrRect.h"
-
-void GrRect::setBounds(const GrPoint pts[], int count) {
- if (count <= 0) {
- this->setEmpty();
- } else {
- GrScalar L, R, T, B;
- L = R = pts[0].fX;
- T = B = pts[0].fY;
- for (int i = 1; i < count; i++) {
- GrScalar x = pts[i].fX;
- GrScalar y = pts[i].fY;
- if (x < L) {
- L = x;
- } else if (x > R) {
- R = x;
- }
- if (y < T) {
- T = y;
- } else if (y > B) {
- B = y;
- }
- }
- this->setLTRB(L, T, R, B);
- }
-}
-
-
-
diff --git a/gpu/src/GrPath.cpp b/gpu/src/GrPath.cpp
index a740dfc..aa89d37 100644
--- a/gpu/src/GrPath.cpp
+++ b/gpu/src/GrPath.cpp
@@ -2,6 +2,7 @@
GrPath::GrPath() {
fConvexHint = kNone_ConvexHint;
+ fConservativeBounds.setLargestInverted();
}
GrPath::GrPath(const GrPath& src) : INHERITED() {
@@ -40,6 +41,7 @@ void GrPath::ensureMoveTo() {
if (fCmds.isEmpty() || this->wasLastVerb(kClose_PathCmd)) {
*fCmds.append() = kMove_PathCmd;
fPts.append()->set(0, 0);
+ fConservativeBounds.growToInclude(0,0);
}
}
@@ -51,12 +53,14 @@ void GrPath::moveTo(GrScalar x, GrScalar y) {
*fCmds.append() = kMove_PathCmd;
fPts.append()->set(x, y);
}
+ fConservativeBounds.growToInclude(x,y);
}
void GrPath::lineTo(GrScalar x, GrScalar y) {
this->ensureMoveTo();
*fCmds.append() = kLine_PathCmd;
fPts.append()->set(x, y);
+ fConservativeBounds.growToInclude(x,y);
}
void GrPath::quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) {
@@ -64,6 +68,8 @@ void GrPath::quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) {
*fCmds.append() = kQuadratic_PathCmd;
fPts.append()->set(x0, y0);
fPts.append()->set(x1, y1);
+ fConservativeBounds.growToInclude(x0,y0);
+ fConservativeBounds.growToInclude(x1,y1);
}
void GrPath::cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
@@ -73,6 +79,9 @@ void GrPath::cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
fPts.append()->set(x0, y0);
fPts.append()->set(x1, y1);
fPts.append()->set(x2, y2);
+ fConservativeBounds.growToInclude(x0,y0);
+ fConservativeBounds.growToInclude(x1,y1);
+ fConservativeBounds.growToInclude(x2,y2);
}
void GrPath::close() {
@@ -95,6 +104,7 @@ void GrPath::offset(GrScalar tx, GrScalar ty) {
iter->offset(tx, ty);
++iter;
}
+ fConservativeBounds.offset(tx, ty);
}
///////////////////////////////////////////////////////////////////////////////
@@ -148,17 +158,18 @@ static void init_from_two_vecs(const GrVec& firstVec,
void GrPath::resetFromIter(GrPathIter* iter) {
fPts.reset();
fCmds.reset();
+ fConservativeBounds.setLargestInverted();
fConvexHint = iter->convexHint();
// first point of the subpath
- GrPoint firstPt(0,0);
+ GrPoint firstPt = { 0, 0 };
// first edge of the subpath
- GrVec firstVec(0,0);
+ GrVec firstVec = { 0, 0 };
// vec of most recently processed edge, that wasn't degenerate
- GrVec previousVec(0,0);
+ GrVec previousVec = { 0, 0 };
// most recently processed point
- GrPoint previousPt(0,0);
+ GrPoint previousPt = { 0, 0 };
// sign indicates whether we're bending left or right
GrScalar turnDir = 0;
@@ -209,6 +220,9 @@ void GrPath::resetFromIter(GrPathIter* iter) {
break;
}
int n = NumPathCmdPoints(cmd);
+ for (int i = 0; i < n; ++i) {
+ fConservativeBounds.growToInclude(pts[i].fX, pts[i].fY);
+ }
if (0 == subPathPts && n > 0) {
previousPt = pts[0];
firstPt = previousPt;
@@ -225,8 +239,8 @@ void GrPath::resetFromIter(GrPathIter* iter) {
if (numSubPaths < 2 && kNone_ConvexHint == fConvexHint) {
while (consumed < n) {
GrAssert(pts[consumed-1] == previousPt);
- GrVec vec;
- vec.setBetween(previousPt, pts[consumed]);
+ GrVec vec = pts[consumed] - previousPt;
+// vec.setBetween(previousPt, pts[consumed]);
if (vec.fX || vec.fY) {
if (subPathPts >= 2) {
if (0 == turnDir) {
@@ -255,8 +269,8 @@ void GrPath::resetFromIter(GrPathIter* iter) {
(!subPathClosed && kEnd_PathCmd == cmd ))) {
// if an additional vector is needed to close the loop check
// that it validates against the previous vector.
- GrVec vec;
- vec.setBetween(previousPt, firstPt);
+ GrVec vec = firstPt - previousPt;
+// vec.setBetween(previousPt, firstPt);
if (vec.fX || vec.fY) {
if (!check_two_vecs(previousVec, vec, turnDir,
&xDir, &yDir, &flipX, &flipY)) {
@@ -409,6 +423,13 @@ GrPath::Iter::Iter(const GrPath& path) : fPath(&path) {
this->rewind();
}
+#ifdef SK_DEBUG
+static bool containsInclusive(const GrRect& rect, const GrPoint& point) {
+ return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
+ point.fY >= rect.fTop && point.fY <= rect.fBottom;
+}
+#endif
+
GrPathCmd GrPath::Iter::next(GrPoint points[]) {
if (fCmdIndex == fPath->fCmds.count()) {
GrAssert(fPtIndex == fPath->fPts.count());
@@ -427,6 +448,7 @@ GrPathCmd GrPath::Iter::next(GrPoint points[]) {
}
fLastPt = srcPts[0];
GrAssert(fPtIndex <= fPath->fPts.count() + 1);
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
fPtIndex += 1;
break;
case kLine_PathCmd:
@@ -436,6 +458,7 @@ GrPathCmd GrPath::Iter::next(GrPoint points[]) {
}
fLastPt = srcPts[0];
GrAssert(fPtIndex <= fPath->fPts.count() + 1);
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
fPtIndex += 1;
break;
case kQuadratic_PathCmd:
@@ -446,6 +469,8 @@ GrPathCmd GrPath::Iter::next(GrPoint points[]) {
}
fLastPt = srcPts[1];
GrAssert(fPtIndex <= fPath->fPts.count() + 2);
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
fPtIndex += 2;
break;
case kCubic_PathCmd:
@@ -457,6 +482,9 @@ GrPathCmd GrPath::Iter::next(GrPoint points[]) {
}
fLastPt = srcPts[2];
GrAssert(fPtIndex <= fPath->fPts.count() + 3);
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
+ GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[2]));
fPtIndex += 3;
break;
case kClose_PathCmd:
@@ -485,4 +513,11 @@ void GrPath::Iter::reset(const GrPath& path) {
fCmdIndex = fPtIndex = 0;
}
+bool GrPath::Iter::getConservativeBounds(GrRect* rect) const {
+ if (!fPath->getConservativeBounds().isEmpty()) {
+ *rect = fPath->getConservativeBounds();
+ return true;
+ }
+ return false;
+}
diff --git a/gpu/src/GrPathUtils.cpp b/gpu/src/GrPathUtils.cpp
index 274dc49..115b0f6 100644
--- a/gpu/src/GrPathUtils.cpp
+++ b/gpu/src/GrPathUtils.cpp
@@ -52,10 +52,10 @@ uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
}
GrPoint q[] = {
- GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
- GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
+ { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
+ { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
};
- GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
+ GrPoint r = { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) };
pointsLeft >>= 1;
uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft);
@@ -91,15 +91,15 @@ uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
return 1;
}
GrPoint q[] = {
- GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
- GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
- GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
+ { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
+ { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
+ { GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY) }
};
GrPoint r[] = {
- GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
- GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
+ { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) },
+ { GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY) }
};
- GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
+ GrPoint s = { GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY) };
pointsLeft >>= 1;
uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
diff --git a/gpu/src/GrPathUtils.h b/gpu/src/GrPathUtils.h
index 97841dd..af05682 100644
--- a/gpu/src/GrPathUtils.h
+++ b/gpu/src/GrPathUtils.h
@@ -18,10 +18,9 @@
#define GrPathUtils_DEFINED
#include "GrNoncopyable.h"
-#include "GrScalar.h"
+#include "GrPoint.h"
class GrPathIter;
-struct GrPoint;
/**
* Utilities for evaluating paths.
diff --git a/gpu/src/GrStencil.cpp b/gpu/src/GrStencil.cpp
index c366f61..a537e16 100644
--- a/gpu/src/GrStencil.cpp
+++ b/gpu/src/GrStencil.cpp
@@ -373,4 +373,4 @@ bool GrStencilSettings::GetClipPasses(GrSetOp op,
GrCrash("Unknown set op");
}
return false;
-} \ No newline at end of file
+}
diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp
index 8ed2c22..3993adb 100644
--- a/gpu/src/GrTesselatedPathRenderer.cpp
+++ b/gpu/src/GrTesselatedPathRenderer.cpp
@@ -55,8 +55,8 @@ static void combineData(GLdouble coords[3], void* vertexData[4],
{
PolygonData* polygonData = static_cast<PolygonData*>(data);
int index = polygonData->fVertices->count();
- *polygonData->fVertices->append() = GrPoint(static_cast<float>(coords[0]),
- static_cast<float>(coords[1]));
+ *polygonData->fVertices->append() = GrPoint::Make(static_cast<float>(coords[0]),
+ static_cast<float>(coords[1]));
*outData = reinterpret_cast<void*>(index);
}
@@ -83,6 +83,59 @@ static unsigned fill_type_to_glu_winding_rule(GrPathFill fill) {
GrTesselatedPathRenderer::GrTesselatedPathRenderer() {
}
+class Edge {
+ public:
+ Edge() {}
+ Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
+ GrPoint intersect(const Edge& other) {
+ return GrPoint::Make(
+ (fY * other.fZ - other.fY * fZ) / (fX * other.fY - other.fX * fY),
+ (fX * other.fZ - other.fX * fZ) / (other.fX * fY - fX * other.fY));
+ }
+ float fX, fY, fZ;
+};
+
+typedef GrTDArray<Edge> EdgeArray;
+
+bool isCCW(const GrPoint* v)
+{
+ GrVec v1 = v[1] - v[0];
+ GrVec v2 = v[2] - v[1];
+ return v1.cross(v2) < 0;
+}
+
+static size_t computeEdgesAndOffsetVertices(const GrMatrix& matrix,
+ const GrMatrix& inverse,
+ GrPoint* vertices,
+ size_t numVertices,
+ EdgeArray* edges)
+{
+ GrPoint p = vertices[numVertices - 1];
+ matrix.mapPoints(&p, 1);
+ float sign = isCCW(vertices) ? -1.0f : 1.0f;
+ for (size_t i = 0; i < numVertices; ++i) {
+ GrPoint q = vertices[i];
+ matrix.mapPoints(&q, 1);
+ if (p == q) continue;
+ GrVec tangent = GrVec::Make(p.fY - q.fY, q.fX - p.fX);
+ float scale = sign / tangent.length();
+ float cross2 = p.fX * q.fY - q.fX * p.fY;
+ Edge edge(tangent.fX * scale,
+ tangent.fY * scale,
+ cross2 * scale + 0.5f);
+ *edges->append() = edge;
+ p = q;
+ }
+ Edge prev_edge = *edges->back();
+ for (size_t i = 0; i < edges->count(); ++i) {
+ Edge edge = edges->at(i);
+ vertices[i] = prev_edge.intersect(edge);
+ inverse.mapPoints(&vertices[i], 1);
+ prev_edge = edge;
+ }
+ return edges->count();
+}
+
void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
GrPathIter* path,
@@ -193,10 +246,10 @@ FINISHED:
if (target->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
}
- *vert++ = GrPoint(bounds.fLeft, bounds.fTop);
- *vert++ = GrPoint(bounds.fLeft, bounds.fBottom);
- *vert++ = GrPoint(bounds.fRight, bounds.fBottom);
- *vert++ = GrPoint(bounds.fRight, bounds.fTop);
+ *vert++ = GrPoint::Make(bounds.fLeft, bounds.fTop);
+ *vert++ = GrPoint::Make(bounds.fLeft, bounds.fBottom);
+ *vert++ = GrPoint::Make(bounds.fRight, bounds.fBottom);
+ *vert++ = GrPoint::Make(bounds.fRight, bounds.fTop);
subpathVertCount[subpath++] = 4;
}
@@ -205,9 +258,40 @@ FINISHED:
size_t count = vert - base;
+ if (count < 3) {
+ delete[] base;
+ return;
+ }
+
if (subpathCnt == 1 && !inverted && path->convexHint() == kConvex_ConvexHint) {
- target->setVertexSourceToArray(layout, base, count);
- target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
+ if (target->isAntialiasState()) {
+ target->enableState(GrDrawTarget::kEdgeAA_StateBit);
+ EdgeArray edges;
+ GrMatrix inverse, matrix = target->getViewMatrix();
+ target->getViewInverse(&inverse);
+
+ count = computeEdgesAndOffsetVertices(matrix, inverse, base, count, &edges);
+ GrPoint triangle[3];
+ triangle[0] = base[0];
+ Edge triangleEdges[6];
+ triangleEdges[0] = *edges.back();
+ triangleEdges[1] = edges[0];
+ for (size_t i = 1; i < count - 1; i++) {
+ triangle[1] = base[i];
+ triangle[2] = base[i + 1];
+ triangleEdges[2] = edges[i - 1];
+ triangleEdges[3] = edges[i];
+ triangleEdges[4] = edges[i];
+ triangleEdges[5] = edges[i + 1];
+ target->setVertexSourceToArray(layout, triangle, 3);
+ target->setEdgeAAData(&triangleEdges[0].fX);
+ target->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
+ }
+ target->disableState(GrDrawTarget::kEdgeAA_StateBit);
+ } else {
+ target->setVertexSourceToArray(layout, base, count);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
+ }
delete[] base;
return;
}
@@ -241,7 +325,7 @@ FINISHED:
int end = start + subpathVertCount[sp];
for (; i < end; ++i) {
double* inVertex = &inVertices[i * 3];
- *vertices.append() = GrPoint(inVertex[0], inVertex[1]);
+ *vertices.append() = GrPoint::Make(inVertex[0], inVertex[1]);
internal_gluTessVertex(tess, inVertex, reinterpret_cast<void*>(i));
}
internal_gluTessEndContour(tess);
@@ -275,3 +359,14 @@ void GrTesselatedPathRenderer::drawPathToStencil(GrDrawTarget* target,
const GrPoint* translate) {
GrAlwaysAssert(!"multipass stencil should not be needed");
}
+
+bool GrTesselatedPathRenderer::supportsAA(GrDrawTarget* target,
+ GrPathIter* path,
+ GrPathFill fill) {
+ int subpathCnt = 0;
+ int tol = GrPathUtils::gTolerance;
+ GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
+ return (subpathCnt == 1 &&
+ !IsFillInverted(fill) &&
+ path->convexHint() == kConvex_ConvexHint);
+}
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 09113e0..0222042 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -36,10 +36,15 @@ void GrTextContext::flushGlyphs() {
GrDrawTarget::AutoStateRestore asr(fDrawTarget);
// setup our sampler state for our text texture/atlas
-
+ GrSamplerState::Filter filter;
+ if (fExtMatrix.isIdentity()) {
+ filter = GrSamplerState::kNearest_Filter;
+ } else {
+ filter = GrSamplerState::kBilinear_Filter;
+ }
GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
GrSamplerState::kRepeat_WrapMode,
- !fExtMatrix.isIdentity());
+ filter);
fDrawTarget->setSamplerState(TEXT_STAGE, sampler);
GrAssert(GrIsALIGN4(fCurrVertex));
diff --git a/gpu/src/GrTexture.cpp b/gpu/src/GrTexture.cpp
index 1ea02a7..8df9c9e 100644
--- a/gpu/src/GrTexture.cpp
+++ b/gpu/src/GrTexture.cpp
@@ -16,6 +16,7 @@
#include "GrTexture.h"
#include "GrContext.h"
+#include "GrGpu.h"
bool GrRenderTarget::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
@@ -28,6 +29,30 @@ bool GrRenderTarget::readPixels(int left, int top, int width, int height,
config, buffer);
}
+void GrRenderTarget::flagAsNeedingResolve(const GrIRect* rect) {
+ if (kCanResolve_ResolveType == getResolveType()) {
+ if (NULL != rect) {
+ fResolveRect.join(*rect);
+ if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
+ fResolveRect.setEmpty();
+ }
+ } else {
+ fResolveRect.setLTRB(0, 0, this->width(), this->height());
+ }
+ }
+}
+
+void GrRenderTarget::overrideResolveRect(const GrIRect rect) {
+ fResolveRect = rect;
+ if (fResolveRect.isEmpty()) {
+ fResolveRect.setLargestInverted();
+ } else {
+ if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
+ fResolveRect.setLargestInverted();
+ }
+ }
+}
+
bool GrTexture::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
// go through context so that all necessary flushing occurs
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index a40d7bd..fef9784 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -11,7 +11,6 @@ SOURCE := \
GrGLTexture.cpp \
GrGLVertexBuffer.cpp \
GrGpu.cpp \
- GrGpuGLShaders2.cpp \
GrGpuGLFixed.cpp \
GrGpuFactory.cpp \
GrGLUtil.cpp \
diff --git a/gpu/src/gr_unittests.cpp b/gpu/src/gr_unittests.cpp
index fd27f19..320dd15 100644
--- a/gpu/src/gr_unittests.cpp
+++ b/gpu/src/gr_unittests.cpp
@@ -152,7 +152,6 @@ void gr_run_unittests() {
test_tdarray();
test_bsearch();
test_binHashKey();
- GrMatrix::UnitTest();
GrRedBlackTree<int>::UnitTest();
GrPath::ConvexUnitTest();
GrDrawTarget::VertexLayoutUnitTest();
diff --git a/gpu/src/mac/GrGLDefaultInterface_mac.cpp b/gpu/src/mac/GrGLDefaultInterface_mac.cpp
index 802d717..b9396fa 100644
--- a/gpu/src/mac/GrGLDefaultInterface_mac.cpp
+++ b/gpu/src/mac/GrGLDefaultInterface_mac.cpp
@@ -91,14 +91,29 @@ void GrGLSetDefaultGLInterface() {
gDefaultInterface.fTexEnvi = glTexEnvi;
// mac uses GLenum for internalFormat param (non-standard)
// amounts to int vs. uint.
- gDefaultInterface.fTexImage2D =
- (GrGLInterface::GrGLTexImage2DProc)glTexImage2D;
+ gDefaultInterface.fTexImage2D = (GrGLTexImage2DProc)glTexImage2D;
gDefaultInterface.fTexParameteri = glTexParameteri;
gDefaultInterface.fTexSubImage2D = glTexSubImage2D;
- gDefaultInterface.fUniform1fv = glUniform1fv;
+ gDefaultInterface.fUniform1f = glUniform1f;
gDefaultInterface.fUniform1i = glUniform1i;
+ gDefaultInterface.fUniform1fv = glUniform1fv;
+ gDefaultInterface.fUniform1iv = glUniform1iv;
+ gDefaultInterface.fUniform2f = glUniform2f;
+ gDefaultInterface.fUniform2i = glUniform2i;
+ gDefaultInterface.fUniform2fv = glUniform2fv;
+ gDefaultInterface.fUniform2iv = glUniform2iv;
+ gDefaultInterface.fUniform3f = glUniform3f;
+ gDefaultInterface.fUniform3i = glUniform3i;
+ gDefaultInterface.fUniform3fv = glUniform3fv;
+ gDefaultInterface.fUniform3iv = glUniform3iv;
+ gDefaultInterface.fUniform4f = glUniform4f;
+ gDefaultInterface.fUniform4i = glUniform4i;
+ gDefaultInterface.fUniform4fv = glUniform4fv;
+ gDefaultInterface.fUniform4iv = glUniform4iv;
gDefaultInterface.fUniform4fv = glUniform4fv;
+ gDefaultInterface.fUniformMatrix2fv = glUniformMatrix2fv;
gDefaultInterface.fUniformMatrix3fv = glUniformMatrix3fv;
+ gDefaultInterface.fUniformMatrix4fv = glUniformMatrix4fv;
gDefaultInterface.fUnmapBuffer = glUnmapBuffer;
gDefaultInterface.fUseProgram = glUseProgram;
gDefaultInterface.fVertexAttrib4fv = glVertexAttrib4fv;
diff --git a/gpu/src/unix/GrGLDefaultInterface_unix.cpp b/gpu/src/unix/GrGLDefaultInterface_unix.cpp
new file mode 100644
index 0000000..ba67065
--- /dev/null
+++ b/gpu/src/unix/GrGLDefaultInterface_unix.cpp
@@ -0,0 +1,183 @@
+/*
+ Copyright 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "GrGLInterface.h"
+
+#include <GL/glx.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glu.h>
+
+#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGL ## F ## Proc) \
+ glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F));
+#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGL ## F ## Proc) \
+ glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F #S));
+
+void GrGLSetDefaultGLInterface() {
+ static GrGLInterface gDefaultInterface;
+ static bool gDefaultInterfaceInit;
+ if (!gDefaultInterfaceInit && NULL != glXGetCurrentContext()) {
+ int major, minor;
+ const char* versionString = (const char*) glGetString(GL_VERSION);
+ const char* extString = (const char*) glGetString(GL_EXTENSIONS);
+ gl_version_from_string(&major, &minor, versionString);
+
+ if (major == 1 && minor < 5) {
+ // We must have array and element_array buffer objects.
+ return;
+ }
+
+ gDefaultInterface.fActiveTexture = glActiveTexture;
+ GR_GL_GET_PROC(AttachShader);
+ GR_GL_GET_PROC(BindAttribLocation);
+ GR_GL_GET_PROC(BindBuffer);
+ gDefaultInterface.fBindTexture = glBindTexture;
+ gDefaultInterface.fBlendColor = glBlendColor;
+ gDefaultInterface.fBlendFunc = glBlendFunc;
+ GR_GL_GET_PROC(BufferData);
+ GR_GL_GET_PROC(BufferSubData);
+ gDefaultInterface.fClear = glClear;
+ gDefaultInterface.fClearColor = glClearColor;
+ gDefaultInterface.fClearStencil = glClearStencil;
+ gDefaultInterface.fClientActiveTexture = glClientActiveTexture;
+ gDefaultInterface.fColorMask = glColorMask;
+ gDefaultInterface.fColorPointer = glColorPointer;
+ gDefaultInterface.fColor4ub = glColor4ub;
+ GR_GL_GET_PROC(CompileShader);
+ gDefaultInterface.fCompressedTexImage2D = glCompressedTexImage2D;
+ GR_GL_GET_PROC(CreateProgram);
+ GR_GL_GET_PROC(CreateShader);
+ gDefaultInterface.fCullFace = glCullFace;
+ GR_GL_GET_PROC(DeleteBuffers);
+ GR_GL_GET_PROC(DeleteProgram);
+ GR_GL_GET_PROC(DeleteShader);
+ gDefaultInterface.fDeleteTextures = glDeleteTextures;
+ gDefaultInterface.fDepthMask = glDepthMask;
+ gDefaultInterface.fDisable = glDisable;
+ gDefaultInterface.fDisableClientState = glDisableClientState;
+ GR_GL_GET_PROC(DisableVertexAttribArray);
+ gDefaultInterface.fDrawArrays = glDrawArrays;
+ gDefaultInterface.fDrawElements = glDrawElements;
+ gDefaultInterface.fEnable = glEnable;
+ gDefaultInterface.fEnableClientState = glEnableClientState;
+ GR_GL_GET_PROC(EnableVertexAttribArray);
+ gDefaultInterface.fFrontFace = glFrontFace;
+ GR_GL_GET_PROC(GenBuffers);
+ GR_GL_GET_PROC(GetBufferParameteriv);
+ gDefaultInterface.fGetError = glGetError;
+ gDefaultInterface.fGetIntegerv = glGetIntegerv;
+ GR_GL_GET_PROC(GetProgramInfoLog);
+ GR_GL_GET_PROC(GetProgramiv);
+ GR_GL_GET_PROC(GetShaderInfoLog);
+ GR_GL_GET_PROC(GetShaderiv);
+ gDefaultInterface.fGetString = glGetString;
+ gDefaultInterface.fGenTextures = glGenTextures;
+ GR_GL_GET_PROC(GetUniformLocation);
+ gDefaultInterface.fLineWidth = glLineWidth;
+ GR_GL_GET_PROC(LinkProgram);
+ gDefaultInterface.fLoadMatrixf = glLoadMatrixf;
+ GR_GL_GET_PROC(MapBuffer);
+ gDefaultInterface.fMatrixMode = glMatrixMode;
+ gDefaultInterface.fPointSize = glPointSize;
+ gDefaultInterface.fPixelStorei = glPixelStorei;
+ gDefaultInterface.fReadPixels = glReadPixels;
+ gDefaultInterface.fScissor = glScissor;
+ gDefaultInterface.fShadeModel = glShadeModel;
+ GR_GL_GET_PROC(ShaderSource);
+ gDefaultInterface.fStencilFunc = glStencilFunc;
+ GR_GL_GET_PROC(StencilFuncSeparate);
+ gDefaultInterface.fStencilMask = glStencilMask;
+ GR_GL_GET_PROC(StencilMaskSeparate);
+ gDefaultInterface.fStencilOp = glStencilOp;
+ GR_GL_GET_PROC(StencilOpSeparate);
+ gDefaultInterface.fTexCoordPointer = glTexCoordPointer;
+ gDefaultInterface.fTexEnvi = glTexEnvi;
+ gDefaultInterface.fTexImage2D = glTexImage2D;
+ gDefaultInterface.fTexParameteri = glTexParameteri;
+ gDefaultInterface.fTexSubImage2D = glTexSubImage2D;
+ GR_GL_GET_PROC(Uniform1f);
+ GR_GL_GET_PROC(Uniform1i);
+ GR_GL_GET_PROC(Uniform1fv);
+ GR_GL_GET_PROC(Uniform1iv);
+ GR_GL_GET_PROC(Uniform2f);
+ GR_GL_GET_PROC(Uniform2i);
+ GR_GL_GET_PROC(Uniform2fv);
+ GR_GL_GET_PROC(Uniform2iv);
+ GR_GL_GET_PROC(Uniform3f);
+ GR_GL_GET_PROC(Uniform3i);
+ GR_GL_GET_PROC(Uniform3fv);
+ GR_GL_GET_PROC(Uniform3iv);
+ GR_GL_GET_PROC(Uniform4f);
+ GR_GL_GET_PROC(Uniform4i);
+ GR_GL_GET_PROC(Uniform4fv);
+ GR_GL_GET_PROC(Uniform4iv);
+ GR_GL_GET_PROC(UniformMatrix2fv);
+ GR_GL_GET_PROC(UniformMatrix3fv);
+ GR_GL_GET_PROC(UniformMatrix4fv);
+ GR_GL_GET_PROC(UnmapBuffer);
+ GR_GL_GET_PROC(UseProgram);
+ GR_GL_GET_PROC(VertexAttrib4fv);
+ GR_GL_GET_PROC(VertexAttribPointer);
+ gDefaultInterface.fVertexPointer = glVertexPointer;
+ gDefaultInterface.fViewport = glViewport;
+
+ // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
+ // GL_ARB_framebuffer_object doesn't use ARB suffix.)
+ if (major >= 3 || has_gl_extension_from_string(
+ "GL_ARB_framebuffer_object", extString)) {
+ GR_GL_GET_PROC(GenFramebuffers);
+ GR_GL_GET_PROC(BindFramebuffer);
+ GR_GL_GET_PROC(FramebufferTexture2D);
+ GR_GL_GET_PROC(CheckFramebufferStatus);
+ GR_GL_GET_PROC(DeleteFramebuffers);
+ GR_GL_GET_PROC(RenderbufferStorage);
+ GR_GL_GET_PROC(GenRenderbuffers);
+ GR_GL_GET_PROC(DeleteRenderbuffers);
+ GR_GL_GET_PROC(FramebufferRenderbuffer);
+ GR_GL_GET_PROC(BindRenderbuffer);
+ GR_GL_GET_PROC(RenderbufferStorageMultisample);
+ GR_GL_GET_PROC(BlitFramebuffer);
+ } else if (has_gl_extension_from_string("GL_EXT_framebuffer_object",
+ extString)) {
+ GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
+ GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
+ GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
+ GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
+ GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
+ GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
+ GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
+ GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
+ GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
+ GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
+ if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
+ extString)) {
+ GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
+ }
+ if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
+ extString)) {
+ GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
+ }
+ } else {
+ // we must have FBOs
+ return;
+ }
+ gDefaultInterface.fBindingsExported = kDesktop_GrGLBinding;
+
+ gDefaultInterfaceInit = true;
+ }
+ if (gDefaultInterfaceInit)
+ GrGLSetGLInterface(&gDefaultInterface);
+}
diff --git a/gpu/src/win/GrGLDefaultInterface_win.cpp b/gpu/src/win/GrGLDefaultInterface_win.cpp
index 6227015..53fb26a 100644
--- a/gpu/src/win/GrGLDefaultInterface_win.cpp
+++ b/gpu/src/win/GrGLDefaultInterface_win.cpp
@@ -25,8 +25,8 @@
* Otherwise, a springboard would be needed that hides the calling convention.
*/
-#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) wglGetProcAddress("gl" #F);
-#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) wglGetProcAddress("gl" #F #S);
+#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGL ## F ## Proc) wglGetProcAddress("gl" #F);
+#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGL ## F ## Proc) wglGetProcAddress("gl" #F #S);
void GrGLSetDefaultGLInterface() {
static GrGLInterface gDefaultInterface;
@@ -117,10 +117,25 @@ void GrGLSetDefaultGLInterface() {
GR_GL_GET_PROC(StencilFuncSeparate);
GR_GL_GET_PROC(StencilMaskSeparate);
GR_GL_GET_PROC(StencilOpSeparate);
- GR_GL_GET_PROC(Uniform1fv);
+ GR_GL_GET_PROC(Uniform1f);
GR_GL_GET_PROC(Uniform1i);
+ GR_GL_GET_PROC(Uniform1fv);
+ GR_GL_GET_PROC(Uniform1iv);
+ GR_GL_GET_PROC(Uniform2f);
+ GR_GL_GET_PROC(Uniform2i);
+ GR_GL_GET_PROC(Uniform2fv);
+ GR_GL_GET_PROC(Uniform2iv);
+ GR_GL_GET_PROC(Uniform3f);
+ GR_GL_GET_PROC(Uniform3i);
+ GR_GL_GET_PROC(Uniform3fv);
+ GR_GL_GET_PROC(Uniform3iv);
+ GR_GL_GET_PROC(Uniform4f);
+ GR_GL_GET_PROC(Uniform4i);
GR_GL_GET_PROC(Uniform4fv);
+ GR_GL_GET_PROC(Uniform4iv);
+ GR_GL_GET_PROC(UniformMatrix2fv);
GR_GL_GET_PROC(UniformMatrix3fv);
+ GR_GL_GET_PROC(UniformMatrix4fv);
GR_GL_GET_PROC(UseProgram);
GR_GL_GET_PROC(VertexAttrib4fv);
GR_GL_GET_PROC(VertexAttribPointer);