• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #include "gl/GrGLInterface.h"
11 #include "GrDebugGL.h"
12 #include "GrShaderObj.h"
13 #include "GrProgramObj.h"
14 #include "GrBufferObj.h"
15 #include "GrTextureUnitObj.h"
16 #include "GrTextureObj.h"
17 #include "GrFrameBufferObj.h"
18 #include "GrRenderBufferObj.h"
19 #include "GrVertexArrayObj.h"
20 #include "SkFloatingPoint.h"
21 #include "../GrGLNoOpInterface.h"
22 
23 namespace { // suppress no previous prototype warning
24 
25 ////////////////////////////////////////////////////////////////////////////////
debugGLActiveTexture(GrGLenum texture)26 GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture) {
27 
28     // Ganesh offsets the texture unit indices
29     texture -= GR_GL_TEXTURE0;
30     GrAlwaysAssert(texture < GrDebugGL::getInstance()->getMaxTextureUnits());
31 
32     GrDebugGL::getInstance()->setCurTextureUnit(texture);
33 }
34 
35 ////////////////////////////////////////////////////////////////////////////////
debugGLAttachShader(GrGLuint programID,GrGLuint shaderID)36 GrGLvoid GR_GL_FUNCTION_TYPE debugGLAttachShader(GrGLuint programID,
37                                                  GrGLuint shaderID) {
38 
39     GrProgramObj *program = GR_FIND(programID, GrProgramObj,
40                                     GrDebugGL::kProgram_ObjTypes);
41     GrAlwaysAssert(program);
42 
43     GrShaderObj *shader = GR_FIND(shaderID,
44                                   GrShaderObj,
45                                   GrDebugGL::kShader_ObjTypes);
46     GrAlwaysAssert(shader);
47 
48     program->AttachShader(shader);
49 }
50 
debugGLBeginQuery(GrGLenum target,GrGLuint id)51 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBeginQuery(GrGLenum target, GrGLuint id) {
52 }
53 
debugGLBindAttribLocation(GrGLuint program,GrGLuint index,const char * name)54 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindAttribLocation(GrGLuint program,
55                                                        GrGLuint index,
56                                                        const char* name) {
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
debugGLBindTexture(GrGLenum target,GrGLuint textureID)60 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindTexture(GrGLenum target,
61                                                 GrGLuint textureID) {
62 
63     // we don't use cube maps
64     GrAlwaysAssert(target == GR_GL_TEXTURE_2D);
65                                     // || target == GR_GL_TEXTURE_CUBE_MAP);
66 
67     // a textureID of 0 is acceptable - it binds to the default texture target
68     GrTextureObj *texture = GR_FIND(textureID, GrTextureObj,
69                                     GrDebugGL::kTexture_ObjTypes);
70 
71     GrDebugGL::getInstance()->setTexture(texture);
72 }
73 
74 
75 ////////////////////////////////////////////////////////////////////////////////
debugGLBufferData(GrGLenum target,GrGLsizeiptr size,const GrGLvoid * data,GrGLenum usage)76 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target,
77                                                GrGLsizeiptr size,
78                                                const GrGLvoid* data,
79                                                GrGLenum usage) {
80     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
81                    GR_GL_ELEMENT_ARRAY_BUFFER == target);
82     GrAlwaysAssert(size >= 0);
83     GrAlwaysAssert(GR_GL_STREAM_DRAW == usage ||
84                    GR_GL_STATIC_DRAW == usage ||
85                    GR_GL_DYNAMIC_DRAW == usage);
86 
87     GrBufferObj *buffer = nullptr;
88     switch (target) {
89         case GR_GL_ARRAY_BUFFER:
90             buffer = GrDebugGL::getInstance()->getArrayBuffer();
91             break;
92         case GR_GL_ELEMENT_ARRAY_BUFFER:
93             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
94             break;
95         default:
96             SkFAIL("Unexpected target to glBufferData");
97             break;
98     }
99 
100     GrAlwaysAssert(buffer);
101     GrAlwaysAssert(buffer->getBound());
102 
103     buffer->allocate(size, reinterpret_cast<const GrGLchar *>(data));
104     buffer->setUsage(usage);
105 }
106 
107 
debugGLPixelStorei(GrGLenum pname,GrGLint param)108 GrGLvoid GR_GL_FUNCTION_TYPE debugGLPixelStorei(GrGLenum pname,
109                                                 GrGLint param) {
110 
111     switch (pname) {
112         case GR_GL_UNPACK_ROW_LENGTH:
113             GrDebugGL::getInstance()->setUnPackRowLength(param);
114             break;
115         case GR_GL_PACK_ROW_LENGTH:
116             GrDebugGL::getInstance()->setPackRowLength(param);
117             break;
118         case GR_GL_UNPACK_ALIGNMENT:
119             break;
120         case GR_GL_PACK_ALIGNMENT:
121             GrAlwaysAssert(false);
122             break;
123         default:
124             GrAlwaysAssert(false);
125             break;
126     }
127 }
128 
debugGLReadPixels(GrGLint x,GrGLint y,GrGLsizei width,GrGLsizei height,GrGLenum format,GrGLenum type,GrGLvoid * pixels)129 GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x,
130                                                GrGLint y,
131                                                GrGLsizei width,
132                                                GrGLsizei height,
133                                                GrGLenum format,
134                                                GrGLenum type,
135                                                GrGLvoid* pixels) {
136 
137     GrGLint pixelsInRow = width;
138     if (0 < GrDebugGL::getInstance()->getPackRowLength()) {
139         pixelsInRow = GrDebugGL::getInstance()->getPackRowLength();
140     }
141 
142     GrGLint componentsPerPixel = 0;
143 
144     switch (format) {
145         case GR_GL_RGBA:
146             // fallthrough
147         case GR_GL_BGRA:
148             componentsPerPixel = 4;
149             break;
150         case GR_GL_RGB:
151             componentsPerPixel = 3;
152             break;
153         case GR_GL_RED:
154             componentsPerPixel = 1;
155             break;
156         default:
157             GrAlwaysAssert(false);
158             break;
159     }
160 
161     GrGLint alignment = 4;  // the pack alignment (one of 1, 2, 4 or 8)
162     // Ganesh currently doesn't support setting GR_GL_PACK_ALIGNMENT
163 
164     GrGLint componentSize = 0;  // size (in bytes) of a single component
165 
166     switch (type) {
167         case GR_GL_UNSIGNED_BYTE:
168             componentSize = 1;
169             break;
170         default:
171             GrAlwaysAssert(false);
172             break;
173     }
174 
175     GrGLint rowStride = 0;  // number of components (not bytes) to skip
176     if (componentSize >= alignment) {
177         rowStride = componentsPerPixel * pixelsInRow;
178     } else {
179         float fTemp =
180             sk_float_ceil(componentSize * componentsPerPixel * pixelsInRow /
181                           static_cast<float>(alignment));
182         rowStride = static_cast<GrGLint>(alignment * fTemp / componentSize);
183     }
184 
185     GrGLchar *scanline = static_cast<GrGLchar *>(pixels);
186     for (int y = 0; y < height; ++y) {
187         memset(scanline, 0, componentsPerPixel * componentSize * width);
188         scanline += rowStride;
189     }
190 }
191 
debugGLUseProgram(GrGLuint programID)192  GrGLvoid GR_GL_FUNCTION_TYPE debugGLUseProgram(GrGLuint programID) {
193 
194      // A programID of 0 is legal
195      GrProgramObj *program = GR_FIND(programID,
196                                      GrProgramObj,
197                                      GrDebugGL::kProgram_ObjTypes);
198 
199      GrDebugGL::getInstance()->useProgram(program);
200  }
201 
debugGLBindFramebuffer(GrGLenum target,GrGLuint frameBufferID)202  GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFramebuffer(GrGLenum target,
203                                                      GrGLuint frameBufferID) {
204 
205      GrAlwaysAssert(GR_GL_FRAMEBUFFER == target ||
206                     GR_GL_READ_FRAMEBUFFER == target ||
207                     GR_GL_DRAW_FRAMEBUFFER);
208 
209      // a frameBufferID of 0 is acceptable - it binds to the default
210      // frame buffer
211      GrFrameBufferObj *frameBuffer = GR_FIND(frameBufferID,
212                                              GrFrameBufferObj,
213                                              GrDebugGL::kFrameBuffer_ObjTypes);
214 
215      GrDebugGL::getInstance()->setFrameBuffer(frameBuffer);
216  }
217 
debugGLBindRenderbuffer(GrGLenum target,GrGLuint renderBufferID)218  GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindRenderbuffer(GrGLenum target, GrGLuint renderBufferID) {
219 
220      GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
221 
222      // a renderBufferID of 0 is acceptable - it unbinds the bound render buffer
223      GrRenderBufferObj *renderBuffer = GR_FIND(renderBufferID,
224                                                GrRenderBufferObj,
225                                                GrDebugGL::kRenderBuffer_ObjTypes);
226 
227      GrDebugGL::getInstance()->setRenderBuffer(renderBuffer);
228  }
229 
debugGLDeleteTextures(GrGLsizei n,const GrGLuint * textures)230  GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteTextures(GrGLsizei n, const GrGLuint* textures) {
231 
232      // first potentially unbind the texture
233      // TODO: move this into GrDebugGL as unBindTexture?
234      for (unsigned int i = 0;
235           i < GrDebugGL::getInstance()->getMaxTextureUnits();
236           ++i) {
237          GrTextureUnitObj *pTU = GrDebugGL::getInstance()->getTextureUnit(i);
238 
239          if (pTU->getTexture()) {
240              for (int j = 0; j < n; ++j) {
241 
242                  if (textures[j] == pTU->getTexture()->getID()) {
243                      // this ID is the current texture - revert the binding to 0
244                      pTU->setTexture(nullptr);
245                  }
246              }
247          }
248      }
249 
250      // TODO: fuse the following block with DeleteRenderBuffers?
251      // Open GL will remove a deleted render buffer from the active
252      // frame buffer but not from any other frame buffer
253      if (GrDebugGL::getInstance()->getFrameBuffer()) {
254 
255          GrFrameBufferObj *frameBuffer = GrDebugGL::getInstance()->getFrameBuffer();
256 
257          for (int i = 0; i < n; ++i) {
258 
259              if (frameBuffer->getColor() &&
260                  textures[i] == frameBuffer->getColor()->getID()) {
261                  frameBuffer->setColor(nullptr);
262              }
263              if (frameBuffer->getDepth() &&
264                  textures[i] == frameBuffer->getDepth()->getID()) {
265                  frameBuffer->setDepth(nullptr);
266              }
267              if (frameBuffer->getStencil() &&
268                  textures[i] == frameBuffer->getStencil()->getID()) {
269                  frameBuffer->setStencil(nullptr);
270              }
271          }
272      }
273 
274      // then actually "delete" the buffers
275      for (int i = 0; i < n; ++i) {
276          GrTextureObj *buffer = GR_FIND(textures[i],
277                                         GrTextureObj,
278                                         GrDebugGL::kTexture_ObjTypes);
279          GrAlwaysAssert(buffer);
280 
281          // OpenGL gives no guarantees if a texture is deleted while attached to
282          // something other than the currently bound frame buffer
283          GrAlwaysAssert(!buffer->getBound());
284 
285          GrAlwaysAssert(!buffer->getDeleted());
286          buffer->deleteAction();
287      }
288 
289  }
290 
debugGLDeleteFramebuffers(GrGLsizei n,const GrGLuint * frameBuffers)291  GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n,
292                                                         const GrGLuint *frameBuffers) {
293 
294      // first potentially unbind the buffers
295      if (GrDebugGL::getInstance()->getFrameBuffer()) {
296          for (int i = 0; i < n; ++i) {
297 
298              if (frameBuffers[i] ==
299                  GrDebugGL::getInstance()->getFrameBuffer()->getID()) {
300                  // this ID is the current frame buffer - rebind to the default
301                  GrDebugGL::getInstance()->setFrameBuffer(nullptr);
302              }
303          }
304      }
305 
306      // then actually "delete" the buffers
307      for (int i = 0; i < n; ++i) {
308          GrFrameBufferObj *buffer = GR_FIND(frameBuffers[i],
309                                             GrFrameBufferObj,
310                                             GrDebugGL::kFrameBuffer_ObjTypes);
311          GrAlwaysAssert(buffer);
312 
313          GrAlwaysAssert(!buffer->getDeleted());
314          buffer->deleteAction();
315      }
316  }
317 
debugGLDeleteRenderbuffers(GrGLsizei n,const GrGLuint * renderBuffers)318  GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteRenderbuffers(GrGLsizei n,
319                                                          const GrGLuint *renderBuffers) {
320 
321      // first potentially unbind the buffers
322      if (GrDebugGL::getInstance()->getRenderBuffer()) {
323          for (int i = 0; i < n; ++i) {
324 
325              if (renderBuffers[i] ==
326                  GrDebugGL::getInstance()->getRenderBuffer()->getID()) {
327                  // this ID is the current render buffer - make no
328                  // render buffer be bound
329                  GrDebugGL::getInstance()->setRenderBuffer(nullptr);
330              }
331          }
332      }
333 
334      // TODO: fuse the following block with DeleteTextures?
335      // Open GL will remove a deleted render buffer from the active frame
336      // buffer but not from any other frame buffer
337      if (GrDebugGL::getInstance()->getFrameBuffer()) {
338 
339          GrFrameBufferObj *frameBuffer =
340                                GrDebugGL::getInstance()->getFrameBuffer();
341 
342          for (int i = 0; i < n; ++i) {
343 
344              if (frameBuffer->getColor() &&
345                  renderBuffers[i] == frameBuffer->getColor()->getID()) {
346                  frameBuffer->setColor(nullptr);
347              }
348              if (frameBuffer->getDepth() &&
349                  renderBuffers[i] == frameBuffer->getDepth()->getID()) {
350                  frameBuffer->setDepth(nullptr);
351              }
352              if (frameBuffer->getStencil() &&
353                  renderBuffers[i] == frameBuffer->getStencil()->getID()) {
354                  frameBuffer->setStencil(nullptr);
355              }
356          }
357      }
358 
359      // then actually "delete" the buffers
360      for (int i = 0; i < n; ++i) {
361          GrRenderBufferObj *buffer = GR_FIND(renderBuffers[i],
362                                              GrRenderBufferObj,
363                                              GrDebugGL::kRenderBuffer_ObjTypes);
364          GrAlwaysAssert(buffer);
365 
366          // OpenGL gives no guarantees if a render buffer is deleted
367          // while attached to something other than the currently
368          // bound frame buffer
369          GrAlwaysAssert(!buffer->getColorBound());
370          GrAlwaysAssert(!buffer->getDepthBound());
371          // However, at GrContext destroy time we release all GrRsources and so stencil buffers
372          // may get deleted before FBOs that refer to them.
373          //GrAlwaysAssert(!buffer->getStencilBound());
374 
375          GrAlwaysAssert(!buffer->getDeleted());
376          buffer->deleteAction();
377      }
378  }
379 
debugGLFramebufferRenderbuffer(GrGLenum target,GrGLenum attachment,GrGLenum renderbuffertarget,GrGLuint renderBufferID)380  GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferRenderbuffer(GrGLenum target,
381                                                              GrGLenum attachment,
382                                                              GrGLenum renderbuffertarget,
383                                                              GrGLuint renderBufferID) {
384 
385      GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
386      GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
387                     GR_GL_DEPTH_ATTACHMENT == attachment ||
388                     GR_GL_STENCIL_ATTACHMENT == attachment);
389      GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
390 
391      GrFrameBufferObj *framebuffer = GrDebugGL::getInstance()->getFrameBuffer();
392      // A render buffer cannot be attached to the default framebuffer
393      GrAlwaysAssert(framebuffer);
394 
395      // a renderBufferID of 0 is acceptable - it unbinds the current
396      // render buffer
397      GrRenderBufferObj *renderbuffer = GR_FIND(renderBufferID,
398                                                GrRenderBufferObj,
399                                                GrDebugGL::kRenderBuffer_ObjTypes);
400 
401      switch (attachment) {
402      case GR_GL_COLOR_ATTACHMENT0:
403          framebuffer->setColor(renderbuffer);
404          break;
405      case GR_GL_DEPTH_ATTACHMENT:
406          framebuffer->setDepth(renderbuffer);
407          break;
408      case GR_GL_STENCIL_ATTACHMENT:
409          framebuffer->setStencil(renderbuffer);
410          break;
411      default:
412          GrAlwaysAssert(false);
413          break;
414      };
415 
416  }
417 
418  ////////////////////////////////////////////////////////////////////////////////
debugGLFramebufferTexture2D(GrGLenum target,GrGLenum attachment,GrGLenum textarget,GrGLuint textureID,GrGLint level)419  GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferTexture2D(GrGLenum target,
420                                                           GrGLenum attachment,
421                                                           GrGLenum textarget,
422                                                           GrGLuint textureID,
423                                                           GrGLint level) {
424 
425      GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
426      GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
427                     GR_GL_DEPTH_ATTACHMENT == attachment ||
428                     GR_GL_STENCIL_ATTACHMENT == attachment);
429      GrAlwaysAssert(GR_GL_TEXTURE_2D == textarget);
430 
431      GrFrameBufferObj *framebuffer = GrDebugGL::getInstance()->getFrameBuffer();
432      // A texture cannot be attached to the default framebuffer
433      GrAlwaysAssert(framebuffer);
434 
435      // A textureID of 0 is allowed - it unbinds the currently bound texture
436      GrTextureObj *texture = GR_FIND(textureID, GrTextureObj,
437                                      GrDebugGL::kTexture_ObjTypes);
438      if (texture) {
439          // The texture shouldn't be bound to a texture unit - this
440          // could lead to a feedback loop
441          GrAlwaysAssert(!texture->getBound());
442      }
443 
444      GrAlwaysAssert(0 == level);
445 
446      switch (attachment) {
447      case GR_GL_COLOR_ATTACHMENT0:
448          framebuffer->setColor(texture);
449          break;
450      case GR_GL_DEPTH_ATTACHMENT:
451          framebuffer->setDepth(texture);
452          break;
453      case GR_GL_STENCIL_ATTACHMENT:
454          framebuffer->setStencil(texture);
455          break;
456      default:
457          GrAlwaysAssert(false);
458          break;
459      };
460  }
461 
debugGLCreateProgram()462 GrGLuint GR_GL_FUNCTION_TYPE debugGLCreateProgram() {
463 
464     GrProgramObj *program = GR_CREATE(GrProgramObj,
465                                       GrDebugGL::kProgram_ObjTypes);
466 
467     return program->getID();
468 }
469 
debugGLCreateShader(GrGLenum type)470 GrGLuint GR_GL_FUNCTION_TYPE debugGLCreateShader(GrGLenum type) {
471 
472     GrAlwaysAssert(GR_GL_VERTEX_SHADER == type ||
473                    GR_GL_FRAGMENT_SHADER == type);
474 
475     GrShaderObj *shader = GR_CREATE(GrShaderObj, GrDebugGL::kShader_ObjTypes);
476     shader->setType(type);
477 
478     return shader->getID();
479 }
480 
debugGLDeleteProgram(GrGLuint programID)481 GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteProgram(GrGLuint programID) {
482 
483     GrProgramObj *program = GR_FIND(programID,
484                                     GrProgramObj,
485                                     GrDebugGL::kProgram_ObjTypes);
486     GrAlwaysAssert(program);
487 
488     if (program->getRefCount()) {
489         // someone is still using this program so we can't delete it here
490         program->setMarkedForDeletion();
491     } else {
492         program->deleteAction();
493     }
494 }
495 
debugGLDeleteShader(GrGLuint shaderID)496 GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteShader(GrGLuint shaderID) {
497 
498     GrShaderObj *shader = GR_FIND(shaderID,
499                                   GrShaderObj,
500                                   GrDebugGL::kShader_ObjTypes);
501     GrAlwaysAssert(shader);
502 
503     if (shader->getRefCount()) {
504         // someone is still using this shader so we can't delete it here
505         shader->setMarkedForDeletion();
506     } else {
507         shader->deleteAction();
508     }
509 }
510 
debugGenObjs(GrDebugGL::GrObjTypes type,GrGLsizei n,GrGLuint * ids)511 GrGLvoid debugGenObjs(GrDebugGL::GrObjTypes type,
512                       GrGLsizei n,
513                       GrGLuint* ids) {
514 
515    for (int i = 0; i < n; ++i) {
516        GrAlwaysAssert(ids[i] == 0);
517        GrFakeRefObj *obj = GrDebugGL::getInstance()->createObj(type);
518        GrAlwaysAssert(obj);
519        ids[i] = obj->getID();
520     }
521 }
522 
debugGLGenBuffers(GrGLsizei n,GrGLuint * ids)523 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
524     debugGenObjs(GrDebugGL::kBuffer_ObjTypes, n, ids);
525 }
526 
debugGLGenerateMipmap(GrGLenum level)527 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenerateMipmap(GrGLenum level) {
528 }
529 
debugGLGenFramebuffers(GrGLsizei n,GrGLuint * ids)530 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenFramebuffers(GrGLsizei n,
531                                                     GrGLuint* ids) {
532     debugGenObjs(GrDebugGL::kFrameBuffer_ObjTypes, n, ids);
533 }
534 
debugGLGenRenderbuffers(GrGLsizei n,GrGLuint * ids)535 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenRenderbuffers(GrGLsizei n,
536                                                      GrGLuint* ids) {
537     debugGenObjs(GrDebugGL::kRenderBuffer_ObjTypes, n, ids);
538 }
539 
debugGLGenTextures(GrGLsizei n,GrGLuint * ids)540 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenTextures(GrGLsizei n, GrGLuint* ids) {
541     debugGenObjs(GrDebugGL::kTexture_ObjTypes, n, ids);
542 }
543 
debugGLGenVertexArrays(GrGLsizei n,GrGLuint * ids)544 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenVertexArrays(GrGLsizei n, GrGLuint* ids) {
545     debugGenObjs(GrDebugGL::kVertexArray_ObjTypes, n, ids);
546 }
547 
debugGLDeleteVertexArrays(GrGLsizei n,const GrGLuint * ids)548 GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteVertexArrays(GrGLsizei n, const GrGLuint* ids) {
549     for (GrGLsizei i = 0; i < n; ++i) {
550         GrVertexArrayObj* array =
551             GR_FIND(ids[i], GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes);
552         GrAlwaysAssert(array);
553 
554         // Deleting the current vertex array binds object 0
555         if (GrDebugGL::getInstance()->getVertexArray() == array) {
556             GrDebugGL::getInstance()->setVertexArray(nullptr);
557         }
558 
559         if (array->getRefCount()) {
560             // someone is still using this vertex array so we can't delete it here
561             array->setMarkedForDeletion();
562         } else {
563             array->deleteAction();
564         }
565     }
566 }
567 
debugGLBindVertexArray(GrGLuint id)568 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindVertexArray(GrGLuint id) {
569     GrVertexArrayObj* array = GR_FIND(id, GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes);
570     GrAlwaysAssert((0 == id) || array);
571     GrDebugGL::getInstance()->setVertexArray(array);
572 }
573 
debugGLBindBuffer(GrGLenum target,GrGLuint bufferID)574 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindBuffer(GrGLenum target, GrGLuint bufferID) {
575     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
576 
577     GrBufferObj *buffer = GR_FIND(bufferID,
578                                   GrBufferObj,
579                                   GrDebugGL::kBuffer_ObjTypes);
580     // 0 is a permissible bufferID - it unbinds the current buffer
581 
582     switch (target) {
583         case GR_GL_ARRAY_BUFFER:
584             GrDebugGL::getInstance()->setArrayBuffer(buffer);
585             break;
586         case GR_GL_ELEMENT_ARRAY_BUFFER:
587             GrDebugGL::getInstance()->setElementArrayBuffer(buffer);
588             break;
589         default:
590             SkFAIL("Unexpected target to glBindBuffer");
591             break;
592     }
593 }
594 
595 // deleting a bound buffer has the side effect of binding 0
debugGLDeleteBuffers(GrGLsizei n,const GrGLuint * ids)596 GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) {
597     // first potentially unbind the buffers
598     for (int i = 0; i < n; ++i) {
599 
600         if (GrDebugGL::getInstance()->getArrayBuffer() &&
601             ids[i] == GrDebugGL::getInstance()->getArrayBuffer()->getID()) {
602             // this ID is the current array buffer
603             GrDebugGL::getInstance()->setArrayBuffer(nullptr);
604         }
605         if (GrDebugGL::getInstance()->getElementArrayBuffer() &&
606             ids[i] ==
607                 GrDebugGL::getInstance()->getElementArrayBuffer()->getID()) {
608             // this ID is the current element array buffer
609             GrDebugGL::getInstance()->setElementArrayBuffer(nullptr);
610         }
611     }
612 
613     // then actually "delete" the buffers
614     for (int i = 0; i < n; ++i) {
615         GrBufferObj *buffer = GR_FIND(ids[i],
616                                       GrBufferObj,
617                                       GrDebugGL::kBuffer_ObjTypes);
618         GrAlwaysAssert(buffer);
619 
620         GrAlwaysAssert(!buffer->getDeleted());
621         buffer->deleteAction();
622     }
623 }
624 
625 // map a buffer to the caller's address space
debugGLMapBufferRange(GrGLenum target,GrGLintptr offset,GrGLsizeiptr length,GrGLbitfield access)626 GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBufferRange(GrGLenum target, GrGLintptr offset,
627                                                     GrGLsizeiptr length, GrGLbitfield access) {
628     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
629                    GR_GL_ELEMENT_ARRAY_BUFFER == target);
630 
631     // We only expect read access and we expect that the buffer or range is always invalidated.
632     GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
633     GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
634 
635     GrBufferObj *buffer = nullptr;
636     switch (target) {
637         case GR_GL_ARRAY_BUFFER:
638             buffer = GrDebugGL::getInstance()->getArrayBuffer();
639             break;
640         case GR_GL_ELEMENT_ARRAY_BUFFER:
641             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
642             break;
643         default:
644             SkFAIL("Unexpected target to glMapBufferRange");
645             break;
646     }
647 
648     if (buffer) {
649         GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
650         GrAlwaysAssert(!buffer->getMapped());
651         buffer->setMapped(offset, length);
652         return buffer->getDataPtr() + offset;
653     }
654 
655     GrAlwaysAssert(false);
656     return nullptr;        // no buffer bound to the target
657 }
658 
debugGLMapBuffer(GrGLenum target,GrGLenum access)659 GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
660     GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
661 
662     GrBufferObj *buffer = nullptr;
663     switch (target) {
664         case GR_GL_ARRAY_BUFFER:
665             buffer = GrDebugGL::getInstance()->getArrayBuffer();
666             break;
667         case GR_GL_ELEMENT_ARRAY_BUFFER:
668             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
669             break;
670         default:
671             SkFAIL("Unexpected target to glMapBuffer");
672             break;
673     }
674 
675     return debugGLMapBufferRange(target, 0, buffer->getSize(),
676                                  GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
677 }
678 
679 // remove a buffer from the caller's address space
680 // TODO: check if the "access" method from "glMapBuffer" was honored
debugGLUnmapBuffer(GrGLenum target)681 GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
682 
683     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
684                    GR_GL_ELEMENT_ARRAY_BUFFER == target);
685 
686     GrBufferObj *buffer = nullptr;
687     switch (target) {
688         case GR_GL_ARRAY_BUFFER:
689             buffer = GrDebugGL::getInstance()->getArrayBuffer();
690             break;
691         case GR_GL_ELEMENT_ARRAY_BUFFER:
692             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
693             break;
694         default:
695             SkFAIL("Unexpected target to glUnmapBuffer");
696             break;
697     }
698 
699     if (buffer) {
700         GrAlwaysAssert(buffer->getMapped());
701         buffer->resetMapped();
702         return GR_GL_TRUE;
703     }
704 
705     GrAlwaysAssert(false);
706     return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
707 }
708 
debugGLFlushMappedBufferRange(GrGLenum target,GrGLintptr offset,GrGLsizeiptr length)709 GrGLvoid GR_GL_FUNCTION_TYPE debugGLFlushMappedBufferRange(GrGLenum target,
710                                                            GrGLintptr offset,
711                                                            GrGLsizeiptr length) {
712     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
713                    GR_GL_ELEMENT_ARRAY_BUFFER == target);
714 
715     GrBufferObj *buffer = nullptr;
716     switch (target) {
717         case GR_GL_ARRAY_BUFFER:
718             buffer = GrDebugGL::getInstance()->getArrayBuffer();
719             break;
720         case GR_GL_ELEMENT_ARRAY_BUFFER:
721             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
722             break;
723         default:
724             SkFAIL("Unexpected target to glUnmapBuffer");
725             break;
726     }
727 
728     if (buffer) {
729         GrAlwaysAssert(buffer->getMapped());
730         GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
731     } else {
732         GrAlwaysAssert(false);
733     }
734 }
735 
736 
debugGLGetBufferParameteriv(GrGLenum target,GrGLenum value,GrGLint * params)737 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
738                                                          GrGLenum value,
739                                                          GrGLint* params) {
740 
741     GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
742                    GR_GL_ELEMENT_ARRAY_BUFFER == target);
743     GrAlwaysAssert(GR_GL_BUFFER_SIZE == value ||
744                    GR_GL_BUFFER_USAGE == value);
745 
746     GrBufferObj *buffer = nullptr;
747     switch (target) {
748         case GR_GL_ARRAY_BUFFER:
749             buffer = GrDebugGL::getInstance()->getArrayBuffer();
750             break;
751         case GR_GL_ELEMENT_ARRAY_BUFFER:
752             buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
753             break;
754     }
755 
756     GrAlwaysAssert(buffer);
757 
758     switch (value) {
759         case GR_GL_BUFFER_MAPPED:
760             *params = GR_GL_FALSE;
761             if (buffer)
762                 *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
763             break;
764         case GR_GL_BUFFER_SIZE:
765             *params = 0;
766             if (buffer)
767                 *params = SkToInt(buffer->getSize());
768             break;
769         case GR_GL_BUFFER_USAGE:
770             *params = GR_GL_STATIC_DRAW;
771             if (buffer)
772                 *params = buffer->getUsage();
773             break;
774         default:
775             SkFAIL("Unexpected value to glGetBufferParamateriv");
776             break;
777     }
778 };
779 } // end of namespace
780 
781 ////////////////////////////////////////////////////////////////////////////////
782 struct GrDebugGLInterface : public GrGLInterface {
783 
784 public:
785 
786 
GrDebugGLInterfaceGrDebugGLInterface787     GrDebugGLInterface()
788         : fWrapped(nullptr) {
789         GrDebugGL::staticRef();
790     }
791 
~GrDebugGLInterfaceGrDebugGLInterface792     virtual ~GrDebugGLInterface() {
793         GrDebugGL::staticUnRef();
794     }
795 
setWrappedGrDebugGLInterface796     void setWrapped(GrGLInterface *interface) {
797         fWrapped.reset(interface);
798     }
799 
abandonGrDebugGLInterface800     void abandon() const override {
801         GrDebugGL::abandon();
802     }
803 
804     // TODO: there are some issues w/ wrapping another GL interface inside the
805     // debug interface:
806     //      Since none of the "gl" methods are member functions they don't get
807     //      a "this" pointer through which to access "fWrapped"
808     //      This could be worked around by having all of them access the
809     //      "glInterface" pointer - i.e., treating the debug interface as a
810     //      true singleton
811     //
812     //      The problem with this is that we also want to handle OpenGL
813     //      contexts. The natural way to do this is to have multiple debug
814     //      interfaces. Each of which represents a separate context. The
815     //      static ID count would still uniquify IDs across all of them.
816     //      The problem then is that we couldn't treat the debug GL
817     //      interface as a singleton (since there would be one for each
818     //      context).
819     //
820     //      The solution to this is probably to alter SkDebugGlContext's
821     //      "makeCurrent" method to make a call like "makeCurrent(this)" to
822     //      the debug GL interface (assuming that the application will create
823     //      multiple SkGLContext's) to let it switch between the active
824     //      context. Everything in the GrDebugGL object would then need to be
825     //      moved to a GrContextObj and the GrDebugGL object would just switch
826     //      between them. Note that this approach would also require that
827     //      SkDebugGLContext wrap an arbitrary other context
828     //      and then pass the wrapped interface to the debug GL interface.
829 
830 protected:
831 private:
832 
833     SkAutoTUnref<GrGLInterface> fWrapped;
834 
835     typedef GrGLInterface INHERITED;
836 };
837 
838 ////////////////////////////////////////////////////////////////////////////////
GrGLCreateDebugInterface()839 const GrGLInterface* GrGLCreateDebugInterface() {
840     GrGLInterface *interface = new GrDebugGLInterface;
841 
842     interface->fStandard = kGL_GrGLStandard;
843 
844     GrGLInterface::Functions* functions = &interface->fFunctions;
845     functions->fActiveTexture = debugGLActiveTexture;
846     functions->fAttachShader = debugGLAttachShader;
847     functions->fBeginQuery = debugGLBeginQuery;
848     functions->fBindAttribLocation = debugGLBindAttribLocation;
849     functions->fBindBuffer = debugGLBindBuffer;
850     functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
851     functions->fBindTexture = debugGLBindTexture;
852     functions->fBindVertexArray = debugGLBindVertexArray;
853     functions->fBlendColor = noOpGLBlendColor;
854     functions->fBlendEquation = noOpGLBlendEquation;
855     functions->fBlendFunc = noOpGLBlendFunc;
856     functions->fBufferData = debugGLBufferData;
857     functions->fBufferSubData = noOpGLBufferSubData;
858     functions->fClear = noOpGLClear;
859     functions->fClearColor = noOpGLClearColor;
860     functions->fClearStencil = noOpGLClearStencil;
861     functions->fColorMask = noOpGLColorMask;
862     functions->fCompileShader = noOpGLCompileShader;
863     functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
864     functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
865     functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
866     functions->fCreateProgram = debugGLCreateProgram;
867     functions->fCreateShader = debugGLCreateShader;
868     functions->fCullFace = noOpGLCullFace;
869     functions->fDeleteBuffers = debugGLDeleteBuffers;
870     functions->fDeleteProgram = debugGLDeleteProgram;
871     functions->fDeleteQueries = noOpGLDeleteIds;
872     functions->fDeleteShader = debugGLDeleteShader;
873     functions->fDeleteTextures = debugGLDeleteTextures;
874     functions->fDeleteVertexArrays = debugGLDeleteVertexArrays;
875     functions->fDepthMask = noOpGLDepthMask;
876     functions->fDisable = noOpGLDisable;
877     functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
878     functions->fDrawArrays = noOpGLDrawArrays;
879     functions->fDrawArraysInstanced = noOpGLDrawArraysInstanced;
880     functions->fDrawBuffer = noOpGLDrawBuffer;
881     functions->fDrawBuffers = noOpGLDrawBuffers;
882     functions->fDrawElements = noOpGLDrawElements;
883     functions->fDrawElementsInstanced = noOpGLDrawElementsInstanced;
884     functions->fEnable = noOpGLEnable;
885     functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
886     functions->fEndQuery = noOpGLEndQuery;
887     functions->fFinish = noOpGLFinish;
888     functions->fFlush = noOpGLFlush;
889     functions->fFlushMappedBufferRange = debugGLFlushMappedBufferRange;
890     functions->fFrontFace = noOpGLFrontFace;
891     functions->fGenerateMipmap = debugGLGenerateMipmap;
892     functions->fGenBuffers = debugGLGenBuffers;
893     functions->fGenQueries = noOpGLGenIds;
894     functions->fGenTextures = debugGLGenTextures;
895     functions->fGetBufferParameteriv = debugGLGetBufferParameteriv;
896     functions->fGetError = noOpGLGetError;
897     functions->fGetIntegerv = noOpGLGetIntegerv;
898     functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
899     functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
900     functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
901     functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
902     functions->fGetQueryiv = noOpGLGetQueryiv;
903     functions->fGetProgramInfoLog = noOpGLGetInfoLog;
904     functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
905     functions->fGetShaderInfoLog = noOpGLGetInfoLog;
906     functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
907     functions->fGetString = noOpGLGetString;
908     functions->fGetStringi = noOpGLGetStringi;
909     functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
910     functions->fGetUniformLocation = noOpGLGetUniformLocation;
911     functions->fGenVertexArrays = debugGLGenVertexArrays;
912     functions->fLineWidth = noOpGLLineWidth;
913     functions->fLinkProgram = noOpGLLinkProgram;
914     functions->fMapBuffer = debugGLMapBuffer;
915     functions->fMapBufferRange = debugGLMapBufferRange;
916     functions->fPixelStorei = debugGLPixelStorei;
917     functions->fQueryCounter = noOpGLQueryCounter;
918     functions->fReadBuffer = noOpGLReadBuffer;
919     functions->fReadPixels = debugGLReadPixels;
920     functions->fScissor = noOpGLScissor;
921     functions->fShaderSource = noOpGLShaderSource;
922     functions->fStencilFunc = noOpGLStencilFunc;
923     functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
924     functions->fStencilMask = noOpGLStencilMask;
925     functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
926     functions->fStencilOp = noOpGLStencilOp;
927     functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
928     functions->fTexImage2D = noOpGLTexImage2D;
929     functions->fTexParameteri = noOpGLTexParameteri;
930     functions->fTexParameteriv = noOpGLTexParameteriv;
931     functions->fTexSubImage2D = noOpGLTexSubImage2D;
932     functions->fTexStorage2D = noOpGLTexStorage2D;
933     functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
934     functions->fUniform1f = noOpGLUniform1f;
935     functions->fUniform1i = noOpGLUniform1i;
936     functions->fUniform1fv = noOpGLUniform1fv;
937     functions->fUniform1iv = noOpGLUniform1iv;
938     functions->fUniform2f = noOpGLUniform2f;
939     functions->fUniform2i = noOpGLUniform2i;
940     functions->fUniform2fv = noOpGLUniform2fv;
941     functions->fUniform2iv = noOpGLUniform2iv;
942     functions->fUniform3f = noOpGLUniform3f;
943     functions->fUniform3i = noOpGLUniform3i;
944     functions->fUniform3fv = noOpGLUniform3fv;
945     functions->fUniform3iv = noOpGLUniform3iv;
946     functions->fUniform4f = noOpGLUniform4f;
947     functions->fUniform4i = noOpGLUniform4i;
948     functions->fUniform4fv = noOpGLUniform4fv;
949     functions->fUniform4iv = noOpGLUniform4iv;
950     functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
951     functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
952     functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
953     functions->fUnmapBuffer = debugGLUnmapBuffer;
954     functions->fUseProgram = debugGLUseProgram;
955     functions->fVertexAttrib1f = noOpGLVertexAttrib1f;
956     functions->fVertexAttrib2fv = noOpGLVertexAttrib2fv;
957     functions->fVertexAttrib3fv = noOpGLVertexAttrib3fv;
958     functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
959     functions->fVertexAttribDivisor = noOpGLVertexAttribDivisor;
960     functions->fVertexAttribIPointer = noOpGLVertexAttribIPointer;
961     functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
962     functions->fViewport = noOpGLViewport;
963     functions->fBindFramebuffer = debugGLBindFramebuffer;
964     functions->fBindRenderbuffer = debugGLBindRenderbuffer;
965     functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
966     functions->fDeleteFramebuffers = debugGLDeleteFramebuffers;
967     functions->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
968     functions->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
969     functions->fFramebufferTexture2D = debugGLFramebufferTexture2D;
970     functions->fGenFramebuffers = debugGLGenFramebuffers;
971     functions->fGenRenderbuffers = debugGLGenRenderbuffers;
972     functions->fGetFramebufferAttachmentParameteriv =
973                                     noOpGLGetFramebufferAttachmentParameteriv;
974     functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
975     functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
976     functions->fRenderbufferStorageMultisample =
977                                     noOpGLRenderbufferStorageMultisample;
978     functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
979     functions->fResolveMultisampleFramebuffer =
980                                     noOpGLResolveMultisampleFramebuffer;
981     functions->fMatrixLoadf = noOpGLMatrixLoadf;
982     functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
983 
984     functions->fBindFragDataLocationIndexed =
985                                     noOpGLBindFragDataLocationIndexed;
986 
987     interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
988                                 functions->fGetIntegerv, nullptr, GR_EGL_NO_DISPLAY);
989 
990     return interface;
991 }
992