|
1 |
|
2 /* |
|
3 * Copyright 2012 Google Inc. |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "gl/GrGLInterface.h" |
|
11 #include "GrDebugGL.h" |
|
12 #include "GrShaderObj.h" |
|
13 #include "GrProgramObj.h" |
|
14 #include "GrBufferObj.h" |
|
15 #include "GrTextureUnitObj.h" |
|
16 #include "GrTextureObj.h" |
|
17 #include "GrFrameBufferObj.h" |
|
18 #include "GrRenderBufferObj.h" |
|
19 #include "GrVertexArrayObj.h" |
|
20 #include "SkFloatingPoint.h" |
|
21 #include "../GrGLNoOpInterface.h" |
|
22 |
|
23 namespace { // suppress no previous prototype warning |
|
24 |
|
25 //////////////////////////////////////////////////////////////////////////////// |
|
26 GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture) { |
|
27 |
|
28 // Ganesh offsets the texture unit indices |
|
29 texture -= GR_GL_TEXTURE0; |
|
30 GrAlwaysAssert(texture < GrDebugGL::getInstance()->getMaxTextureUnits()); |
|
31 |
|
32 GrDebugGL::getInstance()->setCurTextureUnit(texture); |
|
33 } |
|
34 |
|
35 //////////////////////////////////////////////////////////////////////////////// |
|
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 |
|
51 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBeginQuery(GrGLenum target, GrGLuint id) { |
|
52 } |
|
53 |
|
54 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindAttribLocation(GrGLuint program, |
|
55 GrGLuint index, |
|
56 const char* name) { |
|
57 } |
|
58 |
|
59 //////////////////////////////////////////////////////////////////////////////// |
|
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 //////////////////////////////////////////////////////////////////////////////// |
|
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 = 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 |
|
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 |
|
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 |
|
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 (NULL != frameBuffer->getColor() && |
|
260 textures[i] == frameBuffer->getColor()->getID()) { |
|
261 frameBuffer->setColor(NULL); |
|
262 } |
|
263 if (NULL != frameBuffer->getDepth() && |
|
264 textures[i] == frameBuffer->getDepth()->getID()) { |
|
265 frameBuffer->setDepth(NULL); |
|
266 } |
|
267 if (NULL != 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 (NULL != frameBuffer->getColor() && |
|
345 renderBuffers[i] == frameBuffer->getColor()->getID()) { |
|
346 frameBuffer->setColor(NULL); |
|
347 } |
|
348 if (NULL != frameBuffer->getDepth() && |
|
349 renderBuffers[i] == frameBuffer->getDepth()->getID()) { |
|
350 frameBuffer->setDepth(NULL); |
|
351 } |
|
352 if (NULL != 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(NULL != 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(NULL != 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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
511 GrGLvoid 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 |
|
522 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenBuffers(GrGLsizei n, GrGLuint* ids) { |
|
523 debugGenObjs(GrDebugGL::kBuffer_ObjTypes, n, ids); |
|
524 } |
|
525 |
|
526 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenerateMipmap(GrGLenum level) { |
|
527 } |
|
528 |
|
529 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenFramebuffers(GrGLsizei n, |
|
530 GrGLuint* ids) { |
|
531 debugGenObjs(GrDebugGL::kFrameBuffer_ObjTypes, n, ids); |
|
532 } |
|
533 |
|
534 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenRenderbuffers(GrGLsizei n, |
|
535 GrGLuint* ids) { |
|
536 debugGenObjs(GrDebugGL::kRenderBuffer_ObjTypes, n, ids); |
|
537 } |
|
538 |
|
539 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenTextures(GrGLsizei n, GrGLuint* ids) { |
|
540 debugGenObjs(GrDebugGL::kTexture_ObjTypes, n, ids); |
|
541 } |
|
542 |
|
543 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenVertexArrays(GrGLsizei n, GrGLuint* ids) { |
|
544 debugGenObjs(GrDebugGL::kVertexArray_ObjTypes, n, ids); |
|
545 } |
|
546 |
|
547 GrGLvoid 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 |
|
567 GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindVertexArray(GrGLuint id) { |
|
568 GrVertexArrayObj* array = GR_FIND(id, GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes); |
|
569 GrAlwaysAssert((0 == id) || NULL != array); |
|
570 GrDebugGL::getInstance()->setVertexArray(array); |
|
571 } |
|
572 |
|
573 GrGLvoid 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 GrCrash("Unexpected target to glBindBuffer"); |
|
590 break; |
|
591 } |
|
592 } |
|
593 |
|
594 // deleting a bound buffer has the side effect of binding 0 |
|
595 GrGLvoid 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 |
|
625 GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) { |
|
626 |
|
627 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || |
|
628 GR_GL_ELEMENT_ARRAY_BUFFER == target); |
|
629 // GR_GL_READ_ONLY == access || || GR_GL_READ_WRIT == access); |
|
630 GrAlwaysAssert(GR_GL_WRITE_ONLY == access); |
|
631 |
|
632 GrBufferObj *buffer = NULL; |
|
633 switch (target) { |
|
634 case GR_GL_ARRAY_BUFFER: |
|
635 buffer = GrDebugGL::getInstance()->getArrayBuffer(); |
|
636 break; |
|
637 case GR_GL_ELEMENT_ARRAY_BUFFER: |
|
638 buffer = GrDebugGL::getInstance()->getElementArrayBuffer(); |
|
639 break; |
|
640 default: |
|
641 GrCrash("Unexpected target to glMapBuffer"); |
|
642 break; |
|
643 } |
|
644 |
|
645 if (buffer) { |
|
646 GrAlwaysAssert(!buffer->getMapped()); |
|
647 buffer->setMapped(); |
|
648 return buffer->getDataPtr(); |
|
649 } |
|
650 |
|
651 GrAlwaysAssert(false); |
|
652 return NULL; // no buffer bound to the target |
|
653 } |
|
654 |
|
655 // remove a buffer from the caller's address space |
|
656 // TODO: check if the "access" method from "glMapBuffer" was honored |
|
657 GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) { |
|
658 |
|
659 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || |
|
660 GR_GL_ELEMENT_ARRAY_BUFFER == target); |
|
661 |
|
662 GrBufferObj *buffer = NULL; |
|
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 GrCrash("Unexpected target to glUnmapBuffer"); |
|
672 break; |
|
673 } |
|
674 |
|
675 if (buffer) { |
|
676 GrAlwaysAssert(buffer->getMapped()); |
|
677 buffer->resetMapped(); |
|
678 return GR_GL_TRUE; |
|
679 } |
|
680 |
|
681 GrAlwaysAssert(false); |
|
682 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION; |
|
683 } |
|
684 |
|
685 GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target, |
|
686 GrGLenum value, |
|
687 GrGLint* params) { |
|
688 |
|
689 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || |
|
690 GR_GL_ELEMENT_ARRAY_BUFFER == target); |
|
691 GrAlwaysAssert(GR_GL_BUFFER_SIZE == value || |
|
692 GR_GL_BUFFER_USAGE == value); |
|
693 |
|
694 GrBufferObj *buffer = NULL; |
|
695 switch (target) { |
|
696 case GR_GL_ARRAY_BUFFER: |
|
697 buffer = GrDebugGL::getInstance()->getArrayBuffer(); |
|
698 break; |
|
699 case GR_GL_ELEMENT_ARRAY_BUFFER: |
|
700 buffer = GrDebugGL::getInstance()->getElementArrayBuffer(); |
|
701 break; |
|
702 } |
|
703 |
|
704 GrAlwaysAssert(buffer); |
|
705 |
|
706 switch (value) { |
|
707 case GR_GL_BUFFER_MAPPED: |
|
708 *params = GR_GL_FALSE; |
|
709 if (buffer) |
|
710 *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE; |
|
711 break; |
|
712 case GR_GL_BUFFER_SIZE: |
|
713 *params = 0; |
|
714 if (buffer) |
|
715 *params = buffer->getSize(); |
|
716 break; |
|
717 case GR_GL_BUFFER_USAGE: |
|
718 *params = GR_GL_STATIC_DRAW; |
|
719 if (buffer) |
|
720 *params = buffer->getUsage(); |
|
721 break; |
|
722 default: |
|
723 GrCrash("Unexpected value to glGetBufferParamateriv"); |
|
724 break; |
|
725 } |
|
726 }; |
|
727 } // end of namespace |
|
728 |
|
729 //////////////////////////////////////////////////////////////////////////////// |
|
730 struct GrDebugGLInterface : public GrGLInterface { |
|
731 |
|
732 public: |
|
733 SK_DECLARE_INST_COUNT(GrDebugGLInterface) |
|
734 |
|
735 GrDebugGLInterface() |
|
736 : fWrapped(NULL) { |
|
737 GrDebugGL::staticRef(); |
|
738 } |
|
739 |
|
740 virtual ~GrDebugGLInterface() { |
|
741 GrDebugGL::staticUnRef(); |
|
742 } |
|
743 |
|
744 void setWrapped(GrGLInterface *interface) { |
|
745 fWrapped.reset(interface); |
|
746 } |
|
747 |
|
748 // TODO: there are some issues w/ wrapping another GL interface inside the |
|
749 // debug interface: |
|
750 // Since none of the "gl" methods are member functions they don't get |
|
751 // a "this" pointer through which to access "fWrapped" |
|
752 // This could be worked around by having all of them access the |
|
753 // "glInterface" pointer - i.e., treating the debug interface as a |
|
754 // true singleton |
|
755 // |
|
756 // The problem with this is that we also want to handle OpenGL |
|
757 // contexts. The natural way to do this is to have multiple debug |
|
758 // interfaces. Each of which represents a separate context. The |
|
759 // static ID count would still uniquify IDs across all of them. |
|
760 // The problem then is that we couldn't treat the debug GL |
|
761 // interface as a singleton (since there would be one for each |
|
762 // context). |
|
763 // |
|
764 // The solution to this is probably to alter SkDebugGlContext's |
|
765 // "makeCurrent" method to make a call like "makeCurrent(this)" to |
|
766 // the debug GL interface (assuming that the application will create |
|
767 // multiple SkGLContextHelper's) to let it switch between the active |
|
768 // context. Everything in the GrDebugGL object would then need to be |
|
769 // moved to a GrContextObj and the GrDebugGL object would just switch |
|
770 // between them. Note that this approach would also require that |
|
771 // SkDebugGLContext wrap an arbitrary other context |
|
772 // and then pass the wrapped interface to the debug GL interface. |
|
773 |
|
774 protected: |
|
775 private: |
|
776 |
|
777 SkAutoTUnref<GrGLInterface> fWrapped; |
|
778 |
|
779 typedef GrGLInterface INHERITED; |
|
780 }; |
|
781 |
|
782 //////////////////////////////////////////////////////////////////////////////// |
|
783 const GrGLInterface* GrGLCreateDebugInterface() { |
|
784 GrGLInterface* interface = SkNEW(GrDebugGLInterface); |
|
785 |
|
786 interface->fStandard = kGL_GrGLStandard; |
|
787 |
|
788 GrGLInterface::Functions* functions = &interface->fFunctions; |
|
789 functions->fActiveTexture = debugGLActiveTexture; |
|
790 functions->fAttachShader = debugGLAttachShader; |
|
791 functions->fBeginQuery = debugGLBeginQuery; |
|
792 functions->fBindAttribLocation = debugGLBindAttribLocation; |
|
793 functions->fBindBuffer = debugGLBindBuffer; |
|
794 functions->fBindFragDataLocation = noOpGLBindFragDataLocation; |
|
795 functions->fBindTexture = debugGLBindTexture; |
|
796 functions->fBindVertexArray = debugGLBindVertexArray; |
|
797 functions->fBlendColor = noOpGLBlendColor; |
|
798 functions->fBlendFunc = noOpGLBlendFunc; |
|
799 functions->fBufferData = debugGLBufferData; |
|
800 functions->fBufferSubData = noOpGLBufferSubData; |
|
801 functions->fClear = noOpGLClear; |
|
802 functions->fClearColor = noOpGLClearColor; |
|
803 functions->fClearStencil = noOpGLClearStencil; |
|
804 functions->fColorMask = noOpGLColorMask; |
|
805 functions->fCompileShader = noOpGLCompileShader; |
|
806 functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D; |
|
807 functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D; |
|
808 functions->fCreateProgram = debugGLCreateProgram; |
|
809 functions->fCreateShader = debugGLCreateShader; |
|
810 functions->fCullFace = noOpGLCullFace; |
|
811 functions->fDeleteBuffers = debugGLDeleteBuffers; |
|
812 functions->fDeleteProgram = debugGLDeleteProgram; |
|
813 functions->fDeleteQueries = noOpGLDeleteIds; |
|
814 functions->fDeleteShader = debugGLDeleteShader; |
|
815 functions->fDeleteTextures = debugGLDeleteTextures; |
|
816 functions->fDeleteVertexArrays = debugGLDeleteVertexArrays; |
|
817 functions->fDepthMask = noOpGLDepthMask; |
|
818 functions->fDisable = noOpGLDisable; |
|
819 functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray; |
|
820 functions->fDrawArrays = noOpGLDrawArrays; |
|
821 functions->fDrawBuffer = noOpGLDrawBuffer; |
|
822 functions->fDrawBuffers = noOpGLDrawBuffers; |
|
823 functions->fDrawElements = noOpGLDrawElements; |
|
824 functions->fEnable = noOpGLEnable; |
|
825 functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray; |
|
826 functions->fEndQuery = noOpGLEndQuery; |
|
827 functions->fFinish = noOpGLFinish; |
|
828 functions->fFlush = noOpGLFlush; |
|
829 functions->fFrontFace = noOpGLFrontFace; |
|
830 functions->fGenerateMipmap = debugGLGenerateMipmap; |
|
831 functions->fGenBuffers = debugGLGenBuffers; |
|
832 functions->fGenQueries = noOpGLGenIds; |
|
833 functions->fGenTextures = debugGLGenTextures; |
|
834 functions->fGetBufferParameteriv = debugGLGetBufferParameteriv; |
|
835 functions->fGetError = noOpGLGetError; |
|
836 functions->fGetIntegerv = noOpGLGetIntegerv; |
|
837 functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v; |
|
838 functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv; |
|
839 functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v; |
|
840 functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv; |
|
841 functions->fGetQueryiv = noOpGLGetQueryiv; |
|
842 functions->fGetProgramInfoLog = noOpGLGetInfoLog; |
|
843 functions->fGetProgramiv = noOpGLGetShaderOrProgramiv; |
|
844 functions->fGetShaderInfoLog = noOpGLGetInfoLog; |
|
845 functions->fGetShaderiv = noOpGLGetShaderOrProgramiv; |
|
846 functions->fGetString = noOpGLGetString; |
|
847 functions->fGetStringi = noOpGLGetStringi; |
|
848 functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv; |
|
849 functions->fGetUniformLocation = noOpGLGetUniformLocation; |
|
850 functions->fGenVertexArrays = debugGLGenVertexArrays; |
|
851 functions->fLoadIdentity = noOpGLLoadIdentity; |
|
852 functions->fLoadMatrixf = noOpGLLoadMatrixf; |
|
853 functions->fLineWidth = noOpGLLineWidth; |
|
854 functions->fLinkProgram = noOpGLLinkProgram; |
|
855 functions->fMatrixMode = noOpGLMatrixMode; |
|
856 functions->fPixelStorei = debugGLPixelStorei; |
|
857 functions->fQueryCounter = noOpGLQueryCounter; |
|
858 functions->fReadBuffer = noOpGLReadBuffer; |
|
859 functions->fReadPixels = debugGLReadPixels; |
|
860 functions->fScissor = noOpGLScissor; |
|
861 functions->fShaderSource = noOpGLShaderSource; |
|
862 functions->fStencilFunc = noOpGLStencilFunc; |
|
863 functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate; |
|
864 functions->fStencilMask = noOpGLStencilMask; |
|
865 functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate; |
|
866 functions->fStencilOp = noOpGLStencilOp; |
|
867 functions->fStencilOpSeparate = noOpGLStencilOpSeparate; |
|
868 functions->fTexGenfv = noOpGLTexGenfv; |
|
869 functions->fTexGeni = noOpGLTexGeni; |
|
870 functions->fTexImage2D = noOpGLTexImage2D; |
|
871 functions->fTexParameteri = noOpGLTexParameteri; |
|
872 functions->fTexParameteriv = noOpGLTexParameteriv; |
|
873 functions->fTexSubImage2D = noOpGLTexSubImage2D; |
|
874 functions->fTexStorage2D = noOpGLTexStorage2D; |
|
875 functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer; |
|
876 functions->fUniform1f = noOpGLUniform1f; |
|
877 functions->fUniform1i = noOpGLUniform1i; |
|
878 functions->fUniform1fv = noOpGLUniform1fv; |
|
879 functions->fUniform1iv = noOpGLUniform1iv; |
|
880 functions->fUniform2f = noOpGLUniform2f; |
|
881 functions->fUniform2i = noOpGLUniform2i; |
|
882 functions->fUniform2fv = noOpGLUniform2fv; |
|
883 functions->fUniform2iv = noOpGLUniform2iv; |
|
884 functions->fUniform3f = noOpGLUniform3f; |
|
885 functions->fUniform3i = noOpGLUniform3i; |
|
886 functions->fUniform3fv = noOpGLUniform3fv; |
|
887 functions->fUniform3iv = noOpGLUniform3iv; |
|
888 functions->fUniform4f = noOpGLUniform4f; |
|
889 functions->fUniform4i = noOpGLUniform4i; |
|
890 functions->fUniform4fv = noOpGLUniform4fv; |
|
891 functions->fUniform4iv = noOpGLUniform4iv; |
|
892 functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv; |
|
893 functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv; |
|
894 functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv; |
|
895 functions->fUseProgram = debugGLUseProgram; |
|
896 functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv; |
|
897 functions->fVertexAttribPointer = noOpGLVertexAttribPointer; |
|
898 functions->fViewport = noOpGLViewport; |
|
899 functions->fBindFramebuffer = debugGLBindFramebuffer; |
|
900 functions->fBindRenderbuffer = debugGLBindRenderbuffer; |
|
901 functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus; |
|
902 functions->fDeleteFramebuffers = debugGLDeleteFramebuffers; |
|
903 functions->fDeleteRenderbuffers = debugGLDeleteRenderbuffers; |
|
904 functions->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer; |
|
905 functions->fFramebufferTexture2D = debugGLFramebufferTexture2D; |
|
906 functions->fGenFramebuffers = debugGLGenFramebuffers; |
|
907 functions->fGenRenderbuffers = debugGLGenRenderbuffers; |
|
908 functions->fGetFramebufferAttachmentParameteriv = |
|
909 noOpGLGetFramebufferAttachmentParameteriv; |
|
910 functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv; |
|
911 functions->fRenderbufferStorage = noOpGLRenderbufferStorage; |
|
912 functions->fRenderbufferStorageMultisample = |
|
913 noOpGLRenderbufferStorageMultisample; |
|
914 functions->fBlitFramebuffer = noOpGLBlitFramebuffer; |
|
915 functions->fResolveMultisampleFramebuffer = |
|
916 noOpGLResolveMultisampleFramebuffer; |
|
917 functions->fMapBuffer = debugGLMapBuffer; |
|
918 functions->fUnmapBuffer = debugGLUnmapBuffer; |
|
919 functions->fBindFragDataLocationIndexed = |
|
920 noOpGLBindFragDataLocationIndexed; |
|
921 |
|
922 interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi, |
|
923 functions->fGetIntegerv); |
|
924 |
|
925 return interface; |
|
926 } |