VirtualBox

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

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

crOpenGL: unify saved fb/bb image data format

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