GrGpuGL.cpp revision 11b2d8b8d2e0230ccacf6d635f7ab0be8b53ca8d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2011 Google Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGpuGL.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGLStencilBuffer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrGLPath.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTemplates.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTypes.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTemplates.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLuint GR_MAX_GLUINT = ~0U;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLint  GR_INVAL_GLINT = ~0;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we use a spare texture unit to avoid
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mucking with the state of any of the stages.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int SPARE_TEX_UNIT = GrDrawState::kNumStages;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SKIP_CACHE_CHECK    true
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #define CLEAR_ERROR_BEFORE_ALLOC(iface)   GrGLClearErr(iface)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL_NOERRCHECK(iface, call)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #define CHECK_ALLOC_ERROR(iface)          GR_GL_GET_ERROR(iface)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    #define CLEAR_ERROR_BEFORE_ALLOC(iface)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    #define GL_ALLOC_CALL(iface, call)        GR_GL_CALL(iface, call)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    #define CHECK_ALLOC_ERROR(iface)          GR_GL_NO_ERROR
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const GrGLenum gXfermodeCoeff2Blend[] = {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ZERO,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_SRC_COLOR,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_SRC_COLOR,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_DST_COLOR,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_DST_COLOR,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_SRC_ALPHA,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_SRC_ALPHA,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_DST_ALPHA,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_DST_ALPHA,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CONSTANT_COLOR,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_CONSTANT_COLOR,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CONSTANT_ALPHA,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_CONSTANT_ALPHA,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // extended blend coeffs
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_GL_SRC1_COLOR,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_GL_ONE_MINUS_SRC1_COLOR,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_SRC1_ALPHA,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_ONE_MINUS_SRC1_ALPHA,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const bool gCoeffReferencesBlendConst[] = {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        true,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        true,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        true,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        true,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // extended blend coeffs
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        false,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gCoeffReferencesBlendConst[coeff];
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool gPrintStartupSpew = GR_DEBUG;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool fbo_test(const GrGLInterface* gl, int w, int h) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLuint testFBO;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, GenFramebuffers(1, &testFBO));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLuint testRTTex;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, GenTextures(1, &testRTTex));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, testRTTex));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // some implementations require texture to be mip-map complete before
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FBO with level 0 bound as color attachment will be framebuffer complete.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GR_GL_TEXTURE_MIN_FILTER,
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GR_GL_NEAREST));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        GR_GL_COLOR_ATTACHMENT0,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        GR_GL_TEXTURE_2D, testRTTex, 0));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLenum status;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_CALL(gl, DeleteTextures(1, &testRTTex));
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status == GR_GL_FRAMEBUFFER_COMPLETE;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GrAssert(ctxInfo.isInitialized());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fillInConfigRenderableTable();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    fPrintedCaps = false;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLClearErr(fGLContextInfo.interface());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gPrintStartupSpew) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GrGLubyte* ext;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GrGLubyte* vendor;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GrGLubyte* renderer;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GrGLubyte* version;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_CALL_RET(vendor, GetString(GR_GL_VENDOR));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_CALL_RET(renderer, GetString(GR_GL_RENDERER));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_CALL_RET(version, GetString(GR_GL_VERSION));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrPrintf("------------------------- create GrGpuGL %p --------------\n",
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrPrintf("------ VENDOR %s\n", vendor);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrPrintf("------ RENDERER %s\n", renderer);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrPrintf("------ VERSION %s\n",  version);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrPrintf("------ EXTENSIONS\n %s \n", ext);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->initCaps();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fProgramData = NULL;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fProgramCache = new ProgramCache(this->glContextInfo());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fLastSuccessfulStencilFmtIdx = 0;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (false) { // avoid bit rot, suppress warning
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fbo_test(this->glInterface(), 0, 0);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GrGpuGL::~GrGpuGL() {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fProgramData && 0 != fHWProgramID) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // detach the current program so there is no confusion on OpenGL's part
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // that we want it to be deleted
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GrAssert(fHWProgramID == fProgramData->fProgramID);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_CALL(UseProgram(0));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete fProgramCache;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fProgramCache = NULL;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fProgramData = NULL;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This must be called by before the GrDrawTarget destructor
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->releaseGeometry();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This subclass must do this before the base class destructor runs
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // since we will unref the GrGLInterface.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->releaseResources();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GrGpuGL::initCaps() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLint maxTextureUnits;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // check FS and fixed-function texture unit limits
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we only use textures in the fragment stage currently.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // checks are > to make sure we have a spare unit.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GrGLInterface* gl = this->glInterface();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrAssert(maxTextureUnits > GrDrawState::kNumStages);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrGLint numFormats;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkAutoSTMalloc<10, GrGLint> formats(numFormats);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < numFormats; ++i) {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (formats[i] == GR_GL_PALETTE8_RGBA8) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fCaps.f8BitPaletteSupport = true;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            break;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kDesktop_GrGLBinding == this->glBinding()) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // we could also look for GL_ATI_separate_stencil extension or
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // GL_EXT_stencil_two_side but they use different function signatures
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // than GL2.0+ (and than each other).
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // supported on GL 1.4 and higher or by extension
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) ||
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       this->hasExtension("GL_EXT_stencil_wrap");
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // ES 2 has two sided stencil and stencil wrap
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fTwoSidedStencilSupport = true;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fStencilWrapOpsSupport = true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kDesktop_GrGLBinding == this->glBinding()) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         // extension includes glMapBuffer.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fCaps.fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
249
250    if (kDesktop_GrGLBinding == this->glBinding()) {
251        if (this->glVersion() >= GR_GL_VER(2,0) ||
252            this->hasExtension("GL_ARB_texture_non_power_of_two")) {
253            fCaps.fNPOTTextureTileSupport = true;
254        } else {
255            fCaps.fNPOTTextureTileSupport = false;
256        }
257    } else {
258        // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
259        fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
260    }
261
262    fCaps.fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding());
263
264    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize);
265    GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize);
266    // Our render targets are always created with textures as the color
267    // attachment, hence this min:
268    fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize);
269
270    fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType();
271    fCaps.fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING &&
272                                   this->hasExtension("GL_NV_path_rendering");
273
274    // Enable supported shader-related caps
275    if (kDesktop_GrGLBinding == this->glBinding()) {
276        fCaps.fDualSourceBlendingSupport =
277                            this->glVersion() >= GR_GL_VER(3,3) ||
278                            this->hasExtension("GL_ARB_blend_func_extended");
279        fCaps.fShaderDerivativeSupport = true;
280        // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
281        fCaps.fGeometryShaderSupport =
282                                this->glVersion() >= GR_GL_VER(3,2) &&
283                                this->glslGeneration() >= k150_GrGLSLGeneration;
284    } else {
285        fCaps.fShaderDerivativeSupport =
286                            this->hasExtension("GL_OES_standard_derivatives");
287    }
288}
289
290void GrGpuGL::fillInConfigRenderableTable() {
291
292    // OpenGL < 3.0
293    //  no support for render targets unless the GL_ARB_framebuffer_object
294    //  extension is supported (in which case we get ALPHA, RED, RG, RGB,
295    //  RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we
296    //  probably don't get R8 in this case.
297
298    // OpenGL 3.0
299    //  base color renderable: ALPHA, RED, RG, RGB, and RGBA
300    //  sized derivatives: ALPHA8, R8, RGBA4, RGBA8
301
302    // >= OpenGL 3.1
303    //  base color renderable: RED, RG, RGB, and RGBA
304    //  sized derivatives: R8, RGBA4, RGBA8
305    //  if the GL_ARB_compatibility extension is supported then we get back
306    //  support for GL_ALPHA and ALPHA8
307
308    // GL_EXT_bgra adds BGRA render targets to any version
309
310    // ES 2.0
311    //  color renderable: RGBA4, RGB5_A1, RGB565
312    //  GL_EXT_texture_rg adds support for R8 as a color render target
313    //  GL_OES_rgb8_rgba8 and/or GL_ARM_rgba8 adds support for RGBA8
314    //  GL_EXT_texture_format_BGRA8888 and/or GL_APPLE_texture_format_BGRA8888
315    //          added BGRA support
316
317    if (kDesktop_GrGLBinding == this->glBinding()) {
318        // Post 3.0 we will get R8
319        // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object)
320        if (this->glVersion() >= GR_GL_VER(3,0) ||
321            this->hasExtension("GL_ARB_framebuffer_object")) {
322            fConfigRenderSupport[kAlpha_8_GrPixelConfig] = true;
323        }
324    } else {
325        // On ES we can only hope for R8
326        fConfigRenderSupport[kAlpha_8_GrPixelConfig] =
327                                this->glCaps().textureRedSupport();
328    }
329
330    if (kDesktop_GrGLBinding != this->glBinding()) {
331        // only available in ES
332        fConfigRenderSupport[kRGB_565_GrPixelConfig] = true;
333    }
334
335    // Pre 3.0, Ganesh relies on either GL_ARB_framebuffer_object or
336    // GL_EXT_framebuffer_object for FBO support. Both of these
337    // allow RGBA4 render targets so this is always supported.
338    fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = true;
339
340    if (this->glCaps().rgba8RenderbufferSupport()) {
341        fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig] = true;
342    }
343
344    if (this->glCaps().bgraFormatSupport()) {
345        fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig] = true;
346    }
347
348    // the un-premultiplied formats just inherit the premultiplied setting
349    fConfigRenderSupport[kRGBA_8888_UPM_GrPixelConfig] =
350                fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig];
351    fConfigRenderSupport[kBGRA_8888_UPM_GrPixelConfig] =
352                fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig];
353}
354
355bool GrGpuGL::canPreserveReadWriteUnpremulPixels() {
356    if (kUnknown_CanPreserveUnpremulRoundtrip ==
357        fCanPreserveUnpremulRoundtrip) {
358
359        SkAutoTMalloc<uint32_t> data(256 * 256 * 3);
360        uint32_t* srcData = data.get();
361        uint32_t* firstRead = data.get() + 256 * 256;
362        uint32_t* secondRead = data.get() + 2 * 256 * 256;
363
364        for (int y = 0; y < 256; ++y) {
365            for (int x = 0; x < 256; ++x) {
366                uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
367                color[3] = y;
368                color[2] = x;
369                color[1] = x;
370                color[0] = x;
371            }
372        }
373
374        // We have broader support for read/write pixels on render targets
375        // than on textures.
376        GrTextureDesc dstDesc;
377        dstDesc.fFlags = kRenderTarget_GrTextureFlagBit |
378                         kNoStencil_GrTextureFlagBit;
379        dstDesc.fWidth = 256;
380        dstDesc.fHeight = 256;
381        dstDesc.fConfig = kRGBA_8888_PM_GrPixelConfig;
382
383        SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0));
384        if (!dstTex.get()) {
385            return false;
386        }
387        GrRenderTarget* rt = dstTex.get()->asRenderTarget();
388        GrAssert(NULL != rt);
389
390        bool failed = true;
391        static const UnpremulConversion gMethods[] = {
392            kUpOnWrite_DownOnRead_UnpremulConversion,
393            kDownOnWrite_UpOnRead_UnpremulConversion,
394        };
395
396        // pretend that we can do the roundtrip to avoid recursive calls to
397        // this function
398        fCanPreserveUnpremulRoundtrip = kYes_CanPreserveUnpremulRoundtrip;
399        for (size_t i = 0; i < GR_ARRAY_COUNT(gMethods) && failed; ++i) {
400            fUnpremulConversion = gMethods[i];
401            rt->writePixels(0, 0,
402                            256, 256,
403                            kRGBA_8888_UPM_GrPixelConfig, srcData, 0);
404            rt->readPixels(0, 0,
405                           256, 256,
406                           kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
407            rt->writePixels(0, 0,
408                            256, 256,
409                            kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
410            rt->readPixels(0, 0,
411                           256, 256,
412                           kRGBA_8888_UPM_GrPixelConfig, secondRead, 0);
413            failed = false;
414            for (int j = 0; j < 256 * 256; ++j) {
415                if (firstRead[j] != secondRead[j]) {
416                    failed = true;
417                    break;
418                }
419            }
420        }
421        fCanPreserveUnpremulRoundtrip = failed ?
422                        kNo_CanPreserveUnpremulRoundtrip :
423                        kYes_CanPreserveUnpremulRoundtrip;
424    }
425
426    if (kYes_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) {
427        return true;
428    } else {
429        return false;
430    }
431}
432
433GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const {
434    if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
435        return GrPixelConfigSwapRAndB(config);
436    } else {
437        return config;
438    }
439}
440
441GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) const {
442    if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
443        return GrPixelConfigSwapRAndB(config);
444    } else {
445        return config;
446    }
447}
448
449bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const {
450    return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL);
451}
452
453void GrGpuGL::onResetContext() {
454    if (gPrintStartupSpew && !fPrintedCaps) {
455        fPrintedCaps = true;
456        this->getCaps().print();
457        this->glCaps().print();
458    }
459
460    // we don't use the zb at all
461    GL_CALL(Disable(GR_GL_DEPTH_TEST));
462    GL_CALL(DepthMask(GR_GL_FALSE));
463
464    fHWDrawFace = GrDrawState::kInvalid_DrawFace;
465    fHWDitherEnabled = kUnknown_TriState;
466
467    if (kDesktop_GrGLBinding == this->glBinding()) {
468        // Desktop-only state that we never change
469        GL_CALL(Disable(GR_GL_POINT_SMOOTH));
470        GL_CALL(Disable(GR_GL_LINE_SMOOTH));
471        GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
472        GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
473        GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
474        if (this->glCaps().imagingSupport()) {
475            GL_CALL(Disable(GR_GL_COLOR_TABLE));
476        }
477        GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
478        GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
479        // Since ES doesn't support glPointSize at all we always use the VS to
480        // set the point size
481        GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
482
483        // We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
484        // currently part of our gl interface. There are probably others as
485        // well.
486    }
487    fHWAAState.invalidate();
488    fHWWriteToColor = kUnknown_TriState;
489
490    // we only ever use lines in hairline mode
491    GL_CALL(LineWidth(1));
492
493    // invalid
494    fHWActiveTextureUnitIdx = -1;
495
496    fHWBlendState.invalidate();
497
498    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
499        fHWBoundTextures[s] = NULL;
500    }
501
502    fHWScissorSettings.invalidate();
503
504    fHWViewport.invalidate();
505
506    fHWStencilSettings.invalidate();
507    fHWStencilTestEnabled = kUnknown_TriState;
508
509    fHWGeometryState.fIndexBuffer = NULL;
510    fHWGeometryState.fVertexBuffer = NULL;
511
512    fHWGeometryState.fArrayPtrsDirty = true;
513
514    fHWBoundRenderTarget = NULL;
515
516    fHWPathMatrixState.invalidate();
517    if (fCaps.fPathStencilingSupport) {
518        // we don't use the model view matrix.
519        GL_CALL(MatrixMode(GR_GL_MODELVIEW));
520        GL_CALL(LoadIdentity());
521    }
522
523    // we assume these values
524    if (this->glCaps().unpackRowLengthSupport()) {
525        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
526    }
527    if (this->glCaps().packRowLengthSupport()) {
528        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
529    }
530    if (this->glCaps().unpackFlipYSupport()) {
531        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
532    }
533    if (this->glCaps().packFlipYSupport()) {
534        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
535    }
536
537    fHWGeometryState.fVertexOffset = ~0U;
538
539    // Third party GL code may have left vertex attributes enabled. Some GL
540    // implementations (osmesa) may read vetex attributes that are not required
541    // by the current shader. Therefore, we have to ensure that only the
542    // attributes we require for the current draw are enabled or we may cause an
543    // invalid read.
544
545    // Disable all vertex layout bits so that next flush will assume all
546    // optional vertex attributes are disabled.
547    fHWGeometryState.fVertexLayout = 0;
548
549    // We always use the this attribute and assume it is always enabled.
550    int posAttrIdx = GrGLProgram::PositionAttributeIdx();
551    GL_CALL(EnableVertexAttribArray(posAttrIdx));
552    // Disable all other vertex attributes.
553    for  (int va = 0; va < this->glCaps().maxVertexAttributes(); ++va) {
554        if (va != posAttrIdx) {
555            GL_CALL(DisableVertexAttribArray(va));
556        }
557    }
558
559    fHWProgramID = 0;
560    fHWConstAttribColor = GrColor_ILLEGAL;
561    fHWConstAttribCoverage = GrColor_ILLEGAL;
562}
563
564GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) {
565    GrGLTexture::Desc glTexDesc;
566    if (!configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) {
567        return NULL;
568    }
569
570    // next line relies on PlatformTextureDesc's flags matching GrTexture's
571    glTexDesc.fFlags = (GrTextureFlags) desc.fFlags;
572    glTexDesc.fWidth = desc.fWidth;
573    glTexDesc.fHeight = desc.fHeight;
574    glTexDesc.fConfig = desc.fConfig;
575    glTexDesc.fSampleCnt = desc.fSampleCnt;
576    glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
577    glTexDesc.fOwnsID = false;
578    glTexDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
579
580    GrGLTexture* texture = NULL;
581    if (desc.fFlags & kRenderTarget_GrPlatformTextureFlag) {
582        GrGLRenderTarget::Desc glRTDesc;
583        glRTDesc.fRTFBOID = 0;
584        glRTDesc.fTexFBOID = 0;
585        glRTDesc.fMSColorRenderbufferID = 0;
586        glRTDesc.fOwnIDs = true;
587        glRTDesc.fConfig = desc.fConfig;
588        glRTDesc.fSampleCnt = desc.fSampleCnt;
589        if (!this->createRenderTargetObjects(glTexDesc.fWidth,
590                                             glTexDesc.fHeight,
591                                             glTexDesc.fTextureID,
592                                             &glRTDesc)) {
593            return NULL;
594        }
595        texture = new GrGLTexture(this, glTexDesc, glRTDesc);
596    } else {
597        texture = new GrGLTexture(this, glTexDesc);
598    }
599    if (NULL == texture) {
600        return NULL;
601    }
602
603    this->setSpareTextureUnit();
604    return texture;
605}
606
607GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
608    GrGLRenderTarget::Desc glDesc;
609    glDesc.fConfig = desc.fConfig;
610    glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle);
611    glDesc.fMSColorRenderbufferID = 0;
612    glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
613    glDesc.fSampleCnt = desc.fSampleCnt;
614    glDesc.fOwnIDs = false;
615    GrGLIRect viewport;
616    viewport.fLeft   = 0;
617    viewport.fBottom = 0;
618    viewport.fWidth  = desc.fWidth;
619    viewport.fHeight = desc.fHeight;
620
621    GrRenderTarget* tgt = new GrGLRenderTarget(this, glDesc, viewport);
622    if (desc.fStencilBits) {
623        GrGLStencilBuffer::Format format;
624        format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
625        format.fPacked = false;
626        format.fStencilBits = desc.fStencilBits;
627        format.fTotalBits = desc.fStencilBits;
628        GrGLStencilBuffer* sb = new GrGLStencilBuffer(this,
629                                                      0,
630                                                      desc.fWidth,
631                                                      desc.fHeight,
632                                                      desc.fSampleCnt,
633                                                      format);
634        tgt->setStencilBuffer(sb);
635        sb->unref();
636    }
637    return tgt;
638}
639
640////////////////////////////////////////////////////////////////////////////////
641
642void GrGpuGL::onWriteTexturePixels(GrTexture* texture,
643                                   int left, int top, int width, int height,
644                                   GrPixelConfig config, const void* buffer,
645                                   size_t rowBytes) {
646    if (NULL == buffer) {
647        return;
648    }
649    GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
650
651    this->setSpareTextureUnit();
652    GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
653    GrGLTexture::Desc desc;
654    desc.fFlags = glTex->desc().fFlags;
655    desc.fWidth = glTex->width();
656    desc.fHeight = glTex->height();
657    desc.fConfig = glTex->config();
658    desc.fSampleCnt = glTex->desc().fSampleCnt;
659    desc.fTextureID = glTex->textureID();
660    desc.fOrientation = glTex->orientation();
661
662    this->uploadTexData(desc, false,
663                        left, top, width, height,
664                        config, buffer, rowBytes);
665}
666
667namespace {
668bool adjust_pixel_ops_params(int surfaceWidth,
669                             int surfaceHeight,
670                             size_t bpp,
671                             int* left, int* top, int* width, int* height,
672                             const void** data,
673                             size_t* rowBytes) {
674    if (!*rowBytes) {
675        *rowBytes = *width * bpp;
676    }
677
678    GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height);
679    GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight);
680
681    if (!subRect.intersect(bounds)) {
682        return false;
683    }
684    *data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) +
685          (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
686
687    *left = subRect.fLeft;
688    *top = subRect.fTop;
689    *width = subRect.width();
690    *height = subRect.height();
691    return true;
692}
693}
694
695bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
696                            bool isNewTexture,
697                            int left, int top, int width, int height,
698                            GrPixelConfig dataConfig,
699                            const void* data,
700                            size_t rowBytes) {
701    GrAssert(NULL != data || isNewTexture);
702
703    size_t bpp = GrBytesPerPixel(dataConfig);
704    if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
705                                 &width, &height, &data, &rowBytes)) {
706        return false;
707    }
708    size_t trimRowBytes = width * bpp;
709
710    // in case we need a temporary, trimmed copy of the src pixels
711    SkAutoSMalloc<128 * 128> tempStorage;
712
713    bool useTexStorage = isNewTexture &&
714                         this->glCaps().texStorageSupport();
715    if (useTexStorage) {
716        if (kDesktop_GrGLBinding == this->glBinding()) {
717            // 565 is not a sized internal format on desktop GL. So on desktop
718            // with 565 we always use an unsized internal format to let the
719            // system pick the best sized format to convert the 565 data to.
720            // Since glTexStorage only allows sized internal formats we will
721            // instead fallback to glTexImage2D.
722            useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig;
723        } else {
724            // ES doesn't allow paletted textures to be used with tex storage
725            useTexStorage = desc.fConfig != kIndex_8_GrPixelConfig;
726        }
727    }
728
729    GrGLenum internalFormat;
730    GrGLenum externalFormat;
731    GrGLenum externalType;
732    // glTexStorage requires sized internal formats on both desktop and ES. ES
733    // glTexImage requires an unsized format.
734    if (!this->configToGLFormats(dataConfig, useTexStorage, &internalFormat,
735                                 &externalFormat, &externalType)) {
736        return false;
737    }
738
739    if (!isNewTexture && GR_GL_PALETTE8_RGBA8 == internalFormat) {
740        // paletted textures cannot be updated
741        return false;
742    }
743
744    /*
745     *  check whether to allocate a temporary buffer for flipping y or
746     *  because our srcData has extra bytes past each row. If so, we need
747     *  to trim those off here, since GL ES may not let us specify
748     *  GL_UNPACK_ROW_LENGTH.
749     */
750    bool restoreGLRowLength = false;
751    bool swFlipY = false;
752    bool glFlipY = false;
753    if (NULL != data) {
754        if (GrGLTexture::kBottomUp_Orientation == desc.fOrientation) {
755            if (this->glCaps().unpackFlipYSupport()) {
756                glFlipY = true;
757            } else {
758                swFlipY = true;
759            }
760        }
761        if (this->glCaps().unpackRowLengthSupport() && !swFlipY) {
762            // can't use this for flipping, only non-neg values allowed. :(
763            if (rowBytes != trimRowBytes) {
764                GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
765                GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
766                restoreGLRowLength = true;
767            }
768        } else {
769            if (trimRowBytes != rowBytes || swFlipY) {
770                // copy data into our new storage, skipping the trailing bytes
771                size_t trimSize = height * trimRowBytes;
772                const char* src = (const char*)data;
773                if (swFlipY) {
774                    src += (height - 1) * rowBytes;
775                }
776                char* dst = (char*)tempStorage.reset(trimSize);
777                for (int y = 0; y < height; y++) {
778                    memcpy(dst, src, trimRowBytes);
779                    if (swFlipY) {
780                        src -= rowBytes;
781                    } else {
782                        src += rowBytes;
783                    }
784                    dst += trimRowBytes;
785                }
786                // now point data to our copied version
787                data = tempStorage.get();
788            }
789        }
790        if (glFlipY) {
791            GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
792        }
793        GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
794    }
795    bool succeeded = true;
796    if (isNewTexture &&
797        0 == left && 0 == top &&
798        desc.fWidth == width && desc.fHeight == height) {
799        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
800        if (useTexStorage) {
801            // We never resize  or change formats of textures. We don't use
802            // mipmaps currently.
803            GL_ALLOC_CALL(this->glInterface(),
804                          TexStorage2D(GR_GL_TEXTURE_2D,
805                                       1, // levels
806                                       internalFormat,
807                                       desc.fWidth, desc.fHeight));
808        } else {
809            if (GR_GL_PALETTE8_RGBA8 == internalFormat) {
810                GrGLsizei imageSize = desc.fWidth * desc.fHeight +
811                                      kGrColorTableSize;
812                GL_ALLOC_CALL(this->glInterface(),
813                              CompressedTexImage2D(GR_GL_TEXTURE_2D,
814                                                   0, // level
815                                                   internalFormat,
816                                                   desc.fWidth, desc.fHeight,
817                                                   0, // border
818                                                   imageSize,
819                                                   data));
820            } else {
821                GL_ALLOC_CALL(this->glInterface(),
822                              TexImage2D(GR_GL_TEXTURE_2D,
823                                         0, // level
824                                         internalFormat,
825                                         desc.fWidth, desc.fHeight,
826                                         0, // border
827                                         externalFormat, externalType,
828                                         data));
829            }
830        }
831        GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface());
832        if (error != GR_GL_NO_ERROR) {
833            succeeded = false;
834        } else {
835            // if we have data and we used TexStorage to create the texture, we
836            // now upload with TexSubImage.
837            if (NULL != data && useTexStorage) {
838                GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
839                                      0, // level
840                                      left, top,
841                                      width, height,
842                                      externalFormat, externalType,
843                                      data));
844            }
845        }
846    } else {
847        if (swFlipY || glFlipY) {
848            top = desc.fHeight - (top + height);
849        }
850        GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
851                              0, // level
852                              left, top,
853                              width, height,
854                              externalFormat, externalType, data));
855    }
856
857    if (restoreGLRowLength) {
858        GrAssert(this->glCaps().unpackRowLengthSupport());
859        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
860    }
861    if (glFlipY) {
862        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
863    }
864    return succeeded;
865}
866
867namespace {
868bool renderbuffer_storage_msaa(GrGLContextInfo& ctxInfo,
869                               int sampleCount,
870                               GrGLenum format,
871                               int width, int height) {
872    CLEAR_ERROR_BEFORE_ALLOC(ctxInfo.interface());
873    GrAssert(GrGLCaps::kNone_MSFBOType != ctxInfo.caps().msFBOType());
874    bool created = false;
875    if (GrGLCaps::kNVDesktop_CoverageAAType ==
876        ctxInfo.caps().coverageAAType()) {
877        const GrGLCaps::MSAACoverageMode& mode =
878            ctxInfo.caps().getMSAACoverageMode(sampleCount);
879        GL_ALLOC_CALL(ctxInfo.interface(),
880                      RenderbufferStorageMultisampleCoverage(GR_GL_RENDERBUFFER,
881                                                        mode.fCoverageSampleCnt,
882                                                        mode.fColorSampleCnt,
883                                                        format,
884                                                        width, height));
885        created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface()));
886    }
887    if (!created) {
888        // glRBMS will fail if requested samples is > max samples.
889        sampleCount = GrMin(sampleCount, ctxInfo.caps().maxSampleCount());
890        GL_ALLOC_CALL(ctxInfo.interface(),
891                      RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
892                                                     sampleCount,
893                                                     format,
894                                                     width, height));
895        created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface()));
896    }
897    return created;
898}
899}
900
901bool GrGpuGL::createRenderTargetObjects(int width, int height,
902                                        GrGLuint texID,
903                                        GrGLRenderTarget::Desc* desc) {
904    desc->fMSColorRenderbufferID = 0;
905    desc->fRTFBOID = 0;
906    desc->fTexFBOID = 0;
907    desc->fOwnIDs = true;
908
909    GrGLenum status;
910
911    GrGLenum msColorFormat = 0; // suppress warning
912
913    GL_CALL(GenFramebuffers(1, &desc->fTexFBOID));
914    if (!desc->fTexFBOID) {
915        goto FAILED;
916    }
917
918
919    // If we are using multisampling we will create two FBOS. We render
920    // to one and then resolve to the texture bound to the other.
921    if (desc->fSampleCnt > 0) {
922        if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
923            goto FAILED;
924        }
925        GL_CALL(GenFramebuffers(1, &desc->fRTFBOID));
926        GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
927        if (!desc->fRTFBOID ||
928            !desc->fMSColorRenderbufferID ||
929            !this->configToGLFormats(desc->fConfig,
930                                     // GLES requires sized internal formats
931                                     kES2_GrGLBinding == this->glBinding(),
932                                     &msColorFormat, NULL, NULL)) {
933            goto FAILED;
934        }
935    } else {
936        desc->fRTFBOID = desc->fTexFBOID;
937    }
938
939    // below here we may bind the FBO
940    fHWBoundRenderTarget = NULL;
941    if (desc->fRTFBOID != desc->fTexFBOID) {
942        GrAssert(desc->fSampleCnt > 1);
943        GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER,
944                               desc->fMSColorRenderbufferID));
945        if (!renderbuffer_storage_msaa(fGLContextInfo,
946                                       desc->fSampleCnt,
947                                       msColorFormat,
948                                       width, height)) {
949            goto FAILED;
950        }
951        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID));
952        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
953                                      GR_GL_COLOR_ATTACHMENT0,
954                                      GR_GL_RENDERBUFFER,
955                                      desc->fMSColorRenderbufferID));
956        if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
957            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
958            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
959                goto FAILED;
960            }
961            fGLContextInfo.caps().markConfigAsValidColorAttachment(
962                                                                desc->fConfig);
963        }
964    }
965    GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
966
967    GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
968                                 GR_GL_COLOR_ATTACHMENT0,
969                                 GR_GL_TEXTURE_2D,
970                                 texID, 0));
971    if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
972        GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
973        if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
974            goto FAILED;
975        }
976        fGLContextInfo.caps().markConfigAsValidColorAttachment(desc->fConfig);
977    }
978
979    return true;
980
981FAILED:
982    if (desc->fMSColorRenderbufferID) {
983        GL_CALL(DeleteRenderbuffers(1, &desc->fMSColorRenderbufferID));
984    }
985    if (desc->fRTFBOID != desc->fTexFBOID) {
986        GL_CALL(DeleteFramebuffers(1, &desc->fRTFBOID));
987    }
988    if (desc->fTexFBOID) {
989        GL_CALL(DeleteFramebuffers(1, &desc->fTexFBOID));
990    }
991    return false;
992}
993
994// good to set a break-point here to know when createTexture fails
995static GrTexture* return_null_texture() {
996//    GrAssert(!"null texture");
997    return NULL;
998}
999
1000#if 0 && GR_DEBUG
1001static size_t as_size_t(int x) {
1002    return x;
1003}
1004#endif
1005
1006GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
1007                                    const void* srcData,
1008                                    size_t rowBytes) {
1009
1010    GrGLTexture::Desc glTexDesc;
1011    GrGLRenderTarget::Desc  glRTDesc;
1012
1013    // Attempt to catch un- or wrongly initialized sample counts;
1014    GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
1015
1016    glTexDesc.fFlags  = desc.fFlags;
1017    glTexDesc.fWidth  = desc.fWidth;
1018    glTexDesc.fHeight = desc.fHeight;
1019    glTexDesc.fConfig = desc.fConfig;
1020    glTexDesc.fSampleCnt = desc.fSampleCnt;
1021    glTexDesc.fClientCacheID = desc.fClientCacheID;
1022
1023    glTexDesc.fOwnsID = true;
1024
1025    glRTDesc.fMSColorRenderbufferID = 0;
1026    glRTDesc.fRTFBOID = 0;
1027    glRTDesc.fTexFBOID = 0;
1028    glRTDesc.fOwnIDs = true;
1029    glRTDesc.fConfig = glTexDesc.fConfig;
1030
1031    bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
1032
1033    const Caps& caps = this->getCaps();
1034
1035    // We keep GrRenderTargets in GL's normal orientation so that they
1036    // can be drawn to by the outside world without the client having
1037    // to render upside down.
1038    glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
1039                                            GrGLTexture::kTopDown_Orientation;
1040
1041    glRTDesc.fSampleCnt = desc.fSampleCnt;
1042    if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() &&
1043        desc.fSampleCnt) {
1044        //GrPrintf("MSAA RT requested but not supported on this platform.");
1045        return return_null_texture();
1046    }
1047
1048    if (renderTarget) {
1049        if (glTexDesc.fWidth > caps.fMaxRenderTargetSize ||
1050            glTexDesc.fHeight > caps.fMaxRenderTargetSize) {
1051            return return_null_texture();
1052        }
1053    }
1054
1055    GL_CALL(GenTextures(1, &glTexDesc.fTextureID));
1056    if (renderTarget && this->glCaps().textureUsageSupport()) {
1057        // provides a hint about how this texture will be used
1058        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1059                              GR_GL_TEXTURE_USAGE,
1060                              GR_GL_FRAMEBUFFER_ATTACHMENT));
1061    }
1062    if (!glTexDesc.fTextureID) {
1063        return return_null_texture();
1064    }
1065
1066    this->setSpareTextureUnit();
1067    GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
1068
1069    // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
1070    // drivers have a bug where an FBO won't be complete if it includes a
1071    // texture that is not mipmap complete (considering the filter in use).
1072    GrGLTexture::TexParams initialTexParams;
1073    // we only set a subset here so invalidate first
1074    initialTexParams.invalidate();
1075    initialTexParams.fFilter = GR_GL_NEAREST;
1076    initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
1077    initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
1078    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1079                          GR_GL_TEXTURE_MAG_FILTER,
1080                          initialTexParams.fFilter));
1081    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1082                          GR_GL_TEXTURE_MIN_FILTER,
1083                          initialTexParams.fFilter));
1084    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1085                          GR_GL_TEXTURE_WRAP_S,
1086                          initialTexParams.fWrapS));
1087    GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
1088                          GR_GL_TEXTURE_WRAP_T,
1089                          initialTexParams.fWrapT));
1090    if (!this->uploadTexData(glTexDesc, true, 0, 0,
1091                             glTexDesc.fWidth, glTexDesc.fHeight,
1092                             desc.fConfig, srcData, rowBytes)) {
1093        GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
1094        return return_null_texture();
1095    }
1096
1097    GrGLTexture* tex;
1098    if (renderTarget) {
1099        // unbind the texture from the texture unit before binding it to the frame buffer
1100        GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
1101
1102        if (!this->createRenderTargetObjects(glTexDesc.fWidth,
1103                                             glTexDesc.fHeight,
1104                                             glTexDesc.fTextureID,
1105                                             &glRTDesc)) {
1106            GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
1107            return return_null_texture();
1108        }
1109        tex = new GrGLTexture(this, glTexDesc, glRTDesc);
1110    } else {
1111        tex = new GrGLTexture(this, glTexDesc);
1112    }
1113    tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
1114#ifdef TRACE_TEXTURE_CREATION
1115    GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n",
1116             glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
1117#endif
1118    return tex;
1119}
1120
1121namespace {
1122
1123const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
1124
1125void inline get_stencil_rb_sizes(const GrGLInterface* gl,
1126                                 GrGLuint rb,
1127                                 GrGLStencilBuffer::Format* format) {
1128    // we shouldn't ever know one size and not the other
1129    GrAssert((kUnknownBitCount == format->fStencilBits) ==
1130             (kUnknownBitCount == format->fTotalBits));
1131    if (kUnknownBitCount == format->fStencilBits) {
1132        GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1133                                         GR_GL_RENDERBUFFER_STENCIL_SIZE,
1134                                         (GrGLint*)&format->fStencilBits);
1135        if (format->fPacked) {
1136            GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
1137                                             GR_GL_RENDERBUFFER_DEPTH_SIZE,
1138                                             (GrGLint*)&format->fTotalBits);
1139            format->fTotalBits += format->fStencilBits;
1140        } else {
1141            format->fTotalBits = format->fStencilBits;
1142        }
1143    }
1144}
1145}
1146
1147bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
1148                                                 int width, int height) {
1149
1150    // All internally created RTs are also textures. We don't create
1151    // SBs for a client's standalone RT (that is RT that isnt also a texture).
1152    GrAssert(rt->asTexture());
1153    GrAssert(width >= rt->width());
1154    GrAssert(height >= rt->height());
1155
1156    int samples = rt->numSamples();
1157    GrGLuint sbID;
1158    GL_CALL(GenRenderbuffers(1, &sbID));
1159    if (!sbID) {
1160        return false;
1161    }
1162
1163    GrGLStencilBuffer* sb = NULL;
1164
1165    int stencilFmtCnt = this->glCaps().stencilFormats().count();
1166    for (int i = 0; i < stencilFmtCnt; ++i) {
1167        GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
1168        // we start with the last stencil format that succeeded in hopes
1169        // that we won't go through this loop more than once after the
1170        // first (painful) stencil creation.
1171        int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1172        const GrGLCaps::StencilFormat& sFmt =
1173                this->glCaps().stencilFormats()[sIdx];
1174        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1175        // we do this "if" so that we don't call the multisample
1176        // version on a GL that doesn't have an MSAA extension.
1177        bool created;
1178        if (samples > 0) {
1179            created = renderbuffer_storage_msaa(fGLContextInfo,
1180                                                samples,
1181                                                sFmt.fInternalFormat,
1182                                                width, height);
1183        } else {
1184            GL_ALLOC_CALL(this->glInterface(),
1185                          RenderbufferStorage(GR_GL_RENDERBUFFER,
1186                                              sFmt.fInternalFormat,
1187                                              width, height));
1188            created =
1189                (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface()));
1190        }
1191        if (created) {
1192            // After sized formats we attempt an unsized format and take
1193            // whatever sizes GL gives us. In that case we query for the size.
1194            GrGLStencilBuffer::Format format = sFmt;
1195            get_stencil_rb_sizes(this->glInterface(), sbID, &format);
1196            sb = new GrGLStencilBuffer(this, sbID, width, height,
1197                                       samples, format);
1198            if (this->attachStencilBufferToRenderTarget(sb, rt)) {
1199                fLastSuccessfulStencilFmtIdx = sIdx;
1200                rt->setStencilBuffer(sb);
1201                sb->unref();
1202                return true;
1203           }
1204           sb->abandon(); // otherwise we lose sbID
1205           sb->unref();
1206        }
1207    }
1208    GL_CALL(DeleteRenderbuffers(1, &sbID));
1209    return false;
1210}
1211
1212bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
1213                                                GrRenderTarget* rt) {
1214    GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
1215
1216    GrGLuint fbo = glrt->renderFBOID();
1217
1218    if (NULL == sb) {
1219        if (NULL != rt->getStencilBuffer()) {
1220            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1221                                          GR_GL_STENCIL_ATTACHMENT,
1222                                          GR_GL_RENDERBUFFER, 0));
1223            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1224                                          GR_GL_DEPTH_ATTACHMENT,
1225                                          GR_GL_RENDERBUFFER, 0));
1226#if GR_DEBUG
1227            GrGLenum status;
1228            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1229            GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status);
1230#endif
1231        }
1232        return true;
1233    } else {
1234        GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb;
1235        GrGLuint rb = glsb->renderbufferID();
1236
1237        fHWBoundRenderTarget = NULL;
1238        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
1239        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1240                                      GR_GL_STENCIL_ATTACHMENT,
1241                                      GR_GL_RENDERBUFFER, rb));
1242        if (glsb->format().fPacked) {
1243            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1244                                          GR_GL_DEPTH_ATTACHMENT,
1245                                          GR_GL_RENDERBUFFER, rb));
1246        } else {
1247            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1248                                          GR_GL_DEPTH_ATTACHMENT,
1249                                          GR_GL_RENDERBUFFER, 0));
1250        }
1251
1252        GrGLenum status;
1253        if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(),
1254                                                           glsb->format())) {
1255            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1256            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1257                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1258                                              GR_GL_STENCIL_ATTACHMENT,
1259                                              GR_GL_RENDERBUFFER, 0));
1260                if (glsb->format().fPacked) {
1261                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1262                                                  GR_GL_DEPTH_ATTACHMENT,
1263                                                  GR_GL_RENDERBUFFER, 0));
1264                }
1265                return false;
1266            } else {
1267                fGLContextInfo.caps().markColorConfigAndStencilFormatAsVerified(
1268                    rt->config(),
1269                    glsb->format());
1270            }
1271        }
1272        return true;
1273    }
1274}
1275
1276////////////////////////////////////////////////////////////////////////////////
1277
1278GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
1279    GrGLuint id;
1280    GL_CALL(GenBuffers(1, &id));
1281    if (id) {
1282        GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
1283        fHWGeometryState.fArrayPtrsDirty = true;
1284        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1285        // make sure driver can allocate memory for this buffer
1286        GL_ALLOC_CALL(this->glInterface(),
1287                      BufferData(GR_GL_ARRAY_BUFFER,
1288                                 size,
1289                                 NULL,   // data ptr
1290                                 dynamic ? GR_GL_DYNAMIC_DRAW :
1291                                           GR_GL_STATIC_DRAW));
1292        if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1293            GL_CALL(DeleteBuffers(1, &id));
1294            // deleting bound buffer does implicit bind to 0
1295            fHWGeometryState.fVertexBuffer = NULL;
1296            return NULL;
1297        }
1298        GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
1299                                                              size, dynamic);
1300        fHWGeometryState.fVertexBuffer = vertexBuffer;
1301        return vertexBuffer;
1302    }
1303    return NULL;
1304}
1305
1306GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
1307    GrGLuint id;
1308    GL_CALL(GenBuffers(1, &id));
1309    if (id) {
1310        GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
1311        CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1312        // make sure driver can allocate memory for this buffer
1313        GL_ALLOC_CALL(this->glInterface(),
1314                      BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
1315                                 size,
1316                                 NULL,  // data ptr
1317                                 dynamic ? GR_GL_DYNAMIC_DRAW :
1318                                           GR_GL_STATIC_DRAW));
1319        if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1320            GL_CALL(DeleteBuffers(1, &id));
1321            // deleting bound buffer does implicit bind to 0
1322            fHWGeometryState.fIndexBuffer = NULL;
1323            return NULL;
1324        }
1325        GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
1326                                                         size, dynamic);
1327        fHWGeometryState.fIndexBuffer = indexBuffer;
1328        return indexBuffer;
1329    }
1330    return NULL;
1331}
1332
1333GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
1334    GrAssert(fCaps.fPathStencilingSupport);
1335    return new GrGLPath(this, inPath);
1336}
1337
1338void GrGpuGL::flushScissor() {
1339    const GrDrawState& drawState = this->getDrawState();
1340    const GrGLRenderTarget* rt =
1341        static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
1342
1343    GrAssert(NULL != rt);
1344    const GrGLIRect& vp = rt->getViewport();
1345
1346    if (fScissorState.fEnabled) {
1347        GrGLIRect scissor;
1348        scissor.setRelativeTo(vp,
1349                              fScissorState.fRect.fLeft,
1350                              fScissorState.fRect.fTop,
1351                              fScissorState.fRect.width(),
1352                              fScissorState.fRect.height());
1353        // if the scissor fully contains the viewport then we fall through and
1354        // disable the scissor test.
1355        if (!scissor.contains(vp)) {
1356            if (fHWScissorSettings.fRect != scissor) {
1357                scissor.pushToGLScissor(this->glInterface());
1358                fHWScissorSettings.fRect = scissor;
1359            }
1360            if (kYes_TriState != fHWScissorSettings.fEnabled) {
1361                GL_CALL(Enable(GR_GL_SCISSOR_TEST));
1362                fHWScissorSettings.fEnabled = kYes_TriState;
1363            }
1364            return;
1365        }
1366    }
1367    if (kNo_TriState != fHWScissorSettings.fEnabled) {
1368        GL_CALL(Disable(GR_GL_SCISSOR_TEST));
1369        fHWScissorSettings.fEnabled = kNo_TriState;
1370        return;
1371    }
1372}
1373
1374void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
1375    const GrDrawState& drawState = this->getDrawState();
1376    const GrRenderTarget* rt = drawState.getRenderTarget();
1377    // parent class should never let us get here with no RT
1378    GrAssert(NULL != rt);
1379
1380    GrIRect clippedRect;
1381    if (NULL != rect) {
1382        // flushScissor expects rect to be clipped to the target.
1383        clippedRect = *rect;
1384        GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
1385        if (clippedRect.intersect(rtRect)) {
1386            rect = &clippedRect;
1387        } else {
1388            return;
1389        }
1390    }
1391    this->flushRenderTarget(rect);
1392    GrAutoTRestore<ScissorState> asr(&fScissorState);
1393    fScissorState.fEnabled = (NULL != rect);
1394    if (fScissorState.fEnabled) {
1395        fScissorState.fRect = *rect;
1396    }
1397    this->flushScissor();
1398
1399    GrGLfloat r, g, b, a;
1400    static const GrGLfloat scale255 = 1.f / 255.f;
1401    a = GrColorUnpackA(color) * scale255;
1402    GrGLfloat scaleRGB = scale255;
1403    if (GrPixelConfigIsUnpremultiplied(rt->config())) {
1404        scaleRGB *= a;
1405    }
1406    r = GrColorUnpackR(color) * scaleRGB;
1407    g = GrColorUnpackG(color) * scaleRGB;
1408    b = GrColorUnpackB(color) * scaleRGB;
1409
1410    GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
1411    fHWWriteToColor = kYes_TriState;
1412    GL_CALL(ClearColor(r, g, b, a));
1413    GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
1414}
1415
1416void GrGpuGL::clearStencil() {
1417    if (NULL == this->getDrawState().getRenderTarget()) {
1418        return;
1419    }
1420
1421    this->flushRenderTarget(&GrIRect::EmptyIRect());
1422
1423    GrAutoTRestore<ScissorState> asr(&fScissorState);
1424    fScissorState.fEnabled = false;
1425    this->flushScissor();
1426
1427    GL_CALL(StencilMask(0xffffffff));
1428    GL_CALL(ClearStencil(0));
1429    GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1430    fHWStencilSettings.invalidate();
1431}
1432
1433void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
1434    const GrDrawState& drawState = this->getDrawState();
1435    const GrRenderTarget* rt = drawState.getRenderTarget();
1436    GrAssert(NULL != rt);
1437
1438    // this should only be called internally when we know we have a
1439    // stencil buffer.
1440    GrAssert(NULL != rt->getStencilBuffer());
1441    GrGLint stencilBitCount =  rt->getStencilBuffer()->bits();
1442#if 0
1443    GrAssert(stencilBitCount > 0);
1444    GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
1445#else
1446    // we could just clear the clip bit but when we go through
1447    // ANGLE a partial stencil mask will cause clears to be
1448    // turned into draws. Our contract on GrDrawTarget says that
1449    // changing the clip between stencil passes may or may not
1450    // zero the client's clip bits. So we just clear the whole thing.
1451    static const GrGLint clipStencilMask  = ~0;
1452#endif
1453    GrGLint value;
1454    if (insideClip) {
1455        value = (1 << (stencilBitCount - 1));
1456    } else {
1457        value = 0;
1458    }
1459    this->flushRenderTarget(&GrIRect::EmptyIRect());
1460
1461    GrAutoTRestore<ScissorState> asr(&fScissorState);
1462    fScissorState.fEnabled = true;
1463    fScissorState.fRect = rect;
1464    this->flushScissor();
1465
1466    GL_CALL(StencilMask((uint32_t) clipStencilMask));
1467    GL_CALL(ClearStencil(value));
1468    GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1469    fHWStencilSettings.invalidate();
1470}
1471
1472void GrGpuGL::onForceRenderTargetFlush() {
1473    this->flushRenderTarget(&GrIRect::EmptyIRect());
1474}
1475
1476bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
1477                                        int left, int top,
1478                                        int width, int height,
1479                                        GrPixelConfig config,
1480                                        size_t rowBytes) const {
1481    // if GL can do the flip then we'll never pay for it.
1482    if (this->glCaps().packFlipYSupport()) {
1483        return false;
1484    }
1485
1486    // If we have to do memcpy to handle non-trim rowBytes then we
1487    // get the flip for free. Otherwise it costs.
1488    if (this->glCaps().packRowLengthSupport()) {
1489        return true;
1490    }
1491    // If we have to do memcpys to handle rowBytes then y-flip is free
1492    // Note the rowBytes might be tight to the passed in data, but if data
1493    // gets clipped in x to the target the rowBytes will no longer be tight.
1494    if (left >= 0 && (left + width) < renderTarget->width()) {
1495           return 0 == rowBytes ||
1496                  GrBytesPerPixel(config) * width == rowBytes;
1497    } else {
1498        return false;
1499    }
1500}
1501
1502bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1503                           int left, int top,
1504                           int width, int height,
1505                           GrPixelConfig config,
1506                           void* buffer,
1507                           size_t rowBytes,
1508                           bool invertY) {
1509    GrGLenum format;
1510    GrGLenum type;
1511    if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
1512        return false;
1513    }
1514    size_t bpp = GrBytesPerPixel(config);
1515    if (!adjust_pixel_ops_params(target->width(), target->height(), bpp,
1516                                 &left, &top, &width, &height,
1517                                 const_cast<const void**>(&buffer),
1518                                 &rowBytes)) {
1519        return false;
1520    }
1521
1522    // resolve the render target if necessary
1523    GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1524    GrDrawState::AutoRenderTargetRestore artr;
1525    switch (tgt->getResolveType()) {
1526        case GrGLRenderTarget::kCantResolve_ResolveType:
1527            return false;
1528        case GrGLRenderTarget::kAutoResolves_ResolveType:
1529            artr.set(this->drawState(), target);
1530            this->flushRenderTarget(&GrIRect::EmptyIRect());
1531            break;
1532        case GrGLRenderTarget::kCanResolve_ResolveType:
1533            this->onResolveRenderTarget(tgt);
1534            // we don't track the state of the READ FBO ID.
1535            GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1536                                    tgt->textureFBOID()));
1537            break;
1538        default:
1539            GrCrash("Unknown resolve type");
1540    }
1541
1542    const GrGLIRect& glvp = tgt->getViewport();
1543
1544    // the read rect is viewport-relative
1545    GrGLIRect readRect;
1546    readRect.setRelativeTo(glvp, left, top, width, height);
1547
1548    size_t tightRowBytes = bpp * width;
1549    if (0 == rowBytes) {
1550        rowBytes = tightRowBytes;
1551    }
1552    size_t readDstRowBytes = tightRowBytes;
1553    void* readDst = buffer;
1554
1555    // determine if GL can read using the passed rowBytes or if we need
1556    // a scratch buffer.
1557    SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1558    if (rowBytes != tightRowBytes) {
1559        if (this->glCaps().packRowLengthSupport()) {
1560            GrAssert(!(rowBytes % sizeof(GrColor)));
1561            GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowBytes / sizeof(GrColor)));
1562            readDstRowBytes = rowBytes;
1563        } else {
1564            scratch.reset(tightRowBytes * height);
1565            readDst = scratch.get();
1566        }
1567    }
1568    if (!invertY && this->glCaps().packFlipYSupport()) {
1569        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
1570    }
1571    GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
1572                       readRect.fWidth, readRect.fHeight,
1573                       format, type, readDst));
1574    if (readDstRowBytes != tightRowBytes) {
1575        GrAssert(this->glCaps().packRowLengthSupport());
1576        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
1577    }
1578    if (!invertY && this->glCaps().packFlipYSupport()) {
1579        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
1580        invertY = true;
1581    }
1582
1583    // now reverse the order of the rows, since GL's are bottom-to-top, but our
1584    // API presents top-to-bottom. We must preserve the padding contents. Note
1585    // that the above readPixels did not overwrite the padding.
1586    if (readDst == buffer) {
1587        GrAssert(rowBytes == readDstRowBytes);
1588        if (!invertY) {
1589            scratch.reset(tightRowBytes);
1590            void* tmpRow = scratch.get();
1591            // flip y in-place by rows
1592            const int halfY = height >> 1;
1593            char* top = reinterpret_cast<char*>(buffer);
1594            char* bottom = top + (height - 1) * rowBytes;
1595            for (int y = 0; y < halfY; y++) {
1596                memcpy(tmpRow, top, tightRowBytes);
1597                memcpy(top, bottom, tightRowBytes);
1598                memcpy(bottom, tmpRow, tightRowBytes);
1599                top += rowBytes;
1600                bottom -= rowBytes;
1601            }
1602        }
1603    } else {
1604        GrAssert(readDst != buffer);        GrAssert(rowBytes != tightRowBytes);
1605        // copy from readDst to buffer while flipping y
1606        // const int halfY = height >> 1;
1607        const char* src = reinterpret_cast<const char*>(readDst);
1608        char* dst = reinterpret_cast<char*>(buffer);
1609        if (!invertY) {
1610            dst += (height-1) * rowBytes;
1611        }
1612        for (int y = 0; y < height; y++) {
1613            memcpy(dst, src, tightRowBytes);
1614            src += readDstRowBytes;
1615            if (invertY) {
1616                dst += rowBytes;
1617            } else {
1618                dst -= rowBytes;
1619            }
1620        }
1621    }
1622    return true;
1623}
1624
1625void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
1626
1627    GrGLRenderTarget* rt =
1628        static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget());
1629    GrAssert(NULL != rt);
1630
1631    if (fHWBoundRenderTarget != rt) {
1632        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
1633    #if GR_DEBUG
1634        GrGLenum status;
1635        GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1636        if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1637            GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
1638        }
1639    #endif
1640        fHWBoundRenderTarget = rt;
1641        const GrGLIRect& vp = rt->getViewport();
1642        if (fHWViewport != vp) {
1643            vp.pushToGLViewport(this->glInterface());
1644            fHWViewport = vp;
1645        }
1646    }
1647    if (NULL == bound || !bound->isEmpty()) {
1648        rt->flagAsNeedingResolve(bound);
1649    }
1650}
1651
1652GrGLenum gPrimitiveType2GLMode[] = {
1653    GR_GL_TRIANGLES,
1654    GR_GL_TRIANGLE_STRIP,
1655    GR_GL_TRIANGLE_FAN,
1656    GR_GL_POINTS,
1657    GR_GL_LINES,
1658    GR_GL_LINE_STRIP
1659};
1660
1661#define SWAP_PER_DRAW 0
1662
1663#if SWAP_PER_DRAW
1664    #if GR_MAC_BUILD
1665        #include <AGL/agl.h>
1666    #elif GR_WIN32_BUILD
1667        #include <gl/GL.h>
1668        void SwapBuf() {
1669            DWORD procID = GetCurrentProcessId();
1670            HWND hwnd = GetTopWindow(GetDesktopWindow());
1671            while(hwnd) {
1672                DWORD wndProcID = 0;
1673                GetWindowThreadProcessId(hwnd, &wndProcID);
1674                if(wndProcID == procID) {
1675                    SwapBuffers(GetDC(hwnd));
1676                }
1677                hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1678            }
1679         }
1680    #endif
1681#endif
1682
1683void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1684                               uint32_t startVertex,
1685                               uint32_t startIndex,
1686                               uint32_t vertexCount,
1687                               uint32_t indexCount) {
1688    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1689
1690    GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
1691
1692    GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1693    GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1694
1695    // our setupGeometry better have adjusted this to zero since
1696    // DrawElements always draws from the begining of the arrays for idx 0.
1697    GrAssert(0 == startVertex);
1698
1699    GL_CALL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1700                         GR_GL_UNSIGNED_SHORT, indices));
1701#if SWAP_PER_DRAW
1702    glFlush();
1703    #if GR_MAC_BUILD
1704        aglSwapBuffers(aglGetCurrentContext());
1705        int set_a_break_pt_here = 9;
1706        aglSwapBuffers(aglGetCurrentContext());
1707    #elif GR_WIN32_BUILD
1708        SwapBuf();
1709        int set_a_break_pt_here = 9;
1710        SwapBuf();
1711    #endif
1712#endif
1713}
1714
1715void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1716                                  uint32_t startVertex,
1717                                  uint32_t vertexCount) {
1718    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1719
1720    GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1721
1722    // our setupGeometry better have adjusted this to zero.
1723    // DrawElements doesn't take an offset so we always adjus the startVertex.
1724    GrAssert(0 == startVertex);
1725
1726    // pass 0 for parameter first. We have to adjust gl*Pointer() to
1727    // account for startVertex in the DrawElements case. So we always
1728    // rely on setupGeometry to have accounted for startVertex.
1729    GL_CALL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1730#if SWAP_PER_DRAW
1731    glFlush();
1732    #if GR_MAC_BUILD
1733        aglSwapBuffers(aglGetCurrentContext());
1734        int set_a_break_pt_here = 9;
1735        aglSwapBuffers(aglGetCurrentContext());
1736    #elif GR_WIN32_BUILD
1737        SwapBuf();
1738        int set_a_break_pt_here = 9;
1739        SwapBuf();
1740    #endif
1741#endif
1742}
1743
1744namespace {
1745const GrStencilSettings& winding_nv_path_stencil_settings() {
1746    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
1747        kIncClamp_StencilOp,
1748        kIncClamp_StencilOp,
1749        kAlwaysIfInClip_StencilFunc,
1750        ~0, ~0, ~0);
1751    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
1752}
1753const GrStencilSettings& even_odd_nv_path_stencil_settings() {
1754    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
1755        kInvert_StencilOp,
1756        kInvert_StencilOp,
1757        kAlwaysIfInClip_StencilFunc,
1758        ~0, ~0, ~0);
1759    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
1760}
1761}
1762
1763
1764void GrGpuGL::setStencilPathSettings(const GrPath&,
1765                                     GrPathFill fill,
1766                                     GrStencilSettings* settings) {
1767    switch (fill) {
1768        case kEvenOdd_GrPathFill:
1769            *settings = even_odd_nv_path_stencil_settings();
1770            return;
1771        case kWinding_GrPathFill:
1772            *settings = winding_nv_path_stencil_settings();
1773            return;
1774        default:
1775            GrCrash("Unexpected path fill.");
1776    }
1777}
1778
1779void GrGpuGL::onGpuStencilPath(const GrPath* path, GrPathFill fill) {
1780    GrAssert(fCaps.fPathStencilingSupport);
1781
1782    GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
1783    GrDrawState* drawState = this->drawState();
1784    GrAssert(NULL != drawState->getRenderTarget());
1785    if (NULL == drawState->getRenderTarget()->getStencilBuffer()) {
1786        return;
1787    }
1788
1789    // Decide how to manipulate the stencil buffer based on the fill rule.
1790    // Also, assert that the stencil settings we set in setStencilPathSettings
1791    // are present.
1792    GrAssert(!fStencilSettings.isTwoSided());
1793    GrGLenum fillMode;
1794    switch (fill) {
1795        case kWinding_GrPathFill:
1796            fillMode = GR_GL_COUNT_UP;
1797            GrAssert(kIncClamp_StencilOp ==
1798                     fStencilSettings.passOp(GrStencilSettings::kFront_Face));
1799            GrAssert(kIncClamp_StencilOp ==
1800                     fStencilSettings.failOp(GrStencilSettings::kFront_Face));
1801            break;
1802        case kEvenOdd_GrPathFill:
1803            fillMode = GR_GL_INVERT;
1804            GrAssert(kInvert_StencilOp ==
1805                     fStencilSettings.passOp(GrStencilSettings::kFront_Face));
1806            GrAssert(kInvert_StencilOp ==
1807                fStencilSettings.failOp(GrStencilSettings::kFront_Face));
1808            break;
1809        default:
1810            // Only the above two fill rules are allowed.
1811            GrCrash("Unexpected path fill.");
1812    }
1813    GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face);
1814    GL_CALL(StencilFillPath(id, fillMode, writeMask));
1815    //GrPrintf("\tStencilFillPath ID: %d\n", id);
1816}
1817
1818void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
1819
1820    GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
1821
1822    if (rt->needsResolve()) {
1823        GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType());
1824        GrAssert(rt->textureFBOID() != rt->renderFBOID());
1825        GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1826                                rt->renderFBOID()));
1827        GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
1828                                rt->textureFBOID()));
1829        // make sure we go through flushRenderTarget() since we've modified
1830        // the bound DRAW FBO ID.
1831        fHWBoundRenderTarget = NULL;
1832        const GrGLIRect& vp = rt->getViewport();
1833        const GrIRect dirtyRect = rt->getResolveRect();
1834        GrGLIRect r;
1835        r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1836                        dirtyRect.width(), dirtyRect.height());
1837
1838        GrAutoTRestore<ScissorState> asr;
1839        if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
1840            // Apple's extension uses the scissor as the blit bounds.
1841            asr.reset(&fScissorState);
1842            fScissorState.fEnabled = true;
1843            fScissorState.fRect = dirtyRect;
1844            this->flushScissor();
1845            GL_CALL(ResolveMultisampleFramebuffer());
1846        } else {
1847            if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
1848                // this respects the scissor during the blit, so disable it.
1849                GrAssert(GrGLCaps::kDesktopEXT_MSFBOType ==
1850                         this->glCaps().msFBOType());
1851                asr.reset(&fScissorState);
1852                fScissorState.fEnabled = false;
1853                this->flushScissor();
1854            }
1855            int right = r.fLeft + r.fWidth;
1856            int top = r.fBottom + r.fHeight;
1857            GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1858                                    r.fLeft, r.fBottom, right, top,
1859                                    GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
1860        }
1861        rt->flagAsResolved();
1862    }
1863}
1864
1865namespace {
1866
1867GrGLenum gr_to_gl_stencil_func(GrStencilFunc basicFunc) {
1868    static const GrGLenum gTable[] = {
1869        GR_GL_ALWAYS,           // kAlways_StencilFunc
1870        GR_GL_NEVER,            // kNever_StencilFunc
1871        GR_GL_GREATER,          // kGreater_StencilFunc
1872        GR_GL_GEQUAL,           // kGEqual_StencilFunc
1873        GR_GL_LESS,             // kLess_StencilFunc
1874        GR_GL_LEQUAL,           // kLEqual_StencilFunc,
1875        GR_GL_EQUAL,            // kEqual_StencilFunc,
1876        GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
1877    };
1878    GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
1879    GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1880    GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1881    GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1882    GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1883    GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1884    GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1885    GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1886    GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1887    GrAssert((unsigned) basicFunc < kBasicStencilFuncCount);
1888
1889    return gTable[basicFunc];
1890}
1891
1892GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
1893    static const GrGLenum gTable[] = {
1894        GR_GL_KEEP,        // kKeep_StencilOp
1895        GR_GL_REPLACE,     // kReplace_StencilOp
1896        GR_GL_INCR_WRAP,   // kIncWrap_StencilOp
1897        GR_GL_INCR,        // kIncClamp_StencilOp
1898        GR_GL_DECR_WRAP,   // kDecWrap_StencilOp
1899        GR_GL_DECR,        // kDecClamp_StencilOp
1900        GR_GL_ZERO,        // kZero_StencilOp
1901        GR_GL_INVERT,      // kInvert_StencilOp
1902    };
1903    GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kStencilOpCount);
1904    GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1905    GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1906    GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1907    GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1908    GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1909    GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1910    GR_STATIC_ASSERT(6 == kZero_StencilOp);
1911    GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1912    GrAssert((unsigned) op < kStencilOpCount);
1913    return gTable[op];
1914}
1915
1916void set_gl_stencil(const GrGLInterface* gl,
1917                    const GrStencilSettings& settings,
1918                    GrGLenum glFace,
1919                    GrStencilSettings::Face grFace) {
1920    GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace));
1921    GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace));
1922    GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace));
1923
1924    GrGLint ref = settings.funcRef(grFace);
1925    GrGLint mask = settings.funcMask(grFace);
1926    GrGLint writeMask = settings.writeMask(grFace);
1927
1928    if (GR_GL_FRONT_AND_BACK == glFace) {
1929        // we call the combined func just in case separate stencil is not
1930        // supported.
1931        GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask));
1932        GR_GL_CALL(gl, StencilMask(writeMask));
1933        GR_GL_CALL(gl, StencilOp(glFailOp, glPassOp, glPassOp));
1934    } else {
1935        GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask));
1936        GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask));
1937        GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, glPassOp, glPassOp));
1938    }
1939}
1940}
1941
1942void GrGpuGL::flushStencil(DrawType type) {
1943    if (kStencilPath_DrawType == type) {
1944        GrAssert(!fStencilSettings.isTwoSided());
1945        // Just the func, ref, and mask is set here. The op and write mask are params to the call
1946        // that draws the path to the SB (glStencilFillPath)
1947        GrGLenum func =
1948            gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFront_Face));
1949        GL_CALL(PathStencilFunc(func,
1950                                fStencilSettings.funcRef(GrStencilSettings::kFront_Face),
1951                                fStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
1952    } else if (fHWStencilSettings != fStencilSettings) {
1953        if (fStencilSettings.isDisabled()) {
1954            if (kNo_TriState != fHWStencilTestEnabled) {
1955                GL_CALL(Disable(GR_GL_STENCIL_TEST));
1956                fHWStencilTestEnabled = kNo_TriState;
1957            }
1958        } else {
1959            if (kYes_TriState != fHWStencilTestEnabled) {
1960                GL_CALL(Enable(GR_GL_STENCIL_TEST));
1961                fHWStencilTestEnabled = kYes_TriState;
1962            }
1963        }
1964        if (!fStencilSettings.isDisabled()) {
1965            if (this->getCaps().fTwoSidedStencilSupport) {
1966                set_gl_stencil(this->glInterface(),
1967                               fStencilSettings,
1968                               GR_GL_FRONT,
1969                               GrStencilSettings::kFront_Face);
1970                set_gl_stencil(this->glInterface(),
1971                               fStencilSettings,
1972                               GR_GL_BACK,
1973                               GrStencilSettings::kBack_Face);
1974            } else {
1975                set_gl_stencil(this->glInterface(),
1976                               fStencilSettings,
1977                               GR_GL_FRONT_AND_BACK,
1978                               GrStencilSettings::kFront_Face);
1979            }
1980        }
1981        fHWStencilSettings = fStencilSettings;
1982    }
1983}
1984
1985void GrGpuGL::flushAAState(DrawType type) {
1986    const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
1987    if (kDesktop_GrGLBinding == this->glBinding()) {
1988        // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1989        // smooth lines.
1990        // we prefer smooth lines over multisampled lines
1991        bool smoothLines = false;
1992
1993        if (kDrawLines_DrawType == type) {
1994            smoothLines = this->willUseHWAALines();
1995            if (smoothLines) {
1996                if (kYes_TriState != fHWAAState.fSmoothLineEnabled) {
1997                    GL_CALL(Enable(GR_GL_LINE_SMOOTH));
1998                    fHWAAState.fSmoothLineEnabled = kYes_TriState;
1999                    // must disable msaa to use line smoothing
2000                    if (rt->isMultisampled() &&
2001                        kNo_TriState != fHWAAState.fMSAAEnabled) {
2002                        GL_CALL(Disable(GR_GL_MULTISAMPLE));
2003                        fHWAAState.fMSAAEnabled = kNo_TriState;
2004                    }
2005                }
2006            } else {
2007                if (kNo_TriState != fHWAAState.fSmoothLineEnabled) {
2008                    GL_CALL(Disable(GR_GL_LINE_SMOOTH));
2009                    fHWAAState.fSmoothLineEnabled = kNo_TriState;
2010                }
2011            }
2012        }
2013        if (!smoothLines && rt->isMultisampled()) {
2014            // FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths
2015            // convex hulls of each segment appear to get filled.
2016            bool enableMSAA = kStencilPath_DrawType == type ||
2017                              this->getDrawState().isHWAntialiasState();
2018            if (enableMSAA) {
2019                if (kYes_TriState != fHWAAState.fMSAAEnabled) {
2020                    GL_CALL(Enable(GR_GL_MULTISAMPLE));
2021                    fHWAAState.fMSAAEnabled = kYes_TriState;
2022                }
2023            } else {
2024                if (kNo_TriState != fHWAAState.fMSAAEnabled) {
2025                    GL_CALL(Disable(GR_GL_MULTISAMPLE));
2026                    fHWAAState.fMSAAEnabled = kNo_TriState;
2027                }
2028            }
2029        }
2030    }
2031}
2032
2033void GrGpuGL::flushBlend(bool isLines,
2034                         GrBlendCoeff srcCoeff,
2035                         GrBlendCoeff dstCoeff) {
2036    if (isLines && this->willUseHWAALines()) {
2037        if (kYes_TriState != fHWBlendState.fEnabled) {
2038            GL_CALL(Enable(GR_GL_BLEND));
2039            fHWBlendState.fEnabled = kYes_TriState;
2040        }
2041        if (kSA_GrBlendCoeff != fHWBlendState.fSrcCoeff ||
2042            kISA_GrBlendCoeff != fHWBlendState.fDstCoeff) {
2043            GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_GrBlendCoeff],
2044                              gXfermodeCoeff2Blend[kISA_GrBlendCoeff]));
2045            fHWBlendState.fSrcCoeff = kSA_GrBlendCoeff;
2046            fHWBlendState.fDstCoeff = kISA_GrBlendCoeff;
2047        }
2048    } else {
2049        // any optimization to disable blending should
2050        // have already been applied and tweaked the coeffs
2051        // to (1, 0).
2052        bool blendOff = kOne_GrBlendCoeff == srcCoeff &&
2053                        kZero_GrBlendCoeff == dstCoeff;
2054        if (blendOff) {
2055            if (kNo_TriState != fHWBlendState.fEnabled) {
2056                GL_CALL(Disable(GR_GL_BLEND));
2057                fHWBlendState.fEnabled = kNo_TriState;
2058            }
2059        } else {
2060            if (kYes_TriState != fHWBlendState.fEnabled) {
2061                GL_CALL(Enable(GR_GL_BLEND));
2062                fHWBlendState.fEnabled = kYes_TriState;
2063            }
2064            if (fHWBlendState.fSrcCoeff != srcCoeff ||
2065                fHWBlendState.fDstCoeff != dstCoeff) {
2066                GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
2067                                  gXfermodeCoeff2Blend[dstCoeff]));
2068                fHWBlendState.fSrcCoeff = srcCoeff;
2069                fHWBlendState.fDstCoeff = dstCoeff;
2070            }
2071            GrColor blendConst = this->getDrawState().getBlendConstant();
2072            if ((BlendCoeffReferencesConstant(srcCoeff) ||
2073                 BlendCoeffReferencesConstant(dstCoeff)) &&
2074                (!fHWBlendState.fConstColorValid ||
2075                 fHWBlendState.fConstColor != blendConst)) {
2076
2077                float c[] = {
2078                    GrColorUnpackR(blendConst) / 255.f,
2079                    GrColorUnpackG(blendConst) / 255.f,
2080                    GrColorUnpackB(blendConst) / 255.f,
2081                    GrColorUnpackA(blendConst) / 255.f
2082                };
2083                GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
2084                fHWBlendState.fConstColor = blendConst;
2085                fHWBlendState.fConstColorValid = true;
2086            }
2087        }
2088    }
2089}
2090namespace {
2091
2092unsigned gr_to_gl_filter(GrSamplerState::Filter filter) {
2093    switch (filter) {
2094        case GrSamplerState::kBilinear_Filter:
2095            return GR_GL_LINEAR;
2096        case GrSamplerState::kNearest_Filter:
2097            return GR_GL_NEAREST;
2098        default:
2099            GrAssert(!"Unknown filter type");
2100            return GR_GL_LINEAR;
2101    }
2102}
2103
2104// get_swizzle is only called from this .cpp so it is OK to inline it here
2105inline const GrGLenum* get_swizzle(GrPixelConfig config,
2106                                   const GrSamplerState& sampler,
2107                                   const GrGLCaps& glCaps) {
2108    if (GrPixelConfigIsAlphaOnly(config)) {
2109        if (glCaps.textureRedSupport()) {
2110            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED,
2111                                                  GR_GL_RED, GR_GL_RED };
2112            return gRedSmear;
2113        } else {
2114            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
2115                                                    GR_GL_ALPHA, GR_GL_ALPHA };
2116            return gAlphaSmear;
2117        }
2118    } else if (sampler.swapsRAndB()) {
2119        static const GrGLenum gRedBlueSwap[] = { GR_GL_BLUE, GR_GL_GREEN,
2120                                                 GR_GL_RED,  GR_GL_ALPHA };
2121        return gRedBlueSwap;
2122    } else {
2123        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN,
2124                                              GR_GL_BLUE,  GR_GL_ALPHA };
2125        return gStraight;
2126    }
2127}
2128
2129void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) {
2130    GR_GL_CALL(gl, TexParameteriv(GR_GL_TEXTURE_2D,
2131                                  GR_GL_TEXTURE_SWIZZLE_RGBA,
2132                                  reinterpret_cast<const GrGLint*>(swizzle)));
2133}
2134}
2135
2136void GrGpuGL::flushBoundTextureAndParams(int stage) {
2137    GrDrawState* drawState = this->drawState();
2138
2139    GrGLTexture* nextTexture =
2140        static_cast<GrGLTexture*>(drawState->getTexture(stage));
2141
2142    // true for now, but maybe not with GrEffect.
2143    GrAssert(NULL != nextTexture);
2144    // if we created a rt/tex and rendered to it without using a
2145    // texture and now we're texturing from the rt it will still be
2146    // the last bound texture, but it needs resolving. So keep this
2147    // out of the "last != next" check.
2148    GrGLRenderTarget* texRT =
2149        static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
2150    if (NULL != texRT) {
2151        this->onResolveRenderTarget(texRT);
2152    }
2153
2154    if (fHWBoundTextures[stage] != nextTexture) {
2155        this->setTextureUnit(stage);
2156        GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
2157        //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
2158        fHWBoundTextures[stage] = nextTexture;
2159    }
2160
2161    const GrSamplerState& sampler = drawState->getSampler(stage);
2162    ResetTimestamp timestamp;
2163    const GrGLTexture::TexParams& oldTexParams =
2164                            nextTexture->getCachedTexParams(&timestamp);
2165    bool setAll = timestamp < this->getResetTimestamp();
2166    GrGLTexture::TexParams newTexParams;
2167
2168    newTexParams.fFilter = gr_to_gl_filter(sampler.getFilter());
2169
2170    const GrGLenum* wraps =  GrGLTexture::WrapMode2GLWrap();
2171    newTexParams.fWrapS = wraps[sampler.getWrapX()];
2172    newTexParams.fWrapT = wraps[sampler.getWrapY()];
2173    memcpy(newTexParams.fSwizzleRGBA,
2174           get_swizzle(nextTexture->config(), sampler, this->glCaps()),
2175           sizeof(newTexParams.fSwizzleRGBA));
2176    if (setAll || newTexParams.fFilter != oldTexParams.fFilter) {
2177        this->setTextureUnit(stage);
2178        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2179                              GR_GL_TEXTURE_MAG_FILTER,
2180                              newTexParams.fFilter));
2181        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2182                              GR_GL_TEXTURE_MIN_FILTER,
2183                              newTexParams.fFilter));
2184    }
2185    if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
2186        this->setTextureUnit(stage);
2187        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2188                              GR_GL_TEXTURE_WRAP_S,
2189                              newTexParams.fWrapS));
2190    }
2191    if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
2192        this->setTextureUnit(stage);
2193        GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2194                              GR_GL_TEXTURE_WRAP_T,
2195                              newTexParams.fWrapT));
2196    }
2197    if (this->glCaps().textureSwizzleSupport() &&
2198        (setAll || memcmp(newTexParams.fSwizzleRGBA,
2199                          oldTexParams.fSwizzleRGBA,
2200                          sizeof(newTexParams.fSwizzleRGBA)))) {
2201        this->setTextureUnit(stage);
2202        set_tex_swizzle(newTexParams.fSwizzleRGBA,
2203                        this->glInterface());
2204    }
2205    nextTexture->setCachedTexParams(newTexParams,
2206                                    this->getResetTimestamp());
2207}
2208
2209void GrGpuGL::flushMiscFixedFunctionState() {
2210
2211    const GrDrawState& drawState = this->getDrawState();
2212
2213    if (drawState.isDitherState()) {
2214        if (kYes_TriState != fHWDitherEnabled) {
2215            GL_CALL(Enable(GR_GL_DITHER));
2216            fHWDitherEnabled = kYes_TriState;
2217        }
2218    } else {
2219        if (kNo_TriState != fHWDitherEnabled) {
2220            GL_CALL(Disable(GR_GL_DITHER));
2221            fHWDitherEnabled = kNo_TriState;
2222        }
2223    }
2224
2225    if (drawState.isColorWriteDisabled()) {
2226        if (kNo_TriState != fHWWriteToColor) {
2227            GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE,
2228                              GR_GL_FALSE, GR_GL_FALSE));
2229            fHWWriteToColor = kNo_TriState;
2230        }
2231    } else {
2232        if (kYes_TriState != fHWWriteToColor) {
2233            GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
2234            fHWWriteToColor = kYes_TriState;
2235        }
2236    }
2237
2238    if (fHWDrawFace != drawState.getDrawFace()) {
2239        switch (this->getDrawState().getDrawFace()) {
2240            case GrDrawState::kCCW_DrawFace:
2241                GL_CALL(Enable(GR_GL_CULL_FACE));
2242                GL_CALL(CullFace(GR_GL_BACK));
2243                break;
2244            case GrDrawState::kCW_DrawFace:
2245                GL_CALL(Enable(GR_GL_CULL_FACE));
2246                GL_CALL(CullFace(GR_GL_FRONT));
2247                break;
2248            case GrDrawState::kBoth_DrawFace:
2249                GL_CALL(Disable(GR_GL_CULL_FACE));
2250                break;
2251            default:
2252                GrCrash("Unknown draw face.");
2253        }
2254        fHWDrawFace = drawState.getDrawFace();
2255    }
2256}
2257
2258void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
2259    if (fHWGeometryState.fVertexBuffer != buffer) {
2260        fHWGeometryState.fArrayPtrsDirty = true;
2261        fHWGeometryState.fVertexBuffer = buffer;
2262    }
2263}
2264
2265void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
2266    if (fHWGeometryState.fVertexBuffer == buffer) {
2267        // deleting bound buffer does implied bind to 0
2268        fHWGeometryState.fVertexBuffer = NULL;
2269        fHWGeometryState.fArrayPtrsDirty = true;
2270    }
2271}
2272
2273void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
2274    fHWGeometryState.fIndexBuffer = buffer;
2275}
2276
2277void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
2278    if (fHWGeometryState.fIndexBuffer == buffer) {
2279        // deleting bound buffer does implied bind to 0
2280        fHWGeometryState.fIndexBuffer = NULL;
2281    }
2282}
2283
2284void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
2285    GrAssert(NULL != renderTarget);
2286    if (fHWBoundRenderTarget == renderTarget) {
2287        fHWBoundRenderTarget = NULL;
2288    }
2289}
2290
2291void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
2292    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
2293        if (fHWBoundTextures[s] == texture) {
2294            // deleting bound texture does implied bind to 0
2295            fHWBoundTextures[s] = NULL;
2296       }
2297    }
2298}
2299
2300bool GrGpuGL::configToGLFormats(GrPixelConfig config,
2301                                bool getSizedInternalFormat,
2302                                GrGLenum* internalFormat,
2303                                GrGLenum* externalFormat,
2304                                GrGLenum* externalType) {
2305    GrGLenum dontCare;
2306    if (NULL == internalFormat) {
2307        internalFormat = &dontCare;
2308    }
2309    if (NULL == externalFormat) {
2310        externalFormat = &dontCare;
2311    }
2312    if (NULL == externalType) {
2313        externalType = &dontCare;
2314    }
2315
2316    switch (config) {
2317        case kRGBA_8888_PM_GrPixelConfig:
2318        case kRGBA_8888_UPM_GrPixelConfig:
2319            *internalFormat = GR_GL_RGBA;
2320            *externalFormat = GR_GL_RGBA;
2321            if (getSizedInternalFormat) {
2322                *internalFormat = GR_GL_RGBA8;
2323            } else {
2324                *internalFormat = GR_GL_RGBA;
2325            }
2326            *externalType = GR_GL_UNSIGNED_BYTE;
2327            break;
2328        case kBGRA_8888_PM_GrPixelConfig:
2329        case kBGRA_8888_UPM_GrPixelConfig:
2330            if (!this->glCaps().bgraFormatSupport()) {
2331                return false;
2332            }
2333            if (this->glCaps().bgraIsInternalFormat()) {
2334                if (getSizedInternalFormat) {
2335                    *internalFormat = GR_GL_BGRA8;
2336                } else {
2337                    *internalFormat = GR_GL_BGRA;
2338                }
2339            } else {
2340                if (getSizedInternalFormat) {
2341                    *internalFormat = GR_GL_RGBA8;
2342                } else {
2343                    *internalFormat = GR_GL_RGBA;
2344                }
2345            }
2346            *externalFormat = GR_GL_BGRA;
2347            *externalType = GR_GL_UNSIGNED_BYTE;
2348            break;
2349        case kRGB_565_GrPixelConfig:
2350            *internalFormat = GR_GL_RGB;
2351            *externalFormat = GR_GL_RGB;
2352            if (getSizedInternalFormat) {
2353                if (this->glBinding() == kDesktop_GrGLBinding) {
2354                    return false;
2355                } else {
2356                    *internalFormat = GR_GL_RGB565;
2357                }
2358            } else {
2359                *internalFormat = GR_GL_RGB;
2360            }
2361            *externalType = GR_GL_UNSIGNED_SHORT_5_6_5;
2362            break;
2363        case kRGBA_4444_GrPixelConfig:
2364            *internalFormat = GR_GL_RGBA;
2365            *externalFormat = GR_GL_RGBA;
2366            if (getSizedInternalFormat) {
2367                *internalFormat = GR_GL_RGBA4;
2368            } else {
2369                *internalFormat = GR_GL_RGBA;
2370            }
2371            *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
2372            break;
2373        case kIndex_8_GrPixelConfig:
2374            if (this->getCaps().f8BitPaletteSupport) {
2375                *internalFormat = GR_GL_PALETTE8_RGBA8;
2376                // glCompressedTexImage doesn't take external params
2377                *externalFormat = GR_GL_PALETTE8_RGBA8;
2378                // no sized/unsized internal format distinction here
2379                *internalFormat = GR_GL_PALETTE8_RGBA8;
2380                // unused with CompressedTexImage
2381                *externalType = GR_GL_UNSIGNED_BYTE;
2382            } else {
2383                return false;
2384            }
2385            break;
2386        case kAlpha_8_GrPixelConfig:
2387            if (this->glCaps().textureRedSupport()) {
2388                *internalFormat = GR_GL_RED;
2389                *externalFormat = GR_GL_RED;
2390                if (getSizedInternalFormat) {
2391                    *internalFormat = GR_GL_R8;
2392                } else {
2393                    *internalFormat = GR_GL_RED;
2394                }
2395                *externalType = GR_GL_UNSIGNED_BYTE;
2396            } else {
2397                *internalFormat = GR_GL_ALPHA;
2398                *externalFormat = GR_GL_ALPHA;
2399                if (getSizedInternalFormat) {
2400                    *internalFormat = GR_GL_ALPHA8;
2401                } else {
2402                    *internalFormat = GR_GL_ALPHA;
2403                }
2404                *externalType = GR_GL_UNSIGNED_BYTE;
2405            }
2406            break;
2407        default:
2408            return false;
2409    }
2410    return true;
2411}
2412
2413void GrGpuGL::setTextureUnit(int unit) {
2414    GrAssert(unit >= 0 && unit < GrDrawState::kNumStages);
2415    if (fHWActiveTextureUnitIdx != unit) {
2416        GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
2417        fHWActiveTextureUnitIdx = unit;
2418    }
2419}
2420
2421void GrGpuGL::setSpareTextureUnit() {
2422    if (fHWActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2423        GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
2424        fHWActiveTextureUnitIdx = SPARE_TEX_UNIT;
2425    }
2426}
2427
2428void GrGpuGL::setBuffers(bool indexed,
2429                         int* extraVertexOffset,
2430                         int* extraIndexOffset) {
2431
2432    GrAssert(NULL != extraVertexOffset);
2433
2434    const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2435
2436    GrGLVertexBuffer* vbuf;
2437    switch (this->getGeomSrc().fVertexSrc) {
2438    case kBuffer_GeometrySrcType:
2439        *extraVertexOffset = 0;
2440        vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
2441        break;
2442    case kArray_GeometrySrcType:
2443    case kReserved_GeometrySrcType:
2444        this->finalizeReservedVertices();
2445        *extraVertexOffset = geoPoolState.fPoolStartVertex;
2446        vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
2447        break;
2448    default:
2449        vbuf = NULL; // suppress warning
2450        GrCrash("Unknown geometry src type!");
2451    }
2452
2453    GrAssert(NULL != vbuf);
2454    GrAssert(!vbuf->isLocked());
2455    if (fHWGeometryState.fVertexBuffer != vbuf) {
2456        GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
2457        fHWGeometryState.fArrayPtrsDirty = true;
2458        fHWGeometryState.fVertexBuffer = vbuf;
2459    }
2460
2461    if (indexed) {
2462        GrAssert(NULL != extraIndexOffset);
2463
2464        GrGLIndexBuffer* ibuf;
2465        switch (this->getGeomSrc().fIndexSrc) {
2466        case kBuffer_GeometrySrcType:
2467            *extraIndexOffset = 0;
2468            ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
2469            break;
2470        case kArray_GeometrySrcType:
2471        case kReserved_GeometrySrcType:
2472            this->finalizeReservedIndices();
2473            *extraIndexOffset = geoPoolState.fPoolStartIndex;
2474            ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
2475            break;
2476        default:
2477            ibuf = NULL; // suppress warning
2478            GrCrash("Unknown geometry src type!");
2479        }
2480
2481        GrAssert(NULL != ibuf);
2482        GrAssert(!ibuf->isLocked());
2483        if (fHWGeometryState.fIndexBuffer != ibuf) {
2484            GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
2485            fHWGeometryState.fIndexBuffer = ibuf;
2486        }
2487    }
2488}
2489
2490