# robertphillips
imagefiltersscaled
+
+#bsalomon - changes to texture coord precision
+imageblur2
+imageblur_large
+imageblur
+downsamplebitmap_checkerboard_high_512_256
+downsamplebitmap_checkerboard_medium_512_256
+downsamplebitmap_checkerboard_low_512_256
+imagefilterscropped
+downsamplebitmap_text_medium_72.00pt
+downsamplebitmap_text_high_72.00pt
+downsamplebitmap_text_low_72.00pt
+downsamplebitmap_image_high_mandrill_132x132_12x12.astc
+downsamplebitmap_image_medium_mandrill_132x132_12x12.astc
+downsamplebitmap_image_low_mandrill_132x132_12x12.astc
+downsamplebitmap_image_high_mandrill_512.png
+downsamplebitmap_image_medium_mandrill_512.png
+downsamplebitmap_image_low_mandrill_512.png
+imagefiltersbase
+simpleblurroundrect
+blurcircles
+colortype_xfermodes
+
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+
+int make_bm(SkBitmap* bm, int height) {
+ static const int kRadius = 22;
+ static const int kMargin = 8;
+ static const SkScalar kStartAngle = 0;
+ static const SkScalar kDAngle = 25;
+ static const SkScalar kSweep = 320;
+ static const SkScalar kThickness = 8;
+
+ int count = (height / (2 * kRadius + kMargin));
+ height = count * (2 * kRadius + kMargin);
+
+ bm->allocN32Pixels(2 * (kRadius + kMargin), height);
+ SkRandom random;
+
+ SkCanvas wholeCanvas(*bm);
+ wholeCanvas.clear(0x00000000);
+
+ SkScalar angle = kStartAngle;
+ for (int i = 0; i < count; ++i) {
+ SkPaint paint;
+ // The sw rasterizer disables AA for large canvii. So we make a small canvas for each draw.
+ SkBitmap smallBM;
+ SkIRect subRect = SkIRect::MakeXYWH(0, i * (kMargin + 2 * kRadius),
+ 2 * kRadius + kMargin, 2 * kRadius + kMargin);
+ bm->extractSubset(&smallBM, subRect);
+ SkCanvas canvas(smallBM);
+ canvas.translate(kMargin + kRadius, kMargin + kRadius);
+
+ paint.setAntiAlias(true);
+ paint.setColor(random.nextU() | 0xFF000000);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(kThickness);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ SkScalar radius = kRadius - kThickness / 2;
+ SkRect bounds = SkRect::MakeLTRB(-radius, -radius, radius, radius);
+
+ canvas.drawArc(bounds, angle, kSweep, false, paint);
+ angle += kDAngle;
+ }
+ bm->setImmutable();
+ return count;
+}
+
+class TallStretchedBitmapsGM : public skiagm::GM {
+public:
+ TallStretchedBitmapsGM() {}
+
+protected:
+ SkString onShortName() SK_OVERRIDE {
+ return SkString("tall_stretched_bitmaps");
+ }
+
+ SkISize onISize() SK_OVERRIDE {
+ return SkISize::Make(750, 750);
+ }
+
+ void onOnceBeforeDraw() SK_OVERRIDE {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fTallBmps); ++i) {
+ int h = (4 + i) * 1024;
+
+ fTallBmps[i].fItemCnt = make_bm(&fTallBmps[i].fBmp, h);
+ }
+ }
+
+ void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ canvas->scale(1.3f, 1.3f);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fTallBmps); ++i) {
+ SkASSERT(fTallBmps[i].fItemCnt > 10);
+ SkBitmap bmp = fTallBmps[i].fBmp;
+ // Draw the last 10 elements of the bitmap.
+ int startItem = fTallBmps[i].fItemCnt - 10;
+ int itemHeight = bmp.height() / fTallBmps[i].fItemCnt;
+ SkIRect subRect = SkIRect::MakeLTRB(0, startItem * itemHeight,
+ bmp.width(), bmp.height());
+ SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bmp.width()), 10.f * itemHeight);
+ SkPaint paint;
+ paint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ canvas->drawBitmapRect(bmp, &subRect, dstRect, &paint);
+ canvas->translate(SkIntToScalar(bmp.width() + 10), 0);
+ }
+ }
+
+ uint32_t onGetFlags() const SK_OVERRIDE {
+ // This GM causes issues in replay modes.
+ return kSkipTiled_Flag | kNoBBH_Flag | kSkipPicture_Flag;
+ }
+
+private:
+ struct {
+ SkBitmap fBmp;
+ int fItemCnt;
+ } fTallBmps[8];
+ typedef skiagm::GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_GM(return SkNEW(TallStretchedBitmapsGM);)
+
'../gm/testimagefilters.cpp',
'../gm/texdata.cpp',
'../gm/variedtext.cpp',
+ '../gm/tallstretchedbitmaps.cpp',
'../gm/textblob.cpp',
'../gm/textblobshader.cpp',
'../gm/texturedomaineffect.cpp',
'<(skia_src_path)/gpu/GrClipMaskManager.h',
'<(skia_src_path)/gpu/GrClipMaskManager.cpp',
'<(skia_src_path)/gpu/GrContext.cpp',
+ '<(skia_src_path)/gpu/GrCoordTransform.cpp',
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.cpp',
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.h',
'<(skia_src_path)/gpu/GrDefaultPathRenderer.cpp',
#include "SkMatrix.h"
#include "GrTexture.h"
#include "GrTypes.h"
+#include "GrShaderVar.h"
/**
* Coordinates available to GrProcessor subclasses for requesting transformations. Transformed
* coordinates are made available in the the portion of fragment shader emitted by the effect.
+ *
+ * The precision of the shader var that interpolates the transformed coordinates can be specified.
*/
enum GrCoordSet {
/**
GrCoordTransform() { SkDEBUGCODE(fInProcessor = false); }
/**
- * Create a transformation that maps [0, 1] to a texture's boundaries.
+ * Create a transformation that maps [0, 1] to a texture's boundaries. The precision is inferred
+ * from the texture size.
*/
GrCoordTransform(GrCoordSet sourceCoords, const GrTexture* texture) {
+ SkASSERT(texture);
SkDEBUGCODE(fInProcessor = false);
this->reset(sourceCoords, texture);
}
/**
- * Create a transformation from a matrix. The optional texture parameter is used to infer if the
+ * Create a transformation from a matrix. The texture parameter is used to infer if the
* framework should internally do a y reversal to account for it being upside down by Skia's
- * coord convention.
+ * coord convention and the precision of the shader variables used to implement the coord
+ * transform.
*/
- GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) {
+ GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture) {
SkDEBUGCODE(fInProcessor = false);
+ SkASSERT(texture);
this->reset(sourceCoords, m, texture);
}
+ /**
+ * Create a transformation that applies the matrix to a coord set.
+ */
+ GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m,
+ GrShaderVar::Precision precision = GrShaderVar::kDefault_Precision) {
+ SkDEBUGCODE(fInProcessor = false);
+ this->reset(sourceCoords, m, precision);
+ }
+
void reset(GrCoordSet sourceCoords, const GrTexture* texture) {
SkASSERT(!fInProcessor);
SkASSERT(texture);
this->reset(sourceCoords, MakeDivByTextureWHMatrix(texture), texture);
}
- void reset(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) {
- SkASSERT(!fInProcessor);
- fSourceCoords = sourceCoords;
- fMatrix = m;
- fReverseY = texture && kBottomLeft_GrSurfaceOrigin == texture->origin();
- }
+ void reset(GrCoordSet, const SkMatrix&, const GrTexture*);
+ void reset(GrCoordSet sourceCoords, const SkMatrix& m,
+ GrShaderVar::Precision precision = GrShaderVar::kDefault_Precision);
- GrCoordTransform& operator= (const GrCoordTransform& other) {
+ GrCoordTransform& operator= (const GrCoordTransform& that) {
SkASSERT(!fInProcessor);
- fSourceCoords = other.fSourceCoords;
- fMatrix = other.fMatrix;
- fReverseY = other.fReverseY;
+ fSourceCoords = that.fSourceCoords;
+ fMatrix = that.fMatrix;
+ fReverseY = that.fReverseY;
+ fPrecision = that.fPrecision;
return *this;
}
return &fMatrix;
}
- bool operator== (const GrCoordTransform& that) const {
+ bool operator==(const GrCoordTransform& that) const {
return fSourceCoords == that.fSourceCoords &&
fMatrix.cheapEqualTo(that.fMatrix) &&
- fReverseY == that.fReverseY;
+ fReverseY == that.fReverseY &&
+ fPrecision == that.fPrecision;
}
- bool operator!= (const GrCoordTransform& that) const { return !(*this == that); }
+ bool operator!=(const GrCoordTransform& that) const { return !(*this == that); }
GrCoordSet sourceCoords() const { return fSourceCoords; }
const SkMatrix& getMatrix() const { return fMatrix; }
bool reverseY() const { return fReverseY; }
+ GrShaderVar::Precision precision() const { return fPrecision; }
/** Useful for effects that want to insert a texture matrix that is implied by the texture
dimensions */
}
private:
- GrCoordSet fSourceCoords;
- SkMatrix fMatrix;
- bool fReverseY;
-
+ GrCoordSet fSourceCoords;
+ SkMatrix fMatrix;
+ bool fReverseY;
+ GrShaderVar::Precision fPrecision;
typedef SkNoncopyable INHERITED;
#ifdef SK_DEBUG
// Default precision is medium. This is because on OpenGL ES 2 highp support is not
// guaranteed. On (non-ES) OpenGL the specifiers have no effect on precision.
kDefault_Precision = kMedium_Precision,
+
+ kLast_Precision = kHigh_Precision
};
+ static const int kPrecisionCount = kLast_Precision + 1;
/**
* Defaults to a float with no precision specifier
* found in the LICENSE file.
*/
-
-
#ifndef GrTypes_DEFINED
#define GrTypes_DEFINED
};
static const int kGrSLTypeCount = kLast_GrSLType + 1;
+enum GrShaderType {
+ kVertex_GrShaderType,
+ kGeometry_GrShaderType,
+ kFragment_GrShaderType,
+
+ kLastkFragment_GrShaderType = kFragment_GrShaderType
+};
+static const int kGrShaderTypeCount = kLastkFragment_GrShaderType + 1;
+
/**
* Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers.
*/
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrCoordTransform.h"
+#include "GrContext.h"
+#include "GrDrawTargetCaps.h"
+#include "GrGpu.h"
+
+void GrCoordTransform::reset(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture) {
+ SkASSERT(texture);
+ SkASSERT(!fInProcessor);
+
+ fSourceCoords = sourceCoords;
+ fMatrix = m;
+ fReverseY = kBottomLeft_GrSurfaceOrigin == texture->origin();
+
+ // Always start at kDefault. Then if precisions differ we see if the precision needs to be
+ // increased. Our rule is that we want at least 4 subpixel values in the representation for
+ // coords between 0 to 1. Note that this still might not be enough when drawing with repeat
+ // or mirror-repeat modes but that case can be arbitrarily bad.
+ fPrecision = GrShaderVar::kDefault_Precision;
+ if (texture->getContext()) {
+ const GrDrawTargetCaps* caps = texture->getContext()->getGpu()->caps();
+ if (caps->floatPrecisionVaries()) {
+ int maxD = SkTMax(texture->width(), texture->height());
+ const GrDrawTargetCaps::PrecisionInfo* info;
+ info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, fPrecision);
+ do {
+ SkASSERT(info->supported());
+ // Make sure there is at least 2 bits of subpixel precision in the range of
+ // texture coords from 0.5 to 1.0.
+ if ((2 << info->fBits) / maxD > 4) {
+ break;
+ }
+ if (GrShaderVar::kHigh_Precision == fPrecision) {
+ break;
+ }
+ GrShaderVar::Precision nextP = static_cast<GrShaderVar::Precision>(fPrecision + 1);
+ info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, nextP);
+ if (!info->supported()) {
+ break;
+ }
+ fPrecision = nextP;
+ } while (true);
+ }
+ }
+}
+
+void GrCoordTransform::reset(GrCoordSet sourceCoords,
+ const SkMatrix& m,
+ GrShaderVar::Precision precision) {
+ SkASSERT(!fInProcessor);
+ fSourceCoords = sourceCoords;
+ fMatrix = m;
+ fReverseY = false;
+ fPrecision = precision;
+}
fMaxTextureSize = 0;
fMaxSampleCount = 0;
+ fShaderPrecisionVaries = false;
+
memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
}
memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
+ fShaderPrecisionVaries = other.fShaderPrecisionVaries;
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ for (int p = 0; p < GrShaderVar::kPrecisionCount; ++p) {
+ fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p];
+ }
+ }
return *this;
}
return str;
}
+static const char* shader_type_to_string(GrShaderType type) {
+ switch (type) {
+ case kVertex_GrShaderType:
+ return "vertex";
+ case kGeometry_GrShaderType:
+ return "geometry";
+ case kFragment_GrShaderType:
+ return "fragment";
+ }
+ return "";
+}
+
+static const char* precision_to_string(GrShaderVar::Precision p) {
+ switch (p) {
+ case GrShaderVar::kLow_Precision:
+ return "low";
+ case GrShaderVar::kMedium_Precision:
+ return "medium";
+ case GrShaderVar::kHigh_Precision:
+ return "high";
+ }
+ return "";
+}
+
SkString GrDrawTargetCaps::dump() const {
SkString r;
static const char* gNY[] = {"NO", "YES"};
gNY[fConfigTextureSupport[i]]);
}
+ r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
+
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ GrShaderType shaderType = static_cast<GrShaderType>(s);
+ r.appendf("\t%s:\n", shader_type_to_string(shaderType));
+ for (int p = 0; p < GrShaderVar::kPrecisionCount; ++p) {
+ if (fFloatPrecisions[s][p].supported()) {
+ GrShaderVar::Precision precision = static_cast<GrShaderVar::Precision>(p);
+ r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
+ precision_to_string(precision),
+ fFloatPrecisions[s][p].fLogRangeLow,
+ fFloatPrecisions[s][p].fLogRangeHigh,
+ fFloatPrecisions[s][p].fBits);
+ }
+ }
+ }
+
return r;
}
#define GrDrawTargetCaps_DEFINED
#include "GrTypes.h"
+#include "GrTypesPriv.h"
+#include "GrShaderVar.h"
#include "SkRefCnt.h"
#include "SkString.h"
public:
SK_DECLARE_INST_COUNT(GrDrawTargetCaps)
+ /** Info about shader variable precision within a given shader stage. That is, this info
+ is relevant to a float (or vecNf) variable declared with a GrShaderVar::Precision
+ in a given GrShaderType. The info here is hoisted from the OpenGL spec. */
+ struct PrecisionInfo {
+ PrecisionInfo() {
+ fLogRangeLow = 0;
+ fLogRangeHigh = 0;
+ fBits = 0;
+ }
+
+ /** Is this precision level allowed in the shader stage? */
+ bool supported() const { return 0 != fBits; }
+
+ bool operator==(const PrecisionInfo& that) const {
+ return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh &&
+ fBits == that.fBits;
+ }
+ bool operator!=(const PrecisionInfo& that) const { return !(*this == that); }
+
+ /** floor(log2(|min_value|)) */
+ int fLogRangeLow;
+ /** floor(log2(|max_value|)) */
+ int fLogRangeHigh;
+ /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
+ struct) :
+ """
+ If the smallest representable value greater than 1 is 1 + e, then fBits will
+ contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
+ 2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
+ """
+ */
+ int fBits;
+ };
+
+
GrDrawTargetCaps() : fUniqueID(CreateUniqueID()) {
this->reset();
}
return fConfigTextureSupport[config];
}
+ /**
+ * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
+ * given shader type. If the shader type is not supported or the precision level is not
+ * supported in that shader type then the returned struct will report false when supported() is
+ * called.
+ */
+ const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
+ GrShaderVar::Precision precision) const {
+ return fFloatPrecisions[shaderType][precision];
+ };
+
+ /**
+ * Is there any difference between the float shader variable precision types? If this is true
+ * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
+ * report the same info for all precisions in all shader types.
+ */
+ bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
+
/**
* Gets an id that is unique for this GrDrawTargetCaps object. It is static in that it does
* not change when the content of the GrDrawTargetCaps object changes. This will never return
bool fConfigRenderSupport[kGrPixelConfigCnt][2];
bool fConfigTextureSupport[kGrPixelConfigCnt];
+ bool fShaderPrecisionVaries;
+ PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][GrShaderVar::kPrecisionCount];
+
private:
static uint32_t CreateUniqueID();
this->initConfigTexturableTable(ctxInfo, gli);
this->initConfigRenderableTable(ctxInfo);
+ this->initShaderPrecisionTable(ctxInfo, gli);
+
return true;
}
fStencilVerifiedColorConfigs.push_back_n(fStencilFormats.count());
}
+static GrGLenum precision_to_gl_float_type(GrShaderVar::Precision p) {
+ switch (p) {
+ case GrShaderVar::kLow_Precision:
+ return GR_GL_LOW_FLOAT;
+ case GrShaderVar::kMedium_Precision:
+ return GR_GL_MEDIUM_FLOAT;
+ case GrShaderVar::kHigh_Precision:
+ return GR_GL_HIGH_FLOAT;
+ }
+ SkFAIL("Unknown precision.");
+ return -1;
+}
+
+static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
+ switch (type) {
+ case kVertex_GrShaderType:
+ return GR_GL_VERTEX_SHADER;
+ case kGeometry_GrShaderType:
+ return GR_GL_GEOMETRY_SHADER;
+ case kFragment_GrShaderType:
+ return GR_GL_FRAGMENT_SHADER;
+ }
+ SkFAIL("Unknown shader type.");
+ return -1;
+}
+
+void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* intf) {
+ if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4,1) ||
+ ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ if (kGeometry_GrShaderType != s || fGeometryShaderSupport) {
+ GrShaderType shaderType = static_cast<GrShaderType>(s);
+ GrGLenum glShader = shader_type_to_gl_shader(shaderType);
+ PrecisionInfo* first = NULL;
+ fShaderPrecisionVaries = false;
+ for (int p = 0; p < GrShaderVar::kPrecisionCount; ++p) {
+ GrShaderVar::Precision precision = static_cast<GrShaderVar::Precision>(p);
+ GrGLenum glPrecision = precision_to_gl_float_type(precision);
+ GrGLint range[2];
+ GrGLint bits;
+ GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
+ if (bits) {
+ fFloatPrecisions[s][p].fLogRangeLow = range[0];
+ fFloatPrecisions[s][p].fLogRangeHigh = range[1];
+ fFloatPrecisions[s][p].fBits = bits;
+ if (!first) {
+ first = &fFloatPrecisions[s][p];
+ } else if (!fShaderPrecisionVaries) {
+ fShaderPrecisionVaries = (*first != fFloatPrecisions[s][p]);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
+ fShaderPrecisionVaries = false;
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ if (kGeometry_GrShaderType != s || fGeometryShaderSupport) {
+ for (int p = 0; p < GrShaderVar::kPrecisionCount; ++p) {
+ fFloatPrecisions[s][p].fLogRangeLow = 127;
+ fFloatPrecisions[s][p].fLogRangeHigh = 127;
+ fFloatPrecisions[s][p].fBits = 23;
+ }
+ }
+ }
+ }
+}
+
+
void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
GrPixelConfig config,
const GrGLStencilBuffer::Format& format) {
void initConfigRenderableTable(const GrGLContextInfo&);
void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*);
- bool doReadPixelsSupported(const GrGLInterface* intf,
- GrGLenum format,
- GrGLenum type) const;
+ // Must be called after fGeometryShaderSupport is initialized.
+ void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
+
+ bool doReadPixelsSupported(const GrGLInterface* intf, GrGLenum format, GrGLenum type) const;
// tracks configs that have been verified to pass the FBO completeness when
// used as a color attachment
#include "SkChecksum.h"
#include "gl/builders/GrGLFragmentShaderBuilder.h"
-/**
- * The key for an individual coord transform is made up of a matrix type and a bit that
- * indicates the source of the input coords.
- */
-enum {
- kMatrixTypeKeyBits = 1,
- kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
- kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
- kTransformKeyBits = kMatrixTypeKeyBits + 1,
-};
-
-/**
- * We specialize the vertex code for each of these matrix types.
- */
-enum MatrixType {
- kNoPersp_MatrixType = 0,
- kGeneral_MatrixType = 1,
-};
-
/**
* Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
* present in the texture's config. swizzleComponentMask indicates the channels present in the
return key;
}
-static uint32_t gen_transform_key(const GrPendingFragmentStage& stage,
- bool useExplicitLocalCoords) {
+/**
+ * The key for an individual coord transform is made up of a matrix type, a precision, and a bit
+ * that indicates the source of the input coords.
+ */
+enum {
+ kMatrixTypeKeyBits = 1,
+ kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
+
+ kPrecisionBits = 2,
+ kPrecisionShift = kMatrixTypeKeyBits,
+
+ kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
+
+ kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 1,
+};
+
+GR_STATIC_ASSERT(GrShaderVar::kHigh_Precision < (1 << kPrecisionBits));
+
+/**
+ * We specialize the vertex code for each of these matrix types.
+ */
+enum MatrixType {
+ kNoPersp_MatrixType = 0,
+ kGeneral_MatrixType = 1,
+};
+
+static uint32_t gen_transform_key(const GrPendingFragmentStage& stage, bool useExplicitLocalCoords) {
uint32_t totalKey = 0;
int numTransforms = stage.getProcessor()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) {
key |= kPositionCoords_Flag;
}
+
+ GR_STATIC_ASSERT(GrShaderVar::kPrecisionCount <= (1 << kPrecisionBits));
+ key |= (coordTransform.precision() << kPrecisionShift);
+
key <<= kTransformKeyBits * t;
+
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
totalKey |= key;
}
*(p) = GR_GL_INIT_ZERO; \
GR_GL_CALL(gl, GetRenderbufferParameteriv(t, pname, p)); \
} while (0)
+
#define GR_GL_GetTexLevelParameteriv(gl, t, l, pname, p) \
do { \
*(p) = GR_GL_INIT_ZERO; \
GR_GL_CALL(gl, GetTexLevelParameteriv(t, l, pname, p)); \
} while (0)
+#define GR_GL_GetShaderPrecisionFormat(gl, st, pt, range, precision) \
+ do { \
+ (range)[0] = GR_GL_INIT_ZERO; \
+ (range)[1] = GR_GL_INIT_ZERO; \
+ (*precision) = GR_GL_INIT_ZERO; \
+ GR_GL_CALL(gl, GetShaderPrecisionFormat(st, pt, range, precision)); \
+ } while (0)
+
////////////////////////////////////////////////////////////////////////////////
/**
const char* coords = useLocalCoords ? fVS.localCoords() : fVS.positionCoords();
GrGLVertToFrag v(varyingType);
- this->addCoordVarying(varyingName, &v, uniName, coords);
+ this->addVarying(varyingName, &v, processor->coordTransform(t).precision());
+ fCoordVaryings.push_back(TransformVarying(v, uniName, coords));
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
class GrGLUniformBuilder {
public:
enum ShaderVisibility {
- kVertex_Visibility = 0x1,
- kGeometry_Visibility = 0x2,
- kFragment_Visibility = 0x4,
+ kVertex_Visibility = 1 << kVertex_GrShaderType,
+ kGeometry_Visibility = 1 << kGeometry_GrShaderType,
+ kFragment_Visibility = 1 << kFragment_GrShaderType,
};
virtual ~GrGLUniformBuilder() {}
SkString fSourceCoords;
};
- void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
- const char* sourceCoords) {
- this->addVarying(name, v);
- fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
- }
-
const char* rtAdjustment() const { return "rtAdjustment"; }
// number of each input/output type in a single allocation block, used by many builders