VirtualBox

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

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

crOpenGL: host offscreen rendering to fix gnome-shell issues, repaint problems and more

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.2 KB
Line 
1/* $Id: server_presenter.cpp 43932 2012-11-21 19:28:05Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012 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#define CR_DISPLAY_RECTS_UNDEFINED UINT32_MAX
35
36
37#define CR_PRESENTER_ENTRY_FROM_ENTRY(_p) ((PCR_PRESENTER_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(CR_PRESENTER_ENTRY, Ce)))
38#define CR_PRESENTER_FROM_COMPOSITOR(_p) ((PCR_PRESENTER)(((uint8_t*)(_p)) - RT_OFFSETOF(CR_PRESENTER, Compositor)))
39
40
41static int crPtRectsAssignBuffer(PCR_PRESENTER pPresenter, uint32_t cRects)
42{
43 Assert(cRects);
44
45 if (pPresenter->cRectsBuffer >= cRects)
46 {
47 pPresenter->cRects = cRects;
48 return VINF_SUCCESS;
49 }
50
51 if (pPresenter->cRectsBuffer)
52 {
53 Assert(pPresenter->paSrcRects);
54 RTMemFree(pPresenter->paSrcRects);
55 Assert(pPresenter->paDstRects);
56 RTMemFree(pPresenter->paDstRects);
57 }
58
59 pPresenter->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pPresenter->paSrcRects) * cRects);
60 if (pPresenter->paSrcRects)
61 {
62 pPresenter->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pPresenter->paDstRects) * cRects);
63 if (pPresenter->paDstRects)
64 {
65 pPresenter->cRects = cRects;
66 pPresenter->cRectsBuffer = cRects;
67 return VINF_SUCCESS;
68 }
69 else
70 {
71 crWarning("RTMemAlloc failed!");
72 RTMemFree(pPresenter->paSrcRects);
73 pPresenter->paSrcRects = NULL;
74 }
75 }
76 else
77 {
78 crWarning("RTMemAlloc failed!");
79 pPresenter->paDstRects = NULL;
80 }
81
82 pPresenter->cRects = CR_DISPLAY_RECTS_UNDEFINED;
83 pPresenter->cRectsBuffer = 0;
84
85 return VERR_NO_MEMORY;
86}
87
88static void crPtRectsInvalidate(PCR_PRESENTER pPresenter)
89{
90 pPresenter->cRects = CR_DISPLAY_RECTS_UNDEFINED;
91}
92
93static DECLCALLBACK(bool) crPtRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
94{
95 uint32_t* pCounter = (uint32_t*)pvVisitor;
96 Assert(VBoxVrListRectsCount(&pEntry->Vr));
97 *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
98 return true;
99}
100
101typedef struct CR_PRESENTOR_RECTS_ASSIGNER
102{
103 PRTRECT paSrcRects;
104 PRTRECT paDstRects;
105 uint32_t cRects;
106} CR_PRESENTOR_RECTS_ASSIGNER, *PCR_PRESENTOR_RECTS_ASSIGNER;
107
108static DECLCALLBACK(bool) crPtRectsAssignerCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
109{
110 PCR_PRESENTOR_RECTS_ASSIGNER pData = (PCR_PRESENTOR_RECTS_ASSIGNER)pvVisitor;
111 PCR_PRESENTER pPresenter = CR_PRESENTER_FROM_COMPOSITOR(pCompositor);
112 PCR_PRESENTER_ENTRY pEntry = CR_PRESENTER_ENTRY_FROM_ENTRY(pCEntry);
113 pEntry->paSrcRects = pData->paSrcRects;
114 pEntry->paDstRects = pData->paDstRects;
115 uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
116 Assert(cRects);
117 Assert(cRects >= pData->cRects);
118 int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstRects);
119 AssertRC(rc);
120 if (pPresenter->StretchX >= 1. && pPresenter->StretchY >= 1. /* <- stretching can not zero some rects */
121 && !pEntry->Pos.x && !pEntry->Pos.y)
122 {
123 memcpy(pEntry->paSrcRects, pEntry->paDstRects, cRects * sizeof (*pEntry->paSrcRects));
124 }
125 else
126 {
127 for (uint32_t i = 0; i < cRects; ++i)
128 {
129 pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstRects[i].xLeft - pEntry->Pos.x) * pPresenter->StretchX);
130 pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstRects[i].yTop - pEntry->Pos.y) * pPresenter->StretchY);
131 pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstRects[i].xRight - pEntry->Pos.x) * pPresenter->StretchX);
132 pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstRects[i].yBottom - pEntry->Pos.y) * pPresenter->StretchY);
133 }
134
135 bool canZeroX = (pPresenter->StretchX < 1);
136 bool canZeroY = (pPresenter->StretchY < 1);
137 if (canZeroX && canZeroY)
138 {
139 /* filter out zero rectangles*/
140 uint32_t iOrig, iNew;
141 for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
142 {
143 PRTRECT pOrigRect = &pEntry->paSrcRects[iOrig];
144 if (pOrigRect->xLeft == pOrigRect->xRight
145 || pOrigRect->yTop == pOrigRect->yBottom)
146 continue;
147
148 if (iNew != iOrig)
149 {
150 PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
151 *pNewRect = *pOrigRect;
152 }
153
154 ++iNew;
155 }
156
157 Assert(iNew <= iOrig);
158
159 uint32_t cDiff = iOrig - iNew;
160
161 if (cDiff)
162 {
163 pPresenter->cRects -= cDiff;
164 cRects -= cDiff;
165 }
166 }
167 }
168
169 pEntry->cRects = cRects;
170 pData->paDstRects += cRects;
171 pData->paSrcRects += cRects;
172 pData->cRects -= cRects;
173 return true;
174}
175
176static int crPtRectsCheckInit(PCR_PRESENTER pPresenter)
177{
178 if (pPresenter->cRects != CR_DISPLAY_RECTS_UNDEFINED)
179 return VINF_SUCCESS;
180
181 uint32_t cRects = 0;
182 VBoxVrCompositorVisit(&pPresenter->Compositor, crPtRectsCounterCb, &cRects);
183
184 if (!cRects)
185 {
186 pPresenter->cRects = 0;
187 return VINF_SUCCESS;
188 }
189
190 int rc = crPtRectsAssignBuffer(pPresenter, cRects);
191 if (!RT_SUCCESS(rc))
192 return rc;
193
194 CR_PRESENTOR_RECTS_ASSIGNER AssignerData;
195 AssignerData.paSrcRects = pPresenter->paSrcRects;
196 AssignerData.paDstRects = pPresenter->paDstRects;
197 AssignerData.cRects = pPresenter->cRects;
198 VBoxVrCompositorVisit(&pPresenter->Compositor, crPtRectsAssignerCb, &AssignerData);
199 Assert(!AssignerData.cRects);
200 return VINF_SUCCESS;
201}
202
203DECLCALLBACK(int) CrPtCbDrawEntrySingle(struct CR_PRESENTER *pPresenter, struct CR_PRESENTER_ENTRY *pEntry, PCR_BLITTER pBlitter, bool *pfAllEntriesDrawn)
204{
205 if (pfAllEntriesDrawn)
206 *pfAllEntriesDrawn = false;
207
208 int rc = crPtRectsCheckInit(pPresenter);
209 if (!RT_SUCCESS(rc))
210 {
211 crWarning("crPtRectsCheckInit failed, rc %d", rc);
212 return rc;
213 }
214
215 Assert(VBoxVrListRectsCount(&pEntry->Ce.Vr));
216
217 if (!pEntry->cRects)
218 return VINF_SUCCESS;
219
220 rc = pPresenter->pfnDrawTexture(pPresenter, pBlitter, &pEntry->Texture, pEntry->paSrcRects, pEntry->paDstRects, pEntry->cRects);
221 if (!RT_SUCCESS(rc))
222 {
223 crWarning("pfnDrawTexture failed, rc %d", rc);
224 return rc;
225 }
226
227 return VINF_SUCCESS;
228}
229
230static DECLCALLBACK(bool) crPtDrawEntryAllCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
231{
232 struct CR_PRESENTER *pPresenter = CR_PRESENTER_FROM_COMPOSITOR(pCompositor);
233 struct CR_PRESENTER_ENTRY *pEntry = CR_PRESENTER_ENTRY_FROM_ENTRY(pCEntry);
234 PCR_BLITTER pBlitter = (PCR_BLITTER)pvVisitor;
235 bool fAllEntriesDrawn;
236 int rc = CrPtCbDrawEntrySingle(pPresenter, pEntry, pBlitter, &fAllEntriesDrawn);
237 if (!RT_SUCCESS(rc))
238 {
239 crWarning("CrPtCbDrawEntrySingle failed, rc %d", rc);
240 }
241 return !fAllEntriesDrawn;
242}
243
244DECLCALLBACK(int) CrPtCbDrawEntryAll(struct CR_PRESENTER *pPresenter, struct CR_PRESENTER_ENTRY *pEntry, PCR_BLITTER pBlitter, bool *pfAllEntriesDrawn)
245{
246 int rc = crPtRectsCheckInit(pPresenter);
247 if (!RT_SUCCESS(rc))
248 {
249 crWarning("crPtRectsCheckInit failed, rc %d", rc);
250 return rc;
251 }
252
253 VBoxVrCompositorVisit(&pPresenter->Compositor, crPtDrawEntryAllCb, pBlitter);
254
255 if (pfAllEntriesDrawn)
256 *pfAllEntriesDrawn = true;
257
258 return VINF_SUCCESS;
259}
260
261static int crPtEntryRegionsAdd(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
262{
263 uint32_t fChangedFlags = 0;
264 int rc = VBoxVrCompositorEntryRegionsAdd(&pPresenter->Compositor, &pEntry->Ce, cRegions, paRegions, &fChangedFlags);
265 if (!RT_SUCCESS(rc))
266 {
267 crWarning("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc);
268 return rc;
269 }
270
271 if (fChangedFlags & VBOXVR_COMPOSITOR_CF_COMPOSITED_REGIONS_CHANGED)
272 {
273 crPtRectsInvalidate(pPresenter);
274 rc = pPresenter->pfnRegionsChanged(pPresenter);
275 if (!RT_SUCCESS(rc))
276 {
277 crWarning("pfnRegionsChanged failed, rc %d", rc);
278 return rc;
279 }
280 }
281
282 if (pfChanged)
283 *pfChanged = !!fChangedFlags;
284 return VINF_SUCCESS;
285}
286
287static int crPtEntryRegionsSet(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
288{
289 bool fChanged;
290 int rc = VBoxVrCompositorEntryRegionsSet(&pPresenter->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
291 if (!RT_SUCCESS(rc))
292 {
293 crWarning("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc);
294 return rc;
295 }
296
297 if (fChanged)
298 {
299 crPtRectsInvalidate(pPresenter);
300 rc = pPresenter->pfnRegionsChanged(pPresenter);
301 if (!RT_SUCCESS(rc))
302 {
303 crWarning("pfnRegionsChanged failed, rc %d", rc);
304 return rc;
305 }
306 }
307
308 if (pfChanged)
309 *pfChanged = fChanged;
310 return VINF_SUCCESS;
311}
312
313static void crPtEntryPositionSet(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, const RTPOINT *pPos)
314{
315 if (pEntry && (pEntry->Pos.x != pPos->x || pEntry->Pos.y != pPos->y))
316 {
317 if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
318 {
319 VBoxVrCompositorEntryRemove(&pPresenter->Compositor, &pEntry->Ce);
320 crPtRectsInvalidate(pPresenter);
321 }
322 pEntry->Pos = *pPos;
323 }
324}
325
326int CrPtPresentEntry(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, PCR_BLITTER pBlitter)
327{
328 int rc = CrBltEnter(pBlitter, cr_server.currentCtxInfo, cr_server.currentMural);
329 if (!RT_SUCCESS(rc))
330 {
331 crWarning("CrBltEnter failed, rc %d", rc);
332 return rc;
333 }
334
335 rc = pPresenter->pfnDrawEntry(pPresenter, pEntry, pBlitter, NULL);
336
337 CrBltLeave(pBlitter);
338
339 if (!RT_SUCCESS(rc))
340 {
341 crWarning("pfnDraw failed, rc %d", rc);
342 return rc;
343 }
344
345 return VINF_SUCCESS;
346}
347
348static DECLCALLBACK(bool) crPtPresentCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
349{
350 struct CR_PRESENTER *pPresenter = CR_PRESENTER_FROM_COMPOSITOR(pCompositor);
351 struct CR_PRESENTER_ENTRY *pEntry = CR_PRESENTER_ENTRY_FROM_ENTRY(pCEntry);
352 PCR_BLITTER pBlitter = (PCR_BLITTER)pvVisitor;
353 bool fAllDrawn = false;
354 int rc = pPresenter->pfnDrawEntry(pPresenter, pEntry, pBlitter, &fAllDrawn);
355 if (!RT_SUCCESS(rc))
356 {
357 crWarning("pfnDrawEntry failed, rc %d", rc);
358 }
359 return !fAllDrawn;
360}
361
362int CrPtPresent(PCR_PRESENTER pPresenter, PCR_BLITTER pBlitter)
363{
364 int rc = CrBltEnter(pBlitter, cr_server.currentCtxInfo, cr_server.currentMural);
365 if (!RT_SUCCESS(rc))
366 {
367 crWarning("CrBltEnter failed, rc %d", rc);
368 return rc;
369 }
370
371 VBoxVrCompositorVisit(&pPresenter->Compositor, crPtPresentCb, pBlitter);
372
373 CrBltLeave(pBlitter);
374
375 if (!RT_SUCCESS(rc))
376 {
377 crWarning("pfnDraw failed, rc %d", rc);
378 return rc;
379 }
380
381 return VINF_SUCCESS;
382}
383
384int CrPtEntryRegionsAdd(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
385{
386 crPtEntryPositionSet(pPresenter, pEntry, pPos);
387
388 int rc = crPtEntryRegionsAdd(pPresenter, pEntry, cRegions, paRegions, NULL);
389 if (!RT_SUCCESS(rc))
390 {
391 crWarning("crPtEntryRegionsAdd failed, rc %d", rc);
392 return rc;
393 }
394
395 return VINF_SUCCESS;
396}
397
398int CrPtEntryRegionsSet(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
399{
400 crPtEntryPositionSet(pPresenter, pEntry, pPos);
401
402 int rc = crPtEntryRegionsSet(pPresenter, pEntry, cRegions, paRegions, NULL);
403 if (!RT_SUCCESS(rc))
404 {
405 crWarning("crPtEntryRegionsAdd failed, rc %d", rc);
406 return rc;
407 }
408
409 return VINF_SUCCESS;
410}
411
412int CrPtEntryRemove(PCR_PRESENTER pPresenter, PCR_PRESENTER_ENTRY pEntry)
413{
414 if (!VBoxVrCompositorEntryRemove(&pPresenter->Compositor, &pEntry->Ce))
415 return VINF_SUCCESS;
416
417 crPtRectsInvalidate(pPresenter);
418 int rc = pPresenter->pfnRegionsChanged(pPresenter);
419 if (!RT_SUCCESS(rc))
420 {
421 crWarning("pfnRegionsChanged failed, rc %d", rc);
422 return rc;
423 }
424 return VINF_SUCCESS;
425}
426
427int CrPtInit(PCR_PRESENTER pPresenter, PFNCRDISPLAY_REGIONS_CHANGED pfnRegionsChanged, PFNCRDISPLAY_DRAW_ENTRY pfnDrawEntry, PFNCRDISPLAY_DRAW_TEXTURE pfnDrawTexture)
428{
429 memset(pPresenter, 0, sizeof (*pPresenter));
430 VBoxVrCompositorInit(&pPresenter->Compositor, NULL);
431 pPresenter->StretchX = 1.0;
432 pPresenter->StretchY = 1.0;
433 pPresenter->pfnRegionsChanged = pfnRegionsChanged;
434 pPresenter->pfnDrawEntry = pfnDrawEntry;
435 pPresenter->pfnDrawTexture = pfnDrawTexture;
436 return VINF_SUCCESS;
437}
438
439void CrPtTerm(PCR_PRESENTER pPresenter)
440{
441 VBoxVrCompositorTerm(&pPresenter->Compositor);
442 if (pPresenter->paDstRects)
443 RTMemFree(pPresenter->paDstRects);
444 if (pPresenter->paSrcRects)
445 RTMemFree(pPresenter->paSrcRects);
446}
447
448void CrPtSetStretching(PCR_PRESENTER pPresenter, float StretchX, float StretchY)
449{
450 pPresenter->StretchX = StretchX;
451 pPresenter->StretchY = StretchY;
452 crPtRectsInvalidate(pPresenter);
453}
454
455int CrPtGetRegions(PCR_PRESENTER pPresenter, uint32_t *pcRegions, const RTRECT **ppaRegions)
456{
457 int rc = crPtRectsCheckInit(pPresenter);
458 if (!RT_SUCCESS(rc))
459 {
460 crWarning("crPtRectsCheckInit failed, rc %d", rc);
461 return rc;
462 }
463
464 Assert(pPresenter->cRects != CR_DISPLAY_RECTS_UNDEFINED);
465
466 *pcRegions = pPresenter->cRects;
467 *ppaRegions = pPresenter->paDstRects;
468 return VINF_SUCCESS;
469}
470
471/* DISPLAY */
472#define CR_DISPLAY_FROM_PRESENTER(_p) ((PCR_DISPLAY)(((uint8_t*)(_p)) - RT_OFFSETOF(CR_DISPLAY, Presenter)))
473
474static DECLCALLBACK(int) crDpCbRegionsChanged(struct CR_PRESENTER *pPresenter)
475{
476 uint32_t cRegions;
477 const RTRECT *paRegions;
478 int rc = CrPtGetRegions(pPresenter, &cRegions, &paRegions);
479 if (!RT_SUCCESS(rc))
480 {
481 crWarning("CrPtGetRegions failed, rc %d", rc);
482 return rc;
483 }
484
485 PCR_DISPLAY pDisplay = CR_DISPLAY_FROM_PRESENTER(pPresenter);
486
487 cr_server.head_spu->dispatch_table.WindowVisibleRegion(pDisplay->Mural.spuWindow, cRegions, (GLint*)paRegions);
488
489 if (pDisplay->Mural.pvOutputRedirectInstance)
490 {
491 /* @todo the code assumes that RTRECT == four GLInts. */
492 cr_server.outputRedirect.CRORVisibleRegion(pDisplay->Mural.pvOutputRedirectInstance,
493 cRegions, paRegions);
494 }
495
496 return VINF_SUCCESS;
497}
498
499static DECLCALLBACK(int) crDpCbDrawTextureWindow(struct CR_PRESENTER *pPresenter, PCR_BLITTER pBlitter,
500 CR_BLITTER_TEXTURE *pTexture, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects)
501{
502 Assert(CrBltIsEntered(pBlitter));
503 CrBltBlitTexMural(pBlitter, pTexture, paSrcRects, paDstRects, cRects, 0);
504 return VINF_SUCCESS;
505}
506
507int CrDpInit(PCR_DISPLAY pDisplay)
508{
509 const GLint visBits = CR_RGB_BIT | CR_DOUBLE_BIT;
510 int rc = CrPtInit(&pDisplay->Presenter, crDpCbRegionsChanged, CrPtCbDrawEntryAll, crDpCbDrawTextureWindow);
511 if (RT_SUCCESS(rc))
512 {
513 if (crServerMuralInit(&pDisplay->Mural, "", visBits, -1) >= 0)
514 {
515 return VINF_SUCCESS;
516// crServerMuralTerm(&pDisplay->Mural);
517 }
518 else
519 {
520 crWarning("crServerMuralInit failed!");
521 rc = VERR_GENERAL_FAILURE;
522 }
523 CrPtTerm(&pDisplay->Presenter);
524 }
525 CRASSERT(RT_FAILURE(rc));
526 return rc;
527}
528
529void CrDpTerm(PCR_DISPLAY pDisplay)
530{
531 CrPtTerm(&pDisplay->Presenter);
532 crServerMuralTerm(&pDisplay->Mural);
533}
534
535int CrDpBlitterTestWithMural(PCR_BLITTER pBlitter, CRMuralInfo *pMural)
536{
537 CrBltMuralSetCurrent(pBlitter, pMural);
538 /* try to enter to make sure the blitter is initialized completely and to make sure we actually can do that */
539 int rc = CrBltEnter(pBlitter, cr_server.currentCtxInfo, cr_server.currentMural);
540 if (RT_SUCCESS(rc))
541 {
542 CrBltLeave(pBlitter);
543 return VINF_SUCCESS;
544 }
545 else
546 {
547 crWarning("CrBltEnter failed, rc %d", rc);
548 }
549 return rc;
550}
551
552int CrDpBlitterTest(PCR_DISPLAY pDisplay, PCR_BLITTER pBlitter)
553{
554 return CrDpBlitterTestWithMural(pBlitter, &pDisplay->Mural);
555}
556
557void CrDpResize(PCR_DISPLAY pDisplay, uint32_t width, uint32_t height,
558 uint32_t stretchedWidth, uint32_t stretchedHeight)
559{
560 float StretchX, StretchY;
561 StretchX = ((float)stretchedWidth)/width;
562 StretchY = ((float)stretchedHeight)/height;
563 crServerMuralSize(&pDisplay->Mural, stretchedWidth, stretchedHeight);
564 CrPtSetStretching(&pDisplay->Presenter, StretchX, StretchY);
565}
566
567int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
568{
569 return CrPtEntryRegionsSet(&pDisplay->Presenter, &pEntry->Pe, pPos, cRegions, paRegions);
570}
571
572int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions)
573{
574 return CrPtEntryRegionsAdd(&pDisplay->Presenter, &pEntry->Pe, pPos, cRegions, paRegions);
575}
576
577int CrDpPresentEntry(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry)
578{
579 return CrPtPresentEntry(&pDisplay->Presenter, &pEntry->Pe, pDisplay->pBlitter);
580}
581
582void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, PCR_BLITTER_TEXTURE pTextureData)
583{
584 CrPtEntryInit(&pEntry->Pe, pTextureData);
585}
586
587void CrDpEntryCleanup(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry)
588{
589 CrPtEntryRemove(&pDisplay->Presenter, &pEntry->Pe);
590}
591
592int CrDemInit(PCR_DISPLAY_ENTRY_MAP pMap)
593{
594 pMap->pTextureMap = crAllocHashtable();
595 if (pMap->pTextureMap)
596 return VINF_SUCCESS;
597
598 crWarning("crAllocHashtable failed!");
599 return VERR_NO_MEMORY;
600}
601
602void CrDemTerm(PCR_DISPLAY_ENTRY_MAP pMap)
603{
604 crFreeHashtable(pMap->pTextureMap, crFree);
605}
606
607PCR_DISPLAY_ENTRY CrDemEntryGetCreate(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, CRContextInfo *pCtxInfo)
608{
609 PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
610 if (pEntry)
611 return pEntry;
612
613 CRContext *pContext = pCtxInfo->pContext;
614 if (!pContext)
615 {
616 crWarning("pContext is null!");
617 return NULL;
618 }
619
620 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pContext->shared->textureTable, idTexture);
621 if (!pTobj)
622 {
623 crWarning("pTobj is null!");
624 return NULL;
625 }
626
627 GLuint hwId = crStateGetTextureObjHWID(pTobj);
628 if (!hwId)
629 {
630 crWarning("hwId is null!");
631 return NULL;
632 }
633
634 CR_BLITTER_TEXTURE TextureData;
635 TextureData.width = pTobj->level[0]->width;
636 TextureData.height = pTobj->level[0]->height;
637 TextureData.target = pTobj->target;
638 TextureData.hwid = hwId;
639
640 pEntry = (PCR_DISPLAY_ENTRY)crAlloc(sizeof (*pEntry));
641 if (!pEntry)
642 {
643 crWarning("crAlloc failed allocating CR_DISPLAY_ENTRY");
644 return NULL;
645 }
646
647 CrDpEntryInit(pEntry, &TextureData);
648
649 crHashtableAdd(pMap->pTextureMap, idTexture, pEntry);
650 return pEntry;
651
652}
653
654void CrDemEntryDestroy(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture)
655{
656#ifdef DEBUG
657 {
658 PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
659 if (!pEntry)
660 {
661 crWarning("request to delete inexistent entry");
662 return;
663 }
664
665 Assert(!CrDpEntryIsUsed(pEntry));
666 }
667#endif
668 crHashtableDelete(pMap->pTextureMap, idTexture, crFree);
669}
670
671#define CR_PRESENT_SCREEN_MASK 0xffff
672#define CR_PRESENT_FLAGS_OFFSET 16
673
674#define CR_PRESENT_GET_SCREEN(_cfg) ((_cfg) & CR_PRESENT_SCREEN_MASK)
675#define CR_PRESENT_GET_FLAGS(_cfg) ((_cfg) >> CR_PRESENT_FLAGS_OFFSET)
676
677int crServerBlitterInit(PCR_BLITTER pBlitter, CRMuralInfo*pMural)
678{
679 int rc = CrBltInit(pBlitter, pMural);
680 if (RT_SUCCESS(rc))
681 {
682 rc = CrDpBlitterTestWithMural(pBlitter, pMural);
683 if (RT_SUCCESS(rc))
684 return VINF_SUCCESS;
685 else
686 crWarning("CrDpBlitterTestWithMural failed, rc %d", rc);
687 CrBltTerm(pBlitter);
688 }
689 else
690 crWarning("CrBltInit failed, rc %d", rc);
691 return rc;
692}
693
694PCR_BLITTER crServerGetFBOPresentBlitter(CRMuralInfo*pMural)
695{
696 if (cr_server.fFBOModeBlitterInited > 0)
697 return &cr_server.FBOModeBlitter;
698 if (!cr_server.fFBOModeBlitterInited)
699 {
700 int rc = crServerBlitterInit(&cr_server.FBOModeBlitter, pMural);
701 if (RT_SUCCESS(rc))
702 {
703 cr_server.fFBOModeBlitterInited = 1;
704 return &cr_server.FBOModeBlitter;
705 }
706 crWarning("crServerBlitterInit failed rc %d", rc);
707 cr_server.fFBOModeBlitterInited = -1;
708 }
709 return NULL;
710}
711
712static int8_t crServerCheckInitDisplayBlitter()
713{
714 if (cr_server.fPresentBlitterInited)
715 return cr_server.fPresentBlitterInited;
716
717 crDebug("Display Functionality is requested");
718 Assert(!ASMBitTest(cr_server.DisplaysInitMap, 0));
719
720 int rc = CrDemInit(&cr_server.PresentTexturepMap);
721 if (RT_SUCCESS(rc))
722 {
723 rc = CrDpInit(&cr_server.aDispplays[0]);
724 if (RT_SUCCESS(rc))
725 {
726 CRMuralInfo*pMural = CrDpGetMural(&cr_server.aDispplays[0]);
727 rc = crServerBlitterInit(&cr_server.PresentBlitter, pMural);
728 if (RT_SUCCESS(rc))
729 {
730 CrDpBlitterSet(&cr_server.aDispplays[0], &cr_server.PresentBlitter);
731 CrDpResize(&cr_server.aDispplays[0],
732 cr_server.screen[0].w, cr_server.screen[0].h,
733 cr_server.screen[0].w, cr_server.screen[0].h);
734 ASMBitSet(cr_server.DisplaysInitMap, 0);
735 cr_server.fPresentBlitterInited = 1;
736 return 1;
737 }
738 else
739 {
740 crWarning("crServerBlitterInit failed, rc %d", rc);
741 }
742 CrDpTerm(&cr_server.aDispplays[0]);
743 }
744 else
745 {
746 crWarning("CrDpInit failed, rc %d", rc);
747 }
748 CrDemTerm(&cr_server.PresentTexturepMap);
749 }
750 else
751 {
752 crWarning("CrDemInit failed, rc %d", rc);
753 }
754
755 cr_server.fPresentBlitterInited = -1;
756 return -1;
757}
758
759static bool crServerDisplayIsSupported()
760{
761 return crServerCheckInitDisplayBlitter() > 0;
762}
763
764PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen)
765{
766 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
767 return &cr_server.aDispplays[idScreen];
768 return NULL;
769}
770
771static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen)
772{
773 if (idScreen >= CR_MAX_GUEST_MONITORS)
774 {
775 crWarning("invalid idScreen %d", idScreen);
776 return NULL;
777 }
778
779 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
780 return &cr_server.aDispplays[idScreen];
781
782 if (crServerCheckInitDisplayBlitter() > 0)
783 {
784 /* the display (screen id == 0) can be initialized while doing crServerCheckInitDisplayBlitter,
785 * so re-check the bit map */
786 if (ASMBitTest(cr_server.DisplaysInitMap, idScreen))
787 return &cr_server.aDispplays[idScreen];
788
789 int rc = CrDpInit(&cr_server.aDispplays[idScreen]);
790 if (RT_SUCCESS(rc))
791 {
792 CrDpBlitterSet(&cr_server.aDispplays[idScreen], &cr_server.PresentBlitter);
793 CrDpResize(&cr_server.aDispplays[idScreen],
794 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h,
795 cr_server.screen[idScreen].w, cr_server.screen[idScreen].h);
796 ASMBitSet(cr_server.DisplaysInitMap, idScreen);
797 return &cr_server.aDispplays[idScreen];
798 }
799 else
800 {
801 crWarning("CrDpInit failed for screen %d", idScreen);
802 }
803 }
804 else
805 {
806 crWarning("crServerCheckInitDisplayBlitter said \"UNSUPPORTED\"");
807 }
808
809 return NULL;
810}
811
812void SERVER_DISPATCH_APIENTRY
813crServerDispatchTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, GLint *pRects)
814{
815 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
816 PCR_DISPLAY pDisplay = crServerDisplayGet(idScreen);
817 if (!pDisplay)
818 {
819 crWarning("crServerDisplayGet Failed");
820 return;
821 }
822
823 PCR_DISPLAY_ENTRY pEntry = CrDemEntryGetCreate(&cr_server.PresentTexturepMap, texture, cr_server.currentCtxInfo);
824 if (!pEntry)
825 {
826 crWarning("CrDemEntryGetCreate Failed");
827 return;
828 }
829
830 RTPOINT Point = {xPos, yPos};
831 int rc = CrDpEntryRegionsAdd(pDisplay, pEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects);
832 if (!RT_SUCCESS(rc))
833 {
834 crWarning("CrDpEntrySetRegions Failed rc %d", rc);
835 return;
836 }
837
838 rc = CrDpPresentEntry(pDisplay, pEntry);
839 if (!RT_SUCCESS(rc))
840 {
841 crWarning("CrDpEntrySetRegions Failed rc %d", rc);
842 return;
843 }
844}
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