VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c@ 46453

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

crOpenGL: more dump/debug stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 54.2 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "server_dispatch.h"
8#include "server.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_string.h"
12#include "cr_pixeldata.h"
13
14void SERVER_DISPATCH_APIENTRY crServerDispatchSelectBuffer( GLsizei size, GLuint *buffer )
15{
16 (void) size;
17 (void) buffer;
18 crError( "Unsupported network glSelectBuffer call." );
19}
20
21void SERVER_DISPATCH_APIENTRY crServerDispatchGetChromiumParametervCR(GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values)
22{
23 GLubyte local_storage[4096];
24 GLint bytes = 0;
25
26 switch (type) {
27 case GL_BYTE:
28 case GL_UNSIGNED_BYTE:
29 bytes = count * sizeof(GLbyte);
30 break;
31 case GL_SHORT:
32 case GL_UNSIGNED_SHORT:
33 bytes = count * sizeof(GLshort);
34 break;
35 case GL_INT:
36 case GL_UNSIGNED_INT:
37 bytes = count * sizeof(GLint);
38 break;
39 case GL_FLOAT:
40 bytes = count * sizeof(GLfloat);
41 break;
42 case GL_DOUBLE:
43 bytes = count * sizeof(GLdouble);
44 break;
45 default:
46 crError("Bad type in crServerDispatchGetChromiumParametervCR");
47 }
48
49 CRASSERT(bytes >= 0);
50 CRASSERT(bytes < 4096);
51
52 switch (target)
53 {
54 case GL_DBG_CHECK_BREAK_CR:
55 {
56 if (bytes > 0)
57 {
58 GLubyte *pbRc = local_storage;
59 GLuint *puRc = (GLuint *)(bytes >=4 ? local_storage : NULL);
60 int rc;
61 memset(local_storage, 0, bytes);
62 if (cr_server.RcToGuestOnce)
63 {
64 rc = cr_server.RcToGuestOnce;
65 cr_server.RcToGuestOnce = 0;
66 }
67 else
68 {
69 rc = cr_server.RcToGuest;
70 }
71 if (puRc)
72 *puRc = rc;
73 else
74 *pbRc = !!rc;
75 }
76 else
77 {
78 crWarning("zero bytes for GL_DBG_CHECK_BREAK_CR");
79 }
80 break;
81 }
82 default:
83 cr_server.head_spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, local_storage );
84 break;
85 }
86
87 crServerReturnValue( local_storage, bytes );
88}
89
90void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target, GLenum type, GLsizei count, const GLvoid *values)
91{
92 CRMuralInfo *mural = cr_server.curClient->currentMural;
93 static int gather_connect_count = 0;
94
95 switch (target) {
96 case GL_SET_MAX_VIEWPORT_CR:
97 {
98 GLint *maxDims = (GLint *)values;
99 cr_server.limits.maxViewportDims[0] = maxDims[0];
100 cr_server.limits.maxViewportDims[1] = maxDims[1];
101 }
102 break;
103
104 case GL_TILE_INFO_CR:
105 /* message from tilesort SPU to set new tile bounds */
106 {
107 GLint numTiles, muralWidth, muralHeight, server, tiles;
108 GLint *tileBounds;
109 CRASSERT(count >= 4);
110 CRASSERT((count - 4) % 4 == 0); /* must be multiple of four */
111 CRASSERT(type == GL_INT);
112 numTiles = (count - 4) / 4;
113 tileBounds = (GLint *) values;
114 server = tileBounds[0];
115 muralWidth = tileBounds[1];
116 muralHeight = tileBounds[2];
117 tiles = tileBounds[3];
118 CRASSERT(tiles == numTiles);
119 tileBounds += 4; /* skip over header values */
120 /*crServerNewMuralTiling(mural, muralWidth, muralHeight, numTiles, tileBounds);
121 mural->viewportValidated = GL_FALSE;*/
122 }
123 break;
124
125 case GL_GATHER_DRAWPIXELS_CR:
126 if (cr_server.only_swap_once && cr_server.curClient != cr_server.clients[0])
127 break;
128 cr_server.head_spu->dispatch_table.ChromiumParametervCR( target, type, count, values );
129 break;
130
131 case GL_GATHER_CONNECT_CR:
132 /*
133 * We want the last connect to go through,
134 * otherwise we might deadlock in CheckWindowSize()
135 * in the readback spu
136 */
137 gather_connect_count++;
138 if (cr_server.only_swap_once && (gather_connect_count != cr_server.numClients))
139 {
140 break;
141 }
142 cr_server.head_spu->dispatch_table.ChromiumParametervCR( target, type, count, values );
143 gather_connect_count = 0;
144 break;
145
146 case GL_SERVER_VIEW_MATRIX_CR:
147 /* Set this server's view matrix which will get premultiplied onto the
148 * modelview matrix. For non-planar tilesort and stereo.
149 */
150 CRASSERT(count == 18);
151 CRASSERT(type == GL_FLOAT);
152 /* values[0] is the server index. Ignored here but used in tilesort SPU */
153 /* values[1] is the left/right eye index (0 or 1) */
154 {
155 const GLfloat *v = (const GLfloat *) values;
156 const int eye = v[1] == 0.0 ? 0 : 1;
157 crMatrixInitFromFloats(&cr_server.viewMatrix[eye], v + 2);
158
159 crDebug("Got GL_SERVER_VIEW_MATRIX_CR:\n"
160 " %f %f %f %f\n"
161 " %f %f %f %f\n"
162 " %f %f %f %f\n"
163 " %f %f %f %f",
164 cr_server.viewMatrix[eye].m00,
165 cr_server.viewMatrix[eye].m10,
166 cr_server.viewMatrix[eye].m20,
167 cr_server.viewMatrix[eye].m30,
168 cr_server.viewMatrix[eye].m01,
169 cr_server.viewMatrix[eye].m11,
170 cr_server.viewMatrix[eye].m21,
171 cr_server.viewMatrix[eye].m31,
172 cr_server.viewMatrix[eye].m02,
173 cr_server.viewMatrix[eye].m12,
174 cr_server.viewMatrix[eye].m22,
175 cr_server.viewMatrix[eye].m32,
176 cr_server.viewMatrix[eye].m03,
177 cr_server.viewMatrix[eye].m13,
178 cr_server.viewMatrix[eye].m23,
179 cr_server.viewMatrix[eye].m33);
180 }
181 cr_server.viewOverride = GL_TRUE;
182 break;
183
184 case GL_SERVER_PROJECTION_MATRIX_CR:
185 /* Set this server's projection matrix which will get replace the user's
186 * projection matrix. For non-planar tilesort and stereo.
187 */
188 CRASSERT(count == 18);
189 CRASSERT(type == GL_FLOAT);
190 /* values[0] is the server index. Ignored here but used in tilesort SPU */
191 /* values[1] is the left/right eye index (0 or 1) */
192 {
193 const GLfloat *v = (const GLfloat *) values;
194 const int eye = v[1] == 0.0 ? 0 : 1;
195 crMatrixInitFromFloats(&cr_server.projectionMatrix[eye], v + 2);
196
197 crDebug("Got GL_SERVER_PROJECTION_MATRIX_CR:\n"
198 " %f %f %f %f\n"
199 " %f %f %f %f\n"
200 " %f %f %f %f\n"
201 " %f %f %f %f",
202 cr_server.projectionMatrix[eye].m00,
203 cr_server.projectionMatrix[eye].m10,
204 cr_server.projectionMatrix[eye].m20,
205 cr_server.projectionMatrix[eye].m30,
206 cr_server.projectionMatrix[eye].m01,
207 cr_server.projectionMatrix[eye].m11,
208 cr_server.projectionMatrix[eye].m21,
209 cr_server.projectionMatrix[eye].m31,
210 cr_server.projectionMatrix[eye].m02,
211 cr_server.projectionMatrix[eye].m12,
212 cr_server.projectionMatrix[eye].m22,
213 cr_server.projectionMatrix[eye].m32,
214 cr_server.projectionMatrix[eye].m03,
215 cr_server.projectionMatrix[eye].m13,
216 cr_server.projectionMatrix[eye].m23,
217 cr_server.projectionMatrix[eye].m33);
218
219 if (cr_server.projectionMatrix[eye].m33 == 0.0f) {
220 float x = cr_server.projectionMatrix[eye].m00;
221 float y = cr_server.projectionMatrix[eye].m11;
222 float a = cr_server.projectionMatrix[eye].m20;
223 float b = cr_server.projectionMatrix[eye].m21;
224 float c = cr_server.projectionMatrix[eye].m22;
225 float d = cr_server.projectionMatrix[eye].m32;
226 float znear = -d / (1.0f - c);
227 float zfar = (c - 1.0f) * znear / (c + 1.0f);
228 float left = znear * (a - 1.0f) / x;
229 float right = 2.0f * znear / x + left;
230 float bottom = znear * (b - 1.0f) / y;
231 float top = 2.0f * znear / y + bottom;
232 crDebug("Frustum: left, right, bottom, top, near, far: %f, %f, %f, %f, %f, %f", left, right, bottom, top, znear, zfar);
233 }
234 else {
235 /* Todo: Add debug output for orthographic projection*/
236 }
237
238 }
239 cr_server.projectionOverride = GL_TRUE;
240 break;
241
242 default:
243 /* Pass the parameter info to the head SPU */
244 cr_server.head_spu->dispatch_table.ChromiumParametervCR( target, type, count, values );
245 break;
246 }
247}
248
249
250void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParameteriCR(GLenum target, GLint value)
251{
252 switch (target) {
253 case GL_SHARE_CONTEXT_RESOURCES_CR:
254 crStateShareContext(value);
255 break;
256 case GL_RCUSAGE_TEXTURE_SET_CR:
257 crStateSetTextureUsed(value, GL_TRUE);
258 break;
259 case GL_RCUSAGE_TEXTURE_CLEAR_CR:
260 crStateSetTextureUsed(value, GL_FALSE);
261 break;
262 case GL_SHARED_DISPLAY_LISTS_CR:
263 cr_server.sharedDisplayLists = value;
264 break;
265 case GL_SHARED_TEXTURE_OBJECTS_CR:
266 cr_server.sharedTextureObjects = value;
267 break;
268 case GL_SHARED_PROGRAMS_CR:
269 cr_server.sharedPrograms = value;
270 break;
271 case GL_SERVER_CURRENT_EYE_CR:
272 cr_server.currentEye = value ? 1 : 0;
273 break;
274 case GL_HOST_WND_CREATED_HIDDEN:
275 cr_server.bWindowsInitiallyHidden = value ? 1 : 0;
276 break;
277 default:
278 /* Pass the parameter info to the head SPU */
279 cr_server.head_spu->dispatch_table.ChromiumParameteriCR( target, value );
280 }
281}
282
283
284void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParameterfCR(GLenum target, GLfloat value)
285{
286 switch (target) {
287 case GL_SHARED_DISPLAY_LISTS_CR:
288 cr_server.sharedDisplayLists = (int) value;
289 break;
290 case GL_SHARED_TEXTURE_OBJECTS_CR:
291 cr_server.sharedTextureObjects = (int) value;
292 break;
293 case GL_SHARED_PROGRAMS_CR:
294 cr_server.sharedPrograms = (int) value;
295 break;
296 default:
297 /* Pass the parameter info to the head SPU */
298 cr_server.head_spu->dispatch_table.ChromiumParameterfCR( target, value );
299 }
300}
301
302GLint crServerGenerateID(GLint *pCounter)
303{
304 return (*pCounter)++;
305}
306
307/*#define CR_DUMP_BLITS*/
308
309#ifdef CR_DUMP_BLITS
310static int blitnum=0;
311static int copynum=0;
312#endif
313
314# ifdef DEBUG_misha
315//# define CR_CHECK_BLITS
316# include <iprt/assert.h>
317# undef CRASSERT /* iprt assert's int3 are inlined that is why are more convenient to use since they can be easily disabled individually */
318# define CRASSERT Assert
319# endif
320
321
322void SERVER_DISPATCH_APIENTRY
323crServerDispatchCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
324{
325 /*@todo pbo/fbo disabled for now as it's slower, check on other gpus*/
326 static int siHavePBO = 0;
327 static int siHaveFBO = 0;
328
329 if ((target!=GL_TEXTURE_2D) || (height>=0))
330 {
331 cr_server.head_spu->dispatch_table.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
332
333#ifdef CR_DUMP_BLITS
334 {
335 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
336 void *img;
337 GLint w, h;
338 char fname[200];
339
340 copynum++;
341
342 gl->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
343 gl->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
344
345 img = crAlloc(w*h*4);
346 CRASSERT(img);
347
348 gl->GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, img);
349 sprintf(fname, "copy_blit%i_copy_%i.tga", blitnum, copynum);
350 crDumpNamedTGA(fname, w, h, img);
351 crFree(img);
352 }
353#endif
354 }
355 else /* negative height, means we have to Yinvert the source pixels while copying */
356 {
357 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
358
359 if (siHavePBO<0)
360 {
361 const char *ext = (const char*)gl->GetString(GL_EXTENSIONS);
362 siHavePBO = crStrstr(ext, "GL_ARB_pixel_buffer_object") ? 1:0;
363 }
364
365 if (siHaveFBO<0)
366 {
367 const char *ext = (const char*)gl->GetString(GL_EXTENSIONS);
368 siHaveFBO = crStrstr(ext, "GL_EXT_framebuffer_object") ? 1:0;
369 }
370
371 if (siHavePBO==0 && siHaveFBO==0)
372 {
373#if 1
374 GLint dRow, sRow;
375 for (dRow=yoffset, sRow=y-height-1; dRow<yoffset-height; dRow++, sRow--)
376 {
377 gl->CopyTexSubImage2D(target, level, xoffset, dRow, x, sRow, width, 1);
378 }
379#else
380 {
381 GLint w, h, i;
382 char *img1, *img2, *sPtr, *dPtr;
383 CRContext *ctx = crStateGetCurrent();
384
385 w = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->level[0][level].width;
386 h = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->level[0][level].height;
387
388 img1 = crAlloc(4*w*h);
389 img2 = crAlloc(4*width*(-height));
390 CRASSERT(img1 && img2);
391
392 gl->CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, -height);
393 gl->GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, img1);
394
395 sPtr=img1+4*xoffset+4*w*yoffset;
396 dPtr=img2+4*width*(-height-1);
397
398 for (i=0; i<-height; ++i)
399 {
400 crMemcpy(dPtr, sPtr, 4*width);
401 sPtr += 4*w;
402 dPtr -= 4*width;
403 }
404
405 gl->TexSubImage2D(target, level, xoffset, yoffset, width, -height, GL_RGBA, GL_UNSIGNED_BYTE, img2);
406
407 crFree(img1);
408 crFree(img2);
409 }
410#endif
411 }
412 else if (siHaveFBO==1) /*@todo more states to set and restore here*/
413 {
414 GLuint tID, fboID;
415 GLenum status;
416 CRContext *ctx = crStateGetCurrent();
417
418 gl->GenTextures(1, &tID);
419 gl->BindTexture(target, tID);
420 gl->CopyTexImage2D(target, level, GL_RGBA, x, y, width, -height, 0);
421 gl->GenFramebuffersEXT(1, &fboID);
422 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
423 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target,
424 ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid, level);
425 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
426 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
427 {
428 crWarning("Framebuffer status 0x%x", status);
429 }
430
431 gl->Enable(target);
432 gl->PushAttrib(GL_VIEWPORT_BIT);
433 gl->Viewport(xoffset, yoffset, width, -height);
434 gl->MatrixMode(GL_PROJECTION);
435 gl->PushMatrix();
436 gl->LoadIdentity();
437 gl->MatrixMode(GL_MODELVIEW);
438 gl->PushMatrix();
439 gl->LoadIdentity();
440
441 gl->Disable(GL_DEPTH_TEST);
442 gl->Disable(GL_CULL_FACE);
443 gl->Disable(GL_STENCIL_TEST);
444 gl->Disable(GL_SCISSOR_TEST);
445
446 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
447 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
448 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
449 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
450 gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
451
452 gl->Begin(GL_QUADS);
453 gl->TexCoord2f(0.0f, 1.0f);
454 gl->Vertex2f(-1.0, -1.0);
455
456 gl->TexCoord2f(0.0f, 0.0f);
457 gl->Vertex2f(-1.0f, 1.0f);
458
459 gl->TexCoord2f(1.0f, 0.0f);
460 gl->Vertex2f(1.0f, 1.0f);
461
462 gl->TexCoord2f(1.0f, 1.0f);
463 gl->Vertex2f(1.0f, -1.0f);
464 gl->End();
465
466 gl->PopMatrix();
467 gl->MatrixMode(GL_PROJECTION);
468 gl->PopMatrix();
469 gl->PopAttrib();
470
471 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, 0, level);
472 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0);
473 gl->BindTexture(target, ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid);
474 gl->DeleteFramebuffersEXT(1, &fboID);
475 gl->DeleteTextures(1, &tID);
476
477#if 0
478 {
479 GLint dRow, sRow, w, h;
480 void *img1, *img2;
481
482 w = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->level[0][level].width;
483 h = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->level[0][level].height;
484
485 img1 = crAlloc(4*w*h);
486 img2 = crAlloc(4*w*h);
487 CRASSERT(img1 && img2);
488
489 gl->GetTexImage(target, level, GL_BGRA, GL_UNSIGNED_BYTE, img1);
490
491
492 for (dRow=yoffset, sRow=y-height-1; dRow<yoffset-height; dRow++, sRow--)
493 {
494 gl->CopyTexSubImage2D(target, level, xoffset, dRow, x, sRow, width, 1);
495 }
496
497 gl->GetTexImage(target, level, GL_BGRA, GL_UNSIGNED_BYTE, img2);
498
499 if (crMemcmp(img1, img2, 4*w*h))
500 {
501 crDebug("MISMATCH! (%x, %i, ->%i,%i <-%i, %i [%ix%i])", target, level, xoffset, yoffset, x, y, width, height);
502 crDumpTGA(w, h, img1);
503 crDumpTGA(w, h, img2);
504 DebugBreak();
505 }
506 crFree(img1);
507 crFree(img2);
508 }
509#endif
510 }
511 else
512 {
513 GLuint pboId, dRow, sRow;
514 CRContext *ctx = crStateGetCurrent();
515
516 gl->GenBuffersARB(1, &pboId);
517 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
518 gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, -width*height*4, 0, GL_STATIC_COPY_ARB);
519
520#if 1
521 gl->ReadPixels(x, y, width, -height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
522 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
523
524 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
525 for (dRow=yoffset, sRow=-height-1; dRow<yoffset-height; dRow++, sRow--)
526 {
527 gl->TexSubImage2D(target, level, xoffset, dRow, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)((uintptr_t)sRow*width*4));
528 }
529#else /*few times slower again*/
530 for (dRow=0, sRow=y-height-1; dRow<-height; dRow++, sRow--)
531 {
532 gl->ReadPixels(x, sRow, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)((uintptr_t)dRow*width*4));
533 }
534 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
535
536 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
537 gl->TexSubImage2D(target, level, xoffset, yoffset, width, -height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
538#endif
539
540 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
541 gl->DeleteBuffersARB(1, &pboId);
542 }
543 }
544}
545
546#ifdef CR_CHECK_BLITS
547void crDbgFree(void *pvData)
548{
549 crFree(pvData);
550}
551
552void crDbgGetTexImage2D(GLint texTarget, GLint texName, GLvoid **ppvImage, GLint *pw, GLint *ph)
553{
554 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
555 GLint ppb, pub, dstw, dsth, otex;
556 GLint pa, pr, psp, psr, ua, ur, usp, usr;
557 GLvoid *pvImage;
558 GLint rfb, dfb, rb, db;
559
560 gl->GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb);
561 gl->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb);
562 gl->GetIntegerv(GL_READ_BUFFER, &rb);
563 gl->GetIntegerv(GL_DRAW_BUFFER, &db);
564
565 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER_BINDING_EXT, 0);
566 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_BINDING_EXT, 0);
567 gl->ReadBuffer(GL_BACK);
568 gl->DrawBuffer(GL_BACK);
569
570 gl->GetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &ppb);
571 gl->GetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &pub);
572 gl->GetIntegerv(GL_TEXTURE_BINDING_2D, &otex);
573
574 gl->GetIntegerv(GL_PACK_ROW_LENGTH, &pr);
575 gl->GetIntegerv(GL_PACK_ALIGNMENT, &pa);
576 gl->GetIntegerv(GL_PACK_SKIP_PIXELS, &psp);
577 gl->GetIntegerv(GL_PACK_SKIP_ROWS, &psr);
578
579 gl->GetIntegerv(GL_UNPACK_ROW_LENGTH, &ur);
580 gl->GetIntegerv(GL_UNPACK_ALIGNMENT, &ua);
581 gl->GetIntegerv(GL_UNPACK_SKIP_PIXELS, &usp);
582 gl->GetIntegerv(GL_UNPACK_SKIP_ROWS, &usr);
583
584 gl->BindTexture(texTarget, texName);
585 gl->GetTexLevelParameteriv(texTarget, 0, GL_TEXTURE_WIDTH, &dstw);
586 gl->GetTexLevelParameteriv(texTarget, 0, GL_TEXTURE_HEIGHT, &dsth);
587
588 gl->PixelStorei(GL_PACK_ROW_LENGTH, 0);
589 gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
590 gl->PixelStorei(GL_PACK_SKIP_PIXELS, 0);
591 gl->PixelStorei(GL_PACK_SKIP_ROWS, 0);
592
593 gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
594 gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
595 gl->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
596 gl->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
597
598 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER, 0);
599 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);
600
601 pvImage = crAlloc(4*dstw*dsth);
602 gl->GetTexImage(texTarget, 0, GL_BGRA, GL_UNSIGNED_BYTE, pvImage);
603
604 gl->BindTexture(texTarget, otex);
605
606 gl->PixelStorei(GL_PACK_ROW_LENGTH, pr);
607 gl->PixelStorei(GL_PACK_ALIGNMENT, pa);
608 gl->PixelStorei(GL_PACK_SKIP_PIXELS, psp);
609 gl->PixelStorei(GL_PACK_SKIP_ROWS, psr);
610
611 gl->PixelStorei(GL_UNPACK_ROW_LENGTH, ur);
612 gl->PixelStorei(GL_UNPACK_ALIGNMENT, ua);
613 gl->PixelStorei(GL_UNPACK_SKIP_PIXELS, usp);
614 gl->PixelStorei(GL_UNPACK_SKIP_ROWS, usr);
615
616 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER, ppb);
617 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER, pub);
618
619 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER_BINDING_EXT, rfb);
620 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_BINDING_EXT, dfb);
621 gl->ReadBuffer(rb);
622 gl->DrawBuffer(db);
623
624 *ppvImage = pvImage;
625 *pw = dstw;
626 *ph = dsth;
627}
628
629DECLEXPORT(void) crDbgPrint(const char *format, ... )
630{
631 va_list args;
632 static char txt[8092];
633
634 va_start( args, format );
635 vsprintf( txt, format, args );
636
637 OutputDebugString(txt);
638}
639
640void crDbgDumpImage2D(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
641{
642 crDbgPrint("<?dml?><exec cmd=\"!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d\">%s</exec>, ( !vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d )\n",
643 pvData, width, height, bpp, pitch,
644 pszDesc,
645 pvData, width, height, bpp, pitch);
646}
647
648void crDbgDumpTexImage2D(const char* pszDesc, GLint texTarget, GLint texName, GLboolean fBreak)
649{
650 GLvoid *pvImage;
651 GLint w, h;
652 crDbgGetTexImage2D(texTarget, texName, &pvImage, &w, &h);
653 crDbgPrint("%s target(%d), name(%d), width(%d), height(%d)", pszDesc, texTarget, texName, w, h);
654 crDbgDumpImage2D("texture data", pvImage, w, h, 32, (32 * w)/8);
655 if (fBreak)
656 {
657 CRASSERT(0);
658 }
659 crDbgFree(pvImage);
660}
661#endif
662
663PCR_BLITTER crServerVBoxBlitterGet()
664{
665 if (!CrBltIsInitialized(&cr_server.Blitter))
666 {
667 CR_BLITTER_CONTEXT Ctx;
668 int rc;
669 CRASSERT(cr_server.MainContextInfo.SpuContext);
670 Ctx.Base.id = cr_server.MainContextInfo.SpuContext;
671 Ctx.Base.visualBits = cr_server.MainContextInfo.CreateInfo.visualBits;
672 rc = CrBltInit(&cr_server.Blitter, &Ctx, true, true, &cr_server.head_spu->dispatch_table);
673 if (RT_SUCCESS(rc))
674 {
675 CRASSERT(CrBltIsInitialized(&cr_server.Blitter));
676 }
677 else
678 {
679 crWarning("CrBltInit failed, rc %d", rc);
680 CRASSERT(!CrBltIsInitialized(&cr_server.Blitter));
681 return NULL;
682 }
683 }
684 return &cr_server.Blitter;
685}
686
687int crServerVBoxBlitterTexInit(CRContext *ctx, CRMuralInfo *mural, PVBOXVR_TEXTURE pTex, GLboolean fDraw)
688{
689 CRTextureObj *tobj;
690 CRFramebufferObjectState *pBuf = &ctx->framebufferobject;
691 GLenum enmBuf;
692 CRFBOAttachmentPoint *pAp;
693 GLuint idx;
694 CRTextureLevel *tl;
695 CRFramebufferObject *pFBO = fDraw ? pBuf->drawFB : pBuf->readFB;
696
697 if (!pFBO)
698 {
699 GLuint hwid;
700
701 if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
702 return VERR_NOT_IMPLEMENTED;
703
704 enmBuf = fDraw ? ctx->buffer.drawBuffer : ctx->buffer.readBuffer;
705 switch (enmBuf)
706 {
707 case GL_BACK:
708 case GL_BACK_RIGHT:
709 case GL_BACK_LEFT:
710 hwid = mural->aidColorTexs[CR_SERVER_FBO_BB_IDX(mural)];
711 break;
712 case GL_FRONT:
713 case GL_FRONT_RIGHT:
714 case GL_FRONT_LEFT:
715 hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
716 break;
717 default:
718 crWarning("unsupported enum buf");
719 return VERR_NOT_IMPLEMENTED;
720 break;
721 }
722
723 if (!hwid)
724 {
725 crWarning("offscreen render tex hwid is null");
726 return VERR_INVALID_STATE;
727 }
728
729 pTex->width = mural->width;
730 pTex->height = mural->height;
731 pTex->target = GL_TEXTURE_2D;
732 pTex->hwid = hwid;
733 return VINF_SUCCESS;
734 }
735
736 enmBuf = fDraw ? pFBO->drawbuffer[0] : pFBO->readbuffer;
737 idx = enmBuf - GL_COLOR_ATTACHMENT0_EXT;
738 if (idx >= CR_MAX_COLOR_ATTACHMENTS)
739 {
740 crWarning("idx is invalid %d, using 0", idx);
741 }
742
743 pAp = &pFBO->color[idx];
744
745 if (!pAp->name)
746 {
747 crWarning("no collor draw attachment");
748 return VERR_INVALID_STATE;
749 }
750
751 if (pAp->level)
752 {
753 crWarning("non-zero level not implemented");
754 return VERR_NOT_IMPLEMENTED;
755 }
756
757 tobj = (CRTextureObj*)crHashtableSearch(ctx->shared->textureTable, pAp->name);
758 if (!tobj)
759 {
760 crWarning("no texture object found for name %d", pAp->name);
761 return VERR_INVALID_STATE;
762 }
763
764 if (tobj->target != GL_TEXTURE_2D && tobj->target != GL_TEXTURE_RECTANGLE_NV)
765 {
766 crWarning("non-texture[rect|2d] not implemented");
767 return VERR_NOT_IMPLEMENTED;
768 }
769
770 CRASSERT(tobj->hwid);
771
772 tl = tobj->level[0];
773 pTex->width = tl->width;
774 pTex->height = tl->height;
775 pTex->target = tobj->target;
776 pTex->hwid = tobj->hwid;
777
778 return VINF_SUCCESS;
779}
780
781int crServerVBoxBlitterBlitCurrentCtx(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
782 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
783 GLbitfield mask, GLenum filter)
784{
785 PCR_BLITTER pBlitter;
786 CR_BLITTER_CONTEXT Ctx;
787 CRMuralInfo *mural;
788 CRContext *ctx = crStateGetCurrent();
789 PVBOXVR_TEXTURE pDrawTex, pReadTex;
790 VBOXVR_TEXTURE DrawTex, ReadTex;
791 int rc;
792 GLuint idDrawFBO, idReadFBO;
793 CR_BLITTER_WINDOW BltInfo;
794
795 if (mask != GL_COLOR_BUFFER_BIT)
796 {
797 crWarning("not supported blit mask %d", mask);
798 return VERR_NOT_IMPLEMENTED;
799 }
800
801 if (!cr_server.curClient)
802 {
803 crWarning("no current client");
804 return VERR_INVALID_STATE;
805 }
806 mural = cr_server.curClient->currentMural;
807 if (!mural)
808 {
809 crWarning("no current mural");
810 return VERR_INVALID_STATE;
811 }
812
813 rc = crServerVBoxBlitterTexInit(ctx, mural, &DrawTex, GL_TRUE);
814 if (RT_SUCCESS(rc))
815 {
816 pDrawTex = &DrawTex;
817 }
818 else
819 {
820 crWarning("crServerVBoxBlitterTexInit failed for draw");
821 return rc;
822 }
823
824 rc = crServerVBoxBlitterTexInit(ctx, mural, &ReadTex, GL_FALSE);
825 if (RT_SUCCESS(rc))
826 {
827 pReadTex = &ReadTex;
828 }
829 else
830 {
831// crWarning("crServerVBoxBlitterTexInit failed for read");
832 return rc;
833 }
834
835 pBlitter = crServerVBoxBlitterGet();
836 if (!pBlitter)
837 {
838 crWarning("crServerVBoxBlitterGet failed");
839 return VERR_GENERAL_FAILURE;
840 }
841
842 crServerVBoxBlitterWinInit(&BltInfo, mural);
843
844 crServerVBoxBlitterCtxInit(&Ctx, cr_server.curClient->currentCtxInfo);
845
846 CrBltMuralSetCurrent(pBlitter, &BltInfo);
847
848 idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
849 idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
850
851 crStateSwitchPrepare(NULL, ctx, idDrawFBO, idReadFBO);
852
853 rc = CrBltEnter(pBlitter, &Ctx, &BltInfo);
854 if (RT_SUCCESS(rc))
855 {
856 RTRECT ReadRect, DrawRect;
857 ReadRect.xLeft = srcX0;
858 ReadRect.yTop = srcY0;
859 ReadRect.xRight = srcX1;
860 ReadRect.yBottom = srcY1;
861 DrawRect.xLeft = dstX0;
862 DrawRect.yTop = dstY0;
863 DrawRect.xRight = dstX1;
864 DrawRect.yBottom = dstY1;
865 CrBltBlitTexTex(pBlitter, pReadTex, &ReadRect, pDrawTex, &DrawRect, 1, CRBLT_FLAGS_FROM_FILTER(filter));
866 CrBltLeave(pBlitter);
867 }
868 else
869 {
870 crWarning("CrBltEnter failed rc %d", rc);
871 }
872
873 crStateSwitchPostprocess(ctx, NULL, idDrawFBO, idReadFBO);
874
875 return rc;
876}
877
878void SERVER_DISPATCH_APIENTRY
879crServerDispatchBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
880 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
881 GLbitfield mask, GLenum filter)
882{
883 CRContext *ctx = crStateGetCurrent();
884 bool fTryBlitter = false;
885#ifdef CR_CHECK_BLITS
886// {
887 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
888 GLint rfb=0, dfb=0, dtex=0, dlev=-1, rtex=0, rlev=-1, rb=0, db=0, ppb=0, pub=0, vp[4], otex, dstw, dsth;
889 GLint sdtex=0, srtex=0;
890 GLenum dStatus, rStatus;
891
892 CRTextureObj *tobj = 0;
893 CRTextureLevel *tl = 0;
894 GLint id, tuId, pbufId, pbufIdHw, ubufId, ubufIdHw, width, height, depth;
895
896 crDebug("===StateTracker===");
897 crDebug("Current TU: %i", ctx->texture.curTextureUnit);
898
899 tobj = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D;
900 CRASSERT(tobj);
901 tl = &tobj->level[0][0];
902 crDebug("Texture %i(hw %i), w=%i, h=%i", tobj->id, tobj->hwid, tl->width, tl->height, tl->depth);
903
904 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
905 {
906 pbufId = ctx->bufferobject.packBuffer->hwid;
907 }
908 else
909 {
910 pbufId = 0;
911 }
912 crDebug("Pack BufferId %i", pbufId);
913
914 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
915 {
916 ubufId = ctx->bufferobject.unpackBuffer->hwid;
917 }
918 else
919 {
920 ubufId = 0;
921 }
922 crDebug("Unpack BufferId %i", ubufId);
923
924 crDebug("===GPU===");
925 cr_server.head_spu->dispatch_table.GetIntegerv(GL_ACTIVE_TEXTURE, &tuId);
926 crDebug("Current TU: %i", tuId - GL_TEXTURE0_ARB);
927 CRASSERT(tuId - GL_TEXTURE0_ARB == ctx->texture.curTextureUnit);
928
929 cr_server.head_spu->dispatch_table.GetIntegerv(GL_TEXTURE_BINDING_2D, &id);
930 cr_server.head_spu->dispatch_table.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
931 cr_server.head_spu->dispatch_table.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
932 cr_server.head_spu->dispatch_table.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth);
933 crDebug("Texture: %i, w=%i, h=%i, d=%i", id, width, height, depth);
934 CRASSERT(id == tobj->hwid);
935 CRASSERT(width == tl->width);
936 CRASSERT(height == tl->height);
937 CRASSERT(depth == tl->depth);
938
939 cr_server.head_spu->dispatch_table.GetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &pbufIdHw);
940 crDebug("Hw Pack BufferId %i", pbufIdHw);
941 CRASSERT(pbufIdHw == pbufId);
942
943 cr_server.head_spu->dispatch_table.GetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &ubufIdHw);
944 crDebug("Hw Unpack BufferId %i", ubufIdHw);
945 CRASSERT(ubufIdHw == ubufId);
946
947 gl->GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb);
948 gl->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb);
949 gl->GetIntegerv(GL_READ_BUFFER, &rb);
950 gl->GetIntegerv(GL_DRAW_BUFFER, &db);
951
952 gl->GetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &ppb);
953 gl->GetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &pub);
954
955 gl->GetIntegerv(GL_VIEWPORT, &vp[0]);
956
957 gl->GetIntegerv(GL_TEXTURE_BINDING_2D, &otex);
958
959 gl->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &dtex);
960 gl->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &dlev);
961 dStatus = gl->CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
962
963 gl->GetFramebufferAttachmentParameterivEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &rtex);
964 gl->GetFramebufferAttachmentParameterivEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &rlev);
965 rStatus = gl->CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
966
967 if (dtex)
968 {
969 CRASSERT(!dlev);
970 }
971
972 if (rtex)
973 {
974 CRASSERT(!rlev);
975 }
976
977 if (ctx->framebufferobject.drawFB)
978 {
979 CRASSERT(dfb);
980 CRASSERT(ctx->framebufferobject.drawFB->hwid == dfb);
981 CRASSERT(ctx->framebufferobject.drawFB->drawbuffer[0] == db);
982
983 CRASSERT(dStatus==GL_FRAMEBUFFER_COMPLETE_EXT);
984 CRASSERT(db==GL_COLOR_ATTACHMENT0_EXT);
985
986 CRASSERT(ctx->framebufferobject.drawFB->color[0].type == GL_TEXTURE);
987 CRASSERT(ctx->framebufferobject.drawFB->color[0].level == 0);
988 sdtex = ctx->framebufferobject.drawFB->color[0].name;
989 sdtex = crStateGetTextureHWID(sdtex);
990
991 CRASSERT(sdtex);
992 }
993 else
994 {
995 CRASSERT(!dfb);
996 }
997
998 if (ctx->framebufferobject.readFB)
999 {
1000 CRASSERT(rfb);
1001 CRASSERT(ctx->framebufferobject.readFB->hwid == rfb);
1002
1003 CRASSERT(rStatus==GL_FRAMEBUFFER_COMPLETE_EXT);
1004
1005 CRASSERT(ctx->framebufferobject.readFB->color[0].type == GL_TEXTURE);
1006 CRASSERT(ctx->framebufferobject.readFB->color[0].level == 0);
1007 srtex = ctx->framebufferobject.readFB->color[0].name;
1008 srtex = crStateGetTextureHWID(srtex);
1009
1010 CRASSERT(srtex);
1011 }
1012 else
1013 {
1014 CRASSERT(!rfb);
1015 }
1016
1017 CRASSERT(sdtex == dtex);
1018 CRASSERT(srtex == rtex);
1019
1020// crDbgDumpTexImage2D("==> src tex:", GL_TEXTURE_2D, rtex, true);
1021// crDbgDumpTexImage2D("==> dst tex:", GL_TEXTURE_2D, dtex, true);
1022
1023// }
1024#endif
1025#ifdef CR_DUMP_BLITS
1026 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
1027 GLint rfb=0, dfb=0, dtex=0, dlev=-1, rb=0, db=0, ppb=0, pub=0, vp[4], otex, dstw, dsth;
1028 GLenum status;
1029 char fname[200];
1030 void *img;
1031
1032 blitnum++;
1033
1034 crDebug("[%i]BlitFramebufferEXT(%i, %i, %i, %i, %i, %i, %i, %i, %x, %x)", blitnum, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
1035 crDebug("%i, %i <-> %i, %i", srcX1-srcX0, srcY1-srcY0, dstX1-dstX0, dstY1-dstY0);
1036
1037 gl->GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb);
1038 gl->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb);
1039 gl->GetIntegerv(GL_READ_BUFFER, &rb);
1040 gl->GetIntegerv(GL_DRAW_BUFFER, &db);
1041
1042 gl->GetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &ppb);
1043 gl->GetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &pub);
1044
1045 gl->GetIntegerv(GL_VIEWPORT, &vp[0]);
1046
1047 gl->GetIntegerv(GL_TEXTURE_BINDING_2D, &otex);
1048
1049 CRASSERT(!rfb && dfb);
1050 gl->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &dtex);
1051 gl->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &dlev);
1052 status = gl->CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
1053
1054 CRASSERT(status==GL_FRAMEBUFFER_COMPLETE_EXT
1055 && db==GL_COLOR_ATTACHMENT0_EXT
1056 && (rb==GL_FRONT || rb==GL_BACK)
1057 && !rfb && dfb && dtex && !dlev
1058 && !ppb && !pub);
1059
1060 crDebug("Src[rb 0x%x, fbo %i] Dst[db 0x%x, fbo %i(0x%x), tex %i.%i]", rb, rfb, db, dfb, status, dtex, dlev);
1061 crDebug("Viewport [%i, %i, %i, %i]", vp[0], vp[1], vp[2], vp[3]);
1062
1063 gl->PixelStorei(GL_PACK_ROW_LENGTH, 0);
1064 gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
1065 gl->PixelStorei(GL_PACK_SKIP_PIXELS, 0);
1066 gl->PixelStorei(GL_PACK_SKIP_ROWS, 0);
1067
1068 gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1069 gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1070 gl->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1071 gl->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1072
1073 gl->BindTexture(GL_TEXTURE_2D, dtex);
1074 gl->GetTexLevelParameteriv(GL_TEXTURE_2D, dlev, GL_TEXTURE_WIDTH, &dstw);
1075 gl->GetTexLevelParameteriv(GL_TEXTURE_2D, dlev, GL_TEXTURE_HEIGHT, &dsth);
1076 gl->BindTexture(GL_TEXTURE_2D, otex);
1077 crDebug("Dst is %i, %i", dstw, dsth);
1078
1079 CRASSERT(vp[2]>=dstw && vp[3]>=dsth);
1080 img = crAlloc(vp[2]*vp[3]*4);
1081 CRASSERT(img);
1082
1083 gl->ReadPixels(0, 0, vp[2], vp[3], GL_BGRA, GL_UNSIGNED_BYTE, img);
1084 sprintf(fname, "blit%iA_src.tga", blitnum);
1085 crDumpNamedTGA(fname, vp[2], vp[3], img);
1086
1087 gl->BindTexture(GL_TEXTURE_2D, dtex);
1088 gl->GetTexImage(GL_TEXTURE_2D, dlev, GL_BGRA, GL_UNSIGNED_BYTE, img);
1089 sprintf(fname, "blit%iB_dst.tga", blitnum);
1090 crDumpNamedTGA(fname, dstw, dsth, img);
1091 gl->BindTexture(GL_TEXTURE_2D, otex);
1092#endif
1093
1094 if (srcY0 > srcY1)
1095 {
1096 /* work around Intel driver bug on Linux host */
1097 if (1 || dstY0 > dstY1)
1098 {
1099 /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
1100 int32_t tmp = srcY0;
1101 srcY0 = srcY1;
1102 srcY1 = tmp;
1103 tmp = dstY0;
1104 dstY0 = dstY1;
1105 dstY1 = tmp;
1106 }
1107 }
1108
1109 if (srcX0 > srcX1)
1110 {
1111 if (dstX0 > dstX1)
1112 {
1113 /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
1114 int32_t tmp = srcX0;
1115 srcX0 = srcX1;
1116 srcX1 = tmp;
1117 tmp = dstX0;
1118 dstX0 = dstX1;
1119 dstX1 = tmp;
1120 }
1121 }
1122
1123 if (cr_server.fBlitterMode)
1124 {
1125 fTryBlitter = true;
1126 }
1127
1128 if (fTryBlitter)
1129 {
1130 int rc = crServerVBoxBlitterBlitCurrentCtx(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
1131 if (RT_SUCCESS(rc))
1132 goto my_exit;
1133 }
1134
1135 if (ctx->viewport.scissorTest)
1136 cr_server.head_spu->dispatch_table.Disable(GL_SCISSOR_TEST);
1137
1138 cr_server.head_spu->dispatch_table.BlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
1139 dstX0, dstY0, dstX1, dstY1,
1140 mask, filter);
1141
1142 if (ctx->viewport.scissorTest)
1143 cr_server.head_spu->dispatch_table.Enable(GL_SCISSOR_TEST);
1144
1145
1146my_exit:
1147
1148//#ifdef CR_CHECK_BLITS
1149// crDbgDumpTexImage2D("<== src tex:", GL_TEXTURE_2D, rtex, true);
1150// crDbgDumpTexImage2D("<== dst tex:", GL_TEXTURE_2D, dtex, true);
1151//#endif
1152#ifdef CR_DUMP_BLITS
1153 gl->BindTexture(GL_TEXTURE_2D, dtex);
1154 gl->GetTexImage(GL_TEXTURE_2D, dlev, GL_BGRA, GL_UNSIGNED_BYTE, img);
1155 sprintf(fname, "blit%iC_res.tga", blitnum);
1156 crDumpNamedTGA(fname, dstw, dsth, img);
1157 gl->BindTexture(GL_TEXTURE_2D, otex);
1158 crFree(img);
1159#endif
1160 return;
1161}
1162
1163void SERVER_DISPATCH_APIENTRY crServerDispatchDrawBuffer( GLenum mode )
1164{
1165 crStateDrawBuffer( mode );
1166
1167 if (!crStateGetCurrent()->framebufferobject.drawFB)
1168 {
1169 if (mode == GL_FRONT || mode == GL_FRONT_LEFT || mode == GL_FRONT_RIGHT)
1170 cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
1171
1172 if (crServerIsRedirectedToFBO()
1173 && cr_server.curClient->currentMural->aidFBOs[0])
1174 {
1175 CRMuralInfo *mural = cr_server.curClient->currentMural;
1176 GLint iBufferNeeded = -1;
1177 switch (mode)
1178 {
1179 case GL_BACK:
1180 case GL_BACK_LEFT:
1181 case GL_BACK_RIGHT:
1182 mode = GL_COLOR_ATTACHMENT0;
1183 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1184 break;
1185 case GL_FRONT:
1186 case GL_FRONT_LEFT:
1187 case GL_FRONT_RIGHT:
1188 mode = GL_COLOR_ATTACHMENT0;
1189 iBufferNeeded = CR_SERVER_FBO_FB_IDX(mural);
1190 break;
1191 case GL_NONE:
1192 crDebug("DrawBuffer: GL_NONE");
1193 break;
1194 case GL_AUX0:
1195 crDebug("DrawBuffer: GL_AUX0");
1196 break;
1197 case GL_AUX1:
1198 crDebug("DrawBuffer: GL_AUX1");
1199 break;
1200 case GL_AUX2:
1201 crDebug("DrawBuffer: GL_AUX2");
1202 break;
1203 case GL_AUX3:
1204 crDebug("DrawBuffer: GL_AUX3");
1205 break;
1206 case GL_LEFT:
1207 crWarning("DrawBuffer: GL_LEFT not supported properly");
1208 mode = GL_COLOR_ATTACHMENT0;
1209 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1210 break;
1211 case GL_RIGHT:
1212 crWarning("DrawBuffer: GL_RIGHT not supported properly");
1213 mode = GL_COLOR_ATTACHMENT0;
1214 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1215 break;
1216 case GL_FRONT_AND_BACK:
1217 crWarning("DrawBuffer: GL_FRONT_AND_BACK not supported properly");
1218 mode = GL_COLOR_ATTACHMENT0;
1219 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1220 break;
1221 default:
1222 crWarning("DrawBuffer: unexpected mode! 0x%x", mode);
1223 iBufferNeeded = mural->iCurDrawBuffer;
1224 break;
1225 }
1226
1227 if (iBufferNeeded != mural->iCurDrawBuffer)
1228 {
1229 mural->iCurDrawBuffer = iBufferNeeded;
1230 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, iBufferNeeded));
1231 }
1232 }
1233 }
1234
1235 cr_server.head_spu->dispatch_table.DrawBuffer( mode );
1236}
1237
1238void SERVER_DISPATCH_APIENTRY crServerDispatchReadBuffer( GLenum mode )
1239{
1240 crStateReadBuffer( mode );
1241
1242 if (crServerIsRedirectedToFBO()
1243 && cr_server.curClient->currentMural->aidFBOs[0]
1244 && !crStateGetCurrent()->framebufferobject.readFB)
1245 {
1246 CRMuralInfo *mural = cr_server.curClient->currentMural;
1247 GLint iBufferNeeded = -1;
1248 switch (mode)
1249 {
1250 case GL_BACK:
1251 case GL_BACK_LEFT:
1252 case GL_BACK_RIGHT:
1253 mode = GL_COLOR_ATTACHMENT0;
1254 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1255 break;
1256 case GL_FRONT:
1257 case GL_FRONT_LEFT:
1258 case GL_FRONT_RIGHT:
1259 mode = GL_COLOR_ATTACHMENT0;
1260 iBufferNeeded = CR_SERVER_FBO_FB_IDX(mural);
1261 break;
1262 case GL_NONE:
1263 crDebug("ReadBuffer: GL_NONE");
1264 break;
1265 case GL_AUX0:
1266 crDebug("ReadBuffer: GL_AUX0");
1267 break;
1268 case GL_AUX1:
1269 crDebug("ReadBuffer: GL_AUX1");
1270 break;
1271 case GL_AUX2:
1272 crDebug("ReadBuffer: GL_AUX2");
1273 break;
1274 case GL_AUX3:
1275 crDebug("ReadBuffer: GL_AUX3");
1276 break;
1277 case GL_LEFT:
1278 crWarning("ReadBuffer: GL_LEFT not supported properly");
1279 mode = GL_COLOR_ATTACHMENT0;
1280 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1281 break;
1282 case GL_RIGHT:
1283 crWarning("ReadBuffer: GL_RIGHT not supported properly");
1284 mode = GL_COLOR_ATTACHMENT0;
1285 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1286 break;
1287 case GL_FRONT_AND_BACK:
1288 crWarning("ReadBuffer: GL_FRONT_AND_BACK not supported properly");
1289 mode = GL_COLOR_ATTACHMENT0;
1290 iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
1291 break;
1292 default:
1293 crWarning("ReadBuffer: unexpected mode! 0x%x", mode);
1294 iBufferNeeded = mural->iCurDrawBuffer;
1295 break;
1296 }
1297
1298 Assert(CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
1299 if (iBufferNeeded != mural->iCurReadBuffer)
1300 {
1301 mural->iCurReadBuffer = iBufferNeeded;
1302 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, iBufferNeeded));
1303 }
1304 }
1305 cr_server.head_spu->dispatch_table.ReadBuffer( mode );
1306}
1307
1308GLenum SERVER_DISPATCH_APIENTRY crServerDispatchGetError( void )
1309{
1310 GLenum retval, err;
1311 CRContext *ctx = crStateGetCurrent();
1312 retval = ctx->error;
1313
1314 err = cr_server.head_spu->dispatch_table.GetError();
1315 if (retval == GL_NO_ERROR)
1316 retval = err;
1317 else
1318 ctx->error = GL_NO_ERROR;
1319
1320 /* our impl has a single error flag, so we just loop here to reset all error flags to no_error */
1321 while (err != GL_NO_ERROR)
1322 err = cr_server.head_spu->dispatch_table.GetError();
1323
1324 crServerReturnValue( &retval, sizeof(retval) );
1325 return retval; /* WILL PROBABLY BE IGNORED */
1326}
1327
1328void SERVER_DISPATCH_APIENTRY
1329crServerMakeTmpCtxCurrent( GLint window, GLint nativeWindow, GLint context )
1330{
1331 CRContext *pCtx = crStateGetCurrent();
1332 CRContext *pCurCtx = NULL;
1333 GLuint idDrawFBO = 0, idReadFBO = 0;
1334 int fDoPrePostProcess = 0;
1335
1336 if (pCtx)
1337 {
1338 GLint curSrvSpuCtx = cr_server.currentCtxInfo && cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext;
1339 bool fSwitchToTmpCtx = (curSrvSpuCtx != context);
1340 CRMuralInfo *pCurrentMural = cr_server.currentMural;
1341 CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
1342 pCurCtx = pCurCtxInfo ? pCurCtxInfo->pContext : NULL;
1343
1344 CRASSERT(pCurCtx == pCtx);
1345
1346 if (pCurrentMural)
1347 {
1348 idDrawFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurDrawBuffer);
1349 idReadFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurReadBuffer);
1350 }
1351 else
1352 {
1353 idDrawFBO = 0;
1354 idReadFBO = 0;
1355 }
1356
1357 fDoPrePostProcess = fSwitchToTmpCtx ? 1 : -1;
1358 }
1359 else
1360 {
1361 /* this is a GUI thread, so no need to do anything here */
1362 }
1363
1364 if (fDoPrePostProcess > 0)
1365 crStateSwitchPrepare(NULL, pCurCtx, idDrawFBO, idReadFBO);
1366
1367 cr_server.head_spu->dispatch_table.MakeCurrent( window, nativeWindow, context);
1368
1369 if (fDoPrePostProcess < 0)
1370 crStateSwitchPostprocess(pCurCtx, NULL, idDrawFBO, idReadFBO);
1371}
1372
1373void crServerInitTmpCtxDispatch()
1374{
1375 crSPUInitDispatchTable(&cr_server.TmpCtxDispatch);
1376 crSPUCopyDispatchTable(&cr_server.TmpCtxDispatch, &cr_server.head_spu->dispatch_table);
1377 cr_server.TmpCtxDispatch.MakeCurrent = crServerMakeTmpCtxCurrent;
1378}
1379
1380/* dump stuff */
1381#ifdef VBOX_WITH_CRSERVER_DUMPER
1382
1383/* first four bits are buffer dump config
1384 * second four bits are texture dump config
1385 * config flags:
1386 * 1 - blit on enter
1387 * 2 - blit on exit
1388 *
1389 *
1390 * Example:
1391 *
1392 * 0x03 - dump buffer on enter and exit
1393 * 0x22 - dump texture and buffer on exit */
1394
1395unsigned long g_CrDbgDumpEnabled = 1;
1396unsigned long g_CrDbgDumpDraw = CR_SERVER_DUMP_F_COMPILE_SHADER
1397 | CR_SERVER_DUMP_F_LINK_PROGRAM
1398 | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
1399 | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER
1400 | CR_SERVER_DUMP_F_DRAW_TEX_LEAVE
1401 | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
1402 | CR_SERVER_DUMP_F_DRAW_STATE_ENTER
1403 | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER
1404 | CR_SERVER_DUMP_F_DRAWEL
1405 ; //CR_SERVER_DUMP_F_DRAW_BUFF_ENTER | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE;
1406unsigned long g_CrDbgDumpDrawFramesSettings = CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
1407 | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
1408 | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
1409 | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
1410 | CR_SERVER_DUMP_F_COMPILE_SHADER
1411 | CR_SERVER_DUMP_F_LINK_PROGRAM
1412 | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER;
1413unsigned long g_CrDbgDumpDrawFramesAppliedSettings = 0;
1414unsigned long g_CrDbgDumpDrawFramesSavedInitSettings = 0;
1415unsigned long g_CrDbgDumpDrawFramesCount = 0;
1416
1417void crServerDumpCheckTerm()
1418{
1419 if (!CrBltIsInitialized(&cr_server.RecorderBlitter))
1420 return;
1421
1422 CrBltTerm(&cr_server.RecorderBlitter);
1423}
1424
1425int crServerDumpCheckInit()
1426{
1427 int rc;
1428 CR_BLITTER_WINDOW BltWin;
1429 CR_BLITTER_CONTEXT BltCtx;
1430 CRMuralInfo *pBlitterMural;
1431
1432 if (CrBltIsInitialized(&cr_server.RecorderBlitter))
1433 return VINF_SUCCESS;
1434
1435 pBlitterMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
1436 if (!pBlitterMural)
1437 {
1438 crWarning("crServerGetDummyMural failed");
1439 return VERR_GENERAL_FAILURE;
1440 }
1441
1442 crServerVBoxBlitterWinInit(&BltWin, pBlitterMural);
1443 crServerVBoxBlitterCtxInit(&BltCtx, &cr_server.MainContextInfo);
1444
1445 rc = CrBltInit(&cr_server.RecorderBlitter, &BltCtx, true, true, &cr_server.TmpCtxDispatch);
1446 if (!RT_SUCCESS(rc))
1447 {
1448 crWarning("CrBltInit failed rc %d", rc);
1449 return rc;
1450 }
1451
1452 rc = CrBltMuralSetCurrent(&cr_server.RecorderBlitter, &BltWin);
1453 if (!RT_SUCCESS(rc))
1454 {
1455 crWarning("CrBltMuralSetCurrent failed rc %d", rc);
1456 return rc;
1457 }
1458
1459#if 0
1460 crDmpDbgPrintInit(&cr_server.DbgPrintDumper);
1461 cr_server.pDumper = &cr_server.DbgPrintDumper.Base;
1462#else
1463 crDmpHtmlInit(&cr_server.HtmlDumper, "S:\\projects\\virtualbox\\3d\\dumps\\1", "index.html");
1464 cr_server.pDumper = &cr_server.HtmlDumper.Base;
1465#endif
1466
1467 crRecInit(&cr_server.Recorder, &cr_server.RecorderBlitter, &cr_server.TmpCtxDispatch, cr_server.pDumper);
1468 return VINF_SUCCESS;
1469}
1470
1471void crServerDumpShader(GLint id)
1472{
1473 CRContext *ctx = crStateGetCurrent();
1474 crRecDumpShader(&cr_server.Recorder, ctx, id, 0);
1475}
1476
1477void crServerDumpProgram(GLint id)
1478{
1479 CRContext *ctx = crStateGetCurrent();
1480 crRecDumpProgram(&cr_server.Recorder, ctx, id, 0);
1481}
1482
1483void crServerDumpCurrentProgram()
1484{
1485 CRContext *ctx = crStateGetCurrent();
1486 crRecDumpCurrentProgram(&cr_server.Recorder, ctx);
1487}
1488
1489void crServerDumpCurrentProgramUniforms()
1490{
1491 CRContext *ctx = crStateGetCurrent();
1492 crRecDumpCurrentProgramUniforms(&cr_server.Recorder, ctx);
1493}
1494
1495void crServerDumpState()
1496{
1497 CRContext *ctx = crStateGetCurrent();
1498 crRecDumpGlGetState(&cr_server.Recorder, ctx);
1499 crRecDumpGlEnableState(&cr_server.Recorder, ctx);
1500}
1501
1502void crServerDumpDrawel(const char*pszFormat, ...)
1503{
1504 CRContext *ctx = crStateGetCurrent();
1505 va_list pArgList;
1506 va_start(pArgList, pszFormat);
1507 crRecDumpVertAttrV(&cr_server.Recorder, ctx, pszFormat, pArgList);
1508 va_end(pArgList);
1509}
1510
1511void crServerDumpDrawelv(GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
1512{
1513 CRContext *ctx = crStateGetCurrent();
1514 crRecDumpVertAttrv(&cr_server.Recorder, ctx, idx, pszElFormat, cbEl, pvVal, cVal);
1515}
1516
1517void crServerDumpBuffer(int idx)
1518{
1519 CRContextInfo *pCtxInfo = cr_server.currentCtxInfo;
1520 CR_BLITTER_WINDOW BltWin;
1521 CR_BLITTER_CONTEXT BltCtx;
1522 CRContext *ctx = crStateGetCurrent();
1523 GLint idFBO;
1524 GLint idTex;
1525 VBOXVR_TEXTURE RedirTex;
1526 int rc = crServerDumpCheckInit();
1527 idx = idx >= 0 ? idx : crServerMuralFBOIdxFromBufferName(cr_server.currentMural, pCtxInfo->pContext->buffer.drawBuffer);
1528 if (!RT_SUCCESS(rc))
1529 {
1530 crWarning("crServerDumpCheckInit failed, rc %d", rc);
1531 return;
1532 }
1533
1534 if (idx < 0)
1535 {
1536 crWarning("neg idx, unsupported");
1537 return;
1538 }
1539
1540 idFBO = CR_SERVER_FBO_FOR_IDX(cr_server.currentMural, idx);
1541 idTex = CR_SERVER_FBO_TEX_FOR_IDX(cr_server.currentMural, idx);
1542
1543 crServerVBoxBlitterWinInit(&BltWin, cr_server.currentMural);
1544 crServerVBoxBlitterCtxInit(&BltCtx, pCtxInfo);
1545
1546 RedirTex.width = cr_server.currentMural->fboWidth;
1547 RedirTex.height = cr_server.currentMural->fboHeight;
1548 RedirTex.target = GL_TEXTURE_2D;
1549 RedirTex.hwid = idTex;
1550
1551 crRecDumpBuffer(&cr_server.Recorder, ctx, &BltCtx, &BltWin, idFBO, idTex ? &RedirTex : NULL);
1552}
1553
1554void crServerDumpTextures()
1555{
1556 CRContextInfo *pCtxInfo = cr_server.currentCtxInfo;
1557 CR_BLITTER_WINDOW BltWin;
1558 CR_BLITTER_CONTEXT BltCtx;
1559 CRContext *ctx = crStateGetCurrent();
1560 int rc = crServerDumpCheckInit();
1561 if (!RT_SUCCESS(rc))
1562 {
1563 crWarning("crServerDumpCheckInit failed, rc %d", rc);
1564 return;
1565 }
1566
1567 crServerVBoxBlitterWinInit(&BltWin, cr_server.currentMural);
1568 crServerVBoxBlitterCtxInit(&BltCtx, pCtxInfo);
1569
1570 crRecDumpTextures(&cr_server.Recorder, ctx, &BltCtx, &BltWin);
1571}
1572
1573bool crServerDumpFilterOp(unsigned long event, CR_DUMPER *pDumper)
1574{
1575 return CR_SERVER_DUMP_DEFAULT_FILTER_OP(event);
1576}
1577
1578bool crServerDumpFilterDmp(unsigned long event, CR_DUMPER *pDumper)
1579{
1580 return CR_SERVER_DUMP_DEFAULT_FILTER_DMP(event);
1581}
1582
1583void crServerDumpFramesCheck()
1584{
1585 if (!g_CrDbgDumpDrawFramesCount)
1586 return;
1587
1588 if (!g_CrDbgDumpDrawFramesAppliedSettings)
1589 {
1590 if (!g_CrDbgDumpDrawFramesSettings)
1591 {
1592 crWarning("g_CrDbgDumpDrawFramesSettings is NULL, bump will not be started");
1593 g_CrDbgDumpDrawFramesCount = 0;
1594 return;
1595 }
1596
1597 g_CrDbgDumpDrawFramesSavedInitSettings = g_CrDbgDumpDraw;
1598 g_CrDbgDumpDrawFramesAppliedSettings = g_CrDbgDumpDrawFramesSettings;
1599 g_CrDbgDumpDraw = g_CrDbgDumpDrawFramesSettings;
1600 crDmpStrF(cr_server.Recorder.pDumper, "***Starting draw dump for %d frames, settings(0x%x)", g_CrDbgDumpDrawFramesCount, g_CrDbgDumpDraw);
1601 return;
1602 }
1603
1604 --g_CrDbgDumpDrawFramesCount;
1605
1606 if (!g_CrDbgDumpDrawFramesCount)
1607 {
1608 crDmpStrF(cr_server.Recorder.pDumper, "***Stop draw dump");
1609 g_CrDbgDumpDraw = g_CrDbgDumpDrawFramesSavedInitSettings;
1610 g_CrDbgDumpDrawFramesAppliedSettings = 0;
1611 }
1612}
1613#endif
1614/* */
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