VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c@ 43932

Last change on this file since 43932 was 43932, checked in by vboxsync, 13 years ago

crOpenGL: host offscreen rendering to fix gnome-shell issues, repaint problems and more

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/* $Id: server_muralfbo.c 43932 2012-11-21 19:28:05Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Window to FBO redirect support.
5 */
6
7/*
8 * Copyright (C) 2010 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "server.h"
20#include "cr_string.h"
21#include "cr_mem.h"
22#include "render/renderspu.h"
23
24static int crServerGetPointScreen(GLint x, GLint y)
25{
26 int i;
27
28 for (i=0; i<cr_server.screenCount; ++i)
29 {
30 if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
31 && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
32 {
33 return i;
34 }
35 }
36
37 return -1;
38}
39
40static GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
41{
42 return mural->gX < cr_server.screen[sId].x
43 && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
44 && mural->gY < cr_server.screen[sId].y
45 && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
46}
47
48/* Called when a new CRMuralInfo is created
49 * or when OutputRedirect status is changed.
50 */
51void crServerSetupOutputRedirect(CRMuralInfo *mural)
52{
53 /* Unset the previous redirect. */
54 if (mural->pvOutputRedirectInstance)
55 {
56 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
57 mural->pvOutputRedirectInstance = NULL;
58 }
59
60 /* Setup a new redirect. */
61 if (cr_server.bUseOutputRedirect)
62 {
63 /* Query supported formats. */
64 uint32_t cbFormats = 4096;
65 char *pachFormats = (char *)crAlloc(cbFormats);
66
67 if (pachFormats)
68 {
69 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
70 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
71 pachFormats, cbFormats, &cbFormats);
72 if (RT_SUCCESS(rc))
73 {
74 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
75 {
76 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
77 &mural->pvOutputRedirectInstance,
78 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
79 }
80 }
81
82 crFree(pachFormats);
83 }
84
85 /* If this is not NULL then there was a supported format. */
86 if (mural->pvOutputRedirectInstance)
87 {
88 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
89 mural->hX, mural->hY,
90 mural->width, mural->height);
91 // @todo the code assumes that RTRECT == four of GLInts
92 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
93 mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
94 }
95 }
96}
97
98void crServerCheckMuralGeometry(CRMuralInfo *mural)
99{
100 int tlS, brS, trS, blS;
101 int overlappingScreenCount, primaryS, i;
102
103 if (!mural->width || !mural->height)
104 return;
105
106 if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering)
107 {
108 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
109 CRASSERT(cr_server.screenCount>0);
110 CRASSERT(mural->fUseFBO == CR_SERVER_REDIR_NONE);
111
112 mural->hX = mural->gX-cr_server.screen[0].x;
113 mural->hY = mural->gY-cr_server.screen[0].y;
114
115 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
116
117 return;
118 }
119
120 tlS = crServerGetPointScreen(mural->gX, mural->gY);
121 brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
122
123 if (tlS==brS && tlS>=0)
124 {
125 overlappingScreenCount = 1;
126 primaryS = tlS;
127 }
128 else
129 {
130 trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
131 blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
132
133 primaryS = -1; overlappingScreenCount = 0;
134 for (i=0; i<cr_server.screenCount; ++i)
135 {
136 if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
137 || crServerMuralCoverScreen(mural, i))
138 {
139 overlappingScreenCount++;
140 primaryS = primaryS<0 ? i:primaryS;
141 }
142 }
143
144 if (!overlappingScreenCount)
145 {
146 primaryS = 0;
147 }
148 }
149
150 if (primaryS!=mural->screenId)
151 {
152 mural->screenId = primaryS;
153
154 renderspuSetWindowId(cr_server.screen[primaryS].winID);
155 renderspuReparentWindow(mural->spuWindow);
156 renderspuSetWindowId(cr_server.screen[0].winID);
157 }
158
159 mural->hX = mural->gX-cr_server.screen[primaryS].x;
160 mural->hY = mural->gY-cr_server.screen[primaryS].y;
161
162 if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering)
163 {
164 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
165
166 if (mural->fUseFBO)
167 {
168 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
169 crServerDeleteMuralFBO(mural);
170 }
171
172 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
173 }
174 else
175 {
176 GLubyte redir = overlappingScreenCount >= 2 ? CR_SERVER_REDIR_FBO_RAM : cr_server.bForceOffscreenRendering;
177
178 if (mural->spuWindow)
179 {
180 if (mural->fUseFBO)
181 {
182 if (mural->width!=mural->fboWidth
183 || mural->height!=mural->height)
184 {
185 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
186 crServerDeleteMuralFBO(mural);
187 }
188 }
189
190 if (mural->fUseFBO != redir)
191 {
192 crServerRedirMuralFBO(mural, redir);
193 }
194 }
195#ifdef DEBUG_misha
196 else
197 {
198 Assert(!mural->fUseFBO);
199 }
200#endif
201
202 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
203 {
204 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
205
206 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
207 }
208 }
209
210 if (mural->pvOutputRedirectInstance)
211 {
212 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
213 mural->hX, mural->hY,
214 mural->width, mural->height);
215 }
216}
217
218GLboolean crServerSupportRedirMuralFBO(void)
219{
220 static GLboolean fInited = GL_FALSE;
221 static GLboolean fSupported = GL_FALSE;
222 if (!fInited)
223 {
224 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
225
226 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
227 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
228 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
229 fInited = GL_TRUE;
230 }
231 return fSupported;
232}
233
234void crServerRedirMuralFBO(CRMuralInfo *mural, GLubyte redir)
235{
236 if (mural->fUseFBO == redir)
237 {
238 crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
239 return;
240 }
241
242 if (redir)
243 {
244 if (!crServerSupportRedirMuralFBO())
245 {
246 crWarning("FBO not supported, can't redirect window output");
247 return;
248 }
249
250 if (redir == CR_SERVER_REDIR_FBO_RAM)
251 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
252 else
253 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
254
255 if (mural->idFBO==0)
256 {
257 crServerCreateMuralFBO(mural);
258 }
259
260 if (!crStateGetCurrent()->framebufferobject.drawFB)
261 {
262 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->idFBO);
263 }
264 if (!crStateGetCurrent()->framebufferobject.readFB)
265 {
266 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->idFBO);
267 }
268
269 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
270 {
271 crStateGetCurrent()->buffer.width = 0;
272 crStateGetCurrent()->buffer.height = 0;
273 }
274 }
275 else
276 {
277 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_RAM)
278 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
279
280 if (mural->fUseFBO && crServerSupportRedirMuralFBO())
281 {
282 if (!crStateGetCurrent()->framebufferobject.drawFB)
283 {
284 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
285 }
286 if (!crStateGetCurrent()->framebufferobject.readFB)
287 {
288 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
289 }
290 }
291
292 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
293 {
294 crStateGetCurrent()->buffer.width = mural->width;
295 crStateGetCurrent()->buffer.height = mural->height;
296 }
297 }
298
299 mural->fUseFBO = redir;
300}
301
302void crServerCreateMuralFBO(CRMuralInfo *mural)
303{
304 CRContext *ctx = crStateGetCurrent();
305 GLuint uid;
306 GLenum status;
307 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
308
309 CRASSERT(mural->idFBO==0);
310
311 /*Color texture*/
312 gl->GenTextures(1, &mural->idColorTex);
313 gl->BindTexture(GL_TEXTURE_2D, mural->idColorTex);
314 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
315 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
316 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
317 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
318 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
319 {
320 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
321 }
322 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
323 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
324
325 /*Depth&Stencil*/
326 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
327 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
328 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
329 mural->width, mural->height);
330
331 /*FBO*/
332 gl->GenFramebuffersEXT(1, &mural->idFBO);
333 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->idFBO);
334
335 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
336 GL_TEXTURE_2D, mural->idColorTex, 0);
337 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
338 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
339 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
340 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
341
342 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
343 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
344 {
345 crWarning("FBO status(0x%x) isn't complete", status);
346 }
347
348 mural->fboWidth = mural->width;
349 mural->fboHeight = mural->height;
350
351 /*PBO*/
352 if (cr_server.bUsePBOForReadback)
353 {
354 gl->GenBuffersARB(1, &mural->idPBO);
355 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
356 gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
357 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
358
359 if (!mural->idPBO)
360 {
361 crWarning("PBO create failed");
362 }
363 }
364
365 /*Restore gl state*/
366 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
367 gl->BindTexture(GL_TEXTURE_2D, uid);
368
369 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
370 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
371
372 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
373 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
374
375 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
376 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
377
378 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
379 {
380 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
381 }
382}
383
384void crServerDeleteMuralFBO(CRMuralInfo *mural)
385{
386 CRASSERT(!mural->fUseFBO);
387
388 if (mural->idFBO!=0)
389 {
390 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->idColorTex);
391 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
392 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->idFBO);
393
394 mural->idFBO = 0;
395 mural->idColorTex = 0;
396 mural->idDepthStencilRB = 0;
397 }
398
399 if (mural->idPBO!=0)
400 {
401 CRASSERT(cr_server.bUsePBOForReadback);
402 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
403 mural->idPBO = 0;
404 }
405}
406
407#define MIN(a, b) ((a) < (b) ? (a) : (b))
408#define MAX(a, b) ((a) > (b) ? (a) : (b))
409
410static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
411{
412 CRASSERT(a && b && rect);
413
414 rect->x1 = MAX(a->x1, b->x1);
415 rect->x2 = MIN(a->x2, b->x2);
416 rect->y1 = MAX(a->y1, b->y1);
417 rect->y2 = MIN(a->y2, b->y2);
418
419 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
420}
421
422static GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
423{
424 rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
425 rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
426 rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
427 rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
428
429 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
430}
431
432static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
433{
434 int i;
435 int dstrowsize = 4*(pRect->x2-pRect->x1);
436 int srcrowsize = 4*srcWidth;
437 int height = pRect->y2-pRect->y1;
438
439 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
440
441 for (i=0; i<height; ++i)
442 {
443 crMemcpy(pDst, pSrc, dstrowsize);
444
445 pSrc -= srcrowsize;
446 pDst += dstrowsize;
447 }
448}
449
450static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
451{
452 pDst->x1 = pSrc->x1+dx;
453 pDst->x2 = pSrc->x2+dx;
454 pDst->y1 = pSrc->y1+dy;
455 pDst->y2 = pSrc->y2+dy;
456}
457
458void crServerPresentFBO(CRMuralInfo *mural)
459{
460 char *pixels=NULL, *tmppixels;
461 GLuint uid;
462 int i, j;
463 CRrecti rect, rectwr, sectr;
464 GLboolean bUsePBO;
465 CRContext *ctx = crStateGetCurrent();
466
467 CRASSERT(mural->fUseFBO);
468 CRASSERT(cr_server.pfnPresentFBO || mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT);
469
470 if (!mural->bVisible)
471 {
472 return;
473 }
474
475 if (!mural->width || !mural->height)
476 {
477 return;
478 }
479
480 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT)
481 {
482 int rc;
483 PCR_BLITTER pBlitter = crServerGetFBOPresentBlitter(mural);
484 if (!pBlitter)
485 {
486 static int cPrintedWarnings = 0;
487 if (++cPrintedWarnings <= 5)
488 {
489 crWarning("crServerGetFBOPresentBlitter returned no blitter %d", cPrintedWarnings);
490 if (cPrintedWarnings == 5)
491 crWarning("won't print the above crServerGetFBOPresentBlitter warning any more", cPrintedWarnings);
492 }
493 return;
494 }
495
496 CrBltMuralSetCurrent(pBlitter, mural);
497 rc = CrBltEnter(pBlitter, cr_server.currentCtxInfo, cr_server.currentMural);
498 if (RT_SUCCESS(rc))
499 {
500 CR_BLITTER_TEXTURE Tex;
501 RTRECT Rect;
502 Tex.width = mural->width;
503 Tex.height = mural->height;
504 Tex.target = GL_TEXTURE_2D;
505 Tex.hwid = mural->idColorTex;
506 Rect.xLeft = 0;
507 Rect.yTop = 0;
508 Rect.xRight = Tex.width;
509 Rect.yBottom = Tex.height;
510
511 CrBltBlitTexMural(pBlitter, &Tex, &Rect, &Rect, 1, 0);
512 CrBltPresent(pBlitter);
513
514 CrBltLeave(pBlitter);
515 }
516 else
517 {
518 crWarning("CrBltEnter failed rc %d", rc);
519 return;
520 }
521 return;
522 }
523
524 if (cr_server.bUsePBOForReadback && !mural->idPBO)
525 {
526 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
527 }
528
529 bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO;
530
531 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->idColorTex);
532
533 if (bUsePBO)
534 {
535 CRASSERT(mural->idPBO);
536 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
537 }
538 else
539 {
540 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
541 {
542 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
543 }
544
545 pixels = crAlloc(4*mural->fboWidth*mural->fboHeight);
546 if (!pixels)
547 {
548 crWarning("Out of memory in crServerPresentFBO");
549 return;
550 }
551 }
552
553 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
554 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
555
556 /*restore gl state*/
557 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
558 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
559
560 if (bUsePBO)
561 {
562 pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
563 if (!pixels)
564 {
565 crWarning("Failed to MapBuffer in crServerPresentFBO");
566 return;
567 }
568 }
569
570 for (i=0; i<cr_server.screenCount; ++i)
571 {
572 if (crServerIntersectScreen(mural, i, &rect))
573 {
574 /* rect in window relative coords */
575 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
576
577 if (!mural->pVisibleRects)
578 {
579 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
580 if (!mural->bReceivedRects)
581 {
582 tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
583 if (!tmppixels)
584 {
585 crWarning("Out of memory in crServerPresentFBO");
586 crFree(pixels);
587 return;
588 }
589
590 crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
591 /*Note: pfnPresentFBO would free tmppixels*/
592 cr_server.pfnPresentFBO(tmppixels, i, rect.x1-cr_server.screen[i].x, rect.y1-cr_server.screen[i].y, rect.x2-rect.x1, rect.y2-rect.y1);
593 }
594 }
595 else
596 {
597 for (j=0; j<mural->cVisibleRects; ++j)
598 {
599 if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
600 {
601 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
602 if (!tmppixels)
603 {
604 crWarning("Out of memory in crServerPresentFBO");
605 crFree(pixels);
606 return;
607 }
608
609 crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
610 /*Note: pfnPresentFBO would free tmppixels*/
611 cr_server.pfnPresentFBO(tmppixels, i,
612 sectr.x1+mural->gX-cr_server.screen[i].x,
613 sectr.y1+mural->gY-cr_server.screen[i].y,
614 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
615 }
616 }
617 }
618 }
619 }
620
621 if (mural->pvOutputRedirectInstance)
622 {
623 /* @todo find out why presentfbo is not called but crorframe is called. */
624 cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
625 pixels,
626 4 * mural->fboWidth * mural->fboHeight);
627 }
628
629 if (bUsePBO)
630 {
631 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
632 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
633 }
634 else
635 {
636 crFree(pixels);
637 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
638 {
639 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
640 }
641 }
642}
643
644GLboolean crServerIsRedirectedToFBO()
645{
646 return cr_server.curClient
647 && cr_server.curClient->currentMural
648 && cr_server.curClient->currentMural->fUseFBO;
649}
Note: See TracBrowser for help on using the repository browser.

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