VirtualBox

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

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

crOpenGL: more output redirect enhance

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.2 KB
Line 
1/* $Id: server_muralfbo.c 47628 2013-08-09 09:08:20Z 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
49void crServerDEntryResized(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
50{
51 /*PBO*/
52 if (pDEntry->idPBO)
53 {
54 CRASSERT(cr_server.bUsePBOForReadback);
55 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
56 pDEntry->idPBO = 0;
57 }
58
59 if (pDEntry->idInvertTex)
60 {
61 cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
62 pDEntry->idInvertTex = 0;
63 }
64
65 if (pDEntry->pvORInstance)
66 {
67 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
68 pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
69 pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
70 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
71 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
72
73 crServerDEntryVibleRegions(pMural, pDEntry);
74 }
75}
76
77void crServerDEntryMoved(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
78{
79 if (pDEntry->pvORInstance)
80 {
81 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
82 pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
83 pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
84 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
85 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
86
87 crServerDEntryVibleRegions(pMural, pDEntry);
88 }
89
90}
91
92void crServerDEntryVibleRegions(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
93{
94 if (pDEntry->pvORInstance)
95 {
96 uint32_t cRects;
97 const RTRECT *pRects;
98
99 int rc = CrVrScrCompositorEntryRegionsGet(&pMural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
100 if (!RT_SUCCESS(rc))
101 {
102 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
103 return;
104 }
105
106 cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
107 }
108}
109
110/***/
111void crServerDEntryAllResized(CRMuralInfo *pMural)
112{
113 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
114 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
115
116 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
117 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
118 {
119 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
120 crServerDEntryResized(pMural, pDEntry);
121 }
122}
123
124void crServerDEntryAllMoved(CRMuralInfo *pMural)
125{
126 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
127 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
128
129 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
130
131 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
132 {
133 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
134 crServerDEntryMoved(pMural, pDEntry);
135 }
136}
137
138void crServerDEntryAllVibleRegions(CRMuralInfo *pMural)
139{
140 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
141 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
142
143 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
144
145 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
146 {
147 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
148 crServerDEntryVibleRegions(pMural, pDEntry);
149 }
150}
151/**/
152
153void crServerDEntryCheckFBO(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
154{
155 if (!cr_server.bUsePBOForReadback == !pDEntry->idPBO)
156 return;
157
158 if (cr_server.bUsePBOForReadback)
159 {
160 Assert(!pDEntry->idPBO);
161 cr_server.head_spu->dispatch_table.GenBuffersARB(1, &pDEntry->idPBO);
162 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pDEntry->idPBO);
163 cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
164 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width*CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height*4,
165 0, GL_STREAM_READ_ARB);
166 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
167
168 if (!pDEntry->idPBO)
169 {
170 crWarning("PBO create failed");
171 }
172 }
173}
174
175void crServerDEntryCheckInvertTex(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
176{
177 CRContextInfo *pMuralContextInfo;
178
179 if (pDEntry->idInvertTex)
180 return;
181
182 pMuralContextInfo = cr_server.currentCtxInfo;
183 if (!pMuralContextInfo)
184 {
185 /* happens on saved state load */
186 CRASSERT(cr_server.MainContextInfo.SpuContext);
187 pMuralContextInfo = &cr_server.MainContextInfo;
188 cr_server.head_spu->dispatch_table.MakeCurrent(pMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
189 }
190
191 if (pMuralContextInfo->CreateInfo.visualBits != pMural->CreateInfo.visualBits)
192 {
193 crWarning("mural visual bits do not match with current context visual bits!");
194 }
195
196 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
197 {
198 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
199 }
200
201 cr_server.head_spu->dispatch_table.GenTextures(1, &pDEntry->idInvertTex);
202 CRASSERT(pDEntry->idInvertTex);
203 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, pDEntry->idInvertTex);
204 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
205 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
206 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
207 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
208 cr_server.head_spu->dispatch_table.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
209 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
210 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
211 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
212
213
214 /*Restore gl state*/
215 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D,
216 ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid);
217
218 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
219 {
220 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
221 }
222
223 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
224 {
225 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
226 }
227 else
228 {
229 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
230 }
231}
232
233void crServerDEntryImgRelease(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, void*pvImg)
234{
235 GLuint idPBO;
236 CRContext *ctx = crStateGetCurrent();
237
238 idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
239
240 CrHlpFreeTexImage(ctx, idPBO, pvImg);
241}
242
243
244void* crServerDEntryImgAcquire(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, GLenum enmFormat)
245{
246 void* pvData;
247 GLuint idPBO;
248 VBOXVR_TEXTURE Tex;
249 const VBOXVR_TEXTURE * pTex;
250 CRContext *ctx = crStateGetCurrent();
251
252 crServerDEntryCheckFBO(pMural, pDEntry, ctx);
253
254 if (cr_server.bUsePBOForReadback && !pDEntry->idPBO)
255 {
256 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
257 }
258
259 idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
260
261 if (!(CrVrScrCompositorEntryFlagsGet(&pDEntry->CEntry) & CRBLT_F_INVERT_SRC_YCOORDS))
262 pTex = CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
263 else
264 {
265 CRMuralInfo *pCurrentMural = cr_server.currentMural;
266 CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
267 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
268 CRMuralInfo *pBlitterMural;
269 CR_SERVER_CTX_SWITCH CtxSwitch;
270 RTRECT SrcRect, DstRect;
271 CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
272 CR_BLITTER_CONTEXT CtxBltInfo;
273 int rc;
274
275 crServerDEntryCheckInvertTex(pMural, pDEntry, ctx);
276 if (!pDEntry->idInvertTex)
277 {
278 crWarning("crServerDEntryCheckInvertTex failed");
279 return NULL;
280 }
281
282 Tex = *CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
283 Tex.hwid = pDEntry->idInvertTex;
284
285 SrcRect.xLeft = 0;
286 SrcRect.yTop = Tex.height;
287 SrcRect.xRight = Tex.width;
288 SrcRect.yBottom = 0;
289
290 DstRect.xLeft = 0;
291 DstRect.yTop = 0;
292 DstRect.xRight = Tex.width;
293 DstRect.yBottom = Tex.height;
294
295 if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
296 {
297 pBlitterMural = pCurrentMural;
298 }
299 else
300 {
301 pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
302 if (!pBlitterMural)
303 {
304 crWarning("crServerGetDummyMural failed for blitter mural");
305 return NULL;
306 }
307 }
308
309 crServerCtxSwitchPrepare(&CtxSwitch, NULL);
310
311 crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
312 crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
313 crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
314
315 CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
316
317 rc = CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
318 if (RT_SUCCESS(rc))
319 {
320 CrBltBlitTexTex(pBlitter, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry), &SrcRect, &Tex, &DstRect, 1, 0);
321 CrBltLeave(pBlitter);
322 }
323 else
324 {
325 crWarning("CrBltEnter failed rc %d", rc);
326 }
327
328 crServerCtxSwitchPostprocess(&CtxSwitch);
329
330 pTex = &Tex;
331 }
332
333 pvData = CrHlpGetTexImage(ctx, pTex, idPBO, enmFormat);
334 if (!pvData)
335 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
336
337 return pvData;
338}
339
340
341/* Called when a new CRMuralInfo is created
342 * or when OutputRedirect status is changed.
343 */
344void crServerSetupOutputRedirectEntry(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry)
345{
346 /* Unset the previous redirect. */
347 if (pDEntry->pvORInstance)
348 {
349 cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
350 pDEntry->pvORInstance = NULL;
351 }
352
353 /* Setup a new redirect. */
354 if (cr_server.bUseOutputRedirect)
355 {
356 /* Query supported formats. */
357 uint32_t cbFormats = 4096;
358 char *pachFormats = (char *)crAlloc(cbFormats);
359
360 if (pachFormats)
361 {
362 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
363 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
364 pachFormats, cbFormats, &cbFormats);
365 if (RT_SUCCESS(rc))
366 {
367 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
368 {
369 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
370 &pDEntry->pvORInstance,
371 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
372 }
373 }
374
375 crFree(pachFormats);
376 }
377
378 /* If this is not NULL then there was a supported format. */
379 if (pDEntry->pvORInstance)
380 {
381 uint32_t cRects;
382 const RTRECT *pRects;
383
384 int rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
385 if (!RT_SUCCESS(rc))
386 {
387 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
388 return;
389 }
390
391 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
392 mural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
393 mural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
394 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
395 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
396
397 cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
398//!!
399// crServerPresentFBO(mural);
400 }
401 }
402}
403
404void crServerCheckMuralGeometry(CRMuralInfo *mural)
405{
406 int tlS, brS, trS, blS;
407 int overlappingScreenCount = 0, primaryS = -1 , i;
408 uint64_t winID = 0;
409 GLuint fPresentMode;
410
411 if (!mural->CreateInfo.externalID)
412 return;
413
414 CRASSERT(mural->spuWindow);
415 CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
416
417 crServerVBoxCompositionDisableEnter(mural);
418
419 if (!mural->width || !mural->height)
420 {
421 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_F_NONE);
422 crServerDeleteMuralFBO(mural);
423 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
424 return;
425 }
426
427 tlS = crServerGetPointScreen(mural->gX, mural->gY);
428 brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
429
430 if ((tlS==brS && tlS>=0) || cr_server.screenCount <= 1)
431 {
432 if (cr_server.screenCount <= 1)
433 {
434 if (tlS != brS)
435 {
436 if (tlS >= 0)
437 brS = tlS;
438 else
439 tlS = brS;
440 }
441
442 primaryS = 0;
443 }
444 else
445 {
446 Assert(brS == tlS);
447
448 primaryS = brS;
449 }
450
451
452 Assert(brS == tlS);
453
454 if (tlS>=0 && cr_server.screen[tlS].winID)
455 {
456 overlappingScreenCount = 1;
457 }
458 }
459 else
460 {
461 bool fFoundWindIdScreen = false;
462 trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
463 blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
464
465 primaryS = -1; overlappingScreenCount = 0;
466 for (i=0; i<cr_server.screenCount; ++i)
467 {
468 if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
469 || crServerMuralCoverScreen(mural, i))
470 {
471 if ((!fFoundWindIdScreen && cr_server.screen[i].winID) || primaryS<0)
472 primaryS = i;
473
474 if (cr_server.screen[i].winID)
475 {
476 overlappingScreenCount++;
477 fFoundWindIdScreen = true;
478 }
479 }
480 }
481
482 if (primaryS<0)
483 {
484 primaryS = 0;
485 }
486 }
487
488 CRASSERT(primaryS >= 0);
489
490 winID = overlappingScreenCount ? cr_server.screen[primaryS].winID : 0;
491
492 if (!winID != !mural->fHasParentWindow
493 || (winID && primaryS!=mural->screenId))
494 {
495 mural->fHasParentWindow = !!winID;
496
497 renderspuSetWindowId(winID);
498 renderspuReparentWindow(mural->spuWindow);
499 renderspuSetWindowId(cr_server.screen[0].winID);
500 }
501
502 if (primaryS != mural->screenId)
503 {
504 /* mark it invisible on the old screen */
505 crServerWindowSetIsVisible(mural, GL_FALSE);
506 mural->screenId = primaryS;
507 /* check if mural is visivle on the new screen, and mark it as such */
508 crServerWindowCheckIsVisible(mural);
509 }
510
511 mural->hX = mural->gX-cr_server.screen[primaryS].x;
512 mural->hY = mural->gY-cr_server.screen[primaryS].y;
513
514 fPresentMode = cr_server.fPresentMode;
515
516 if (!mural->fHasParentWindow)
517 fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
518
519 if (!overlappingScreenCount)
520 fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
521 else if (overlappingScreenCount > 1)
522 fPresentMode = (fPresentMode | CR_SERVER_REDIR_F_FBO_RAM_VMFB | cr_server.fVramPresentModeDefault) & ~CR_SERVER_REDIR_F_DISPLAY;
523
524 if (!mural->fUseDefaultDEntry)
525 {
526 /* only display matters */
527 fPresentMode &= CR_SERVER_REDIR_F_DISPLAY;
528 }
529
530 fPresentMode = crServerRedirModeAdjust(fPresentMode);
531
532 if (!(fPresentMode & CR_SERVER_REDIR_F_FBO))
533 {
534 crServerRedirMuralFBO(mural, fPresentMode);
535 crServerDeleteMuralFBO(mural);
536 }
537 else
538 {
539 if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO)
540 {
541 if (mural->width!=mural->fboWidth
542 || mural->height!=mural->fboHeight)
543 {
544 crServerRedirMuralFBO(mural, fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
545 crServerDeleteMuralFBO(mural);
546 }
547 }
548
549 crServerRedirMuralFBO(mural, fPresentMode);
550 }
551
552 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
553 {
554 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
555
556 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
557 }
558
559 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
560}
561
562GLboolean crServerSupportRedirMuralFBO(void)
563{
564 static GLboolean fInited = GL_FALSE;
565 static GLboolean fSupported = GL_FALSE;
566 if (!fInited)
567 {
568 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
569
570 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
571 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
572 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
573 fInited = GL_TRUE;
574 }
575 return fSupported;
576}
577
578static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels);
579
580#define CR_SERVER_MURAL_FROM_RPW_ENTRY(_pEntry) ((CRMuralInfo*)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(CRMuralInfo, RpwEntry)))
581
582static DECLCALLBACK(void) crServerMuralRpwDataCB(const struct CR_SERVER_RPW_ENTRY* pEntry, void *pvEntryTexData)
583{
584 CRMuralInfo *pMural = CR_SERVER_MURAL_FROM_RPW_ENTRY(pEntry);
585
586 Assert(&pMural->RpwEntry == pEntry);
587 crError("port me!");
588 // crServerPresentMuralVRAM(pMural, pvEntryTexData);
589}
590
591static void crServerCreateMuralFBO(CRMuralInfo *mural);
592
593static bool crServerEnableMuralRpw(CRMuralInfo *mural, GLboolean fEnable)
594{
595 if (!mural->CreateInfo.externalID)
596 {
597 crWarning("trying to change Rpw setting for internal mural %d", mural->spuWindow);
598 return !fEnable;
599 }
600
601 if (fEnable)
602 {
603 if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
604 {
605 int rc;
606 if (!crServerRpwIsInitialized(&cr_server.RpwWorker))
607 {
608 rc = crServerRpwInit(&cr_server.RpwWorker);
609 if (!RT_SUCCESS(rc))
610 {
611 crWarning("crServerRpwInit failed rc %d", rc);
612 return false;
613 }
614 }
615
616 CRASSERT(!mural->RpwEntry.Size.cx);
617 CRASSERT(!mural->RpwEntry.Size.cy);
618
619 if (!crServerRpwEntryIsInitialized(&mural->RpwEntry))
620 {
621 rc = crServerRpwEntryInit(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height, crServerMuralRpwDataCB);
622 if (!RT_SUCCESS(rc))
623 {
624 crWarning("crServerRpwEntryInit failed rc %d", rc);
625 return false;
626 }
627 }
628 else
629 {
630 rc = crServerRpwEntryResize(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height);
631 if (!RT_SUCCESS(rc))
632 {
633 crWarning("crServerRpwEntryResize failed rc %d", rc);
634 return false;
635 }
636 }
637
638 mural->fPresentMode |= CR_SERVER_REDIR_F_FBO_RPW;
639 }
640 }
641 else
642 {
643 if ((mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
644 {
645// crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
646 mural->fPresentMode &= ~CR_SERVER_REDIR_F_FBO_RPW;
647 }
648 }
649
650 return true;
651}
652
653static void crServerEnableDisplayMuralFBO(CRMuralInfo *mural, GLboolean fEnable)
654{
655 if (!mural->CreateInfo.externalID)
656 {
657 crWarning("trying to change display setting for internal mural %d", mural->spuWindow);
658 return;
659 }
660
661 if (fEnable)
662 {
663 if (!(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
664 {
665 mural->fPresentMode |= CR_SERVER_REDIR_F_DISPLAY;
666
667 if (mural->bVisible)
668 crServerWindowShow(mural);
669 }
670 }
671 else
672 {
673 if ((mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
674 {
675 mural->fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
676
677 if (mural->bVisible)
678 crServerWindowShow(mural);
679 }
680 }
681}
682
683void crServerRedirMuralFBO(CRMuralInfo *mural, GLuint redir)
684{
685 if (mural->fPresentMode == redir)
686 {
687// if (redir)
688// crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
689 return;
690 }
691
692 if (!mural->CreateInfo.externalID)
693 {
694 crWarning("trying to change redir setting for internal mural %d", mural->spuWindow);
695 return;
696 }
697
698 crServerVBoxCompositionDisableEnter(mural);
699
700 if (redir & CR_SERVER_REDIR_F_FBO)
701 {
702 if (!crServerSupportRedirMuralFBO())
703 {
704 crWarning("FBO not supported, can't redirect window output");
705 goto end;
706 }
707
708 if (mural->fUseDefaultDEntry && mural->aidFBOs[0]==0)
709 {
710 crServerCreateMuralFBO(mural);
711 }
712
713 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
714 {
715 if (!crStateGetCurrent()->framebufferobject.drawFB)
716 {
717 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
718 }
719 if (!crStateGetCurrent()->framebufferobject.readFB)
720 {
721 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
722 }
723
724 crStateGetCurrent()->buffer.width = 0;
725 crStateGetCurrent()->buffer.height = 0;
726 }
727 }
728 else
729 {
730 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
731 {
732 if (!crStateGetCurrent()->framebufferobject.drawFB)
733 {
734 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
735 }
736 if (!crStateGetCurrent()->framebufferobject.readFB)
737 {
738 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
739 }
740
741 crStateGetCurrent()->buffer.width = mural->width;
742 crStateGetCurrent()->buffer.height = mural->height;
743 }
744 }
745
746 crServerEnableMuralRpw(mural, !!(redir & CR_SERVER_REDIR_F_FBO_RPW));
747
748 crServerEnableDisplayMuralFBO(mural, !!(redir & CR_SERVER_REDIR_F_DISPLAY));
749
750 mural->fPresentMode = redir;
751
752end:
753 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
754}
755
756static void crServerCreateMuralFBO(CRMuralInfo *mural)
757{
758 CRContext *ctx = crStateGetCurrent();
759 GLuint uid, i;
760 GLenum status;
761 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
762 CRContextInfo *pMuralContextInfo;
763
764 CRASSERT(mural->aidFBOs[0]==0);
765 CRASSERT(mural->aidFBOs[1]==0);
766 CRASSERT(mural->fUseDefaultDEntry);
767 CRASSERT(mural->width == mural->DefaultDEntry.CEntry.Tex.width);
768 CRASSERT(mural->height == mural->DefaultDEntry.CEntry.Tex.height);
769
770 pMuralContextInfo = cr_server.currentCtxInfo;
771 if (!pMuralContextInfo)
772 {
773 /* happens on saved state load */
774 CRASSERT(cr_server.MainContextInfo.SpuContext);
775 pMuralContextInfo = &cr_server.MainContextInfo;
776 cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
777 }
778
779 if (pMuralContextInfo->CreateInfo.visualBits != mural->CreateInfo.visualBits)
780 {
781 crWarning("mural visual bits do not match with current context visual bits!");
782 }
783
784 mural->cBuffers = 2;
785 mural->iBbBuffer = 0;
786 /*Color texture*/
787
788 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
789 {
790 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
791 }
792
793 for (i = 0; i < mural->cBuffers; ++i)
794 {
795 gl->GenTextures(1, &mural->aidColorTexs[i]);
796 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
797 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
798 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
799 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
800 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
801 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
802 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
803 }
804
805 /*Depth&Stencil*/
806 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
807 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
808 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
809 mural->width, mural->height);
810
811 /*FBO*/
812 for (i = 0; i < mural->cBuffers; ++i)
813 {
814 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
815 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
816
817 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
818 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
819 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
820 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
821 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
822 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
823
824 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
825 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
826 {
827 crWarning("FBO status(0x%x) isn't complete", status);
828 }
829 }
830
831 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
832 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
833
834 mural->fboWidth = mural->width;
835 mural->fboHeight = mural->height;
836
837 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
838 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
839
840 /*Restore gl state*/
841 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
842 gl->BindTexture(GL_TEXTURE_2D, uid);
843
844 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
845 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
846
847 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
848 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
849
850 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
851 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
852
853 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
854 {
855 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
856 }
857
858 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
859 {
860 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
861 }
862 else
863 {
864 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
865 }
866
867 CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
868
869 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
870
871// if (mural->fRootVrOn)
872// CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
873}
874
875void crServerDeleteMuralFBO(CRMuralInfo *mural)
876{
877 CRASSERT(!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO));
878
879 if (mural->aidFBOs[0]!=0)
880 {
881 GLuint i;
882 for (i = 0; i < mural->cBuffers; ++i)
883 {
884 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
885 mural->aidColorTexs[i] = 0;
886 }
887
888 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
889 mural->idDepthStencilRB = 0;
890
891 for (i = 0; i < mural->cBuffers; ++i)
892 {
893 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
894 mural->aidFBOs[i] = 0;
895 }
896 }
897
898 mural->cBuffers = 0;
899
900 if (crServerRpwEntryIsInitialized(&mural->RpwEntry))
901 crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
902}
903
904#define MIN(a, b) ((a) < (b) ? (a) : (b))
905#define MAX(a, b) ((a) > (b) ? (a) : (b))
906
907static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
908{
909 CRASSERT(a && b && rect);
910
911 rect->x1 = MAX(a->x1, b->x1);
912 rect->x2 = MIN(a->x2, b->x2);
913 rect->y1 = MAX(a->y1, b->y1);
914 rect->y2 = MIN(a->y2, b->y2);
915
916 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
917}
918
919static GLboolean crServerIntersectScreen(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, int sId, CRrecti *rect)
920{
921 rect->x1 = MAX(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x, cr_server.screen[sId].x);
922 rect->x2 = MIN(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x
923 + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
924 cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
925 rect->y1 = MAX(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y, cr_server.screen[sId].y);
926 rect->y2 = MIN(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y
927 + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
928 cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
929
930 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
931}
932
933static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
934{
935 int i;
936 int dstrowsize = 4*(pRect->x2-pRect->x1);
937 int srcrowsize = 4*srcWidth;
938 int height = pRect->y2-pRect->y1;
939
940 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
941
942 for (i=0; i<height; ++i)
943 {
944 crMemcpy(pDst, pSrc, dstrowsize);
945
946 pSrc -= srcrowsize;
947 pDst += dstrowsize;
948 }
949}
950
951static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
952{
953 pDst->x1 = pSrc->x1+dx;
954 pDst->x2 = pSrc->x2+dx;
955 pDst->y1 = pSrc->y1+dy;
956 pDst->y2 = pSrc->y2+dy;
957}
958
959static void crServerVBoxCompositionPresentPerform(CRMuralInfo *mural)
960{
961 CRMuralInfo *currentMural = cr_server.currentMural;
962 CRContextInfo *curCtxInfo = cr_server.currentCtxInfo;
963 GLuint idDrawFBO, idReadFBO;
964 CRContext *curCtx = curCtxInfo ? curCtxInfo->pContext : NULL;
965
966 CRASSERT(curCtx == crStateGetCurrent());
967
968 Assert((mural->fPresentMode & CR_SERVER_REDIR_F_FBO) || !mural->fUseDefaultDEntry);
969 Assert(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
970
971 mural->fDataPresented = GL_TRUE;
972
973 if (currentMural)
974 {
975 idDrawFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurDrawBuffer);
976 idReadFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurReadBuffer);
977 }
978 else
979 {
980 idDrawFBO = 0;
981 idReadFBO = 0;
982 }
983
984 crStateSwitchPrepare(NULL, curCtx, idDrawFBO, idReadFBO);
985
986 if (!mural->fRootVrOn)
987 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, NULL);
988 else
989 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->RootVrCompositor, NULL);
990
991 crStateSwitchPostprocess(curCtx, NULL, idDrawFBO, idReadFBO);
992}
993
994void crServerVBoxCompositionPresent(CRMuralInfo *mural)
995{
996 if (!crServerVBoxCompositionPresentNeeded(mural))
997 return;
998 crServerVBoxCompositionPresentPerform(mural);
999}
1000
1001static void crServerVBoxCompositionReenable(CRMuralInfo *mural)
1002{
1003 GLboolean fForcePresent = mural->fForcePresentState;
1004 GLboolean fOrPresentOnReenable = mural->fOrPresentOnReenable;
1005
1006 mural->fForcePresentState = GL_FALSE;
1007 mural->fOrPresentOnReenable = GL_FALSE;
1008
1009 if ((mural->fUseDefaultDEntry && !(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
1010 || !mural->fDataPresented
1011 || (!fForcePresent
1012 && !crServerVBoxCompositionPresentNeeded(mural)))
1013 return;
1014
1015 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
1016 crServerVBoxCompositionPresentPerform(mural);
1017
1018 if (fOrPresentOnReenable
1019 && cr_server.bUseOutputRedirect
1020 && crServerVBoxCompositionPresentNeeded(mural))
1021 crServerPresentOutputRedirect(mural);
1022}
1023
1024static void crServerVBoxCompositionDisable(CRMuralInfo *mural)
1025{
1026 if ((mural->fPresentMode & (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)) != (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)
1027 || !mural->fDataPresented)
1028 return;
1029 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
1030}
1031
1032void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural)
1033{
1034 ++cr_server.cDisableEvents;
1035 Assert(cr_server.cDisableEvents);
1036
1037 ++mural->cDisabled;
1038 Assert(mural->cDisabled);
1039 if (mural->cDisabled == 1)
1040 {
1041 crServerVBoxCompositionDisable(mural);
1042 }
1043}
1044
1045void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled)
1046{
1047 mural->fForcePresentState |= fForcePresentOnEnabled;
1048 --mural->cDisabled;
1049 Assert(mural->cDisabled < UINT32_MAX/2);
1050 if (!mural->cDisabled)
1051 {
1052 crServerVBoxCompositionReenable(mural);
1053 }
1054
1055 --cr_server.cDisableEvents;
1056 Assert(cr_server.cDisableEvents < UINT32_MAX/2);
1057 crVBoxServerCheckVisibilityEvent(-1);
1058}
1059
1060static void crServerVBoxCompositionSetEnableStateGlobalCB(unsigned long key, void *data1, void *data2)
1061{
1062 CRMuralInfo *mural = (CRMuralInfo *)data1;
1063
1064 if (data2)
1065 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
1066 else
1067 crServerVBoxCompositionDisableEnter(mural);
1068}
1069
1070DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
1071{
1072 int i;
1073
1074 crHashtableWalk(cr_server.muralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
1075
1076 crHashtableWalk(cr_server.dummyMuralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
1077
1078 for (i = 0; i < cr_server.screenCount; ++i)
1079 {
1080 PCR_DISPLAY pDisplay = crServerDisplayGetInitialized((uint32_t)i);
1081 if (!pDisplay)
1082 continue;
1083
1084 if (!fEnable)
1085 CrDpEnter(pDisplay);
1086 else
1087 CrDpLeave(pDisplay);
1088 }
1089}
1090
1091static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels)
1092{
1093 char *tmppixels;
1094 CRrecti rect, rectwr, sectr;
1095 int i, rc;
1096 uint32_t j;
1097
1098 if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RAM_VMFB)
1099 {
1100 for (i=0; i<cr_server.screenCount; ++i)
1101 {
1102 if (crServerIntersectScreen(mural, pDEntry, i, &rect))
1103 {
1104 uint32_t cRects;
1105 const RTRECT *pRects;
1106
1107 /* rect in window relative coords */
1108 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
1109
1110 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
1111 if (RT_SUCCESS(rc))
1112 {
1113 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
1114 for (j=0; j<cRects; ++j)
1115 {
1116 if (crServerIntersectRect(&rectwr, (CRrecti*)&pRects[j], &sectr))
1117 {
1118 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
1119 if (!tmppixels)
1120 {
1121 crWarning("Out of memory in crServerPresentFBO");
1122 crFree(pixels);
1123 return;
1124 }
1125
1126 crServerCopySubImage(tmppixels, pixels, &sectr, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
1127 /*Note: pfnPresentFBO would free tmppixels*/
1128 cr_server.pfnPresentFBO(tmppixels, i,
1129 sectr.x1+mural->gX+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x-cr_server.screen[i].x,
1130 sectr.y1+mural->gY+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y-cr_server.screen[i].y,
1131 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
1132 }
1133 }
1134 }
1135 else
1136 {
1137 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
1138 }
1139 }
1140 }
1141 }
1142
1143 if (pDEntry->pvORInstance)
1144 {
1145 /* @todo find out why presentfbo is not called but crorframe is called. */
1146 cr_server.outputRedirect.CRORFrame(pDEntry->pvORInstance,
1147 pixels,
1148 4 * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
1149 }
1150}
1151
1152void crServerPresentOutputRedirectEntry(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
1153{
1154 char *pixels=NULL;
1155
1156 if (!pDEntry->pvORInstance)
1157 {
1158 crServerSetupOutputRedirectEntry(pMural, pDEntry);
1159 if (!pDEntry->pvORInstance)
1160 {
1161 crWarning("crServerSetupOutputRedirectEntry failed!");
1162 return;
1163 }
1164 }
1165
1166 if (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW)
1167 {
1168 crError("port me!");
1169#if 0
1170 /* 1. blit to RPW entry draw texture */
1171 CRMuralInfo *pCurrentMural = cr_server.currentMural;
1172 CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
1173 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
1174 CRMuralInfo *pBlitterMural;
1175 CR_SERVER_CTX_SWITCH CtxSwitch;
1176 RTRECT Rect;
1177 VBOXVR_TEXTURE DstTex;
1178 CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
1179 CR_BLITTER_CONTEXT CtxBltInfo;
1180 int rc;
1181
1182 Rect.xLeft = 0;
1183 Rect.yTop = 0;
1184 Rect.xRight = Tex.width;
1185 Rect.yBottom = Tex.height;
1186
1187 if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
1188 {
1189 pBlitterMural = pCurrentMural;
1190 }
1191 else
1192 {
1193 pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
1194 if (!pBlitterMural)
1195 {
1196 crWarning("crServerGetDummyMural failed for blitter mural");
1197 return;
1198 }
1199 }
1200
1201 crServerRpwEntryDrawSettingsToTex(&mural->RpwEntry, &DstTex);
1202
1203 crServerCtxSwitchPrepare(&CtxSwitch, NULL);
1204
1205 crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
1206 crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
1207 crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
1208
1209 CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
1210
1211 rc = CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
1212 if (RT_SUCCESS(rc))
1213 {
1214 CrBltBlitTexTex(pBlitter, &Tex, &Rect, &DstTex, &Rect, 1, 0);
1215 CrBltLeave(pBlitter);
1216 }
1217 else
1218 {
1219 crWarning("CrBltEnter failed rc %d", rc);
1220 }
1221
1222 crServerCtxSwitchPostprocess(&CtxSwitch);
1223
1224#if 1
1225 if (RT_SUCCESS(rc))
1226 {
1227 /* 2. submit RPW entry */
1228 rc = crServerRpwEntrySubmit(&cr_server.RpwWorker, &mural->RpwEntry);
1229 if (!RT_SUCCESS(rc))
1230 {
1231 crWarning("crServerRpwEntrySubmit failed rc %d", rc);
1232 }
1233 }
1234#endif
1235#endif
1236 return;
1237 }
1238
1239 pixels = crServerDEntryImgAcquire(pMural, pDEntry, GL_BGRA);
1240 if (!pixels)
1241 {
1242 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
1243 return;
1244 }
1245
1246 crServerDentryPresentVRAM(pMural, pDEntry, pixels);
1247
1248 crServerDEntryImgRelease(pMural, pDEntry, pixels);
1249}
1250
1251void crServerPresentOutputRedirect(CRMuralInfo *pMural)
1252{
1253 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1254 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1255
1256 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1257
1258 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1259 {
1260 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1261 crServerPresentOutputRedirectEntry(pMural, pDEntry);
1262 }
1263}
1264
1265void crServerOutputRedirectCheckEnableDisable(CRMuralInfo *pMural)
1266{
1267 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1268 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1269
1270 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1271
1272 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1273 {
1274 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1275 crServerSetupOutputRedirectEntry(pMural, pDEntry);
1276 }
1277}
1278
1279void crServerPresentFBO(CRMuralInfo *mural)
1280{
1281 CRASSERT(mural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1282 CRASSERT(cr_server.pfnPresentFBO || (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY));
1283
1284 if (!crServerVBoxCompositionPresentNeeded(mural))
1285 return;
1286
1287 mural->fDataPresented = GL_TRUE;
1288
1289 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
1290 crServerVBoxCompositionPresentPerform(mural);
1291
1292 if (mural->fPresentMode & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
1293 crServerPresentOutputRedirect(mural);
1294}
1295
1296GLboolean crServerIsRedirectedToFBO()
1297{
1298#ifdef DEBUG_misha
1299 Assert(cr_server.curClient);
1300 if (cr_server.curClient)
1301 {
1302 Assert(cr_server.curClient->currentMural == cr_server.currentMural);
1303 Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
1304 }
1305#endif
1306 return cr_server.curClient
1307 && cr_server.curClient->currentMural
1308 && (cr_server.curClient->currentMural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1309}
1310
1311GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
1312{
1313 switch (buffer)
1314 {
1315 case GL_FRONT:
1316 case GL_FRONT_LEFT:
1317 case GL_FRONT_RIGHT:
1318 return CR_SERVER_FBO_FB_IDX(mural);
1319 case GL_BACK:
1320 case GL_BACK_LEFT:
1321 case GL_BACK_RIGHT:
1322 return CR_SERVER_FBO_BB_IDX(mural);
1323 case GL_NONE:
1324 case GL_AUX0:
1325 case GL_AUX1:
1326 case GL_AUX2:
1327 case GL_AUX3:
1328 case GL_LEFT:
1329 case GL_RIGHT:
1330 case GL_FRONT_AND_BACK:
1331 return -1;
1332 default:
1333 crWarning("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer);
1334 return -2;
1335 }
1336}
1337
1338void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
1339{
1340 CRContext *ctx = crStateGetCurrent();
1341 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
1342 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
1343 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
1344 if (mural->iCurDrawBuffer >= 0)
1345 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
1346 if (mural->iCurReadBuffer >= 0)
1347 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
1348 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
1349 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
1350 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
1351 {
1352 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
1353 }
1354 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
1355 {
1356 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
1357 }
1358 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1359 Assert(mural->fUseDefaultDEntry);
1360 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1361 if (mural->fRootVrOn)
1362 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1363}
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