VirtualBox

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

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

extend PDMIDISPLAYCONNECTOR::pfnVBVAXxx and VBVA resize for better DevVGA/CrCmd integration

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette