VirtualBox

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

Last change on this file since 49448 was 48692, checked in by vboxsync, 11 years ago

crOpenGL: fix composition disable

  • 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 48692 2013-09-25 17:04:19Z 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_DISPLAY)
1027 || (mural->fUseDefaultDEntry && !(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
1028 || !mural->fDataPresented)
1029 return;
1030 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
1031}
1032
1033void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural)
1034{
1035 ++cr_server.cDisableEvents;
1036 Assert(cr_server.cDisableEvents);
1037
1038 ++mural->cDisabled;
1039 Assert(mural->cDisabled);
1040 if (mural->cDisabled == 1)
1041 {
1042 crServerVBoxCompositionDisable(mural);
1043 }
1044}
1045
1046void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled)
1047{
1048 mural->fForcePresentState |= fForcePresentOnEnabled;
1049 --mural->cDisabled;
1050 Assert(mural->cDisabled < UINT32_MAX/2);
1051 if (!mural->cDisabled)
1052 {
1053 crServerVBoxCompositionReenable(mural);
1054 }
1055
1056 --cr_server.cDisableEvents;
1057 Assert(cr_server.cDisableEvents < UINT32_MAX/2);
1058 crVBoxServerCheckVisibilityEvent(-1);
1059}
1060
1061static void crServerVBoxCompositionSetEnableStateGlobalCB(unsigned long key, void *data1, void *data2)
1062{
1063 CRMuralInfo *mural = (CRMuralInfo *)data1;
1064
1065 if (data2)
1066 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
1067 else
1068 crServerVBoxCompositionDisableEnter(mural);
1069}
1070
1071DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
1072{
1073 int i;
1074
1075 crHashtableWalk(cr_server.muralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
1076
1077 crHashtableWalk(cr_server.dummyMuralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
1078
1079 for (i = 0; i < cr_server.screenCount; ++i)
1080 {
1081 PCR_DISPLAY pDisplay = crServerDisplayGetInitialized((uint32_t)i);
1082 if (!pDisplay)
1083 continue;
1084
1085 if (!fEnable)
1086 CrDpEnter(pDisplay);
1087 else
1088 CrDpLeave(pDisplay);
1089 }
1090}
1091
1092static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels)
1093{
1094 char *tmppixels;
1095 CRrecti rect, rectwr, sectr;
1096 int i, rc;
1097 uint32_t j;
1098
1099 if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RAM_VMFB)
1100 {
1101 for (i=0; i<cr_server.screenCount; ++i)
1102 {
1103 if (crServerIntersectScreen(mural, pDEntry, i, &rect))
1104 {
1105 uint32_t cRects;
1106 const RTRECT *pRects;
1107
1108 /* rect in window relative coords */
1109 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
1110
1111 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
1112 if (RT_SUCCESS(rc))
1113 {
1114 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
1115 for (j=0; j<cRects; ++j)
1116 {
1117 if (crServerIntersectRect(&rectwr, (CRrecti*)&pRects[j], &sectr))
1118 {
1119 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
1120 if (!tmppixels)
1121 {
1122 crWarning("Out of memory in crServerPresentFBO");
1123 crFree(pixels);
1124 return;
1125 }
1126
1127 crServerCopySubImage(tmppixels, pixels, &sectr, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
1128 /*Note: pfnPresentFBO would free tmppixels*/
1129 cr_server.pfnPresentFBO(tmppixels, i,
1130 sectr.x1+mural->gX+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x-cr_server.screen[i].x,
1131 sectr.y1+mural->gY+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y-cr_server.screen[i].y,
1132 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
1133 }
1134 }
1135 }
1136 else
1137 {
1138 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
1139 }
1140 }
1141 }
1142 }
1143
1144 if (pDEntry->pvORInstance)
1145 {
1146 /* @todo find out why presentfbo is not called but crorframe is called. */
1147 cr_server.outputRedirect.CRORFrame(pDEntry->pvORInstance,
1148 pixels,
1149 4 * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
1150 }
1151}
1152
1153void crServerPresentOutputRedirectEntry(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
1154{
1155 char *pixels=NULL;
1156
1157 if (!pDEntry->pvORInstance)
1158 {
1159 crServerSetupOutputRedirectEntry(pMural, pDEntry);
1160 if (!pDEntry->pvORInstance)
1161 {
1162 crWarning("crServerSetupOutputRedirectEntry failed!");
1163 return;
1164 }
1165 }
1166
1167 if (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW)
1168 {
1169 crError("port me!");
1170#if 0
1171 /* 1. blit to RPW entry draw texture */
1172 CRMuralInfo *pCurrentMural = cr_server.currentMural;
1173 CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
1174 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
1175 CRMuralInfo *pBlitterMural;
1176 CR_SERVER_CTX_SWITCH CtxSwitch;
1177 RTRECT Rect;
1178 VBOXVR_TEXTURE DstTex;
1179 CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
1180 CR_BLITTER_CONTEXT CtxBltInfo;
1181 int rc;
1182
1183 Rect.xLeft = 0;
1184 Rect.yTop = 0;
1185 Rect.xRight = Tex.width;
1186 Rect.yBottom = Tex.height;
1187
1188 if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
1189 {
1190 pBlitterMural = pCurrentMural;
1191 }
1192 else
1193 {
1194 pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
1195 if (!pBlitterMural)
1196 {
1197 crWarning("crServerGetDummyMural failed for blitter mural");
1198 return;
1199 }
1200 }
1201
1202 crServerRpwEntryDrawSettingsToTex(&mural->RpwEntry, &DstTex);
1203
1204 crServerCtxSwitchPrepare(&CtxSwitch, NULL);
1205
1206 crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
1207 crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
1208 crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
1209
1210 CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
1211
1212 rc = CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
1213 if (RT_SUCCESS(rc))
1214 {
1215 CrBltBlitTexTex(pBlitter, &Tex, &Rect, &DstTex, &Rect, 1, 0);
1216 CrBltLeave(pBlitter);
1217 }
1218 else
1219 {
1220 crWarning("CrBltEnter failed rc %d", rc);
1221 }
1222
1223 crServerCtxSwitchPostprocess(&CtxSwitch);
1224
1225#if 1
1226 if (RT_SUCCESS(rc))
1227 {
1228 /* 2. submit RPW entry */
1229 rc = crServerRpwEntrySubmit(&cr_server.RpwWorker, &mural->RpwEntry);
1230 if (!RT_SUCCESS(rc))
1231 {
1232 crWarning("crServerRpwEntrySubmit failed rc %d", rc);
1233 }
1234 }
1235#endif
1236#endif
1237 return;
1238 }
1239
1240 pixels = crServerDEntryImgAcquire(pMural, pDEntry, GL_BGRA);
1241 if (!pixels)
1242 {
1243 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
1244 return;
1245 }
1246
1247 crServerDentryPresentVRAM(pMural, pDEntry, pixels);
1248
1249 crServerDEntryImgRelease(pMural, pDEntry, pixels);
1250}
1251
1252void crServerPresentOutputRedirect(CRMuralInfo *pMural)
1253{
1254 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1255 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1256
1257 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1258
1259 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1260 {
1261 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1262 crServerPresentOutputRedirectEntry(pMural, pDEntry);
1263 }
1264}
1265
1266void crServerOutputRedirectCheckEnableDisable(CRMuralInfo *pMural)
1267{
1268 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1269 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1270
1271 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1272
1273 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1274 {
1275 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1276 crServerSetupOutputRedirectEntry(pMural, pDEntry);
1277 }
1278}
1279
1280void crServerPresentFBO(CRMuralInfo *mural)
1281{
1282 CRASSERT(mural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1283 CRASSERT(cr_server.pfnPresentFBO || (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY));
1284
1285 if (!crServerVBoxCompositionPresentNeeded(mural))
1286 return;
1287
1288 mural->fDataPresented = GL_TRUE;
1289
1290 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
1291 crServerVBoxCompositionPresentPerform(mural);
1292
1293 if (mural->fPresentMode & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
1294 crServerPresentOutputRedirect(mural);
1295}
1296
1297GLboolean crServerIsRedirectedToFBO()
1298{
1299#ifdef DEBUG_misha
1300 Assert(cr_server.curClient);
1301 if (cr_server.curClient)
1302 {
1303 Assert(cr_server.curClient->currentMural == cr_server.currentMural);
1304 Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
1305 }
1306#endif
1307 return cr_server.curClient
1308 && cr_server.curClient->currentMural
1309 && (cr_server.curClient->currentMural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1310}
1311
1312GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
1313{
1314 switch (buffer)
1315 {
1316 case GL_FRONT:
1317 case GL_FRONT_LEFT:
1318 case GL_FRONT_RIGHT:
1319 return CR_SERVER_FBO_FB_IDX(mural);
1320 case GL_BACK:
1321 case GL_BACK_LEFT:
1322 case GL_BACK_RIGHT:
1323 return CR_SERVER_FBO_BB_IDX(mural);
1324 case GL_NONE:
1325 case GL_AUX0:
1326 case GL_AUX1:
1327 case GL_AUX2:
1328 case GL_AUX3:
1329 case GL_LEFT:
1330 case GL_RIGHT:
1331 case GL_FRONT_AND_BACK:
1332 return -1;
1333 default:
1334 crWarning("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer);
1335 return -2;
1336 }
1337}
1338
1339void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
1340{
1341 CRContext *ctx = crStateGetCurrent();
1342 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
1343 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
1344 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
1345 if (mural->iCurDrawBuffer >= 0)
1346 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
1347 if (mural->iCurReadBuffer >= 0)
1348 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
1349 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
1350 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
1351 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
1352 {
1353 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
1354 }
1355 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
1356 {
1357 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
1358 }
1359 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1360 Assert(mural->fUseDefaultDEntry);
1361 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1362 if (mural->fRootVrOn)
1363 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1364}
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