VirtualBox

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

Last change on this file since 55832 was 55832, checked in by vboxsync, 9 years ago

Host 3D: back to usage of DEPTH_STENCIL attachement.

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