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