VirtualBox

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

最後變更 在這個檔案從49977是 49261,由 vboxsync 提交於 11 年 前

crOpenGL: dumper fixes

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

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