VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp@ 50436

Last change on this file since 50436 was 50394, checked in by vboxsync, 11 years ago

crOpenGL: greyed-out 3D image on VM pause

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/* $Id: server_muralfbo.cpp 50394 2014-02-10 15:33:47Z 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 void crServerRedirMuralFbSync(CRMuralInfo *mural);
26
27void crServerCheckMuralGeometry(CRMuralInfo *mural)
28{
29 if (!mural->CreateInfo.externalID)
30 return;
31
32 CRASSERT(mural->spuWindow);
33 CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
34
35 if (!mural->width || !mural->height
36 || mural->fboWidth != mural->width
37 || mural->fboHeight != mural->height)
38 {
39 crServerRedirMuralFbClear(mural);
40 crServerRedirMuralFBO(mural, false);
41 crServerDeleteMuralFBO(mural);
42 }
43
44 if (!mural->width || !mural->height)
45 return;
46
47 crServerRedirMuralFBO(mural, true);
48 crServerRedirMuralFbSync(mural);
49}
50
51static void crServerCheckMuralGeometryCB(unsigned long key, void *data1, void *data2)
52{
53 CRMuralInfo *pMI = (CRMuralInfo*) data1;
54
55 if (!pMI->fRedirected || pMI == data2)
56 return;
57
58 crServerCheckMuralGeometry(pMI);
59}
60
61
62void crServerCheckAllMuralGeometry(CRMuralInfo *pMI)
63{
64 CR_FBMAP Map;
65 int rc = CrPMgrHlpGlblUpdateBegin(&Map);
66 if (!RT_SUCCESS(rc))
67 {
68 WARN(("CrPMgrHlpGlblUpdateBegin failed %d", rc));
69 return;
70 }
71
72 crHashtableWalk(cr_server.muralTable, crServerCheckMuralGeometryCB, pMI);
73
74 if (pMI)
75 crServerCheckMuralGeometry(pMI);
76
77 CrPMgrHlpGlblUpdateEnd(&Map);
78}
79
80GLboolean crServerSupportRedirMuralFBO(void)
81{
82 static GLboolean fInited = GL_FALSE;
83 static GLboolean fSupported = GL_FALSE;
84 if (!fInited)
85 {
86 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
87
88 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
89 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
90 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
91 fInited = GL_TRUE;
92 }
93 return fSupported;
94}
95
96static void crServerCreateMuralFBO(CRMuralInfo *mural);
97
98void crServerRedirMuralFbClear(CRMuralInfo *mural)
99{
100 uint32_t i;
101 for (i = 0; i < mural->cUsedFBDatas; ++i)
102 {
103 CR_FBDATA *pData = mural->apUsedFBDatas[i];
104 int rc = CrFbUpdateBegin(pData->hFb);
105 if (RT_SUCCESS(rc))
106 {
107 CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
108 CrFbUpdateEnd(pData->hFb);
109 }
110 else
111 WARN(("CrFbUpdateBegin failed rc %d", rc));
112 }
113 mural->cUsedFBDatas = 0;
114
115 for (i = 0; i < cr_server.screenCount; ++i)
116 {
117 GLuint j;
118 CR_FBDATA *pData = &mural->aFBDatas[i];
119 if (!pData->hFb)
120 continue;
121
122 CrFbEntryRelease(pData->hFb, pData->hFbEntry);
123 pData->hFbEntry = NULL;
124
125 for (j = 0; j < mural->cBuffers; ++j)
126 {
127 CrTdRelease(pData->apTexDatas[j]);
128 pData->apTexDatas[j] = NULL;
129 }
130
131 pData->hFb = NULL;
132 }
133}
134
135static int crServerRedirMuralDbSyncFb(CRMuralInfo *mural, HCR_FRAMEBUFFER hFb, CR_FBDATA **ppData)
136{
137 CR_FBDATA *pData;
138 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(hFb);
139 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
140 RTRECT FbRect = *CrVrScrCompositorRectGet(pCompositor);
141 RTRECT DefaultRegionsRect;
142 const RTRECT * pRegions;
143 uint32_t cRegions;
144 RTPOINT Pos;
145 RTRECT MuralRect;
146 int rc;
147
148 CRASSERT(mural->fRedirected);
149
150 *ppData = NULL;
151
152 if (!mural->bVisible)
153 return VINF_SUCCESS;
154
155 MuralRect.xLeft = mural->gX;
156 MuralRect.yTop = mural->gY;
157 MuralRect.xRight = MuralRect.xLeft + mural->width;
158 MuralRect.yBottom = MuralRect.yTop + mural->height;
159
160 Pos.x = mural->gX - pScreenInfo->i32OriginX;
161 Pos.y = mural->gY - pScreenInfo->i32OriginY;
162
163 VBoxRectTranslate(&FbRect, pScreenInfo->i32OriginX, pScreenInfo->i32OriginY);
164
165 VBoxRectIntersect(&FbRect, &MuralRect);
166
167 if (VBoxRectIsZero(&FbRect))
168 return VINF_SUCCESS;
169
170 if (mural->bReceivedRects)
171 {
172 pRegions = (const RTRECT*)mural->pVisibleRects;
173 cRegions = mural->cVisibleRects;
174 }
175 else
176 {
177 DefaultRegionsRect.xLeft = 0;
178 DefaultRegionsRect.yTop = 0;
179 DefaultRegionsRect.xRight = mural->width;
180 DefaultRegionsRect.yBottom = mural->height;
181 pRegions = &DefaultRegionsRect;
182 cRegions = 1;
183 }
184
185 if (!cRegions)
186 return VINF_SUCCESS;
187
188 pData = &mural->aFBDatas[pScreenInfo->u32ViewIndex];
189
190 if (!pData->hFb)
191 {
192 pData->hFb = hFb;
193
194 for (uint32_t i = 0; i < mural->cBuffers; ++i)
195 {
196 VBOXVR_TEXTURE Tex;
197 int rc;
198 Tex.width = mural->width;
199 Tex.height = mural->height;
200 Tex.hwid = mural->aidColorTexs[i];
201 Tex.target = GL_TEXTURE_2D;
202
203 pData->apTexDatas[i] = CrFbTexDataCreate(&Tex);
204 }
205
206 rc = CrFbEntryCreateForTexData(hFb, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)], 0, &pData->hFbEntry);
207 if (!RT_SUCCESS(rc))
208 {
209 WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
210 }
211 }
212 else
213 {
214 CRASSERT(pData->hFb == hFb);
215 }
216
217 rc = CrFbUpdateBegin(hFb);
218 if (!RT_SUCCESS(rc))
219 {
220 WARN(("CrFbUpdateBegin failed rc %d", rc));
221 return rc;
222 }
223
224 rc = CrFbEntryRegionsSet(hFb, pData->hFbEntry, &Pos, cRegions, pRegions, true);
225 if (!RT_SUCCESS(rc))
226 {
227 WARN(("CrFbEntryRegionsSet failed rc %d", rc));
228 }
229
230 CrFbUpdateEnd(hFb);
231
232 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry = CrFbEntryGetCompositorEntry(pData->hFbEntry);
233 if (CrVrScrCompositorEntryIsUsed(pCEntry))
234 *ppData = pData;
235
236 return rc;
237}
238
239static void crServerRedirMuralFbSync(CRMuralInfo *mural)
240{
241 uint32_t i;
242 uint32_t cUsedFBs = 0;
243 HCR_FRAMEBUFFER ahUsedFbs[CR_MAX_GUEST_MONITORS];
244 HCR_FRAMEBUFFER hFb;
245
246 for (i = 0; i < mural->cUsedFBDatas; ++i)
247 {
248 CR_FBDATA *pData = mural->apUsedFBDatas[i];
249 int rc = CrFbUpdateBegin(pData->hFb);
250 if (RT_SUCCESS(rc))
251 {
252 ahUsedFbs[cUsedFBs] = pData->hFb;
253 CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
254 ++cUsedFBs;
255 }
256 else
257 WARN(("CrFbUpdateBegin failed rc %d", rc));
258 }
259 mural->cUsedFBDatas = 0;
260
261 if (!mural->width
262 || !mural->height
263 || !mural->bVisible
264 )
265 goto end;
266
267 CRASSERT(mural->fRedirected);
268
269 for (hFb = CrPMgrFbGetFirstEnabled();
270 hFb;
271 hFb = CrPMgrFbGetNextEnabled(hFb))
272 {
273 CR_FBDATA *pData = NULL;
274 int rc = crServerRedirMuralDbSyncFb(mural, hFb, &pData);
275 if (!RT_SUCCESS(rc))
276 {
277 WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
278 continue;
279 }
280
281 if (!pData)
282 continue;
283
284 mural->apUsedFBDatas[mural->cUsedFBDatas] = pData;
285 ++mural->cUsedFBDatas;
286 }
287
288end:
289
290 for (i = 0; i < cUsedFBs; ++i)
291 {
292 CrFbUpdateEnd(ahUsedFbs[i]);
293 }
294}
295
296static void crVBoxServerMuralFbCleanCB(unsigned long key, void *data1, void *data2)
297{
298 CRMuralInfo *pMI = (CRMuralInfo*) data1;
299 HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
300 uint32_t i;
301 for (i = 0; i < pMI->cUsedFBDatas; ++i)
302 {
303 CR_FBDATA *pData = pMI->apUsedFBDatas[i];
304 if (hFb != pData->hFb)
305 continue;
306
307 CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
308 break;
309 }
310}
311
312static void crVBoxServerMuralFbSetCB(unsigned long key, void *data1, void *data2)
313{
314 CRMuralInfo *pMI = (CRMuralInfo*) data1;
315 HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
316 uint32_t i;
317 CR_FBDATA *pData = NULL;
318 bool fFbWasUsed = false;
319
320 Assert(hFb);
321
322 if (!pMI->fRedirected)
323 {
324 Assert(!pMI->cUsedFBDatas);
325 return;
326 }
327
328 for (i = 0; i < pMI->cUsedFBDatas; ++i)
329 {
330 CR_FBDATA *pData = pMI->apUsedFBDatas[i];
331 if (hFb != pData->hFb)
332 continue;
333
334 fFbWasUsed = true;
335 break;
336 }
337
338 if (CrFbIsEnabled(hFb))
339 {
340 int rc = crServerRedirMuralDbSyncFb(pMI, hFb, &pData);
341 if (!RT_SUCCESS(rc))
342 {
343 WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
344 pData = NULL;
345 }
346 }
347
348 if (pData)
349 {
350 if (!fFbWasUsed)
351 {
352 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
353 for (i = 0; i < pMI->cUsedFBDatas; ++i)
354 {
355 CR_FBDATA *pData = pMI->apUsedFBDatas[i];
356 uint32_t idCurScreen = CrFbGetScreenInfo(pData->hFb)->u32ViewIndex;
357 if (idCurScreen > idScreen)
358 break;
359
360 Assert(idCurScreen != idScreen);
361 }
362
363 for (int j = pMI->cUsedFBDatas; j > i; --j)
364 {
365 pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j-1];
366 }
367
368 pMI->apUsedFBDatas[i] = pData;
369 ++pMI->cUsedFBDatas;
370 }
371 /* else - nothing to do */
372 }
373 else
374 {
375 if (fFbWasUsed)
376 {
377 for (int j = i; j < pMI->cUsedFBDatas - 1; ++j)
378 {
379 pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j+1];
380 }
381 --pMI->cUsedFBDatas;
382 }
383 /* else - nothing to do */
384 }
385}
386
387void crVBoxServerMuralFbResizeEnd(HCR_FRAMEBUFFER hFb)
388{
389 crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbSetCB, hFb);
390}
391
392void crVBoxServerMuralFbResizeBegin(HCR_FRAMEBUFFER hFb)
393{
394 crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbCleanCB, hFb);
395}
396
397
398static int crVBoxServerResizeScreen(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
399{
400 int rc;
401 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
402 if (!hFb)
403 {
404 WARN(("CrPMgrFbGet failed"));
405 return VERR_INVALID_PARAMETER;
406 }
407
408 rc = CrFbUpdateBegin(hFb);
409 if (!RT_SUCCESS(rc))
410 {
411 WARN(("CrFbUpdateBegin failed %d", rc));
412 return rc;
413 }
414
415 crVBoxServerMuralFbResizeBegin(hFb);
416
417 rc = CrFbResize(hFb, pScreen, pvVRAM);
418 if (!RT_SUCCESS(rc))
419 {
420 WARN(("CrFbResize failed %d", rc));
421 }
422
423 crVBoxServerMuralFbResizeEnd(hFb);
424
425 CrFbUpdateEnd(hFb);
426
427 CrPMgrNotifyResize(hFb);
428
429 return rc;
430}
431
432DECLEXPORT(int) crVBoxServerNotifyResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
433{
434 int rc = crVBoxServerResizeScreen(pScreen, pvVRAM);
435 if (!RT_SUCCESS(rc))
436 {
437 WARN(("err"));
438 return rc;
439 }
440
441 return VINF_SUCCESS;
442}
443
444void crServerRedirMuralFBO(CRMuralInfo *mural, bool fEnabled)
445{
446 if (!mural->fRedirected == !fEnabled)
447 {
448 return;
449 }
450
451 if (!mural->CreateInfo.externalID)
452 {
453 WARN(("trying to change redir setting for internal mural %d", mural->spuWindow));
454 return;
455 }
456
457 if (fEnabled)
458 {
459 if (!crServerSupportRedirMuralFBO())
460 {
461 WARN(("FBO not supported, can't redirect window output"));
462 return;
463 }
464
465 if (mural->aidFBOs[0]==0)
466 {
467 crServerCreateMuralFBO(mural);
468 }
469
470 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
471 {
472 if (!crStateGetCurrent()->framebufferobject.drawFB)
473 {
474 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
475 }
476 if (!crStateGetCurrent()->framebufferobject.readFB)
477 {
478 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
479 }
480
481 crStateGetCurrent()->buffer.width = 0;
482 crStateGetCurrent()->buffer.height = 0;
483 }
484 }
485 else
486 {
487 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
488 {
489 if (!crStateGetCurrent()->framebufferobject.drawFB)
490 {
491 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
492 }
493 if (!crStateGetCurrent()->framebufferobject.readFB)
494 {
495 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
496 }
497
498 crStateGetCurrent()->buffer.width = mural->width;
499 crStateGetCurrent()->buffer.height = mural->height;
500 }
501 }
502
503 mural->fRedirected = !!fEnabled;
504}
505
506static void crServerCreateMuralFBO(CRMuralInfo *mural)
507{
508 CRContext *ctx = crStateGetCurrent();
509 GLuint uid, i;
510 GLenum status;
511 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
512 CRContextInfo *pMuralContextInfo;
513
514 CRASSERT(mural->aidFBOs[0]==0);
515 CRASSERT(mural->aidFBOs[1]==0);
516
517 pMuralContextInfo = cr_server.currentCtxInfo;
518 if (!pMuralContextInfo)
519 {
520 /* happens on saved state load */
521 CRASSERT(cr_server.MainContextInfo.SpuContext);
522 pMuralContextInfo = &cr_server.MainContextInfo;
523 cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
524 }
525
526 if (pMuralContextInfo->CreateInfo.realVisualBits != mural->CreateInfo.realVisualBits)
527 {
528 WARN(("mural visual bits do not match with current context visual bits!"));
529 }
530
531 mural->cBuffers = 2;
532 mural->iBbBuffer = 0;
533 /*Color texture*/
534
535 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
536 {
537 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
538 }
539
540 for (i = 0; i < mural->cBuffers; ++i)
541 {
542 gl->GenTextures(1, &mural->aidColorTexs[i]);
543 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
544 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
545 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
546 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
547 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
548 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
549 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
550 }
551
552 /*Depth&Stencil*/
553 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
554 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
555 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
556 mural->width, mural->height);
557
558 /*FBO*/
559 for (i = 0; i < mural->cBuffers; ++i)
560 {
561 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
562 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
563
564 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
565 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
566 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
567 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
568 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
569 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
570
571 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
572 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
573 {
574 WARN(("FBO status(0x%x) isn't complete", status));
575 }
576 }
577
578 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
579 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
580
581 mural->fboWidth = mural->width;
582 mural->fboHeight = mural->height;
583
584 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
585 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
586
587 /*Restore gl state*/
588 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
589 gl->BindTexture(GL_TEXTURE_2D, uid);
590
591 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
592 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
593
594 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
595 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
596
597 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
598 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
599
600 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
601 {
602 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
603 }
604
605 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
606 {
607 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
608 }
609 else
610 {
611 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
612 }
613
614 CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
615}
616
617void crServerDeleteMuralFBO(CRMuralInfo *mural)
618{
619 if (mural->aidFBOs[0]!=0)
620 {
621 GLuint i;
622 for (i = 0; i < mural->cBuffers; ++i)
623 {
624 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
625 mural->aidColorTexs[i] = 0;
626 }
627
628 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
629 mural->idDepthStencilRB = 0;
630
631 for (i = 0; i < mural->cBuffers; ++i)
632 {
633 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
634 mural->aidFBOs[i] = 0;
635 }
636 }
637
638 mural->cBuffers = 0;
639}
640
641#define MIN(a, b) ((a) < (b) ? (a) : (b))
642#define MAX(a, b) ((a) > (b) ? (a) : (b))
643
644static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
645{
646 CRASSERT(a && b && rect);
647
648 rect->x1 = MAX(a->x1, b->x1);
649 rect->x2 = MIN(a->x2, b->x2);
650 rect->y1 = MAX(a->y1, b->y1);
651 rect->y2 = MIN(a->y2, b->y2);
652
653 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
654}
655
656DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
657{
658}
659
660DECLEXPORT(void) crServerVBoxScreenshotRelease(CR_SCREENSHOT *pScreenshot)
661{
662 if (pScreenshot->fDataAllocated)
663 {
664 RTMemFree(pScreenshot->Img.pvData);
665 pScreenshot->fDataAllocated = 0;
666 }
667}
668
669DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, uint32_t height, uint32_t pitch, void *pvBuffer, CR_SCREENSHOT *pScreenshot)
670{
671 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32Screen);
672 if (!hFb)
673 return VERR_INVALID_STATE;
674
675 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
676
677 if (!width)
678 width = pScreen->u32Width;
679 if (!height)
680 height = pScreen->u32Height;
681 if (!pitch)
682 pitch = pScreen->u32LineSize;
683
684 if (CrFbHas3DData(hFb)
685 || pScreen->u32Width != width
686 || pScreen->u32Height != height
687 || pScreen->u32LineSize != pitch
688 || pScreen->u16BitsPerPixel != 32)
689 {
690 RTRECT Rect;
691
692 pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
693 if (!pvBuffer)
694 {
695 pScreenshot->Img.pvData = RTMemAlloc(pScreenshot->Img.cbData);
696 if (!pScreenshot->Img.pvData)
697 {
698 WARN(("RTMemAlloc failed"));
699 return VERR_NO_MEMORY;
700 }
701 pScreenshot->fDataAllocated = 1;
702 }
703 else
704 {
705 pScreenshot->Img.pvData = pvBuffer;
706 pScreenshot->fDataAllocated = 0;
707 }
708
709 pScreenshot->Img.enmFormat = GL_BGRA;
710 pScreenshot->Img.width = width;
711 pScreenshot->Img.height = height;
712 pScreenshot->Img.bpp = 32;
713 pScreenshot->Img.pitch = pitch;
714 Rect.xLeft = 0;
715 Rect.yTop = 0;
716 Rect.xRight = pScreen->u32Width;
717 Rect.yBottom = pScreen->u32Height;
718 int rc = CrFbBltGetContents(hFb, &Rect, 1, &Rect, &pScreenshot->Img);
719 if (!RT_SUCCESS(rc))
720 {
721 WARN(("CrFbBltGetContents failed %d", rc));
722 crServerVBoxScreenshotRelease(pScreenshot);
723 return rc;
724 }
725 }
726 else
727 {
728 pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
729 if (!pvBuffer)
730 pScreenshot->Img.pvData = CrFbGetVRAM(hFb);
731 else
732 {
733 pScreenshot->Img.pvData = pvBuffer;
734 memcpy(pvBuffer, CrFbGetVRAM(hFb), pScreenshot->Img.cbData);
735 }
736 pScreenshot->Img.enmFormat = GL_BGRA;
737 pScreenshot->Img.width = pScreen->u32Width;
738 pScreenshot->Img.height = pScreen->u32Height;
739 pScreenshot->Img.bpp = pScreen->u16BitsPerPixel;
740 pScreenshot->Img.pitch = pScreen->u32LineSize;
741
742 pScreenshot->fDataAllocated = 0;
743 }
744
745 pScreenshot->u32Screen = u32Screen;
746
747 return VINF_SUCCESS;
748}
749
750extern DECLEXPORT(int) crServerVBoxWindowsShow(bool fShow)
751{
752 return CrPMgrModeWinVisible(fShow);
753}
754
755void crServerPresentFBO(CRMuralInfo *mural)
756{
757 uint32_t i;
758 for (i = 0; i < mural->cUsedFBDatas; ++i)
759 {
760 CR_FBDATA *pData = mural->apUsedFBDatas[i];
761 int rc = CrFbUpdateBegin(pData->hFb);
762 if (RT_SUCCESS(rc))
763 {
764 CrFbEntryTexDataUpdate(pData->hFb, pData->hFbEntry, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)]);
765 CrFbUpdateEnd(pData->hFb);
766 }
767 else
768 WARN(("CrFbUpdateBegin failed rc %d", rc));
769 }
770}
771
772GLboolean crServerIsRedirectedToFBO()
773{
774#ifdef DEBUG_misha
775 Assert(cr_server.curClient);
776 if (cr_server.curClient)
777 {
778 Assert(cr_server.curClient->currentMural == cr_server.currentMural);
779 Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
780 }
781#endif
782 return cr_server.curClient
783 && cr_server.curClient->currentMural
784 && cr_server.curClient->currentMural->fRedirected;
785}
786
787GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
788{
789 switch (buffer)
790 {
791 case GL_FRONT:
792 case GL_FRONT_LEFT:
793 case GL_FRONT_RIGHT:
794 return CR_SERVER_FBO_FB_IDX(mural);
795 case GL_BACK:
796 case GL_BACK_LEFT:
797 case GL_BACK_RIGHT:
798 return CR_SERVER_FBO_BB_IDX(mural);
799 case GL_NONE:
800 case GL_AUX0:
801 case GL_AUX1:
802 case GL_AUX2:
803 case GL_AUX3:
804 case GL_LEFT:
805 case GL_RIGHT:
806 case GL_FRONT_AND_BACK:
807 return -1;
808 default:
809 WARN(("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer));
810 return -2;
811 }
812}
813
814void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
815{
816 CRContext *ctx = crStateGetCurrent();
817 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
818 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
819 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
820 if (mural->iCurDrawBuffer >= 0)
821 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
822 if (mural->iCurReadBuffer >= 0)
823 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
824 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
825 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
826 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
827 {
828 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
829 }
830 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
831 {
832 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
833 }
834 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
835}
836
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