VirtualBox

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

最後變更 在這個檔案從55769是 55761,由 vboxsync 提交於 10 年 前

3D: saving state: use separate buffers for DEPTH and STENCIL data. Needs more testing.

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

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