VirtualBox

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

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

crOpenGL: root vr for display (disabled so far)

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