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