Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 
      9 #include "GrNonAtomicRef.h"
     10 #include "gl/GrGLInterface.h"
     11 #include "GrGLTestInterface.h"
     12 #include "SkMutex.h"
     13 #include "SkTDArray.h"
     14 #include <type_traits>
     15 
     16 // added to suppress 'no previous prototype' warning and because this code is duplicated in
     17 // SkNullGLContext.cpp
     18 namespace {
     19 
     20 class GLObject : public GrNonAtomicRef<GLObject> {
     21 public:
     22     GLObject(GrGLuint id) : fID(id) {}
     23     virtual ~GLObject() {}
     24 
     25     GrGLuint id() const { return fID; }
     26 
     27 private:
     28     GrGLuint fID;
     29 };
     30 
     31 // This class maintains a sparsely populated array of object pointers.
     32 template<typename T> class TGLObjectManager {
     33    static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject");
     34 
     35 public:
     36     TGLObjectManager() : fFreeListHead(kFreeListEnd) {
     37         *fGLObjects.append() = nullptr; // 0 is not a valid GL object id.
     38     }
     39 
     40     ~TGLObjectManager() {
     41         // nullptr out the entries that are really free list links rather than ptrs before deleting.
     42         intptr_t curr = fFreeListHead;
     43         while (kFreeListEnd != curr) {
     44             intptr_t next = reinterpret_cast<intptr_t>(fGLObjects[SkToS32(curr)]);
     45             fGLObjects[SkToS32(curr)] = nullptr;
     46             curr = next;
     47         }
     48 
     49         fGLObjects.safeUnrefAll();
     50     }
     51 
     52     T* lookUp(GrGLuint id) {
     53         T* object = fGLObjects[id];
     54         SkASSERT(object && object->id() == id);
     55         return object;
     56     }
     57 
     58     T* create() {
     59         GrGLuint id;
     60         T* object;
     61 
     62         if (kFreeListEnd == fFreeListHead) {
     63             // no free slots - create a new one
     64             id = fGLObjects.count();
     65             object = new T(id);
     66             *fGLObjects.append() = object;
     67         } else {
     68             // grab the head of the free list and advance the head to the next free slot.
     69             id = static_cast<GrGLuint>(fFreeListHead);
     70             fFreeListHead = reinterpret_cast<intptr_t>(fGLObjects[id]);
     71 
     72             object = new T(id);
     73             fGLObjects[id] = object;
     74         }
     75 
     76         return object;
     77     }
     78 
     79     void free(T* object) {
     80         SkASSERT(object);
     81         SkASSERT(fGLObjects.count() > 0);
     82 
     83         GrGLuint id = object->id();
     84         object->unref();
     85 
     86         fGLObjects[id] = reinterpret_cast<T*>(fFreeListHead);
     87         fFreeListHead = id;
     88     }
     89 
     90 private:
     91     static const intptr_t kFreeListEnd = -1;
     92     // Index of the first entry of fGLObjects in the free list. Free slots in fGLObjects are indices
     93     // to the next free slot. The last free slot has a value of kFreeListEnd.
     94     intptr_t        fFreeListHead;
     95     SkTDArray<T*>   fGLObjects;
     96 };
     97 
     98 class Buffer : public GLObject {
     99 public:
    100     Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {}
    101     ~Buffer() { delete[] fDataPtr; }
    102 
    103     void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
    104         if (fDataPtr) {
    105             SkASSERT(0 != fSize);
    106             delete[] fDataPtr;
    107         }
    108 
    109         fSize = size;
    110         fDataPtr = new char[size];
    111     }
    112 
    113     GrGLchar* dataPtr()          { return fDataPtr; }
    114     GrGLsizeiptr size() const    { return fSize; }
    115 
    116     void setMapped(bool mapped)  { fMapped = mapped; }
    117     bool mapped() const          { return fMapped; }
    118 
    119 private:
    120     GrGLchar*    fDataPtr;
    121     GrGLsizeiptr fSize;         // size in bytes
    122     bool         fMapped;
    123 
    124     typedef GLObject INHERITED;
    125 };
    126 
    127 class FramebufferAttachment : public GLObject {
    128 public:
    129     int numSamples() const { return fNumSamples; }
    130 
    131 protected:
    132     FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {}
    133 
    134     int fNumSamples;
    135 
    136     typedef GLObject INHERITED;
    137 };
    138 
    139 class Renderbuffer : public FramebufferAttachment {
    140 public:
    141     Renderbuffer(int id) : INHERITED(id) {}
    142     void setNumSamples(int numSamples) { fNumSamples = numSamples; }
    143 
    144 private:
    145     typedef FramebufferAttachment INHERITED;
    146 };
    147 
    148 class Texture : public FramebufferAttachment {
    149 public:
    150     Texture() : INHERITED(1) {}
    151 
    152 private:
    153     typedef FramebufferAttachment INHERITED;
    154 };
    155 
    156 class Framebuffer : public GLObject {
    157 public:
    158     Framebuffer(int id) : INHERITED(id) {}
    159 
    160     void setAttachment(GrGLenum attachmentPoint, const FramebufferAttachment* attachment) {
    161         switch (attachmentPoint) {
    162             default:
    163                 SK_ABORT("Invalid framebuffer attachment.");
    164                 break;
    165             case GR_GL_STENCIL_ATTACHMENT:
    166                 fAttachments[(int)AttachmentPoint::kStencil].reset(SkRef(attachment));
    167                 break;
    168             case GR_GL_DEPTH_ATTACHMENT:
    169                 fAttachments[(int)AttachmentPoint::kDepth].reset(SkRef(attachment));
    170                 break;
    171             case GR_GL_COLOR_ATTACHMENT0:
    172                 fAttachments[(int)AttachmentPoint::kColor].reset(SkRef(attachment));
    173                 break;
    174         }
    175     }
    176 
    177     void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
    178         for (auto& attachment : fAttachments) {
    179             if (attachment.get() == deleted) {
    180                 attachment.reset(nullptr);
    181             }
    182         }
    183     }
    184 
    185     int numSamples() const {
    186         int numSamples = 0;
    187         for (auto& attachment : fAttachments) {
    188             if (!attachment) {
    189                 continue;
    190             }
    191             if (numSamples) {
    192                 GrAlwaysAssert(attachment->numSamples() == numSamples);
    193                 continue;
    194             }
    195             numSamples = attachment->numSamples();
    196         }
    197         GrAlwaysAssert(numSamples);
    198         return numSamples;
    199     }
    200 
    201 private:
    202     enum AttachmentPoint {
    203         kStencil,
    204         kDepth,
    205         kColor
    206     };
    207     constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor;
    208 
    209     sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints];
    210 
    211     typedef GLObject INHERITED;
    212 };
    213 
    214 /** Null interface implementation */
    215 class NullInterface : public GrGLTestInterface {
    216 public:
    217     NullInterface(bool enableNVPR)
    218         : fCurrDrawFramebuffer(0)
    219         , fCurrReadFramebuffer(0)
    220         , fCurrRenderbuffer(0)
    221         , fCurrProgramID(0)
    222         , fCurrShaderID(0)
    223         , fCurrGenericID(0)
    224         , fCurrUniformLocation(0)
    225         , fCurrPathID(0) {
    226         memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
    227         fAdvertisedExtensions.push_back("GL_ARB_framebuffer_object");
    228         fAdvertisedExtensions.push_back("GL_ARB_blend_func_extended");
    229         fAdvertisedExtensions.push_back("GL_ARB_timer_query");
    230         fAdvertisedExtensions.push_back("GL_ARB_draw_buffers");
    231         fAdvertisedExtensions.push_back("GL_ARB_occlusion_query");
    232         fAdvertisedExtensions.push_back("GL_EXT_stencil_wrap");
    233         if (enableNVPR) {
    234             fAdvertisedExtensions.push_back("GL_NV_path_rendering");
    235             fAdvertisedExtensions.push_back("GL_ARB_program_interface_query");
    236         }
    237         fAdvertisedExtensions.push_back(nullptr);
    238 
    239         this->init(kGL_GrGLStandard);
    240     }
    241 
    242     GrGLenum checkFramebufferStatus(GrGLenum target) override {
    243         return GR_GL_FRAMEBUFFER_COMPLETE;
    244     }
    245 
    246     GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
    247         for (int i = 0; i < n; ++i) {
    248             Buffer* buffer = fBufferManager.create();
    249             ids[i] = buffer->id();
    250         }
    251     }
    252 
    253     GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
    254                         GrGLenum usage) override {
    255         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
    256         if (id > 0) {
    257             Buffer* buffer = fBufferManager.lookUp(id);
    258             buffer->allocate(size, (const GrGLchar*) data);
    259         }
    260     }
    261 
    262     GrGLuint createProgram() override {
    263         return ++fCurrProgramID;
    264     }
    265 
    266     GrGLuint createShader(GrGLenum type) override {
    267         return ++fCurrShaderID;
    268     }
    269 
    270     GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) override {
    271         fBoundBuffers[GetBufferIndex(target)] = buffer;
    272     }
    273 
    274    // deleting a bound buffer has the side effect of binding 0
    275    GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override {
    276         // First potentially unbind the buffers.
    277         for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) {
    278             if (!fBoundBuffers[buffIdx]) {
    279                 continue;
    280             }
    281             for (int i = 0; i < n; ++i) {
    282                 if (ids[i] == fBoundBuffers[buffIdx]) {
    283                     fBoundBuffers[buffIdx] = 0;
    284                     break;
    285                 }
    286             }
    287         }
    288 
    289         // Then actually "delete" the buffers.
    290         for (int i = 0; i < n; ++i) {
    291             if (ids[i] > 0) {
    292                 Buffer* buffer = fBufferManager.lookUp(ids[i]);
    293                 fBufferManager.free(buffer);
    294             }
    295         }
    296     }
    297 
    298     GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override {
    299         for (int i = 0; i < n; ++i) {
    300             Framebuffer* framebuffer = fFramebufferManager.create();
    301             framebuffers[i] = framebuffer->id();
    302         }
    303     }
    304 
    305     GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint framebuffer) override {
    306         SkASSERT(GR_GL_FRAMEBUFFER == target || GR_GL_DRAW_FRAMEBUFFER == target ||
    307                  GR_GL_READ_FRAMEBUFFER == target);
    308         if (GR_GL_READ_FRAMEBUFFER != target) {
    309             fCurrDrawFramebuffer = framebuffer;
    310         }
    311         if (GR_GL_DRAW_FRAMEBUFFER != target) {
    312             fCurrReadFramebuffer = framebuffer;
    313         }
    314     }
    315 
    316     GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint* ids) override {
    317         for (int i = 0; i < n; ++i) {
    318             if (ids[i] == fCurrDrawFramebuffer) {
    319                 fCurrDrawFramebuffer = 0;
    320             }
    321             if (ids[i] == fCurrReadFramebuffer) {
    322                 fCurrReadFramebuffer = 0;
    323             }
    324 
    325             if (ids[i] > 0) {
    326                 Framebuffer* framebuffer = fFramebufferManager.lookUp(ids[i]);
    327                 fFramebufferManager.free(framebuffer);
    328             }
    329         }
    330     }
    331 
    332     GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
    333 
    334     GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override {
    335         for (int i = 0; i < n; ++i) {
    336             Renderbuffer* renderbuffer = fRenderbufferManager.create();
    337             renderbuffers[i] = renderbuffer->id();
    338         }
    339     }
    340 
    341     GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override {
    342         SkASSERT(GR_GL_RENDERBUFFER == target);
    343         fCurrRenderbuffer = renderbuffer;
    344     }
    345 
    346     GrGLvoid deleteRenderbuffers(GrGLsizei n, const GrGLuint* ids) override {
    347         for (int i = 0; i < n; ++i) {
    348             if (ids[i] <= 0) {
    349                 continue;
    350             }
    351             if (ids[i] == fCurrRenderbuffer) {
    352                 fCurrRenderbuffer = 0;
    353             }
    354             Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(ids[i]);
    355 
    356             if (fCurrDrawFramebuffer) {
    357                 Framebuffer* drawFramebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
    358                 drawFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
    359             }
    360             if (fCurrReadFramebuffer) {
    361                 Framebuffer* readFramebuffer = fFramebufferManager.lookUp(fCurrReadFramebuffer);
    362                 readFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
    363             }
    364 
    365             fRenderbufferManager.free(renderbuffer);
    366         }
    367     }
    368 
    369     GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width,
    370                                  GrGLsizei height) override {
    371         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
    372         GrAlwaysAssert(fCurrRenderbuffer);
    373         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
    374         renderbuffer->setNumSamples(1);
    375     }
    376 
    377     GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples,
    378                                             GrGLenum internalformat, GrGLsizei width,
    379                                             GrGLsizei height) override {
    380         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
    381         GrAlwaysAssert(samples > 0);
    382         GrAlwaysAssert(fCurrRenderbuffer);
    383         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
    384         renderbuffer->setNumSamples(samples);
    385     }
    386 
    387     GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
    388                                       GrGLsizei width, GrGLsizei height) override {
    389         SK_ABORT("Not implemented");
    390     }
    391 
    392     GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
    393                                                  GrGLenum GrGLinternalformat, GrGLsizei width,
    394                                                  GrGLsizei height) override {
    395         SK_ABORT("Not implemented");
    396     }
    397 
    398     GrGLvoid framebufferRenderbuffer(GrGLenum target, GrGLenum attachment,
    399                                      GrGLenum renderbuffertarget,
    400                                      GrGLuint renderBufferID) override {
    401         GrGLuint id = this->getBoundFramebufferID(target);
    402         GrAlwaysAssert(id);
    403         Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
    404 
    405         GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
    406         GrAlwaysAssert(fCurrRenderbuffer);
    407         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
    408 
    409         framebuffer->setAttachment(attachment, renderbuffer);
    410     }
    411 
    412     GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
    413                                           GrGLenum renderbuffertarget,
    414                                           GrGLuint renderbuffer) override {
    415         SK_ABORT("Not implemented");
    416     }
    417 
    418     GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
    419         this->genGenericIds(n, textures);
    420     }
    421 
    422     GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
    423                                   GrGLuint textureID, GrGLint level) override {
    424         GrGLuint id = this->getBoundFramebufferID(target);
    425         GrAlwaysAssert(id);
    426         Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
    427         framebuffer->setAttachment(attachment, this->getSingleTextureObject());
    428     }
    429 
    430     GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
    431                                              GrGLenum textarget, GrGLuint texture, GrGLint level,
    432                                              GrGLsizei samples) override {
    433         SK_ABORT("Not implemented");
    434     }
    435 
    436     GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
    437                                        GrGLenum textarget, GrGLuint texture,
    438                                        GrGLint level) override {
    439         SK_ABORT("Not implemented");
    440     }
    441 
    442     GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
    443                                        GrGLenum textarget, GrGLuint texture,
    444                                        GrGLint level) override {
    445         SK_ABORT("Not implemented");
    446     }
    447 
    448     GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
    449                                        GrGLenum textarget, GrGLuint texture, GrGLint level,
    450                                        GrGLint zoffset) override {
    451         SK_ABORT("Not implemented");
    452     }
    453 
    454     GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
    455         this->genGenericIds(n, arrays);
    456     }
    457 
    458     GrGLenum getError() override { return GR_GL_NO_ERROR; }
    459 
    460     GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
    461         // TODO: remove from Ganesh the #defines for gets we don't use.
    462         // We would like to minimize gets overall due to performance issues
    463         switch (pname) {
    464             case GR_GL_CONTEXT_PROFILE_MASK:
    465                 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
    466                 break;
    467             case GR_GL_STENCIL_BITS:
    468                 *params = 8;
    469                 break;
    470             case GR_GL_SAMPLES: {
    471                 GrAlwaysAssert(fCurrDrawFramebuffer);
    472                 Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
    473                 *params = framebuffer->numSamples();
    474                 break;
    475             }
    476             case GR_GL_FRAMEBUFFER_BINDING:
    477                 *params = 0;
    478                 break;
    479             case GR_GL_VIEWPORT:
    480                 params[0] = 0;
    481                 params[1] = 0;
    482                 params[2] = 800;
    483                 params[3] = 600;
    484                 break;
    485             case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    486             case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
    487             case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
    488             case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    489                 *params = 8;
    490                 break;
    491             case GR_GL_MAX_TEXTURE_COORDS:
    492                 *params = 8;
    493                 break;
    494             case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
    495                 *params = kDefaultMaxVertexUniformVectors;
    496                 break;
    497             case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
    498                 *params = kDefaultMaxFragmentUniformVectors;
    499                 break;
    500             case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
    501                 *params = 16 * 4;
    502                 break;
    503             case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    504                 *params = 0;
    505                 break;
    506             case GR_GL_COMPRESSED_TEXTURE_FORMATS:
    507                 break;
    508             case GR_GL_MAX_TEXTURE_SIZE:
    509                 *params = 8192;
    510                 break;
    511             case GR_GL_MAX_RENDERBUFFER_SIZE:
    512                 *params = 8192;
    513                 break;
    514             case GR_GL_MAX_SAMPLES:
    515                 *params = 32;
    516                 break;
    517             case GR_GL_MAX_VERTEX_ATTRIBS:
    518                 *params = kDefaultMaxVertexAttribs;
    519                 break;
    520             case GR_GL_MAX_VARYING_VECTORS:
    521                 *params = kDefaultMaxVaryingVectors;
    522                 break;
    523             case GR_GL_NUM_EXTENSIONS: {
    524                 GrGLint i = 0;
    525                 while (fAdvertisedExtensions[i++]);
    526                 *params = i;
    527                 break;
    528             }
    529             default:
    530                 SkFAIL("Unexpected pname to GetIntegerv");
    531         }
    532     }
    533 
    534     GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
    535         this->getShaderOrProgramiv(program, pname, params);
    536     }
    537 
    538     GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
    539                                char* infolog) override {
    540         this->getInfoLog(program, bufsize, length, infolog);
    541     }
    542 
    543     GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
    544         val[0] = val[1] = 0.5f;
    545     }
    546 
    547     GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
    548         switch (pname) {
    549             case GR_GL_CURRENT_QUERY:
    550                 *params = 0;
    551                 break;
    552             case GR_GL_QUERY_COUNTER_BITS:
    553                 *params = 32;
    554                 break;
    555             default:
    556                 SkFAIL("Unexpected pname passed GetQueryiv.");
    557         }
    558     }
    559 
    560     GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
    561         this->queryResult(id, pname, params);
    562     }
    563 
    564     GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
    565         this->queryResult(id, pname, params);
    566     }
    567 
    568     GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
    569         this->queryResult(id, pname, params);
    570     }
    571 
    572     GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
    573         this->queryResult(id, pname, params);
    574     }
    575 
    576     GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
    577         this->getShaderOrProgramiv(shader, pname, params);
    578     }
    579 
    580     GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
    581                               char* infolog) override {
    582         this->getInfoLog(shader, bufsize, length, infolog);
    583     }
    584 
    585     const GrGLubyte* getString(GrGLenum name) override {
    586         switch (name) {
    587             case GR_GL_EXTENSIONS:
    588                 return CombinedExtensionString();
    589             case GR_GL_VERSION:
    590                 return (const GrGLubyte*)"4.0 Null GL";
    591             case GR_GL_SHADING_LANGUAGE_VERSION:
    592                 return (const GrGLubyte*)"4.20.8 Null GLSL";
    593             case GR_GL_VENDOR:
    594                 return (const GrGLubyte*)"Null Vendor";
    595             case GR_GL_RENDERER:
    596                 return (const GrGLubyte*)"The Null (Non-)Renderer";
    597             default:
    598                 SkFAIL("Unexpected name passed to GetString");
    599                 return nullptr;
    600         }
    601     }
    602 
    603     const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
    604         switch (name) {
    605             case GR_GL_EXTENSIONS: {
    606                 GrGLint count;
    607                 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
    608                 if ((GrGLint)i <= count) {
    609                     return (const GrGLubyte*) fAdvertisedExtensions[i];
    610                 } else {
    611                     return nullptr;
    612                 }
    613             }
    614             default:
    615                 SkFAIL("Unexpected name passed to GetStringi");
    616                 return nullptr;
    617         }
    618     }
    619 
    620     GrGLint getUniformLocation(GrGLuint program, const char* name) override {
    621         return ++fCurrUniformLocation;
    622     }
    623 
    624     GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
    625                              GrGLbitfield access) override {
    626         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
    627         if (id > 0) {
    628             // We just ignore the offset and length here.
    629             Buffer* buffer = fBufferManager.lookUp(id);
    630             SkASSERT(!buffer->mapped());
    631             buffer->setMapped(true);
    632             return buffer->dataPtr();
    633         }
    634         return nullptr;
    635     }
    636 
    637     GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
    638         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
    639         if (id > 0) {
    640             Buffer* buffer = fBufferManager.lookUp(id);
    641             SkASSERT(!buffer->mapped());
    642             buffer->setMapped(true);
    643             return buffer->dataPtr();
    644         }
    645 
    646         SkASSERT(false);
    647         return nullptr;            // no buffer bound to target
    648     }
    649 
    650     GrGLboolean unmapBuffer(GrGLenum target) override {
    651         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
    652         if (id > 0) {
    653             Buffer* buffer = fBufferManager.lookUp(id);
    654             SkASSERT(buffer->mapped());
    655             buffer->setMapped(false);
    656             return GR_GL_TRUE;
    657         }
    658 
    659         GrAlwaysAssert(false);
    660         return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
    661     }
    662 
    663     GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override {
    664         switch (pname) {
    665             case GR_GL_BUFFER_MAPPED: {
    666                 *params = GR_GL_FALSE;
    667                 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
    668                 if (id > 0) {
    669                     Buffer* buffer = fBufferManager.lookUp(id);
    670                     if (buffer->mapped()) {
    671                         *params = GR_GL_TRUE;
    672                     }
    673                 }
    674                 break; }
    675             default:
    676                 SkFAIL("Unexpected pname to GetBufferParamateriv");
    677                 break;
    678         }
    679     }
    680 
    681     // NV_path_rendering
    682     GrGLuint genPaths(GrGLsizei range) override {
    683         return ++fCurrPathID;
    684     }
    685 
    686 
    687 private:
    688     inline int static GetBufferIndex(GrGLenum glTarget) {
    689         switch (glTarget) {
    690             default:                           SkFAIL("Unexpected GL target to GetBufferIndex");
    691             case GR_GL_ARRAY_BUFFER:           return 0;
    692             case GR_GL_ELEMENT_ARRAY_BUFFER:   return 1;
    693             case GR_GL_TEXTURE_BUFFER:         return 2;
    694             case GR_GL_DRAW_INDIRECT_BUFFER:   return 3;
    695             case GR_GL_PIXEL_PACK_BUFFER:      return 4;
    696             case GR_GL_PIXEL_UNPACK_BUFFER:    return 5;
    697         }
    698     }
    699     constexpr int static kNumBufferTargets = 6;
    700 
    701     TGLObjectManager<Buffer>         fBufferManager;
    702     GrGLuint                         fBoundBuffers[kNumBufferTargets];
    703     TGLObjectManager<Framebuffer>    fFramebufferManager;
    704     GrGLuint                         fCurrDrawFramebuffer;
    705     GrGLuint                         fCurrReadFramebuffer;
    706     TGLObjectManager<Renderbuffer>   fRenderbufferManager;
    707     GrGLuint                         fCurrRenderbuffer;
    708     GrGLuint                         fCurrProgramID;
    709     GrGLuint                         fCurrShaderID;
    710     GrGLuint                         fCurrGenericID;
    711     GrGLuint                         fCurrUniformLocation;
    712     GrGLuint                         fCurrPathID;
    713     sk_sp<const Texture>             fSingleTextureObject;
    714     SkTArray<const char*>            fAdvertisedExtensions;
    715 
    716     // the OpenGLES 2.0 spec says this must be >= 128
    717     static const GrGLint kDefaultMaxVertexUniformVectors = 128;
    718 
    719     // the OpenGLES 2.0 spec says this must be >=16
    720     static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
    721 
    722     // the OpenGLES 2.0 spec says this must be >= 8
    723     static const GrGLint kDefaultMaxVertexAttribs = 8;
    724 
    725     // the OpenGLES 2.0 spec says this must be >= 8
    726     static const GrGLint kDefaultMaxVaryingVectors = 8;
    727 
    728     GrGLuint getBoundFramebufferID(GrGLenum target) {
    729         switch (target) {
    730             case GR_GL_FRAMEBUFFER:
    731             case GR_GL_DRAW_FRAMEBUFFER:
    732                 return fCurrDrawFramebuffer;
    733             case GR_GL_READ_FRAMEBUFFER:
    734                 return fCurrReadFramebuffer;
    735             default:
    736                 SK_ABORT("Invalid framebuffer target.");
    737                 return 0;
    738         }
    739     }
    740 
    741     const Texture* getSingleTextureObject() {
    742         // We currently only use FramebufferAttachment objects for a sample count, and all textures
    743         // in Skia have one sample, so there is no need as of yet to track individual textures. This
    744         // also works around a bug in chromium's cc_unittests where they send us texture IDs that
    745         // were generated by cc::TestGLES2Interface.
    746         if (!fSingleTextureObject) {
    747             fSingleTextureObject.reset(new Texture);
    748         }
    749         return fSingleTextureObject.get();
    750     }
    751 
    752     const GrGLubyte* CombinedExtensionString() {
    753         static SkString gExtString;
    754         static SkMutex gMutex;
    755         gMutex.acquire();
    756         if (0 == gExtString.size()) {
    757             int i = 0;
    758             while (fAdvertisedExtensions[i]) {
    759                 if (i > 0) {
    760                     gExtString.append(" ");
    761                 }
    762                 gExtString.append(fAdvertisedExtensions[i]);
    763                 ++i;
    764             }
    765         }
    766         gMutex.release();
    767         return (const GrGLubyte*) gExtString.c_str();
    768     }
    769 
    770     GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
    771         for (int i = 0; i < n; ++i) {
    772             ids[i] = ++fCurrGenericID;
    773         }
    774     }
    775 
    776     GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
    777                         char* infolog) {
    778         if (length) {
    779             *length = 0;
    780         }
    781         if (bufsize > 0) {
    782             *infolog = 0;
    783         }
    784     }
    785 
    786     GrGLvoid getShaderOrProgramiv(GrGLuint object,  GrGLenum pname, GrGLint* params) {
    787         switch (pname) {
    788             case GR_GL_LINK_STATUS:  // fallthru
    789             case GR_GL_COMPILE_STATUS:
    790                 *params = GR_GL_TRUE;
    791                 break;
    792             case GR_GL_INFO_LOG_LENGTH:
    793                 *params = 0;
    794                 break;
    795                 // we don't expect any other pnames
    796             default:
    797                 SkFAIL("Unexpected pname to GetProgramiv");
    798                 break;
    799         }
    800     }
    801 
    802     template <typename T>
    803     void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
    804         switch (pname) {
    805             case GR_GL_QUERY_RESULT_AVAILABLE:
    806                 *params = GR_GL_TRUE;
    807                 break;
    808             case GR_GL_QUERY_RESULT:
    809                 *params = 0;
    810                 break;
    811             default:
    812                 SkFAIL("Unexpected pname passed to GetQueryObject.");
    813                 break;
    814         }
    815     }
    816 
    817     typedef GrGLTestInterface INHERITED;
    818 };
    819 
    820 }  // anonymous namespace
    821 
    822 const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); }
    823