michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrCoordTransform_DEFINED michael@0: #define GrCoordTransform_DEFINED michael@0: michael@0: #include "GrEffect.h" michael@0: #include "SkMatrix.h" michael@0: #include "GrTexture.h" michael@0: #include "GrTypes.h" michael@0: michael@0: /** michael@0: * Coordinates available to GrEffect subclasses for requesting transformations. Transformed michael@0: * coordinates are made available in the the portion of fragment shader emitted by the effect. michael@0: */ michael@0: enum GrCoordSet { michael@0: /** michael@0: * The user-space coordinates that map to the fragment being rendered. These coords account for michael@0: * any change of coordinate system done on the CPU by GrContext before rendering, and also are michael@0: * correct for draws that take explicit local coords rather than inferring them from the michael@0: * primitive's positions (e.g. drawVertices). These are usually the coords a GrEffect wants. michael@0: */ michael@0: kLocal_GrCoordSet, michael@0: michael@0: /** michael@0: * The actual vertex position. Note that GrContext may not draw using the original view matrix michael@0: * specified by the caller, as it may have transformed vertices into another space. These are michael@0: * usually not the coordinates a GrEffect wants. michael@0: */ michael@0: kPosition_GrCoordSet michael@0: }; michael@0: michael@0: /** michael@0: * A class representing a linear transformation from one of the built-in coordinate sets (local or michael@0: * position). GrEffects just define these transformations, and the framework does the rest of the michael@0: * work to make the transformed coordinates available in their fragment shader. michael@0: */ michael@0: class GrCoordTransform : public SkNoncopyable { michael@0: public: michael@0: GrCoordTransform() { SkDEBUGCODE(fInEffect = false); } michael@0: michael@0: /** michael@0: * Create a transformation that maps [0, 1] to a texture's boundaries. michael@0: */ michael@0: GrCoordTransform(GrCoordSet sourceCoords, const GrTexture* texture) { michael@0: SkDEBUGCODE(fInEffect = false); michael@0: this->reset(sourceCoords, texture); michael@0: } michael@0: michael@0: /** michael@0: * Create a transformation from a matrix. The optional texture parameter is used to infer if the michael@0: * framework should internally do a y reversal to account for it being upside down by Skia's michael@0: * coord convention. michael@0: */ michael@0: GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) { michael@0: SkDEBUGCODE(fInEffect = false); michael@0: this->reset(sourceCoords, m, texture); michael@0: } michael@0: michael@0: void reset(GrCoordSet sourceCoords, const GrTexture* texture) { michael@0: SkASSERT(!fInEffect); michael@0: SkASSERT(NULL != texture); michael@0: this->reset(sourceCoords, GrEffect::MakeDivByTextureWHMatrix(texture), texture); michael@0: } michael@0: michael@0: void reset(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) { michael@0: SkASSERT(!fInEffect); michael@0: fSourceCoords = sourceCoords; michael@0: fMatrix = m; michael@0: fReverseY = NULL != texture && kBottomLeft_GrSurfaceOrigin == texture->origin(); michael@0: } michael@0: michael@0: GrCoordTransform& operator= (const GrCoordTransform& other) { michael@0: SkASSERT(!fInEffect); michael@0: fSourceCoords = other.fSourceCoords; michael@0: fMatrix = other.fMatrix; michael@0: fReverseY = other.fReverseY; michael@0: return *this; michael@0: } michael@0: michael@0: /** michael@0: * Access the matrix for editing. Note, this must be done before adding the transform to an michael@0: * effect, since effects are immutable. michael@0: */ michael@0: SkMatrix* accessMatrix() { michael@0: SkASSERT(!fInEffect); michael@0: return &fMatrix; michael@0: } michael@0: michael@0: bool operator== (const GrCoordTransform& other) const { michael@0: return fSourceCoords == other.fSourceCoords && michael@0: fMatrix.cheapEqualTo(other.fMatrix) && michael@0: fReverseY == other.fReverseY; michael@0: } michael@0: michael@0: GrCoordSet sourceCoords() const { return fSourceCoords; } michael@0: const SkMatrix& getMatrix() const { return fMatrix; } michael@0: bool reverseY() const { return fReverseY; } michael@0: michael@0: private: michael@0: GrCoordSet fSourceCoords; michael@0: SkMatrix fMatrix; michael@0: bool fReverseY; michael@0: michael@0: typedef SkNoncopyable INHERITED; michael@0: michael@0: #ifdef SK_DEBUG michael@0: public: michael@0: void setInEffect() const { fInEffect = true; } michael@0: private: michael@0: mutable bool fInEffect; michael@0: #endif michael@0: }; michael@0: michael@0: #endif