VirtualBox

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

Last change on this file since 78375 was 78375, checked in by vboxsync, 6 years ago

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

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