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
23namespace { // suppress no previous prototype warning
24
25////////////////////////////////////////////////////////////////////////////////
26GrGLvoid 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////////////////////////////////////////////////////////////////////////////////
36GrGLvoid 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
51GrGLvoid GR_GL_FUNCTION_TYPE debugGLBeginQuery(GrGLenum target, GrGLuint id) {
52}
53
54GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindAttribLocation(GrGLuint program,
55                                                       GrGLuint index,
56                                                       const char* name) {
57}
58
59////////////////////////////////////////////////////////////////////////////////
60GrGLvoid 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////////////////////////////////////////////////////////////////////////////////
76GrGLvoid 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 = NULL;
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
108GrGLvoid 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
129GrGLvoid 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
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
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
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
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(NULL);
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(NULL);
262             }
263             if (frameBuffer->getDepth() &&
264                 textures[i] == frameBuffer->getDepth()->getID()) {
265                 frameBuffer->setDepth(NULL);
266             }
267             if (frameBuffer->getStencil() &&
268                 textures[i] == frameBuffer->getStencil()->getID()) {
269                 frameBuffer->setStencil(NULL);
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
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(NULL);
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
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(NULL);
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(NULL);
347             }
348             if (frameBuffer->getDepth() &&
349                 renderBuffers[i] == frameBuffer->getDepth()->getID()) {
350                 frameBuffer->setDepth(NULL);
351             }
352             if (frameBuffer->getStencil() &&
353                 renderBuffers[i] == frameBuffer->getStencil()->getID()) {
354                 frameBuffer->setStencil(NULL);
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
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 ////////////////////////////////////////////////////////////////////////////////
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
462GrGLuint GR_GL_FUNCTION_TYPE debugGLCreateProgram() {
463
464    GrProgramObj *program = GR_CREATE(GrProgramObj,
465                                      GrDebugGL::kProgram_ObjTypes);
466
467    return program->getID();
468}
469
470GrGLuint 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
481GrGLvoid 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
496GrGLvoid 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
511GrGLvoid debugGenObjs(GrDebugGL::GrObjTypes type,
512                      GrGLsizei n,
513                      GrGLuint* ids) {
514
515   for (int i = 0; i < n; ++i) {
516        GrFakeRefObj *obj = GrDebugGL::getInstance()->createObj(type);
517        GrAlwaysAssert(obj);
518        ids[i] = obj->getID();
519    }
520}
521
522GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
523    debugGenObjs(GrDebugGL::kBuffer_ObjTypes, n, ids);
524}
525
526GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenerateMipmap(GrGLenum level) {
527}
528
529GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenFramebuffers(GrGLsizei n,
530                                                    GrGLuint* ids) {
531    debugGenObjs(GrDebugGL::kFrameBuffer_ObjTypes, n, ids);
532}
533
534GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenRenderbuffers(GrGLsizei n,
535                                                     GrGLuint* ids) {
536    debugGenObjs(GrDebugGL::kRenderBuffer_ObjTypes, n, ids);
537}
538
539GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenTextures(GrGLsizei n, GrGLuint* ids) {
540    debugGenObjs(GrDebugGL::kTexture_ObjTypes, n, ids);
541}
542
543GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenVertexArrays(GrGLsizei n, GrGLuint* ids) {
544    debugGenObjs(GrDebugGL::kVertexArray_ObjTypes, n, ids);
545}
546
547GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteVertexArrays(GrGLsizei n, const GrGLuint* ids) {
548    for (GrGLsizei i = 0; i < n; ++i) {
549        GrVertexArrayObj* array =
550            GR_FIND(ids[i], GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes);
551        GrAlwaysAssert(array);
552
553        // Deleting the current vertex array binds object 0
554        if (GrDebugGL::getInstance()->getVertexArray() == array) {
555            GrDebugGL::getInstance()->setVertexArray(NULL);
556        }
557
558        if (array->getRefCount()) {
559            // someone is still using this vertex array so we can't delete it here
560            array->setMarkedForDeletion();
561        } else {
562            array->deleteAction();
563        }
564    }
565}
566
567GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindVertexArray(GrGLuint id) {
568    GrVertexArrayObj* array = GR_FIND(id, GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes);
569    GrAlwaysAssert((0 == id) || array);
570    GrDebugGL::getInstance()->setVertexArray(array);
571}
572
573GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindBuffer(GrGLenum target, GrGLuint bufferID) {
574    GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
575
576    GrBufferObj *buffer = GR_FIND(bufferID,
577                                  GrBufferObj,
578                                  GrDebugGL::kBuffer_ObjTypes);
579    // 0 is a permissible bufferID - it unbinds the current buffer
580
581    switch (target) {
582        case GR_GL_ARRAY_BUFFER:
583            GrDebugGL::getInstance()->setArrayBuffer(buffer);
584            break;
585        case GR_GL_ELEMENT_ARRAY_BUFFER:
586            GrDebugGL::getInstance()->setElementArrayBuffer(buffer);
587            break;
588        default:
589            SkFAIL("Unexpected target to glBindBuffer");
590            break;
591    }
592}
593
594// deleting a bound buffer has the side effect of binding 0
595GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) {
596    // first potentially unbind the buffers
597    for (int i = 0; i < n; ++i) {
598
599        if (GrDebugGL::getInstance()->getArrayBuffer() &&
600            ids[i] == GrDebugGL::getInstance()->getArrayBuffer()->getID()) {
601            // this ID is the current array buffer
602            GrDebugGL::getInstance()->setArrayBuffer(NULL);
603        }
604        if (GrDebugGL::getInstance()->getElementArrayBuffer() &&
605            ids[i] ==
606                GrDebugGL::getInstance()->getElementArrayBuffer()->getID()) {
607            // this ID is the current element array buffer
608            GrDebugGL::getInstance()->setElementArrayBuffer(NULL);
609        }
610    }
611
612    // then actually "delete" the buffers
613    for (int i = 0; i < n; ++i) {
614        GrBufferObj *buffer = GR_FIND(ids[i],
615                                      GrBufferObj,
616                                      GrDebugGL::kBuffer_ObjTypes);
617        GrAlwaysAssert(buffer);
618
619        GrAlwaysAssert(!buffer->getDeleted());
620        buffer->deleteAction();
621    }
622}
623
624// map a buffer to the caller's address space
625GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBufferRange(GrGLenum target, GrGLintptr offset,
626                                                    GrGLsizeiptr length, GrGLbitfield access) {
627    GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
628                   GR_GL_ELEMENT_ARRAY_BUFFER == target);
629
630    // We only expect read access and we expect that the buffer or range is always invalidated.
631    GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
632    GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
633
634    GrBufferObj *buffer = NULL;
635    switch (target) {
636        case GR_GL_ARRAY_BUFFER:
637            buffer = GrDebugGL::getInstance()->getArrayBuffer();
638            break;
639        case GR_GL_ELEMENT_ARRAY_BUFFER:
640            buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
641            break;
642        default:
643            SkFAIL("Unexpected target to glMapBufferRange");
644            break;
645    }
646
647    if (buffer) {
648        GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
649        GrAlwaysAssert(!buffer->getMapped());
650        buffer->setMapped(offset, length);
651        return buffer->getDataPtr() + offset;
652    }
653
654    GrAlwaysAssert(false);
655    return NULL;        // no buffer bound to the target
656}
657
658GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
659    GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
660
661    GrBufferObj *buffer = NULL;
662    switch (target) {
663        case GR_GL_ARRAY_BUFFER:
664            buffer = GrDebugGL::getInstance()->getArrayBuffer();
665            break;
666        case GR_GL_ELEMENT_ARRAY_BUFFER:
667            buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
668            break;
669        default:
670            SkFAIL("Unexpected target to glMapBuffer");
671            break;
672    }
673
674    return debugGLMapBufferRange(target, 0, buffer->getSize(),
675                                 GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
676}
677
678// remove a buffer from the caller's address space
679// TODO: check if the "access" method from "glMapBuffer" was honored
680GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
681
682    GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
683                   GR_GL_ELEMENT_ARRAY_BUFFER == target);
684
685    GrBufferObj *buffer = NULL;
686    switch (target) {
687        case GR_GL_ARRAY_BUFFER:
688            buffer = GrDebugGL::getInstance()->getArrayBuffer();
689            break;
690        case GR_GL_ELEMENT_ARRAY_BUFFER:
691            buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
692            break;
693        default:
694            SkFAIL("Unexpected target to glUnmapBuffer");
695            break;
696    }
697
698    if (buffer) {
699        GrAlwaysAssert(buffer->getMapped());
700        buffer->resetMapped();
701        return GR_GL_TRUE;
702    }
703
704    GrAlwaysAssert(false);
705    return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
706}
707
708GrGLvoid GR_GL_FUNCTION_TYPE debugGLFlushMappedBufferRange(GrGLenum target,
709                                                           GrGLintptr offset,
710                                                           GrGLsizeiptr length) {
711    GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
712                   GR_GL_ELEMENT_ARRAY_BUFFER == target);
713
714    GrBufferObj *buffer = NULL;
715    switch (target) {
716        case GR_GL_ARRAY_BUFFER:
717            buffer = GrDebugGL::getInstance()->getArrayBuffer();
718            break;
719        case GR_GL_ELEMENT_ARRAY_BUFFER:
720            buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
721            break;
722        default:
723            SkFAIL("Unexpected target to glUnmapBuffer");
724            break;
725    }
726
727    if (buffer) {
728        GrAlwaysAssert(buffer->getMapped());
729        GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
730    } else {
731        GrAlwaysAssert(false);
732    }
733}
734
735
736GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
737                                                         GrGLenum value,
738                                                         GrGLint* params) {
739
740    GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
741                   GR_GL_ELEMENT_ARRAY_BUFFER == target);
742    GrAlwaysAssert(GR_GL_BUFFER_SIZE == value ||
743                   GR_GL_BUFFER_USAGE == value);
744
745    GrBufferObj *buffer = NULL;
746    switch (target) {
747        case GR_GL_ARRAY_BUFFER:
748            buffer = GrDebugGL::getInstance()->getArrayBuffer();
749            break;
750        case GR_GL_ELEMENT_ARRAY_BUFFER:
751            buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
752            break;
753    }
754
755    GrAlwaysAssert(buffer);
756
757    switch (value) {
758        case GR_GL_BUFFER_MAPPED:
759            *params = GR_GL_FALSE;
760            if (buffer)
761                *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
762            break;
763        case GR_GL_BUFFER_SIZE:
764            *params = 0;
765            if (buffer)
766                *params = SkToInt(buffer->getSize());
767            break;
768        case GR_GL_BUFFER_USAGE:
769            *params = GR_GL_STATIC_DRAW;
770            if (buffer)
771                *params = buffer->getUsage();
772            break;
773        default:
774            SkFAIL("Unexpected value to glGetBufferParamateriv");
775            break;
776    }
777};
778} // end of namespace
779
780////////////////////////////////////////////////////////////////////////////////
781struct GrDebugGLInterface : public GrGLInterface {
782
783public:
784    SK_DECLARE_INST_COUNT(GrDebugGLInterface)
785
786    GrDebugGLInterface()
787        : fWrapped(NULL) {
788        GrDebugGL::staticRef();
789    }
790
791    virtual ~GrDebugGLInterface() {
792        GrDebugGL::staticUnRef();
793    }
794
795    void setWrapped(GrGLInterface *interface) {
796        fWrapped.reset(interface);
797    }
798
799    virtual void abandon() const SK_OVERRIDE {
800        GrDebugGL::abandon();
801    }
802
803    // TODO: there are some issues w/ wrapping another GL interface inside the
804    // debug interface:
805    //      Since none of the "gl" methods are member functions they don't get
806    //      a "this" pointer through which to access "fWrapped"
807    //      This could be worked around by having all of them access the
808    //      "glInterface" pointer - i.e., treating the debug interface as a
809    //      true singleton
810    //
811    //      The problem with this is that we also want to handle OpenGL
812    //      contexts. The natural way to do this is to have multiple debug
813    //      interfaces. Each of which represents a separate context. The
814    //      static ID count would still uniquify IDs across all of them.
815    //      The problem then is that we couldn't treat the debug GL
816    //      interface as a singleton (since there would be one for each
817    //      context).
818    //
819    //      The solution to this is probably to alter SkDebugGlContext's
820    //      "makeCurrent" method to make a call like "makeCurrent(this)" to
821    //      the debug GL interface (assuming that the application will create
822    //      multiple SkGLContextHelper's) to let it switch between the active
823    //      context. Everything in the GrDebugGL object would then need to be
824    //      moved to a GrContextObj and the GrDebugGL object would just switch
825    //      between them. Note that this approach would also require that
826    //      SkDebugGLContext wrap an arbitrary other context
827    //      and then pass the wrapped interface to the debug GL interface.
828
829protected:
830private:
831
832    SkAutoTUnref<GrGLInterface> fWrapped;
833
834    typedef GrGLInterface INHERITED;
835};
836
837////////////////////////////////////////////////////////////////////////////////
838const GrGLInterface* GrGLCreateDebugInterface() {
839    GrGLInterface* interface = SkNEW(GrDebugGLInterface);
840
841    interface->fStandard = kGL_GrGLStandard;
842
843    GrGLInterface::Functions* functions = &interface->fFunctions;
844    functions->fActiveTexture = debugGLActiveTexture;
845    functions->fAttachShader = debugGLAttachShader;
846    functions->fBeginQuery = debugGLBeginQuery;
847    functions->fBindAttribLocation = debugGLBindAttribLocation;
848    functions->fBindBuffer = debugGLBindBuffer;
849    functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
850    functions->fBindTexture = debugGLBindTexture;
851    functions->fBindVertexArray = debugGLBindVertexArray;
852    functions->fBlendColor = noOpGLBlendColor;
853    functions->fBlendFunc = noOpGLBlendFunc;
854    functions->fBufferData = debugGLBufferData;
855    functions->fBufferSubData = noOpGLBufferSubData;
856    functions->fClear = noOpGLClear;
857    functions->fClearColor = noOpGLClearColor;
858    functions->fClearStencil = noOpGLClearStencil;
859    functions->fColorMask = noOpGLColorMask;
860    functions->fCompileShader = noOpGLCompileShader;
861    functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
862    functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
863    functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
864    functions->fCreateProgram = debugGLCreateProgram;
865    functions->fCreateShader = debugGLCreateShader;
866    functions->fCullFace = noOpGLCullFace;
867    functions->fDeleteBuffers = debugGLDeleteBuffers;
868    functions->fDeleteProgram = debugGLDeleteProgram;
869    functions->fDeleteQueries = noOpGLDeleteIds;
870    functions->fDeleteShader = debugGLDeleteShader;
871    functions->fDeleteTextures = debugGLDeleteTextures;
872    functions->fDeleteVertexArrays = debugGLDeleteVertexArrays;
873    functions->fDepthMask = noOpGLDepthMask;
874    functions->fDisable = noOpGLDisable;
875    functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
876    functions->fDrawArrays = noOpGLDrawArrays;
877    functions->fDrawBuffer = noOpGLDrawBuffer;
878    functions->fDrawBuffers = noOpGLDrawBuffers;
879    functions->fDrawElements = noOpGLDrawElements;
880    functions->fEnable = noOpGLEnable;
881    functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
882    functions->fEndQuery = noOpGLEndQuery;
883    functions->fFinish = noOpGLFinish;
884    functions->fFlush = noOpGLFlush;
885    functions->fFlushMappedBufferRange = debugGLFlushMappedBufferRange;
886    functions->fFrontFace = noOpGLFrontFace;
887    functions->fGenerateMipmap = debugGLGenerateMipmap;
888    functions->fGenBuffers = debugGLGenBuffers;
889    functions->fGenQueries = noOpGLGenIds;
890    functions->fGenTextures = debugGLGenTextures;
891    functions->fGetBufferParameteriv = debugGLGetBufferParameteriv;
892    functions->fGetError = noOpGLGetError;
893    functions->fGetIntegerv = noOpGLGetIntegerv;
894    functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
895    functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
896    functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
897    functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
898    functions->fGetQueryiv = noOpGLGetQueryiv;
899    functions->fGetProgramInfoLog = noOpGLGetInfoLog;
900    functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
901    functions->fGetShaderInfoLog = noOpGLGetInfoLog;
902    functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
903    functions->fGetString = noOpGLGetString;
904    functions->fGetStringi = noOpGLGetStringi;
905    functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
906    functions->fGetUniformLocation = noOpGLGetUniformLocation;
907    functions->fGenVertexArrays = debugGLGenVertexArrays;
908    functions->fLineWidth = noOpGLLineWidth;
909    functions->fLinkProgram = noOpGLLinkProgram;
910    functions->fMapBuffer = debugGLMapBuffer;
911    functions->fMapBufferRange = debugGLMapBufferRange;
912    functions->fPixelStorei = debugGLPixelStorei;
913    functions->fQueryCounter = noOpGLQueryCounter;
914    functions->fReadBuffer = noOpGLReadBuffer;
915    functions->fReadPixels = debugGLReadPixels;
916    functions->fScissor = noOpGLScissor;
917    functions->fShaderSource = noOpGLShaderSource;
918    functions->fStencilFunc = noOpGLStencilFunc;
919    functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
920    functions->fStencilMask = noOpGLStencilMask;
921    functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
922    functions->fStencilOp = noOpGLStencilOp;
923    functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
924    functions->fTexImage2D = noOpGLTexImage2D;
925    functions->fTexParameteri = noOpGLTexParameteri;
926    functions->fTexParameteriv = noOpGLTexParameteriv;
927    functions->fTexSubImage2D = noOpGLTexSubImage2D;
928    functions->fTexStorage2D = noOpGLTexStorage2D;
929    functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
930    functions->fUniform1f = noOpGLUniform1f;
931    functions->fUniform1i = noOpGLUniform1i;
932    functions->fUniform1fv = noOpGLUniform1fv;
933    functions->fUniform1iv = noOpGLUniform1iv;
934    functions->fUniform2f = noOpGLUniform2f;
935    functions->fUniform2i = noOpGLUniform2i;
936    functions->fUniform2fv = noOpGLUniform2fv;
937    functions->fUniform2iv = noOpGLUniform2iv;
938    functions->fUniform3f = noOpGLUniform3f;
939    functions->fUniform3i = noOpGLUniform3i;
940    functions->fUniform3fv = noOpGLUniform3fv;
941    functions->fUniform3iv = noOpGLUniform3iv;
942    functions->fUniform4f = noOpGLUniform4f;
943    functions->fUniform4i = noOpGLUniform4i;
944    functions->fUniform4fv = noOpGLUniform4fv;
945    functions->fUniform4iv = noOpGLUniform4iv;
946    functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
947    functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
948    functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
949    functions->fUnmapBuffer = debugGLUnmapBuffer;
950    functions->fUseProgram = debugGLUseProgram;
951    functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
952    functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
953    functions->fViewport = noOpGLViewport;
954    functions->fBindFramebuffer = debugGLBindFramebuffer;
955    functions->fBindRenderbuffer = debugGLBindRenderbuffer;
956    functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
957    functions->fDeleteFramebuffers = debugGLDeleteFramebuffers;
958    functions->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
959    functions->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
960    functions->fFramebufferTexture2D = debugGLFramebufferTexture2D;
961    functions->fGenFramebuffers = debugGLGenFramebuffers;
962    functions->fGenRenderbuffers = debugGLGenRenderbuffers;
963    functions->fGetFramebufferAttachmentParameteriv =
964                                    noOpGLGetFramebufferAttachmentParameteriv;
965    functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
966    functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
967    functions->fRenderbufferStorageMultisample =
968                                    noOpGLRenderbufferStorageMultisample;
969    functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
970    functions->fResolveMultisampleFramebuffer =
971                                    noOpGLResolveMultisampleFramebuffer;
972    functions->fMatrixLoadf = noOpGLMatrixLoadf;
973    functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
974
975    functions->fBindFragDataLocationIndexed =
976                                    noOpGLBindFragDataLocationIndexed;
977
978    interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
979                                functions->fGetIntegerv);
980
981    return interface;
982}
983