VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp@ 48726

Last change on this file since 48726 was 48726, checked in by vboxsync, 12 years ago

crOpenGL: seamless fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.5 KB
Line 
1/* $Id: server_presenter.cpp 48726 2013-09-27 10:19:54Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-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#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "server_dispatch.h"
24#include "server.h"
25#include "cr_mem.h"
26#include "cr_string.h"
27#include <cr_vreg.h>
28
29#include <iprt/cdefs.h>
30#include <iprt/types.h>
31#include <iprt/asm.h>
32#include <iprt/mem.h>
33#include <iprt/list.h>
34#include <iprt/memcache.h>
35
36#include "render/renderspu.h"
37
38/* DISPLAY */
39
40int CrDpInit(PCR_DISPLAY pDisplay)
41{
42 const GLint visBits = cr_server.MainContextInfo.CreateInfo.visualBits;
43 if (crServerMuralInit(&pDisplay->Mural, "", visBits, -1, GL_FALSE) < 0)
44 {
45 crWarning("crServerMuralInit failed!");
46 return VERR_GENERAL_FAILURE;
47 }
48
49 crServerWindowVisibleRegion(&pDisplay->Mural);
50 crServerDEntryAllVibleRegions(&pDisplay->Mural);
51
52 crServerMuralShow(&pDisplay->Mural, GL_TRUE);
53
54 pDisplay->fForcePresent = GL_FALSE;
55 return VINF_SUCCESS;
56}
57
58void CrDpTerm(PCR_DISPLAY pDisplay)
59{
60 crServerMuralTerm(&pDisplay->Mural);
61}
62
63void CrDpResize(PCR_DISPLAY pDisplay, int32_t xPos, int32_t yPos, uint32_t width, uint32_t height)
64{
65 if (xPos != pDisplay->Mural.gX
66 || yPos != pDisplay->Mural.gY
67 || width != pDisplay->Mural.width
68 || height != pDisplay->Mural.height)
69 {
70 crServerMuralPosition(&pDisplay->Mural, xPos, yPos, GL_TRUE);
71 if (!crServerMuralSize(&pDisplay->Mural, width, height))
72 crServerCheckMuralGeometry(&pDisplay->Mural);
73 }
74 else
75 crServerCheckMuralGeometry(&pDisplay->Mural);
76}
77
78void CrDpReparent(PCR_DISPLAY pDisplay, CRScreenInfo *pScreen)
79{
80 renderspuSetWindowId(pScreen->winID);
81 crServerWindowReparent(&pDisplay->Mural);
82 renderspuSetWindowId(cr_server.screen[0].winID);
83
84 CrDpResize(pDisplay, pScreen->x, pScreen->y, pScreen->w, pScreen->h);
85}
86
87
88int CrDpSaveState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM)
89{
90 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
91 CrVrScrCompositorIterInit(&pDisplay->Mural.Compositor, &Iter);
92 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
93 uint32_t u32 = 0;
94 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
95 {
96 ++u32;
97 }
98
99 int rc = SSMR3PutU32(pSSM, u32);
100 AssertRCReturn(rc, rc);
101
102 CrVrScrCompositorIterInit(&pDisplay->Mural.Compositor, &Iter);
103
104 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
105 {
106 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
107 rc = CrDemEntrySaveState(pDEntry, pSSM);
108 AssertRCReturn(rc, rc);
109
110 u32 = CrVrScrCompositorEntryFlagsGet(&pDEntry->CEntry);
111 rc = SSMR3PutU32(pSSM, u32);
112 AssertRCReturn(rc, rc);
113
114 rc = SSMR3PutS32(pSSM, CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x);
115 AssertRCReturn(rc, rc);
116
117 rc = SSMR3PutS32(pSSM, CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y);
118 AssertRCReturn(rc, rc);
119
120 const RTRECT * pRects;
121 rc = CrVrScrCompositorEntryRegionsGet(&pDisplay->Mural.Compositor, &pDEntry->CEntry, &u32, NULL, NULL, &pRects);
122 AssertRCReturn(rc, rc);
123
124 rc = SSMR3PutU32(pSSM, u32);
125 AssertRCReturn(rc, rc);
126
127 if (u32)
128 {
129 rc = SSMR3PutMem(pSSM, pRects, u32 * sizeof (*pRects));
130 AssertRCReturn(rc, rc);
131 }
132 }
133
134 return VINF_SUCCESS;
135}
136
137int CrDpLoadState(PCR_DISPLAY pDisplay, PSSMHANDLE pSSM, uint32_t version)
138{
139 uint32_t u32 = 0;
140 int rc = SSMR3GetU32(pSSM, &u32);
141 AssertRCReturn(rc, rc);
142
143 if (!u32)
144 return VINF_SUCCESS;
145
146 CrDpEnter(pDisplay);
147
148 for (uint32_t i = 0; i < u32; ++i)
149 {
150 CR_DISPLAY_ENTRY *pDEntry;
151 rc = CrDemEntryLoadState(&cr_server.PresentTexturepMap, &pDEntry, pSSM);
152 AssertRCReturn(rc, rc);
153
154 uint32_t fFlags;
155 rc = SSMR3GetU32(pSSM, &fFlags);
156 AssertRCReturn(rc, rc);
157
158 CrVrScrCompositorEntryFlagsSet(&pDEntry->CEntry, fFlags);
159
160 RTPOINT Pos;
161 rc = SSMR3GetS32(pSSM, &Pos.x);
162 AssertRCReturn(rc, rc);
163
164 rc = SSMR3GetS32(pSSM, &Pos.y);
165 AssertRCReturn(rc, rc);
166
167 uint32_t cRects;
168 rc = SSMR3GetU32(pSSM, &cRects);
169 AssertRCReturn(rc, rc);
170
171 RTRECT * pRects = NULL;
172 if (cRects)
173 {
174 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
175 AssertReturn(pRects, VERR_NO_MEMORY);
176
177 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
178 AssertRCReturn(rc, rc);
179 }
180
181 rc = CrDpEntryRegionsAdd(pDisplay, pDEntry, &Pos, (uint32_t)cRects, (const RTRECT*)pRects, NULL);
182 AssertRCReturn(rc, rc);
183
184 if (pRects)
185 crFree(pRects);
186 }
187
188 CrDpLeave(pDisplay);
189
190 return VINF_SUCCESS;
191}
192
193
194int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
195{
196 int rc = CrVrScrCompositorEntryRegionsSet(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, NULL);
197 return rc;
198}
199
200void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
201{
202 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
203}
204
205void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
206{
207 crDebug("Dumping rects (%d)", cRects);
208 for (uint32_t i = 0; i < cRects; ++i)
209 {
210 crDbgDumpRect(i, &paRects[i]);
211 }
212 crDebug("End Dumping rects (%d)", cRects);
213}
214
215int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, CR_DISPLAY_ENTRY_MAP *pMap)
216{
217 uint32_t fChangeFlags = 0;
218 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
219
220 if (pMap)
221 CrDemEnter(pMap);
222
223 int rc = CrVrScrCompositorEntryRegionsAdd(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, &pReplacedScrEntry, &fChangeFlags);
224 if (RT_SUCCESS(rc))
225 {
226 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
227 {
228 uint32_t cRects;
229 const RTRECT *pRects;
230 bool fChanged = true;
231 if (pDisplay->Mural.fRootVrOn)
232 {
233 int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
234 if (!RT_SUCCESS(rc))
235 {
236 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
237 fChanged = false;
238 }
239 }
240
241 if (fChanged)
242 crServerWindowVisibleRegion(&pDisplay->Mural);
243
244 crServerDEntryAllVibleRegions(&pDisplay->Mural);
245
246 Assert(!pReplacedScrEntry);
247 }
248 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)
249 {
250 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
251 {
252 Assert(pReplacedScrEntry);
253 Assert(pEntry);
254 if (pDisplay->Mural.fRootVrOn)
255 {
256 CR_DISPLAY_ENTRY *pReplacedDEntry = CR_DENTRY_FROM_CENTRY(pReplacedScrEntry);
257 Assert(CrVrScrCompositorEntryIsUsed(&pReplacedDEntry->RootVrCEntry));
258 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->RootVrCEntry));
259 CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, CrVrScrCompositorEntryTexGet(&pEntry->CEntry), NULL);
260 CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, CrVrScrCompositorEntryFlagsGet(&pEntry->CEntry));
261 CrVrScrCompositorEntryReplace(&pDisplay->Mural.RootVrCompositor, &pReplacedDEntry->RootVrCEntry, &pEntry->RootVrCEntry);
262 }
263 }
264 else
265 {
266 Assert(!pReplacedScrEntry);
267 if (pDisplay->Mural.fRootVrOn)
268 {
269 bool fChanged = false;
270 int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
271 if (RT_SUCCESS(rc))
272 {
273 if (fChanged)
274 crServerWindowVisibleRegion(&pDisplay->Mural);
275 }
276 else
277 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
278 }
279 }
280 }
281 else
282 {
283 Assert(!(fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED));
284 Assert(!pReplacedScrEntry);
285 }
286 }
287 else
288 crWarning("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc);
289
290 if (pMap)
291 CrDemLeave(pMap, CR_DENTRY_FROM_CENTRY(pEntry), CR_DENTRY_FROM_CENTRY(pReplacedScrEntry));
292
293 return rc;
294}
295
296void CrDpRegionsClear(PCR_DISPLAY pDisplay)
297{
298 bool fChanged = false;
299 CrVrScrCompositorRegionsClear(&pDisplay->Mural.Compositor, &fChanged);
300 if (fChanged)
301 {
302 crServerMuralVisibleRegion(&pDisplay->Mural, 0, NULL);
303 }
304}
305
306#define PCR_DISPLAY_ENTRY_FROM_CENTRY(_pe) ((PCR_DISPLAY_ENTRY)((uint8_t*)(_pe) - RT_OFFSETOF(CR_DISPLAY_ENTRY, CEntry)))
307static DECLCALLBACK(void) crDpEntryCEntryReleaseCB(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
308{
309 PCR_DISPLAY_ENTRY pCEntry = PCR_DISPLAY_ENTRY_FROM_CENTRY(pEntry);
310 CrDemEntryRelease(pCEntry);
311}
312
313void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
314{
315 CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, pfnEntryReleased);
316 CrVrScrCompositorEntryFlagsSet(&pEntry->CEntry, fFlags);
317 CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, pTextureData, NULL);
318 CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, fFlags);
319 pEntry->pvORInstance = NULL;
320 pEntry->idPBO = 0;
321 pEntry->idInvertTex = 0;
322}
323
324void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pDEntry)
325{
326 if (pDEntry->idPBO)
327 {
328 CRASSERT(cr_server.bUsePBOForReadback);
329 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
330 pDEntry->idPBO = 0;
331 }
332
333 if (pDEntry->idInvertTex)
334 {
335 cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
336 pDEntry->idInvertTex = 0;
337 }
338
339 if (pDEntry->pvORInstance)
340 {
341 cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
342 pDEntry->pvORInstance = NULL;
343 }
344}
345
346void CrDpEnter(PCR_DISPLAY pDisplay)
347{
348 pDisplay->fForcePresent |= crServerVBoxCompositionPresentNeeded(&pDisplay->Mural);
349 crServerVBoxCompositionDisableEnter(&pDisplay->Mural);
350}
351
352void CrDpLeave(PCR_DISPLAY pDisplay)
353{
354 pDisplay->Mural.fDataPresented = GL_TRUE;
355 pDisplay->Mural.fOrPresentOnReenable = GL_TRUE;
356 crServerVBoxCompositionDisableLeave(&pDisplay->Mural, pDisplay->fForcePresent);
357 pDisplay->fForcePresent = GL_FALSE;
358}
359
360void CrDpRootUpdate(PCR_DISPLAY pDisplay)
361{
362 crVBoxServerUpdateMuralRootVisibleRegion(&pDisplay->Mural);
363}
364
365
366typedef struct CR_DEM_ENTRY_INFO
367{
368 CRTextureObj *pTobj;
369 uint32_t cEntries;
370} CR_DEM_ENTRY_INFO;
371
372typedef struct CR_DEM_ENTRY
373{
374 CR_DISPLAY_ENTRY Entry;
375 CR_DEM_ENTRY_INFO *pInfo;
376 CR_DISPLAY_ENTRY_MAP *pMap;
377 RTLISTNODE Node;
378} CR_DEM_ENTRY;
379
380#define PCR_DEM_ENTRY_FROM_ENTRY(_pEntry) ((CR_DEM_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_DEM_ENTRY, Entry)))
381
382static RTMEMCACHE g_VBoxCrDemLookasideList;
383static RTMEMCACHE g_VBoxCrDemInfoLookasideList;
384
385int CrDemGlobalInit()
386{
387 int rc = RTMemCacheCreate(&g_VBoxCrDemLookasideList, sizeof (CR_DEM_ENTRY),
388 0, /* size_t cbAlignment */
389 UINT32_MAX, /* uint32_t cMaxObjects */
390 NULL, /* PFNMEMCACHECTOR pfnCtor*/
391 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
392 NULL, /* void *pvUser*/
393 0 /* uint32_t fFlags*/
394 );
395 if (RT_SUCCESS(rc))
396 {
397 rc = RTMemCacheCreate(&g_VBoxCrDemInfoLookasideList, sizeof (CR_DEM_ENTRY_INFO),
398 0, /* size_t cbAlignment */
399 UINT32_MAX, /* uint32_t cMaxObjects */
400 NULL, /* PFNMEMCACHECTOR pfnCtor*/
401 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
402 NULL, /* void *pvUser*/
403 0 /* uint32_t fFlags*/
404 );
405 if (RT_SUCCESS(rc))
406 return VINF_SUCCESS;
407 else
408 crWarning("RTMemCacheCreate failed rc %d", rc);
409
410 RTMemCacheDestroy(g_VBoxCrDemLookasideList);
411 }
412 else
413 crWarning("RTMemCacheCreate failed rc %d", rc);
414 return VINF_SUCCESS;
415}
416
417void CrDemTeGlobalTerm()
418{
419 RTMemCacheDestroy(g_VBoxCrDemLookasideList);
420 RTMemCacheDestroy(g_VBoxCrDemInfoLookasideList);
421}
422
423static CR_DEM_ENTRY* crDemEntryAlloc()
424{
425 return (CR_DEM_ENTRY*)RTMemCacheAlloc(g_VBoxCrDemLookasideList);
426}
427
428static CR_DEM_ENTRY_INFO* crDemEntryInfoAlloc()
429{
430 return (CR_DEM_ENTRY_INFO*)RTMemCacheAlloc(g_VBoxCrDemInfoLookasideList);
431}
432
433static void crDemEntryFree(CR_DEM_ENTRY* pDemEntry)
434{
435 CrDpEntryCleanup(&pDemEntry->Entry);
436 RTMemCacheFree(g_VBoxCrDemLookasideList, pDemEntry);
437}
438
439static void crDemEntryInfoFree(CR_DEM_ENTRY_INFO* pDemEntryInfo)
440{
441 RTMemCacheFree(g_VBoxCrDemInfoLookasideList, pDemEntryInfo);
442}
443
444void crDemEntryRelease(PCR_DISPLAY_ENTRY_MAP pMap, CR_DEM_ENTRY *pDemEntry)
445{
446 CR_DEM_ENTRY_INFO *pInfo = pDemEntry->pInfo;
447 CRTextureObj *pTobj = pInfo->pTobj;
448
449 --pInfo->cEntries;
450
451 if (!pInfo->cEntries)
452 {
453 CR_STATE_SHAREDOBJ_USAGE_CLEAR(pInfo->pTobj, cr_server.MainContextInfo.pContext);
454
455 crHashtableDelete(pMap->pTexIdToDemInfoMap, pTobj->id, NULL);
456
457 crDemEntryInfoFree(pInfo);
458 }
459
460 if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
461 {
462 CRSharedState *pShared = crStateGlobalSharedAcquire();
463
464 CRASSERT(pShared);
465 /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
466 * in addition to calling crStateDeleteTextureObject to delete a state object */
467 crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
468
469 crStateGlobalSharedRelease();
470 }
471
472 crStateGlobalSharedRelease();
473
474 if (!pMap->cEntered)
475 crDemEntryFree(pDemEntry);
476 else
477 RTListNodeInsertAfter(&pMap->ReleasedList, &pDemEntry->Node);
478}
479
480int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap)
481{
482 pMap->pTexIdToDemInfoMap = crAllocHashtable();
483 if (pMap->pTexIdToDemInfoMap)
484 {
485 RTListInit(&pMap->ReleasedList);
486 return VINF_SUCCESS;
487 }
488
489 crWarning("crAllocHashtable failed");
490 return VERR_NO_MEMORY;
491}
492
493void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap)
494{
495 CRASSERT(RTListIsEmpty(&pMap->ReleasedList));
496 CRASSERT(!pMap->cEntered);
497 crFreeHashtable(pMap->pTexIdToDemInfoMap, NULL);
498 pMap->pTexIdToDemInfoMap = NULL;
499}
500
501void CrDemEnter(PCR_DISPLAY_ENTRY_MAP pMap)
502{
503 ++pMap->cEntered;
504 Assert(pMap->cEntered);
505}
506
507void CrDemLeave(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY pNewEntry, PCR_DISPLAY_ENTRY pReplacedEntry)
508{
509 Assert(pMap->cEntered);
510 --pMap->cEntered;
511 Assert(!pReplacedEntry || pNewEntry);
512 if (pNewEntry && pReplacedEntry)
513 {
514 CR_DEM_ENTRY *pNewDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pNewEntry);
515 CR_DEM_ENTRY *pReplacedDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pReplacedEntry);
516 Assert(!RTListIsEmpty(&pMap->ReleasedList));
517 Assert(!RTListIsEmpty(&pReplacedDemEntry->Node));
518 Assert(RTListIsEmpty(&pNewDemEntry->Node));
519 Assert(!pNewDemEntry->Entry.pvORInstance);
520 if (!pNewDemEntry->Entry.pvORInstance)
521 {
522 pNewDemEntry->Entry.pvORInstance = pReplacedDemEntry->Entry.pvORInstance;
523 pReplacedDemEntry->Entry.pvORInstance = NULL;
524 }
525 RTListNodeRemove(&pReplacedDemEntry->Node);
526 crDemEntryFree(pReplacedDemEntry);
527 }
528
529 if (!pMap->cEntered)
530 {
531 CR_DEM_ENTRY *pCurEntry, *pNextEntry;
532 RTListForEachSafe(&pMap->ReleasedList, pCurEntry, pNextEntry, CR_DEM_ENTRY, Node)
533 {
534 RTListNodeRemove(&pCurEntry->Node);
535 crDemEntryFree(pCurEntry);
536 }
537 }
538}
539
540void CrDemEntryRelease(PCR_DISPLAY_ENTRY pEntry)
541{
542 CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
543 crDemEntryRelease(pDemEntry->pMap, pDemEntry);
544}
545
546int CrDemEntrySaveState(PCR_DISPLAY_ENTRY pEntry, PSSMHANDLE pSSM)
547{
548 CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
549 int rc = SSMR3PutU32(pSSM, pDemEntry->pInfo->pTobj->id);
550 AssertRCReturn(rc, rc);
551 return rc;
552}
553
554int CrDemEntryLoadState(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY *ppEntry, PSSMHANDLE pSSM)
555{
556 uint32_t u32;
557 int rc = SSMR3GetU32(pSSM, &u32);
558 AssertRCReturn(rc, rc);
559
560 PCR_DISPLAY_ENTRY pEntry = CrDemEntryAcquire(pMap, u32, CRBLT_F_INVERT_SRC_YCOORDS);
561 if (!pEntry)
562 {
563 crWarning("CrDemEntryAcquire failed");
564 return VERR_NO_MEMORY;
565 }
566
567 *ppEntry = pEntry;
568 return VINF_SUCCESS;
569}
570
571PCR_DISPLAY_ENTRY CrDemEntryAcquire(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, uint32_t fFlags)
572{
573 CR_DEM_ENTRY *pDemEntry = NULL;
574
575 CRSharedState *pShared = crStateGlobalSharedAcquire();
576 if (!pShared)
577 {
578 crWarning("pShared is null!");
579 return NULL;
580 }
581
582 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
583 if (!pTobj)
584 {
585 crWarning("pTobj is null!");
586 crStateGlobalSharedRelease();
587 return NULL;
588 }
589
590 Assert(pTobj->id == idTexture);
591
592 GLuint hwId = crStateGetTextureObjHWID(pTobj);
593 if (!hwId)
594 {
595 crWarning("hwId is null!");
596 crStateGlobalSharedRelease();
597 return NULL;
598 }
599
600 VBOXVR_TEXTURE TextureData;
601 TextureData.width = pTobj->level[0]->width;
602 TextureData.height = pTobj->level[0]->height;
603 TextureData.target = pTobj->target;
604 TextureData.hwid = hwId;
605
606 pDemEntry = crDemEntryAlloc();
607 if (!pDemEntry)
608 {
609 crWarning("crDemEntryAlloc failed allocating CR_DEM_ENTRY");
610 crStateGlobalSharedRelease();
611 return NULL;
612 }
613
614 CrDpEntryInit(&pDemEntry->Entry, &TextureData, fFlags, crDpEntryCEntryReleaseCB);
615
616 CR_DEM_ENTRY_INFO *pInfo = (CR_DEM_ENTRY_INFO*)crHashtableSearch(pMap->pTexIdToDemInfoMap, pTobj->id);
617 if (!pInfo)
618 {
619 pInfo = crDemEntryInfoAlloc();
620 CRASSERT(pInfo);
621 crHashtableAdd(pMap->pTexIdToDemInfoMap, pTobj->id, pInfo);
622 pInfo->cEntries = 0;
623 pInfo->pTobj = pTobj;
624 }
625
626 ++pInfo->cEntries;
627 pDemEntry->pInfo = pInfo;
628 pDemEntry->pMap = pMap;
629 RTListInit(&pDemEntry->Node);
630
631 /* just use main context info's context to hold the texture reference */
632 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
633
634 return &pDemEntry->Entry;
635}
636
637PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen)
638{
639 if (idScreen >= CR_MAX_GUEST_MONITORS)
640 {
641 crWarning("invalid idScreen %d", idScreen);
642 return NULL;
643 }
644
645 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
646 {
647 Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
648 return &cr_server.aDispplays[idScreen];
649 }
650 return NULL;
651}
652
653static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen)
654{
655 if (idScreen >= CR_MAX_GUEST_MONITORS)
656 {
657 crWarning("invalid idScreen %d", idScreen);
658 return NULL;
659 }
660
661 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
662 {
663 Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
664 return &cr_server.aDispplays[idScreen];
665 }
666
667 int rc = CrDpInit(&cr_server.aDispplays[idScreen]);
668 if (RT_SUCCESS(rc))
669 {
670 CrDpResize(&cr_server.aDispplays[idScreen],
671 cr_server.screen[idScreen].x, cr_server.screen[idScreen].y,
672 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h);
673 ASMBitSet(cr_server.DisplaysInitMap, idScreen);
674 return &cr_server.aDispplays[idScreen];
675 }
676 else
677 {
678 crWarning("CrDpInit failed for screen %d", idScreen);
679 }
680
681 return NULL;
682}
683
684int crServerDisplaySaveState(PSSMHANDLE pSSM)
685{
686 int rc;
687 int cDisplays = 0, i;
688 for (i = 0; i < cr_server.screenCount; ++i)
689 {
690 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
691 ++cDisplays;
692 }
693
694 rc = SSMR3PutS32(pSSM, cDisplays);
695 AssertRCReturn(rc, rc);
696
697 if (!cDisplays)
698 return VINF_SUCCESS;
699
700 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
701 AssertRCReturn(rc, rc);
702
703 for (i = 0; i < cr_server.screenCount; ++i)
704 {
705 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
706 AssertRCReturn(rc, rc);
707
708 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
709 AssertRCReturn(rc, rc);
710
711 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
712 AssertRCReturn(rc, rc);
713
714 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
715 AssertRCReturn(rc, rc);
716 }
717
718 for (i = 0; i < cr_server.screenCount; ++i)
719 {
720 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
721 {
722 rc = SSMR3PutS32(pSSM, i);
723 AssertRCReturn(rc, rc);
724
725 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
726 AssertRCReturn(rc, rc);
727 }
728 }
729
730 return VINF_SUCCESS;
731}
732
733int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
734{
735 int rc;
736 int cDisplays, screenCount, i;
737
738 rc = SSMR3GetS32(pSSM, &cDisplays);
739 AssertRCReturn(rc, rc);
740
741 if (!cDisplays)
742 return VINF_SUCCESS;
743
744 rc = SSMR3GetS32(pSSM, &screenCount);
745 AssertRCReturn(rc, rc);
746
747 CRASSERT(screenCount == cr_server.screenCount);
748
749 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
750
751 for (i = 0; i < cr_server.screenCount; ++i)
752 {
753 int32_t x, y;
754 uint32_t w, h;
755 rc = SSMR3GetS32(pSSM, &x);
756 AssertRCReturn(rc, rc);
757
758 rc = SSMR3GetS32(pSSM, &y);
759 AssertRCReturn(rc, rc);
760
761 rc = SSMR3GetU32(pSSM, &w);
762 AssertRCReturn(rc, rc);
763
764 rc = SSMR3GetU32(pSSM, &h);
765 AssertRCReturn(rc, rc);
766
767 rc = crVBoxServerMapScreen(i, x, y, w, h, cr_server.screen[i].winID);
768 AssertRCReturn(rc, rc);
769 }
770
771 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
772
773 for (i = 0; i < cDisplays; ++i)
774 {
775 int iScreen;
776
777 rc = SSMR3GetS32(pSSM, &iScreen);
778 AssertRCReturn(rc, rc);
779
780 PCR_DISPLAY pDisplay = crServerDisplayGet((uint32_t)iScreen);
781 if (!pDisplay)
782 {
783 crWarning("crServerDisplayGet failed");
784 return VERR_GENERAL_FAILURE;
785 }
786
787 rc = CrDpLoadState(pDisplay, pSSM, u32Version);
788 AssertRCReturn(rc, rc);
789 }
790
791 return VINF_SUCCESS;
792}
793
794void crServerDisplayTermAll()
795{
796 int i;
797 for (i = 0; i < cr_server.screenCount; ++i)
798 {
799 if (ASMBitTest(cr_server.DisplaysInitMap, i))
800 {
801 CrDpTerm(&cr_server.aDispplays[i]);
802 ASMBitClear(cr_server.DisplaysInitMap, i);
803 }
804 }
805}
806
807void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData)
808{
809 if (idPBO)
810 {
811 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
812 if (pCurCtx)
813 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
814 else
815 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
816 }
817 else
818 {
819 crFree(pvData);
820 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
821 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
822 }
823}
824
825void CrHlpPutTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLenum enmFormat, void *pvData)
826{
827 CRASSERT(pTexture->hwid);
828 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
829
830 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
831 {
832 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
833 }
834
835 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
836 cr_server.head_spu->dispatch_table.TexSubImage2D(GL_TEXTURE_2D, 0 /* level*/, 0 /*xoffset*/, 0 /*yoffset*/, pTexture->width, pTexture->height, enmFormat, GL_UNSIGNED_BYTE, pvData);
837
838 /*restore gl state*/
839 if (pCurCtx)
840 {
841 CRTextureObj *pTObj;
842 CRTextureLevel *pTImg;
843 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
844
845 GLuint uid = pTObj->hwid;
846 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
847 }
848 else
849 {
850 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
851 }
852
853 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
854 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pCurCtx->bufferobject.unpackBuffer->hwid);
855}
856
857void* CrHlpGetTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLuint idPBO, GLenum enmFormat)
858{
859 void *pvData = NULL;
860 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
861
862 if (idPBO)
863 {
864 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, idPBO);
865 }
866 else
867 {
868 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
869 {
870 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
871 }
872
873 pvData = crAlloc(4*pTexture->width*pTexture->height);
874 if (!pvData)
875 {
876 crWarning("Out of memory in CrHlpGetTexImage");
877 return NULL;
878 }
879 }
880
881 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
882 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
883
884 /*restore gl state*/
885 if (pCurCtx)
886 {
887 CRTextureObj *pTObj;
888 CRTextureLevel *pTImg;
889 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
890
891 GLuint uid = pTObj->hwid;
892 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
893 }
894 else
895 {
896 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
897 }
898
899 if (idPBO)
900 {
901 pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
902 if (!pvData)
903 {
904 crWarning("Failed to MapBuffer in CrHlpGetTexImage");
905 return NULL;
906 }
907 }
908
909 CRASSERT(pvData);
910 return pvData;
911}
912
913void SERVER_DISPATCH_APIENTRY
914crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
915{
916 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
917 if (idScreen >= CR_MAX_GUEST_MONITORS)
918 {
919 crWarning("Invalid guest screen");
920 return;
921 }
922
923 PCR_DISPLAY pDisplay;
924 PCR_DISPLAY_ENTRY pEntry = NULL;
925
926 if (texture)
927 {
928 pEntry = CrDemEntryAcquire(&cr_server.PresentTexturepMap, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS);
929 if (!pEntry)
930 {
931 crWarning("CrDemEntryAcquire Failed");
932 return;
933 }
934
935 pDisplay = crServerDisplayGet(idScreen);
936 if (!pDisplay)
937 {
938 crWarning("crServerDisplayGet Failed");
939 return;
940 }
941 }
942 else
943 {
944 pDisplay = crServerDisplayGetInitialized(idScreen);
945 if (!pDisplay)
946 {
947 /* no display initialized, and nothing to present */
948 return;
949 }
950 }
951
952 CrDpEnter(pDisplay);
953
954 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
955 {
956 RTPOINT Point = {xPos, yPos};
957 int rc = CrDpEntryRegionsAdd(pDisplay, pEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, &cr_server.PresentTexturepMap);
958 if (!RT_SUCCESS(rc))
959 {
960 crWarning("CrDpEntryRegionsAdd Failed rc %d", rc);
961// if (pEntry)
962// CrDemEntryRelease(pEntry);
963 return;
964 }
965 }
966 else
967 {
968 CrDpRegionsClear(pDisplay);
969 }
970
971 CrDpLeave(pDisplay);
972}
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