VirtualBox

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

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

crOpenGL: some cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.4 KB
Line 
1/* $Id: server_presenter.cpp 48733 2013-09-27 13:07:23Z 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.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#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 bool fChanged = true;
229 if (pDisplay->Mural.fRootVrOn)
230 {
231 int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
232 if (!RT_SUCCESS(rc))
233 {
234 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
235 fChanged = false;
236 }
237 }
238
239 if (fChanged)
240 crServerWindowVisibleRegion(&pDisplay->Mural);
241
242 crServerDEntryAllVibleRegions(&pDisplay->Mural);
243
244 Assert(!pReplacedScrEntry);
245 }
246 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)
247 {
248 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
249 {
250 Assert(pReplacedScrEntry);
251 Assert(pEntry);
252 if (pDisplay->Mural.fRootVrOn)
253 {
254 CR_DISPLAY_ENTRY *pReplacedDEntry = CR_DENTRY_FROM_CENTRY(pReplacedScrEntry);
255 Assert(CrVrScrCompositorEntryIsUsed(&pReplacedDEntry->RootVrCEntry));
256 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->RootVrCEntry));
257 CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, CrVrScrCompositorEntryTexGet(&pEntry->CEntry), NULL);
258 CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, CrVrScrCompositorEntryFlagsGet(&pEntry->CEntry));
259 CrVrScrCompositorEntryReplace(&pDisplay->Mural.RootVrCompositor, &pReplacedDEntry->RootVrCEntry, &pEntry->RootVrCEntry);
260 }
261 }
262 else
263 {
264 Assert(!pReplacedScrEntry);
265 if (pDisplay->Mural.fRootVrOn)
266 {
267 bool fChanged = false;
268 int rc = crServerMuralSynchRootVr(&pDisplay->Mural, &fChanged);
269 if (RT_SUCCESS(rc))
270 {
271 if (fChanged)
272 crServerWindowVisibleRegion(&pDisplay->Mural);
273 }
274 else
275 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
276 }
277 }
278 }
279 else
280 {
281 Assert(!(fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED));
282 Assert(!pReplacedScrEntry);
283 }
284 }
285 else
286 crWarning("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc);
287
288 if (pMap)
289 CrDemLeave(pMap, CR_DENTRY_FROM_CENTRY(pEntry), CR_DENTRY_FROM_CENTRY(pReplacedScrEntry));
290
291 return rc;
292}
293
294void CrDpRegionsClear(PCR_DISPLAY pDisplay)
295{
296 bool fChanged = false;
297 CrVrScrCompositorRegionsClear(&pDisplay->Mural.Compositor, &fChanged);
298 if (fChanged)
299 {
300 crServerMuralVisibleRegion(&pDisplay->Mural, 0, NULL);
301 }
302}
303
304#define PCR_DISPLAY_ENTRY_FROM_CENTRY(_pe) ((PCR_DISPLAY_ENTRY)((uint8_t*)(_pe) - RT_OFFSETOF(CR_DISPLAY_ENTRY, CEntry)))
305static DECLCALLBACK(void) crDpEntryCEntryReleaseCB(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
306{
307 PCR_DISPLAY_ENTRY pCEntry = PCR_DISPLAY_ENTRY_FROM_CENTRY(pEntry);
308 CrDemEntryRelease(pCEntry);
309}
310
311void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
312{
313 CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, pfnEntryReleased);
314 CrVrScrCompositorEntryFlagsSet(&pEntry->CEntry, fFlags);
315 CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, pTextureData, NULL);
316 CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, fFlags);
317 pEntry->pvORInstance = NULL;
318 pEntry->idPBO = 0;
319 pEntry->idInvertTex = 0;
320}
321
322void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pDEntry)
323{
324 if (pDEntry->idPBO)
325 {
326 CRASSERT(cr_server.bUsePBOForReadback);
327 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
328 pDEntry->idPBO = 0;
329 }
330
331 if (pDEntry->idInvertTex)
332 {
333 cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
334 pDEntry->idInvertTex = 0;
335 }
336
337 if (pDEntry->pvORInstance)
338 {
339 cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
340 pDEntry->pvORInstance = NULL;
341 }
342}
343
344void CrDpEnter(PCR_DISPLAY pDisplay)
345{
346 pDisplay->fForcePresent |= crServerVBoxCompositionPresentNeeded(&pDisplay->Mural);
347 crServerVBoxCompositionDisableEnter(&pDisplay->Mural);
348}
349
350void CrDpLeave(PCR_DISPLAY pDisplay)
351{
352 pDisplay->Mural.fDataPresented = GL_TRUE;
353 pDisplay->Mural.fOrPresentOnReenable = GL_TRUE;
354 crServerVBoxCompositionDisableLeave(&pDisplay->Mural, pDisplay->fForcePresent);
355 pDisplay->fForcePresent = GL_FALSE;
356}
357
358void CrDpRootUpdate(PCR_DISPLAY pDisplay)
359{
360 crVBoxServerUpdateMuralRootVisibleRegion(&pDisplay->Mural);
361}
362
363
364typedef struct CR_DEM_ENTRY_INFO
365{
366 CRTextureObj *pTobj;
367 uint32_t cEntries;
368} CR_DEM_ENTRY_INFO;
369
370typedef struct CR_DEM_ENTRY
371{
372 CR_DISPLAY_ENTRY Entry;
373 CR_DEM_ENTRY_INFO *pInfo;
374 CR_DISPLAY_ENTRY_MAP *pMap;
375 RTLISTNODE Node;
376} CR_DEM_ENTRY;
377
378#define PCR_DEM_ENTRY_FROM_ENTRY(_pEntry) ((CR_DEM_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_DEM_ENTRY, Entry)))
379
380static RTMEMCACHE g_VBoxCrDemLookasideList;
381static RTMEMCACHE g_VBoxCrDemInfoLookasideList;
382
383int CrDemGlobalInit()
384{
385 int rc = RTMemCacheCreate(&g_VBoxCrDemLookasideList, sizeof (CR_DEM_ENTRY),
386 0, /* size_t cbAlignment */
387 UINT32_MAX, /* uint32_t cMaxObjects */
388 NULL, /* PFNMEMCACHECTOR pfnCtor*/
389 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
390 NULL, /* void *pvUser*/
391 0 /* uint32_t fFlags*/
392 );
393 if (RT_SUCCESS(rc))
394 {
395 rc = RTMemCacheCreate(&g_VBoxCrDemInfoLookasideList, sizeof (CR_DEM_ENTRY_INFO),
396 0, /* size_t cbAlignment */
397 UINT32_MAX, /* uint32_t cMaxObjects */
398 NULL, /* PFNMEMCACHECTOR pfnCtor*/
399 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
400 NULL, /* void *pvUser*/
401 0 /* uint32_t fFlags*/
402 );
403 if (RT_SUCCESS(rc))
404 return VINF_SUCCESS;
405 else
406 crWarning("RTMemCacheCreate failed rc %d", rc);
407
408 RTMemCacheDestroy(g_VBoxCrDemLookasideList);
409 }
410 else
411 crWarning("RTMemCacheCreate failed rc %d", rc);
412 return VINF_SUCCESS;
413}
414
415void CrDemTeGlobalTerm()
416{
417 RTMemCacheDestroy(g_VBoxCrDemLookasideList);
418 RTMemCacheDestroy(g_VBoxCrDemInfoLookasideList);
419}
420
421static CR_DEM_ENTRY* crDemEntryAlloc()
422{
423 return (CR_DEM_ENTRY*)RTMemCacheAlloc(g_VBoxCrDemLookasideList);
424}
425
426static CR_DEM_ENTRY_INFO* crDemEntryInfoAlloc()
427{
428 return (CR_DEM_ENTRY_INFO*)RTMemCacheAlloc(g_VBoxCrDemInfoLookasideList);
429}
430
431static void crDemEntryFree(CR_DEM_ENTRY* pDemEntry)
432{
433 CrDpEntryCleanup(&pDemEntry->Entry);
434 RTMemCacheFree(g_VBoxCrDemLookasideList, pDemEntry);
435}
436
437static void crDemEntryInfoFree(CR_DEM_ENTRY_INFO* pDemEntryInfo)
438{
439 RTMemCacheFree(g_VBoxCrDemInfoLookasideList, pDemEntryInfo);
440}
441
442void crDemEntryRelease(PCR_DISPLAY_ENTRY_MAP pMap, CR_DEM_ENTRY *pDemEntry)
443{
444 CR_DEM_ENTRY_INFO *pInfo = pDemEntry->pInfo;
445 CRTextureObj *pTobj = pInfo->pTobj;
446
447 --pInfo->cEntries;
448
449 if (!pInfo->cEntries)
450 {
451 CR_STATE_SHAREDOBJ_USAGE_CLEAR(pInfo->pTobj, cr_server.MainContextInfo.pContext);
452
453 crHashtableDelete(pMap->pTexIdToDemInfoMap, pTobj->id, NULL);
454
455 crDemEntryInfoFree(pInfo);
456 }
457
458 if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
459 {
460 CRSharedState *pShared = crStateGlobalSharedAcquire();
461
462 CRASSERT(pShared);
463 /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
464 * in addition to calling crStateDeleteTextureObject to delete a state object */
465 crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
466
467 crStateGlobalSharedRelease();
468 }
469
470 crStateGlobalSharedRelease();
471
472 if (!pMap->cEntered)
473 crDemEntryFree(pDemEntry);
474 else
475 RTListNodeInsertAfter(&pMap->ReleasedList, &pDemEntry->Node);
476}
477
478int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap)
479{
480 pMap->pTexIdToDemInfoMap = crAllocHashtable();
481 if (pMap->pTexIdToDemInfoMap)
482 {
483 RTListInit(&pMap->ReleasedList);
484 return VINF_SUCCESS;
485 }
486
487 crWarning("crAllocHashtable failed");
488 return VERR_NO_MEMORY;
489}
490
491void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap)
492{
493 CRASSERT(RTListIsEmpty(&pMap->ReleasedList));
494 CRASSERT(!pMap->cEntered);
495 crFreeHashtable(pMap->pTexIdToDemInfoMap, NULL);
496 pMap->pTexIdToDemInfoMap = NULL;
497}
498
499void CrDemEnter(PCR_DISPLAY_ENTRY_MAP pMap)
500{
501 ++pMap->cEntered;
502 Assert(pMap->cEntered);
503}
504
505void CrDemLeave(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY pNewEntry, PCR_DISPLAY_ENTRY pReplacedEntry)
506{
507 Assert(pMap->cEntered);
508 --pMap->cEntered;
509 Assert(!pReplacedEntry || pNewEntry);
510 if (pNewEntry && pReplacedEntry)
511 {
512 CR_DEM_ENTRY *pNewDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pNewEntry);
513 CR_DEM_ENTRY *pReplacedDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pReplacedEntry);
514 Assert(!RTListIsEmpty(&pMap->ReleasedList));
515 Assert(!RTListIsEmpty(&pReplacedDemEntry->Node));
516 Assert(RTListIsEmpty(&pNewDemEntry->Node));
517 Assert(!pNewDemEntry->Entry.pvORInstance);
518 if (!pNewDemEntry->Entry.pvORInstance)
519 {
520 pNewDemEntry->Entry.pvORInstance = pReplacedDemEntry->Entry.pvORInstance;
521 pReplacedDemEntry->Entry.pvORInstance = NULL;
522 }
523 RTListNodeRemove(&pReplacedDemEntry->Node);
524 crDemEntryFree(pReplacedDemEntry);
525 }
526
527 if (!pMap->cEntered)
528 {
529 CR_DEM_ENTRY *pCurEntry, *pNextEntry;
530 RTListForEachSafe(&pMap->ReleasedList, pCurEntry, pNextEntry, CR_DEM_ENTRY, Node)
531 {
532 RTListNodeRemove(&pCurEntry->Node);
533 crDemEntryFree(pCurEntry);
534 }
535 }
536}
537
538void CrDemEntryRelease(PCR_DISPLAY_ENTRY pEntry)
539{
540 CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
541 crDemEntryRelease(pDemEntry->pMap, pDemEntry);
542}
543
544int CrDemEntrySaveState(PCR_DISPLAY_ENTRY pEntry, PSSMHANDLE pSSM)
545{
546 CR_DEM_ENTRY *pDemEntry = PCR_DEM_ENTRY_FROM_ENTRY(pEntry);
547 int rc = SSMR3PutU32(pSSM, pDemEntry->pInfo->pTobj->id);
548 AssertRCReturn(rc, rc);
549 return rc;
550}
551
552int CrDemEntryLoadState(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY *ppEntry, PSSMHANDLE pSSM)
553{
554 uint32_t u32;
555 int rc = SSMR3GetU32(pSSM, &u32);
556 AssertRCReturn(rc, rc);
557
558 PCR_DISPLAY_ENTRY pEntry = CrDemEntryAcquire(pMap, u32, CRBLT_F_INVERT_SRC_YCOORDS);
559 if (!pEntry)
560 {
561 crWarning("CrDemEntryAcquire failed");
562 return VERR_NO_MEMORY;
563 }
564
565 *ppEntry = pEntry;
566 return VINF_SUCCESS;
567}
568
569PCR_DISPLAY_ENTRY CrDemEntryAcquire(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, uint32_t fFlags)
570{
571 CR_DEM_ENTRY *pDemEntry = NULL;
572
573 CRSharedState *pShared = crStateGlobalSharedAcquire();
574 if (!pShared)
575 {
576 crWarning("pShared is null!");
577 return NULL;
578 }
579
580 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
581 if (!pTobj)
582 {
583 crWarning("pTobj is null!");
584 crStateGlobalSharedRelease();
585 return NULL;
586 }
587
588 Assert(pTobj->id == idTexture);
589
590 GLuint hwId = crStateGetTextureObjHWID(pTobj);
591 if (!hwId)
592 {
593 crWarning("hwId is null!");
594 crStateGlobalSharedRelease();
595 return NULL;
596 }
597
598 VBOXVR_TEXTURE TextureData;
599 TextureData.width = pTobj->level[0]->width;
600 TextureData.height = pTobj->level[0]->height;
601 TextureData.target = pTobj->target;
602 TextureData.hwid = hwId;
603
604 pDemEntry = crDemEntryAlloc();
605 if (!pDemEntry)
606 {
607 crWarning("crDemEntryAlloc failed allocating CR_DEM_ENTRY");
608 crStateGlobalSharedRelease();
609 return NULL;
610 }
611
612 CrDpEntryInit(&pDemEntry->Entry, &TextureData, fFlags, crDpEntryCEntryReleaseCB);
613
614 CR_DEM_ENTRY_INFO *pInfo = (CR_DEM_ENTRY_INFO*)crHashtableSearch(pMap->pTexIdToDemInfoMap, pTobj->id);
615 if (!pInfo)
616 {
617 pInfo = crDemEntryInfoAlloc();
618 CRASSERT(pInfo);
619 crHashtableAdd(pMap->pTexIdToDemInfoMap, pTobj->id, pInfo);
620 pInfo->cEntries = 0;
621 pInfo->pTobj = pTobj;
622 }
623
624 ++pInfo->cEntries;
625 pDemEntry->pInfo = pInfo;
626 pDemEntry->pMap = pMap;
627 RTListInit(&pDemEntry->Node);
628
629 /* just use main context info's context to hold the texture reference */
630 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
631
632 return &pDemEntry->Entry;
633}
634
635PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen)
636{
637 if (idScreen >= CR_MAX_GUEST_MONITORS)
638 {
639 crWarning("invalid idScreen %d", idScreen);
640 return NULL;
641 }
642
643 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
644 {
645 Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
646 return &cr_server.aDispplays[idScreen];
647 }
648 return NULL;
649}
650
651static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen)
652{
653 if (idScreen >= CR_MAX_GUEST_MONITORS)
654 {
655 crWarning("invalid idScreen %d", idScreen);
656 return NULL;
657 }
658
659 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
660 {
661 Assert(cr_server.aDispplays[idScreen].Mural.screenId == idScreen);
662 return &cr_server.aDispplays[idScreen];
663 }
664
665 int rc = CrDpInit(&cr_server.aDispplays[idScreen]);
666 if (RT_SUCCESS(rc))
667 {
668 CrDpResize(&cr_server.aDispplays[idScreen],
669 cr_server.screen[idScreen].x, cr_server.screen[idScreen].y,
670 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h);
671 ASMBitSet(cr_server.DisplaysInitMap, idScreen);
672 return &cr_server.aDispplays[idScreen];
673 }
674 else
675 {
676 crWarning("CrDpInit failed for screen %d", idScreen);
677 }
678
679 return NULL;
680}
681
682int crServerDisplaySaveState(PSSMHANDLE pSSM)
683{
684 int rc;
685 int cDisplays = 0, i;
686 for (i = 0; i < cr_server.screenCount; ++i)
687 {
688 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
689 ++cDisplays;
690 }
691
692 rc = SSMR3PutS32(pSSM, cDisplays);
693 AssertRCReturn(rc, rc);
694
695 if (!cDisplays)
696 return VINF_SUCCESS;
697
698 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
699 AssertRCReturn(rc, rc);
700
701 for (i = 0; i < cr_server.screenCount; ++i)
702 {
703 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
704 AssertRCReturn(rc, rc);
705
706 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
707 AssertRCReturn(rc, rc);
708
709 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
710 AssertRCReturn(rc, rc);
711
712 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
713 AssertRCReturn(rc, rc);
714 }
715
716 for (i = 0; i < cr_server.screenCount; ++i)
717 {
718 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
719 {
720 rc = SSMR3PutS32(pSSM, i);
721 AssertRCReturn(rc, rc);
722
723 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
724 AssertRCReturn(rc, rc);
725 }
726 }
727
728 return VINF_SUCCESS;
729}
730
731int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
732{
733 int rc;
734 int cDisplays, screenCount, i;
735
736 rc = SSMR3GetS32(pSSM, &cDisplays);
737 AssertRCReturn(rc, rc);
738
739 if (!cDisplays)
740 return VINF_SUCCESS;
741
742 rc = SSMR3GetS32(pSSM, &screenCount);
743 AssertRCReturn(rc, rc);
744
745 CRASSERT(screenCount == cr_server.screenCount);
746
747 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
748
749 for (i = 0; i < cr_server.screenCount; ++i)
750 {
751 int32_t x, y;
752 uint32_t w, h;
753 rc = SSMR3GetS32(pSSM, &x);
754 AssertRCReturn(rc, rc);
755
756 rc = SSMR3GetS32(pSSM, &y);
757 AssertRCReturn(rc, rc);
758
759 rc = SSMR3GetU32(pSSM, &w);
760 AssertRCReturn(rc, rc);
761
762 rc = SSMR3GetU32(pSSM, &h);
763 AssertRCReturn(rc, rc);
764
765 rc = crVBoxServerMapScreen(i, x, y, w, h, cr_server.screen[i].winID);
766 AssertRCReturn(rc, rc);
767 }
768
769 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
770
771 for (i = 0; i < cDisplays; ++i)
772 {
773 int iScreen;
774
775 rc = SSMR3GetS32(pSSM, &iScreen);
776 AssertRCReturn(rc, rc);
777
778 PCR_DISPLAY pDisplay = crServerDisplayGet((uint32_t)iScreen);
779 if (!pDisplay)
780 {
781 crWarning("crServerDisplayGet failed");
782 return VERR_GENERAL_FAILURE;
783 }
784
785 rc = CrDpLoadState(pDisplay, pSSM, u32Version);
786 AssertRCReturn(rc, rc);
787 }
788
789 return VINF_SUCCESS;
790}
791
792void crServerDisplayTermAll()
793{
794 int i;
795 for (i = 0; i < cr_server.screenCount; ++i)
796 {
797 if (ASMBitTest(cr_server.DisplaysInitMap, i))
798 {
799 CrDpTerm(&cr_server.aDispplays[i]);
800 ASMBitClear(cr_server.DisplaysInitMap, i);
801 }
802 }
803}
804
805void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData)
806{
807 if (idPBO)
808 {
809 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
810 if (pCurCtx)
811 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
812 else
813 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
814 }
815 else
816 {
817 crFree(pvData);
818 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
819 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
820 }
821}
822
823void CrHlpPutTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLenum enmFormat, void *pvData)
824{
825 CRASSERT(pTexture->hwid);
826 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
827
828 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
829 {
830 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
831 }
832
833 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
834 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);
835
836 /*restore gl state*/
837 if (pCurCtx)
838 {
839 CRTextureObj *pTObj;
840 CRTextureLevel *pTImg;
841 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
842
843 GLuint uid = pTObj->hwid;
844 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
845 }
846 else
847 {
848 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
849 }
850
851 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
852 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pCurCtx->bufferobject.unpackBuffer->hwid);
853}
854
855void* CrHlpGetTexImage(CRContext *pCurCtx, const VBOXVR_TEXTURE *pTexture, GLuint idPBO, GLenum enmFormat)
856{
857 void *pvData = NULL;
858 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
859
860 if (idPBO)
861 {
862 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, idPBO);
863 }
864 else
865 {
866 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
867 {
868 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
869 }
870
871 pvData = crAlloc(4*pTexture->width*pTexture->height);
872 if (!pvData)
873 {
874 crWarning("Out of memory in CrHlpGetTexImage");
875 return NULL;
876 }
877 }
878
879 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
880 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
881
882 /*restore gl state*/
883 if (pCurCtx)
884 {
885 CRTextureObj *pTObj;
886 CRTextureLevel *pTImg;
887 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
888
889 GLuint uid = pTObj->hwid;
890 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
891 }
892 else
893 {
894 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
895 }
896
897 if (idPBO)
898 {
899 pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
900 if (!pvData)
901 {
902 crWarning("Failed to MapBuffer in CrHlpGetTexImage");
903 return NULL;
904 }
905 }
906
907 CRASSERT(pvData);
908 return pvData;
909}
910
911void SERVER_DISPATCH_APIENTRY
912crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
913{
914 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
915 if (idScreen >= CR_MAX_GUEST_MONITORS)
916 {
917 crWarning("Invalid guest screen");
918 return;
919 }
920
921 PCR_DISPLAY pDisplay;
922 PCR_DISPLAY_ENTRY pEntry = NULL;
923
924 if (texture)
925 {
926 pEntry = CrDemEntryAcquire(&cr_server.PresentTexturepMap, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS);
927 if (!pEntry)
928 {
929 crWarning("CrDemEntryAcquire Failed");
930 return;
931 }
932
933 pDisplay = crServerDisplayGet(idScreen);
934 if (!pDisplay)
935 {
936 crWarning("crServerDisplayGet Failed");
937 return;
938 }
939 }
940 else
941 {
942 pDisplay = crServerDisplayGetInitialized(idScreen);
943 if (!pDisplay)
944 {
945 /* no display initialized, and nothing to present */
946 return;
947 }
948 }
949
950 CrDpEnter(pDisplay);
951
952 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
953 {
954 RTPOINT Point = {xPos, yPos};
955 int rc = CrDpEntryRegionsAdd(pDisplay, pEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, &cr_server.PresentTexturepMap);
956 if (!RT_SUCCESS(rc))
957 {
958 crWarning("CrDpEntryRegionsAdd Failed rc %d", rc);
959// if (pEntry)
960// CrDemEntryRelease(pEntry);
961 return;
962 }
963 }
964 else
965 {
966 CrDpRegionsClear(pDisplay);
967 }
968
969 CrDpLeave(pDisplay);
970}
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