Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2011 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 #include "GrGpuGL.h"
     18 #include "GrMemory.h"
     19 #include "GrTypes.h"
     20 
     21 static const GrGLuint GR_MAX_GLUINT = ~0;
     22 static const GrGLint  GR_INVAL_GLINT = ~0;
     23 
     24 // we use a spare texture unit to avoid
     25 // mucking with the state of any of the stages.
     26 static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
     27 
     28 #define SKIP_CACHE_CHECK    true
     29 
     30 static const GrGLenum gXfermodeCoeff2Blend[] = {
     31     GR_GL_ZERO,
     32     GR_GL_ONE,
     33     GR_GL_SRC_COLOR,
     34     GR_GL_ONE_MINUS_SRC_COLOR,
     35     GR_GL_DST_COLOR,
     36     GR_GL_ONE_MINUS_DST_COLOR,
     37     GR_GL_SRC_ALPHA,
     38     GR_GL_ONE_MINUS_SRC_ALPHA,
     39     GR_GL_DST_ALPHA,
     40     GR_GL_ONE_MINUS_DST_ALPHA,
     41     GR_GL_CONSTANT_COLOR,
     42     GR_GL_ONE_MINUS_CONSTANT_COLOR,
     43     GR_GL_CONSTANT_ALPHA,
     44     GR_GL_ONE_MINUS_CONSTANT_ALPHA,
     45 
     46     // extended blend coeffs
     47     GR_GL_SRC1_COLOR,
     48     GR_GL_ONE_MINUS_SRC1_COLOR,
     49     GR_GL_SRC1_ALPHA,
     50     GR_GL_ONE_MINUS_SRC1_ALPHA,
     51 };
     52 
     53 bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
     54     static const bool gCoeffReferencesBlendConst[] = {
     55         false,
     56         false,
     57         false,
     58         false,
     59         false,
     60         false,
     61         false,
     62         false,
     63         false,
     64         false,
     65         true,
     66         true,
     67         true,
     68         true,
     69 
     70         // extended blend coeffs
     71         false,
     72         false,
     73         false,
     74         false,
     75     };
     76     return gCoeffReferencesBlendConst[coeff];
     77     GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
     78 
     79     GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
     80     GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
     81     GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
     82     GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
     83     GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
     84     GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
     85     GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
     86     GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
     87     GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
     88     GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
     89     GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
     90     GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
     91     GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
     92     GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
     93 
     94     GR_STATIC_ASSERT(14 == kS2C_BlendCoeff);
     95     GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff);
     96     GR_STATIC_ASSERT(16 == kS2A_BlendCoeff);
     97     GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff);
     98 
     99     // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
    100     GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
    101 }
    102 
    103 ///////////////////////////////////////////////////////////////////////////////
    104 
    105 void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
    106                                   GrSamplerState::SampleMode mode,
    107                                   GrMatrix* matrix) {
    108     GrAssert(NULL != texture);
    109     GrAssert(NULL != matrix);
    110     if (GR_Scalar1 != texture->contentScaleX() ||
    111         GR_Scalar1 != texture->contentScaleY()) {
    112         if (GrSamplerState::kRadial_SampleMode == mode) {
    113             GrMatrix scale;
    114             scale.setScale(texture->contentScaleX(), texture->contentScaleX());
    115             matrix->postConcat(scale);
    116         } else if (GrSamplerState::kNormal_SampleMode == mode) {
    117             GrMatrix scale;
    118             scale.setScale(texture->contentScaleX(), texture->contentScaleY());
    119             matrix->postConcat(scale);
    120         } else {
    121             GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
    122         }
    123     }
    124     GrGLTexture::Orientation orientation = texture->orientation();
    125     if (GrGLTexture::kBottomUp_Orientation == orientation) {
    126         GrMatrix invY;
    127         invY.setAll(GR_Scalar1, 0,           0,
    128                     0,          -GR_Scalar1, GR_Scalar1,
    129                     0,          0,           GrMatrix::I()[8]);
    130         matrix->postConcat(invY);
    131     } else {
    132         GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
    133     }
    134 }
    135 
    136 bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
    137                                       const GrSamplerState& sampler) {
    138     GrAssert(NULL != texture);
    139     if (!sampler.getMatrix().isIdentity()) {
    140         return false;
    141     }
    142     if (GR_Scalar1 != texture->contentScaleX() ||
    143         GR_Scalar1 != texture->contentScaleY()) {
    144         return false;
    145     }
    146     GrGLTexture::Orientation orientation = texture->orientation();
    147     if (GrGLTexture::kBottomUp_Orientation == orientation) {
    148         return false;
    149     } else {
    150         GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
    151     }
    152     return true;
    153 }
    154 
    155 ///////////////////////////////////////////////////////////////////////////////
    156 
    157 static bool gPrintStartupSpew;
    158 
    159 static bool fbo_test(int w, int h) {
    160 
    161     GrGLint savedFBO;
    162     GrGLint savedTexUnit;
    163     GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
    164     GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
    165 
    166     GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
    167 
    168     GrGLuint testFBO;
    169     GR_GL(GenFramebuffers(1, &testFBO));
    170     GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
    171     GrGLuint testRTTex;
    172     GR_GL(GenTextures(1, &testRTTex));
    173     GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
    174     // some implementations require texture to be mip-map complete before
    175     // FBO with level 0 bound as color attachment will be framebuffer complete.
    176     GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
    177     GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
    178                      0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
    179     GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
    180     GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
    181                                GR_GL_TEXTURE_2D, testRTTex, 0));
    182     GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    183     GR_GL(DeleteFramebuffers(1, &testFBO));
    184     GR_GL(DeleteTextures(1, &testRTTex));
    185 
    186     GR_GL(ActiveTexture(savedTexUnit));
    187     GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
    188 
    189     return status == GR_GL_FRAMEBUFFER_COMPLETE;
    190 }
    191 
    192 GrGpuGL::GrGpuGL() {
    193 
    194     if (gPrintStartupSpew) {
    195         GrPrintf("------------------------- create GrGpuGL %p --------------\n",
    196                  this);
    197         GrPrintf("------ VENDOR %s\n",
    198                  GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
    199         GrPrintf("------ RENDERER %s\n",
    200                  GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
    201         GrPrintf("------ VERSION %s\n",
    202                  GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
    203         GrPrintf("------ EXTENSIONS\n %s \n",
    204                  GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
    205     }
    206 
    207     GrGLClearErr();
    208 
    209     resetDirtyFlags();
    210 
    211     GrGLint maxTextureUnits;
    212     // check FS and fixed-function texture unit limits
    213     // we only use textures in the fragment stage currently.
    214     // checks are > to make sure we have a spare unit.
    215     if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
    216         GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
    217         GrAssert(maxTextureUnits > kNumStages);
    218     }
    219     if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
    220         GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
    221         GrAssert(maxTextureUnits > kNumStages);
    222     }
    223     if (GR_GL_SUPPORT_ES2) {
    224         GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
    225                           &fMaxFragmentUniformVectors);
    226     } else if (GR_GL_SUPPORT_DESKTOP) {
    227         GrGLint max;
    228         GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
    229         fMaxFragmentUniformVectors = max / 4;
    230     } else {
    231         fMaxFragmentUniformVectors = 16;
    232     }
    233 
    234     ////////////////////////////////////////////////////////////////////////////
    235     // Check for supported features.
    236 
    237     int major, minor;
    238     gl_version(&major, &minor);
    239 
    240     GrGLint numFormats;
    241     GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
    242     GrAutoSTMalloc<10, GrGLint> formats(numFormats);
    243     GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
    244     for (int i = 0; i < numFormats; ++i) {
    245         if (formats[i] == GR_GL_PALETTE8_RGBA8) {
    246             f8bitPaletteSupport = true;
    247             break;
    248         }
    249     }
    250 
    251     if (gPrintStartupSpew) {
    252         GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
    253     }
    254 
    255     GR_STATIC_ASSERT(0 == kNone_GrAALevel);
    256     GR_STATIC_ASSERT(1 == kLow_GrAALevel);
    257     GR_STATIC_ASSERT(2 == kMed_GrAALevel);
    258     GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
    259 
    260     memset(fAASamples, 0, sizeof(fAASamples));
    261     fMSFBOType = kNone_MSFBO;
    262     if (GR_GL_SUPPORT_ES) {
    263        if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
    264            // chrome's extension is equivalent to the EXT msaa
    265            // and fbo_blit extensions.
    266             fMSFBOType = kDesktopEXT_MSFBO;
    267        } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
    268             fMSFBOType = kAppleES_MSFBO;
    269         }
    270     } else {
    271         GrAssert(GR_GL_SUPPORT_DESKTOP);
    272         if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
    273             fMSFBOType = kDesktopARB_MSFBO;
    274         } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
    275                    has_gl_extension("GL_EXT_framebuffer_blit")) {
    276             fMSFBOType = kDesktopEXT_MSFBO;
    277         }
    278     }
    279     if (gPrintStartupSpew) {
    280         switch (fMSFBOType) {
    281             case kNone_MSFBO:
    282                 GrPrintf("MSAA Support: NONE\n");
    283                 break;
    284             case kDesktopARB_MSFBO:
    285                 GrPrintf("MSAA Support: DESKTOP ARB.\n");
    286                 break;
    287             case kDesktopEXT_MSFBO:
    288                 GrPrintf("MSAA Support: DESKTOP EXT.\n");
    289                 break;
    290             case kAppleES_MSFBO:
    291                 GrPrintf("MSAA Support: APPLE ES.\n");
    292                 break;
    293         }
    294     }
    295 
    296     if (kNone_MSFBO != fMSFBOType) {
    297         GrGLint maxSamples;
    298         GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
    299         if (maxSamples > 1 ) {
    300             fAASamples[kNone_GrAALevel] = 0;
    301             fAASamples[kLow_GrAALevel] = GrMax(2,
    302                                                GrFixedFloorToInt((GR_FixedHalf) *
    303                                                maxSamples));
    304             fAASamples[kMed_GrAALevel] = GrMax(2,
    305                                                GrFixedFloorToInt(((GR_Fixed1*3)/4) *
    306                                                maxSamples));
    307             fAASamples[kHigh_GrAALevel] = maxSamples;
    308         }
    309         if (gPrintStartupSpew) {
    310             GrPrintf("\tMax Samples: %d\n", maxSamples);
    311         }
    312     }
    313     fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
    314 
    315     if (GR_GL_SUPPORT_DESKTOP) {
    316         fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
    317                           has_gl_extension("GL_EXT_stencil_wrap");
    318     } else {
    319         fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
    320     }
    321     if (gPrintStartupSpew) {
    322         GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
    323     }
    324 
    325     if (GR_GL_SUPPORT_DESKTOP) {
    326         // we could also look for GL_ATI_separate_stencil extension or
    327         // GL_EXT_stencil_two_side but they use different function signatures
    328         // than GL2.0+ (and than each other).
    329         fTwoSidedStencilSupport = (major >= 2);
    330         // supported on GL 1.4 and higher or by extension
    331         fStencilWrapOpsSupport = (major > 1) ||
    332                                  ((1 == major) && (minor >= 4)) ||
    333                                   has_gl_extension("GL_EXT_stencil_wrap");
    334     } else {
    335         // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
    336         // an ES1 extension.
    337         fTwoSidedStencilSupport = (major >= 2);
    338         // stencil wrap support is in ES2, ES1 requires extension.
    339         fStencilWrapOpsSupport = (major > 1) ||
    340                                   has_gl_extension("GL_OES_stencil_wrap");
    341     }
    342     if (gPrintStartupSpew) {
    343         GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
    344                 (fTwoSidedStencilSupport ? "YES" : "NO"),
    345                 (fStencilWrapOpsSupport ? "YES" : "NO"));
    346     }
    347 
    348     if (GR_GL_SUPPORT_DESKTOP) {
    349         fRGBA8Renderbuffer = true;
    350     } else {
    351         fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
    352     }
    353     if (gPrintStartupSpew) {
    354         GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
    355     }
    356 
    357 
    358     if (GR_GL_SUPPORT_ES) {
    359         if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
    360             GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
    361         }
    362     }
    363 
    364     if (GR_GL_SUPPORT_DESKTOP) {
    365         fBufferLockSupport = true; // we require VBO support and the desktop VBO
    366                                    // extension includes glMapBuffer.
    367     } else {
    368         fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
    369     }
    370 
    371     if (gPrintStartupSpew) {
    372         GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
    373     }
    374 
    375     if (GR_GL_SUPPORT_DESKTOP) {
    376         if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
    377             fNPOTTextureTileSupport = true;
    378             fNPOTTextureSupport = true;
    379         } else {
    380             fNPOTTextureTileSupport = false;
    381             fNPOTTextureSupport = false;
    382         }
    383     } else {
    384         if (major >= 2) {
    385             fNPOTTextureSupport = true;
    386             fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
    387         } else {
    388             fNPOTTextureSupport =
    389                         has_gl_extension("GL_APPLE_texture_2D_limited_npot");
    390             fNPOTTextureTileSupport = false;
    391         }
    392     }
    393 
    394     fAALineSupport = GR_GL_SUPPORT_DESKTOP;
    395 
    396     ////////////////////////////////////////////////////////////////////////////
    397     // Experiments to determine limitations that can't be queried. TODO: Make
    398     // these a preprocess that generate some compile time constants.
    399 
    400     // sanity check to make sure we can at least create an FBO from a POT texture
    401 
    402     bool simpleFBOSuccess = fbo_test(128, 128);
    403     if (gPrintStartupSpew) {
    404         if (!simpleFBOSuccess) {
    405             GrPrintf("FBO Sanity Test: FAILED\n");
    406         } else {
    407             GrPrintf("FBO Sanity Test: PASSED\n");
    408         }
    409     }
    410     GrAssert(simpleFBOSuccess);
    411 
    412     /* Experimentation has found that some GLs that support NPOT textures
    413        do not support FBOs with a NPOT texture. They report "unsupported" FBO
    414        status. I don't know how to explicitly query for this. Do an
    415        experiment. Note they may support NPOT with a renderbuffer but not a
    416        texture. Presumably, the implementation bloats the renderbuffer
    417        internally to the next POT.
    418      */
    419     bool fNPOTRenderTargetSupport = false;
    420     if (fNPOTTextureSupport) {
    421         fNPOTRenderTargetSupport = fbo_test(200, 200);
    422     }
    423 
    424     if (gPrintStartupSpew) {
    425         if (fNPOTTextureSupport) {
    426             GrPrintf("NPOT textures supported\n");
    427             if (fNPOTTextureTileSupport) {
    428                 GrPrintf("NPOT texture tiling supported\n");
    429             } else {
    430                 GrPrintf("NPOT texture tiling NOT supported\n");
    431             }
    432             if (fNPOTRenderTargetSupport) {
    433                 GrPrintf("NPOT render targets supported\n");
    434             } else {
    435                 GrPrintf("NPOT render targets NOT supported\n");
    436             }
    437         } else {
    438             GrPrintf("NPOT textures NOT supported\n");
    439         }
    440     }
    441 
    442     GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
    443 
    444     /* The iPhone 4 has a restriction that for an FBO with texture color
    445        attachment with height <= 8 then the width must be <= height. Here
    446        we look for such a limitation.
    447      */
    448     fMinRenderTargetHeight = GR_INVAL_GLINT;
    449     GrGLint maxRenderSize;
    450     GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
    451     // fbo_test creates FBOs with texture bound to the color attachment
    452     maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
    453 
    454     if (gPrintStartupSpew) {
    455         GrPrintf("Small height FBO texture experiments\n");
    456     }
    457 
    458     for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
    459         GrGLuint w = maxRenderSize;
    460         GrGLuint h = i;
    461         if (fbo_test(w, h)) {
    462             if (gPrintStartupSpew) {
    463                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
    464             }
    465             fMinRenderTargetHeight = i;
    466             break;
    467         } else {
    468             if (gPrintStartupSpew) {
    469                 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
    470             }
    471         }
    472     }
    473     GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
    474 
    475     if (gPrintStartupSpew) {
    476         GrPrintf("Small width FBO texture experiments\n");
    477     }
    478     fMinRenderTargetWidth = GR_MAX_GLUINT;
    479     for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
    480         GrGLuint w = i;
    481         GrGLuint h = maxRenderSize;
    482         if (fbo_test(w, h)) {
    483             if (gPrintStartupSpew) {
    484                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
    485             }
    486             fMinRenderTargetWidth = i;
    487             break;
    488         } else {
    489             if (gPrintStartupSpew) {
    490                 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
    491             }
    492         }
    493     }
    494     GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
    495 }
    496 
    497 GrGpuGL::~GrGpuGL() {
    498 }
    499 
    500 void GrGpuGL::resetContext() {
    501     // We detect cases when blending is effectively off
    502     fHWBlendDisabled = false;
    503     GR_GL(Enable(GR_GL_BLEND));
    504 
    505     // we don't use the zb at all
    506     GR_GL(Disable(GR_GL_DEPTH_TEST));
    507     GR_GL(DepthMask(GR_GL_FALSE));
    508 
    509     GR_GL(Disable(GR_GL_CULL_FACE));
    510     GR_GL(FrontFace(GR_GL_CCW));
    511     fHWDrawState.fDrawFace = kBoth_DrawFace;
    512 
    513     GR_GL(Disable(GR_GL_DITHER));
    514     if (GR_GL_SUPPORT_DESKTOP) {
    515         GR_GL(Disable(GR_GL_LINE_SMOOTH));
    516         GR_GL(Disable(GR_GL_POINT_SMOOTH));
    517         GR_GL(Disable(GR_GL_MULTISAMPLE));
    518         fHWAAState.fMSAAEnabled = false;
    519         fHWAAState.fSmoothLineEnabled = false;
    520     }
    521 
    522     GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
    523     fHWDrawState.fFlagBits = 0;
    524 
    525     // we only ever use lines in hairline mode
    526     GR_GL(LineWidth(1));
    527 
    528     // invalid
    529     fActiveTextureUnitIdx = -1;
    530 
    531     // illegal values
    532     fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
    533     fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
    534 
    535     fHWDrawState.fBlendConstant = 0x00000000;
    536     GR_GL(BlendColor(0,0,0,0));
    537 
    538     fHWDrawState.fColor = GrColor_ILLEGAL;
    539 
    540     fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
    541 
    542     for (int s = 0; s < kNumStages; ++s) {
    543         fHWDrawState.fTextures[s] = NULL;
    544         fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
    545                                                         -GR_ScalarMax,
    546                                                         true);
    547 
    548         fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
    549     }
    550 
    551     fHWBounds.fScissorRect.invalidate();
    552     fHWBounds.fScissorEnabled = false;
    553     GR_GL(Disable(GR_GL_SCISSOR_TEST));
    554     fHWBounds.fViewportRect.invalidate();
    555 
    556     fHWDrawState.fStencilSettings.invalidate();
    557     fHWStencilClip = false;
    558     fClipState.fClipIsDirty = true;
    559 
    560     fHWGeometryState.fIndexBuffer = NULL;
    561     fHWGeometryState.fVertexBuffer = NULL;
    562 
    563     fHWGeometryState.fArrayPtrsDirty = true;
    564 
    565     GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
    566     fHWDrawState.fRenderTarget = NULL;
    567 }
    568 
    569 GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
    570 
    571     bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
    572                      kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
    573     bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
    574                           kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
    575 
    576     GrGLRenderTarget::GLRenderTargetIDs rtIDs;
    577     if (isRenderTarget) {
    578         rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
    579         if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
    580             if (kGrCanResolve_GrPlatformRenderTargetFlagBit  & desc.fRenderTargetFlags) {
    581                 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
    582             } else {
    583                 GrAssert(!isTexture); // this should have been filtered by GrContext
    584                 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
    585             }
    586         } else {
    587             rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
    588         }
    589         // we don't know what the RB ids are without glGets and we don't care
    590         // since we aren't responsible for deleting them.
    591         rtIDs.fStencilRenderbufferID = 0;
    592         rtIDs.fMSColorRenderbufferID = 0;
    593 
    594         rtIDs.fOwnIDs = false;
    595     } else {
    596         rtIDs.reset();
    597     }
    598 
    599     if (isTexture) {
    600         GrGLTexture::GLTextureDesc texDesc;
    601         GrGLenum dontCare;
    602         if (!canBeTexture(desc.fConfig, &dontCare,
    603                          &texDesc.fUploadFormat,
    604                          &texDesc.fUploadType)) {
    605             return NULL;
    606         }
    607 
    608         GrGLTexture::TexParams params;
    609 
    610         texDesc.fAllocWidth  = texDesc.fContentWidth  = desc.fWidth;
    611         texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
    612 
    613         texDesc.fFormat             = texDesc.fFormat;
    614         texDesc.fOrientation        = GrGLTexture::kBottomUp_Orientation;
    615         texDesc.fStencilBits        = desc.fStencilBits;
    616         texDesc.fTextureID          = desc.fPlatformTexture;
    617         texDesc.fUploadByteCount    = GrBytesPerPixel(desc.fConfig);
    618         texDesc.fOwnsID             = false;
    619 
    620         params.invalidate(); // rather than do glGets.
    621 
    622         return new GrGLTexture(this, texDesc, rtIDs, params);
    623     } else {
    624         GrGLIRect viewport;
    625         viewport.fLeft   = 0;
    626         viewport.fBottom = 0;
    627         viewport.fWidth  = desc.fWidth;
    628         viewport.fHeight = desc.fHeight;
    629 
    630         return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
    631                                     kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
    632                                     viewport, NULL);
    633     }
    634 }
    635 
    636 GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
    637 
    638     GrGLRenderTarget::GLRenderTargetIDs rtIDs;
    639 
    640     GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
    641     rtIDs.fTexFBOID = rtIDs.fRTFBOID;
    642     rtIDs.fMSColorRenderbufferID = 0;
    643     rtIDs.fStencilRenderbufferID = 0;
    644 
    645     GrGLIRect viewport;
    646     viewport.setFromGLViewport();
    647     GrGLuint stencilBits;
    648     GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
    649 
    650     GrGLint samples;
    651     GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
    652 
    653     rtIDs.fOwnIDs = false;
    654 
    655     return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
    656                                 (samples > 0), viewport, NULL);
    657 }
    658 
    659 ///////////////////////////////////////////////////////////////////////////////
    660 
    661 static const GrGLuint UNKNOWN_BITS = ~0;
    662 
    663 struct StencilFormat {
    664     GrGLenum  fEnum;
    665     GrGLuint  fBits;
    666     bool      fPacked;
    667 };
    668 
    669 const StencilFormat* GrGLStencilFormats() {
    670     // defines stencil formats from more to less preferred
    671     static const StencilFormat desktopStencilFormats[] = {
    672         {GR_GL_STENCIL_INDEX8,     8,            false},
    673         {GR_GL_STENCIL_INDEX16,    16,           false},
    674         {GR_GL_DEPTH24_STENCIL8,   8,            true },
    675         {GR_GL_STENCIL_INDEX4,     4,            false},
    676         {GR_GL_STENCIL_INDEX,      UNKNOWN_BITS, false},
    677         {GR_GL_DEPTH_STENCIL,      UNKNOWN_BITS, true },
    678         {0, 0, false}
    679     };
    680 
    681     static const StencilFormat esStencilFormats[] = {
    682         {GR_GL_STENCIL_INDEX8,     8,   false},
    683         {GR_GL_DEPTH24_STENCIL8,   8,   true },
    684         {GR_GL_STENCIL_INDEX4,     4,   false},
    685         {0, 0, false}
    686     };
    687 
    688     if (GR_GL_SUPPORT_DESKTOP) {
    689         return desktopStencilFormats;
    690     } else {
    691         return esStencilFormats;
    692     }
    693 }
    694 
    695 // good to set a break-point here to know when createTexture fails
    696 static GrTexture* return_null_texture() {
    697 //    GrAssert(!"null texture");
    698     return NULL;
    699 }
    700 
    701 #if GR_DEBUG
    702 static size_t as_size_t(int x) {
    703     return x;
    704 }
    705 #endif
    706 
    707 GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
    708                                     const void* srcData,
    709                                     size_t rowBytes) {
    710 
    711 #if GR_COLLECT_STATS
    712     ++fStats.fTextureCreateCnt;
    713 #endif
    714 
    715     this->setSpareTextureUnit();
    716 
    717     static const GrGLTexture::TexParams DEFAULT_PARAMS = {
    718         GR_GL_NEAREST,
    719         GR_GL_CLAMP_TO_EDGE,
    720         GR_GL_CLAMP_TO_EDGE
    721     };
    722 
    723     GrGLTexture::GLTextureDesc glDesc;
    724     GrGLenum internalFormat;
    725 
    726     glDesc.fContentWidth  = desc.fWidth;
    727     glDesc.fContentHeight = desc.fHeight;
    728     glDesc.fAllocWidth    = desc.fWidth;
    729     glDesc.fAllocHeight   = desc.fHeight;
    730     glDesc.fStencilBits   = 0;
    731     glDesc.fFormat        = desc.fFormat;
    732     glDesc.fOwnsID        = true;
    733 
    734     bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
    735     if (!canBeTexture(desc.fFormat,
    736                       &internalFormat,
    737                       &glDesc.fUploadFormat,
    738                       &glDesc.fUploadType)) {
    739         return return_null_texture();
    740     }
    741 
    742     GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
    743     GrGLint samples = fAASamples[desc.fAALevel];
    744     if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
    745         GrPrintf("AA RT requested but not supported on this platform.");
    746     }
    747 
    748     GR_GL(GenTextures(1, &glDesc.fTextureID));
    749     if (!glDesc.fTextureID) {
    750         return return_null_texture();
    751     }
    752 
    753     glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
    754 
    755     // in case we need a temporary, trimmed copy of the src pixels
    756     GrAutoSMalloc<128 * 128> trimStorage;
    757 
    758     /*
    759      *  check if our srcData has extra bytes past each row. If so, we need
    760      *  to trim those off here, since GL doesn't let us pass the rowBytes as
    761      *  a parameter to glTexImage2D
    762      */
    763     if (GR_GL_SUPPORT_DESKTOP) {
    764         if (srcData) {
    765             GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
    766                               rowBytes / glDesc.fUploadByteCount));
    767         }
    768     } else {
    769         size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
    770         if (srcData && (trimRowBytes < rowBytes)) {
    771             // copy the data into our new storage, skipping the trailing bytes
    772             size_t trimSize = desc.fHeight * trimRowBytes;
    773             const char* src = (const char*)srcData;
    774             char* dst = (char*)trimStorage.realloc(trimSize);
    775             for (uint32_t y = 0; y < desc.fHeight; y++) {
    776                 memcpy(dst, src, trimRowBytes);
    777                 src += rowBytes;
    778                 dst += trimRowBytes;
    779             }
    780             // now point srcData to our trimmed version
    781             srcData = trimStorage.get();
    782         }
    783     }
    784 
    785     if (renderTarget) {
    786         if (!this->npotRenderTargetSupport()) {
    787             glDesc.fAllocWidth  = GrNextPow2(desc.fWidth);
    788             glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
    789         }
    790 
    791         glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
    792                                         glDesc.fAllocWidth);
    793         glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
    794                                          glDesc.fAllocHeight);
    795     } else if (!this->npotTextureSupport()) {
    796         glDesc.fAllocWidth  = GrNextPow2(desc.fWidth);
    797         glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
    798     }
    799 
    800     GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
    801     GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
    802                         GR_GL_TEXTURE_MAG_FILTER,
    803                         DEFAULT_PARAMS.fFilter));
    804     GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
    805                         GR_GL_TEXTURE_MIN_FILTER,
    806                         DEFAULT_PARAMS.fFilter));
    807     GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
    808                         GR_GL_TEXTURE_WRAP_S,
    809                         DEFAULT_PARAMS.fWrapS));
    810     GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
    811                         GR_GL_TEXTURE_WRAP_T,
    812                         DEFAULT_PARAMS.fWrapT));
    813 
    814     GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
    815     if (kIndex_8_GrPixelConfig == desc.fFormat &&
    816         supports8BitPalette()) {
    817         // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
    818         GrAssert(desc.fWidth == glDesc.fAllocWidth);
    819         GrAssert(desc.fHeight == glDesc.fAllocHeight);
    820         GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
    821                               kGrColorTableSize;
    822         GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
    823                                    glDesc.fAllocWidth, glDesc.fAllocHeight,
    824                                    0, imageSize, srcData));
    825         GrGLRestoreResetRowLength();
    826     } else {
    827         if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
    828                                 glDesc.fAllocHeight != desc.fHeight)) {
    829             GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
    830                              glDesc.fAllocWidth, glDesc.fAllocHeight,
    831                              0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
    832             GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
    833                                 desc.fHeight, glDesc.fUploadFormat,
    834                                 glDesc.fUploadType, srcData));
    835             GrGLRestoreResetRowLength();
    836 
    837             uint32_t extraW = glDesc.fAllocWidth  - desc.fWidth;
    838             uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
    839             uint32_t maxTexels = extraW * extraH;
    840             maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
    841             maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
    842 
    843             GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
    844 
    845             uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
    846             if (extraH) {
    847                 uint8_t* lastRowStart = (uint8_t*) srcData +
    848                                         (desc.fHeight - 1) * rowSize;
    849                 uint8_t* extraRowStart = (uint8_t*)texels.get();
    850 
    851                 for (uint32_t i = 0; i < extraH; ++i) {
    852                     memcpy(extraRowStart, lastRowStart, rowSize);
    853                     extraRowStart += rowSize;
    854                 }
    855                 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
    856                                     extraH, glDesc.fUploadFormat, glDesc.fUploadType,
    857                                     texels.get()));
    858             }
    859             if (extraW) {
    860                 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
    861                 uint8_t* extraTexel = (uint8_t*)texels.get();
    862                 for (uint32_t j = 0; j < desc.fHeight; ++j) {
    863                     for (uint32_t i = 0; i < extraW; ++i) {
    864                         memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
    865                         extraTexel += glDesc.fUploadByteCount;
    866                     }
    867                     edgeTexel += rowSize;
    868                 }
    869                 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
    870                                     desc.fHeight, glDesc.fUploadFormat,
    871                                     glDesc.fUploadType, texels.get()));
    872             }
    873             if (extraW && extraH) {
    874                 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
    875                                        - glDesc.fUploadByteCount;
    876                 uint8_t* extraTexel = (uint8_t*)texels.get();
    877                 for (uint32_t i = 0; i < extraW*extraH; ++i) {
    878                     memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
    879                     extraTexel += glDesc.fUploadByteCount;
    880                 }
    881                 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
    882                                     extraW, extraH, glDesc.fUploadFormat,
    883                                     glDesc.fUploadType, texels.get()));
    884             }
    885 
    886         } else {
    887             GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
    888                              glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
    889                              glDesc.fUploadType, srcData));
    890             GrGLRestoreResetRowLength();
    891         }
    892     }
    893 
    894     glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
    895 
    896     GrGLRenderTarget::GLRenderTargetIDs rtIDs;
    897     rtIDs.fStencilRenderbufferID = 0;
    898     rtIDs.fMSColorRenderbufferID = 0;
    899     rtIDs.fRTFBOID = 0;
    900     rtIDs.fTexFBOID = 0;
    901     rtIDs.fOwnIDs = true;
    902     GrGLenum msColorRenderbufferFormat = -1;
    903 
    904     if (renderTarget) {
    905 #if GR_COLLECT_STATS
    906         ++fStats.fRenderTargetCreateCnt;
    907 #endif
    908         bool failed = true;
    909         GrGLenum status;
    910         GrGLint err;
    911 
    912         // If need have both RT flag and srcData we have
    913         // to invert the data before uploading because FBO
    914         // will be rendered bottom up
    915         GrAssert(NULL == srcData);
    916         glDesc.fOrientation =  GrGLTexture::kBottomUp_Orientation;
    917 
    918         GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
    919         GrAssert(rtIDs.fTexFBOID);
    920 
    921         // If we are using multisampling and we will create two FBOS We render
    922         // to one and then resolve to the texture bound to the other.
    923         if (samples > 1 && kNone_MSFBO != fMSFBOType) {
    924             GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
    925             GrAssert(0 != rtIDs.fRTFBOID);
    926             GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
    927             GrAssert(0 != rtIDs.fMSColorRenderbufferID);
    928             if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
    929                 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
    930                 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
    931                 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
    932                 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
    933                 return return_null_texture();
    934             }
    935         } else {
    936             rtIDs.fRTFBOID = rtIDs.fTexFBOID;
    937         }
    938         if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
    939             GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
    940             GrAssert(0 != rtIDs.fStencilRenderbufferID);
    941         }
    942 
    943         // someone suggested that some systems might require
    944         // unbinding the texture before we call FramebufferTexture2D
    945         // (seems unlikely)
    946         GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
    947 
    948         err = ~GR_GL_NO_ERROR;
    949 
    950         const StencilFormat* stencilFormats = GrGLStencilFormats();
    951         for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
    952             if (rtIDs.fStencilRenderbufferID) {
    953                 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
    954                                        rtIDs.fStencilRenderbufferID));
    955                 if (samples > 1) {
    956                     GR_GL_NO_ERR(RenderbufferStorageMultisample(
    957                                                 GR_GL_RENDERBUFFER,
    958                                                 samples,
    959                                                 stencilFormats[i].fEnum,
    960                                                 glDesc.fAllocWidth,
    961                                                 glDesc.fAllocHeight));
    962                 } else {
    963                     GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
    964                                                      stencilFormats[i].fEnum,
    965                                                      glDesc.fAllocWidth,
    966                                                      glDesc.fAllocHeight));
    967                 }
    968                 err = GrGLGetGLInterface()->fGetError();
    969                 if (err != GR_GL_NO_ERROR) {
    970                     continue;
    971                 }
    972             }
    973             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
    974                 GrAssert(samples > 1);
    975                 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
    976                                        rtIDs.fMSColorRenderbufferID));
    977                 GR_GL_NO_ERR(RenderbufferStorageMultisample(
    978                                                    GR_GL_RENDERBUFFER,
    979                                                    samples,
    980                                                    msColorRenderbufferFormat,
    981                                                    glDesc.fAllocWidth,
    982                                                    glDesc.fAllocHeight));
    983                 err = GrGLGetGLInterface()->fGetError();
    984                 if (err != GR_GL_NO_ERROR) {
    985                     continue;
    986                 }
    987             }
    988             GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
    989 
    990 #if GR_COLLECT_STATS
    991             ++fStats.fRenderTargetChngCnt;
    992 #endif
    993             GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
    994                                         GR_GL_COLOR_ATTACHMENT0,
    995                                         GR_GL_TEXTURE_2D,
    996                                         glDesc.fTextureID, 0));
    997             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
    998                 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    999                 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
   1000                     GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
   1001                              status, desc.fWidth, desc.fHeight);
   1002                     continue;
   1003                 }
   1004                 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
   1005             #if GR_COLLECT_STATS
   1006                 ++fStats.fRenderTargetChngCnt;
   1007             #endif
   1008                 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
   1009                                               GR_GL_COLOR_ATTACHMENT0,
   1010                                               GR_GL_RENDERBUFFER,
   1011                                               rtIDs.fMSColorRenderbufferID));
   1012 
   1013             }
   1014             if (rtIDs.fStencilRenderbufferID) {
   1015                 // bind the stencil to rt fbo if present, othewise the tex fbo
   1016                 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
   1017                                               GR_GL_STENCIL_ATTACHMENT,
   1018                                               GR_GL_RENDERBUFFER,
   1019                                               rtIDs.fStencilRenderbufferID));
   1020                 // if it is a packed format bind to depth also, otherwise
   1021                 // we may get an unsupported fbo completeness result
   1022                 if (stencilFormats[i].fPacked) {
   1023                     GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
   1024                                                   GR_GL_DEPTH_ATTACHMENT,
   1025                                                   GR_GL_RENDERBUFFER,
   1026                                                   rtIDs.fStencilRenderbufferID));
   1027                 }
   1028             }
   1029             status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
   1030 
   1031             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
   1032                 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
   1033                          status, desc.fWidth, desc.fHeight);
   1034                 // undo the depth bind
   1035                 if (rtIDs.fStencilRenderbufferID &&
   1036                     stencilFormats[i].fPacked) {
   1037                     GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
   1038                                                     GR_GL_DEPTH_ATTACHMENT,
   1039                                                     GR_GL_RENDERBUFFER,
   1040                                                     0));
   1041                 }
   1042                 continue;
   1043             }
   1044             // we're successful!
   1045             failed = false;
   1046             if (rtIDs.fStencilRenderbufferID) {
   1047                 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
   1048                     GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
   1049                 } else {
   1050                     glDesc.fStencilBits = stencilFormats[i].fBits;
   1051                 }
   1052             }
   1053             break;
   1054         }
   1055         if (failed) {
   1056             if (rtIDs.fStencilRenderbufferID) {
   1057                 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
   1058             }
   1059             if (rtIDs.fMSColorRenderbufferID) {
   1060                 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
   1061             }
   1062             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
   1063                 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
   1064             }
   1065             if (rtIDs.fTexFBOID) {
   1066                 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
   1067             }
   1068             GR_GL(DeleteTextures(1, &glDesc.fTextureID));
   1069             return return_null_texture();
   1070         }
   1071     }
   1072 #ifdef TRACE_TEXTURE_CREATION
   1073     GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
   1074              tex->fTextureID, width, height, tex->fUploadByteCount);
   1075 #endif
   1076     GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
   1077 
   1078     if (0 != rtIDs.fTexFBOID) {
   1079         GrRenderTarget* rt = tex->asRenderTarget();
   1080         // We've messed with FBO state but may not have set the correct viewport
   1081         // so just dirty the rendertarget state to force a resend.
   1082         fHWDrawState.fRenderTarget = NULL;
   1083 
   1084         // clear the new stencil buffer if we have one
   1085         if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
   1086             GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
   1087             fCurrDrawState.fRenderTarget = rt;
   1088             this->clearStencil(0, ~0);
   1089             fCurrDrawState.fRenderTarget = rtSave;
   1090         }
   1091     }
   1092     return tex;
   1093 }
   1094 
   1095 GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
   1096     GrGLuint id;
   1097     GR_GL(GenBuffers(1, &id));
   1098     if (id) {
   1099         GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
   1100         fHWGeometryState.fArrayPtrsDirty = true;
   1101         GrGLClearErr();
   1102         // make sure driver can allocate memory for this buffer
   1103         GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
   1104                                 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
   1105         if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
   1106             GR_GL(DeleteBuffers(1, &id));
   1107             // deleting bound buffer does implicit bind to 0
   1108             fHWGeometryState.fVertexBuffer = NULL;
   1109             return NULL;
   1110         }
   1111         GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
   1112                                                               size, dynamic);
   1113         fHWGeometryState.fVertexBuffer = vertexBuffer;
   1114         return vertexBuffer;
   1115     }
   1116     return NULL;
   1117 }
   1118 
   1119 GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
   1120     GrGLuint id;
   1121     GR_GL(GenBuffers(1, &id));
   1122     if (id) {
   1123         GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
   1124         GrGLClearErr();
   1125         // make sure driver can allocate memory for this buffer
   1126         GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
   1127                                 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
   1128         if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
   1129             GR_GL(DeleteBuffers(1, &id));
   1130             // deleting bound buffer does implicit bind to 0
   1131             fHWGeometryState.fIndexBuffer = NULL;
   1132             return NULL;
   1133         }
   1134         GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
   1135                                                          size, dynamic);
   1136         fHWGeometryState.fIndexBuffer = indexBuffer;
   1137         return indexBuffer;
   1138     }
   1139     return NULL;
   1140 }
   1141 
   1142 void GrGpuGL::flushScissor(const GrIRect* rect) {
   1143     GrAssert(NULL != fCurrDrawState.fRenderTarget);
   1144     const GrGLIRect& vp =
   1145             ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
   1146 
   1147     GrGLIRect scissor;
   1148     if (NULL != rect) {
   1149         scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
   1150                               rect->width(), rect->height());
   1151         if (scissor.contains(vp)) {
   1152             rect = NULL;
   1153         }
   1154     }
   1155 
   1156     if (NULL != rect) {
   1157         if (fHWBounds.fScissorRect != scissor) {
   1158             scissor.pushToGLScissor();
   1159             fHWBounds.fScissorRect = scissor;
   1160         }
   1161         if (!fHWBounds.fScissorEnabled) {
   1162             GR_GL(Enable(GR_GL_SCISSOR_TEST));
   1163             fHWBounds.fScissorEnabled = true;
   1164         }
   1165     } else {
   1166         if (fHWBounds.fScissorEnabled) {
   1167             GR_GL(Disable(GR_GL_SCISSOR_TEST));
   1168             fHWBounds.fScissorEnabled = false;
   1169         }
   1170     }
   1171 }
   1172 
   1173 void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
   1174     if (NULL == fCurrDrawState.fRenderTarget) {
   1175         return;
   1176     }
   1177     GrIRect r;
   1178     if (NULL != rect) {
   1179         // flushScissor expects rect to be clipped to the target.
   1180         r = *rect;
   1181         GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
   1182                                          fCurrDrawState.fRenderTarget->height());
   1183         if (r.intersect(rtRect)) {
   1184             rect = &r;
   1185         } else {
   1186             return;
   1187         }
   1188     }
   1189     this->flushRenderTarget(rect);
   1190     this->flushScissor(rect);
   1191     GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
   1192     fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
   1193     GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
   1194                      GrColorUnpackG(color)/255.f,
   1195                      GrColorUnpackB(color)/255.f,
   1196                      GrColorUnpackA(color)/255.f));
   1197     GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
   1198 }
   1199 
   1200 void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
   1201     if (NULL == fCurrDrawState.fRenderTarget) {
   1202         return;
   1203     }
   1204 
   1205     this->flushRenderTarget(&GrIRect::EmptyIRect());
   1206 
   1207     if (fHWBounds.fScissorEnabled) {
   1208         GR_GL(Disable(GR_GL_SCISSOR_TEST));
   1209         fHWBounds.fScissorEnabled = false;
   1210     }
   1211     GR_GL(StencilMask(mask));
   1212     GR_GL(ClearStencil(value));
   1213     GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
   1214     fHWDrawState.fStencilSettings.invalidate();
   1215 }
   1216 
   1217 void GrGpuGL::clearStencilClip(const GrIRect& rect) {
   1218     GrAssert(NULL != fCurrDrawState.fRenderTarget);
   1219 #if 0
   1220     GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
   1221     GrAssert(stencilBitCount > 0);
   1222     GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
   1223 #else
   1224     // we could just clear the clip bit but when we go through
   1225     // angle a partial stencil mask will cause clears to be
   1226     // turned into draws. Our contract on GrDrawTarget says that
   1227     // changing the clip between stencil passes may or may not
   1228     // zero the client's clip bits. So we just clear the whole thing.
   1229     static const GrGLint clipStencilMask  = ~0;
   1230 #endif
   1231     this->flushRenderTarget(&GrIRect::EmptyIRect());
   1232     flushScissor(&rect);
   1233     GR_GL(StencilMask(clipStencilMask));
   1234     GR_GL(ClearStencil(0));
   1235     GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
   1236     fHWDrawState.fStencilSettings.invalidate();
   1237 }
   1238 
   1239 void GrGpuGL::onForceRenderTargetFlush() {
   1240     this->flushRenderTarget(&GrIRect::EmptyIRect());
   1241 }
   1242 
   1243 bool GrGpuGL::onReadPixels(GrRenderTarget* target,
   1244                            int left, int top, int width, int height,
   1245                            GrPixelConfig config, void* buffer) {
   1246     GrGLenum internalFormat;  // we don't use this for glReadPixels
   1247     GrGLenum format;
   1248     GrGLenum type;
   1249     if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
   1250         return false;
   1251     }
   1252     GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
   1253     GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
   1254     switch (tgt->getResolveType()) {
   1255         case GrGLRenderTarget::kCantResolve_ResolveType:
   1256             return false;
   1257         case GrGLRenderTarget::kAutoResolves_ResolveType:
   1258             autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
   1259             fCurrDrawState.fRenderTarget = target;
   1260             this->flushRenderTarget(&GrIRect::EmptyIRect());
   1261             break;
   1262         case GrGLRenderTarget::kCanResolve_ResolveType:
   1263             this->resolveRenderTarget(tgt);
   1264             // we don't track the state of the READ FBO ID.
   1265             GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
   1266             break;
   1267         default:
   1268             GrCrash("Unknown resolve type");
   1269     }
   1270 
   1271     const GrGLIRect& glvp = tgt->getViewport();
   1272 
   1273     // the read rect is viewport-relative
   1274     GrGLIRect readRect;
   1275     readRect.setRelativeTo(glvp, left, top, width, height);
   1276     GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
   1277                      readRect.fWidth, readRect.fHeight,
   1278                      format, type, buffer));
   1279 
   1280     // now reverse the order of the rows, since GL's are bottom-to-top, but our
   1281     // API presents top-to-bottom
   1282     {
   1283         size_t stride = width * GrBytesPerPixel(config);
   1284         GrAutoMalloc rowStorage(stride);
   1285         void* tmp = rowStorage.get();
   1286 
   1287         const int halfY = height >> 1;
   1288         char* top = reinterpret_cast<char*>(buffer);
   1289         char* bottom = top + (height - 1) * stride;
   1290         for (int y = 0; y < halfY; y++) {
   1291             memcpy(tmp, top, stride);
   1292             memcpy(top, bottom, stride);
   1293             memcpy(bottom, tmp, stride);
   1294             top += stride;
   1295             bottom -= stride;
   1296         }
   1297     }
   1298     return true;
   1299 }
   1300 
   1301 void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
   1302 
   1303     GrAssert(NULL != fCurrDrawState.fRenderTarget);
   1304 
   1305     GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
   1306     if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
   1307         GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
   1308     #if GR_COLLECT_STATS
   1309         ++fStats.fRenderTargetChngCnt;
   1310     #endif
   1311     #if GR_DEBUG
   1312         GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
   1313         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
   1314             GrPrintf("-- glCheckFramebufferStatus %x\n", status);
   1315         }
   1316     #endif
   1317         fDirtyFlags.fRenderTargetChanged = true;
   1318         fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
   1319         const GrGLIRect& vp = rt->getViewport();
   1320         if (fHWBounds.fViewportRect != vp) {
   1321             vp.pushToGLViewport();
   1322             fHWBounds.fViewportRect = vp;
   1323         }
   1324     }
   1325     if (NULL == bound || !bound->isEmpty()) {
   1326         rt->flagAsNeedingResolve(bound);
   1327     }
   1328 }
   1329 
   1330 GrGLenum gPrimitiveType2GLMode[] = {
   1331     GR_GL_TRIANGLES,
   1332     GR_GL_TRIANGLE_STRIP,
   1333     GR_GL_TRIANGLE_FAN,
   1334     GR_GL_POINTS,
   1335     GR_GL_LINES,
   1336     GR_GL_LINE_STRIP
   1337 };
   1338 
   1339 #define SWAP_PER_DRAW 0
   1340 
   1341 #if SWAP_PER_DRAW
   1342     #if GR_MAC_BUILD
   1343         #include <AGL/agl.h>
   1344     #elif GR_WIN32_BUILD
   1345         void SwapBuf() {
   1346             DWORD procID = GetCurrentProcessId();
   1347             HWND hwnd = GetTopWindow(GetDesktopWindow());
   1348             while(hwnd) {
   1349                 DWORD wndProcID = 0;
   1350                 GetWindowThreadProcessId(hwnd, &wndProcID);
   1351                 if(wndProcID == procID) {
   1352                     SwapBuffers(GetDC(hwnd));
   1353                 }
   1354                 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
   1355             }
   1356          }
   1357     #endif
   1358 #endif
   1359 
   1360 void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
   1361                             uint32_t startVertex,
   1362                             uint32_t startIndex,
   1363                             uint32_t vertexCount,
   1364                             uint32_t indexCount) {
   1365     GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
   1366 
   1367     GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
   1368 
   1369     GrAssert(NULL != fHWGeometryState.fIndexBuffer);
   1370     GrAssert(NULL != fHWGeometryState.fVertexBuffer);
   1371 
   1372     // our setupGeometry better have adjusted this to zero since
   1373     // DrawElements always draws from the begining of the arrays for idx 0.
   1374     GrAssert(0 == startVertex);
   1375 
   1376     GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
   1377                        GR_GL_UNSIGNED_SHORT, indices));
   1378 #if SWAP_PER_DRAW
   1379     glFlush();
   1380     #if GR_MAC_BUILD
   1381         aglSwapBuffers(aglGetCurrentContext());
   1382         int set_a_break_pt_here = 9;
   1383         aglSwapBuffers(aglGetCurrentContext());
   1384     #elif GR_WIN32_BUILD
   1385         SwapBuf();
   1386         int set_a_break_pt_here = 9;
   1387         SwapBuf();
   1388     #endif
   1389 #endif
   1390 }
   1391 
   1392 void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
   1393                                uint32_t startVertex,
   1394                                uint32_t vertexCount) {
   1395     GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
   1396 
   1397     GrAssert(NULL != fHWGeometryState.fVertexBuffer);
   1398 
   1399     // our setupGeometry better have adjusted this to zero.
   1400     // DrawElements doesn't take an offset so we always adjus the startVertex.
   1401     GrAssert(0 == startVertex);
   1402 
   1403     // pass 0 for parameter first. We have to adjust gl*Pointer() to
   1404     // account for startVertex in the DrawElements case. So we always
   1405     // rely on setupGeometry to have accounted for startVertex.
   1406     GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
   1407 #if SWAP_PER_DRAW
   1408     glFlush();
   1409     #if GR_MAC_BUILD
   1410         aglSwapBuffers(aglGetCurrentContext());
   1411         int set_a_break_pt_here = 9;
   1412         aglSwapBuffers(aglGetCurrentContext());
   1413     #elif GR_WIN32_BUILD
   1414         SwapBuf();
   1415         int set_a_break_pt_here = 9;
   1416         SwapBuf();
   1417     #endif
   1418 #endif
   1419 }
   1420 
   1421 void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
   1422 
   1423     if (rt->needsResolve()) {
   1424         GrAssert(kNone_MSFBO != fMSFBOType);
   1425         GrAssert(rt->textureFBOID() != rt->renderFBOID());
   1426         GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
   1427                                         rt->renderFBOID()));
   1428         GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
   1429                                         rt->textureFBOID()));
   1430     #if GR_COLLECT_STATS
   1431         ++fStats.fRenderTargetChngCnt;
   1432     #endif
   1433         // make sure we go through flushRenderTarget() since we've modified
   1434         // the bound DRAW FBO ID.
   1435         fHWDrawState.fRenderTarget = NULL;
   1436         const GrGLIRect& vp = rt->getViewport();
   1437         const GrIRect dirtyRect = rt->getResolveRect();
   1438         GrGLIRect r;
   1439         r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
   1440                         dirtyRect.width(), dirtyRect.height());
   1441 
   1442         if (kAppleES_MSFBO == fMSFBOType) {
   1443             // Apple's extension uses the scissor as the blit bounds.
   1444             GR_GL(Enable(GR_GL_SCISSOR_TEST));
   1445             GR_GL(Scissor(r.fLeft, r.fBottom,
   1446                           r.fWidth, r.fHeight));
   1447             GR_GL(ResolveMultisampleFramebuffer());
   1448             fHWBounds.fScissorRect.invalidate();
   1449             fHWBounds.fScissorEnabled = true;
   1450         } else {
   1451             if (kDesktopARB_MSFBO != fMSFBOType) {
   1452                 // this respects the scissor during the blit, so disable it.
   1453                 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
   1454                 flushScissor(NULL);
   1455             }
   1456             int right = r.fLeft + r.fWidth;
   1457             int top = r.fBottom + r.fHeight;
   1458             GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
   1459                                   r.fLeft, r.fBottom, right, top,
   1460                                   GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
   1461         }
   1462         rt->flagAsResolved();
   1463     }
   1464 }
   1465 
   1466 static const GrGLenum grToGLStencilFunc[] = {
   1467     GR_GL_ALWAYS,           // kAlways_StencilFunc
   1468     GR_GL_NEVER,            // kNever_StencilFunc
   1469     GR_GL_GREATER,          // kGreater_StencilFunc
   1470     GR_GL_GEQUAL,           // kGEqual_StencilFunc
   1471     GR_GL_LESS,             // kLess_StencilFunc
   1472     GR_GL_LEQUAL,           // kLEqual_StencilFunc,
   1473     GR_GL_EQUAL,            // kEqual_StencilFunc,
   1474     GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
   1475 };
   1476 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
   1477 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
   1478 GR_STATIC_ASSERT(1 == kNever_StencilFunc);
   1479 GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
   1480 GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
   1481 GR_STATIC_ASSERT(4 == kLess_StencilFunc);
   1482 GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
   1483 GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
   1484 GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
   1485 
   1486 static const GrGLenum grToGLStencilOp[] = {
   1487     GR_GL_KEEP,        // kKeep_StencilOp
   1488     GR_GL_REPLACE,     // kReplace_StencilOp
   1489     GR_GL_INCR_WRAP,   // kIncWrap_StencilOp
   1490     GR_GL_INCR,        // kIncClamp_StencilOp
   1491     GR_GL_DECR_WRAP,   // kDecWrap_StencilOp
   1492     GR_GL_DECR,        // kDecClamp_StencilOp
   1493     GR_GL_ZERO,        // kZero_StencilOp
   1494     GR_GL_INVERT,      // kInvert_StencilOp
   1495 };
   1496 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
   1497 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
   1498 GR_STATIC_ASSERT(1 == kReplace_StencilOp);
   1499 GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
   1500 GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
   1501 GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
   1502 GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
   1503 GR_STATIC_ASSERT(6 == kZero_StencilOp);
   1504 GR_STATIC_ASSERT(7 == kInvert_StencilOp);
   1505 
   1506 void GrGpuGL::flushStencil() {
   1507     const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
   1508 
   1509     // use stencil for clipping if clipping is enabled and the clip
   1510     // has been written into the stencil.
   1511     bool stencilClip = fClipState.fClipInStencil &&
   1512                        (kClip_StateBit & fCurrDrawState.fFlagBits);
   1513     bool stencilChange = fHWStencilClip != stencilClip  ||
   1514                          fHWDrawState.fStencilSettings != *settings ||
   1515                          ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
   1516                           (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
   1517 
   1518     if (stencilChange) {
   1519 
   1520         // we can't simultaneously perform stencil-clipping and modify the stencil clip
   1521         GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
   1522 
   1523         if (settings->isDisabled()) {
   1524             if (stencilClip) {
   1525                 settings = &gClipStencilSettings;
   1526             }
   1527         }
   1528 
   1529         if (settings->isDisabled()) {
   1530             GR_GL(Disable(GR_GL_STENCIL_TEST));
   1531         } else {
   1532             GR_GL(Enable(GR_GL_STENCIL_TEST));
   1533     #if GR_DEBUG
   1534             if (!fStencilWrapOpsSupport) {
   1535                 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
   1536                 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
   1537                 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
   1538                 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
   1539                 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
   1540                 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
   1541                 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
   1542                 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
   1543             }
   1544     #endif
   1545             int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
   1546             GrAssert(stencilBits ||
   1547                      (GrStencilSettings::gDisabled ==
   1548                       fCurrDrawState.fStencilSettings));
   1549             GrGLuint clipStencilMask = 1 << (stencilBits - 1);
   1550             GrGLuint userStencilMask = clipStencilMask - 1;
   1551 
   1552             unsigned int frontRef  = settings->fFrontFuncRef;
   1553             unsigned int frontMask = settings->fFrontFuncMask;
   1554             unsigned int frontWriteMask = settings->fFrontWriteMask;
   1555             GrGLenum frontFunc;
   1556 
   1557             if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
   1558 
   1559                 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
   1560                 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
   1561             } else {
   1562                 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
   1563 
   1564                 ConvertStencilFuncAndMask(settings->fFrontFunc,
   1565                                           stencilClip,
   1566                                           clipStencilMask,
   1567                                           userStencilMask,
   1568                                           &frontRef,
   1569                                           &frontMask);
   1570                 frontWriteMask &= userStencilMask;
   1571             }
   1572             GrAssert(settings->fFrontFailOp >= 0 &&
   1573                      (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
   1574             GrAssert(settings->fFrontPassOp >= 0 &&
   1575                      (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
   1576             GrAssert(settings->fBackFailOp >= 0 &&
   1577                      (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
   1578             GrAssert(settings->fBackPassOp >= 0 &&
   1579                      (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
   1580             if (fTwoSidedStencilSupport) {
   1581                 GrGLenum backFunc;
   1582 
   1583                 unsigned int backRef  = settings->fBackFuncRef;
   1584                 unsigned int backMask = settings->fBackFuncMask;
   1585                 unsigned int backWriteMask = settings->fBackWriteMask;
   1586 
   1587 
   1588                 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
   1589                     GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
   1590                     backFunc = grToGLStencilFunc[settings->fBackFunc];
   1591                 } else {
   1592                     backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
   1593                     ConvertStencilFuncAndMask(settings->fBackFunc,
   1594                                               stencilClip,
   1595                                               clipStencilMask,
   1596                                               userStencilMask,
   1597                                               &backRef,
   1598                                               &backMask);
   1599                     backWriteMask &= userStencilMask;
   1600                 }
   1601 
   1602                 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
   1603                 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
   1604                 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
   1605                 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
   1606                 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
   1607                                                   grToGLStencilOp[settings->fFrontPassOp],
   1608                                                   grToGLStencilOp[settings->fFrontPassOp]));
   1609 
   1610                 GR_GL(StencilOpSeparate(GR_GL_BACK,  grToGLStencilOp[settings->fBackFailOp],
   1611                                                   grToGLStencilOp[settings->fBackPassOp],
   1612                                                   grToGLStencilOp[settings->fBackPassOp]));
   1613             } else {
   1614                 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
   1615                 GR_GL(StencilMask(frontWriteMask));
   1616                 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
   1617                                 grToGLStencilOp[settings->fFrontPassOp],
   1618                                 grToGLStencilOp[settings->fFrontPassOp]));
   1619             }
   1620         }
   1621         fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
   1622         fHWStencilClip = stencilClip;
   1623     }
   1624 }
   1625 
   1626 bool GrGpuGL::useSmoothLines() {
   1627     // there is a conflict between using smooth lines and our use of
   1628     // premultiplied alpha. Smooth lines tweak the incoming alpha value
   1629     // but not in a premul-alpha way. So we only use them when our alpha
   1630     // is 0xff.
   1631 
   1632     // TODO: write a smarter line frag shader.
   1633 
   1634     return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
   1635            canDisableBlend();
   1636 }
   1637 
   1638 void GrGpuGL::flushAAState(GrPrimitiveType type) {
   1639     if (GR_GL_SUPPORT_DESKTOP) {
   1640         // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
   1641         // smooth lines.
   1642 
   1643         // we prefer smooth lines over multisampled lines
   1644         // msaa should be disabled if drawing smooth lines.
   1645         if (GrIsPrimTypeLines(type)) {
   1646             bool smooth = useSmoothLines();
   1647             if (!fHWAAState.fSmoothLineEnabled && smooth) {
   1648                 GR_GL(Enable(GR_GL_LINE_SMOOTH));
   1649                 fHWAAState.fSmoothLineEnabled = true;
   1650             } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
   1651                 GR_GL(Disable(GR_GL_LINE_SMOOTH));
   1652                 fHWAAState.fSmoothLineEnabled = false;
   1653             }
   1654             if (fCurrDrawState.fRenderTarget->isMultisampled() &&
   1655                 fHWAAState.fMSAAEnabled) {
   1656                 GR_GL(Disable(GR_GL_MULTISAMPLE));
   1657                 fHWAAState.fMSAAEnabled = false;
   1658             }
   1659         } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
   1660                    !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
   1661                    fHWAAState.fMSAAEnabled) {
   1662             if (fHWAAState.fMSAAEnabled) {
   1663                 GR_GL(Disable(GR_GL_MULTISAMPLE));
   1664                 fHWAAState.fMSAAEnabled = false;
   1665             } else {
   1666                 GR_GL(Enable(GR_GL_MULTISAMPLE));
   1667                 fHWAAState.fMSAAEnabled = true;
   1668             }
   1669         }
   1670     }
   1671 }
   1672 
   1673 void GrGpuGL::flushBlend(GrPrimitiveType type,
   1674                          GrBlendCoeff srcCoeff,
   1675                          GrBlendCoeff dstCoeff) {
   1676     if (GrIsPrimTypeLines(type) && useSmoothLines()) {
   1677         if (fHWBlendDisabled) {
   1678             GR_GL(Enable(GR_GL_BLEND));
   1679             fHWBlendDisabled = false;
   1680         }
   1681         if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
   1682             kISA_BlendCoeff != fHWDrawState.fDstBlend) {
   1683             GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
   1684                             gXfermodeCoeff2Blend[kISA_BlendCoeff]));
   1685             fHWDrawState.fSrcBlend = kSA_BlendCoeff;
   1686             fHWDrawState.fDstBlend = kISA_BlendCoeff;
   1687         }
   1688     } else {
   1689         bool blendOff = canDisableBlend();
   1690         if (fHWBlendDisabled != blendOff) {
   1691             if (blendOff) {
   1692                 GR_GL(Disable(GR_GL_BLEND));
   1693             } else {
   1694                 GR_GL(Enable(GR_GL_BLEND));
   1695             }
   1696             fHWBlendDisabled = blendOff;
   1697         }
   1698         if (!blendOff) {
   1699             if (fHWDrawState.fSrcBlend != srcCoeff ||
   1700                 fHWDrawState.fDstBlend != dstCoeff) {
   1701                 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
   1702                                 gXfermodeCoeff2Blend[dstCoeff]));
   1703                 fHWDrawState.fSrcBlend = srcCoeff;
   1704                 fHWDrawState.fDstBlend = dstCoeff;
   1705             }
   1706             if ((BlendCoeffReferencesConstant(srcCoeff) ||
   1707                  BlendCoeffReferencesConstant(dstCoeff)) &&
   1708                 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
   1709 
   1710                 float c[] = {
   1711                     GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
   1712                     GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
   1713                     GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
   1714                     GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
   1715                 };
   1716                 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
   1717                 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
   1718             }
   1719         }
   1720     }
   1721 }
   1722 
   1723 bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
   1724 
   1725     // GrGpu::setupClipAndFlushState should have already checked this
   1726     // and bailed if not true.
   1727     GrAssert(NULL != fCurrDrawState.fRenderTarget);
   1728 
   1729     for (int s = 0; s < kNumStages; ++s) {
   1730         // bind texture and set sampler state
   1731         if (this->isStageEnabled(s)) {
   1732             GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
   1733 
   1734             // true for now, but maybe not with GrEffect.
   1735             GrAssert(NULL != nextTexture);
   1736             // if we created a rt/tex and rendered to it without using a
   1737             // texture and now we're texuring from the rt it will still be
   1738             // the last bound texture, but it needs resolving. So keep this
   1739             // out of the "last != next" check.
   1740             GrGLRenderTarget* texRT =
   1741                 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
   1742             if (NULL != texRT) {
   1743                 resolveRenderTarget(texRT);
   1744             }
   1745 
   1746             if (fHWDrawState.fTextures[s] != nextTexture) {
   1747                 setTextureUnit(s);
   1748                 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
   1749             #if GR_COLLECT_STATS
   1750                 ++fStats.fTextureChngCnt;
   1751             #endif
   1752                 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
   1753                 fHWDrawState.fTextures[s] = nextTexture;
   1754             }
   1755 
   1756             const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
   1757             const GrGLTexture::TexParams& oldTexParams =
   1758                                                 nextTexture->getTexParams();
   1759             GrGLTexture::TexParams newTexParams;
   1760 
   1761             if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
   1762                 newTexParams.fFilter = GR_GL_NEAREST;
   1763             } else {
   1764                 newTexParams.fFilter = GR_GL_LINEAR;
   1765             }
   1766 
   1767             newTexParams.fWrapS =
   1768                         GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
   1769             newTexParams.fWrapT =
   1770                         GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
   1771 
   1772             if (newTexParams.fFilter != oldTexParams.fFilter) {
   1773                 setTextureUnit(s);
   1774                 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
   1775                                     GR_GL_TEXTURE_MAG_FILTER,
   1776                                     newTexParams.fFilter));
   1777                 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
   1778                                     GR_GL_TEXTURE_MIN_FILTER,
   1779                                     newTexParams.fFilter));
   1780             }
   1781             if (newTexParams.fWrapS != oldTexParams.fWrapS) {
   1782                 setTextureUnit(s);
   1783                 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
   1784                                     GR_GL_TEXTURE_WRAP_S,
   1785                                     newTexParams.fWrapS));
   1786             }
   1787             if (newTexParams.fWrapT != oldTexParams.fWrapT) {
   1788                 setTextureUnit(s);
   1789                 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
   1790                                     GR_GL_TEXTURE_WRAP_T,
   1791                                     newTexParams.fWrapT));
   1792             }
   1793             nextTexture->setTexParams(newTexParams);
   1794 
   1795             // The texture matrix has to compensate for texture width/height
   1796             // and NPOT-embedded-in-POT
   1797             fDirtyFlags.fTextureChangedMask |= (1 << s);
   1798         }
   1799     }
   1800 
   1801     GrIRect* rect = NULL;
   1802     GrIRect clipBounds;
   1803     if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
   1804         fClip.hasConservativeBounds()) {
   1805         fClip.getConservativeBounds().roundOut(&clipBounds);
   1806         rect = &clipBounds;
   1807     }
   1808     this->flushRenderTarget(rect);
   1809     this->flushAAState(type);
   1810 
   1811     if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
   1812         (fHWDrawState.fFlagBits & kDither_StateBit)) {
   1813         if (fCurrDrawState.fFlagBits & kDither_StateBit) {
   1814             GR_GL(Enable(GR_GL_DITHER));
   1815         } else {
   1816             GR_GL(Disable(GR_GL_DITHER));
   1817         }
   1818     }
   1819 
   1820     if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
   1821         (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
   1822         GrGLenum mask;
   1823         if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
   1824             mask = GR_GL_FALSE;
   1825         } else {
   1826             mask = GR_GL_TRUE;
   1827         }
   1828         GR_GL(ColorMask(mask, mask, mask, mask));
   1829     }
   1830 
   1831     if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
   1832         switch (fCurrDrawState.fDrawFace) {
   1833             case kCCW_DrawFace:
   1834                 GR_GL(Enable(GR_GL_CULL_FACE));
   1835                 GR_GL(CullFace(GR_GL_BACK));
   1836                 break;
   1837             case kCW_DrawFace:
   1838                 GR_GL(Enable(GR_GL_CULL_FACE));
   1839                 GR_GL(CullFace(GR_GL_FRONT));
   1840                 break;
   1841             case kBoth_DrawFace:
   1842                 GR_GL(Disable(GR_GL_CULL_FACE));
   1843                 break;
   1844             default:
   1845                 GrCrash("Unknown draw face.");
   1846         }
   1847         fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
   1848     }
   1849 
   1850 #if GR_DEBUG
   1851     // check for circular rendering
   1852     for (int s = 0; s < kNumStages; ++s) {
   1853         GrAssert(!this->isStageEnabled(s) ||
   1854                  NULL == fCurrDrawState.fRenderTarget ||
   1855                  NULL == fCurrDrawState.fTextures[s] ||
   1856                  fCurrDrawState.fTextures[s]->asRenderTarget() !=
   1857                     fCurrDrawState.fRenderTarget);
   1858     }
   1859 #endif
   1860 
   1861     flushStencil();
   1862 
   1863     // flushStencil may look at the private state bits, so keep it before this.
   1864     fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
   1865     return true;
   1866 }
   1867 
   1868 void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
   1869     if (fHWGeometryState.fVertexBuffer != buffer) {
   1870         fHWGeometryState.fArrayPtrsDirty = true;
   1871         fHWGeometryState.fVertexBuffer = buffer;
   1872     }
   1873 }
   1874 
   1875 void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
   1876     if (fHWGeometryState.fVertexBuffer == buffer) {
   1877         // deleting bound buffer does implied bind to 0
   1878         fHWGeometryState.fVertexBuffer = NULL;
   1879         fHWGeometryState.fArrayPtrsDirty = true;
   1880     }
   1881 }
   1882 
   1883 void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
   1884     fGeometrySrc.fIndexBuffer = buffer;
   1885 }
   1886 
   1887 void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
   1888     if (fHWGeometryState.fIndexBuffer == buffer) {
   1889         // deleting bound buffer does implied bind to 0
   1890         fHWGeometryState.fIndexBuffer = NULL;
   1891     }
   1892 }
   1893 
   1894 void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
   1895     GrAssert(NULL != renderTarget);
   1896     if (fCurrDrawState.fRenderTarget == renderTarget) {
   1897         fCurrDrawState.fRenderTarget = NULL;
   1898     }
   1899     if (fHWDrawState.fRenderTarget == renderTarget) {
   1900         fHWDrawState.fRenderTarget = NULL;
   1901     }
   1902 }
   1903 
   1904 void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
   1905     for (int s = 0; s < kNumStages; ++s) {
   1906         if (fCurrDrawState.fTextures[s] == texture) {
   1907             fCurrDrawState.fTextures[s] = NULL;
   1908         }
   1909         if (fHWDrawState.fTextures[s] == texture) {
   1910             // deleting bound texture does implied bind to 0
   1911             fHWDrawState.fTextures[s] = NULL;
   1912        }
   1913     }
   1914 }
   1915 
   1916 bool GrGpuGL::canBeTexture(GrPixelConfig config,
   1917                            GrGLenum* internalFormat,
   1918                            GrGLenum* format,
   1919                            GrGLenum* type) {
   1920     switch (config) {
   1921         case kRGBA_8888_GrPixelConfig:
   1922         case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
   1923             *format = GR_GL_32BPP_COLOR_FORMAT;
   1924             if (GR_GL_SUPPORT_ES) {
   1925                 // according to GL_EXT_texture_format_BGRA8888 the *internal*
   1926                 // format for a BGRA is BGRA not RGBA (as on desktop)
   1927                 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
   1928             } else {
   1929                 *internalFormat = GR_GL_RGBA;
   1930             }
   1931             *type = GR_GL_UNSIGNED_BYTE;
   1932             break;
   1933         case kRGB_565_GrPixelConfig:
   1934             *format = GR_GL_RGB;
   1935             *internalFormat = GR_GL_RGB;
   1936             *type = GR_GL_UNSIGNED_SHORT_5_6_5;
   1937             break;
   1938         case kRGBA_4444_GrPixelConfig:
   1939             *format = GR_GL_RGBA;
   1940             *internalFormat = GR_GL_RGBA;
   1941             *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
   1942             break;
   1943         case kIndex_8_GrPixelConfig:
   1944             if (this->supports8BitPalette()) {
   1945                 *format = GR_GL_PALETTE8_RGBA8;
   1946                 *internalFormat = GR_GL_PALETTE8_RGBA8;
   1947                 *type = GR_GL_UNSIGNED_BYTE;   // unused I think
   1948             } else {
   1949                 return false;
   1950             }
   1951             break;
   1952         case kAlpha_8_GrPixelConfig:
   1953             *format = GR_GL_ALPHA;
   1954             *internalFormat = GR_GL_ALPHA;
   1955             *type = GR_GL_UNSIGNED_BYTE;
   1956             break;
   1957         default:
   1958             return false;
   1959     }
   1960     return true;
   1961 }
   1962 
   1963 void GrGpuGL::setTextureUnit(int unit) {
   1964     GrAssert(unit >= 0 && unit < kNumStages);
   1965     if (fActiveTextureUnitIdx != unit) {
   1966         GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
   1967         fActiveTextureUnitIdx = unit;
   1968     }
   1969 }
   1970 
   1971 void GrGpuGL::setSpareTextureUnit() {
   1972     if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
   1973         GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
   1974         fActiveTextureUnitIdx = SPARE_TEX_UNIT;
   1975     }
   1976 }
   1977 
   1978 /* On ES the internalFormat and format must match for TexImage and we use
   1979    GL_RGB, GL_RGBA for color formats. We also generally like having the driver
   1980    decide the internalFormat. However, on ES internalFormat for
   1981    RenderBufferStorage* has to be a specific format (not a base format like
   1982    GL_RGBA).
   1983  */
   1984 bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
   1985     switch (config) {
   1986         case kRGBA_8888_GrPixelConfig:
   1987         case kRGBX_8888_GrPixelConfig:
   1988             if (fRGBA8Renderbuffer) {
   1989                 *format = GR_GL_RGBA8;
   1990                 return true;
   1991             } else {
   1992                 return false;
   1993             }
   1994         case kRGB_565_GrPixelConfig:
   1995             GrAssert(GR_GL_SUPPORT_ES);  // ES2 supports 565. ES1 supports it
   1996                                          // with FBO extension desktop GL has
   1997                                          // no such internal format
   1998             *format = GR_GL_RGB565;
   1999             return true;
   2000         case kRGBA_4444_GrPixelConfig:
   2001             *format = GR_GL_RGBA4;
   2002             return true;
   2003         default:
   2004             return false;
   2005     }
   2006 }
   2007 
   2008 void GrGpuGL::resetDirtyFlags() {
   2009     Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
   2010 }
   2011 
   2012 void GrGpuGL::setBuffers(bool indexed,
   2013                          int* extraVertexOffset,
   2014                          int* extraIndexOffset) {
   2015 
   2016     GrAssert(NULL != extraVertexOffset);
   2017 
   2018     GrGLVertexBuffer* vbuf;
   2019     switch (fGeometrySrc.fVertexSrc) {
   2020     case kBuffer_GeometrySrcType:
   2021         *extraVertexOffset = 0;
   2022         vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
   2023         break;
   2024     case kArray_GeometrySrcType:
   2025     case kReserved_GeometrySrcType:
   2026         finalizeReservedVertices();
   2027         *extraVertexOffset = fCurrPoolStartVertex;
   2028         vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
   2029         break;
   2030     default:
   2031         vbuf = NULL; // suppress warning
   2032         GrCrash("Unknown geometry src type!");
   2033     }
   2034 
   2035     GrAssert(NULL != vbuf);
   2036     GrAssert(!vbuf->isLocked());
   2037     if (fHWGeometryState.fVertexBuffer != vbuf) {
   2038         GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
   2039         fHWGeometryState.fArrayPtrsDirty = true;
   2040         fHWGeometryState.fVertexBuffer = vbuf;
   2041     }
   2042 
   2043     if (indexed) {
   2044         GrAssert(NULL != extraIndexOffset);
   2045 
   2046         GrGLIndexBuffer* ibuf;
   2047         switch (fGeometrySrc.fIndexSrc) {
   2048         case kBuffer_GeometrySrcType:
   2049             *extraIndexOffset = 0;
   2050             ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
   2051             break;
   2052         case kArray_GeometrySrcType:
   2053         case kReserved_GeometrySrcType:
   2054             finalizeReservedIndices();
   2055             *extraIndexOffset = fCurrPoolStartIndex;
   2056             ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
   2057             break;
   2058         default:
   2059             ibuf = NULL; // suppress warning
   2060             GrCrash("Unknown geometry src type!");
   2061         }
   2062 
   2063         GrAssert(NULL != ibuf);
   2064         GrAssert(!ibuf->isLocked());
   2065         if (fHWGeometryState.fIndexBuffer != ibuf) {
   2066             GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
   2067             fHWGeometryState.fIndexBuffer = ibuf;
   2068         }
   2069     }
   2070 }
   2071 
   2072 int GrGpuGL::getMaxEdges() const {
   2073     // FIXME:  This is a pessimistic estimate based on how many other things
   2074     // want to add uniforms.  This should be centralized somewhere.
   2075     return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
   2076 }
   2077