VirtualBox

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

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

crOpenGL: more TexPresent fixes & saved state impl

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