VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp@ 46515

Last change on this file since 46515 was 46515, checked in by vboxsync, 11 years ago

crOpenGL: more debugging/dumping

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 48.6 KB
Line 
1/* $Id: dump.cpp 46515 2013-06-12 22:47:50Z vboxsync $ */
2
3/** @file
4 * Blitter API implementation
5 */
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#include "cr_blitter.h"
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "cr_mem.h"
24#include "cr_string.h"
25#include <cr_dump.h>
26#include "cr_pixeldata.h"
27
28#include <iprt/cdefs.h>
29#include <iprt/types.h>
30#include <iprt/mem.h>
31
32#include <stdio.h>
33
34#ifdef VBOX_WITH_CRDUMPER
35
36/* dump stuff */
37#pragma pack(1)
38typedef struct VBOX_BITMAPFILEHEADER {
39 uint16_t bfType;
40 uint32_t bfSize;
41 uint16_t bfReserved1;
42 uint16_t bfReserved2;
43 uint32_t bfOffBits;
44} VBOX_BITMAPFILEHEADER;
45
46typedef struct VBOX_BITMAPINFOHEADER {
47 uint32_t biSize;
48 int32_t biWidth;
49 int32_t biHeight;
50 uint16_t biPlanes;
51 uint16_t biBitCount;
52 uint32_t biCompression;
53 uint32_t biSizeImage;
54 int32_t biXPelsPerMeter;
55 int32_t biYPelsPerMeter;
56 uint32_t biClrUsed;
57 uint32_t biClrImportant;
58} VBOX_BITMAPINFOHEADER;
59#pragma pack()
60
61void crDmpImgBmp(CR_BLITTER_IMG *pImg, const char *pszFilename)
62{
63 static int sIdx = 0;
64
65 if ( pImg->bpp != 16
66 && pImg->bpp != 24
67 && pImg->bpp != 32)
68 {
69 crWarning("not supported bpp %d", pImg->bpp);
70 return;
71 }
72
73 FILE *f = fopen (pszFilename, "wb");
74 if (!f)
75 {
76 crWarning("fopen failed");
77 return;
78 }
79
80 VBOX_BITMAPFILEHEADER bf;
81
82 bf.bfType = 'MB';
83 bf.bfSize = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER) + pImg->cbData;
84 bf.bfReserved1 = 0;
85 bf.bfReserved2 = 0;
86 bf.bfOffBits = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER);
87
88 VBOX_BITMAPINFOHEADER bi;
89
90 bi.biSize = sizeof (bi);
91 bi.biWidth = pImg->width;
92 bi.biHeight = pImg->height;
93 bi.biPlanes = 1;
94 bi.biBitCount = pImg->bpp;
95 bi.biCompression = 0;
96 bi.biSizeImage = pImg->cbData;
97 bi.biXPelsPerMeter = 0;
98 bi.biYPelsPerMeter = 0;
99 bi.biClrUsed = 0;
100 bi.biClrImportant = 0;
101
102 fwrite (&bf, 1, sizeof (bf), f);
103 fwrite (&bi, 1, sizeof (bi), f);
104 fwrite (pImg->pvData, 1, pImg->cbData, f);
105
106 fclose (f);
107}
108
109typedef struct CRDUMPGETHWID_DATA
110{
111 GLuint hwid;
112 PFNCRDUMPGETHWID pfnGetHwid;
113 unsigned long Key;
114 void* pvObj;
115} CRDUMPGETHWID_DATA;
116
117static void crDmpHashtableSearchByHwidCB(unsigned long key, void *pData1, void *pData2)
118{
119 CRDUMPGETHWID_DATA *pData = (CRDUMPGETHWID_DATA*)pData2;
120 if (pData->pvObj)
121 return;
122
123 if (pData->hwid == pData->pfnGetHwid(pData1))
124 {
125 pData->Key = key;
126 pData->pvObj = pData1;
127 }
128}
129
130void* crDmpHashtableSearchByHwid(CRHashTable *pHash, GLuint hwid, PFNCRDUMPGETHWID pfnGetHwid, unsigned long *pKey)
131{
132 CRDUMPGETHWID_DATA Data = {0};
133 Data.hwid = hwid;
134 Data.pfnGetHwid = pfnGetHwid;
135 crHashtableWalk(pHash, crDmpHashtableSearchByHwidCB, &Data);
136
137 Assert(Data.pvObj);
138
139 if (pKey)
140 *pKey = Data.Key;
141 return Data.pvObj;
142}
143
144#if 0
145typedef struct CR_SERVER_DUMP_FIND_TEX
146{
147 GLint hwid;
148 CRTextureObj *pTobj
149} CR_SERVER_DUMP_FIND_TEX;
150
151void crServerDumpFindTexCb(unsigned long key, void *pData1, void *pData2)
152{
153 CR_SERVER_DUMP_FIND_TEX *pTex = (CR_SERVER_DUMP_FIND_TEX*)pData2;
154 CRTextureObj *pTobj = (CRTextureObj *)pData1;
155 if (pTobj->hwid == pTex->hwid)
156 pTex->pTobj = pTobj;
157}
158#endif
159
160#define CR_DUMP_MAKE_CASE(_val) case _val: return #_val
161#define CR_DUMP_MAKE_CASE_UNKNOWN(_val, _str, _pDumper) default: { \
162 crWarning("%s %d", (_str), _val); \
163 crDmpStrF((_pDumper), "WARNING: %s %d", (_str), _val); \
164 return (_str); \
165}
166
167DECLINLINE(size_t) crDmpFormatVal(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbVal, const void *pvVal)
168{
169 if (pszElFormat[0] != '%' || pszElFormat[1] == '\0')
170 {
171 crWarning("invalid format %s", pszElFormat);
172 return 0;
173 }
174 switch (cbVal)
175 {
176 case 8:
177 return sprintf_s(pString, cbString, pszElFormat, *((double*)pvVal));
178 case 4:
179 {
180 /* we do not care only about type specifiers, all the rest is not accepted */
181 switch (pszElFormat[1])
182 {
183 case 'f':
184 /* float would be promoted to double */
185 return sprintf_s(pString, cbString, pszElFormat, *((float*)pvVal));
186 default:
187 return sprintf_s(pString, cbString, pszElFormat, *((uint32_t*)pvVal));
188 }
189 }
190 case 2:
191 return sprintf_s(pString, cbString, pszElFormat, *((uint16_t*)pvVal));
192 case 1:
193 return sprintf_s(pString, cbString, pszElFormat, *((uint8_t*)pvVal));
194 default:
195 crWarning("unsupported size %d", cbVal);
196 return 0;
197 }
198}
199
200VBOXDUMPDECL(size_t) crDmpFormatRawArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
201{
202 if (cbString < 2)
203 {
204 crWarning("too few buffer size");
205 return 0;
206 }
207
208 const size_t cbInitString = cbString;
209 *pString++ = '{';
210 --cbString;
211 size_t cbWritten;
212 const uint8_t *pu8Val = (const uint8_t *)pvVal;
213 for (uint32_t i = 0; i < cVal; ++i)
214 {
215 cbWritten = crDmpFormatVal(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val);
216 pu8Val += cbEl;
217 Assert(cbString >= cbWritten);
218 pString += cbWritten;
219 cbString -= cbWritten;
220 if (i != cVal - 1)
221 {
222 cbWritten = sprintf_s(pString, cbString, ", ");
223 Assert(cbString >= cbWritten);
224 pString += cbWritten;
225 cbString -= cbWritten;
226 }
227 }
228
229 if (!cbString)
230 {
231 crWarning("too few buffer size");
232 return 0;
233 }
234 *pString++ = '}';
235 --cbString;
236
237 if (!cbString)
238 {
239 crWarning("too few buffer size");
240 return 0;
241 }
242 *pString++ = '\0';
243
244 return cbInitString - cbString;
245}
246
247VBOXDUMPDECL(size_t) crDmpFormatMatrixArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cX, uint32_t cY)
248{
249 if (cbString < 2)
250 {
251 crWarning("too few buffer size");
252 return 0;
253 }
254
255 const size_t cbInitString = cbString;
256 *pString++ = '{';
257 --cbString;
258 size_t cbWritten;
259 const uint8_t *pu8Val = (const uint8_t *)pvVal;
260 for (uint32_t i = 0; i < cY; ++i)
261 {
262 cbWritten = crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val, cX);
263 pu8Val += (cbEl * cX);
264 Assert(cbString >= cbWritten);
265 pString += cbWritten;
266 cbString -= cbWritten;
267 if (i != cY - 1)
268 {
269 if (cbString < 3)
270 {
271 crWarning("too few buffer size");
272 return 0;
273 }
274 *pString++ = ',';
275 --cbString;
276 *pString++ = '\n';
277 --cbString;
278 }
279 }
280 if (!cbString)
281 {
282 crWarning("too few buffer size");
283 return 0;
284 }
285 *pString++ = '}';
286 --cbString;
287
288 if (!cbString)
289 {
290 crWarning("too few buffer size");
291 return 0;
292 }
293 *pString++ = '\0';
294
295 return cbInitString - cbString;
296}
297
298VBOXDUMPDECL(size_t) crDmpFormatArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
299{
300 switch(cVal)
301 {
302 case 1:
303 return crDmpFormatVal(pString, cbString, pszElFormat, cbEl, pvVal);
304 case 16:
305 return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 4, 4);
306 case 9:
307 return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 3, 3);
308 case 0:
309 crWarning("value array is empty");
310 return 0;
311 default:
312 return crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, pvVal, cVal);
313 }
314}
315
316VBOXDUMPDECL(void) crRecDumpVertAttrv(CR_RECORDER *pRec, CRContext *ctx, GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
317{
318 char aBuf[1024];
319 crDmpFormatRawArray(aBuf, sizeof (aBuf), pszElFormat, cbEl, pvVal, cVal);
320 crDmpStrF(pRec->pDumper, "(%u, %s)", idx, aBuf);
321}
322
323VBOXDUMPDECL(void) crRecDumpVertAttrV(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, va_list pArgList)
324{
325 crDmpStrV(pRec->pDumper, pszFormat, pArgList);
326}
327
328VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, ...)
329{
330 va_list pArgList;
331 va_start(pArgList, pszFormat);
332 crRecDumpVertAttrV(pRec, ctx, pszFormat, pArgList);
333 va_end(pArgList);
334}
335
336void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
337{
338 GLenum texTarget = 0;
339 GLint hwBuf = 0, hwDrawBuf = 0;
340 GLint hwTex = 0, hwObjType = 0, hwTexLevel = 0, hwCubeFace = 0;
341 GLint width = 0, height = 0, depth = 0;
342 CR_BLITTER_IMG Img = {0};
343 VBOXVR_TEXTURE Tex;
344 int rc;
345
346 pRec->pDispatch->GetIntegerv(GL_DRAW_BUFFER, &hwDrawBuf);
347 pRec->pDispatch->GetIntegerv(GL_FRAMEBUFFER_BINDING, &hwBuf);
348 if (hwBuf)
349 {
350 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &hwTex);
351 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &hwObjType);
352 if (hwObjType == GL_TEXTURE)
353 {
354 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &hwTexLevel);
355 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &hwCubeFace);
356 if (hwCubeFace)
357 {
358 crWarning("cube face: unsupported");
359 return;
360 }
361
362 if (hwTexLevel)
363 {
364 crWarning("non-zero tex level attached, unsupported");
365 return;
366 }
367 }
368 else
369 {
370 crWarning("unsupported");
371 return;
372 }
373 }
374 else
375 {
376 crWarning("no buffer attached: unsupported");
377 return;
378 }
379
380 if (ctx->framebufferobject.drawFB)
381 {
382 GLuint iColor = (hwDrawBuf - GL_COLOR_ATTACHMENT0_EXT);
383 CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, ctx->framebufferobject.drawFB->color[iColor].name);
384 CRTextureLevel *pTl = NULL;
385
386 Assert(iColor < RT_ELEMENTS(ctx->framebufferobject.drawFB->color));
387
388 if (!pTobj)
389 {
390 crWarning("no tobj");
391 return;
392 }
393 Assert(pTobj->hwid == hwTex);
394 Assert(pTobj);
395 Assert(ctx->framebufferobject.drawFB->hwid);
396 Assert(ctx->framebufferobject.drawFB->hwid == hwBuf);
397 Assert(ctx->framebufferobject.drawFB->drawbuffer[0] == hwDrawBuf);
398
399 Assert(ctx->framebufferobject.drawFB->color[iColor].level == hwTexLevel);
400 Assert(ctx->framebufferobject.drawFB->color[iColor].type == hwObjType);
401
402 texTarget = pTobj->target;
403
404 Assert(texTarget == GL_TEXTURE_2D);
405
406 pTl = &pTobj->level[0][hwTexLevel];
407
408 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
409 if (!RT_SUCCESS(rc))
410 {
411 crWarning("CrBltEnter failed, rc %d", rc);
412 return;
413 }
414
415 pRec->pDispatch->BindTexture(texTarget, hwTex);
416
417 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_WIDTH, &width);
418 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_HEIGHT, &height);
419 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_DEPTH, &depth);
420
421 Assert(width == pTl->width);
422 Assert(height == pTl->height);
423 Assert(depth == pTl->depth);
424
425 pRec->pDispatch->BindTexture(texTarget, 0);
426 }
427 else
428 {
429 Assert(hwBuf == idRedirFBO);
430 if (!pRedirTex)
431 {
432 crWarning("pRedirTex is expected for non-FBO state!");
433 return;
434 }
435
436 Assert(hwTex == pRedirTex->hwid);
437
438 texTarget = pRedirTex->target;
439
440 width = pRedirTex->width;
441 height = pRedirTex->height;
442
443 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
444 if (!RT_SUCCESS(rc))
445 {
446 crWarning("CrBltEnter failed, rc %d", rc);
447 return;
448 }
449 }
450
451 Tex.width = width;
452 Tex.height = height;
453 Tex.target = texTarget;
454 Tex.hwid = hwTex;
455
456 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
457 if (RT_SUCCESS(rc))
458 {
459 crDmpImg(pRec->pDumper, &Img, "buffer_data");
460 CrBltImgFree(pRec->pBlitter, &Img);
461 }
462 else
463 {
464 crWarning("CrBltImgGetTex failed, rc %d", rc);
465 }
466
467 CrBltLeave(pRec->pBlitter);
468}
469
470static const char *crRecDumpShaderTypeString(GLenum enmType, CR_DUMPER *pDumper)
471{
472 switch (enmType)
473 {
474 CR_DUMP_MAKE_CASE(GL_VERTEX_SHADER_ARB);
475 CR_DUMP_MAKE_CASE(GL_FRAGMENT_SHADER_ARB);
476 CR_DUMP_MAKE_CASE(GL_GEOMETRY_SHADER_ARB);
477 CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Shader Type", pDumper);
478 }
479}
480
481static const char *crRecDumpVarTypeString(GLenum enmType, CR_DUMPER *pDumper)
482{
483 switch (enmType)
484 {
485 CR_DUMP_MAKE_CASE(GL_BYTE);
486 CR_DUMP_MAKE_CASE(GL_UNSIGNED_BYTE);
487 CR_DUMP_MAKE_CASE(GL_SHORT);
488 CR_DUMP_MAKE_CASE(GL_UNSIGNED_SHORT);
489 CR_DUMP_MAKE_CASE(GL_FLOAT);
490 CR_DUMP_MAKE_CASE(GL_DOUBLE);
491 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC2);
492 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC3);
493 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC4);
494 CR_DUMP_MAKE_CASE(GL_INT);
495 CR_DUMP_MAKE_CASE(GL_UNSIGNED_INT);
496 CR_DUMP_MAKE_CASE(GL_INT_VEC2);
497 CR_DUMP_MAKE_CASE(GL_INT_VEC3);
498 CR_DUMP_MAKE_CASE(GL_INT_VEC4);
499 CR_DUMP_MAKE_CASE(GL_BOOL);
500 CR_DUMP_MAKE_CASE(GL_BOOL_VEC2);
501 CR_DUMP_MAKE_CASE(GL_BOOL_VEC3);
502 CR_DUMP_MAKE_CASE(GL_BOOL_VEC4);
503 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2);
504 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3);
505 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4);
506 CR_DUMP_MAKE_CASE(GL_SAMPLER_1D);
507 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D);
508 CR_DUMP_MAKE_CASE(GL_SAMPLER_3D);
509 CR_DUMP_MAKE_CASE(GL_SAMPLER_CUBE);
510 CR_DUMP_MAKE_CASE(GL_SAMPLER_1D_SHADOW);
511 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_SHADOW);
512 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_ARB);
513 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_SHADOW_ARB);
514 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x3);
515 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x4);
516 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x2);
517 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x4);
518 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x2);
519 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x3);
520 CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Variable Type", pDumper);
521 }
522}
523
524static char *crRecDumpGetLine(char **ppszStr, uint32_t *pcbStr)
525{
526 char *pszStr, *pNewLine;
527 const uint32_t cbStr = *pcbStr;
528
529 if (!cbStr)
530 {
531 /* zero-length string */
532 return NULL;
533 }
534
535 if ((*ppszStr)[cbStr-1] != '\0')
536 {
537 crWarning("string should be null-rerminated, forcing it!");
538 (*ppszStr)[cbStr-1] = '\0';
539 }
540 pszStr = *ppszStr;
541 if (!*pszStr)
542 {
543 *pcbStr = 0;
544 return NULL;
545 }
546
547 if (!(pNewLine = strstr(pszStr, "\n")))
548 {
549 /* the string contains a single line! */
550 *ppszStr += strlen(pszStr);
551 *pcbStr = 0;
552 return pszStr;
553 }
554
555 *pNewLine = '\0';
556 *pcbStr = cbStr - (((uintptr_t)pNewLine) - ((uintptr_t)pszStr)) - 1;
557 Assert((*pcbStr) >= 0);
558 Assert((*pcbStr) < cbStr);
559 *ppszStr = pNewLine + 1;
560
561 return pszStr;
562}
563
564static void crRecDumpStrByLine(CR_DUMPER *pDumper, char *pszStr, uint32_t cbStr)
565{
566 char *pszCurLine;
567 while ((pszCurLine = crRecDumpGetLine(&pszStr, &cbStr)) != NULL)
568 {
569 crDmpStrF(pDumper, "%s", pszCurLine);
570 }
571}
572
573static DECLCALLBACK(GLuint) crDmpGetHwidShaderCB(void *pvObj)
574{
575 return ((CRGLSLShader*)pvObj)->hwid;
576}
577
578static DECLCALLBACK(GLuint) crDmpGetHwidProgramCB(void *pvObj)
579{
580 return ((CRGLSLProgram*)pvObj)->hwid;
581}
582
583void crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
584{
585 GLint length = 0;
586 GLint type = 0;
587 GLint compileStatus = 0;
588 CRGLSLShader *pShad;
589
590 if (!id)
591 {
592 unsigned long tstKey = 0;
593 Assert(hwid);
594 pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
595 Assert(pShad);
596 if (!pShad)
597 return;
598 id = pShad->id;
599 Assert(tstKey == id);
600 }
601 else
602 {
603 pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
604 Assert(pShad);
605 if (!pShad)
606 return;
607 }
608
609 if (!hwid)
610 hwid = pShad->hwid;
611
612 Assert(pShad->hwid == hwid);
613 Assert(pShad->id == id);
614
615 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
616 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
617 crDmpStrF(pRec->pDumper, "SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d):", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
618
619 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &length);
620
621 char *pszSource = (char*)crCalloc(length + 1);
622 if (!pszSource)
623 {
624 crWarning("crCalloc failed");
625 crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
626 return;
627 }
628
629 pRec->pDispatch->GetShaderSource(hwid, length, NULL, pszSource);
630 crRecDumpStrByLine(pRec->pDumper, pszSource, length);
631
632 crFree(pszSource);
633
634 crDmpStr(pRec->pDumper, "===END SHADER====");
635}
636
637void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
638{
639 GLint cShaders = 0, linkStatus = 0;
640 char *source = NULL;
641 CRGLSLProgram *pProg;
642
643 if (!id)
644 {
645 unsigned long tstKey = 0;
646 Assert(hwid);
647 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
648 Assert(pProg);
649 if (!pProg)
650 return;
651 id = pProg->id;
652 Assert(tstKey == id);
653 }
654 else
655 {
656 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
657 Assert(pProg);
658 if (!pProg)
659 return;
660 }
661
662 if (!hwid)
663 hwid = pProg->hwid;
664
665 Assert(pProg->hwid == hwid);
666 Assert(pProg->id == id);
667
668 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
669 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
670
671 crDmpStrF(pRec->pDumper, "PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d):", ctx->id, id, hwid, linkStatus, cShaders);
672
673 GLhandleARB *pShaders = (GLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
674 if (!pShaders)
675 {
676 crWarning("crCalloc failed");
677 crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
678 return;
679 }
680
681 pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
682 for (GLint i = 0; i < cShaders; ++i)
683 {
684 crRecDumpShader(pRec, ctx, 0, pShaders[i]);
685 }
686
687 crFree(pShaders);
688
689 GLsizei cbLog = 0;
690
691 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog);
692 if (cbLog)
693 {
694 char *pszLog = (char *)crCalloc(cbLog+1);
695 pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog);
696 crDmpStrF(pRec->pDumper, "==LOG==");
697 crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog);
698 crDmpStrF(pRec->pDumper, "==Done LOG==");
699 crFree(pszLog);
700 }
701 else
702 {
703 crDmpStrF(pRec->pDumper, "==No LOG==");
704 }
705
706 crDmpStr(pRec->pDumper, "===END PROGRAM====");
707}
708
709void crRecRecompileShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
710{
711 GLint length = 0;
712 GLint type = 0;
713 GLint compileStatus = 0;
714 CRGLSLShader *pShad;
715
716 if (!id)
717 {
718 unsigned long tstKey = 0;
719 Assert(hwid);
720 pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
721 Assert(pShad);
722 if (!pShad)
723 return;
724 id = pShad->id;
725 Assert(tstKey == id);
726 }
727 else
728 {
729 pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
730 Assert(pShad);
731 if (!pShad)
732 return;
733 }
734
735 if (!hwid)
736 hwid = pShad->hwid;
737
738 Assert(pShad->hwid == hwid);
739 Assert(pShad->id == id);
740
741 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
742 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
743 crDmpStrF(pRec->pDumper, "==RECOMPILE SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d)==", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
744
745 compileStatus = 0;
746 GLenum status;
747 while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
748 pRec->pDispatch->CompileShader(hwid);
749 while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
750 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
751
752 crDmpStrF(pRec->pDumper, "==Done RECOMPILE SHADER, status(%d)==", compileStatus);
753}
754
755void crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
756{
757 GLint cShaders = 0, linkStatus = 0;
758 char *source = NULL;
759 CRGLSLProgram *pProg;
760
761 if (!id)
762 {
763 unsigned long tstKey = 0;
764 Assert(hwid);
765 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
766 Assert(pProg);
767 if (!pProg)
768 return;
769 id = pProg->id;
770 Assert(tstKey == id);
771 }
772 else
773 {
774 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
775 Assert(pProg);
776 if (!pProg)
777 return;
778 }
779
780 if (!hwid)
781 hwid = pProg->hwid;
782
783 Assert(pProg->hwid == hwid);
784 Assert(pProg->id == id);
785
786 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
787 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
788
789 crDmpStrF(pRec->pDumper, "==RECOMPILE PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d)==", ctx->id, id, hwid, linkStatus, cShaders);
790
791 GLhandleARB *pShaders = (GLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
792 if (!pShaders)
793 {
794 crWarning("crCalloc failed");
795 crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
796 return;
797 }
798
799 pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
800 for (GLint i = 0; i < cShaders; ++i)
801 {
802 crRecRecompileShader(pRec, ctx, 0, pShaders[i]);
803 }
804
805 crFree(pShaders);
806
807 linkStatus = 0;
808 GLenum status;
809 while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
810 pRec->pDispatch->LinkProgram(hwid);
811 while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
812 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
813
814 crDmpStrF(pRec->pDumper, "==Done RECOMPILE PROGRAM, status(%d)==", linkStatus);
815}
816
817VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
818{
819 GLint curProgram = 0;
820 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
821 if (curProgram)
822 {
823 Assert(ctx->glsl.activeProgram);
824 if (!ctx->glsl.activeProgram)
825 crWarning("no active program state with active hw program");
826 else
827 Assert(ctx->glsl.activeProgram->hwid == curProgram);
828 crRecDumpProgram(pRec, ctx, 0, curProgram);
829 }
830 else
831 {
832 Assert(!ctx->glsl.activeProgram);
833 crDmpStrF(pRec->pDumper, "--no active program");
834 }
835}
836
837void crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
838{
839 CRGLSLProgram *pProg;
840
841 if (!id)
842 {
843 unsigned long tstKey = 0;
844 Assert(hwid);
845 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
846 Assert(pProg);
847 if (!pProg)
848 return;
849 id = pProg->id;
850 Assert(tstKey == id);
851 }
852 else
853 {
854 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
855 Assert(pProg);
856 if (!pProg)
857 return;
858 }
859
860 if (!hwid)
861 hwid = pProg->hwid;
862
863 Assert(pProg->hwid == hwid);
864 Assert(pProg->id == id);
865
866 GLint maxUniformLen = 0, activeUniforms = 0, i, j, uniformsCount = 0;
867 GLenum type;
868 GLint size, location;
869 GLchar *pszName = NULL;
870 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
871 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
872
873 if (!maxUniformLen)
874 {
875 if (activeUniforms)
876 {
877 crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
878 activeUniforms = 0;
879 }
880 }
881
882 if (activeUniforms>0)
883 {
884 pszName = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
885
886 if (!pszName)
887 {
888 crWarning("crRecDumpProgramUniforms: out of memory");
889 return;
890 }
891 }
892
893 for (i=0; i<activeUniforms; ++i)
894 {
895 pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
896 uniformsCount += size;
897 }
898 Assert(uniformsCount>=activeUniforms);
899
900 if (activeUniforms>0)
901 {
902 GLfloat fdata[16];
903 GLint idata[16];
904 char *pIndexStr=NULL;
905
906 for (i=0; i<activeUniforms; ++i)
907 {
908 bool fPrintBraketsWithName = false;
909 pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
910
911 if (size>1)
912 {
913 pIndexStr = crStrchr(pszName, '[');
914 if (!pIndexStr)
915 {
916 pIndexStr = pszName+crStrlen(pszName);
917 fPrintBraketsWithName = true;
918 }
919 }
920
921 if (fPrintBraketsWithName)
922 {
923 crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
924 Assert(size > 1);
925 }
926 else
927 crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
928
929 GLint uniformTypeSize = crStateGetUniformSize(type);
930 Assert(uniformTypeSize >= 1);
931
932 for (j=0; j<size; ++j)
933 {
934 if (size>1)
935 {
936 sprintf(pIndexStr, "[%i]", j);
937 }
938 location = pRec->pDispatch->GetUniformLocation(hwid, pszName);
939
940 if (crStateIsIntUniform(type))
941 {
942 pRec->pDispatch->GetUniformiv(hwid, location, &idata[0]);
943 switch (uniformTypeSize)
944 {
945 case 1:
946 crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
947 break;
948 case 2:
949 crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
950 break;
951 case 3:
952 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
953 break;
954 case 4:
955 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
956 break;
957 default:
958 for (GLint k = 0; k < uniformTypeSize; ++k)
959 {
960 crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
961 }
962 break;
963 }
964 }
965 else
966 {
967 pRec->pDispatch->GetUniformfv(hwid, location, &fdata[0]);
968 switch (uniformTypeSize)
969 {
970 case 1:
971 crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
972 break;
973 case 2:
974 crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
975 break;
976 case 3:
977 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
978 break;
979 case 4:
980 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
981 break;
982 default:
983 for (GLint k = 0; k < uniformTypeSize; ++k)
984 {
985 crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
986 }
987 break;
988 }
989 }
990 }
991 }
992
993 crFree(pszName);
994 }
995}
996
997void crRecDumpProgramAttribs(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
998{
999 CRGLSLProgram *pProg;
1000
1001 if (!id)
1002 {
1003 unsigned long tstKey = 0;
1004 Assert(hwid);
1005 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
1006 Assert(pProg);
1007 if (!pProg)
1008 return;
1009 id = pProg->id;
1010 Assert(tstKey == id);
1011 }
1012 else
1013 {
1014 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
1015 Assert(pProg);
1016 if (!pProg)
1017 return;
1018 }
1019
1020 if (!hwid)
1021 hwid = pProg->hwid;
1022
1023 Assert(pProg->hwid == hwid);
1024 Assert(pProg->id == id);
1025
1026 GLint maxAttribLen = 0, activeAttrib = 0, i, j, attribCount = 0;
1027 GLenum type;
1028 GLint size, location;
1029 GLchar *pszName = NULL;
1030 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
1031 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTES, &activeAttrib);
1032
1033 if (!maxAttribLen)
1034 {
1035 if (activeAttrib)
1036 {
1037 crWarning("activeAttrib (%d), while maxAttribLen is zero", activeAttrib);
1038 activeAttrib = 0;
1039 }
1040 }
1041
1042 if (activeAttrib>0)
1043 {
1044 pszName = (GLchar *) crAlloc((maxAttribLen+8)*sizeof(GLchar));
1045
1046 if (!pszName)
1047 {
1048 crWarning("crRecDumpProgramAttrib: out of memory");
1049 return;
1050 }
1051 }
1052
1053 for (i=0; i<activeAttrib; ++i)
1054 {
1055 pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
1056 attribCount += size;
1057 }
1058 Assert(attribCount>=activeAttrib);
1059
1060 if (activeAttrib>0)
1061 {
1062 GLfloat fdata[16];
1063 GLint idata[16];
1064 char *pIndexStr=NULL;
1065
1066 for (i=0; i<activeAttrib; ++i)
1067 {
1068 bool fPrintBraketsWithName = false;
1069 pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
1070 GLint arrayBufferBind = 0, arrayEnabled = 0, arraySize = 0, arrayStride = 0, arrayType = 0, arrayNormalized = 0, arrayInteger = 0/*, arrayDivisor = 0*/;
1071
1072 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &arrayBufferBind);
1073 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &arrayEnabled);
1074 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &arraySize);
1075 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &arrayStride);
1076 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &arrayType);
1077 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &arrayNormalized);
1078 pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &arrayInteger);
1079// pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &arrayDivisor);
1080
1081 if (size>1)
1082 {
1083 pIndexStr = crStrchr(pszName, '[');
1084 if (!pIndexStr)
1085 {
1086 pIndexStr = pszName+crStrlen(pszName);
1087 fPrintBraketsWithName = true;
1088 }
1089 }
1090
1091 if (fPrintBraketsWithName)
1092 {
1093 crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
1094 Assert(size > 1);
1095 }
1096 else
1097 crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
1098
1099 crDmpStrF(pRec->pDumper, "Array buff(%d), enabled(%d) size(%d), stride(%d), type(%s), normalized(%d), integer(%d)", arrayBufferBind, arrayEnabled, arraySize, arrayStride, crRecDumpVarTypeString(arrayType, pRec->pDumper), arrayNormalized, arrayInteger);
1100
1101 GLint attribTypeSize = crStateGetUniformSize(type);
1102 Assert(attribTypeSize >= 1);
1103
1104 for (j=0; j<size; ++j)
1105 {
1106 if (size>1)
1107 {
1108 sprintf(pIndexStr, "[%i]", j);
1109 }
1110 location = pRec->pDispatch->GetAttribLocation(hwid, pszName);
1111
1112 if (crStateIsIntUniform(type))
1113 {
1114 pRec->pDispatch->GetVertexAttribivARB(location, GL_CURRENT_VERTEX_ATTRIB, &idata[0]);
1115 switch (attribTypeSize)
1116 {
1117 case 1:
1118 crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
1119 break;
1120 case 2:
1121 crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
1122 break;
1123 case 3:
1124 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
1125 break;
1126 case 4:
1127 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
1128 break;
1129 default:
1130 for (GLint k = 0; k < attribTypeSize; ++k)
1131 {
1132 crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
1133 }
1134 break;
1135 }
1136 }
1137 else
1138 {
1139 pRec->pDispatch->GetVertexAttribfvARB(location, GL_CURRENT_VERTEX_ATTRIB, &fdata[0]);
1140 switch (attribTypeSize)
1141 {
1142 case 1:
1143 crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
1144 break;
1145 case 2:
1146 crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
1147 break;
1148 case 3:
1149 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
1150 break;
1151 case 4:
1152 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
1153 break;
1154 default:
1155 for (GLint k = 0; k < attribTypeSize; ++k)
1156 {
1157 crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
1158 }
1159 break;
1160 }
1161 }
1162 }
1163 }
1164
1165 crFree(pszName);
1166 }
1167}
1168
1169VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx)
1170{
1171 GLint curProgram = 0;
1172 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
1173 if (curProgram)
1174 {
1175 Assert(ctx->glsl.activeProgram);
1176 if (!ctx->glsl.activeProgram)
1177 crWarning("no active program state with active hw program");
1178 else
1179 Assert(ctx->glsl.activeProgram->hwid == curProgram);
1180 crRecDumpProgramUniforms(pRec, ctx, 0, curProgram);
1181 }
1182 else
1183 {
1184 Assert(!ctx->glsl.activeProgram);
1185 crDmpStrF(pRec->pDumper, "--no active program");
1186 }
1187}
1188
1189VBOXDUMPDECL(void) crRecDumpCurrentProgramAttribs(CR_RECORDER *pRec, CRContext *ctx)
1190{
1191 GLint curProgram = 0;
1192 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
1193 if (curProgram)
1194 {
1195 Assert(ctx->glsl.activeProgram);
1196 if (!ctx->glsl.activeProgram)
1197 crWarning("no active program state with active hw program");
1198 else
1199 Assert(ctx->glsl.activeProgram->hwid == curProgram);
1200 crRecDumpProgramAttribs(pRec, ctx, 0, curProgram);
1201 }
1202 else
1203 {
1204 Assert(!ctx->glsl.activeProgram);
1205 crDmpStrF(pRec->pDumper, "--no active program");
1206 }
1207}
1208
1209VBOXDUMPDECL(void) crRecRecompileCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
1210{
1211 GLint curProgram = 0;
1212 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
1213 if (curProgram)
1214 {
1215 Assert(ctx->glsl.activeProgram);
1216 if (!ctx->glsl.activeProgram)
1217 crWarning("no active program state with active hw program");
1218 else
1219 Assert(ctx->glsl.activeProgram->hwid == curProgram);
1220 crRecRecompileProgram(pRec, ctx, 0, curProgram);
1221 }
1222 else
1223 {
1224 Assert(!ctx->glsl.activeProgram);
1225 crDmpStrF(pRec->pDumper, "--no active program");
1226 }
1227}
1228
1229void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin)
1230{
1231 GLint maxUnits = 0;
1232 GLint curTexUnit = 0;
1233 GLint restoreTexUnit = 0;
1234 GLint curProgram = 0;
1235 int rc;
1236 int i;
1237
1238 pRec->pDispatch->GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits);
1239 maxUnits = RT_MIN(CR_MAX_TEXTURE_UNITS, maxUnits);
1240
1241 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
1242 Assert(curProgram);
1243 Assert(ctx->glsl.activeProgram && ctx->glsl.activeProgram->hwid == curProgram);
1244
1245 Assert(maxUnits);
1246 pRec->pDispatch->GetIntegerv(GL_ACTIVE_TEXTURE, &curTexUnit);
1247 restoreTexUnit = curTexUnit;
1248 Assert(curTexUnit >= GL_TEXTURE0);
1249 Assert(curTexUnit < GL_TEXTURE0 + maxUnits);
1250
1251 Assert(ctx->texture.curTextureUnit == restoreTexUnit - GL_TEXTURE0);
1252
1253 for (i = 0; i < maxUnits; ++i)
1254 {
1255 GLboolean enabled1D;
1256 GLboolean enabled2D;
1257 GLboolean enabled3D;
1258 GLboolean enabledCubeMap;
1259 GLboolean enabledRect;
1260 CRTextureUnit *tu = &ctx->texture.unit[i];
1261
1262 if (i > 1)
1263 break;
1264
1265 if (curTexUnit != i + GL_TEXTURE0)
1266 {
1267 pRec->pDispatch->ActiveTextureARB(i + GL_TEXTURE0);
1268 curTexUnit = i + GL_TEXTURE0;
1269 }
1270
1271 enabled1D = pRec->pDispatch->IsEnabled(GL_TEXTURE_1D);
1272 enabled2D = pRec->pDispatch->IsEnabled(GL_TEXTURE_2D);
1273 enabled3D = pRec->pDispatch->IsEnabled(GL_TEXTURE_3D);
1274 enabledCubeMap = pRec->pDispatch->IsEnabled(GL_TEXTURE_CUBE_MAP_ARB);
1275 enabledRect = pRec->pDispatch->IsEnabled(GL_TEXTURE_RECTANGLE_NV);
1276
1277 Assert(enabled1D == tu->enabled1D);
1278 Assert(enabled2D == tu->enabled2D);
1279 Assert(enabled3D == tu->enabled3D);
1280 Assert(enabledCubeMap == tu->enabledCubeMap);
1281 Assert(enabledRect == tu->enabledRect);
1282
1283 if (enabled1D)
1284 {
1285 crWarning("GL_TEXTURE_1D: unsupported");
1286 }
1287
1288// if (enabled2D)
1289 {
1290 GLint hwTex = 0;
1291 CR_BLITTER_IMG Img = {0};
1292 VBOXVR_TEXTURE Tex;
1293
1294 GLint width = 0, height = 0, depth = 0;
1295 CRTextureObj *pTobj = tu->currentTexture2D;
1296
1297 pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_2D, &hwTex);
1298 if (hwTex)
1299 {
1300 CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
1301 Assert(pTobj
1302 && pTobj->hwid == hwTex);
1303
1304 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
1305 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
1306 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth);
1307
1308 Assert(width == pTl->width);
1309 Assert(height == pTl->height);
1310 Assert(depth == pTl->depth);
1311
1312 Tex.width = width;
1313 Tex.height = height;
1314 Tex.target = GL_TEXTURE_2D;
1315 Tex.hwid = hwTex;
1316
1317 crRecDumpTexParam(pRec, ctx, GL_TEXTURE_2D);
1318 crRecDumpTexEnv(pRec, ctx);
1319 crRecDumpTexGen(pRec, ctx);
1320
1321 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
1322 if (RT_SUCCESS(rc))
1323 {
1324 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
1325 if (RT_SUCCESS(rc))
1326 {
1327 crDmpImgF(pRec->pDumper, &Img, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height);
1328 CrBltImgFree(pRec->pBlitter, &Img);
1329 }
1330 else
1331 {
1332 crWarning("CrBltImgGetTex failed, rc %d", rc);
1333 }
1334 CrBltLeave(pRec->pBlitter);
1335 }
1336 else
1337 {
1338 crWarning("CrBltEnter failed, rc %d", rc);
1339 }
1340 }
1341// else
1342// {
1343// Assert(!pTobj || pTobj->hwid == 0);
1344// crWarning("no TEXTURE_2D bound!");
1345// }
1346 }
1347#if 0
1348 if (enabled3D)
1349 {
1350 crWarning("GL_TEXTURE_3D: unsupported");
1351 }
1352
1353 if (enabledCubeMap)
1354 {
1355 crWarning("GL_TEXTURE_CUBE_MAP_ARB: unsupported");
1356 }
1357
1358// if (enabledRect)
1359 {
1360 GLint hwTex = 0;
1361 CR_BLITTER_IMG Img = {0};
1362 VBOXVR_TEXTURE Tex;
1363
1364 GLint width = 0, height = 0, depth = 0;
1365 CRTextureObj *pTobj = tu->currentTextureRect;
1366
1367 pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_NV, &hwTex);
1368 if (hwTex)
1369 {
1370 CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
1371 Assert(pTobj
1372 && pTobj->hwid == hwTex);
1373
1374 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_WIDTH, &width);
1375 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_HEIGHT, &height);
1376 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_DEPTH, &depth);
1377
1378 Assert(width == pTl->width);
1379 Assert(height == pTl->height);
1380 Assert(depth == pTl->depth);
1381
1382 Tex.width = width;
1383 Tex.height = height;
1384 Tex.target = GL_TEXTURE_RECTANGLE_NV;
1385 Tex.hwid = hwTex;
1386
1387 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
1388 if (RT_SUCCESS(rc))
1389 {
1390 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
1391 if (RT_SUCCESS(rc))
1392 {
1393 crDmpImgF(pRec->pDumper, &Img, "Unit %d: TEXTURE_RECTANGLE data", i);
1394 CrBltImgFree(pRec->pBlitter, &Img);
1395 }
1396 else
1397 {
1398 crWarning("CrBltImgGetTex failed, rc %d", rc);
1399 }
1400 CrBltLeave(pRec->pBlitter);
1401 }
1402 else
1403 {
1404 crWarning("CrBltEnter failed, rc %d", rc);
1405 }
1406 }
1407// else
1408// {
1409// Assert(!pTobj || pTobj->hwid == 0);
1410// crWarning("no TEXTURE_RECTANGLE bound!");
1411// }
1412 }
1413#endif
1414 }
1415
1416 if (curTexUnit != restoreTexUnit)
1417 {
1418 pRec->pDispatch->ActiveTextureARB(restoreTexUnit);
1419 curTexUnit = restoreTexUnit;
1420 }
1421}
1422
1423static void crDmpPrint(const char* szString, ...)
1424{
1425 char szBuffer[4096] = {0};
1426 va_list pArgList;
1427 va_start(pArgList, szString);
1428 RTStrPrintfV(szBuffer, sizeof (szBuffer), szString, pArgList);
1429 va_end(pArgList);
1430
1431 OutputDebugStringA(szBuffer);
1432}
1433
1434static void crDmpPrintDmlCmd(const char* pszDesc, const char* pszCmd)
1435{
1436 crDmpPrint("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd);
1437}
1438
1439void crDmpPrintDumpDmlCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
1440{
1441 char Cmd[1024];
1442 sprintf(Cmd, "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
1443 crDmpPrintDmlCmd(pszDesc, Cmd);
1444}
1445
1446DECLCALLBACK(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
1447{
1448 crDmpPrintDumpDmlCmd(pszEntryDesc, pImg->pvData, pImg->width, pImg->height, pImg->bpp, pImg->pitch);
1449 RT_BREAKPOINT();
1450}
1451
1452DECLCALLBACK(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr)
1453{
1454 OutputDebugStringA(pszStr);
1455}
1456
1457static void crDmpHtmlDumpStrExact(struct CR_HTML_DUMPER * pDumper, const char *pszStr)
1458{
1459 fprintf(pDumper->pFile, "%s", pszStr);
1460 fflush(pDumper->pFile);
1461}
1462
1463static DECLCALLBACK(void) crDmpHtmlDumpStr(struct CR_DUMPER * pDumper, const char*pszStr)
1464{
1465 CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
1466 fprintf(pHtmlDumper->pFile, "<pre>%s</pre>\n", pszStr);
1467 fflush(pHtmlDumper->pFile);
1468}
1469
1470static DECLCALLBACK(void) crDmpHtmlDumpImg(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
1471{
1472 CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
1473 char szBuffer[4096] = {0};
1474 size_t cbWritten = RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/", pHtmlDumper->pszDir);
1475 char *pszFileName = szBuffer + cbWritten;
1476 RTStrPrintf(pszFileName, sizeof(szBuffer) - cbWritten, "img%d.bmp", ++pHtmlDumper->cImg);
1477 crDmpImgBmp(pImg, szBuffer);
1478 fprintf(pHtmlDumper->pFile, "<a href=\"%s\"><pre>%s</pre><img src=\"%s\" alt=\"%s\" width=\"150\" height=\"100\" /></a><br>\n",
1479 pszFileName, pszEntryDesc, pszFileName, pszEntryDesc);
1480 fflush(pHtmlDumper->pFile);
1481}
1482
1483static void crDmpHtmlPrintHeader(struct CR_HTML_DUMPER * pDumper)
1484{
1485 fprintf(pDumper->pFile, "<html><body>\n");
1486 fflush(pDumper->pFile);
1487}
1488
1489static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper)
1490{
1491 fprintf(pDumper->pFile, "</body></html>\n");
1492 fflush(pDumper->pFile);
1493}
1494
1495DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile)
1496{
1497 int rc = VERR_NO_MEMORY;
1498 pDumper->Base.pfnDumpImg = crDmpHtmlDumpImg;
1499 pDumper->Base.pfnDumpStr = crDmpHtmlDumpStr;
1500 pDumper->cImg = 0;
1501 pDumper->pszDir = crStrdup(pszDir);
1502 if (pDumper->pszDir)
1503 {
1504 pDumper->pszFile = crStrdup(pszFile);
1505 if (pDumper->pszFile)
1506 {
1507 char szBuffer[4096] = {0};
1508 RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/%s", pszDir, pszFile);
1509
1510 pDumper->pszFile = crStrdup(pszFile);
1511 pDumper->pFile = fopen(szBuffer, "w");
1512 if (pDumper->pFile)
1513 {
1514 crDmpHtmlPrintHeader(pDumper);
1515 return VINF_SUCCESS;
1516 }
1517 else
1518 {
1519 crWarning("open failed");
1520 rc = VERR_OPEN_FAILED;
1521 }
1522 crFree((void*)pDumper->pszFile);
1523 }
1524 else
1525 {
1526 crWarning("open failed");
1527 }
1528 crFree((void*)pDumper->pszDir);
1529 }
1530 else
1531 {
1532 crWarning("open failed");
1533 }
1534 return rc;
1535}
1536
1537#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette