add local-matrix to shader::context

BUG=skia:
R=scroggo@google.com, dominikg@chromium.org

Author: reed@google.com

Review URL: https://codereview.chromium.org/263293005

git-svn-id: http://skia.googlecode.com/svn/trunk@14592 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-05-06 17:16:03 +00:00
parent 7418bd8cad
commit 80116dcf1e
9 changed files with 46 additions and 52 deletions

View File

@ -123,17 +123,17 @@ public:
* ContextRec acts as a parameter bundle for creating Contexts.
*/
struct ContextRec {
ContextRec() : fDevice(NULL), fPaint(NULL), fMatrix(NULL) {}
ContextRec(const ContextRec& other)
: fDevice(other.fDevice), fPaint(other.fPaint), fMatrix(other.fMatrix) {}
ContextRec() : fDevice(NULL), fPaint(NULL), fMatrix(NULL), fLocalMatrix(NULL) {}
ContextRec(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
: fDevice(&device)
, fPaint(&paint)
, fMatrix(&matrix) {}
, fMatrix(&matrix)
, fLocalMatrix(NULL) {}
const SkBitmap* fDevice; // the bitmap we are drawing into
const SkPaint* fPaint; // the current paint associated with the draw
const SkMatrix* fMatrix; // the current matrix in the canvas
const SkBitmap* fDevice; // the bitmap we are drawing into
const SkPaint* fPaint; // the current paint associated with the draw
const SkMatrix* fMatrix; // the current matrix in the canvas
const SkMatrix* fLocalMatrix; // optional local matrix
};
class Context : public ::SkNoncopyable {
@ -200,14 +200,15 @@ public:
};
static MatrixClass ComputeMatrixClass(const SkMatrix&);
uint8_t getPaintAlpha() const { return fPaintAlpha; }
const SkMatrix& getTotalInverse() const { return fTotalInverse; }
MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
uint8_t getPaintAlpha() const { return fPaintAlpha; }
const SkMatrix& getTotalInverse() const { return fTotalInverse; }
MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
const SkMatrix& getCTM() const { return fCTM; }
private:
SkMatrix fTotalInverse;
uint8_t fPaintAlpha;
uint8_t fTotalInverseClass;
SkMatrix fCTM;
SkMatrix fTotalInverse;
uint8_t fPaintAlpha;
uint8_t fTotalInverseClass;
typedef SkNoncopyable INHERITED;
};

View File

@ -71,10 +71,7 @@ private:
// an Sk3DBlitter in SkDraw.cpp
// Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
// yet found a situation where the size below isn't big enough.
typedef SkSmallAllocator<3, sizeof(SkBitmapProcShader) +
sizeof(SkBitmapProcShader::BitmapProcShaderContext) +
sizeof(SkBitmapProcState) +
sizeof(void*) * 2> SkTBlitterAllocator;
typedef SkSmallAllocator<3, 768> SkTBlitterAllocator;
// If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
// the SkShader.

View File

@ -1,4 +1,3 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
#include "SkBlitter.h"
#include "SkAntiRun.h"
#include "SkColor.h"
@ -26,8 +24,7 @@ SkBlitter::~SkBlitter() {}
bool SkBlitter::isNullBlitter() const { return false; }
bool SkBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix) {
bool SkBlitter::resetShaderContext(const SkShader::ContextRec&) {
return true;
}
@ -1030,10 +1027,7 @@ SkShaderBlitter::~SkShaderBlitter() {
fShader->unref();
}
bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix) {
SkShader::ContextRec rec(device, paint, matrix);
bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) {
// Only destroy the old context if we have a new one. We need to ensure to have a
// live context in fShaderContext because the storage is owned by an SkSmallAllocator
// outside of this class.
@ -1045,6 +1039,7 @@ bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint&
// Need a valid context in fShaderContext's storage, so we can later (or our caller) call
// the in-place destructor.
SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec));
return false;
}
return ctx != NULL;
return true;
}

View File

@ -64,8 +64,7 @@ public:
/**
* Special methods for SkShaderBlitter. On all other classes this is a no-op.
*/
virtual bool resetShaderContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix);
virtual bool resetShaderContext(const SkShader::ContextRec&);
virtual SkShader::Context* getShaderContext() const;
///@name non-virtual helpers

View File

@ -41,8 +41,7 @@ public:
* Will create the context at the same location as the old one (this is safe
* because the shader itself is unchanged).
*/
virtual bool resetShaderContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix) SK_OVERRIDE;
virtual bool resetShaderContext(const SkShader::ContextRec&) SK_OVERRIDE;
virtual SkShader::Context* getShaderContext() const SK_OVERRIDE { return fShaderContext; }

View File

@ -2403,7 +2403,13 @@ bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const S
if (!m.invert(&im)) {
return false;
}
fDstToUnit.setConcat(im, this->getTotalInverse());
// We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix
// as our interators are intrinsically tied to the vertices, and nothing else.
SkMatrix ctmInv;
if (!this->getCTM().invert(&ctmInv)) {
return false;
}
fDstToUnit.setConcat(im, ctmInv);
return true;
}
@ -2556,18 +2562,13 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
VertState::Proc vertProc = state.chooseProc(vmode);
if (NULL != textures || NULL != colors) {
SkMatrix tempM;
SkMatrix savedLocalM;
if (shader) {
savedLocalM = shader->getLocalMatrix();
}
while (vertProc(&state)) {
if (NULL != textures) {
SkMatrix tempM;
if (texture_to_matrix(state, vertices, textures, &tempM)) {
tempM.postConcat(savedLocalM);
shader->setLocalMatrix(tempM);
if (!blitter->resetShaderContext(*fBitmap, p, *fMatrix)) {
SkShader::ContextRec rec(*fBitmap, p, *fMatrix);
rec.fLocalMatrix = &tempM;
if (!blitter->resetShaderContext(rec)) {
continue;
}
}
@ -2603,11 +2604,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
};
SkScan::FillTriangle(tmp, *fRC, blitter.get());
}
// now restore the shader's original local matrix
if (NULL != shader) {
shader->setLocalMatrix(savedLocalM);
}
} else {
// no colors[] and no texture
HairProc hairProc = ChooseHairProc(paint.isAntiAlias());

View File

@ -52,7 +52,7 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
fPicture->flatten(buffer);
}
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const {
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const {
SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
SkMatrix m;
@ -61,6 +61,9 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const {
} else {
m = matrix;
}
if (localM) {
m.preConcat(*localM);
}
// Use a rotation-invariant scale
SkPoint scale;
@ -115,7 +118,7 @@ size_t SkPictureShader::contextSize() const {
}
SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const {
SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix));
SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix));
if (NULL == bitmapShader.get()) {
return NULL;
}
@ -190,7 +193,7 @@ void SkPictureShader::toString(SkString* str) const {
#if SK_SUPPORT_GPU
GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(context->getMatrix()));
SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(context->getMatrix(), NULL));
if (!bitmapShader) {
return NULL;
}

View File

@ -41,7 +41,7 @@ protected:
private:
SkPictureShader(SkPicture*, TileMode, TileMode, const SkMatrix* = NULL);
SkShader* refBitmapShader(const SkMatrix&) const;
SkShader* refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix) const;
SkPicture* fPicture;
TileMode fTmx, fTmy;

View File

@ -53,6 +53,10 @@ bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse
total.setConcat(*m, this->getLocalMatrix());
m = &total;
}
if (rec.fLocalMatrix) {
total.setConcat(*m, *rec.fLocalMatrix);
m = &total;
}
return m->invert(totalInverse);
}
@ -63,7 +67,7 @@ SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage)
return this->onCreateContext(rec, storage);
}
SkShader::Context* SkShader::onCreateContext(const ContextRec&, void*) const {
SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const {
return NULL;
}
@ -72,7 +76,7 @@ size_t SkShader::contextSize() const {
}
SkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
: fShader(shader)
: fShader(shader), fCTM(*rec.fMatrix)
{
// Because the context parameters must be valid at this point, we know that the matrix is
// invertible.