VirtualBox

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

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

crOpenGL: saved state and dummy mural/context fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1/* $Id: server_presenter.cpp 47116 2013-07-12 12:35:16Z 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
34
35/* DISPLAY */
36
37//static DECLCALLBACK(int) crDpCbRegionsChanged(struct CR_PRESENTER *pPresenter)
38//{
39// uint32_t cRegions;
40// const RTRECT *paRegions;
41// int rc = CrPtGetRegions(pPresenter, &cRegions, &paRegions);
42// if (!RT_SUCCESS(rc))
43// {
44// crWarning("CrPtGetRegions failed, rc %d", rc);
45// return rc;
46// }
47//
48// PCR_DISPLAY pDisplay = CR_DISPLAY_FROM_PRESENTER(pPresenter);
49//
50// cr_server.head_spu->dispatch_table.WindowVisibleRegion(pDisplay->Mural.spuWindow, cRegions, (GLint*)paRegions);
51//
52// if (pDisplay->Mural.pvOutputRedirectInstance)
53// {
54// /* @todo the code assumes that RTRECT == four GLInts. */
55// cr_server.outputRedirect.CRORVisibleRegion(pDisplay->Mural.pvOutputRedirectInstance,
56// cRegions, paRegions);
57// }
58//
59// return VINF_SUCCESS;
60//}
61
62int CrDpInit(PCR_DISPLAY pDisplay)
63{
64 const GLint visBits = cr_server.MainContextInfo.CreateInfo.visualBits;
65 if (crServerMuralInit(&pDisplay->Mural, "", visBits, 0, GL_FALSE) < 0)
66 {
67 crWarning("crServerMuralInit failed!");
68 return VERR_GENERAL_FAILURE;
69 }
70 pDisplay->fForcePresent = GL_FALSE;
71 return VINF_SUCCESS;
72}
73
74void CrDpTerm(PCR_DISPLAY pDisplay)
75{
76 crServerMuralTerm(&pDisplay->Mural);
77}
78
79void CrDpResize(PCR_DISPLAY pDisplay, int32_t xPos, int32_t yPos, uint32_t width, uint32_t height)
80{
81 crServerMuralVisibleRegion(&pDisplay->Mural, 0, NULL);
82 crServerMutalPosition(&pDisplay->Mural, xPos, yPos);
83 crServerMuralSize(&pDisplay->Mural, width, height);
84 crServerMuralShow(&pDisplay->Mural, GL_TRUE);
85 CrVrScrCompositorSetStretching(&pDisplay->Mural.Compositor, 1., 1.);
86}
87
88int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
89{
90 int rc = CrVrScrCompositorEntryRegionsSet(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, NULL);
91 return rc;
92}
93
94void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
95{
96 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
97}
98
99void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
100{
101 crDebug("Dumping rects (%d)", cRects);
102 for (uint32_t i = 0; i < cRects; ++i)
103 {
104 crDbgDumpRect(i, &paRects[i]);
105 }
106 crDebug("End Dumping rects (%d)", cRects);
107}
108
109int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
110{
111 uint32_t fChangeFlags = 0;
112 int rc = CrVrScrCompositorEntryRegionsAdd(&pDisplay->Mural.Compositor, pEntry ? &pEntry->CEntry : NULL, pPos, cRegions, paRegions, false, &fChangeFlags);
113 if (RT_SUCCESS(rc))
114 {
115 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
116 {
117 uint32_t cRects;
118 const RTRECT *pRects;
119 rc = CrVrScrCompositorRegionsGet(&pDisplay->Mural.Compositor, &cRects, NULL, &pRects, NULL);
120 if (RT_SUCCESS(rc))
121 crServerMuralVisibleRegion(&pDisplay->Mural, cRects, (GLint *)pRects);
122 else
123 crWarning("CrVrScrCompositorRegionsGet failed, rc %d", rc);
124 }
125 }
126 else
127 crWarning("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc);
128
129 return rc;
130}
131
132void CrDpEntryRegionsClear(PCR_DISPLAY pDisplay)
133{
134 bool fChanged = false;
135 CrVrScrCompositorRegionsClear(&pDisplay->Mural.Compositor, &fChanged);
136 if (fChanged)
137 {
138 crServerMuralVisibleRegion(&pDisplay->Mural, 0, NULL);
139 }
140}
141
142#define PCR_DISPLAY_ENTRY_FROM_CENTRY(_pe) ((PCR_DISPLAY_ENTRY)((uint8_t*)(_pe) - RT_OFFSETOF(CR_DISPLAY_ENTRY, CEntry)))
143static DECLCALLBACK(void) crDpEntryCEntryReleaseCB(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
144{
145 PCR_DISPLAY_ENTRY pCEntry = PCR_DISPLAY_ENTRY_FROM_CENTRY(pEntry);
146 CrDemEntryRelease(pCEntry);
147}
148
149void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, void *pvUserData1, void *pvUserData2)
150{
151 CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, crDpEntryCEntryReleaseCB);
152 CrVrScrCompositorEntryFlagsSet(&pEntry->CEntry, CRBLT_F_INVERT_SRC_YCOORDS);
153 CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, pTextureData, NULL);
154 CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, CRBLT_F_INVERT_SRC_YCOORDS);
155 pEntry->pvUserData1 = pvUserData1;
156 pEntry->pvUserData2 = pvUserData2;
157}
158
159void CrDpEntryCleanup(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry)
160{
161 CrVrScrCompositorEntryRemove(&pDisplay->Mural.Compositor, &pEntry->CEntry);
162}
163
164void CrDpEnter(PCR_DISPLAY pDisplay)
165{
166 pDisplay->fForcePresent = crServerVBoxCompositionPresentNeeded(&pDisplay->Mural);
167 crServerVBoxCompositionDisableEnter(&pDisplay->Mural);
168}
169
170void CrDpLeave(PCR_DISPLAY pDisplay)
171{
172 pDisplay->Mural.fDataPresented = GL_TRUE;
173 crServerVBoxCompositionDisableLeave(&pDisplay->Mural, pDisplay->fForcePresent);
174}
175
176int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap)
177{
178 pMap->pTextureMap = crAllocHashtable();
179 if (pMap->pTextureMap)
180 return VINF_SUCCESS;
181
182 crWarning("crAllocHashtable failed!");
183 return VERR_NO_MEMORY;
184}
185
186void crDemEntryRelease(PCR_DISPLAY_ENTRY_MAP pMap, PCR_DISPLAY_ENTRY pEntry, bool fForceDelete)
187{
188 CRTextureObj *pTobj = (CRTextureObj *)pEntry->pvUserData2;
189 if (!pTobj)
190 {
191 crWarning("Trying to release entry that does not have tobj specified");
192 return;
193 }
194
195 CR_STATE_SHAREDOBJ_USAGE_CLEAR(pTobj, cr_server.MainContextInfo.pContext);
196
197 bool fDeleteEntry = fForceDelete;
198 GLuint idTexture = pTobj->id;
199
200 if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
201 {
202 CRSharedState *pShared = crStateGlobalSharedAcquire();
203
204 CRASSERT(pShared);
205 /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
206 * in addition to calling crStateDeleteTextureObject to delete a state object */
207 crHashtableDelete(pShared->textureTable, idTexture, crStateDeleteTextureCallback);
208
209 crStateGlobalSharedRelease();
210
211 fDeleteEntry = true;
212 }
213 else
214 {
215 /* this is something we would not generally expect */
216 CRASSERT(!fForceDelete);
217 }
218
219 if (fDeleteEntry)
220 {
221 if (pMap)
222 crHashtableDelete(pMap->pTextureMap, idTexture, crFree);
223 else
224 crFree(pEntry); /* <- when called from crDemTermEntryCb */
225
226 crStateGlobalSharedRelease();
227 }
228}
229
230void crDemTermEntryCb(void *pvEntry)
231{
232 crDemEntryRelease(NULL, (PCR_DISPLAY_ENTRY)pvEntry, true);
233}
234
235void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap)
236{
237 crFreeHashtable(pMap->pTextureMap, crDemTermEntryCb);
238}
239
240void CrDemEntryRelease(PCR_DISPLAY_ENTRY pEntry)
241{
242 PCR_DISPLAY_ENTRY_MAP pMap = (PCR_DISPLAY_ENTRY_MAP)pEntry->pvUserData1;
243 Assert(pMap);
244 crDemEntryRelease(pMap, pEntry, false);
245}
246
247PCR_DISPLAY_ENTRY CrDemEntryAcquire(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture)
248{
249 PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
250 if (pEntry)
251 return pEntry;
252
253 CRSharedState *pShared = crStateGlobalSharedAcquire();
254 if (!pShared)
255 {
256 crWarning("pShared is null!");
257 return NULL;
258 }
259
260 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
261 if (!pTobj)
262 {
263 crWarning("pTobj is null!");
264 crStateGlobalSharedRelease();
265 return NULL;
266 }
267
268 Assert(pTobj->id == idTexture);
269
270 GLuint hwId = crStateGetTextureObjHWID(pTobj);
271 if (!hwId)
272 {
273 crWarning("hwId is null!");
274 crStateGlobalSharedRelease();
275 return NULL;
276 }
277
278 VBOXVR_TEXTURE TextureData;
279 TextureData.width = pTobj->level[0]->width;
280 TextureData.height = pTobj->level[0]->height;
281 TextureData.target = pTobj->target;
282 TextureData.hwid = hwId;
283
284 pEntry = (PCR_DISPLAY_ENTRY)crAlloc(sizeof (*pEntry));
285 if (!pEntry)
286 {
287 crWarning("crAlloc failed allocating CR_DISPLAY_ENTRY");
288 crStateGlobalSharedRelease();
289 return NULL;
290 }
291
292 CrDpEntryInit(pEntry, &TextureData, pMap, pTobj);
293
294 /* just use main context info's context to hold the texture reference */
295 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
296
297 crHashtableAdd(pMap->pTextureMap, idTexture, pEntry);
298 return pEntry;
299
300}
301#if 0
302void CrDemEntryDestroy(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture)
303{
304#ifdef DEBUG
305 {
306 PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
307 if (!pEntry)
308 {
309 crWarning("request to delete inexistent entry");
310 return;
311 }
312
313 Assert(!CrDpEntryIsUsed(pEntry));
314 }
315#endif
316 crHashtableDelete(pMap->pTextureMap, idTexture, crFree);
317}
318#endif
319PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen)
320{
321 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
322 return &cr_server.aDispplays[idScreen];
323 return NULL;
324}
325
326static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen)
327{
328 if (idScreen >= CR_MAX_GUEST_MONITORS)
329 {
330 crWarning("invalid idScreen %d", idScreen);
331 return NULL;
332 }
333
334 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
335 return &cr_server.aDispplays[idScreen];
336
337 int rc = CrDpInit(&cr_server.aDispplays[idScreen]);
338 if (RT_SUCCESS(rc))
339 {
340 CrDpResize(&cr_server.aDispplays[idScreen],
341 cr_server.screen[idScreen].x, cr_server.screen[idScreen].y,
342 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h);
343 ASMBitSet(cr_server.DisplaysInitMap, idScreen);
344 return &cr_server.aDispplays[idScreen];
345 }
346 else
347 {
348 crWarning("CrDpInit failed for screen %d", idScreen);
349 }
350
351 return NULL;
352}
353
354void crServerDisplayTermAll()
355{
356 int i;
357 for (i = 0; i < cr_server.screenCount; ++i)
358 {
359 if (ASMBitTest(cr_server.DisplaysInitMap, i))
360 {
361 CrDpTerm(&cr_server.aDispplays[i]);
362 ASMBitClear(cr_server.DisplaysInitMap, i);
363 }
364 }
365}
366
367void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData)
368{
369 if (idPBO)
370 {
371 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
372 if (pCurCtx)
373 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
374 else
375 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
376 }
377 else
378 {
379 crFree(pvData);
380 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
381 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
382 }
383}
384
385void CrHlpPutTexImage(CRContext *pCurCtx, PVBOXVR_TEXTURE pTexture, GLenum enmFormat, void *pvData)
386{
387 CRASSERT(pTexture->hwid);
388 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
389
390 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
391 {
392 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
393 }
394
395 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
396 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);
397
398 /*restore gl state*/
399 if (pCurCtx)
400 {
401 CRTextureObj *pTObj;
402 CRTextureLevel *pTImg;
403 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
404
405 GLuint uid = pTObj->hwid;
406 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
407 }
408 else
409 {
410 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
411 }
412
413 if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_UNPACK_BUFFER_ARB))
414 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pCurCtx->bufferobject.unpackBuffer->hwid);
415}
416
417void* CrHlpGetTexImage(CRContext *pCurCtx, PVBOXVR_TEXTURE pTexture, GLuint idPBO, GLenum enmFormat)
418{
419 void *pvData = NULL;
420 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
421
422 if (idPBO)
423 {
424 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, idPBO);
425 }
426 else
427 {
428 if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
429 {
430 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
431 }
432
433 pvData = crAlloc(4*pTexture->width*pTexture->height);
434 if (!pvData)
435 {
436 crWarning("Out of memory in CrHlpGetTexImage");
437 return NULL;
438 }
439 }
440
441 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
442 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
443
444 /*restore gl state*/
445 if (pCurCtx)
446 {
447 CRTextureObj *pTObj;
448 CRTextureLevel *pTImg;
449 crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
450
451 GLuint uid = pTObj->hwid;
452 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
453 }
454 else
455 {
456 cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
457 }
458
459 if (idPBO)
460 {
461 pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
462 if (!pvData)
463 {
464 crWarning("Failed to MapBuffer in CrHlpGetTexImage");
465 return NULL;
466 }
467 }
468
469 CRASSERT(pvData);
470 return pvData;
471}
472
473void SERVER_DISPATCH_APIENTRY
474crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
475{
476 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
477 PCR_DISPLAY pDisplay = crServerDisplayGet(idScreen);
478 if (!pDisplay)
479 {
480 crWarning("crServerDisplayGet Failed");
481 return;
482 }
483
484 PCR_DISPLAY_ENTRY pEntry = NULL;
485 if (texture)
486 {
487 pEntry = CrDemEntryAcquire(&cr_server.PresentTexturepMap, texture);
488 if (!pEntry)
489 {
490 crWarning("CrDemEntryAcquire Failed");
491 return;
492 }
493 }
494
495 CrDpEnter(pDisplay);
496
497 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
498 {
499 RTPOINT Point = {xPos, yPos};
500 int rc = CrDpEntryRegionsAdd(pDisplay, pEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects);
501 if (!RT_SUCCESS(rc))
502 {
503 crWarning("CrDpEntryRegionsAdd Failed rc %d", rc);
504// if (pEntry)
505// CrDemEntryRelease(pEntry);
506 return;
507 }
508 }
509 else
510 {
511 CrDpEntryRegionsClear(pDisplay);
512 }
513
514 CrDpLeave(pDisplay);
515}
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