Home | History | Annotate | Download | only in debug
      1 
      2 /*
      3  * Copyright 2012 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "DebugGLTestContext.h"
     10 
     11 #include "GrBufferObj.h"
     12 #include "GrFrameBufferObj.h"
     13 #include "GrProgramObj.h"
     14 #include "GrRenderBufferObj.h"
     15 #include "GrShaderObj.h"
     16 #include "GrTextureObj.h"
     17 #include "GrTextureUnitObj.h"
     18 #include "GrVertexArrayObj.h"
     19 #include "gl/GrGLTestInterface.h"
     20 
     21 #include "SkMutex.h"
     22 
     23 namespace {
     24 
     25 // Helper macro to make creating an object (where you need to get back a derived type) easier
     26 #define CREATE(className, classEnum)                     \
     27     reinterpret_cast<className *>(this->createObj(classEnum))
     28 
     29 // Helper macro to make creating an object (where you need to get back a derived type) easier
     30 #define FIND(id, className, classEnum)                   \
     31     reinterpret_cast<className *>(this->findObject(id, classEnum))
     32 
     33 class DebugInterface : public GrGLTestInterface {
     34 public:
     35     DebugInterface()
     36         : fCurrGenericID(0)
     37         , fCurrTextureUnit(0)
     38         , fVertexArray(nullptr)
     39         , fPackRowLength(0)
     40         , fUnpackRowLength(0)
     41         , fPackAlignment(4)
     42         , fFrameBuffer(nullptr)
     43         , fRenderBuffer(nullptr)
     44         , fProgram(nullptr)
     45         , fAbandoned(false) {
     46         for (int i = 0; i < kDefaultMaxTextureUnits; ++i) {
     47             fTextureUnits[i] =
     48                 reinterpret_cast<GrTextureUnitObj*>(this->createObj(kTextureUnit_ObjTypes));
     49             fTextureUnits[i]->ref();
     50             fTextureUnits[i]->setNumber(i);
     51         }
     52         memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
     53         this->init(kGL_GrGLStandard);
     54     }
     55 
     56     ~DebugInterface() override {
     57         // unref & delete the texture units first so they don't show up on the leak report
     58         for (int i = 0; i < kDefaultMaxTextureUnits; ++i) {
     59             fTextureUnits[i]->unref();
     60             fTextureUnits[i]->deleteAction();
     61         }
     62         for (int i = 0; i < fObjects.count(); ++i) {
     63             delete fObjects[i];
     64         }
     65         fObjects.reset();
     66 
     67         memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
     68         fVertexArray = nullptr;
     69 
     70         this->report();
     71     }
     72 
     73     void abandon() const override { fAbandoned = true; }
     74 
     75     GrGLvoid activeTexture(GrGLenum texture) override {
     76         // Ganesh offsets the texture unit indices
     77         texture -= GR_GL_TEXTURE0;
     78         GrAlwaysAssert(texture < kDefaultMaxTextureUnits);
     79         fCurrTextureUnit = texture;
     80     }
     81 
     82     GrGLvoid attachShader(GrGLuint programID, GrGLuint shaderID) override {
     83 
     84         GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
     85         GrAlwaysAssert(program);
     86 
     87         GrShaderObj *shader = FIND(shaderID, GrShaderObj, kShader_ObjTypes);
     88         GrAlwaysAssert(shader);
     89 
     90         program->AttachShader(shader);
     91     }
     92 
     93     ////////////////////////////////////////////////////////////////////////////////
     94     GrGLvoid bindTexture(GrGLenum target, GrGLuint textureID) override {
     95         GrAlwaysAssert(target == GR_GL_TEXTURE_2D ||
     96                        target == GR_GL_TEXTURE_RECTANGLE ||
     97                        target == GR_GL_TEXTURE_EXTERNAL);
     98 
     99         // a textureID of 0 is acceptable - it binds to the default texture target
    100         GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
    101 
    102         this->setTexture(texture);
    103     }
    104 
    105     GrGLboolean isTexture(GrGLuint textureID) override {
    106         GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
    107 
    108         return texture ? GR_GL_TRUE : GR_GL_FALSE;
    109     }
    110 
    111     ////////////////////////////////////////////////////////////////////////////////
    112     GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
    113                         GrGLenum usage) override {
    114         GrAlwaysAssert(size >= 0);
    115         GrAlwaysAssert(GR_GL_STREAM_DRAW == usage ||
    116                        GR_GL_STATIC_DRAW == usage ||
    117                        GR_GL_DYNAMIC_DRAW == usage);
    118 
    119         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    120         GrAlwaysAssert(buffer);
    121         GrAlwaysAssert(buffer->getBound());
    122 
    123         buffer->allocate(size, reinterpret_cast<const GrGLchar *>(data));
    124         buffer->setUsage(usage);
    125     }
    126 
    127 
    128     GrGLvoid pixelStorei(GrGLenum pname, GrGLint param) override {
    129 
    130         switch (pname) {
    131             case GR_GL_UNPACK_ROW_LENGTH:
    132                 fUnpackRowLength = param;
    133                 break;
    134             case GR_GL_PACK_ROW_LENGTH:
    135                 fPackRowLength = param;
    136                 break;
    137             case GR_GL_UNPACK_ALIGNMENT:
    138                 break;
    139             case GR_GL_PACK_ALIGNMENT:
    140                 fPackAlignment = param;
    141                 break;
    142             default:
    143                 GrAlwaysAssert(false);
    144                 break;
    145         }
    146     }
    147 
    148     GrGLvoid readPixels(GrGLint x,
    149                         GrGLint y,
    150                         GrGLsizei width,
    151                         GrGLsizei height,
    152                         GrGLenum format,
    153                         GrGLenum type,
    154                         GrGLvoid* pixels) override {
    155 
    156         GrGLint pixelsInRow = width;
    157         if (fPackRowLength > 0) {
    158             pixelsInRow = fPackRowLength;
    159         }
    160 
    161         GrGLint componentsPerPixel = 0;
    162 
    163         switch (format) {
    164             case GR_GL_RGBA:
    165                 // fallthrough
    166             case GR_GL_BGRA:
    167                 componentsPerPixel = 4;
    168                 break;
    169             case GR_GL_RGB:
    170                 componentsPerPixel = 3;
    171                 break;
    172             case GR_GL_RED:
    173                 componentsPerPixel = 1;
    174                 break;
    175             default:
    176                 GrAlwaysAssert(false);
    177                 break;
    178         }
    179 
    180         GrGLint alignment = fPackAlignment;
    181 
    182         GrGLint componentSize = 0;  // size (in bytes) of a single component
    183 
    184         switch (type) {
    185             case GR_GL_UNSIGNED_BYTE:
    186                 componentSize = 1;
    187                 break;
    188             default:
    189                 GrAlwaysAssert(false);
    190                 break;
    191         }
    192 
    193         GrGLint rowStride = 0;  // number of components (not bytes) to skip
    194         if (componentSize >= alignment) {
    195             rowStride = componentsPerPixel * pixelsInRow;
    196         } else {
    197             float fTemp =
    198                 sk_float_ceil(componentSize * componentsPerPixel * pixelsInRow /
    199                               static_cast<float>(alignment));
    200             rowStride = static_cast<GrGLint>(alignment * fTemp / componentSize);
    201         }
    202 
    203         GrGLchar *scanline = static_cast<GrGLchar *>(pixels);
    204         for (int y = 0; y < height; ++y) {
    205             memset(scanline, 0, componentsPerPixel * componentSize * width);
    206             scanline += rowStride;
    207         }
    208     }
    209 
    210     GrGLvoid useProgram(GrGLuint programID) override {
    211 
    212         // A programID of 0 is legal
    213         GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
    214 
    215         this->useProgram(program);
    216     }
    217 
    218     GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint frameBufferID) override {
    219 
    220         GrAlwaysAssert(GR_GL_FRAMEBUFFER == target ||
    221                        GR_GL_READ_FRAMEBUFFER == target ||
    222                        GR_GL_DRAW_FRAMEBUFFER);
    223 
    224         // a frameBufferID of 0 is acceptable - it binds to the default
    225         // frame buffer
    226         GrFrameBufferObj *frameBuffer = FIND(frameBufferID, GrFrameBufferObj,
    227                                              kFrameBuffer_ObjTypes);
    228 
    229         this->setFrameBuffer(frameBuffer);
    230     }
    231 
    232     GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderBufferID) override {
    233 
    234         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
    235 
    236         // a renderBufferID of 0 is acceptable - it unbinds the bound render buffer
    237         GrRenderBufferObj *renderBuffer = FIND(renderBufferID, GrRenderBufferObj,
    238                                                kRenderBuffer_ObjTypes);
    239 
    240         this->setRenderBuffer(renderBuffer);
    241     }
    242 
    243     GrGLvoid deleteTextures(GrGLsizei n, const GrGLuint* textures) override {
    244         // first potentially unbind the texture
    245         for (unsigned int i = 0; i < kDefaultMaxTextureUnits; ++i) {
    246             GrTextureUnitObj *pTU = this->getTextureUnit(i);
    247 
    248             if (pTU->getTexture()) {
    249                 for (int j = 0; j < n; ++j) {
    250 
    251                     if (textures[j] == pTU->getTexture()->getID()) {
    252                         // this ID is the current texture - revert the binding to 0
    253                         pTU->setTexture(nullptr);
    254                     }
    255                 }
    256             }
    257         }
    258 
    259         // TODO: fuse the following block with DeleteRenderBuffers?
    260         // Open GL will remove a deleted render buffer from the active
    261         // frame buffer but not from any other frame buffer
    262         if (this->getFrameBuffer()) {
    263 
    264             GrFrameBufferObj *frameBuffer = this->getFrameBuffer();
    265 
    266             for (int i = 0; i < n; ++i) {
    267 
    268                 if (frameBuffer->getColor() &&
    269                     textures[i] == frameBuffer->getColor()->getID()) {
    270                     frameBuffer->setColor(nullptr);
    271                 }
    272                 if (frameBuffer->getDepth() &&
    273                     textures[i] == frameBuffer->getDepth()->getID()) {
    274                     frameBuffer->setDepth(nullptr);
    275                 }
    276                 if (frameBuffer->getStencil() &&
    277                     textures[i] == frameBuffer->getStencil()->getID()) {
    278                     frameBuffer->setStencil(nullptr);
    279                 }
    280             }
    281         }
    282 
    283         // then actually "delete" the buffers
    284         for (int i = 0; i < n; ++i) {
    285             GrTextureObj *buffer = FIND(textures[i], GrTextureObj, kTexture_ObjTypes);
    286             GrAlwaysAssert(buffer);
    287 
    288             // OpenGL gives no guarantees if a texture is deleted while attached to
    289             // something other than the currently bound frame buffer
    290             GrAlwaysAssert(!buffer->getBound());
    291 
    292             GrAlwaysAssert(!buffer->getDeleted());
    293             buffer->deleteAction();
    294         }
    295 
    296     }
    297 
    298     GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint *frameBuffers) override {
    299 
    300         // first potentially unbind the buffers
    301         if (this->getFrameBuffer()) {
    302             for (int i = 0; i < n; ++i) {
    303 
    304                 if (frameBuffers[i] ==
    305                     this->getFrameBuffer()->getID()) {
    306                     // this ID is the current frame buffer - rebind to the default
    307                     this->setFrameBuffer(nullptr);
    308                 }
    309             }
    310         }
    311 
    312         // then actually "delete" the buffers
    313         for (int i = 0; i < n; ++i) {
    314             GrFrameBufferObj *buffer = FIND(frameBuffers[i], GrFrameBufferObj,
    315                                             kFrameBuffer_ObjTypes);
    316             GrAlwaysAssert(buffer);
    317 
    318             GrAlwaysAssert(!buffer->getDeleted());
    319             buffer->deleteAction();
    320         }
    321     }
    322 
    323     GrGLvoid deleteRenderbuffers(GrGLsizei n,const GrGLuint *renderBuffers) override {
    324 
    325         // first potentially unbind the buffers
    326         if (this->getRenderBuffer()) {
    327             for (int i = 0; i < n; ++i) {
    328 
    329                 if (renderBuffers[i] ==
    330                     this->getRenderBuffer()->getID()) {
    331                     // this ID is the current render buffer - make no
    332                     // render buffer be bound
    333                     this->setRenderBuffer(nullptr);
    334                 }
    335             }
    336         }
    337 
    338         // TODO: fuse the following block with DeleteTextures?
    339         // Open GL will remove a deleted render buffer from the active frame
    340         // buffer but not from any other frame buffer
    341         if (this->getFrameBuffer()) {
    342 
    343             GrFrameBufferObj *frameBuffer = this->getFrameBuffer();
    344 
    345             for (int i = 0; i < n; ++i) {
    346 
    347                 if (frameBuffer->getColor() &&
    348                     renderBuffers[i] == frameBuffer->getColor()->getID()) {
    349                     frameBuffer->setColor(nullptr);
    350                 }
    351                 if (frameBuffer->getDepth() &&
    352                     renderBuffers[i] == frameBuffer->getDepth()->getID()) {
    353                     frameBuffer->setDepth(nullptr);
    354                 }
    355                 if (frameBuffer->getStencil() &&
    356                     renderBuffers[i] == frameBuffer->getStencil()->getID()) {
    357                     frameBuffer->setStencil(nullptr);
    358                 }
    359             }
    360         }
    361 
    362         // then actually "delete" the buffers
    363         for (int i = 0; i < n; ++i) {
    364             GrRenderBufferObj *buffer = FIND(renderBuffers[i], GrRenderBufferObj,
    365                                              kRenderBuffer_ObjTypes);
    366             GrAlwaysAssert(buffer);
    367 
    368             // OpenGL gives no guarantees if a render buffer is deleted
    369             // while attached to something other than the currently
    370             // bound frame buffer
    371             GrAlwaysAssert(!buffer->getColorBound());
    372             GrAlwaysAssert(!buffer->getDepthBound());
    373             // However, at GrContext destroy time we release all GrRsources and so stencil buffers
    374             // may get deleted before FBOs that refer to them.
    375             //GrAlwaysAssert(!buffer->getStencilBound());
    376 
    377             GrAlwaysAssert(!buffer->getDeleted());
    378             buffer->deleteAction();
    379         }
    380     }
    381 
    382     GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width,
    383                                  GrGLsizei height) override {
    384         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
    385         GrRenderBufferObj* renderBuffer = this->getRenderBuffer();
    386         GrAlwaysAssert(renderBuffer);
    387         renderBuffer->setNumSamples(1);
    388     }
    389 
    390     GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples,
    391                                             GrGLenum internalformat, GrGLsizei width,
    392                                             GrGLsizei height) override {
    393         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
    394         GrRenderBufferObj* renderBuffer = this->getRenderBuffer();
    395         GrAlwaysAssert(renderBuffer);
    396         renderBuffer->setNumSamples(samples);
    397     }
    398 
    399     GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
    400                                       GrGLsizei width, GrGLsizei height) override {
    401         SK_ABORT("Not implemented");
    402     }
    403 
    404     GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
    405                                                  GrGLenum GrGLinternalformat, GrGLsizei width,
    406                                                  GrGLsizei height) override {
    407         SK_ABORT("Not implemented");
    408     }
    409 
    410     GrGLvoid framebufferRenderbuffer(GrGLenum target,
    411                                      GrGLenum attachment,
    412                                      GrGLenum renderbuffertarget,
    413                                      GrGLuint renderBufferID) override {
    414 
    415         GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
    416         GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
    417                        GR_GL_DEPTH_ATTACHMENT == attachment ||
    418                        GR_GL_STENCIL_ATTACHMENT == attachment);
    419         GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
    420 
    421         GrFrameBufferObj *framebuffer = this->getFrameBuffer();
    422         // A render buffer cannot be attached to the default framebuffer
    423         GrAlwaysAssert(framebuffer);
    424 
    425         // a renderBufferID of 0 is acceptable - it unbinds the current
    426         // render buffer
    427         GrRenderBufferObj *renderbuffer = FIND(renderBufferID, GrRenderBufferObj,
    428                                                kRenderBuffer_ObjTypes);
    429 
    430         switch (attachment) {
    431             case GR_GL_COLOR_ATTACHMENT0:
    432                 framebuffer->setColor(renderbuffer);
    433                 break;
    434             case GR_GL_DEPTH_ATTACHMENT:
    435                 framebuffer->setDepth(renderbuffer);
    436                 break;
    437             case GR_GL_STENCIL_ATTACHMENT:
    438                 framebuffer->setStencil(renderbuffer);
    439                 break;
    440             default:
    441                 GrAlwaysAssert(false);
    442                 break;
    443         };
    444 
    445     }
    446 
    447     GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
    448                                           GrGLenum renderbuffertarget,
    449                                           GrGLuint renderbuffer) override {
    450         SK_ABORT("Not implemented");
    451     }
    452 
    453     ////////////////////////////////////////////////////////////////////////////////
    454     GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
    455                                   GrGLuint textureID, GrGLint level) override {
    456 
    457         GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
    458         GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
    459                        GR_GL_DEPTH_ATTACHMENT == attachment ||
    460                        GR_GL_STENCIL_ATTACHMENT == attachment);
    461         GrAlwaysAssert(GR_GL_TEXTURE_2D == textarget);
    462 
    463         GrFrameBufferObj *framebuffer = this->getFrameBuffer();
    464         // A texture cannot be attached to the default framebuffer
    465         GrAlwaysAssert(framebuffer);
    466 
    467         // A textureID of 0 is allowed - it unbinds the currently bound texture
    468         GrTextureObj *texture = FIND(textureID, GrTextureObj, kTexture_ObjTypes);
    469         if (texture) {
    470             // The texture shouldn't be bound to a texture unit - this
    471             // could lead to a feedback loop
    472             GrAlwaysAssert(!texture->getBound());
    473         }
    474 
    475         GrAlwaysAssert(0 == level);
    476 
    477         switch (attachment) {
    478             case GR_GL_COLOR_ATTACHMENT0:
    479                 framebuffer->setColor(texture);
    480                 break;
    481             case GR_GL_DEPTH_ATTACHMENT:
    482                 framebuffer->setDepth(texture);
    483                 break;
    484             case GR_GL_STENCIL_ATTACHMENT:
    485                 framebuffer->setStencil(texture);
    486                 break;
    487             default:
    488                 GrAlwaysAssert(false);
    489                 break;
    490         };
    491     }
    492 
    493     GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
    494                                              GrGLenum textarget, GrGLuint texture, GrGLint level,
    495                                              GrGLsizei samples) override {
    496         SK_ABORT("Not implemented");
    497     }
    498 
    499     GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
    500                                        GrGLenum textarget, GrGLuint texture,
    501                                        GrGLint level) override {
    502         SK_ABORT("Not implemented");
    503     }
    504 
    505     GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
    506                                        GrGLenum textarget, GrGLuint texture,
    507                                        GrGLint level) override {
    508         SK_ABORT("Not implemented");
    509     }
    510 
    511     GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
    512                                        GrGLenum textarget, GrGLuint texture, GrGLint level,
    513                                        GrGLint zoffset) override {
    514         SK_ABORT("Not implemented");
    515     }
    516 
    517     GrGLuint createProgram() override {
    518 
    519         GrProgramObj *program = CREATE(GrProgramObj, kProgram_ObjTypes);
    520 
    521         return program->getID();
    522     }
    523 
    524     GrGLuint createShader(GrGLenum type) override {
    525 
    526         GrAlwaysAssert(GR_GL_VERTEX_SHADER == type ||
    527                        GR_GL_FRAGMENT_SHADER == type);
    528 
    529         GrShaderObj *shader = CREATE(GrShaderObj, kShader_ObjTypes);
    530         shader->setType(type);
    531 
    532         return shader->getID();
    533     }
    534 
    535     GrGLenum checkFramebufferStatus(GrGLenum target) override { return GR_GL_FRAMEBUFFER_COMPLETE; }
    536 
    537     GrGLvoid deleteProgram(GrGLuint programID) override {
    538 
    539         GrProgramObj *program = FIND(programID, GrProgramObj, kProgram_ObjTypes);
    540         GrAlwaysAssert(program);
    541 
    542         if (program->getRefCount()) {
    543             // someone is still using this program so we can't delete it here
    544             program->setMarkedForDeletion();
    545         } else {
    546             program->deleteAction();
    547         }
    548     }
    549 
    550     GrGLvoid deleteShader(GrGLuint shaderID) override {
    551 
    552         GrShaderObj *shader = FIND(shaderID, GrShaderObj, kShader_ObjTypes);
    553         GrAlwaysAssert(shader);
    554 
    555         if (shader->getRefCount()) {
    556             // someone is still using this shader so we can't delete it here
    557             shader->setMarkedForDeletion();
    558         } else {
    559             shader->deleteAction();
    560         }
    561     }
    562 
    563     GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
    564         this->genObjs(kBuffer_ObjTypes, n, ids);
    565     }
    566 
    567     GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint* ids) override {
    568         this->genObjs(kFrameBuffer_ObjTypes, n, ids);
    569     }
    570 
    571     GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint* ids) override {
    572         this->genObjs(kRenderBuffer_ObjTypes, n, ids);
    573     }
    574 
    575     GrGLvoid genTextures(GrGLsizei n, GrGLuint* ids) override {
    576         this->genObjs(kTexture_ObjTypes, n, ids);
    577     }
    578 
    579     GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint* ids) override {
    580         this->genObjs(kVertexArray_ObjTypes, n, ids);
    581     }
    582 
    583     GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
    584 
    585     GrGLenum getError() override { return GR_GL_NO_ERROR; }
    586 
    587     GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
    588         // TODO: remove from Ganesh the #defines for gets we don't use.
    589         // We would like to minimize gets overall due to performance issues
    590         switch (pname) {
    591             case GR_GL_CONTEXT_PROFILE_MASK:
    592                 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
    593                 break;
    594             case GR_GL_STENCIL_BITS:
    595                 *params = 8;
    596                 break;
    597             case GR_GL_SAMPLES: {
    598                 GrFrameBufferObj* framebuffer = this->getFrameBuffer();
    599                 GrAlwaysAssert(framebuffer);
    600                 int numSamples = 0;
    601 
    602                 if (GrFBBindableObj* stencil = framebuffer->getStencil()) {
    603                     numSamples = stencil->numSamples();
    604                 }
    605                 if (GrFBBindableObj* depth = framebuffer->getDepth()) {
    606                     GrAlwaysAssert(!numSamples || numSamples == depth->numSamples());
    607                     numSamples = depth->numSamples();
    608                 }
    609                 if (GrFBBindableObj* color = framebuffer->getColor()) {
    610                     GrAlwaysAssert(!numSamples || numSamples == color->numSamples());
    611                     numSamples = color->numSamples();
    612                 }
    613                 GrAlwaysAssert(numSamples);
    614                 *params = numSamples;
    615                 break;
    616             }
    617             case GR_GL_FRAMEBUFFER_BINDING:
    618                 *params = 0;
    619                 break;
    620             case GR_GL_VIEWPORT:
    621                 params[0] = 0;
    622                 params[1] = 0;
    623                 params[2] = 800;
    624                 params[3] = 600;
    625                 break;
    626             case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    627             case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
    628             case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
    629             case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    630                 *params = 8;
    631                 break;
    632             case GR_GL_MAX_TEXTURE_COORDS:
    633                 *params = 8;
    634                 break;
    635             case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
    636                 *params = kDefaultMaxVertexUniformVectors;
    637                 break;
    638             case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
    639                 *params = kDefaultMaxFragmentUniformVectors;
    640                 break;
    641             case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
    642                 *params = 16 * 4;
    643                 break;
    644             case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    645                 *params = 0;
    646                 break;
    647             case GR_GL_COMPRESSED_TEXTURE_FORMATS:
    648                 break;
    649             case GR_GL_MAX_TEXTURE_SIZE:
    650                 *params = 8192;
    651                 break;
    652             case GR_GL_MAX_RENDERBUFFER_SIZE:
    653                 *params = 8192;
    654                 break;
    655             case GR_GL_MAX_SAMPLES:
    656                 *params = 32;
    657                 break;
    658             case GR_GL_MAX_VERTEX_ATTRIBS:
    659                 *params = kDefaultMaxVertexAttribs;
    660                 break;
    661             case GR_GL_MAX_VARYING_VECTORS:
    662                 *params = kDefaultMaxVaryingVectors;
    663                 break;
    664             case GR_GL_NUM_EXTENSIONS: {
    665                 GrGLint i = 0;
    666                 while (kExtensions[i++]);
    667                 *params = i;
    668                 break;
    669             }
    670             default:
    671                 SK_ABORT("Unexpected pname to GetIntegerv");
    672         }
    673     }
    674 
    675     GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
    676         val[0] = val[1] = 0.5f;
    677     }
    678 
    679     GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
    680         this->getShaderOrProgramiv(program, pname, params);
    681     }
    682 
    683     GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
    684                                char* infolog) override {
    685         this->getInfoLog(program, bufsize, length, infolog);
    686     }
    687 
    688     GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
    689         switch (pname) {
    690             case GR_GL_CURRENT_QUERY:
    691                 *params = 0;
    692                 break;
    693             case GR_GL_QUERY_COUNTER_BITS:
    694                 *params = 32;
    695                 break;
    696             default:
    697                 SK_ABORT("Unexpected pname passed GetQueryiv.");
    698         }
    699     }
    700 
    701     GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
    702         this->queryResult(id, pname, params);
    703     }
    704 
    705     GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
    706         this->queryResult(id, pname, params);
    707     }
    708 
    709     GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
    710         this->queryResult(id, pname, params);
    711     }
    712 
    713     GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
    714         this->queryResult(id, pname, params);
    715     }
    716 
    717     GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
    718         this->getShaderOrProgramiv(shader, pname, params);
    719     }
    720 
    721     GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
    722                               char* infolog) override {
    723         this->getInfoLog(shader, bufsize, length, infolog);
    724     }
    725 
    726     const GrGLubyte* getString(GrGLenum name) override {
    727         switch (name) {
    728             case GR_GL_EXTENSIONS:
    729                 return CombinedExtensionString();
    730             case GR_GL_VERSION:
    731                 return (const GrGLubyte*)"4.0 Debug GL";
    732             case GR_GL_SHADING_LANGUAGE_VERSION:
    733                 return (const GrGLubyte*)"4.20.8 Debug GLSL";
    734             case GR_GL_VENDOR:
    735                 return (const GrGLubyte*)"Debug Vendor";
    736             case GR_GL_RENDERER:
    737                 return (const GrGLubyte*)"The Debug (Non-)Renderer";
    738             default:
    739                 SK_ABORT("Unexpected name passed to GetString");
    740                 return nullptr;
    741         }
    742     }
    743 
    744     const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
    745         switch (name) {
    746             case GR_GL_EXTENSIONS: {
    747                 GrGLint count;
    748                 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
    749                 if ((GrGLint)i <= count) {
    750                     return (const GrGLubyte*) kExtensions[i];
    751                 } else {
    752                     return nullptr;
    753                 }
    754             }
    755             default:
    756                 SK_ABORT("Unexpected name passed to GetStringi");
    757                 return nullptr;
    758         }
    759     }
    760 
    761     GrGLvoid getTexLevelParameteriv(GrGLenum target, GrGLint level, GrGLenum pname,
    762                                     GrGLint* params) override {
    763         // we used to use this to query stuff about externally created textures,
    764         // now we just require clients to tell us everything about the texture.
    765         SK_ABORT("Should never query texture parameters.");
    766     }
    767 
    768     GrGLvoid deleteVertexArrays(GrGLsizei n, const GrGLuint* ids) override {
    769         for (GrGLsizei i = 0; i < n; ++i) {
    770             GrVertexArrayObj* array = FIND(ids[i], GrVertexArrayObj, kVertexArray_ObjTypes);
    771             GrAlwaysAssert(array);
    772 
    773             // Deleting the current vertex array binds object 0
    774             if (this->getVertexArray() == array) {
    775                 this->setVertexArray(nullptr);
    776             }
    777 
    778             if (array->getRefCount()) {
    779                 // someone is still using this vertex array so we can't delete it here
    780                 array->setMarkedForDeletion();
    781             } else {
    782                 array->deleteAction();
    783             }
    784         }
    785     }
    786 
    787     GrGLvoid bindVertexArray(GrGLuint id) override {
    788         GrVertexArrayObj* array = FIND(id, GrVertexArrayObj, kVertexArray_ObjTypes);
    789         GrAlwaysAssert((0 == id) || array);
    790         this->setVertexArray(array);
    791     }
    792 
    793     GrGLvoid bindBuffer(GrGLenum target, GrGLuint bufferID) override {
    794         GrBufferObj *buffer = FIND(bufferID, GrBufferObj, kBuffer_ObjTypes);
    795         // 0 is a permissible bufferID - it unbinds the current buffer
    796 
    797         this->setBuffer(GetBufferIndex(target), buffer);
    798     }
    799 
    800     // deleting a bound buffer has the side effect of binding 0
    801     GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override {
    802         // first potentially unbind the buffers
    803         for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) {
    804             GrBufferObj* buffer = fBoundBuffers[buffIdx];
    805             if (!buffer) {
    806                 continue;
    807             }
    808             for (int i = 0; i < n; ++i) {
    809                 if (ids[i] == buffer->getID()) {
    810                     this->setBuffer(buffIdx, nullptr);
    811                     break;
    812                 }
    813             }
    814         }
    815 
    816         // then actually "delete" the buffers
    817         for (int i = 0; i < n; ++i) {
    818             GrBufferObj *buffer = FIND(ids[i], GrBufferObj, kBuffer_ObjTypes);
    819             GrAlwaysAssert(buffer);
    820 
    821             GrAlwaysAssert(!buffer->getDeleted());
    822             buffer->deleteAction();
    823         }
    824     }
    825 
    826     // map a buffer to the caller's address space
    827     GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
    828                              GrGLbitfield access) override {
    829         // We only expect read access and we expect that the buffer or range is always invalidated.
    830         GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
    831         GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
    832 
    833         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    834         if (buffer) {
    835             GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
    836             GrAlwaysAssert(!buffer->getMapped());
    837             buffer->setMapped(offset, length);
    838             return buffer->getDataPtr() + offset;
    839         }
    840 
    841         GrAlwaysAssert(false);
    842         return nullptr;        // no buffer bound to the target
    843     }
    844 
    845     GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
    846         GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
    847         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    848         return this->mapBufferRange(target, 0, buffer->getSize(),
    849                                     GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
    850     }
    851 
    852     // remove a buffer from the caller's address space
    853     // TODO: check if the "access" method from "glMapBuffer" was honored
    854     GrGLboolean unmapBuffer(GrGLenum target) override {
    855         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    856         if (buffer) {
    857             GrAlwaysAssert(buffer->getMapped());
    858             buffer->resetMapped();
    859             return GR_GL_TRUE;
    860         }
    861 
    862         GrAlwaysAssert(false);
    863         return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
    864     }
    865 
    866     GrGLvoid flushMappedBufferRange(GrGLenum target, GrGLintptr offset,
    867                                     GrGLsizeiptr length) override {
    868         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    869         if (buffer) {
    870             GrAlwaysAssert(buffer->getMapped());
    871             GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
    872         } else {
    873             GrAlwaysAssert(false);
    874         }
    875     }
    876 
    877     GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum value, GrGLint* params) override {
    878 
    879         GrAlwaysAssert(GR_GL_BUFFER_SIZE == value ||
    880                        GR_GL_BUFFER_USAGE == value);
    881 
    882         GrBufferObj *buffer = fBoundBuffers[GetBufferIndex(target)];
    883         GrAlwaysAssert(buffer);
    884 
    885         switch (value) {
    886             case GR_GL_BUFFER_MAPPED:
    887                 *params = GR_GL_FALSE;
    888                 if (buffer)
    889                     *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
    890                 break;
    891             case GR_GL_BUFFER_SIZE:
    892                 *params = 0;
    893                 if (buffer)
    894                     *params = SkToInt(buffer->getSize());
    895                 break;
    896             case GR_GL_BUFFER_USAGE:
    897                 *params = GR_GL_STATIC_DRAW;
    898                 if (buffer)
    899                     *params = buffer->getUsage();
    900                 break;
    901             default:
    902                 SK_ABORT("Unexpected value to glGetBufferParamateriv");
    903                 break;
    904         }
    905     }
    906 
    907 private:
    908     inline int static GetBufferIndex(GrGLenum glTarget) {
    909         switch (glTarget) {
    910             default:                           SK_ABORT("Unexpected GL target to GetBufferIndex");
    911             case GR_GL_ARRAY_BUFFER:           return 0;
    912             case GR_GL_ELEMENT_ARRAY_BUFFER:   return 1;
    913             case GR_GL_TEXTURE_BUFFER:         return 2;
    914             case GR_GL_DRAW_INDIRECT_BUFFER:   return 3;
    915         }
    916     }
    917     constexpr int static kNumBufferTargets = 4;
    918 
    919     // the OpenGLES 2.0 spec says this must be >= 128
    920     static const GrGLint kDefaultMaxVertexUniformVectors = 128;
    921 
    922     // the OpenGLES 2.0 spec says this must be >=16
    923     static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
    924 
    925     // the OpenGLES 2.0 spec says this must be >= 8
    926     static const GrGLint kDefaultMaxVertexAttribs = 8;
    927 
    928     // the OpenGLES 2.0 spec says this must be >= 8
    929     static const GrGLint kDefaultMaxVaryingVectors = 8;
    930 
    931     // the OpenGLES 2.0 spec says this must be >= 2
    932     static const GrGLint kDefaultMaxTextureUnits = 8;
    933 
    934     static const char* kExtensions[];
    935 
    936     GrGLuint                    fCurrGenericID;
    937     GrGLuint                    fCurrTextureUnit;
    938     GrTextureUnitObj*           fTextureUnits[kDefaultMaxTextureUnits];
    939     GrBufferObj*                fBoundBuffers[kNumBufferTargets];
    940     GrVertexArrayObj*           fVertexArray;
    941     GrGLint                     fPackRowLength;
    942     GrGLint                     fUnpackRowLength;
    943     GrGLint                     fPackAlignment;
    944     GrFrameBufferObj*           fFrameBuffer;
    945     GrRenderBufferObj*          fRenderBuffer;
    946     GrProgramObj*               fProgram;
    947     mutable bool                fAbandoned;
    948     // global store of all objects
    949     SkTArray<GrFakeRefObj *>    fObjects;
    950 
    951     static const GrGLubyte* CombinedExtensionString() {
    952         static SkString gExtString;
    953         static SkMutex gMutex;
    954         gMutex.acquire();
    955         if (0 == gExtString.size()) {
    956             int i = 0;
    957             while (kExtensions[i]) {
    958                 if (i > 0) {
    959                     gExtString.append(" ");
    960                 }
    961                 gExtString.append(kExtensions[i]);
    962                 ++i;
    963             }
    964         }
    965         gMutex.release();
    966         return (const GrGLubyte*) gExtString.c_str();
    967     }
    968 
    969     GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
    970         for (int i = 0; i < n; ++i) {
    971             ids[i] = ++fCurrGenericID;
    972         }
    973     }
    974 
    975     GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
    976                         char* infolog) {
    977         if (length) {
    978             *length = 0;
    979         }
    980         if (bufsize > 0) {
    981             *infolog = 0;
    982         }
    983     }
    984 
    985     GrGLvoid getShaderOrProgramiv(GrGLuint object,  GrGLenum pname, GrGLint* params) {
    986         switch (pname) {
    987             case GR_GL_LINK_STATUS:  // fallthru
    988             case GR_GL_COMPILE_STATUS:
    989                 *params = GR_GL_TRUE;
    990                 break;
    991             case GR_GL_INFO_LOG_LENGTH: // fallthru
    992             case GL_PROGRAM_BINARY_LENGTH:
    993                 *params = 0;
    994                 break;
    995                 // we don't expect any other pnames
    996             default:
    997                 SK_ABORT("Unexpected pname to GetProgramiv");
    998                 break;
    999         }
   1000     }
   1001 
   1002     template <typename T>
   1003     void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
   1004         switch (pname) {
   1005             case GR_GL_QUERY_RESULT_AVAILABLE:
   1006                 *params = GR_GL_TRUE;
   1007                 break;
   1008             case GR_GL_QUERY_RESULT:
   1009                 *params = 0;
   1010                 break;
   1011             default:
   1012                 SK_ABORT("Unexpected pname passed to GetQueryObject.");
   1013                 break;
   1014         }
   1015     }
   1016 
   1017     enum ObjTypes {
   1018         kTexture_ObjTypes = 0,
   1019         kBuffer_ObjTypes,
   1020         kRenderBuffer_ObjTypes,
   1021         kFrameBuffer_ObjTypes,
   1022         kShader_ObjTypes,
   1023         kProgram_ObjTypes,
   1024         kTextureUnit_ObjTypes,
   1025         kVertexArray_ObjTypes,
   1026         kObjTypeCount
   1027     };
   1028 
   1029     typedef GrFakeRefObj *(*Create)();
   1030 
   1031     static Create gFactoryFunc[kObjTypeCount];
   1032 
   1033     GrGLvoid genObjs(ObjTypes type, GrGLsizei n, GrGLuint* ids) {
   1034         for (int i = 0; i < n; ++i) {
   1035             GrAlwaysAssert(ids[i] == 0);
   1036             GrFakeRefObj *obj = this->createObj(type);
   1037             GrAlwaysAssert(obj);
   1038             ids[i] = obj->getID();
   1039         }
   1040     }
   1041 
   1042     GrFakeRefObj* createObj(ObjTypes type) {
   1043         GrFakeRefObj *temp = (*gFactoryFunc[type])();
   1044 
   1045         fObjects.push_back(temp);
   1046 
   1047         return temp;
   1048     }
   1049 
   1050     GrFakeRefObj* findObject(GrGLuint ID, ObjTypes type) {
   1051         for (int i = 0; i < fObjects.count(); ++i) {
   1052             if (fObjects[i]->getID() == ID) { // && fObjects[i]->getType() == type) {
   1053                 // The application shouldn't be accessing objects
   1054                 // that (as far as OpenGL knows) were already deleted
   1055                 GrAlwaysAssert(!fObjects[i]->getDeleted());
   1056                 GrAlwaysAssert(!fObjects[i]->getMarkedForDeletion());
   1057                 return fObjects[i];
   1058             }
   1059         }
   1060         return nullptr;
   1061     }
   1062 
   1063     GrTextureUnitObj* getTextureUnit(int unit) {
   1064         GrAlwaysAssert(0 <= unit && kDefaultMaxTextureUnits > unit);
   1065 
   1066         return fTextureUnits[unit];
   1067     }
   1068 
   1069     GrGLvoid setBuffer(int buffIdx, GrBufferObj* buffer) {
   1070         if (fBoundBuffers[buffIdx]) {
   1071             // automatically break the binding of the old buffer
   1072             GrAlwaysAssert(fBoundBuffers[buffIdx]->getBound());
   1073             fBoundBuffers[buffIdx]->resetBound();
   1074 
   1075             GrAlwaysAssert(!fBoundBuffers[buffIdx]->getDeleted());
   1076             fBoundBuffers[buffIdx]->unref();
   1077         }
   1078 
   1079         if (buffer) {
   1080             GrAlwaysAssert(!buffer->getDeleted());
   1081             buffer->ref();
   1082 
   1083             GrAlwaysAssert(!buffer->getBound());
   1084             buffer->setBound();
   1085         }
   1086 
   1087         fBoundBuffers[buffIdx] = buffer;
   1088     }
   1089 
   1090     void setVertexArray(GrVertexArrayObj* vertexArray) {
   1091         if (vertexArray) {
   1092             SkASSERT(!vertexArray->getDeleted());
   1093         }
   1094         SkRefCnt_SafeAssign(fVertexArray, vertexArray);
   1095     }
   1096 
   1097     GrVertexArrayObj* getVertexArray() { return fVertexArray; }
   1098 
   1099     void setTexture(GrTextureObj *texture) {
   1100         fTextureUnits[fCurrTextureUnit]->setTexture(texture);
   1101     }
   1102 
   1103     void setFrameBuffer(GrFrameBufferObj *frameBuffer) {
   1104         if (fFrameBuffer) {
   1105             GrAlwaysAssert(fFrameBuffer->getBound());
   1106             fFrameBuffer->resetBound();
   1107 
   1108             GrAlwaysAssert(!fFrameBuffer->getDeleted());
   1109             fFrameBuffer->unref();
   1110         }
   1111 
   1112         fFrameBuffer = frameBuffer;
   1113 
   1114         if (fFrameBuffer) {
   1115             GrAlwaysAssert(!fFrameBuffer->getDeleted());
   1116             fFrameBuffer->ref();
   1117 
   1118             GrAlwaysAssert(!fFrameBuffer->getBound());
   1119             fFrameBuffer->setBound();
   1120         }
   1121     }
   1122 
   1123     GrFrameBufferObj *getFrameBuffer() { return fFrameBuffer; }
   1124 
   1125     void setRenderBuffer(GrRenderBufferObj *renderBuffer) {
   1126         if (fRenderBuffer) {
   1127             GrAlwaysAssert(fRenderBuffer->getBound());
   1128             fRenderBuffer->resetBound();
   1129 
   1130             GrAlwaysAssert(!fRenderBuffer->getDeleted());
   1131             fRenderBuffer->unref();
   1132         }
   1133 
   1134         fRenderBuffer = renderBuffer;
   1135 
   1136         if (fRenderBuffer) {
   1137             GrAlwaysAssert(!fRenderBuffer->getDeleted());
   1138             fRenderBuffer->ref();
   1139 
   1140             GrAlwaysAssert(!fRenderBuffer->getBound());
   1141             fRenderBuffer->setBound();
   1142         }
   1143     }
   1144     GrRenderBufferObj *getRenderBuffer() { return fRenderBuffer; }
   1145 
   1146     void useProgram(GrProgramObj *program) {
   1147         if (fProgram) {
   1148             GrAlwaysAssert(fProgram->getInUse());
   1149             fProgram->resetInUse();
   1150 
   1151             GrAlwaysAssert(!fProgram->getDeleted());
   1152             fProgram->unref();
   1153         }
   1154 
   1155         fProgram = program;
   1156 
   1157         if (fProgram) {
   1158             GrAlwaysAssert(!fProgram->getDeleted());
   1159             fProgram->ref();
   1160 
   1161             GrAlwaysAssert(!fProgram->getInUse());
   1162             fProgram->setInUse();
   1163         }
   1164     }
   1165 
   1166     void report() const {
   1167         for (int i = 0; i < fObjects.count(); ++i) {
   1168             if (!fAbandoned) {
   1169                 GrAlwaysAssert(0 == fObjects[i]->getRefCount());
   1170                 GrAlwaysAssert(fObjects[i]->getDeleted());
   1171             }
   1172         }
   1173     }
   1174 
   1175     typedef GrGLTestInterface INHERITED;
   1176 };
   1177 
   1178 #undef CREATE
   1179 #undef FIND
   1180 
   1181 DebugInterface::Create DebugInterface::gFactoryFunc[kObjTypeCount] = {
   1182     GrTextureObj::createGrTextureObj,
   1183     GrBufferObj::createGrBufferObj,
   1184     GrRenderBufferObj::createGrRenderBufferObj,
   1185     GrFrameBufferObj::createGrFrameBufferObj,
   1186     GrShaderObj::createGrShaderObj,
   1187     GrProgramObj::createGrProgramObj,
   1188     GrTextureUnitObj::createGrTextureUnitObj,
   1189     GrVertexArrayObj::createGrVertexArrayObj,
   1190 };
   1191 
   1192 const char* DebugInterface::kExtensions[] = {
   1193     "GL_ARB_framebuffer_object",
   1194     "GL_ARB_blend_func_extended",
   1195     "GL_ARB_timer_query",
   1196     "GL_ARB_draw_buffers",
   1197     "GL_ARB_occlusion_query",
   1198     "GL_EXT_stencil_wrap",
   1199     nullptr, // signifies the end of the array.
   1200 };
   1201 
   1202 class DebugGLContext : public sk_gpu_test::GLTestContext {
   1203 public:
   1204     DebugGLContext() { this->init(sk_make_sp<DebugInterface>()); }
   1205 
   1206     ~DebugGLContext() override { this->teardown(); }
   1207 
   1208 private:
   1209     void onPlatformMakeCurrent() const override {}
   1210     std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
   1211     void onPlatformSwapBuffers() const override {}
   1212     GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
   1213 };
   1214 }  // anonymous namespace
   1215 
   1216 namespace sk_gpu_test {
   1217 GLTestContext* CreateDebugGLTestContext(GLTestContext* shareContext) {
   1218     if (shareContext) {
   1219         return nullptr;
   1220     }
   1221     GLTestContext* ctx = new DebugGLContext();
   1222     if (ctx->isValid()) {
   1223         return ctx;
   1224     }
   1225     delete ctx;
   1226     return nullptr;
   1227 }
   1228 }
   1229