VirtualBox

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

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

crOpenGL: offscreen rendering & VRDP+3D-related fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/* $Id: server_muralfbo.c 45009 2013-03-12 17:27:04Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Window to FBO redirect support.
5 */
6
7/*
8 * Copyright (C) 2010-2013 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 "cr_vreg.h"
23#include "render/renderspu.h"
24
25static int crServerGetPointScreen(GLint x, GLint y)
26{
27 int i;
28
29 for (i=0; i<cr_server.screenCount; ++i)
30 {
31 if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
32 && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
33 {
34 return i;
35 }
36 }
37
38 return -1;
39}
40
41static GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
42{
43 return mural->gX < cr_server.screen[sId].x
44 && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
45 && mural->gY < cr_server.screen[sId].y
46 && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
47}
48
49/* Called when a new CRMuralInfo is created
50 * or when OutputRedirect status is changed.
51 */
52void crServerSetupOutputRedirect(CRMuralInfo *mural)
53{
54 /* Unset the previous redirect. */
55 if (mural->pvOutputRedirectInstance)
56 {
57 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
58 mural->pvOutputRedirectInstance = NULL;
59 }
60
61 /* Setup a new redirect. */
62 if (cr_server.bUseOutputRedirect)
63 {
64 /* Query supported formats. */
65 uint32_t cbFormats = 4096;
66 char *pachFormats = (char *)crAlloc(cbFormats);
67
68 if (pachFormats)
69 {
70 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
71 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
72 pachFormats, cbFormats, &cbFormats);
73 if (RT_SUCCESS(rc))
74 {
75 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
76 {
77 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
78 &mural->pvOutputRedirectInstance,
79 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
80 }
81 }
82
83 crFree(pachFormats);
84 }
85
86 /* If this is not NULL then there was a supported format. */
87 if (mural->pvOutputRedirectInstance)
88 {
89 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
90 mural->hX, mural->hY,
91 mural->width, mural->height);
92 // @todo the code assumes that RTRECT == four of GLInts
93 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
94 mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
95 }
96 }
97}
98
99void crServerCheckMuralGeometry(CRMuralInfo *mural)
100{
101 int tlS, brS, trS, blS;
102 int overlappingScreenCount, primaryS, i;
103
104 if (!mural->CreateInfo.externalID)
105 return;
106
107 if (!mural->width || !mural->height)
108 return;
109
110 if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering)
111 {
112 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
113 CRASSERT(cr_server.screenCount>0);
114 CRASSERT(mural->fUseFBO == CR_SERVER_REDIR_NONE);
115
116 mural->hX = mural->gX-cr_server.screen[0].x;
117 mural->hY = mural->gY-cr_server.screen[0].y;
118
119 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
120
121 return;
122 }
123
124 tlS = crServerGetPointScreen(mural->gX, mural->gY);
125 brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
126
127 if (tlS==brS && tlS>=0)
128 {
129 overlappingScreenCount = 1;
130 primaryS = tlS;
131 }
132 else
133 {
134 trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
135 blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
136
137 primaryS = -1; overlappingScreenCount = 0;
138 for (i=0; i<cr_server.screenCount; ++i)
139 {
140 if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
141 || crServerMuralCoverScreen(mural, i))
142 {
143 overlappingScreenCount++;
144 primaryS = primaryS<0 ? i:primaryS;
145 }
146 }
147
148 if (!overlappingScreenCount)
149 {
150 primaryS = 0;
151 }
152 }
153
154 if (primaryS!=mural->screenId)
155 {
156 mural->screenId = primaryS;
157
158 renderspuSetWindowId(cr_server.screen[primaryS].winID);
159 renderspuReparentWindow(mural->spuWindow);
160 renderspuSetWindowId(cr_server.screen[0].winID);
161 }
162
163 mural->hX = mural->gX-cr_server.screen[primaryS].x;
164 mural->hY = mural->gY-cr_server.screen[primaryS].y;
165
166 if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering)
167 {
168 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
169
170 if (mural->fUseFBO)
171 {
172 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
173 crServerDeleteMuralFBO(mural);
174 }
175
176 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
177 }
178 else
179 {
180 GLubyte redir = overlappingScreenCount >= 2 ? CR_SERVER_REDIR_FBO_RAM : cr_server.bForceOffscreenRendering;
181
182 if (mural->spuWindow)
183 {
184 if (mural->fUseFBO)
185 {
186 if (mural->width!=mural->fboWidth
187 || mural->height!=mural->fboHeight)
188 {
189 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
190 crServerDeleteMuralFBO(mural);
191 }
192 }
193
194 if (mural->fUseFBO != redir)
195 {
196 crServerRedirMuralFBO(mural, redir);
197 }
198 }
199#ifdef DEBUG_misha
200 else
201 {
202 Assert(!mural->fUseFBO);
203 }
204#endif
205
206 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
207 {
208 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
209
210 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
211 }
212 }
213
214 if (mural->pvOutputRedirectInstance)
215 {
216 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
217 mural->hX, mural->hY,
218 mural->width, mural->height);
219 }
220}
221
222GLboolean crServerSupportRedirMuralFBO(void)
223{
224 static GLboolean fInited = GL_FALSE;
225 static GLboolean fSupported = GL_FALSE;
226 if (!fInited)
227 {
228 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
229
230 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
231 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
232 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
233 fInited = GL_TRUE;
234 }
235 return fSupported;
236}
237
238static void crServerCreateMuralFBO(CRMuralInfo *mural);
239
240void crServerRedirMuralFBO(CRMuralInfo *mural, GLubyte redir)
241{
242 if (mural->fUseFBO == redir)
243 {
244 if (redir)
245 crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
246 return;
247 }
248
249 if (redir)
250 {
251 if (!crServerSupportRedirMuralFBO())
252 {
253 crWarning("FBO not supported, can't redirect window output");
254 return;
255 }
256
257 if (redir == CR_SERVER_REDIR_FBO_RAM)
258 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
259 else
260 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
261
262 if (mural->aidFBOs[0]==0)
263 {
264 crServerCreateMuralFBO(mural);
265 }
266
267 if (cr_server.currentMural == mural)
268 {
269 if (!crStateGetCurrent()->framebufferobject.drawFB)
270 {
271 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
272 }
273 if (!crStateGetCurrent()->framebufferobject.readFB)
274 {
275 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
276 }
277
278 crStateGetCurrent()->buffer.width = 0;
279 crStateGetCurrent()->buffer.height = 0;
280 }
281 }
282 else
283 {
284 if (redir == CR_SERVER_REDIR_NONE)
285 {
286 /* tell renderspu we do not want compositor presentation anymore
287 * renderspu will ensure its redraw thread is done with using the compositor, etc. */
288 crServerVBoxCompositionDisable(mural);
289 }
290
291 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_RAM)
292 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
293
294 if (cr_server.currentMural == mural)
295 {
296 if (!crStateGetCurrent()->framebufferobject.drawFB)
297 {
298 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
299 }
300 if (!crStateGetCurrent()->framebufferobject.readFB)
301 {
302 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
303 }
304
305 crStateGetCurrent()->buffer.width = mural->width;
306 crStateGetCurrent()->buffer.height = mural->height;
307 }
308 }
309
310 mural->fUseFBO = redir;
311}
312
313static void crServerCreateMuralFBO(CRMuralInfo *mural)
314{
315 CRContext *ctx = crStateGetCurrent();
316 GLuint uid, i;
317 GLenum status;
318 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
319 CRContextInfo *pMuralContextInfo;
320
321 CRASSERT(mural->aidFBOs[0]==0);
322 CRASSERT(mural->aidFBOs[1]==0);
323 CRASSERT(mural->width == mural->CEntry.Tex.width);
324 CRASSERT(mural->height == mural->CEntry.Tex.height);
325
326 pMuralContextInfo = cr_server.currentCtxInfo;
327 if (!pMuralContextInfo)
328 {
329 /* happens on saved state load */
330 CRASSERT(cr_server.MainContextInfo.SpuContext);
331 pMuralContextInfo = &cr_server.MainContextInfo;
332 cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
333 }
334
335 if (pMuralContextInfo->CreateInfo.visualBits != mural->CreateInfo.visualBits)
336 {
337 crWarning("mural visual bits do not match with current context visual bits!");
338 }
339
340 mural->cBuffers = 2;
341 mural->iBbBuffer = 0;
342 /*Color texture*/
343 for (i = 0; i < mural->cBuffers; ++i)
344 {
345 gl->GenTextures(1, &mural->aidColorTexs[i]);
346 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
347 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
348 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
349 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
350 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
351 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
352 {
353 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
354 }
355 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
356 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
357 }
358
359 /*Depth&Stencil*/
360 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
361 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
362 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
363 mural->width, mural->height);
364
365 /*FBO*/
366 for (i = 0; i < mural->cBuffers; ++i)
367 {
368 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
369 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
370
371 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
372 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
373 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
374 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
375 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
376 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
377
378 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
379 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
380 {
381 crWarning("FBO status(0x%x) isn't complete", status);
382 }
383 }
384
385 mural->fboWidth = mural->width;
386 mural->fboHeight = mural->height;
387
388 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
389 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
390
391 /*PBO*/
392 if (cr_server.bUsePBOForReadback)
393 {
394 gl->GenBuffersARB(1, &mural->idPBO);
395 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
396 gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
397 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
398
399 if (!mural->idPBO)
400 {
401 crWarning("PBO create failed");
402 }
403 }
404
405 /*Restore gl state*/
406 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
407 gl->BindTexture(GL_TEXTURE_2D, uid);
408
409 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
410 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
411
412 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
413 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
414
415 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
416 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
417
418 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
419 {
420 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
421 }
422
423 CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
424 CrVrScrCompositorEntryTexNameUpdate(&mural->CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
425}
426
427void crServerDeleteMuralFBO(CRMuralInfo *mural)
428{
429 CRASSERT(!mural->fUseFBO);
430
431 if (mural->aidFBOs[0]!=0)
432 {
433 GLuint i;
434 for (i = 0; i < mural->cBuffers; ++i)
435 {
436 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
437 mural->aidColorTexs[i] = 0;
438 }
439
440 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
441 mural->idDepthStencilRB = 0;
442
443 for (i = 0; i < mural->cBuffers; ++i)
444 {
445 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
446 mural->aidFBOs[i] = 0;
447 }
448 }
449
450 if (mural->idPBO!=0)
451 {
452 CRASSERT(cr_server.bUsePBOForReadback);
453 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
454 mural->idPBO = 0;
455 }
456
457 mural->cBuffers = 0;
458}
459
460#define MIN(a, b) ((a) < (b) ? (a) : (b))
461#define MAX(a, b) ((a) > (b) ? (a) : (b))
462
463static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
464{
465 CRASSERT(a && b && rect);
466
467 rect->x1 = MAX(a->x1, b->x1);
468 rect->x2 = MIN(a->x2, b->x2);
469 rect->y1 = MAX(a->y1, b->y1);
470 rect->y2 = MIN(a->y2, b->y2);
471
472 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
473}
474
475static GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
476{
477 rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
478 rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
479 rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
480 rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
481
482 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
483}
484
485static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
486{
487 int i;
488 int dstrowsize = 4*(pRect->x2-pRect->x1);
489 int srcrowsize = 4*srcWidth;
490 int height = pRect->y2-pRect->y1;
491
492 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
493
494 for (i=0; i<height; ++i)
495 {
496 crMemcpy(pDst, pSrc, dstrowsize);
497
498 pSrc -= srcrowsize;
499 pDst += dstrowsize;
500 }
501}
502
503static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
504{
505 pDst->x1 = pSrc->x1+dx;
506 pDst->x2 = pSrc->x2+dx;
507 pDst->y1 = pSrc->y1+dy;
508 pDst->y2 = pSrc->y2+dy;
509}
510
511void crServerVBoxCompositionPresent(CRMuralInfo *mural)
512{
513 CRMuralInfo *currentMural = cr_server.currentMural;
514 CRContextInfo *curCtxInfo = cr_server.currentCtxInfo;
515 GLuint idDrawFBO, idReadFBO;
516 CRContext *curCtx = curCtxInfo->pContext;
517
518 CRASSERT(curCtx == crStateGetCurrent());
519
520 if (!mural->bVisible)
521 {
522 return;
523 }
524
525 if (!mural->width || !mural->height)
526 {
527 return;
528 }
529
530 if (!CrVrScrCompositorEntryIsInList(&mural->CEntry))
531 return;
532
533 if (currentMural)
534 {
535 idDrawFBO = currentMural->aidFBOs[currentMural->iCurDrawBuffer];
536 idReadFBO = currentMural->aidFBOs[currentMural->iCurReadBuffer];
537 }
538 else
539 {
540 idDrawFBO = 0;
541 idReadFBO = 0;
542 }
543
544 crStateSwitchPrepare(NULL, curCtx, idDrawFBO, idReadFBO);
545
546 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, &mural->CEntry);
547
548 crStateSwitchPostprocess(curCtx, NULL, idDrawFBO, idReadFBO);
549
550 mural->fCompositorPresented = GL_TRUE;
551}
552
553void crServerVBoxCompositionReenable(CRMuralInfo *mural)
554{
555 if (!mural->fCompositorPresented)
556 return;
557
558 crServerVBoxCompositionPresent(mural);
559}
560
561void crServerVBoxCompositionDisable(CRMuralInfo *mural)
562{
563 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
564}
565
566void crServerPresentFBO(CRMuralInfo *mural)
567{
568 char *pixels=NULL, *tmppixels;
569 int i, j;
570 CRrecti rect, rectwr, sectr;
571 GLuint idPBO;
572 CRContext *ctx = crStateGetCurrent();
573 VBOXVR_TEXTURE Tex;
574
575 CRASSERT(mural->fUseFBO);
576 CRASSERT(cr_server.pfnPresentFBO || mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT);
577
578 if (!mural->bVisible)
579 {
580 return;
581 }
582
583 if (!mural->width || !mural->height)
584 {
585 return;
586 }
587
588 if (!CrVrScrCompositorEntryIsInList(&mural->CEntry))
589 return;
590
591 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT)
592 {
593 crServerVBoxCompositionPresent(mural);
594 return;
595 }
596
597 Tex.width = mural->width;
598 Tex.height = mural->height;
599 Tex.target = GL_TEXTURE_2D;
600 Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
601 CRASSERT(Tex.hwid);
602
603 if (cr_server.bUsePBOForReadback && !mural->idPBO)
604 {
605 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
606 }
607
608 idPBO = cr_server.bUsePBOForReadback ? mural->idPBO : 0;
609 if (idPBO)
610 {
611 CRASSERT(mural->fboWidth == mural->width);
612 CRASSERT(mural->fboHeight == mural->height);
613 }
614
615 pixels = CrHlpGetTexImage(ctx, &Tex, idPBO, GL_BGRA);
616 if (!pixels)
617 {
618 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
619 return;
620 }
621
622 for (i=0; i<cr_server.screenCount; ++i)
623 {
624 if (crServerIntersectScreen(mural, i, &rect))
625 {
626 /* rect in window relative coords */
627 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
628
629 if (!mural->pVisibleRects)
630 {
631 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
632 if (!mural->bReceivedRects)
633 {
634 tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
635 if (!tmppixels)
636 {
637 crWarning("Out of memory in crServerPresentFBO");
638 crFree(pixels);
639 return;
640 }
641
642 crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
643 /*Note: pfnPresentFBO would free tmppixels*/
644 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);
645 }
646 }
647 else
648 {
649 for (j=0; j<mural->cVisibleRects; ++j)
650 {
651 if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
652 {
653 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
654 if (!tmppixels)
655 {
656 crWarning("Out of memory in crServerPresentFBO");
657 crFree(pixels);
658 return;
659 }
660
661 crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
662 /*Note: pfnPresentFBO would free tmppixels*/
663 cr_server.pfnPresentFBO(tmppixels, i,
664 sectr.x1+mural->gX-cr_server.screen[i].x,
665 sectr.y1+mural->gY-cr_server.screen[i].y,
666 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
667 }
668 }
669 }
670 }
671 }
672
673 if (mural->pvOutputRedirectInstance)
674 {
675 /* @todo find out why presentfbo is not called but crorframe is called. */
676 cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
677 pixels,
678 4 * mural->fboWidth * mural->fboHeight);
679 }
680
681 CrHlpFreeTexImage(ctx, idPBO, pixels);
682}
683
684GLboolean crServerIsRedirectedToFBO()
685{
686 return cr_server.curClient
687 && cr_server.curClient->currentMural
688 && cr_server.curClient->currentMural->fUseFBO;
689}
690
691GLuint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
692{
693 if (buffer == GL_FRONT
694 || buffer == GL_FRONT_LEFT
695 || buffer == GL_FRONT_RIGHT)
696 return CR_SERVER_FBO_FB_IDX(mural);
697 return CR_SERVER_FBO_BB_IDX(mural);
698}
699
700void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
701{
702 CRContext *ctx = crStateGetCurrent();
703 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
704 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
705 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
706 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
707 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
708 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1);
709 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1);
710 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
711 {
712 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
713 }
714 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
715 {
716 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
717 }
718 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
719 CrVrScrCompositorEntryTexNameUpdate(&mural->CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
720}
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