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