Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2010 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #include "GrGLConfig.h"
     19 
     20 #include "GrGpuGLFixed.h"
     21 #include "GrGpuVertex.h"
     22 
     23 #define SKIP_CACHE_CHECK    true
     24 
     25 struct GrGpuMatrix {
     26     GrGLfloat    fMat[16];
     27 
     28     void reset() {
     29         Gr_bzero(fMat, sizeof(fMat));
     30         fMat[0] = fMat[5] = fMat[10] = fMat[15] = GR_Scalar1;
     31     }
     32 
     33     void set(const GrMatrix& m) {
     34         Gr_bzero(fMat, sizeof(fMat));
     35         fMat[0]  = GrScalarToFloat(m[GrMatrix::kMScaleX]);
     36         fMat[4]  = GrScalarToFloat(m[GrMatrix::kMSkewX]);
     37         fMat[12] = GrScalarToFloat(m[GrMatrix::kMTransX]);
     38 
     39         fMat[1]  = GrScalarToFloat(m[GrMatrix::kMSkewY]);
     40         fMat[5]  = GrScalarToFloat(m[GrMatrix::kMScaleY]);
     41         fMat[13] = GrScalarToFloat(m[GrMatrix::kMTransY]);
     42 
     43         fMat[3]  = GrScalarToFloat(m[GrMatrix::kMPersp0]);
     44         fMat[7]  = GrScalarToFloat(m[GrMatrix::kMPersp1]);
     45         fMat[15] = GrScalarToFloat(m[GrMatrix::kMPersp2]);
     46 
     47         fMat[10] = 1.f;    // z-scale
     48     }
     49 };
     50 
     51 // these must match the order in the corresponding enum in GrGpu.h
     52 static const GrGLenum gMatrixMode2Enum[] = {
     53     GR_GL_MODELVIEW, GR_GL_TEXTURE
     54 };
     55 
     56 ///////////////////////////////////////////////////////////////////////////////
     57 
     58 GrGpuGLFixed::GrGpuGLFixed() {
     59     f4X4DownsampleFilterSupport = false;
     60     fDualSourceBlendingSupport = false;
     61 }
     62 
     63 GrGpuGLFixed::~GrGpuGLFixed() {
     64 }
     65 
     66 void GrGpuGLFixed::resetContext() {
     67     INHERITED::resetContext();
     68 
     69     GR_GL(Disable(GR_GL_TEXTURE_2D));
     70 
     71     for (int s = 0; s < kNumStages; ++s) {
     72         setTextureUnit(s);
     73         GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY));
     74         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_TEXTURE_ENV_MODE, GR_GL_COMBINE));
     75         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_RGB,   GR_GL_MODULATE));
     76         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_RGB,      GR_GL_TEXTURE0+s));
     77         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_RGB,      GR_GL_PREVIOUS));
     78         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_RGB,  GR_GL_SRC_COLOR));
     79 
     80         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_ALPHA, GR_GL_MODULATE));
     81         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_ALPHA, GR_GL_TEXTURE0+s));
     82         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND0_ALPHA, GR_GL_SRC_ALPHA));
     83         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_ALPHA, GR_GL_PREVIOUS));
     84         GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_ALPHA, GR_GL_SRC_ALPHA));
     85 
     86         // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending
     87         // upon whether we have a (premultiplied) RGBA texture or just an ALPHA
     88         // texture, e.g.:
     89         //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,  GL_SRC_COLOR);
     90         fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
     91     }
     92 
     93     fHWGeometryState.fVertexLayout = 0;
     94     fHWGeometryState.fVertexOffset  = ~0;
     95     GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY));
     96     GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
     97     GR_GL(ShadeModel(GR_GL_FLAT));
     98     GR_GL(DisableClientState(GR_GL_COLOR_ARRAY));
     99 
    100     GR_GL(PointSize(1.f));
    101 
    102     GrGLClearErr();
    103     fTextVerts = false;
    104 
    105     fBaseVertex = 0xffffffff;
    106 }
    107 
    108 
    109 void GrGpuGLFixed::flushProjectionMatrix() {
    110     float mat[16];
    111     Gr_bzero(mat, sizeof(mat));
    112 
    113     GrAssert(NULL != fCurrDrawState.fRenderTarget);
    114 
    115     mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
    116     mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
    117     mat[10] = -1.f;
    118     mat[15] = 1;
    119 
    120     mat[12] = -1.f;
    121     mat[13] = 1.f;
    122 
    123     GR_GL(MatrixMode(GR_GL_PROJECTION));
    124     GR_GL(LoadMatrixf(mat));
    125 }
    126 
    127 bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
    128 
    129     bool usingTextures[kNumStages];
    130 
    131     for (int s = 0; s < kNumStages; ++s) {
    132         usingTextures[s] = this->isStageEnabled(s);
    133         if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
    134             unimpl("Fixed pipe doesn't support radial/sweep gradients");
    135             return false;
    136         }
    137     }
    138 
    139     if (GR_GL_SUPPORT_ES1) {
    140         if (BlendCoeffReferencesConstant(fCurrDrawState.fSrcBlend) ||
    141             BlendCoeffReferencesConstant(fCurrDrawState.fDstBlend)) {
    142             unimpl("ES1 doesn't support blend constant");
    143             return false;
    144         }
    145     }
    146 
    147     if (!flushGLStateCommon(type)) {
    148         return false;
    149     }
    150 
    151     this->flushBlend(type, fCurrDrawState.fSrcBlend, fCurrDrawState.fDstBlend);
    152 
    153     if (fDirtyFlags.fRenderTargetChanged) {
    154         flushProjectionMatrix();
    155     }
    156 
    157     for (int s = 0; s < kNumStages; ++s) {
    158         bool wasUsingTexture = StageWillBeUsed(s, fHWGeometryState.fVertexLayout, fHWDrawState);
    159         if (usingTextures[s] != wasUsingTexture) {
    160             setTextureUnit(s);
    161             if (usingTextures[s]) {
    162                 GR_GL(Enable(GR_GL_TEXTURE_2D));
    163             } else {
    164                 GR_GL(Disable(GR_GL_TEXTURE_2D));
    165             }
    166         }
    167     }
    168 
    169     uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
    170     uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
    171                               kColor_VertexLayoutBit);
    172 
    173     if (vertColor != prevVertColor) {
    174         if (vertColor) {
    175             GR_GL(ShadeModel(GR_GL_SMOOTH));
    176             // invalidate the immediate mode color
    177             fHWDrawState.fColor = GrColor_ILLEGAL;
    178         } else {
    179             GR_GL(ShadeModel(GR_GL_FLAT));
    180         }
    181     }
    182 
    183 
    184     if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
    185         GR_GL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
    186                        GrColorUnpackG(fCurrDrawState.fColor),
    187                        GrColorUnpackB(fCurrDrawState.fColor),
    188                        GrColorUnpackA(fCurrDrawState.fColor)));
    189         fHWDrawState.fColor = fCurrDrawState.fColor;
    190     }
    191 
    192     // set texture environment, decide whether we are modulating by RGB or A.
    193     for (int s = 0; s < kNumStages; ++s) {
    194         if (usingTextures[s]) {
    195             GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
    196             if (NULL != texture) {
    197                 TextureEnvRGBOperands nextRGBOperand0 =
    198                     (GrPixelConfigIsAlphaOnly(texture->config())) ?
    199                         kAlpha_TextureEnvRGBOperand :
    200                         kColor_TextureEnvRGBOperand;
    201                 if (fHWRGBOperand0[s] != nextRGBOperand0) {
    202                     setTextureUnit(s);
    203                     GR_GL(TexEnvi(GR_GL_TEXTURE_ENV,
    204                                   GR_GL_OPERAND0_RGB,
    205                                   (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
    206                                     GR_GL_SRC_ALPHA :
    207                                     GR_GL_SRC_COLOR));
    208                     fHWRGBOperand0[s] = nextRGBOperand0;
    209                 }
    210 
    211                 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
    212                     (fHWDrawState.fSamplerStates[s].getMatrix() !=
    213                      getSamplerMatrix(s))) {
    214 
    215                     GrMatrix texMat = getSamplerMatrix(s);
    216                     AdjustTextureMatrix(texture,
    217                                         GrSamplerState::kNormal_SampleMode,
    218                                         &texMat);
    219                     GrGpuMatrix glm;
    220                     glm.set(texMat);
    221                     setTextureUnit(s);
    222                     GR_GL(MatrixMode(GR_GL_TEXTURE));
    223                     GR_GL(LoadMatrixf(glm.fMat));
    224                     recordHWSamplerMatrix(s, getSamplerMatrix(s));
    225                 }
    226             } else {
    227                 GrAssert(!"Rendering with texture vert flag set but no bound texture");
    228                 return false;
    229             }
    230         }
    231     }
    232 
    233     if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
    234         GrGpuMatrix glm;
    235         glm.set(fCurrDrawState.fViewMatrix);
    236         GR_GL(MatrixMode(GR_GL_MODELVIEW));
    237         GR_GL(LoadMatrixf(glm.fMat));
    238         fHWDrawState.fViewMatrix =
    239         fCurrDrawState.fViewMatrix;
    240     }
    241     resetDirtyFlags();
    242     return true;
    243 }
    244 
    245 void GrGpuGLFixed::setupGeometry(int* startVertex,
    246                                  int* startIndex,
    247                                  int vertexCount,
    248                                  int indexCount) {
    249 
    250     int newColorOffset;
    251     int newTexCoordOffsets[kNumStages];
    252 
    253     GrGLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
    254                                                       newTexCoordOffsets,
    255                                                       &newColorOffset);
    256     int oldColorOffset;
    257     int oldTexCoordOffsets[kNumStages];
    258     GrGLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
    259                                                       oldTexCoordOffsets,
    260                                                       &oldColorOffset);
    261 
    262     bool indexed = NULL != startIndex;
    263 
    264     int extraVertexOffset;
    265     int extraIndexOffset;
    266     setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
    267 
    268     GrGLenum scalarType;
    269     if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
    270         scalarType = GrGLTextType;
    271     } else {
    272         scalarType = GrGLType;
    273     }
    274 
    275     size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
    276     *startVertex = 0;
    277     if (indexed) {
    278         *startIndex += extraIndexOffset;
    279     }
    280 
    281     // all the Pointers must be set if any of these are true
    282     bool allOffsetsChange =  fHWGeometryState.fArrayPtrsDirty ||
    283                              vertexOffset != fHWGeometryState.fVertexOffset ||
    284                              newStride != oldStride;
    285 
    286     // position and tex coord offsets change if above conditions are true
    287     // or the type changed based on text vs nontext type coords.
    288     bool posAndTexChange = allOffsetsChange ||
    289                            ((GrGLTextType != GrGLType) &&
    290                                 (kTextFormat_VertexLayoutBit &
    291                                   (fHWGeometryState.fVertexLayout ^
    292                                    fGeometrySrc.fVertexLayout)));
    293 
    294     if (posAndTexChange) {
    295         GR_GL(VertexPointer(2, scalarType, newStride, (GrGLvoid*)vertexOffset));
    296         fHWGeometryState.fVertexOffset = vertexOffset;
    297     }
    298 
    299     for (int s = 0; s < kNumStages; ++s) {
    300         // need to enable array if tex coord offset is 0
    301         // (using positions as coords)
    302         if (newTexCoordOffsets[s] >= 0) {
    303             GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[s]);
    304             if (oldTexCoordOffsets[s] < 0) {
    305                 GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s));
    306                 GR_GL(EnableClientState(GR_GL_TEXTURE_COORD_ARRAY));
    307                 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
    308             } else if (posAndTexChange ||
    309                        newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
    310                 GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s));
    311                 GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
    312             }
    313         } else if (oldTexCoordOffsets[s] >= 0) {
    314             GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s));
    315             GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
    316         }
    317     }
    318 
    319     if (newColorOffset > 0) {
    320         GrGLvoid* colorOffset = (GrGLvoid*)(vertexOffset + newColorOffset);
    321         if (oldColorOffset <= 0) {
    322             GR_GL(EnableClientState(GR_GL_COLOR_ARRAY));
    323             GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset));
    324         } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
    325             GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset));
    326         }
    327     } else if (oldColorOffset > 0) {
    328         GR_GL(DisableClientState(GR_GL_COLOR_ARRAY));
    329     }
    330 
    331     fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
    332     fHWGeometryState.fArrayPtrsDirty = false;
    333 }
    334