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