1d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com/*
2d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com * Copyright 2012 Google Inc.
3d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com *
4d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
5d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com * found in the LICENSE file.
6d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com */
7d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
8d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com#ifndef GrGLEffectMatrix_DEFINED
9d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com#define GrGLEffectMatrix_DEFINED
10d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
11d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com#include "GrGLEffect.h"
12d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com#include "SkMatrix.h"
13d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
14d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.comclass GrTexture;
15d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
16d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com/**
178bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * This is a helper to implement a matrix in a GrGLEffect that operates on incoming coords in the
188bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * vertex shader and writes them to an attribute to be used in the fragment shader. When the input
198bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * coords in the vertex shader are local coordinates this class accounts for the coord change matrix
208bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * communicated via GrDrawEffect. The input coords may also be positions and in this case the coord
218bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * change matrix is ignored. The GrGLEffectMatrix will emit different code based on the type of
228bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * matrix and thus must contribute to the effect's key.
238bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com *
248bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * This class cannot be used to apply a matrix to coordinates that come in the form of custom vertex
258bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com * attributes.
26d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com */
27d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.comclass GrGLEffectMatrix {
288bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.comprivate:
298bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    // We specialize the generated code for each of these matrix types.
308bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    enum MatrixTypes {
318bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kIdentity_MatrixType    = 0,
328bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kTrans_MatrixType       = 1,
338bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kNoPersp_MatrixType     = 2,
348bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kGeneral_MatrixType     = 3,
358bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    };
368bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    // The key for is made up of a matrix type and a bit that indicates the source of the input
378bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    // coords.
388bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    enum {
398bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kMatrixTypeKeyBits      = 2,
408bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kMatrixTypeKeyMask      = (1 << kMatrixTypeKeyBits) - 1,
418bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kPositionCoords_Flag    = (1 << kMatrixTypeKeyBits),
428bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kKeyBitsPrivate         = kMatrixTypeKeyBits + 1,
438bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    };
448bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com
45d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.compublic:
468bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com
478bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    typedef GrEffect::CoordsType CoordsType;
488bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com
49d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    typedef GrGLEffect::EffectKey EffectKey;
508bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com
51d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    /**
52d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * The matrix uses kKeyBits of the effect's EffectKey. A GrGLEffect may place these bits at an
53d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * arbitrary shift in its final key. However, when GrGLEffectMatrix::emitCode*() code is called
54d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * the relevant bits must be in the lower kKeyBits of the key parameter.
55d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     */
56d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    enum {
578bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        kKeyBits = kKeyBitsPrivate,
58d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com        kKeyMask = (1 << kKeyBits) - 1,
59d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    };
60d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
618bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    GrGLEffectMatrix(CoordsType coordsType)
628bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        : fUni(GrGLUniformManager::kInvalidUniformHandle)
638bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        , fCoordsType(coordsType) {
648bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        GrAssert(GrEffect::kLocal_CoordsType == coordsType ||
658bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                 GrEffect::kPosition_CoordsType == coordsType);
66d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com        fPrevMatrix = SkMatrix::InvalidMatrix();
67d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    }
68d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
69d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    /**
70d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * Generates the key for the portion of the code emitted by this class's emitCode() function.
71d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * Pass a texture to make GrGLEffectMatrix automatically adjust for the texture's origin. Pass
728bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com     * NULL when not using the EffectMatrix for a texture lookup, or if the GrGLEffect subclass
738bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com     * wants to handle origin adjustments in some other manner. The coords type param must match the
748bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com     * param that would be used to initialize GrGLEffectMatrix for the generating GrEffect.
75d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     */
76d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    static EffectKey GenKey(const SkMatrix& effectMatrix,
778bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                            const GrDrawEffect&,
788bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                            CoordsType,
79d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                            const GrTexture*);
80d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
81d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    /**
82d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * Emits code to implement the matrix in the VS. A varying is added as an output of the VS and
83d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * input to the FS. The varying may be either a vec2f or vec3f depending upon whether
84d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * perspective interpolation is required or not. The names of the varying in the VS and FS are
85d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * are returned as output parameters and the type of the varying is the return value. The suffix
86d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * is an optional parameter that can be used to make all variables emitted by the object
87d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * unique within a stage. It is only necessary if multiple GrGLEffectMatrix objects are used by
88d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * a GrGLEffect.
89d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     */
90d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    GrSLType emitCode(GrGLShaderBuilder*,
91d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                      EffectKey,
92d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                      const char** fsCoordName, /* optional */
93d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                      const char** vsCoordName = NULL,
94d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                      const char* suffix = NULL);
95d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
96d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    /**
97d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * This is similar to emitCode except that it performs perspective division in the FS if the
98d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     * texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f.
99d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     */
100d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    void emitCodeMakeFSCoords2D(GrGLShaderBuilder*,
101d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                                EffectKey,
102d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                                const char** fsCoordName, /* optional */
103d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                                const char** vsVaryingName = NULL,
104d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                                GrSLType* vsVaryingType = NULL,
105d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                                const char* suffix = NULL);
106d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    /**
1078bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com     * Call from a GrGLEffect's subclass to update the texture matrix. The effectMatrix and texture
1088bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com     * params should match those used with GenKey.
109d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com     */
110d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    void setData(const GrGLUniformManager& uniformManager,
111d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                 const SkMatrix& effectMatrix,
1128bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                 const GrDrawEffect& drawEffect,
113d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                 const GrTexture*);
114d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
115d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    GrGLUniformManager::UniformHandle fUni;
116d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    GrSLType                          fUniType;
117d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    SkMatrix                          fPrevMatrix;
1188bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    CoordsType                        fCoordsType;
119d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com};
120d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
1213a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com#endif
122