VirtualBox

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

Last change on this file since 46402 was 46402, checked in by vboxsync, 12 years ago

crOpenGL: missing file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.5 KB
Line 
1/* $Id: dump.cpp 46402 2013-06-06 06:35:11Z 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
167VBOXDUMPDECL(size_t) crDmpFormatRawArrayf(char *pString, size_t cbString, const float *pVal, uint32_t cVal)
168{
169 if (cbString < 2)
170 {
171 crWarning("too few buffer size");
172 return 0;
173 }
174
175 const size_t cbInitString = cbString;
176 *pString++ = '{';
177 --cbString;
178 size_t cbWritten;
179 for (uint32_t i = 0; i < cVal; ++i)
180 {
181 cbWritten = sprintf_s(pString, cbString,
182 (i != cVal - 1) ? "%f, " : "%f", *pVal);
183 Assert(cbString >= cbWritten);
184 pString += cbWritten;
185 cbString -= cbWritten;
186 }
187
188 if (!cbString)
189 {
190 crWarning("too few buffer size");
191 return 0;
192 }
193 *pString++ = '}';
194 --cbString;
195
196 if (!cbString)
197 {
198 crWarning("too few buffer size");
199 return 0;
200 }
201 *pString++ = '\0';
202
203 return cbInitString - cbString;
204}
205
206VBOXDUMPDECL(size_t) crDmpFormatMatrixArrayf(char *pString, size_t cbString, const float *pVal, uint32_t cX, uint32_t cY)
207{
208 if (cbString < 2)
209 {
210 crWarning("too few buffer size");
211 return 0;
212 }
213
214 const size_t cbInitString = cbString;
215 *pString++ = '{';
216 --cbString;
217 size_t cbWritten;
218 for (uint32_t i = 0; i < cY; ++i)
219 {
220 cbWritten = crDmpFormatRawArrayf(pString, cbString, pVal, cX);
221 Assert(cbString >= cbWritten);
222 pString += cbWritten;
223 cbString -= cbWritten;
224 if (i != cY - 1)
225 {
226 if (cbString < 3)
227 {
228 crWarning("too few buffer size");
229 return 0;
230 }
231 *pString++ = ',';
232 --cbString;
233 *pString++ = '\n';
234 --cbString;
235 }
236 }
237 if (!cbString)
238 {
239 crWarning("too few buffer size");
240 return 0;
241 }
242 *pString++ = '}';
243 --cbString;
244
245 if (!cbString)
246 {
247 crWarning("too few buffer size");
248 return 0;
249 }
250 *pString++ = '\0';
251
252 return cbInitString - cbString;
253}
254
255VBOXDUMPDECL(size_t) crDmpFormatArrayf(char *pString, size_t cbString, const float *pVal, uint32_t cVal)
256{
257 switch(cVal)
258 {
259 case 1:
260 return sprintf_s(pString, cbString, "%f", *pVal);
261 case 16:
262 return crDmpFormatMatrixArrayf(pString, cbString, pVal, 4, 4);
263 case 9:
264 return crDmpFormatMatrixArrayf(pString, cbString, pVal, 3, 3);
265 case 0:
266 crWarning("value array is empty");
267 return 0;
268 default:
269 return crDmpFormatRawArrayf(pString, cbString, pVal, cVal);
270 }
271}
272
273void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
274{
275 GLenum texTarget = 0;
276 GLint hwBuf = 0, hwDrawBuf = 0;
277 GLint hwTex = 0, hwObjType = 0, hwTexLevel = 0, hwCubeFace = 0;
278 GLint width = 0, height = 0, depth = 0;
279 CR_BLITTER_IMG Img = {0};
280 VBOXVR_TEXTURE Tex;
281 int rc;
282
283 pRec->pDispatch->GetIntegerv(GL_DRAW_BUFFER, &hwDrawBuf);
284 pRec->pDispatch->GetIntegerv(GL_FRAMEBUFFER_BINDING, &hwBuf);
285 if (hwBuf)
286 {
287 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &hwTex);
288 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &hwObjType);
289 if (hwObjType == GL_TEXTURE)
290 {
291 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &hwTexLevel);
292 pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &hwCubeFace);
293 if (hwCubeFace)
294 {
295 crWarning("cube face: unsupported");
296 return;
297 }
298
299 if (hwTexLevel)
300 {
301 crWarning("non-zero tex level attached, unsupported");
302 return;
303 }
304 }
305 else
306 {
307 crWarning("unsupported");
308 return;
309 }
310 }
311 else
312 {
313 crWarning("no buffer attached: unsupported");
314 return;
315 }
316
317 if (ctx->framebufferobject.drawFB)
318 {
319 GLuint iColor = (hwDrawBuf - GL_COLOR_ATTACHMENT0_EXT);
320 CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, ctx->framebufferobject.drawFB->color[iColor].name);
321 CRTextureLevel *pTl = NULL;
322
323 Assert(iColor < RT_ELEMENTS(ctx->framebufferobject.drawFB->color));
324
325 if (!pTobj)
326 {
327 crWarning("no tobj");
328 return;
329 }
330 Assert(pTobj->hwid == hwTex);
331 Assert(pTobj);
332 Assert(ctx->framebufferobject.drawFB->hwid);
333 Assert(ctx->framebufferobject.drawFB->hwid == hwBuf);
334 Assert(ctx->framebufferobject.drawFB->drawbuffer[0] == hwDrawBuf);
335
336 Assert(ctx->framebufferobject.drawFB->color[iColor].level == hwTexLevel);
337 Assert(ctx->framebufferobject.drawFB->color[iColor].type == hwObjType);
338
339 texTarget = pTobj->target;
340
341 Assert(texTarget == GL_TEXTURE_2D);
342
343 pTl = &pTobj->level[0][hwTexLevel];
344
345 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
346 if (!RT_SUCCESS(rc))
347 {
348 crWarning("CrBltEnter failed, rc %d", rc);
349 return;
350 }
351
352 pRec->pDispatch->BindTexture(texTarget, hwTex);
353
354 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_WIDTH, &width);
355 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_HEIGHT, &height);
356 pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_DEPTH, &depth);
357
358 Assert(width == pTl->width);
359 Assert(height == pTl->height);
360 Assert(depth == pTl->depth);
361
362 pRec->pDispatch->BindTexture(texTarget, 0);
363 }
364 else
365 {
366 Assert(hwBuf == idRedirFBO);
367 if (!pRedirTex)
368 {
369 crWarning("pRedirTex is expected for non-FBO state!");
370 return;
371 }
372
373 Assert(hwTex == pRedirTex->hwid);
374
375 texTarget = pRedirTex->target;
376
377 width = pRedirTex->width;
378 height = pRedirTex->height;
379
380 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
381 if (!RT_SUCCESS(rc))
382 {
383 crWarning("CrBltEnter failed, rc %d", rc);
384 return;
385 }
386 }
387
388 Tex.width = width;
389 Tex.height = height;
390 Tex.target = texTarget;
391 Tex.hwid = hwTex;
392
393 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
394 if (RT_SUCCESS(rc))
395 {
396 crDmpImg(pRec->pDumper, &Img, "buffer_data");
397 CrBltImgFree(pRec->pBlitter, &Img);
398 }
399 else
400 {
401 crWarning("CrBltImgGetTex failed, rc %d", rc);
402 }
403
404 CrBltLeave(pRec->pBlitter);
405}
406
407static const char *crRecDumpShaderTypeString(GLenum enmType, CR_DUMPER *pDumper)
408{
409 switch (enmType)
410 {
411 CR_DUMP_MAKE_CASE(GL_VERTEX_SHADER_ARB);
412 CR_DUMP_MAKE_CASE(GL_FRAGMENT_SHADER_ARB);
413 CR_DUMP_MAKE_CASE(GL_GEOMETRY_SHADER_ARB);
414 CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Shader Type", pDumper);
415 }
416}
417
418static const char *crRecDumpVarTypeString(GLenum enmType, CR_DUMPER *pDumper)
419{
420 switch (enmType)
421 {
422 CR_DUMP_MAKE_CASE(GL_FLOAT);
423 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC2);
424 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC3);
425 CR_DUMP_MAKE_CASE(GL_FLOAT_VEC4);
426 CR_DUMP_MAKE_CASE(GL_INT);
427 CR_DUMP_MAKE_CASE(GL_INT_VEC2);
428 CR_DUMP_MAKE_CASE(GL_INT_VEC3);
429 CR_DUMP_MAKE_CASE(GL_INT_VEC4);
430 CR_DUMP_MAKE_CASE(GL_BOOL);
431 CR_DUMP_MAKE_CASE(GL_BOOL_VEC2);
432 CR_DUMP_MAKE_CASE(GL_BOOL_VEC3);
433 CR_DUMP_MAKE_CASE(GL_BOOL_VEC4);
434 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2);
435 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3);
436 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4);
437 CR_DUMP_MAKE_CASE(GL_SAMPLER_1D);
438 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D);
439 CR_DUMP_MAKE_CASE(GL_SAMPLER_3D);
440 CR_DUMP_MAKE_CASE(GL_SAMPLER_CUBE);
441 CR_DUMP_MAKE_CASE(GL_SAMPLER_1D_SHADOW);
442 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_SHADOW);
443 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_ARB);
444 CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_SHADOW_ARB);
445 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x3);
446 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x4);
447 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x2);
448 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x4);
449 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x2);
450 CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x3);
451 CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Variable Type", pDumper);
452 }
453}
454
455static char *crRecDumpGetLine(char **ppszStr, uint32_t *pcbStr)
456{
457 char *pszStr, *pNewLine;
458 const uint32_t cbStr = *pcbStr;
459
460 if (!cbStr)
461 {
462 /* zero-length string */
463 return NULL;
464 }
465
466 if ((*ppszStr)[cbStr-1] != '\0')
467 {
468 crWarning("string should be null-rerminated, forcing it!");
469 (*ppszStr)[cbStr-1] = '\0';
470 }
471 pszStr = *ppszStr;
472 if (!*pszStr)
473 {
474 *pcbStr = 0;
475 return NULL;
476 }
477
478 if (!(pNewLine = strstr(pszStr, "\n")))
479 {
480 /* the string contains a single line! */
481 *ppszStr += strlen(pszStr);
482 *pcbStr = 0;
483 return pszStr;
484 }
485
486 *pNewLine = '\0';
487 *pcbStr = cbStr - (((uintptr_t)pNewLine) - ((uintptr_t)pszStr)) - 1;
488 Assert((*pcbStr) >= 0);
489 Assert((*pcbStr) < cbStr);
490 *ppszStr = pNewLine + 1;
491
492 return pszStr;
493}
494
495static void crRecDumpStrByLine(CR_DUMPER *pDumper, char *pszStr, uint32_t cbStr)
496{
497 char *pszCurLine;
498 while ((pszCurLine = crRecDumpGetLine(&pszStr, &cbStr)) != NULL)
499 {
500 crDmpStrF(pDumper, "%s", pszCurLine);
501 }
502}
503
504static DECLCALLBACK(GLuint) crDmpGetHwidShaderCB(void *pvObj)
505{
506 return ((CRGLSLShader*)pvObj)->hwid;
507}
508
509static DECLCALLBACK(GLuint) crDmpGetHwidProgramCB(void *pvObj)
510{
511 return ((CRGLSLProgram*)pvObj)->hwid;
512}
513
514void crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
515{
516 GLint length = 0;
517 GLint type = 0;
518 GLint compileStatus = 0;
519 CRGLSLShader *pShad;
520
521 if (!id)
522 {
523 unsigned long tstKey = 0;
524 Assert(hwid);
525 pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
526 Assert(pShad);
527 if (!pShad)
528 return;
529 id = pShad->id;
530 Assert(tstKey == id);
531 }
532 else
533 {
534 pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
535 Assert(pShad);
536 if (!pShad)
537 return;
538 }
539
540 if (!hwid)
541 hwid = pShad->hwid;
542
543 Assert(pShad->hwid == hwid);
544 Assert(pShad->id == id);
545
546 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
547 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
548 crDmpStrF(pRec->pDumper, "SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d):", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
549
550 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &length);
551
552 char *pszSource = (char*)crCalloc(length + 1);
553 if (!pszSource)
554 {
555 crWarning("crCalloc failed");
556 crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
557 return;
558 }
559
560 pRec->pDispatch->GetShaderSource(hwid, length, NULL, pszSource);
561 crRecDumpStrByLine(pRec->pDumper, pszSource, length);
562
563 crFree(pszSource);
564
565 crDmpStr(pRec->pDumper, "===END SHADER====");
566}
567
568void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
569{
570 GLint cShaders = 0, linkStatus = 0;
571 char *source = NULL;
572 CRGLSLProgram *pProg;
573
574 if (!id)
575 {
576 unsigned long tstKey = 0;
577 Assert(hwid);
578 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
579 Assert(pProg);
580 if (!pProg)
581 return;
582 id = pProg->id;
583 Assert(tstKey == id);
584 }
585 else
586 {
587 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
588 Assert(pProg);
589 if (!pProg)
590 return;
591 }
592
593 if (!hwid)
594 hwid = pProg->hwid;
595
596 Assert(pProg->hwid == hwid);
597 Assert(pProg->id == id);
598
599 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
600 pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
601
602 crDmpStrF(pRec->pDumper, "PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d):", ctx->id, id, hwid, linkStatus, cShaders);
603
604 GLhandleARB *pShaders = (GLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
605 if (!pShaders)
606 {
607 crWarning("crCalloc failed");
608 crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
609 return;
610 }
611
612 pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
613 for (GLint i = 0; i < cShaders; ++i)
614 {
615 crRecDumpShader(pRec, ctx, 0, pShaders[i]);
616 }
617
618 crFree(pShaders);
619
620 crDmpStr(pRec->pDumper, "===END PROGRAM====");
621}
622
623VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
624{
625 GLint curProgram = 0;
626 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
627 if (curProgram)
628 {
629 Assert(ctx->glsl.activeProgram);
630 if (!ctx->glsl.activeProgram)
631 crWarning("no active program state with active hw program");
632 else
633 Assert(ctx->glsl.activeProgram->hwid == curProgram);
634 crRecDumpProgram(pRec, ctx, 0, curProgram);
635 }
636 else
637 {
638 Assert(!ctx->glsl.activeProgram);
639 crDmpStrF(pRec->pDumper, "--no active program");
640 }
641}
642
643void crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
644{
645 CRGLSLProgram *pProg;
646
647 if (!id)
648 {
649 unsigned long tstKey = 0;
650 Assert(hwid);
651 pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
652 Assert(pProg);
653 if (!pProg)
654 return;
655 id = pProg->id;
656 Assert(tstKey == id);
657 }
658 else
659 {
660 pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
661 Assert(pProg);
662 if (!pProg)
663 return;
664 }
665
666 if (!hwid)
667 hwid = pProg->hwid;
668
669 Assert(pProg->hwid == hwid);
670 Assert(pProg->id == id);
671
672 GLint maxUniformLen = 0, activeUniforms = 0, i, j, uniformsCount = 0;
673 GLenum type;
674 GLint size, location;
675 GLchar *pszName = NULL;
676 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
677 pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
678
679 if (!maxUniformLen)
680 {
681 if (activeUniforms)
682 {
683 crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
684 activeUniforms = 0;
685 }
686 }
687
688 if (activeUniforms>0)
689 {
690 pszName = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
691
692 if (!pszName)
693 {
694 crWarning("crRecDumpProgramUniforms: out of memory");
695 return;
696 }
697 }
698
699 for (i=0; i<activeUniforms; ++i)
700 {
701 pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
702 uniformsCount += size;
703 }
704 Assert(uniformsCount>=activeUniforms);
705
706 if (activeUniforms>0)
707 {
708 GLfloat fdata[16];
709 GLint idata[16];
710 char *pIndexStr=NULL;
711
712 for (i=0; i<activeUniforms; ++i)
713 {
714 bool fPrintBraketsWithName = false;
715 pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
716
717 if (size>1)
718 {
719 pIndexStr = crStrchr(pszName, '[');
720 if (!pIndexStr)
721 {
722 pIndexStr = pszName+crStrlen(pszName);
723 fPrintBraketsWithName = true;
724 }
725 }
726
727 if (fPrintBraketsWithName)
728 {
729 crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
730 Assert(size > 1);
731 }
732 else
733 crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
734
735 GLint uniformTypeSize = crStateGetUniformSize(type);
736 Assert(uniformTypeSize >= 1);
737
738 for (j=0; j<size; ++j)
739 {
740 if (size>1)
741 {
742 sprintf(pIndexStr, "[%i]", j);
743 }
744 location = pRec->pDispatch->GetUniformLocation(hwid, pszName);
745
746 if (crStateIsIntUniform(type))
747 {
748 pRec->pDispatch->GetUniformiv(hwid, location, &idata[0]);
749 switch (uniformTypeSize)
750 {
751 case 1:
752 crDmpStrF(pRec->pDumper, "%s = %d;", pszName, idata[0]);
753 break;
754 case 2:
755 crDmpStrF(pRec->pDumper, "%s = {%d, %d};", pszName, idata[0], idata[1]);
756 break;
757 case 3:
758 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d};", pszName, idata[0], idata[1], idata[2]);
759 break;
760 case 4:
761 crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d};", pszName, idata[0], idata[1], idata[2], idata[3]);
762 break;
763 default:
764 for (GLint k = 0; k < uniformTypeSize; ++k)
765 {
766 crDmpStrF(pRec->pDumper, "%s[%d] = %d;", pszName, k, idata[k]);
767 }
768 break;
769 }
770 }
771 else
772 {
773 pRec->pDispatch->GetUniformfv(hwid, location, &fdata[0]);
774 switch (uniformTypeSize)
775 {
776 case 1:
777 crDmpStrF(pRec->pDumper, "%s = %f;", pszName, fdata[0]);
778 break;
779 case 2:
780 crDmpStrF(pRec->pDumper, "%s = {%f, %f};", pszName, fdata[0], fdata[1]);
781 break;
782 case 3:
783 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f};", pszName, fdata[0], fdata[1], fdata[2]);
784 break;
785 case 4:
786 crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f};", pszName, fdata[0], fdata[1], fdata[2], fdata[3]);
787 break;
788 default:
789 for (GLint k = 0; k < uniformTypeSize; ++k)
790 {
791 crDmpStrF(pRec->pDumper, "%s[%d] = %f;", pszName, k, fdata[k]);
792 }
793 break;
794 }
795 }
796 }
797 }
798
799 crFree(pszName);
800 }
801}
802
803VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx)
804{
805 GLint curProgram = 0;
806 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
807 if (curProgram)
808 {
809 Assert(ctx->glsl.activeProgram);
810 if (!ctx->glsl.activeProgram)
811 crWarning("no active program state with active hw program");
812 else
813 Assert(ctx->glsl.activeProgram->hwid == curProgram);
814 crRecDumpProgramUniforms(pRec, ctx, 0, curProgram);
815 }
816 else
817 {
818 Assert(!ctx->glsl.activeProgram);
819 crDmpStrF(pRec->pDumper, "--no active program");
820 }
821}
822
823void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin)
824{
825 GLint maxUnits = 0;
826 GLint curTexUnit = 0;
827 GLint restoreTexUnit = 0;
828 GLint curProgram = 0;
829 int rc;
830 int i;
831
832 pRec->pDispatch->GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits);
833 maxUnits = RT_MIN(CR_MAX_TEXTURE_UNITS, maxUnits);
834
835 pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
836 Assert(curProgram);
837 Assert(ctx->glsl.activeProgram && ctx->glsl.activeProgram->hwid == curProgram);
838
839 Assert(maxUnits);
840 pRec->pDispatch->GetIntegerv(GL_ACTIVE_TEXTURE, &curTexUnit);
841 restoreTexUnit = curTexUnit;
842 Assert(curTexUnit >= GL_TEXTURE0);
843 Assert(curTexUnit < GL_TEXTURE0 + maxUnits);
844
845 Assert(ctx->texture.curTextureUnit == restoreTexUnit - GL_TEXTURE0);
846
847 for (i = 0; i < maxUnits; ++i)
848 {
849 GLboolean enabled1D;
850 GLboolean enabled2D;
851 GLboolean enabled3D;
852 GLboolean enabledCubeMap;
853 GLboolean enabledRect;
854 CRTextureUnit *tu = &ctx->texture.unit[i];
855
856 if (i > 1)
857 break;
858
859 if (curTexUnit != i + GL_TEXTURE0)
860 {
861 pRec->pDispatch->ActiveTextureARB(i + GL_TEXTURE0);
862 curTexUnit = i + GL_TEXTURE0;
863 }
864
865 enabled1D = pRec->pDispatch->IsEnabled(GL_TEXTURE_1D);
866 enabled2D = pRec->pDispatch->IsEnabled(GL_TEXTURE_2D);
867 enabled3D = pRec->pDispatch->IsEnabled(GL_TEXTURE_3D);
868 enabledCubeMap = pRec->pDispatch->IsEnabled(GL_TEXTURE_CUBE_MAP_ARB);
869 enabledRect = pRec->pDispatch->IsEnabled(GL_TEXTURE_RECTANGLE_NV);
870
871 Assert(enabled1D == tu->enabled1D);
872 Assert(enabled2D == tu->enabled2D);
873 Assert(enabled3D == tu->enabled3D);
874 Assert(enabledCubeMap == tu->enabledCubeMap);
875 Assert(enabledRect == tu->enabledRect);
876
877 if (enabled1D)
878 {
879 crWarning("GL_TEXTURE_1D: unsupported");
880 }
881
882// if (enabled2D)
883 {
884 GLint hwTex = 0;
885 CR_BLITTER_IMG Img = {0};
886 VBOXVR_TEXTURE Tex;
887
888 GLint width = 0, height = 0, depth = 0;
889 CRTextureObj *pTobj = tu->currentTexture2D;
890
891 pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_2D, &hwTex);
892 if (hwTex)
893 {
894 CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
895 Assert(pTobj
896 && pTobj->hwid == hwTex);
897
898 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
899 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
900 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth);
901
902 Assert(width == pTl->width);
903 Assert(height == pTl->height);
904 Assert(depth == pTl->depth);
905
906 Tex.width = width;
907 Tex.height = height;
908 Tex.target = GL_TEXTURE_2D;
909 Tex.hwid = hwTex;
910
911 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
912 if (RT_SUCCESS(rc))
913 {
914 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
915 if (RT_SUCCESS(rc))
916 {
917 crDmpImgF(pRec->pDumper, &Img, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d)", ctx, i, pTobj->id, pTobj->hwid);
918 CrBltImgFree(pRec->pBlitter, &Img);
919 }
920 else
921 {
922 crWarning("CrBltImgGetTex failed, rc %d", rc);
923 }
924 CrBltLeave(pRec->pBlitter);
925 }
926 else
927 {
928 crWarning("CrBltEnter failed, rc %d", rc);
929 }
930 }
931// else
932// {
933// Assert(!pTobj || pTobj->hwid == 0);
934// crWarning("no TEXTURE_2D bound!");
935// }
936 }
937#if 0
938 if (enabled3D)
939 {
940 crWarning("GL_TEXTURE_3D: unsupported");
941 }
942
943 if (enabledCubeMap)
944 {
945 crWarning("GL_TEXTURE_CUBE_MAP_ARB: unsupported");
946 }
947
948// if (enabledRect)
949 {
950 GLint hwTex = 0;
951 CR_BLITTER_IMG Img = {0};
952 VBOXVR_TEXTURE Tex;
953
954 GLint width = 0, height = 0, depth = 0;
955 CRTextureObj *pTobj = tu->currentTextureRect;
956
957 pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_NV, &hwTex);
958 if (hwTex)
959 {
960 CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
961 Assert(pTobj
962 && pTobj->hwid == hwTex);
963
964 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_WIDTH, &width);
965 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_HEIGHT, &height);
966 pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_DEPTH, &depth);
967
968 Assert(width == pTl->width);
969 Assert(height == pTl->height);
970 Assert(depth == pTl->depth);
971
972 Tex.width = width;
973 Tex.height = height;
974 Tex.target = GL_TEXTURE_RECTANGLE_NV;
975 Tex.hwid = hwTex;
976
977 rc = CrBltEnter(pRec->pBlitter, pCurCtx, pCurWin);
978 if (RT_SUCCESS(rc))
979 {
980 rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
981 if (RT_SUCCESS(rc))
982 {
983 crDmpImgF(pRec->pDumper, &Img, "Unit %d: TEXTURE_RECTANGLE data", i);
984 CrBltImgFree(pRec->pBlitter, &Img);
985 }
986 else
987 {
988 crWarning("CrBltImgGetTex failed, rc %d", rc);
989 }
990 CrBltLeave(pRec->pBlitter);
991 }
992 else
993 {
994 crWarning("CrBltEnter failed, rc %d", rc);
995 }
996 }
997// else
998// {
999// Assert(!pTobj || pTobj->hwid == 0);
1000// crWarning("no TEXTURE_RECTANGLE bound!");
1001// }
1002 }
1003#endif
1004 }
1005
1006 if (curTexUnit != restoreTexUnit)
1007 {
1008 pRec->pDispatch->ActiveTextureARB(restoreTexUnit);
1009 curTexUnit = restoreTexUnit;
1010 }
1011}
1012
1013static void crDmpPrint(const char* szString, ...)
1014{
1015 char szBuffer[4096] = {0};
1016 va_list pArgList;
1017 va_start(pArgList, szString);
1018 RTStrPrintfV(szBuffer, sizeof (szBuffer), szString, pArgList);
1019 va_end(pArgList);
1020
1021 OutputDebugStringA(szBuffer);
1022}
1023
1024static void crDmpPrintDmlCmd(const char* pszDesc, const char* pszCmd)
1025{
1026 crDmpPrint("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd);
1027}
1028
1029void crDmpPrintDumpDmlCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
1030{
1031 char Cmd[1024];
1032 sprintf(Cmd, "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
1033 crDmpPrintDmlCmd(pszDesc, Cmd);
1034}
1035
1036DECLCALLBACK(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
1037{
1038 crDmpPrintDumpDmlCmd(pszEntryDesc, pImg->pvData, pImg->width, pImg->height, pImg->bpp, pImg->pitch);
1039 RT_BREAKPOINT();
1040}
1041
1042DECLCALLBACK(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr)
1043{
1044 OutputDebugStringA(pszStr);
1045}
1046
1047static void crDmpHtmlDumpStrExact(struct CR_HTML_DUMPER * pDumper, const char *pszStr)
1048{
1049 fprintf(pDumper->pFile, "%s", pszStr);
1050 fflush(pDumper->pFile);
1051}
1052
1053static DECLCALLBACK(void) crDmpHtmlDumpStr(struct CR_DUMPER * pDumper, const char*pszStr)
1054{
1055 CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
1056 fprintf(pHtmlDumper->pFile, "<pre>%s</pre>\n", pszStr);
1057 fflush(pHtmlDumper->pFile);
1058}
1059
1060static DECLCALLBACK(void) crDmpHtmlDumpImg(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
1061{
1062 CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
1063 char szBuffer[4096] = {0};
1064 size_t cbWritten = RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/", pHtmlDumper->pszDir);
1065 char *pszFileName = szBuffer + cbWritten;
1066 RTStrPrintf(pszFileName, sizeof(szBuffer) - cbWritten, "img%d.bmp", ++pHtmlDumper->cImg);
1067 crDmpImgBmp(pImg, szBuffer);
1068 fprintf(pHtmlDumper->pFile, "<a href=\"%s\"><pre>%s</pre><img src=\"%s\" alt=\"%s\" width=\"150\" height=\"100\" /></a><br>\n",
1069 pszFileName, pszEntryDesc, pszFileName, pszEntryDesc);
1070 fflush(pHtmlDumper->pFile);
1071}
1072
1073static void crDmpHtmlPrintHeader(struct CR_HTML_DUMPER * pDumper)
1074{
1075 fprintf(pDumper->pFile, "<html><body>\n");
1076 fflush(pDumper->pFile);
1077}
1078
1079static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper)
1080{
1081 fprintf(pDumper->pFile, "</body></html>\n");
1082 fflush(pDumper->pFile);
1083}
1084
1085DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile)
1086{
1087 int rc = VERR_NO_MEMORY;
1088 pDumper->Base.pfnDumpImg = crDmpHtmlDumpImg;
1089 pDumper->Base.pfnDumpStr = crDmpHtmlDumpStr;
1090 pDumper->cImg = 0;
1091 pDumper->pszDir = crStrdup(pszDir);
1092 if (pDumper->pszDir)
1093 {
1094 pDumper->pszFile = crStrdup(pszFile);
1095 if (pDumper->pszFile)
1096 {
1097 char szBuffer[4096] = {0};
1098 RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/%s", pszDir, pszFile);
1099
1100 pDumper->pszFile = crStrdup(pszFile);
1101 pDumper->pFile = fopen(szBuffer, "w");
1102 if (pDumper->pFile)
1103 {
1104 crDmpHtmlPrintHeader(pDumper);
1105 return VINF_SUCCESS;
1106 }
1107 else
1108 {
1109 crWarning("open failed");
1110 rc = VERR_OPEN_FAILED;
1111 }
1112 crFree((void*)pDumper->pszFile);
1113 }
1114 else
1115 {
1116 crWarning("open failed");
1117 }
1118 crFree((void*)pDumper->pszDir);
1119 }
1120 else
1121 {
1122 crWarning("open failed");
1123 }
1124 return rc;
1125}
1126
1127#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