VirtualBox

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

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

crOpenGL: double-buffering for offscreen rendering, bugxifes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 KB
Line 
1/* $Id: server_muralfbo.c 43980 2012-11-28 07:10:56Z 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
234static void crServerCreateMuralFBO(CRMuralInfo *mural);
235
236void crServerRedirMuralFBO(CRMuralInfo *mural, GLubyte redir)
237{
238 if (mural->fUseFBO == redir)
239 {
240 if (redir)
241 crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
242 return;
243 }
244
245 if (redir)
246 {
247 if (!crServerSupportRedirMuralFBO())
248 {
249 crWarning("FBO not supported, can't redirect window output");
250 return;
251 }
252
253 if (redir == CR_SERVER_REDIR_FBO_RAM)
254 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
255 else
256 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
257
258 if (mural->aidFBOs[0]==0)
259 {
260 crServerCreateMuralFBO(mural);
261 }
262
263 if (!crStateGetCurrent()->framebufferobject.drawFB)
264 {
265 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
266 }
267 if (!crStateGetCurrent()->framebufferobject.readFB)
268 {
269 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
270 }
271
272 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
273 {
274 crStateGetCurrent()->buffer.width = 0;
275 crStateGetCurrent()->buffer.height = 0;
276 }
277 }
278 else
279 {
280 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_RAM)
281 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
282
283 if (mural->fUseFBO && crServerSupportRedirMuralFBO())
284 {
285 if (!crStateGetCurrent()->framebufferobject.drawFB)
286 {
287 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
288 }
289 if (!crStateGetCurrent()->framebufferobject.readFB)
290 {
291 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
292 }
293 }
294
295 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
296 {
297 crStateGetCurrent()->buffer.width = mural->width;
298 crStateGetCurrent()->buffer.height = mural->height;
299 }
300 }
301
302 mural->fUseFBO = redir;
303}
304
305static void crServerCreateMuralFBO(CRMuralInfo *mural)
306{
307 CRContext *ctx = crStateGetCurrent();
308 GLuint uid, i;
309 GLenum status;
310 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
311
312 CRASSERT(mural->aidFBOs[0]==0);
313 CRASSERT(mural->aidFBOs[1]==0);
314
315 mural->cBuffers = 2;
316 mural->iBbBuffer = 0;
317 /*Color texture*/
318 for (i = 0; i < mural->cBuffers; ++i)
319 {
320 gl->GenTextures(1, &mural->aidColorTexs[i]);
321 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
322 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
323 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
324 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
325 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
326 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
327 {
328 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
329 }
330 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
331 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
332 }
333
334 /*Depth&Stencil*/
335 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
336 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
337 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
338 mural->width, mural->height);
339
340 /*FBO*/
341 for (i = 0; i < mural->cBuffers; ++i)
342 {
343 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
344 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
345
346 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
347 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
348 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
349 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
350 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
351 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
352
353 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
354 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
355 {
356 crWarning("FBO status(0x%x) isn't complete", status);
357 }
358 }
359
360 mural->fboWidth = mural->width;
361 mural->fboHeight = mural->height;
362
363 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
364 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
365
366 /*PBO*/
367 if (cr_server.bUsePBOForReadback)
368 {
369 gl->GenBuffersARB(1, &mural->idPBO);
370 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
371 gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
372 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
373
374 if (!mural->idPBO)
375 {
376 crWarning("PBO create failed");
377 }
378 }
379
380 /*Restore gl state*/
381 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
382 gl->BindTexture(GL_TEXTURE_2D, uid);
383
384 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
385 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
386
387 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
388 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
389
390 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
391 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
392
393 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
394 {
395 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
396 }
397}
398
399void crServerDeleteMuralFBO(CRMuralInfo *mural)
400{
401 CRASSERT(!mural->fUseFBO);
402
403 if (mural->aidFBOs[0]!=0)
404 {
405 GLuint i;
406 for (i = 0; i < mural->cBuffers; ++i)
407 {
408 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
409 mural->aidColorTexs[i] = 0;
410 }
411
412 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
413 mural->idDepthStencilRB = 0;
414
415 for (i = 0; i < mural->cBuffers; ++i)
416 {
417 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
418 mural->aidFBOs[i] = 0;
419 }
420 }
421
422 if (mural->idPBO!=0)
423 {
424 CRASSERT(cr_server.bUsePBOForReadback);
425 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
426 mural->idPBO = 0;
427 }
428
429 mural->cBuffers = 0;
430}
431
432#define MIN(a, b) ((a) < (b) ? (a) : (b))
433#define MAX(a, b) ((a) > (b) ? (a) : (b))
434
435static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
436{
437 CRASSERT(a && b && rect);
438
439 rect->x1 = MAX(a->x1, b->x1);
440 rect->x2 = MIN(a->x2, b->x2);
441 rect->y1 = MAX(a->y1, b->y1);
442 rect->y2 = MIN(a->y2, b->y2);
443
444 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
445}
446
447static GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
448{
449 rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
450 rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
451 rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
452 rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
453
454 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
455}
456
457static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
458{
459 int i;
460 int dstrowsize = 4*(pRect->x2-pRect->x1);
461 int srcrowsize = 4*srcWidth;
462 int height = pRect->y2-pRect->y1;
463
464 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
465
466 for (i=0; i<height; ++i)
467 {
468 crMemcpy(pDst, pSrc, dstrowsize);
469
470 pSrc -= srcrowsize;
471 pDst += dstrowsize;
472 }
473}
474
475static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
476{
477 pDst->x1 = pSrc->x1+dx;
478 pDst->x2 = pSrc->x2+dx;
479 pDst->y1 = pSrc->y1+dy;
480 pDst->y2 = pSrc->y2+dy;
481}
482
483void crServerPresentFBO(CRMuralInfo *mural)
484{
485 char *pixels=NULL, *tmppixels;
486 GLuint uid;
487 int i, j;
488 CRrecti rect, rectwr, sectr;
489 GLboolean bUsePBO;
490 CRContext *ctx = crStateGetCurrent();
491
492 CRASSERT(mural->fUseFBO);
493 CRASSERT(cr_server.pfnPresentFBO || mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT);
494
495 if (!mural->bVisible)
496 {
497 return;
498 }
499
500 if (!mural->width || !mural->height)
501 {
502 return;
503 }
504
505 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT)
506 {
507 int rc;
508 PCR_BLITTER pBlitter = crServerGetFBOPresentBlitter(mural);
509 if (!pBlitter)
510 {
511 static int cPrintedWarnings = 0;
512 if (++cPrintedWarnings <= 5)
513 {
514 crWarning("crServerGetFBOPresentBlitter returned no blitter %d", cPrintedWarnings);
515 if (cPrintedWarnings == 5)
516 crWarning("won't print the above crServerGetFBOPresentBlitter warning any more", cPrintedWarnings);
517 }
518 return;
519 }
520
521 CrBltMuralSetCurrent(pBlitter, mural);
522 rc = CrBltEnter(pBlitter, cr_server.currentCtxInfo, cr_server.currentMural);
523 if (RT_SUCCESS(rc))
524 {
525 CR_BLITTER_TEXTURE Tex;
526 RTRECT Rect;
527 Tex.width = mural->width;
528 Tex.height = mural->height;
529 Tex.target = GL_TEXTURE_2D;
530 Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
531 Rect.xLeft = 0;
532 Rect.yTop = 0;
533 Rect.xRight = Tex.width;
534 Rect.yBottom = Tex.height;
535
536 CrBltBlitTexMural(pBlitter, &Tex, &Rect, &Rect, 1, 0);
537 CrBltPresent(pBlitter);
538
539 CrBltLeave(pBlitter);
540 }
541 else
542 {
543 crWarning("CrBltEnter failed rc %d", rc);
544 return;
545 }
546 return;
547 }
548
549 if (cr_server.bUsePBOForReadback && !mural->idPBO)
550 {
551 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
552 }
553
554 bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO;
555
556 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
557
558 if (bUsePBO)
559 {
560 CRASSERT(mural->idPBO);
561 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
562 }
563 else
564 {
565 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
566 {
567 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
568 }
569
570 pixels = crAlloc(4*mural->fboWidth*mural->fboHeight);
571 if (!pixels)
572 {
573 crWarning("Out of memory in crServerPresentFBO");
574 return;
575 }
576 }
577
578 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
579 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
580
581 /*restore gl state*/
582 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
583 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
584
585 if (bUsePBO)
586 {
587 pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
588 if (!pixels)
589 {
590 crWarning("Failed to MapBuffer in crServerPresentFBO");
591 return;
592 }
593 }
594
595 for (i=0; i<cr_server.screenCount; ++i)
596 {
597 if (crServerIntersectScreen(mural, i, &rect))
598 {
599 /* rect in window relative coords */
600 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
601
602 if (!mural->pVisibleRects)
603 {
604 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
605 if (!mural->bReceivedRects)
606 {
607 tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
608 if (!tmppixels)
609 {
610 crWarning("Out of memory in crServerPresentFBO");
611 crFree(pixels);
612 return;
613 }
614
615 crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
616 /*Note: pfnPresentFBO would free tmppixels*/
617 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);
618 }
619 }
620 else
621 {
622 for (j=0; j<mural->cVisibleRects; ++j)
623 {
624 if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
625 {
626 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
627 if (!tmppixels)
628 {
629 crWarning("Out of memory in crServerPresentFBO");
630 crFree(pixels);
631 return;
632 }
633
634 crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
635 /*Note: pfnPresentFBO would free tmppixels*/
636 cr_server.pfnPresentFBO(tmppixels, i,
637 sectr.x1+mural->gX-cr_server.screen[i].x,
638 sectr.y1+mural->gY-cr_server.screen[i].y,
639 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
640 }
641 }
642 }
643 }
644 }
645
646 if (mural->pvOutputRedirectInstance)
647 {
648 /* @todo find out why presentfbo is not called but crorframe is called. */
649 cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
650 pixels,
651 4 * mural->fboWidth * mural->fboHeight);
652 }
653
654 if (bUsePBO)
655 {
656 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
657 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
658 }
659 else
660 {
661 crFree(pixels);
662 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
663 {
664 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
665 }
666 }
667}
668
669GLboolean crServerIsRedirectedToFBO()
670{
671 return cr_server.curClient
672 && cr_server.curClient->currentMural
673 && cr_server.curClient->currentMural->fUseFBO;
674}
675
676GLuint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
677{
678 if (buffer == GL_FRONT
679 || buffer == GL_FRONT_LEFT
680 || buffer == GL_FRONT_RIGHT)
681 return CR_SERVER_FBO_FB_IDX(mural);
682 return CR_SERVER_FBO_BB_IDX(mural);
683}
684
685void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
686{
687 CRContext *ctx = crStateGetCurrent();
688 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
689 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
690 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
691 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
692 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
693 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1);
694 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1);
695 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
696 {
697 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
698 }
699 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
700 {
701 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
702 }
703}
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