1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "GrGpuGL.h"
11#include "GrGLStencilBuffer.h"
12#include "GrTypes.h"
13#include "SkTemplates.h"
14
15static const GrGLuint GR_MAX_GLUINT = ~0;
16static const GrGLint  GR_INVAL_GLINT = ~0;
17
18#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
19#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
20
21// we use a spare texture unit to avoid
22// mucking with the state of any of the stages.
23static const int SPARE_TEX_UNIT = GrDrawState::kNumStages;
24
25#define SKIP_CACHE_CHECK    true
26
27#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
28    #define CLEAR_ERROR_BEFORE_ALLOC(iface)   GrGLClearErr(iface)
29    #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL_NOERRCHECK(iface, call)
30    #define CHECK_ALLOC_ERROR(iface)          GR_GL_GET_ERROR(iface)
31#else
32    #define CLEAR_ERROR_BEFORE_ALLOC(iface)
33    #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL(iface, call)
34    #define CHECK_ALLOC_ERROR(iface)          GR_GL_NO_ERROR
35#endif
36
37
38///////////////////////////////////////////////////////////////////////////////
39
40static const GrGLenum gXfermodeCoeff2Blend[] = {
41    GR_GL_ZERO,
42    GR_GL_ONE,
43    GR_GL_SRC_COLOR,
44    GR_GL_ONE_MINUS_SRC_COLOR,
45    GR_GL_DST_COLOR,
46    GR_GL_ONE_MINUS_DST_COLOR,
47    GR_GL_SRC_ALPHA,
48    GR_GL_ONE_MINUS_SRC_ALPHA,
49    GR_GL_DST_ALPHA,
50    GR_GL_ONE_MINUS_DST_ALPHA,
51    GR_GL_CONSTANT_COLOR,
52    GR_GL_ONE_MINUS_CONSTANT_COLOR,
53    GR_GL_CONSTANT_ALPHA,
54    GR_GL_ONE_MINUS_CONSTANT_ALPHA,
55
56    // extended blend coeffs
57    GR_GL_SRC1_COLOR,
58    GR_GL_ONE_MINUS_SRC1_COLOR,
59    GR_GL_SRC1_ALPHA,
60    GR_GL_ONE_MINUS_SRC1_ALPHA,
61};
62
63bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
64    static const bool gCoeffReferencesBlendConst[] = {
65        false,
66        false,
67        false,
68        false,
69        false,
70        false,
71        false,
72        false,
73        false,
74        false,
75        true,
76        true,
77        true,
78        true,
79
80        // extended blend coeffs
81        false,
82        false,
83        false,
84        false,
85    };
86    return gCoeffReferencesBlendConst[coeff];
87    GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
88
89    GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
90    GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
91    GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
92    GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
93    GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
94    GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
95    GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
96    GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
97    GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
98    GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
99    GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
100    GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
101    GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
102    GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
103
104    GR_STATIC_ASSERT(14 == kS2C_BlendCoeff);
105    GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff);
106    GR_STATIC_ASSERT(16 == kS2A_BlendCoeff);
107    GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff);
108
109    // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
110    GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
111}
112
113///////////////////////////////////////////////////////////////////////////////
114
115void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
116                                  GrSamplerState::SampleMode mode,
117                                  GrMatrix* matrix) {
118    GrAssert(NULL != texture);
119    GrAssert(NULL != matrix);
120    GrGLTexture::Orientation orientation = texture->orientation();
121    if (GrGLTexture::kBottomUp_Orientation == orientation) {
122        GrMatrix invY;
123        invY.setAll(GR_Scalar1, 0,           0,
124                    0,          -GR_Scalar1, GR_Scalar1,
125                    0,          0,           GrMatrix::I()[8]);
126        matrix->postConcat(invY);
127    } else {
128        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
129    }
130}
131
132bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
133                                      const GrSamplerState& sampler) {
134    GrAssert(NULL != texture);
135    if (!sampler.getMatrix().isIdentity()) {
136        return false;
137    }
138    GrGLTexture::Orientation orientation = texture->orientation();
139    if (GrGLTexture::kBottomUp_Orientation == orientation) {
140        return false;
141    } else {
142        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
143    }
144    return true;
145}
146
147///////////////////////////////////////////////////////////////////////////////
148
149static bool gPrintStartupSpew;
150
151static bool fbo_test(const GrGLInterface* gl, int w, int h) {
152
153    GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
154
155    GrGLuint testFBO;
156    GR_GL_CALL(gl, GenFramebuffers(1, &testFBO));
157    GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
158    GrGLuint testRTTex;
159    GR_GL_CALL(gl, GenTextures(1, &testRTTex));
160    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, testRTTex));
161    // some implementations require texture to be mip-map complete before
162    // FBO with level 0 bound as color attachment will be framebuffer complete.
163    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
164                                 GR_GL_TEXTURE_MIN_FILTER,
165                                 GR_GL_NEAREST));
166    GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
167                              0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
168    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
169    GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
170                                        GR_GL_COLOR_ATTACHMENT0,
171                                        GR_GL_TEXTURE_2D, testRTTex, 0));
172    GrGLenum status;
173    GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
174    GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO));
175    GR_GL_CALL(gl, DeleteTextures(1, &testRTTex));
176
177    return status == GR_GL_FRAMEBUFFER_COMPLETE;
178}
179
180GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
181
182    GrAssert(ctxInfo.isInitialized());
183
184    fPrintedCaps = false;
185
186    GrGLClearErr(fGLContextInfo.interface());
187
188    if (gPrintStartupSpew) {
189        const GrGLubyte* ext;
190        GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
191        const GrGLubyte* vendor;
192        const GrGLubyte* renderer;
193        const GrGLubyte* version;
194        GL_CALL_RET(vendor, GetString(GR_GL_VENDOR));
195        GL_CALL_RET(renderer, GetString(GR_GL_RENDERER));
196        GL_CALL_RET(version, GetString(GR_GL_VERSION));
197        GrPrintf("------------------------- create GrGpuGL %p --------------\n",
198                 this);
199        GrPrintf("------ VENDOR %s\n", vendor);
200        GrPrintf("------ RENDERER %s\n", renderer);
201        GrPrintf("------ VERSION %s\n",  version);
202        GrPrintf("------ EXTENSIONS\n %s \n", ext);
203    }
204
205    this->resetDirtyFlags();
206
207    this->initCaps();
208
209    fLastSuccessfulStencilFmtIdx = 0;
210    fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip;
211}
212
213GrGpuGL::~GrGpuGL() {
214    // This must be called by before the GrDrawTarget destructor
215    this->releaseGeometry();
216    // This subclass must do this before the base class destructor runs
217    // since we will unref the GrGLInterface.
218    this->releaseResources();
219}
220
221///////////////////////////////////////////////////////////////////////////////
222
223void GrGpuGL::initCaps() {
224    GrGLint maxTextureUnits;
225    // check FS and fixed-function texture unit limits
226    // we only use textures in the fragment stage currently.
227    // checks are > to make sure we have a spare unit.
228    const GrGLInterface* gl = this->glInterface();
229    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
230    GrAssert(maxTextureUnits > GrDrawState::kNumStages);
231    if (kES2_GrGLBinding != this->glBinding()) {
232        GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
233        GrAssert(maxTextureUnits > GrDrawState::kNumStages);
234    }
235
236    GrGLint numFormats;
237    GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
238    SkAutoSTMalloc<10, GrGLint> formats(numFormats);
239    GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
240    for (int i = 0; i < numFormats; ++i) {
241        if (formats[i] == GR_GL_PALETTE8_RGBA8) {
242            fCaps.f8BitPaletteSupport = true;
243            break;
244        }
245    }
246
247    if (kDesktop_GrGLBinding == this->glBinding()) {
248        // we could also look for GL_ATI_separate_stencil extension or
249        // GL_EXT_stencil_two_side but they use different function signatures
250        // than GL2.0+ (and than each other).
251        fCaps.fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0));
252        // supported on GL 1.4 and higher or by extension
253        fCaps.fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) ||
254                                       this->hasExtension("GL_EXT_stencil_wrap");
255    } else {
256        // ES 2 has two sided stencil and stencil wrap
257        fCaps.fTwoSidedStencilSupport = true;
258        fCaps.fStencilWrapOpsSupport = true;
259    }
260
261    if (kDesktop_GrGLBinding == this->glBinding()) {
262        fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO
263                                         // extension includes glMapBuffer.
264    } else {
265        fCaps.fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
266    }
267
268    if (kDesktop_GrGLBinding == this->glBinding()) {
269        if (this->glVersion() >= GR_GL_VER(2,0) ||
270            this->hasExtension("GL_ARB_texture_non_power_of_two")) {
271            fCaps.fNPOTTextureTileSupport = true;
272        } else {
273            fCaps.fNPOTTextureTileSupport = false;
274        }
275    } else {
276        // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
277        fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
278    }
279
280    fCaps.fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding());
281
282    ////////////////////////////////////////////////////////////////////////////
283    // Experiments to determine limitations that can't be queried.
284    // TODO: Make these a preprocess that generate some compile time constants.
285    // TODO: probe once at startup, rather than once per context creation.
286
287    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize);
288    GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize);
289    // Our render targets are always created with textures as the color
290    // attachment, hence this min:
291    fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize);
292
293    fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType();
294}
295
296bool GrGpuGL::canPreserveReadWriteUnpremulPixels() {
297    if (kUnknown_CanPreserveUnpremulRoundtrip ==
298        fCanPreserveUnpremulRoundtrip) {
299
300        SkAutoTMalloc<uint32_t> data(256 * 256 * 3);
301        uint32_t* srcData = data.get();
302        uint32_t* firstRead = data.get() + 256 * 256;
303        uint32_t* secondRead = data.get() + 2 * 256 * 256;
304
305        for (int y = 0; y < 256; ++y) {
306            for (int x = 0; x < 256; ++x) {
307                uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
308                color[3] = y;
309                color[2] = x;
310                color[1] = x;
311                color[0] = x;
312            }
313        }
314
315        // We have broader support for read/write pixels on render targets
316        // than on textures.
317        GrTextureDesc dstDesc;
318        dstDesc.fFlags = kRenderTarget_GrTextureFlagBit |
319                         kNoStencil_GrTextureFlagBit;
320        dstDesc.fWidth = 256;
321        dstDesc.fHeight = 256;
322        dstDesc.fConfig = kRGBA_8888_GrPixelConfig;
323        dstDesc.fSampleCnt = 0;
324
325        SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0));
326        if (!dstTex.get()) {
327            return false;
328        }
329        GrRenderTarget* rt = dstTex.get()->asRenderTarget();
330        GrAssert(NULL != rt);
331
332        bool failed = true;
333        static const UnpremulConversion gMethods[] = {
334            kUpOnWrite_DownOnRead_UnpremulConversion,
335            kDownOnWrite_UpOnRead_UnpremulConversion,
336        };
337
338        // pretend that we can do the roundtrip to avoid recursive calls to
339        // this function
340        fCanPreserveUnpremulRoundtrip = kYes_CanPreserveUnpremulRoundtrip;
341        for (size_t i = 0; i < GR_ARRAY_COUNT(gMethods) && failed; ++i) {
342            fUnpremulConversion = gMethods[i];
343            rt->writePixels(0, 0,
344                            256, 256,
345                            kRGBA_8888_UPM_GrPixelConfig, srcData, 0);
346            rt->readPixels(0, 0,
347                           256, 256,
348                           kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
349            rt->writePixels(0, 0,
350                            256, 256,
351                            kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
352            rt->readPixels(0, 0,
353                           256, 256,
354                           kRGBA_8888_UPM_GrPixelConfig, secondRead, 0);
355            failed = false;
356            for (int j = 0; j < 256 * 256; ++j) {
357                if (firstRead[j] != secondRead[j]) {
358                    failed = true;
359                    break;
360                }
361            }
362        }
363        fCanPreserveUnpremulRoundtrip = failed ?
364                        kNo_CanPreserveUnpremulRoundtrip :
365                        kYes_CanPreserveUnpremulRoundtrip;
366    }
367
368    if (kYes_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) {
369        return true;
370    } else {
371        return false;
372    }
373}
374
375GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const {
376    if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
377        return GrPixelConfigSwapRAndB(config);
378    } else {
379        return config;
380    }
381}
382
383GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) const {
384    if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
385        return GrPixelConfigSwapRAndB(config);
386    } else {
387        return config;
388    }
389}
390
391bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const {
392    return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL);
393}
394
395void GrGpuGL::onResetContext() {
396    if (gPrintStartupSpew && !fPrintedCaps) {
397        fPrintedCaps = true;
398        this->getCaps().print();
399        this->glCaps().print();
400    }
401
402    // We detect cases when blending is effectively off
403    fHWBlendDisabled = false;
404    GL_CALL(Enable(GR_GL_BLEND));
405
406    // we don't use the zb at all
407    GL_CALL(Disable(GR_GL_DEPTH_TEST));
408    GL_CALL(DepthMask(GR_GL_FALSE));
409
410    GL_CALL(Disable(GR_GL_CULL_FACE));
411    GL_CALL(FrontFace(GR_GL_CCW));
412    fHWDrawState.setDrawFace(GrDrawState::kBoth_DrawFace);
413
414    GL_CALL(Disable(GR_GL_DITHER));
415    if (kDesktop_GrGLBinding == this->glBinding()) {
416        GL_CALL(Disable(GR_GL_LINE_SMOOTH));
417        GL_CALL(Disable(GR_GL_POINT_SMOOTH));
418        GL_CALL(Disable(GR_GL_MULTISAMPLE));
419        fHWAAState.fMSAAEnabled = false;
420        fHWAAState.fSmoothLineEnabled = false;
421    }
422
423    GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
424    fHWDrawState.resetStateFlags();
425
426    // we only ever use lines in hairline mode
427    GL_CALL(LineWidth(1));
428
429    // invalid
430    fActiveTextureUnitIdx = -1;
431
432    // illegal values
433    fHWDrawState.setBlendFunc((GrBlendCoeff)0xFF, (GrBlendCoeff)0xFF);
434
435    fHWDrawState.setBlendConstant(0x00000000);
436    GL_CALL(BlendColor(0,0,0,0));
437
438    fHWDrawState.setColor(GrColor_ILLEGAL);
439
440    fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix());
441
442    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
443        fHWDrawState.setTexture(s, NULL);
444        fHWDrawState.sampler(s)->setRadial2Params(-GR_ScalarMax,
445                                                  -GR_ScalarMax,
446                                                  true);
447        *fHWDrawState.sampler(s)->matrix() = GrMatrix::InvalidMatrix();
448        fHWDrawState.sampler(s)->setConvolutionParams(0, NULL);
449    }
450
451    fHWBounds.fScissorRect.invalidate();
452    fHWBounds.fScissorEnabled = false;
453    GL_CALL(Disable(GR_GL_SCISSOR_TEST));
454    fHWBounds.fViewportRect.invalidate();
455
456    fHWDrawState.stencil()->invalidate();
457    fHWStencilClip = false;
458    fClipInStencil = false;
459
460    fHWGeometryState.fIndexBuffer = NULL;
461    fHWGeometryState.fVertexBuffer = NULL;
462
463    fHWGeometryState.fArrayPtrsDirty = true;
464
465    GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
466    fHWDrawState.setRenderTarget(NULL);
467
468    // we assume these values
469    if (this->glCaps().unpackRowLengthSupport()) {
470        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
471    }
472    if (this->glCaps().packRowLengthSupport()) {
473        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
474    }
475    if (this->glCaps().unpackFlipYSupport()) {
476        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
477    }
478    if (this->glCaps().packFlipYSupport()) {
479        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
480    }
481}
482
483GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) {
484    GrGLTexture::Desc glTexDesc;
485    if (!configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) {
486        return NULL;
487    }
488
489    glTexDesc.fWidth = desc.fWidth;
490    glTexDesc.fHeight = desc.fHeight;
491    glTexDesc.fConfig = desc.fConfig;
492    glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
493    glTexDesc.fOwnsID = false;
494    glTexDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
495
496    GrGLTexture* texture = NULL;
497    if (desc.fFlags & kRenderTarget_GrPlatformTextureFlag) {
498        GrGLRenderTarget::Desc glRTDesc;
499        glRTDesc.fRTFBOID = 0;
500        glRTDesc.fTexFBOID = 0;
501        glRTDesc.fMSColorRenderbufferID = 0;
502        glRTDesc.fOwnIDs = true;
503        glRTDesc.fConfig = desc.fConfig;
504        glRTDesc.fSampleCnt = desc.fSampleCnt;
505        if (!this->createRenderTargetObjects(glTexDesc.fWidth,
506                                             glTexDesc.fHeight,
507                                             glTexDesc.fTextureID,
508                                             &glRTDesc)) {
509            return NULL;
510        }
511        texture = new GrGLTexture(this, glTexDesc, glRTDesc);
512    } else {
513        texture = new GrGLTexture(this, glTexDesc);
514    }
515    if (NULL == texture) {
516        return NULL;
517    }
518
519    this->setSpareTextureUnit();
520    return texture;
521}
522
523GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
524    GrGLRenderTarget::Desc glDesc;
525    glDesc.fConfig = desc.fConfig;
526    glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle);
527    glDesc.fMSColorRenderbufferID = 0;
528    glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
529    glDesc.fSampleCnt = desc.fSampleCnt;
530    glDesc.fOwnIDs = false;
531    GrGLIRect viewport;
532    viewport.fLeft   = 0;
533    viewport.fBottom = 0;
534    viewport.fWidth  = desc.fWidth;
535    viewport.fHeight = desc.fHeight;
536
537    GrRenderTarget* tgt = new GrGLRenderTarget(this, glDesc, viewport);
538    if (desc.fStencilBits) {
539        GrGLStencilBuffer::Format format;
540        format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
541        format.fPacked = false;
542        format.fStencilBits = desc.fStencilBits;
543        format.fTotalBits = desc.fStencilBits;
544        GrGLStencilBuffer* sb = new GrGLStencilBuffer(this,
545                                                      0,
546                                                      desc.fWidth,
547                                                      desc.fHeight,
548                                                      desc.fSampleCnt,
549                                                      format);
550        tgt->setStencilBuffer(sb);
551        sb->unref();
552    }
553    return tgt;
554}
555
556////////////////////////////////////////////////////////////////////////////////
557
558void GrGpuGL::onWriteTexturePixels(GrTexture* texture,
559                                   int left, int top, int width, int height,
560                                   GrPixelConfig config, const void* buffer,
561                                   size_t rowBytes) {
562    if (NULL == buffer) {
563        return;
564    }
565    GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
566
567    this->setSpareTextureUnit();
568    GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
569    GrGLTexture::Desc desc;
570    desc.fConfig = glTex->config();
571    desc.fWidth = glTex->width();
572    desc.fHeight = glTex->height();
573    desc.fOrientation = glTex->orientation();
574    desc.fTextureID = glTex->textureID();
575
576    this->uploadTexData(desc, false,
577                        left, top, width, height,
578                        config, buffer, rowBytes);
579}
580
581namespace {
582bool adjust_pixel_ops_params(int surfaceWidth,
583                             int surfaceHeight,
584                             size_t bpp,
585                             int* left, int* top, int* width, int* height,
586                             const void** data,
587                             size_t* rowBytes) {
588    if (!*rowBytes) {
589        *rowBytes = *width * bpp;
590    }
591
592    GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height);
593    GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight);
594
595    if (!subRect.intersect(bounds)) {
596        return false;
597    }
598    *data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) +
599          (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
600
601    *left = subRect.fLeft;
602    *top = subRect.fTop;
603    *width = subRect.width();
604    *height = subRect.height();
605    return true;
606}
607}
608
609bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
610                            bool isNewTexture,
611                            int left, int top, int width, int height,
612                            GrPixelConfig dataConfig,
613                            const void* data,
614                            size_t rowBytes) {
615    GrAssert(NULL != data || isNewTexture);
616
617    size_t bpp = GrBytesPerPixel(dataConfig);
618    if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
619                                 &width, &height, &data, &rowBytes)) {
620        return false;
621    }
622    size_t trimRowBytes = width * bpp;
623
624    // in case we need a temporary, trimmed copy of the src pixels
625    SkAutoSMalloc<128 * 128> tempStorage;
626
627    bool useTexStorage = isNewTexture &&
628                         this->glCaps().texStorageSupport();
629    if (useTexStorage) {
630        if (kDesktop_GrGLBinding == this->glBinding()) {
631            // 565 is not a sized internal format on desktop GL. So on desktop
632            // with 565 we always use an unsized internal format to let the
633            // system pick the best sized format to convert the 565 data to.
634            // Since glTexStorage only allows sized internal formats we will
635            // instead fallback to glTexImage2D.
636            useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig;
637        } else {
638            // ES doesn't allow paletted textures to be used with tex storage
639            useTexStorage = desc.fConfig != kIndex_8_GrPixelConfig;
640        }
641    }
642
643    GrGLenum internalFormat;
644    GrGLenum externalFormat;
645    GrGLenum externalType;
646    // glTexStorage requires sized internal formats on both desktop and ES. ES
647    // glTexImage requires an unsized format.
648    if (!this->configToGLFormats(dataConfig, useTexStorage, &internalFormat,
649                                 &externalFormat, &externalType)) {
650        return false;
651    }
652
653    if (!isNewTexture && GR_GL_PALETTE8_RGBA8 == internalFormat) {
654        // paletted textures cannot be updated
655        return false;
656    }
657
658    /*
659     *  check whether to allocate a temporary buffer for flipping y or
660     *  because our srcData has extra bytes past each row. If so, we need
661     *  to trim those off here, since GL ES may not let us specify
662     *  GL_UNPACK_ROW_LENGTH.
663     */
664    bool restoreGLRowLength = false;
665    bool swFlipY = false;
666    bool glFlipY = false;
667    if (NULL != data) {
668        if (GrGLTexture::kBottomUp_Orientation == desc.fOrientation) {
669            if (this->glCaps().unpackFlipYSupport()) {
670                glFlipY = true;
671            } else {
672                swFlipY = true;
673            }
674        }
675        if (this->glCaps().unpackRowLengthSupport() && !swFlipY) {
676            // can't use this for flipping, only non-neg values allowed. :(
677            if (rowBytes != trimRowBytes) {
678                GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
679                GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
680                restoreGLRowLength = true;
681            }
682        } else {
683            if (trimRowBytes != rowBytes || swFlipY) {
684                // copy data into our new storage, skipping the trailing bytes
685                size_t trimSize = height * trimRowBytes;
686                const char* src = (const char*)data;
687                if (swFlipY) {
688                    src += (height - 1) * rowBytes;
689                }
690                char* dst = (char*)tempStorage.reset(trimSize);
691                for (int y = 0; y < height; y++) {
692                    memcpy(dst, src, trimRowBytes);
693                    if (swFlipY) {
694                        src -= rowBytes;
695                    } else {
696                        src += rowBytes;
697                    }
698                    dst += trimRowBytes;
699                }
700                // now point data to our copied version
701                data = tempStorage.get();
702            }
703        }
704        if (glFlipY) {
705            GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
706        }
707        GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
708    }
709    bool succeeded = true;
710    if (isNewTexture &&
711        0 == left && 0 == top &&
712        desc.fWidth == width && desc.fHeight == height) {
713        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
714        if (useTexStorage) {
715            // We never resize  or change formats of textures. We don't use
716            // mipmaps currently.
717            GL_ALLOC_CALL(this->glInterface(),
718                          TexStorage2D(GR_GL_TEXTURE_2D,
719                                       1, // levels
720                                       internalFormat,
721                                       desc.fWidth, desc.fHeight));
722        } else {
723            if (GR_GL_PALETTE8_RGBA8 == internalFormat) {
724                GrGLsizei imageSize = desc.fWidth * desc.fHeight +
725                                      kGrColorTableSize;
726                GL_ALLOC_CALL(this->glInterface(),
727                              CompressedTexImage2D(GR_GL_TEXTURE_2D,
728                                                   0, // level
729                                                   internalFormat,
730                                                   desc.fWidth, desc.fHeight,
731                                                   0, // border
732                                                   imageSize,
733                                                   data));
734            } else {
735                GL_ALLOC_CALL(this->glInterface(),
736                              TexImage2D(GR_GL_TEXTURE_2D,
737                                         0, // level
738                                         internalFormat,
739                                         desc.fWidth, desc.fHeight,
740                                         0, // border
741                                         externalFormat, externalType,
742                                         data));
743            }
744        }
745        GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface());
746        if (error != GR_GL_NO_ERROR) {
747            succeeded = false;
748        } else {
749            // if we have data and we used TexStorage to create the texture, we
750            // now upload with TexSubImage.
751            if (NULL != data && useTexStorage) {
752                GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
753                                      0, // level
754                                      left, top,
755                                      width, height,
756                                      externalFormat, externalType,
757                                      data));
758            }
759        }
760    } else {
761        if (swFlipY || glFlipY) {
762            top = desc.fHeight - (top + height);
763        }
764        GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
765                              0, // level
766                              left, top,
767                              width, height,
768                              externalFormat, externalType, data));
769    }
770
771    if (restoreGLRowLength) {
772        GrAssert(this->glCaps().unpackRowLengthSupport());
773        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
774    }
775    if (glFlipY) {
776        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
777    }
778    return succeeded;
779}
780
781bool GrGpuGL::createRenderTargetObjects(int width, int height,
782                                        GrGLuint texID,
783                                        GrGLRenderTarget::Desc* desc) {
784    desc->fMSColorRenderbufferID = 0;
785    desc->fRTFBOID = 0;
786    desc->fTexFBOID = 0;
787    desc->fOwnIDs = true;
788
789    GrGLenum status;
790    GrGLint err;
791
792    GrGLenum msColorFormat = 0; // suppress warning
793
794    GL_CALL(GenFramebuffers(1, &desc->fTexFBOID));
795    if (!desc->fTexFBOID) {
796        goto FAILED;
797    }
798
799
800    // If we are using multisampling we will create two FBOS. We render
801    // to one and then resolve to the texture bound to the other.
802    if (desc->fSampleCnt > 0) {
803        if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
804            goto FAILED;
805        }
806        GL_CALL(GenFramebuffers(1, &desc->fRTFBOID));
807        GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
808        if (!desc->fRTFBOID ||
809            !desc->fMSColorRenderbufferID ||
810            !this->configToGLFormats(desc->fConfig,
811                                     // GLES requires sized internal formats
812                                     kES2_GrGLBinding == this->glBinding(),
813                                     &msColorFormat, NULL, NULL)) {
814            goto FAILED;
815        }
816    } else {
817        desc->fRTFBOID = desc->fTexFBOID;
818    }
819
820    // below here we may bind the FBO
821    fHWDrawState.setRenderTarget(NULL);
822    if (desc->fRTFBOID != desc->fTexFBOID) {
823        GrAssert(desc->fSampleCnt > 1);
824        GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER,
825                               desc->fMSColorRenderbufferID));
826        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
827        GL_ALLOC_CALL(this->glInterface(),
828                      RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
829                                                     desc->fSampleCnt,
830                                                     msColorFormat,
831                                                     width, height));
832        err = CHECK_ALLOC_ERROR(this->glInterface());
833        if (err != GR_GL_NO_ERROR) {
834            goto FAILED;
835        }
836        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID));
837        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
838                                      GR_GL_COLOR_ATTACHMENT0,
839                                      GR_GL_RENDERBUFFER,
840                                      desc->fMSColorRenderbufferID));
841        if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
842            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
843            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
844                goto FAILED;
845            }
846            fGLContextInfo.caps().markConfigAsValidColorAttachment(
847                                                                desc->fConfig);
848        }
849    }
850    GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
851
852    GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
853                                 GR_GL_COLOR_ATTACHMENT0,
854                                 GR_GL_TEXTURE_2D,
855                                 texID, 0));
856    if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
857        GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
858        if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
859            goto FAILED;
860        }
861        fGLContextInfo.caps().markConfigAsValidColorAttachment(desc->fConfig);
862    }
863
864    return true;
865
866FAILED:
867    if (desc->fMSColorRenderbufferID) {
868        GL_CALL(DeleteRenderbuffers(1, &desc->fMSColorRenderbufferID));
869    }
870    if (desc->fRTFBOID != desc->fTexFBOID) {
871        GL_CALL(DeleteFramebuffers(1, &desc->fRTFBOID));
872    }
873    if (desc->fTexFBOID) {
874        GL_CALL(DeleteFramebuffers(1, &desc->fTexFBOID));
875    }
876    return false;
877}
878
879// good to set a break-point here to know when createTexture fails
880static GrTexture* return_null_texture() {
881//    GrAssert(!"null texture");
882    return NULL;
883}
884
885#if GR_DEBUG
886static size_t as_size_t(int x) {
887    return x;
888}
889#endif
890
891GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
892                                    const void* srcData,
893                                    size_t rowBytes) {
894
895#if GR_COLLECT_STATS
896    ++fStats.fTextureCreateCnt;
897#endif
898
899    GrGLTexture::Desc glTexDesc;
900    GrGLRenderTarget::Desc  glRTDesc;
901
902    // Attempt to catch un- or wrongly initialized sample counts;
903    GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
904
905    glTexDesc.fWidth  = desc.fWidth;
906    glTexDesc.fHeight = desc.fHeight;
907    glTexDesc.fConfig = desc.fConfig;
908    glTexDesc.fOwnsID = true;
909
910    glRTDesc.fMSColorRenderbufferID = 0;
911    glRTDesc.fRTFBOID = 0;
912    glRTDesc.fTexFBOID = 0;
913    glRTDesc.fOwnIDs = true;
914    glRTDesc.fConfig = glTexDesc.fConfig;
915
916    bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
917
918    const Caps& caps = this->getCaps();
919
920    // We keep GrRenderTargets in GL's normal orientation so that they
921    // can be drawn to by the outside world without the client having
922    // to render upside down.
923    glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
924                                            GrGLTexture::kTopDown_Orientation;
925
926    glRTDesc.fSampleCnt = desc.fSampleCnt;
927    if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() &&
928        desc.fSampleCnt) {
929        GrPrintf("MSAA RT requested but not supported on this platform.");
930    }
931
932    if (renderTarget) {
933        if (glTexDesc.fWidth > caps.fMaxRenderTargetSize ||
934            glTexDesc.fHeight > caps.fMaxRenderTargetSize) {
935            return return_null_texture();
936        }
937    }
938
939    GL_CALL(GenTextures(1, &glTexDesc.fTextureID));
940    if (renderTarget && this->glCaps().textureUsageSupport()) {
941        // provides a hint about how this texture will be used
942        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
943                              GR_GL_TEXTURE_USAGE,
944                              GR_GL_FRAMEBUFFER_ATTACHMENT));
945    }
946    if (!glTexDesc.fTextureID) {
947        return return_null_texture();
948    }
949
950    this->setSpareTextureUnit();
951    GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
952
953    // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
954    // drivers have a bug where an FBO won't be complete if it includes a
955    // texture that is not mipmap complete (considering the filter in use).
956    GrGLTexture::TexParams initialTexParams;
957    // we only set a subset here so invalidate first
958    initialTexParams.invalidate();
959    initialTexParams.fFilter = GR_GL_NEAREST;
960    initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
961    initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
962    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
963                          GR_GL_TEXTURE_MAG_FILTER,
964                          initialTexParams.fFilter));
965    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
966                          GR_GL_TEXTURE_MIN_FILTER,
967                          initialTexParams.fFilter));
968    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
969                          GR_GL_TEXTURE_WRAP_S,
970                          initialTexParams.fWrapS));
971    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
972                          GR_GL_TEXTURE_WRAP_T,
973                          initialTexParams.fWrapT));
974    if (!this->uploadTexData(glTexDesc, true, 0, 0,
975                             glTexDesc.fWidth, glTexDesc.fHeight,
976                             desc.fConfig, srcData, rowBytes)) {
977        GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
978        return return_null_texture();
979    }
980
981    GrGLTexture* tex;
982    if (renderTarget) {
983#if GR_COLLECT_STATS
984        ++fStats.fRenderTargetCreateCnt;
985#endif
986        if (!this->createRenderTargetObjects(glTexDesc.fWidth,
987                                             glTexDesc.fHeight,
988                                             glTexDesc.fTextureID,
989                                             &glRTDesc)) {
990            GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
991            return return_null_texture();
992        }
993        tex = new GrGLTexture(this, glTexDesc, glRTDesc);
994    } else {
995        tex = new GrGLTexture(this, glTexDesc);
996    }
997    tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
998#ifdef TRACE_TEXTURE_CREATION
999    GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n",
1000             glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
1001#endif
1002    return tex;
1003}
1004
1005namespace {
1006
1007const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
1008
1009void inline get_stencil_rb_sizes(const GrGLInterface* gl,
1010                                 GrGLuint rb,
1011                                 GrGLStencilBuffer::Format* format) {
1012    // we shouldn't ever know one size and not the other
1013    GrAssert((kUnknownBitCount == format->fStencilBits) ==
1014             (kUnknownBitCount == format->fTotalBits));
1015    if (kUnknownBitCount == format->fStencilBits) {
1016        GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1017                                         GR_GL_RENDERBUFFER_STENCIL_SIZE,
1018                                         (GrGLint*)&format->fStencilBits);
1019        if (format->fPacked) {
1020            GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1021                                             GR_GL_RENDERBUFFER_DEPTH_SIZE,
1022                                             (GrGLint*)&format->fTotalBits);
1023            format->fTotalBits += format->fStencilBits;
1024        } else {
1025            format->fTotalBits = format->fStencilBits;
1026        }
1027    }
1028}
1029}
1030
1031bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
1032                                                 int width, int height) {
1033
1034    // All internally created RTs are also textures. We don't create
1035    // SBs for a client's standalone RT (that is RT that isnt also a texture).
1036    GrAssert(rt->asTexture());
1037    GrAssert(width >= rt->width());
1038    GrAssert(height >= rt->height());
1039
1040    int samples = rt->numSamples();
1041    GrGLuint sbID;
1042    GL_CALL(GenRenderbuffers(1, &sbID));
1043    if (!sbID) {
1044        return false;
1045    }
1046
1047    GrGLStencilBuffer* sb = NULL;
1048
1049    int stencilFmtCnt = this->glCaps().stencilFormats().count();
1050    for (int i = 0; i < stencilFmtCnt; ++i) {
1051        GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
1052        // we start with the last stencil format that succeeded in hopes
1053        // that we won't go through this loop more than once after the
1054        // first (painful) stencil creation.
1055        int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1056        const GrGLCaps::StencilFormat& sFmt =
1057                this->glCaps().stencilFormats()[sIdx];
1058        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1059        // we do this "if" so that we don't call the multisample
1060        // version on a GL that doesn't have an MSAA extension.
1061        if (samples > 1) {
1062            GL_ALLOC_CALL(this->glInterface(),
1063                          RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
1064                                                         samples,
1065                                                         sFmt.fInternalFormat,
1066                                                         width, height));
1067        } else {
1068            GL_ALLOC_CALL(this->glInterface(),
1069                          RenderbufferStorage(GR_GL_RENDERBUFFER,
1070                                              sFmt.fInternalFormat,
1071                                              width, height));
1072        }
1073
1074        GrGLenum err = CHECK_ALLOC_ERROR(this->glInterface());
1075        if (err == GR_GL_NO_ERROR) {
1076            // After sized formats we attempt an unsized format and take whatever
1077            // sizes GL gives us. In that case we query for the size.
1078            GrGLStencilBuffer::Format format = sFmt;
1079            get_stencil_rb_sizes(this->glInterface(), sbID, &format);
1080            sb = new GrGLStencilBuffer(this, sbID, width, height,
1081                                       samples, format);
1082            if (this->attachStencilBufferToRenderTarget(sb, rt)) {
1083                fLastSuccessfulStencilFmtIdx = sIdx;
1084                rt->setStencilBuffer(sb);
1085                sb->unref();
1086                return true;
1087           }
1088           sb->abandon(); // otherwise we lose sbID
1089           sb->unref();
1090        }
1091    }
1092    GL_CALL(DeleteRenderbuffers(1, &sbID));
1093    return false;
1094}
1095
1096bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
1097                                                GrRenderTarget* rt) {
1098    GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
1099
1100    GrGLuint fbo = glrt->renderFBOID();
1101
1102    if (NULL == sb) {
1103        if (NULL != rt->getStencilBuffer()) {
1104            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1105                                          GR_GL_STENCIL_ATTACHMENT,
1106                                          GR_GL_RENDERBUFFER, 0));
1107            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1108                                          GR_GL_DEPTH_ATTACHMENT,
1109                                          GR_GL_RENDERBUFFER, 0));
1110#if GR_DEBUG
1111            GrGLenum status;
1112            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1113            GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status);
1114#endif
1115        }
1116        return true;
1117    } else {
1118        GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb;
1119        GrGLuint rb = glsb->renderbufferID();
1120
1121        fHWDrawState.setRenderTarget(NULL);
1122        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
1123        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1124                                      GR_GL_STENCIL_ATTACHMENT,
1125                                      GR_GL_RENDERBUFFER, rb));
1126        if (glsb->format().fPacked) {
1127            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1128                                          GR_GL_DEPTH_ATTACHMENT,
1129                                          GR_GL_RENDERBUFFER, rb));
1130        } else {
1131            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1132                                          GR_GL_DEPTH_ATTACHMENT,
1133                                          GR_GL_RENDERBUFFER, 0));
1134        }
1135
1136        GrGLenum status;
1137        if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(),
1138                                                           glsb->format())) {
1139            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1140            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1141                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1142                                              GR_GL_STENCIL_ATTACHMENT,
1143                                              GR_GL_RENDERBUFFER, 0));
1144                if (glsb->format().fPacked) {
1145                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1146                                                  GR_GL_DEPTH_ATTACHMENT,
1147                                                  GR_GL_RENDERBUFFER, 0));
1148                }
1149                return false;
1150            } else {
1151                fGLContextInfo.caps().markColorConfigAndStencilFormatAsVerified(
1152                    rt->config(),
1153                    glsb->format());
1154            }
1155        }
1156        return true;
1157    }
1158}
1159
1160////////////////////////////////////////////////////////////////////////////////
1161
1162GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
1163    GrGLuint id;
1164    GL_CALL(GenBuffers(1, &id));
1165    if (id) {
1166        GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
1167        fHWGeometryState.fArrayPtrsDirty = true;
1168        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1169        // make sure driver can allocate memory for this buffer
1170        GL_ALLOC_CALL(this->glInterface(),
1171                      BufferData(GR_GL_ARRAY_BUFFER,
1172                                 size,
1173                                 NULL,   // data ptr
1174                                 dynamic ? GR_GL_DYNAMIC_DRAW :
1175                                           GR_GL_STATIC_DRAW));
1176        if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1177            GL_CALL(DeleteBuffers(1, &id));
1178            // deleting bound buffer does implicit bind to 0
1179            fHWGeometryState.fVertexBuffer = NULL;
1180            return NULL;
1181        }
1182        GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
1183                                                              size, dynamic);
1184        fHWGeometryState.fVertexBuffer = vertexBuffer;
1185        return vertexBuffer;
1186    }
1187    return NULL;
1188}
1189
1190GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
1191    GrGLuint id;
1192    GL_CALL(GenBuffers(1, &id));
1193    if (id) {
1194        GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
1195        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1196        // make sure driver can allocate memory for this buffer
1197        GL_ALLOC_CALL(this->glInterface(),
1198                      BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
1199                                 size,
1200                                 NULL,  // data ptr
1201                                 dynamic ? GR_GL_DYNAMIC_DRAW :
1202                                           GR_GL_STATIC_DRAW));
1203        if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1204            GL_CALL(DeleteBuffers(1, &id));
1205            // deleting bound buffer does implicit bind to 0
1206            fHWGeometryState.fIndexBuffer = NULL;
1207            return NULL;
1208        }
1209        GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
1210                                                         size, dynamic);
1211        fHWGeometryState.fIndexBuffer = indexBuffer;
1212        return indexBuffer;
1213    }
1214    return NULL;
1215}
1216
1217void GrGpuGL::flushScissor(const GrIRect* rect) {
1218    const GrDrawState& drawState = this->getDrawState();
1219    const GrGLRenderTarget* rt =
1220        static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
1221
1222    GrAssert(NULL != rt);
1223    const GrGLIRect& vp = rt->getViewport();
1224
1225    GrGLIRect scissor;
1226    if (NULL != rect) {
1227        scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
1228                              rect->width(), rect->height());
1229        if (scissor.contains(vp)) {
1230            rect = NULL;
1231        }
1232    }
1233
1234    if (NULL != rect) {
1235        if (fHWBounds.fScissorRect != scissor) {
1236            scissor.pushToGLScissor(this->glInterface());
1237            fHWBounds.fScissorRect = scissor;
1238        }
1239        if (!fHWBounds.fScissorEnabled) {
1240            GL_CALL(Enable(GR_GL_SCISSOR_TEST));
1241            fHWBounds.fScissorEnabled = true;
1242        }
1243    } else {
1244        if (fHWBounds.fScissorEnabled) {
1245            GL_CALL(Disable(GR_GL_SCISSOR_TEST));
1246            fHWBounds.fScissorEnabled = false;
1247        }
1248    }
1249}
1250
1251void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
1252    const GrDrawState& drawState = this->getDrawState();
1253    const GrRenderTarget* rt = drawState.getRenderTarget();
1254    // parent class should never let us get here with no RT
1255    GrAssert(NULL != rt);
1256
1257    GrIRect clippedRect;
1258    if (NULL != rect) {
1259        // flushScissor expects rect to be clipped to the target.
1260        clippedRect = *rect;
1261        GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
1262        if (clippedRect.intersect(rtRect)) {
1263            rect = &clippedRect;
1264        } else {
1265            return;
1266        }
1267    }
1268    this->flushRenderTarget(rect);
1269    this->flushScissor(rect);
1270
1271    GrGLfloat r, g, b, a;
1272    static const GrGLfloat scale255 = 1.f / 255.f;
1273    a = GrColorUnpackA(color) * scale255;
1274    GrGLfloat scaleRGB = scale255;
1275    if (GrPixelConfigIsUnpremultiplied(rt->config())) {
1276        scaleRGB *= a;
1277    }
1278    r = GrColorUnpackR(color) * scaleRGB;
1279    g = GrColorUnpackG(color) * scaleRGB;
1280    b = GrColorUnpackB(color) * scaleRGB;
1281
1282    GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
1283    fHWDrawState.disableState(GrDrawState::kNoColorWrites_StateBit);
1284    GL_CALL(ClearColor(r, g, b, a));
1285    GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
1286}
1287
1288void GrGpuGL::clearStencil() {
1289    if (NULL == this->getDrawState().getRenderTarget()) {
1290        return;
1291    }
1292
1293    this->flushRenderTarget(&GrIRect::EmptyIRect());
1294
1295    if (fHWBounds.fScissorEnabled) {
1296        GL_CALL(Disable(GR_GL_SCISSOR_TEST));
1297        fHWBounds.fScissorEnabled = false;
1298    }
1299    GL_CALL(StencilMask(0xffffffff));
1300    GL_CALL(ClearStencil(0));
1301    GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1302    fHWDrawState.stencil()->invalidate();
1303}
1304
1305void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
1306    const GrDrawState& drawState = this->getDrawState();
1307    const GrRenderTarget* rt = drawState.getRenderTarget();
1308    GrAssert(NULL != rt);
1309
1310    // this should only be called internally when we know we have a
1311    // stencil buffer.
1312    GrAssert(NULL != rt->getStencilBuffer());
1313    GrGLint stencilBitCount =  rt->getStencilBuffer()->bits();
1314#if 0
1315    GrAssert(stencilBitCount > 0);
1316    GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
1317#else
1318    // we could just clear the clip bit but when we go through
1319    // ANGLE a partial stencil mask will cause clears to be
1320    // turned into draws. Our contract on GrDrawTarget says that
1321    // changing the clip between stencil passes may or may not
1322    // zero the client's clip bits. So we just clear the whole thing.
1323    static const GrGLint clipStencilMask  = ~0;
1324#endif
1325    GrGLint value;
1326    if (insideClip) {
1327        value = (1 << (stencilBitCount - 1));
1328    } else {
1329        value = 0;
1330    }
1331    this->flushRenderTarget(&GrIRect::EmptyIRect());
1332    this->flushScissor(&rect);
1333    GL_CALL(StencilMask(clipStencilMask));
1334    GL_CALL(ClearStencil(value));
1335    GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1336    fHWDrawState.stencil()->invalidate();
1337}
1338
1339void GrGpuGL::onForceRenderTargetFlush() {
1340    this->flushRenderTarget(&GrIRect::EmptyIRect());
1341}
1342
1343bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
1344                                        int left, int top,
1345                                        int width, int height,
1346                                        GrPixelConfig config,
1347                                        size_t rowBytes) const {
1348    // if GL can do the flip then we'll never pay for it.
1349    if (this->glCaps().packFlipYSupport()) {
1350        return false;
1351    }
1352
1353    // If we have to do memcpy to handle non-trim rowBytes then we
1354    // get the flip for free. Otherwise it costs.
1355    if (this->glCaps().packRowLengthSupport()) {
1356        return true;
1357    }
1358    // If we have to do memcpys to handle rowBytes then y-flip is free
1359    // Note the rowBytes might be tight to the passed in data, but if data
1360    // gets clipped in x to the target the rowBytes will no longer be tight.
1361    if (left >= 0 && (left + width) < renderTarget->width()) {
1362           return 0 == rowBytes ||
1363                  GrBytesPerPixel(config) * width == rowBytes;
1364    } else {
1365        return false;
1366    }
1367}
1368
1369bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1370                           int left, int top,
1371                           int width, int height,
1372                           GrPixelConfig config,
1373                           void* buffer,
1374                           size_t rowBytes,
1375                           bool invertY) {
1376    GrGLenum format;
1377    GrGLenum type;
1378    if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
1379        return false;
1380    }
1381    size_t bpp = GrBytesPerPixel(config);
1382    if (!adjust_pixel_ops_params(target->width(), target->height(), bpp,
1383                                 &left, &top, &width, &height,
1384                                 const_cast<const void**>(&buffer),
1385                                 &rowBytes)) {
1386        return false;
1387    }
1388
1389    // resolve the render target if necessary
1390    GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1391    GrDrawState::AutoRenderTargetRestore artr;
1392    switch (tgt->getResolveType()) {
1393        case GrGLRenderTarget::kCantResolve_ResolveType:
1394            return false;
1395        case GrGLRenderTarget::kAutoResolves_ResolveType:
1396            artr.set(this->drawState(), target);
1397            this->flushRenderTarget(&GrIRect::EmptyIRect());
1398            break;
1399        case GrGLRenderTarget::kCanResolve_ResolveType:
1400            this->onResolveRenderTarget(tgt);
1401            // we don't track the state of the READ FBO ID.
1402            GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1403                                    tgt->textureFBOID()));
1404            break;
1405        default:
1406            GrCrash("Unknown resolve type");
1407    }
1408
1409    const GrGLIRect& glvp = tgt->getViewport();
1410
1411    // the read rect is viewport-relative
1412    GrGLIRect readRect;
1413    readRect.setRelativeTo(glvp, left, top, width, height);
1414
1415    size_t tightRowBytes = bpp * width;
1416    if (0 == rowBytes) {
1417        rowBytes = tightRowBytes;
1418    }
1419    size_t readDstRowBytes = tightRowBytes;
1420    void* readDst = buffer;
1421
1422    // determine if GL can read using the passed rowBytes or if we need
1423    // a scratch buffer.
1424    SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1425    if (rowBytes != tightRowBytes) {
1426        if (this->glCaps().packRowLengthSupport()) {
1427            GrAssert(!(rowBytes % sizeof(GrColor)));
1428            GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowBytes / sizeof(GrColor)));
1429            readDstRowBytes = rowBytes;
1430        } else {
1431            scratch.reset(tightRowBytes * height);
1432            readDst = scratch.get();
1433        }
1434    }
1435    if (!invertY && this->glCaps().packFlipYSupport()) {
1436        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
1437    }
1438    GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
1439                       readRect.fWidth, readRect.fHeight,
1440                       format, type, readDst));
1441    if (readDstRowBytes != tightRowBytes) {
1442        GrAssert(this->glCaps().packRowLengthSupport());
1443        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
1444    }
1445    if (!invertY && this->glCaps().packFlipYSupport()) {
1446        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
1447        invertY = true;
1448    }
1449
1450    // now reverse the order of the rows, since GL's are bottom-to-top, but our
1451    // API presents top-to-bottom. We must preserve the padding contents. Note
1452    // that the above readPixels did not overwrite the padding.
1453    if (readDst == buffer) {
1454        GrAssert(rowBytes == readDstRowBytes);
1455        if (!invertY) {
1456            scratch.reset(tightRowBytes);
1457            void* tmpRow = scratch.get();
1458            // flip y in-place by rows
1459            const int halfY = height >> 1;
1460            char* top = reinterpret_cast<char*>(buffer);
1461            char* bottom = top + (height - 1) * rowBytes;
1462            for (int y = 0; y < halfY; y++) {
1463                memcpy(tmpRow, top, tightRowBytes);
1464                memcpy(top, bottom, tightRowBytes);
1465                memcpy(bottom, tmpRow, tightRowBytes);
1466                top += rowBytes;
1467                bottom -= rowBytes;
1468            }
1469        }
1470    } else {
1471        GrAssert(readDst != buffer);        GrAssert(rowBytes != tightRowBytes);
1472        // copy from readDst to buffer while flipping y
1473        const int halfY = height >> 1;
1474        const char* src = reinterpret_cast<const char*>(readDst);
1475        char* dst = reinterpret_cast<char*>(buffer);
1476        if (!invertY) {
1477            dst += (height-1) * rowBytes;
1478        }
1479        for (int y = 0; y < height; y++) {
1480            memcpy(dst, src, tightRowBytes);
1481            src += readDstRowBytes;
1482            if (invertY) {
1483                dst += rowBytes;
1484            } else {
1485                dst -= rowBytes;
1486            }
1487        }
1488    }
1489    return true;
1490}
1491
1492void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
1493
1494    GrGLRenderTarget* rt =
1495        static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget());
1496    GrAssert(NULL != rt);
1497
1498    if (fHWDrawState.getRenderTarget() != rt) {
1499        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
1500    #if GR_COLLECT_STATS
1501        ++fStats.fRenderTargetChngCnt;
1502    #endif
1503    #if GR_DEBUG
1504        GrGLenum status;
1505        GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1506        if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1507            GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
1508        }
1509    #endif
1510        fDirtyFlags.fRenderTargetChanged = true;
1511        fHWDrawState.setRenderTarget(rt);
1512        const GrGLIRect& vp = rt->getViewport();
1513        if (fHWBounds.fViewportRect != vp) {
1514            vp.pushToGLViewport(this->glInterface());
1515            fHWBounds.fViewportRect = vp;
1516        }
1517    }
1518    if (NULL == bound || !bound->isEmpty()) {
1519        rt->flagAsNeedingResolve(bound);
1520    }
1521}
1522
1523GrGLenum gPrimitiveType2GLMode[] = {
1524    GR_GL_TRIANGLES,
1525    GR_GL_TRIANGLE_STRIP,
1526    GR_GL_TRIANGLE_FAN,
1527    GR_GL_POINTS,
1528    GR_GL_LINES,
1529    GR_GL_LINE_STRIP
1530};
1531
1532#define SWAP_PER_DRAW 0
1533
1534#if SWAP_PER_DRAW
1535    #if GR_MAC_BUILD
1536        #include <AGL/agl.h>
1537    #elif GR_WIN32_BUILD
1538        void SwapBuf() {
1539            DWORD procID = GetCurrentProcessId();
1540            HWND hwnd = GetTopWindow(GetDesktopWindow());
1541            while(hwnd) {
1542                DWORD wndProcID = 0;
1543                GetWindowThreadProcessId(hwnd, &wndProcID);
1544                if(wndProcID == procID) {
1545                    SwapBuffers(GetDC(hwnd));
1546                }
1547                hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1548            }
1549         }
1550    #endif
1551#endif
1552
1553void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1554                               uint32_t startVertex,
1555                               uint32_t startIndex,
1556                               uint32_t vertexCount,
1557                               uint32_t indexCount) {
1558    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1559
1560    GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
1561
1562    GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1563    GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1564
1565    // our setupGeometry better have adjusted this to zero since
1566    // DrawElements always draws from the begining of the arrays for idx 0.
1567    GrAssert(0 == startVertex);
1568
1569    GL_CALL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1570                         GR_GL_UNSIGNED_SHORT, indices));
1571#if SWAP_PER_DRAW
1572    glFlush();
1573    #if GR_MAC_BUILD
1574        aglSwapBuffers(aglGetCurrentContext());
1575        int set_a_break_pt_here = 9;
1576        aglSwapBuffers(aglGetCurrentContext());
1577    #elif GR_WIN32_BUILD
1578        SwapBuf();
1579        int set_a_break_pt_here = 9;
1580        SwapBuf();
1581    #endif
1582#endif
1583}
1584
1585void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1586                                  uint32_t startVertex,
1587                                  uint32_t vertexCount) {
1588    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1589
1590    GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1591
1592    // our setupGeometry better have adjusted this to zero.
1593    // DrawElements doesn't take an offset so we always adjus the startVertex.
1594    GrAssert(0 == startVertex);
1595
1596    // pass 0 for parameter first. We have to adjust gl*Pointer() to
1597    // account for startVertex in the DrawElements case. So we always
1598    // rely on setupGeometry to have accounted for startVertex.
1599    GL_CALL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1600#if SWAP_PER_DRAW
1601    glFlush();
1602    #if GR_MAC_BUILD
1603        aglSwapBuffers(aglGetCurrentContext());
1604        int set_a_break_pt_here = 9;
1605        aglSwapBuffers(aglGetCurrentContext());
1606    #elif GR_WIN32_BUILD
1607        SwapBuf();
1608        int set_a_break_pt_here = 9;
1609        SwapBuf();
1610    #endif
1611#endif
1612}
1613
1614void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
1615
1616    GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
1617
1618    if (rt->needsResolve()) {
1619        GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType());
1620        GrAssert(rt->textureFBOID() != rt->renderFBOID());
1621        GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1622                                rt->renderFBOID()));
1623        GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
1624                                rt->textureFBOID()));
1625    #if GR_COLLECT_STATS
1626        ++fStats.fRenderTargetChngCnt;
1627    #endif
1628        // make sure we go through flushRenderTarget() since we've modified
1629        // the bound DRAW FBO ID.
1630        fHWDrawState.setRenderTarget(NULL);
1631        const GrGLIRect& vp = rt->getViewport();
1632        const GrIRect dirtyRect = rt->getResolveRect();
1633        GrGLIRect r;
1634        r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1635                        dirtyRect.width(), dirtyRect.height());
1636
1637        if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
1638            // Apple's extension uses the scissor as the blit bounds.
1639            GL_CALL(Enable(GR_GL_SCISSOR_TEST));
1640            GL_CALL(Scissor(r.fLeft, r.fBottom,
1641                            r.fWidth, r.fHeight));
1642            GL_CALL(ResolveMultisampleFramebuffer());
1643            fHWBounds.fScissorRect.invalidate();
1644            fHWBounds.fScissorEnabled = true;
1645        } else {
1646            if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
1647                // this respects the scissor during the blit, so disable it.
1648                GrAssert(GrGLCaps::kDesktopEXT_MSFBOType ==
1649                         this->glCaps().msFBOType());
1650                this->flushScissor(NULL);
1651            }
1652            int right = r.fLeft + r.fWidth;
1653            int top = r.fBottom + r.fHeight;
1654            GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1655                                    r.fLeft, r.fBottom, right, top,
1656                                    GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
1657        }
1658        rt->flagAsResolved();
1659    }
1660}
1661
1662static const GrGLenum grToGLStencilFunc[] = {
1663    GR_GL_ALWAYS,           // kAlways_StencilFunc
1664    GR_GL_NEVER,            // kNever_StencilFunc
1665    GR_GL_GREATER,          // kGreater_StencilFunc
1666    GR_GL_GEQUAL,           // kGEqual_StencilFunc
1667    GR_GL_LESS,             // kLess_StencilFunc
1668    GR_GL_LEQUAL,           // kLEqual_StencilFunc,
1669    GR_GL_EQUAL,            // kEqual_StencilFunc,
1670    GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
1671};
1672GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1673GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1674GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1675GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1676GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1677GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1678GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1679GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1680GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1681
1682static const GrGLenum grToGLStencilOp[] = {
1683    GR_GL_KEEP,        // kKeep_StencilOp
1684    GR_GL_REPLACE,     // kReplace_StencilOp
1685    GR_GL_INCR_WRAP,   // kIncWrap_StencilOp
1686    GR_GL_INCR,        // kIncClamp_StencilOp
1687    GR_GL_DECR_WRAP,   // kDecWrap_StencilOp
1688    GR_GL_DECR,        // kDecClamp_StencilOp
1689    GR_GL_ZERO,        // kZero_StencilOp
1690    GR_GL_INVERT,      // kInvert_StencilOp
1691};
1692GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1693GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1694GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1695GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1696GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1697GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1698GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1699GR_STATIC_ASSERT(6 == kZero_StencilOp);
1700GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1701
1702void GrGpuGL::flushStencil() {
1703    const GrDrawState& drawState = this->getDrawState();
1704
1705    const GrStencilSettings* settings = &drawState.getStencil();
1706
1707    // use stencil for clipping if clipping is enabled and the clip
1708    // has been written into the stencil.
1709    bool stencilClip = fClipInStencil && drawState.isClipState();
1710    bool drawClipToStencil =
1711        drawState.isStateFlagEnabled(kModifyStencilClip_StateBit);
1712    bool stencilChange = (fHWDrawState.getStencil() != *settings) ||
1713                         (fHWStencilClip != stencilClip) ||
1714                         (fHWDrawState.isStateFlagEnabled(kModifyStencilClip_StateBit) !=
1715                          drawClipToStencil);
1716
1717    if (stencilChange) {
1718
1719        // we can't simultaneously perform stencil-clipping and
1720        // modify the stencil clip
1721        GrAssert(!stencilClip || !drawClipToStencil);
1722
1723        if (settings->isDisabled()) {
1724            if (stencilClip) {
1725                settings = GetClipStencilSettings();
1726            }
1727        }
1728
1729        if (settings->isDisabled()) {
1730            GL_CALL(Disable(GR_GL_STENCIL_TEST));
1731        } else {
1732            GL_CALL(Enable(GR_GL_STENCIL_TEST));
1733    #if GR_DEBUG
1734            if (!this->getCaps().fStencilWrapOpsSupport) {
1735                GrAssert(settings->frontPassOp() != kIncWrap_StencilOp);
1736                GrAssert(settings->frontPassOp() != kDecWrap_StencilOp);
1737                GrAssert(settings->frontFailOp() != kIncWrap_StencilOp);
1738                GrAssert(settings->backFailOp() != kDecWrap_StencilOp);
1739                GrAssert(settings->backPassOp() != kIncWrap_StencilOp);
1740                GrAssert(settings->backPassOp() != kDecWrap_StencilOp);
1741                GrAssert(settings->backFailOp() != kIncWrap_StencilOp);
1742                GrAssert(settings->frontFailOp() != kDecWrap_StencilOp);
1743            }
1744    #endif
1745            int stencilBits = 0;
1746            GrStencilBuffer* stencilBuffer =
1747                drawState.getRenderTarget()->getStencilBuffer();
1748            if (NULL != stencilBuffer) {
1749                stencilBits = stencilBuffer->bits();
1750            }
1751            // TODO: dynamically attach a stencil buffer
1752            GrAssert(stencilBits || settings->isDisabled());
1753
1754            GrGLuint clipStencilMask = 0;
1755            GrGLuint userStencilMask = ~0;
1756            if (stencilBits > 0) {
1757                clipStencilMask =  1 << (stencilBits - 1);
1758                userStencilMask = clipStencilMask - 1;
1759            }
1760
1761            unsigned int frontRef  = settings->frontFuncRef();
1762            unsigned int frontMask = settings->frontFuncMask();
1763            unsigned int frontWriteMask = settings->frontWriteMask();
1764            GrGLenum frontFunc;
1765
1766            if (drawClipToStencil) {
1767                GrAssert(settings->frontFunc() < kBasicStencilFuncCount);
1768                frontFunc = grToGLStencilFunc[settings->frontFunc()];
1769            } else {
1770                frontFunc = grToGLStencilFunc[ConvertStencilFunc(
1771                        stencilClip, settings->frontFunc())];
1772
1773                ConvertStencilFuncAndMask(settings->frontFunc(),
1774                                          stencilClip,
1775                                          clipStencilMask,
1776                                          userStencilMask,
1777                                          &frontRef,
1778                                          &frontMask);
1779                frontWriteMask &= userStencilMask;
1780            }
1781            GrAssert((size_t)
1782                settings->frontFailOp() < GR_ARRAY_COUNT(grToGLStencilOp));
1783            GrAssert((size_t)
1784                settings->frontPassOp() < GR_ARRAY_COUNT(grToGLStencilOp));
1785            GrAssert((size_t)
1786                settings->backFailOp() < GR_ARRAY_COUNT(grToGLStencilOp));
1787            GrAssert((size_t)
1788                settings->backPassOp() < GR_ARRAY_COUNT(grToGLStencilOp));
1789            if (this->getCaps().fTwoSidedStencilSupport) {
1790                GrGLenum backFunc;
1791
1792                unsigned int backRef  = settings->backFuncRef();
1793                unsigned int backMask = settings->backFuncMask();
1794                unsigned int backWriteMask = settings->backWriteMask();
1795
1796
1797                if (drawClipToStencil) {
1798                    GrAssert(settings->backFunc() < kBasicStencilFuncCount);
1799                    backFunc = grToGLStencilFunc[settings->backFunc()];
1800                } else {
1801                    backFunc = grToGLStencilFunc[ConvertStencilFunc(
1802                        stencilClip, settings->backFunc())];
1803                    ConvertStencilFuncAndMask(settings->backFunc(),
1804                                              stencilClip,
1805                                              clipStencilMask,
1806                                              userStencilMask,
1807                                              &backRef,
1808                                              &backMask);
1809                    backWriteMask &= userStencilMask;
1810                }
1811
1812                GL_CALL(StencilFuncSeparate(GR_GL_FRONT, frontFunc,
1813                                            frontRef, frontMask));
1814                GL_CALL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1815                GL_CALL(StencilFuncSeparate(GR_GL_BACK, backFunc,
1816                                            backRef, backMask));
1817                GL_CALL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1818                GL_CALL(StencilOpSeparate(GR_GL_FRONT,
1819                                    grToGLStencilOp[settings->frontFailOp()],
1820                                    grToGLStencilOp[settings->frontPassOp()],
1821                                    grToGLStencilOp[settings->frontPassOp()]));
1822
1823                GL_CALL(StencilOpSeparate(GR_GL_BACK,
1824                                    grToGLStencilOp[settings->backFailOp()],
1825                                    grToGLStencilOp[settings->backPassOp()],
1826                                    grToGLStencilOp[settings->backPassOp()]));
1827            } else {
1828                GL_CALL(StencilFunc(frontFunc, frontRef, frontMask));
1829                GL_CALL(StencilMask(frontWriteMask));
1830                GL_CALL(StencilOp(grToGLStencilOp[settings->frontFailOp()],
1831                                grToGLStencilOp[settings->frontPassOp()],
1832                                grToGLStencilOp[settings->frontPassOp()]));
1833            }
1834        }
1835        *fHWDrawState.stencil() = *settings;
1836        fHWStencilClip = stencilClip;
1837    }
1838}
1839
1840void GrGpuGL::flushAAState(GrPrimitiveType type) {
1841    const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
1842    if (kDesktop_GrGLBinding == this->glBinding()) {
1843        // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1844        // smooth lines.
1845
1846        // we prefer smooth lines over multisampled lines
1847        // msaa should be disabled if drawing smooth lines.
1848        if (GrIsPrimTypeLines(type)) {
1849            bool smooth = this->willUseHWAALines();
1850            if (!fHWAAState.fSmoothLineEnabled && smooth) {
1851                GL_CALL(Enable(GR_GL_LINE_SMOOTH));
1852                fHWAAState.fSmoothLineEnabled = true;
1853            } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
1854                GL_CALL(Disable(GR_GL_LINE_SMOOTH));
1855                fHWAAState.fSmoothLineEnabled = false;
1856            }
1857            if (rt->isMultisampled() &&
1858                fHWAAState.fMSAAEnabled) {
1859                GL_CALL(Disable(GR_GL_MULTISAMPLE));
1860                fHWAAState.fMSAAEnabled = false;
1861            }
1862        } else if (rt->isMultisampled() &&
1863                   this->getDrawState().isHWAntialiasState() !=
1864                   fHWAAState.fMSAAEnabled) {
1865            if (fHWAAState.fMSAAEnabled) {
1866                GL_CALL(Disable(GR_GL_MULTISAMPLE));
1867                fHWAAState.fMSAAEnabled = false;
1868            } else {
1869                GL_CALL(Enable(GR_GL_MULTISAMPLE));
1870                fHWAAState.fMSAAEnabled = true;
1871            }
1872        }
1873    }
1874}
1875
1876void GrGpuGL::flushBlend(GrPrimitiveType type,
1877                         GrBlendCoeff srcCoeff,
1878                         GrBlendCoeff dstCoeff) {
1879    if (GrIsPrimTypeLines(type) && this->willUseHWAALines()) {
1880        if (fHWBlendDisabled) {
1881            GL_CALL(Enable(GR_GL_BLEND));
1882            fHWBlendDisabled = false;
1883        }
1884        if (kSA_BlendCoeff != fHWDrawState.getSrcBlendCoeff() ||
1885            kISA_BlendCoeff != fHWDrawState.getDstBlendCoeff()) {
1886            GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1887                              gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1888            fHWDrawState.setBlendFunc(kSA_BlendCoeff, kISA_BlendCoeff);
1889        }
1890    } else {
1891        // any optimization to disable blending should
1892        // have already been applied and tweaked the coeffs
1893        // to (1, 0).
1894        bool blendOff = kOne_BlendCoeff == srcCoeff &&
1895                        kZero_BlendCoeff == dstCoeff;
1896        if (fHWBlendDisabled != blendOff) {
1897            if (blendOff) {
1898                GL_CALL(Disable(GR_GL_BLEND));
1899            } else {
1900                GL_CALL(Enable(GR_GL_BLEND));
1901            }
1902            fHWBlendDisabled = blendOff;
1903        }
1904        if (!blendOff) {
1905            if (fHWDrawState.getSrcBlendCoeff() != srcCoeff ||
1906                fHWDrawState.getDstBlendCoeff() != dstCoeff) {
1907                GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1908                                  gXfermodeCoeff2Blend[dstCoeff]));
1909                fHWDrawState.setBlendFunc(srcCoeff, dstCoeff);
1910            }
1911            GrColor blendConst = fCurrDrawState.getBlendConstant();
1912            if ((BlendCoeffReferencesConstant(srcCoeff) ||
1913                 BlendCoeffReferencesConstant(dstCoeff)) &&
1914                fHWDrawState.getBlendConstant() != blendConst) {
1915
1916                float c[] = {
1917                    GrColorUnpackR(blendConst) / 255.f,
1918                    GrColorUnpackG(blendConst) / 255.f,
1919                    GrColorUnpackB(blendConst) / 255.f,
1920                    GrColorUnpackA(blendConst) / 255.f
1921                };
1922                GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
1923                fHWDrawState.setBlendConstant(blendConst);
1924            }
1925        }
1926    }
1927}
1928
1929namespace {
1930
1931unsigned gr_to_gl_filter(GrSamplerState::Filter filter) {
1932    switch (filter) {
1933        case GrSamplerState::kBilinear_Filter:
1934        case GrSamplerState::k4x4Downsample_Filter:
1935            return GR_GL_LINEAR;
1936        case GrSamplerState::kNearest_Filter:
1937        case GrSamplerState::kConvolution_Filter:
1938        case GrSamplerState::kErode_Filter:
1939        case GrSamplerState::kDilate_Filter:
1940            return GR_GL_NEAREST;
1941        default:
1942            GrAssert(!"Unknown filter type");
1943            return GR_GL_LINEAR;
1944    }
1945}
1946
1947const GrGLenum* get_swizzle(GrPixelConfig config,
1948                            const GrSamplerState& sampler) {
1949    if (GrPixelConfigIsAlphaOnly(config)) {
1950        static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
1951                                                GR_GL_ALPHA, GR_GL_ALPHA };
1952        return gAlphaSmear;
1953    } else if (sampler.swapsRAndB()) {
1954        static const GrGLenum gRedBlueSwap[] = { GR_GL_BLUE, GR_GL_GREEN,
1955                                                 GR_GL_RED,  GR_GL_ALPHA };
1956        return gRedBlueSwap;
1957    } else {
1958        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN,
1959                                              GR_GL_BLUE,  GR_GL_ALPHA };
1960        return gStraight;
1961    }
1962}
1963
1964void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) {
1965    // should add texparameteri to interface to make 1 instead of 4 calls here
1966    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
1967                                 GR_GL_TEXTURE_SWIZZLE_R,
1968                                 swizzle[0]));
1969    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
1970                                 GR_GL_TEXTURE_SWIZZLE_G,
1971                                 swizzle[1]));
1972    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
1973                                 GR_GL_TEXTURE_SWIZZLE_B,
1974                                 swizzle[2]));
1975    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
1976                                 GR_GL_TEXTURE_SWIZZLE_A,
1977                                 swizzle[3]));
1978}
1979}
1980
1981bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
1982
1983    GrDrawState* drawState = this->drawState();
1984    // GrGpu::setupClipAndFlushState should have already checked this
1985    // and bailed if not true.
1986    GrAssert(NULL != drawState->getRenderTarget());
1987
1988    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1989        // bind texture and set sampler state
1990        if (this->isStageEnabled(s)) {
1991            GrGLTexture* nextTexture =
1992                static_cast<GrGLTexture*>(drawState->getTexture(s));
1993
1994            // true for now, but maybe not with GrEffect.
1995            GrAssert(NULL != nextTexture);
1996            // if we created a rt/tex and rendered to it without using a
1997            // texture and now we're texuring from the rt it will still be
1998            // the last bound texture, but it needs resolving. So keep this
1999            // out of the "last != next" check.
2000            GrGLRenderTarget* texRT =
2001                static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
2002            if (NULL != texRT) {
2003                this->onResolveRenderTarget(texRT);
2004            }
2005
2006            if (fHWDrawState.getTexture(s) != nextTexture) {
2007                setTextureUnit(s);
2008                GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
2009            #if GR_COLLECT_STATS
2010                ++fStats.fTextureChngCnt;
2011            #endif
2012                //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
2013                fHWDrawState.setTexture(s, nextTexture);
2014                // The texture matrix has to compensate for texture width/height
2015                // and NPOT-embedded-in-POT
2016                fDirtyFlags.fTextureChangedMask |= (1 << s);
2017            }
2018
2019            const GrSamplerState& sampler = drawState->getSampler(s);
2020            ResetTimestamp timestamp;
2021            const GrGLTexture::TexParams& oldTexParams =
2022                                    nextTexture->getCachedTexParams(&timestamp);
2023            bool setAll = timestamp < this->getResetTimestamp();
2024            GrGLTexture::TexParams newTexParams;
2025
2026            newTexParams.fFilter = gr_to_gl_filter(sampler.getFilter());
2027
2028            const GrGLenum* wraps =  GrGLTexture::WrapMode2GLWrap();
2029            newTexParams.fWrapS = wraps[sampler.getWrapX()];
2030            newTexParams.fWrapT = wraps[sampler.getWrapY()];
2031            memcpy(newTexParams.fSwizzleRGBA,
2032                   get_swizzle(nextTexture->config(), sampler),
2033                   sizeof(newTexParams.fSwizzleRGBA));
2034            if (setAll || newTexParams.fFilter != oldTexParams.fFilter) {
2035                setTextureUnit(s);
2036                GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2037                                        GR_GL_TEXTURE_MAG_FILTER,
2038                                        newTexParams.fFilter));
2039                GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2040                                        GR_GL_TEXTURE_MIN_FILTER,
2041                                        newTexParams.fFilter));
2042            }
2043            if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
2044                setTextureUnit(s);
2045                GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2046                                        GR_GL_TEXTURE_WRAP_S,
2047                                        newTexParams.fWrapS));
2048            }
2049            if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
2050                setTextureUnit(s);
2051                GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2052                                        GR_GL_TEXTURE_WRAP_T,
2053                                        newTexParams.fWrapT));
2054            }
2055            if (this->glCaps().textureSwizzleSupport() &&
2056                (setAll ||
2057                 memcmp(newTexParams.fSwizzleRGBA,
2058                        oldTexParams.fSwizzleRGBA,
2059                        sizeof(newTexParams.fSwizzleRGBA)))) {
2060                setTextureUnit(s);
2061                set_tex_swizzle(newTexParams.fSwizzleRGBA,
2062                                this->glInterface());
2063            }
2064            nextTexture->setCachedTexParams(newTexParams,
2065                                            this->getResetTimestamp());
2066        }
2067    }
2068
2069    GrIRect* rect = NULL;
2070    GrIRect clipBounds;
2071    if (drawState->isClipState() &&
2072        fClip.hasConservativeBounds()) {
2073        fClip.getConservativeBounds().roundOut(&clipBounds);
2074        rect = &clipBounds;
2075    }
2076    this->flushRenderTarget(rect);
2077    this->flushAAState(type);
2078
2079    if (drawState->isDitherState() != fHWDrawState.isDitherState()) {
2080        if (drawState->isDitherState()) {
2081            GL_CALL(Enable(GR_GL_DITHER));
2082        } else {
2083            GL_CALL(Disable(GR_GL_DITHER));
2084        }
2085    }
2086
2087    if (drawState->isColorWriteDisabled() !=
2088        fHWDrawState.isColorWriteDisabled()) {
2089        GrGLenum mask;
2090        if (drawState->isColorWriteDisabled()) {
2091            mask = GR_GL_FALSE;
2092        } else {
2093            mask = GR_GL_TRUE;
2094        }
2095        GL_CALL(ColorMask(mask, mask, mask, mask));
2096    }
2097
2098    if (fHWDrawState.getDrawFace() != drawState->getDrawFace()) {
2099        switch (fCurrDrawState.getDrawFace()) {
2100            case GrDrawState::kCCW_DrawFace:
2101                GL_CALL(Enable(GR_GL_CULL_FACE));
2102                GL_CALL(CullFace(GR_GL_BACK));
2103                break;
2104            case GrDrawState::kCW_DrawFace:
2105                GL_CALL(Enable(GR_GL_CULL_FACE));
2106                GL_CALL(CullFace(GR_GL_FRONT));
2107                break;
2108            case GrDrawState::kBoth_DrawFace:
2109                GL_CALL(Disable(GR_GL_CULL_FACE));
2110                break;
2111            default:
2112                GrCrash("Unknown draw face.");
2113        }
2114        fHWDrawState.setDrawFace(drawState->getDrawFace());
2115    }
2116
2117#if GR_DEBUG
2118    // check for circular rendering
2119    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
2120        GrAssert(!this->isStageEnabled(s) ||
2121                 NULL == drawState->getRenderTarget() ||
2122                 NULL == drawState->getTexture(s) ||
2123                 drawState->getTexture(s)->asRenderTarget() !=
2124                    drawState->getRenderTarget());
2125    }
2126#endif
2127
2128    this->flushStencil();
2129
2130    // This copy must happen after flushStencil() is called. flushStencil()
2131    // relies on detecting when the kModifyStencilClip_StateBit state has
2132    // changed since the last draw.
2133    fHWDrawState.copyStateFlags(*drawState);
2134    return true;
2135}
2136
2137void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
2138    if (fHWGeometryState.fVertexBuffer != buffer) {
2139        fHWGeometryState.fArrayPtrsDirty = true;
2140        fHWGeometryState.fVertexBuffer = buffer;
2141    }
2142}
2143
2144void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
2145    if (fHWGeometryState.fVertexBuffer == buffer) {
2146        // deleting bound buffer does implied bind to 0
2147        fHWGeometryState.fVertexBuffer = NULL;
2148        fHWGeometryState.fArrayPtrsDirty = true;
2149    }
2150}
2151
2152void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
2153    fHWGeometryState.fIndexBuffer = buffer;
2154}
2155
2156void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
2157    if (fHWGeometryState.fIndexBuffer == buffer) {
2158        // deleting bound buffer does implied bind to 0
2159        fHWGeometryState.fIndexBuffer = NULL;
2160    }
2161}
2162
2163void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
2164    GrAssert(NULL != renderTarget);
2165    GrDrawState* drawState = this->drawState();
2166    if (drawState->getRenderTarget() == renderTarget) {
2167        drawState->setRenderTarget(NULL);
2168    }
2169    if (fHWDrawState.getRenderTarget() == renderTarget) {
2170        fHWDrawState.setRenderTarget(NULL);
2171    }
2172}
2173
2174void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
2175    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
2176        GrDrawState* drawState = this->drawState();
2177        if (drawState->getTexture(s) == texture) {
2178            fCurrDrawState.setTexture(s, NULL);
2179        }
2180        if (fHWDrawState.getTexture(s) == texture) {
2181            // deleting bound texture does implied bind to 0
2182            fHWDrawState.setTexture(s, NULL);
2183       }
2184    }
2185}
2186
2187bool GrGpuGL::configToGLFormats(GrPixelConfig config,
2188                                bool getSizedInternalFormat,
2189                                GrGLenum* internalFormat,
2190                                GrGLenum* externalFormat,
2191                                GrGLenum* externalType) {
2192    GrGLenum dontCare;
2193    if (NULL == internalFormat) {
2194        internalFormat = &dontCare;
2195    }
2196    if (NULL == externalFormat) {
2197        externalFormat = &dontCare;
2198    }
2199    if (NULL == externalType) {
2200        externalType = &dontCare;
2201    }
2202
2203    switch (config) {
2204        case kRGBA_8888_PM_GrPixelConfig:
2205        case kRGBA_8888_UPM_GrPixelConfig:
2206            *internalFormat = GR_GL_RGBA;
2207            *externalFormat = GR_GL_RGBA;
2208            if (getSizedInternalFormat) {
2209                *internalFormat = GR_GL_RGBA8;
2210            } else {
2211                *internalFormat = GR_GL_RGBA;
2212            }
2213            *externalType = GR_GL_UNSIGNED_BYTE;
2214            break;
2215        case kBGRA_8888_PM_GrPixelConfig:
2216        case kBGRA_8888_UPM_GrPixelConfig:
2217            if (!this->glCaps().bgraFormatSupport()) {
2218                return false;
2219            }
2220            if (this->glCaps().bgraIsInternalFormat()) {
2221                if (getSizedInternalFormat) {
2222                    *internalFormat = GR_GL_BGRA8;
2223                } else {
2224                    *internalFormat = GR_GL_BGRA;
2225                }
2226            } else {
2227                if (getSizedInternalFormat) {
2228                    *internalFormat = GR_GL_RGBA8;
2229                } else {
2230                    *internalFormat = GR_GL_RGBA;
2231                }
2232            }
2233            *externalFormat = GR_GL_BGRA;
2234            *externalType = GR_GL_UNSIGNED_BYTE;
2235            break;
2236        case kRGB_565_GrPixelConfig:
2237            *internalFormat = GR_GL_RGB;
2238            *externalFormat = GR_GL_RGB;
2239            if (getSizedInternalFormat) {
2240                if (this->glBinding() == kDesktop_GrGLBinding) {
2241                    return false;
2242                } else {
2243                    *internalFormat = GR_GL_RGB565;
2244                }
2245            } else {
2246                *internalFormat = GR_GL_RGB;
2247            }
2248            *externalType = GR_GL_UNSIGNED_SHORT_5_6_5;
2249            break;
2250        case kRGBA_4444_GrPixelConfig:
2251            *internalFormat = GR_GL_RGBA;
2252            *externalFormat = GR_GL_RGBA;
2253            if (getSizedInternalFormat) {
2254                *internalFormat = GR_GL_RGBA4;
2255            } else {
2256                *internalFormat = GR_GL_RGBA;
2257            }
2258            *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
2259            break;
2260        case kIndex_8_GrPixelConfig:
2261            if (this->getCaps().f8BitPaletteSupport) {
2262                *internalFormat = GR_GL_PALETTE8_RGBA8;
2263                // glCompressedTexImage doesn't take external params
2264                *externalFormat = GR_GL_PALETTE8_RGBA8;
2265                // no sized/unsized internal format distinction here
2266                *internalFormat = GR_GL_PALETTE8_RGBA8;
2267                // unused with CompressedTexImage
2268                *externalType = GR_GL_UNSIGNED_BYTE;
2269            } else {
2270                return false;
2271            }
2272            break;
2273        case kAlpha_8_GrPixelConfig:
2274            *internalFormat = GR_GL_ALPHA;
2275            *externalFormat = GR_GL_ALPHA;
2276            if (getSizedInternalFormat) {
2277                *internalFormat = GR_GL_ALPHA8;
2278            } else {
2279                *internalFormat = GR_GL_ALPHA;
2280            }
2281            *externalType = GR_GL_UNSIGNED_BYTE;
2282            break;
2283        default:
2284            return false;
2285    }
2286    return true;
2287}
2288
2289void GrGpuGL::setTextureUnit(int unit) {
2290    GrAssert(unit >= 0 && unit < GrDrawState::kNumStages);
2291    if (fActiveTextureUnitIdx != unit) {
2292        GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
2293        fActiveTextureUnitIdx = unit;
2294    }
2295}
2296
2297void GrGpuGL::setSpareTextureUnit() {
2298    if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2299        GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
2300        fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2301    }
2302}
2303
2304void GrGpuGL::resetDirtyFlags() {
2305    Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2306}
2307
2308void GrGpuGL::setBuffers(bool indexed,
2309                         int* extraVertexOffset,
2310                         int* extraIndexOffset) {
2311
2312    GrAssert(NULL != extraVertexOffset);
2313
2314    const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2315
2316    GrGLVertexBuffer* vbuf;
2317    switch (this->getGeomSrc().fVertexSrc) {
2318    case kBuffer_GeometrySrcType:
2319        *extraVertexOffset = 0;
2320        vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
2321        break;
2322    case kArray_GeometrySrcType:
2323    case kReserved_GeometrySrcType:
2324        this->finalizeReservedVertices();
2325        *extraVertexOffset = geoPoolState.fPoolStartVertex;
2326        vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
2327        break;
2328    default:
2329        vbuf = NULL; // suppress warning
2330        GrCrash("Unknown geometry src type!");
2331    }
2332
2333    GrAssert(NULL != vbuf);
2334    GrAssert(!vbuf->isLocked());
2335    if (fHWGeometryState.fVertexBuffer != vbuf) {
2336        GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
2337        fHWGeometryState.fArrayPtrsDirty = true;
2338        fHWGeometryState.fVertexBuffer = vbuf;
2339    }
2340
2341    if (indexed) {
2342        GrAssert(NULL != extraIndexOffset);
2343
2344        GrGLIndexBuffer* ibuf;
2345        switch (this->getGeomSrc().fIndexSrc) {
2346        case kBuffer_GeometrySrcType:
2347            *extraIndexOffset = 0;
2348            ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
2349            break;
2350        case kArray_GeometrySrcType:
2351        case kReserved_GeometrySrcType:
2352            this->finalizeReservedIndices();
2353            *extraIndexOffset = geoPoolState.fPoolStartIndex;
2354            ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
2355            break;
2356        default:
2357            ibuf = NULL; // suppress warning
2358            GrCrash("Unknown geometry src type!");
2359        }
2360
2361        GrAssert(NULL != ibuf);
2362        GrAssert(!ibuf->isLocked());
2363        if (fHWGeometryState.fIndexBuffer != ibuf) {
2364            GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
2365            fHWGeometryState.fIndexBuffer = ibuf;
2366        }
2367    }
2368}
2369
2370int GrGpuGL::getMaxEdges() const {
2371    // FIXME:  This is a pessimistic estimate based on how many other things
2372    // want to add uniforms.  This should be centralized somewhere.
2373    return GR_CT_MIN(this->glCaps().maxFragmentUniformVectors() - 8,
2374                     GrDrawState::kMaxEdges);
2375}
2376
2377