VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/compositor.cpp@ 50095

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

crOpenGL: presentation infrastructure rework (still work in progress)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.4 KB
Line 
1/* $Id: compositor.cpp 50095 2014-01-17 16:34:07Z vboxsync $ */
2
3/** @file
4 * Compositor impl
5 */
6
7/*
8 * Copyright (C) 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_compositor.h>
19
20#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
21
22
23static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
24{
25 Assert(cRects);
26
27 if (pCompositor->cRectsBuffer >= cRects)
28 {
29 pCompositor->cRects = cRects;
30 return VINF_SUCCESS;
31 }
32
33 if (pCompositor->cRectsBuffer)
34 {
35 Assert(pCompositor->paSrcRects);
36 RTMemFree(pCompositor->paSrcRects);
37 pCompositor->paSrcRects = NULL;
38 Assert(pCompositor->paDstRects);
39 RTMemFree(pCompositor->paDstRects);
40 pCompositor->paDstRects = NULL;
41 Assert(pCompositor->paDstUnstretchedRects);
42 RTMemFree(pCompositor->paDstUnstretchedRects);
43 pCompositor->paDstUnstretchedRects = NULL;
44 }
45 else
46 {
47 Assert(!pCompositor->paSrcRects);
48 Assert(!pCompositor->paDstRects);
49 Assert(!pCompositor->paDstUnstretchedRects);
50 }
51
52 pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paSrcRects) * cRects);
53 if (pCompositor->paSrcRects)
54 {
55 pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstRects) * cRects);
56 if (pCompositor->paDstRects)
57 {
58 pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects);
59 if (pCompositor->paDstUnstretchedRects)
60 {
61 pCompositor->cRects = cRects;
62 pCompositor->cRectsBuffer = cRects;
63 return VINF_SUCCESS;
64 }
65
66 RTMemFree(pCompositor->paDstRects);
67 pCompositor->paDstRects = NULL;
68 }
69 else
70 {
71 WARN(("RTMemAlloc failed!"));
72 }
73 RTMemFree(pCompositor->paSrcRects);
74 pCompositor->paSrcRects = NULL;
75 }
76 else
77 {
78 WARN(("RTMemAlloc failed!"));
79 }
80
81 pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
82 pCompositor->cRectsBuffer = 0;
83
84 return VERR_NO_MEMORY;
85}
86
87static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
88{
89 pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
90}
91
92static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
93{
94 uint32_t* pCounter = (uint32_t*)pvVisitor;
95 Assert(VBoxVrListRectsCount(&pEntry->Vr));
96 *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
97 return true;
98}
99
100typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
101{
102 PRTRECT paSrcRects;
103 PRTRECT paDstRects;
104 PRTRECT paDstUnstretchedRects;
105 uint32_t cRects;
106} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
107
108static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
109{
110 PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
111 PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
112 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
113 pEntry->paSrcRects = pData->paSrcRects;
114 pEntry->paDstRects = pData->paDstRects;
115 pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
116 uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
117 Assert(cRects);
118 Assert(cRects <= pData->cRects);
119 int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
120 AssertRC(rc);
121
122 if (!pEntry->Rect.xLeft && !pEntry->Rect.yTop)
123 {
124 memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paSrcRects));
125 }
126 else
127 {
128 for (uint32_t i = 0; i < cRects; ++i)
129 {
130 pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Rect.xLeft));
131 pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Rect.yTop));
132 pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Rect.xLeft));
133 pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Rect.yTop));
134 }
135 }
136
137#ifndef IN_RING0
138 if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
139 {
140 for (uint32_t i = 0; i < cRects; ++i)
141 {
142 if (pCompositor->StretchX != 1.)
143 {
144 pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
145 pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
146 }
147 if (pCompositor->StretchY != 1.)
148 {
149 pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
150 pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
151 }
152 }
153 }
154 else
155#endif
156 {
157 memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paDstUnstretchedRects));
158 }
159
160#if 0//ndef IN_RING0
161 bool canZeroX = (pCompositor->StretchX < 1.);
162 bool canZeroY = (pCompositor->StretchY < 1.);
163 if (canZeroX && canZeroY)
164 {
165 /* filter out zero rectangles*/
166 uint32_t iOrig, iNew;
167 for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
168 {
169 PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
170 if (pOrigRect->xLeft != pOrigRect->xRight
171 && pOrigRect->yTop != pOrigRect->yBottom)
172 continue;
173
174 if (iNew != iOrig)
175 {
176 PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
177 *pNewRect = *pOrigRect;
178 }
179
180 ++iNew;
181 }
182
183 Assert(iNew <= iOrig);
184
185 uint32_t cDiff = iOrig - iNew;
186
187 if (cDiff)
188 {
189 pCompositor->cRects -= cDiff;
190 cRects -= cDiff;
191 }
192 }
193#endif
194
195 pEntry->cRects = cRects;
196 pData->paDstRects += cRects;
197 pData->paSrcRects += cRects;
198 pData->paDstUnstretchedRects += cRects;
199 pData->cRects -= cRects;
200 return true;
201}
202
203static int crVrScrCompositorRectsCheckInit(const VBOXVR_SCR_COMPOSITOR *pcCompositor)
204{
205 VBOXVR_SCR_COMPOSITOR *pCompositor = const_cast<VBOXVR_SCR_COMPOSITOR*>(pcCompositor);
206
207 if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
208 return VINF_SUCCESS;
209
210 uint32_t cRects = 0;
211 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
212
213 if (!cRects)
214 {
215 pCompositor->cRects = 0;
216 return VINF_SUCCESS;
217 }
218
219 int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
220 if (!RT_SUCCESS(rc))
221 return rc;
222
223 VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
224 AssignerData.paSrcRects = pCompositor->paSrcRects;
225 AssignerData.paDstRects = pCompositor->paDstRects;
226 AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
227 AssignerData.cRects = pCompositor->cRects;
228 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
229 Assert(!AssignerData.cRects);
230 return VINF_SUCCESS;
231}
232
233
234static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
235{
236 uint32_t fChangedFlags = 0;
237 PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
238 int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions, paRegions, &pReplacedEntry, &fChangedFlags);
239 if (!RT_SUCCESS(rc))
240 {
241 WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
242 return rc;
243 }
244
245 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
246
247 if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
248 {
249 crVrScrCompositorRectsInvalidate(pCompositor);
250 }
251 else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
252 {
253 Assert(pReplacedScrEntry);
254 }
255
256 if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
257 {
258 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
259 }
260 else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
261 {
262 CrVrScrCompositorEntrySetChanged(pEntry, true);
263 }
264
265 if (pfChangedFlags)
266 *pfChangedFlags = fChangedFlags;
267
268 if (ppReplacedScrEntry)
269 *ppReplacedScrEntry = pReplacedScrEntry;
270
271 return VINF_SUCCESS;
272}
273
274static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
275{
276 bool fChanged;
277 int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
278 if (!RT_SUCCESS(rc))
279 {
280 WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
281 return rc;
282 }
283
284 if (fChanged)
285 {
286 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
287 if (!CrVrScrCompositorEntryIsInList(pEntry))
288 {
289 pEntry->cRects = 0;
290 pEntry->paSrcRects = NULL;
291 pEntry->paDstRects = NULL;
292 pEntry->paDstUnstretchedRects = NULL;
293 }
294 crVrScrCompositorRectsInvalidate(pCompositor);
295 }
296
297
298 if (pfChanged)
299 *pfChanged = fChanged;
300 return VINF_SUCCESS;
301}
302
303static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, bool *pfChanged)
304{
305 if (pfChanged)
306 *pfChanged = false;
307 if (pEntry && (pEntry->Rect.xLeft != pPos->x || pEntry->Rect.yTop != pPos->y))
308 {
309 if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
310 {
311 int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Rect.xLeft, pPos->y - pEntry->Rect.yTop, pfChanged);
312 if (!RT_SUCCESS(rc))
313 {
314 WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
315 return rc;
316 }
317
318 crVrScrCompositorRectsInvalidate(pCompositor);
319 }
320
321 VBoxRectMove(&pEntry->Rect, pPos->x, pPos->y);
322 CrVrScrCompositorEntrySetChanged(pEntry, true);
323
324 if (pfChanged)
325 *pfChanged = true;
326 }
327 return VINF_SUCCESS;
328}
329
330static int crVrScrCompositorEntryEnsureRegionsBounds(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool *pfChanged)
331{
332 RTRECT Rect;
333 Rect.xLeft = RT_MAX(pCompositor->Rect.xLeft, pEntry->Rect.xLeft);
334 Rect.yTop = RT_MAX(pCompositor->Rect.yTop, pEntry->Rect.yTop);
335 Rect.xRight = RT_MIN(pCompositor->Rect.xRight, pEntry->Rect.xRight);
336 Rect.yBottom = RT_MIN(pCompositor->Rect.yBottom, pEntry->Rect.yBottom);
337 bool fChanged = false;
338
339 if (pfChanged)
340 *pfChanged = false;
341
342 int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
343 if (!RT_SUCCESS(rc))
344 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
345
346 if (pfChanged)
347 *pfChanged = fChanged;
348 return rc;
349}
350
351VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags)
352{
353 int rc;
354 uint32_t fChangeFlags = 0;
355 bool fPosChanged = false;
356 RTRECT *paTranslatedRects = NULL;
357 if (pPos)
358 {
359 rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
360 if (!RT_SUCCESS(rc))
361 {
362 WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
363 return rc;
364 }
365 }
366
367 if (fPosRelated)
368 {
369 if (!pEntry)
370 {
371 WARN(("Entry is expected to be specified for pos-related regions"));
372 return VERR_INVALID_PARAMETER;
373 }
374
375 if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
376 {
377 paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
378 if (!paTranslatedRects)
379 {
380 WARN(("RTMemAlloc failed"));
381 return VERR_NO_MEMORY;
382 }
383 memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
384 for (uint32_t i = 0; i < cRegions; ++i)
385 {
386 VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
387 paRegions = paTranslatedRects;
388 }
389 }
390 }
391
392 rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
393 if (!RT_SUCCESS(rc))
394 {
395 WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
396 goto done;
397 }
398
399 if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
400 {
401 bool fAdjusted = false;
402 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, &fAdjusted);
403 if (!RT_SUCCESS(rc))
404 {
405 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
406 goto done;
407 }
408
409 if (fAdjusted)
410 {
411 fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
412 fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
413 }
414 }
415
416 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
417 fPosChanged = false;
418 else if (ppReplacedScrEntry)
419 *ppReplacedScrEntry = NULL;
420
421 if (pfChangeFlags)
422 {
423 if (fPosChanged)
424 {
425 /* means entry was in list and was moved, so regions changed */
426 *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
427 }
428 else
429 *pfChangeFlags = fChangeFlags;
430 }
431
432done:
433
434 if (paTranslatedRects)
435 RTMemFree(paTranslatedRects);
436
437 return rc;
438}
439
440VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect)
441{
442 if (!memcmp(&pEntry->Rect, pRect, sizeof (*pRect)))
443 {
444 return VINF_SUCCESS;
445 }
446 RTPOINT Point = {pRect->xLeft, pRect->yTop};
447 bool fChanged = false;
448 int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, &Point, &fChanged);
449 if (!RT_SUCCESS(rc))
450 {
451 WARN(("crVrScrCompositorEntryPositionSet failed %d", rc));
452 return rc;
453 }
454
455 pEntry->Rect = *pRect;
456
457 if (!CrVrScrCompositorEntryIsUsed(pEntry))
458 return VINF_SUCCESS;
459
460 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
461 if (!RT_SUCCESS(rc))
462 {
463 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
464 return rc;
465 }
466
467 return VINF_SUCCESS;
468}
469
470VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex)
471{
472 if (pEntry->pTex == pTex)
473 return VINF_SUCCESS;
474
475 if (pEntry->pTex)
476 CrTdRelease(pEntry->pTex);
477 if (pTex)
478 CrTdAddRef(pTex);
479 pEntry->pTex = pTex;
480 return VINF_SUCCESS;
481}
482
483VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged)
484{
485 /* @todo: the fChanged sate calculation is really rough now, this is enough for now though */
486 bool fChanged = false, fPosChanged = false;
487 bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
488 RTRECT *paTranslatedRects = NULL;
489 int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
490 if (!RT_SUCCESS(rc))
491 {
492 WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
493 return rc;
494 }
495
496 if (pPos)
497 {
498 rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
499 if (!RT_SUCCESS(rc))
500 {
501 WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
502 return rc;
503 }
504 }
505
506 if (fPosRelated)
507 {
508 if (!pEntry)
509 {
510 WARN(("Entry is expected to be specified for pos-related regions"));
511 return VERR_INVALID_PARAMETER;
512 }
513
514 if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
515 {
516 paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
517 if (!paTranslatedRects)
518 {
519 WARN(("RTMemAlloc failed"));
520 return VERR_NO_MEMORY;
521 }
522 memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
523 for (uint32_t i = 0; i < cRegions; ++i)
524 {
525 VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
526 paRegions = paTranslatedRects;
527 }
528 }
529 }
530
531 rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
532 if (!RT_SUCCESS(rc))
533 {
534 WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
535 return rc;
536 }
537
538 if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
539 {
540 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
541 if (!RT_SUCCESS(rc))
542 {
543 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
544 return rc;
545 }
546 }
547
548 if (pfChanged)
549 *pfChanged = fPosChanged || fChanged || fWasInList;
550
551 return VINF_SUCCESS;
552}
553
554VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
555{
556 bool fChanged = false;
557 int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
558 if (!RT_SUCCESS(rc))
559 {
560 WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
561 return rc;
562 }
563
564 if (fChanged)
565 {
566 CrVrScrCompositorEntrySetChanged(pEntry, true);
567 crVrScrCompositorRectsInvalidate(pCompositor);
568 }
569
570 if (pfChanged)
571 *pfChanged = fChanged;
572
573 return VINF_SUCCESS;
574}
575
576VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
577{
578 bool fChanged = false;
579 int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
580 if (!RT_SUCCESS(rc))
581 {
582 WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
583 return rc;
584 }
585
586 if (fChanged)
587 crVrScrCompositorRectsInvalidate(pCompositor);
588
589 if (pfChanged)
590 *pfChanged = fChanged;
591
592 return VINF_SUCCESS;
593}
594
595VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
596{
597 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
598 CrVrScrCompositorIterInit(pCompositor, &Iter);
599 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
600 int rc = VINF_SUCCESS;
601 bool fChanged = false;
602
603 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
604 {
605 bool fTmpChanged = false;
606 int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
607 if (RT_SUCCESS(tmpRc))
608 {
609 fChanged |= fTmpChanged;
610 }
611 else
612 {
613 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
614 rc = tmpRc;
615 }
616 }
617
618 if (pfChanged)
619 *pfChanged = fChanged;
620
621 return rc;
622}
623
624VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
625{
626 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
627 CrVrScrCompositorIterInit(pCompositor, &Iter);
628 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
629 int rc = VINF_SUCCESS;
630 bool fChanged = false;
631
632 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
633 {
634 bool fTmpChanged = false;
635 int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
636 if (RT_SUCCESS(tmpRc))
637 {
638 fChanged |= fTmpChanged;
639 }
640 else
641 {
642 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
643 rc = tmpRc;
644 }
645 }
646
647 if (pfChanged)
648 *pfChanged = fChanged;
649
650 return rc;
651}
652
653VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos)
654{
655 int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
656 if (!RT_SUCCESS(rc))
657 {
658 WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
659 return rc;
660 }
661
662 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
663 if (!RT_SUCCESS(rc))
664 {
665 WARN(("RegionsSet: crVrScrCompositorEntryEnsureRegionsBounds failed rc %d", rc));
666 return rc;
667 }
668
669 return VINF_SUCCESS;
670}
671
672/* regions are valid until the next CrVrScrCompositor call */
673VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
674{
675 if (CrVrScrCompositorEntryIsUsed(pEntry))
676 {
677 int rc = crVrScrCompositorRectsCheckInit(pCompositor);
678 if (!RT_SUCCESS(rc))
679 {
680 WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
681 return rc;
682 }
683 }
684
685 Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
686
687 *pcRegions = pEntry->cRects;
688 if (ppaSrcRegions)
689 *ppaSrcRegions = pEntry->paSrcRects;
690 if (ppaDstRegions)
691 *ppaDstRegions = pEntry->paDstRects;
692 if (ppaDstUnstretchedRects)
693 *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
694
695 return VINF_SUCCESS;
696}
697
698VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
699{
700 return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
701}
702
703VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
704{
705 if (pEntry->fFlags == fFlags)
706 return;
707
708 pEntry->fFlags = fFlags;
709 CrVrScrCompositorEntrySetChanged(pEntry, true);
710}
711
712static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
713{
714 pEntry->cRects = 0;
715 pEntry->paSrcRects = NULL;
716 pEntry->paDstRects = NULL;
717 pEntry->paDstUnstretchedRects = NULL;
718}
719
720static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
721{
722 pToEntry->cRects = pEntry->cRects;
723 pToEntry->paSrcRects = pEntry->paSrcRects;
724 pToEntry->paDstRects = pEntry->paDstRects;
725 pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
726 crVrScrCompositorEntryDataCleanup(pEntry);
727}
728
729VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
730{
731 if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
732 return VINF_SUCCESS;
733
734 CrVrScrCompositorEntrySetChanged(pEntry, true);
735 crVrScrCompositorEntryDataCleanup(pEntry);
736
737 crVrScrCompositorRectsInvalidate(pCompositor);
738 return VINF_SUCCESS;
739}
740
741VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
742{
743 Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
744
745 if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
746 return false;
747
748 CrVrScrCompositorEntrySetChanged(pEntry, true);
749 crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
750 CrVrScrCompositorEntrySetChanged(pNewEntry, true);
751
752 return true;
753}
754
755static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
756{
757 PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
758
759 CrVrScrCompositorEntrySetChanged(pCEntry, true);
760
761 Assert(!CrVrScrCompositorEntryIsInList(pCEntry));
762
763 if (pReplacingEntry)
764 {
765 PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry);
766 Assert(CrVrScrCompositorEntryIsInList(pCReplacingEntry));
767 pCReplacingEntry->cRects = pCEntry->cRects;
768 pCReplacingEntry->paSrcRects = pCEntry->paSrcRects;
769 pCReplacingEntry->paDstRects = pCEntry->paDstRects;
770 pCReplacingEntry->paDstUnstretchedRects = pCEntry->paDstUnstretchedRects;
771 }
772
773 if (pCEntry->pfnEntryReleased)
774 {
775 PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
776 PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
777 pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
778 }
779}
780
781VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect, bool *pfChanged)
782{
783 if (!memcmp(&pCompositor->Rect, pRect, sizeof (pCompositor->Rect)))
784 {
785 if (pfChanged)
786 *pfChanged = false;
787 return VINF_SUCCESS;
788 }
789
790 pCompositor->Rect = *pRect;
791
792 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
793 CrVrScrCompositorIterInit(pCompositor, &Iter);
794 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
795 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
796 {
797 int rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
798 if (!RT_SUCCESS(rc))
799 {
800 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
801 return rc;
802 }
803 }
804
805 return VINF_SUCCESS;
806}
807
808VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect)
809{
810 memset(pCompositor, 0, sizeof (*pCompositor));
811 VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
812 pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
813 if (pRect)
814 pCompositor->Rect = *pRect;
815#ifndef IN_RING0
816 pCompositor->StretchX = 1.0;
817 pCompositor->StretchY = 1.0;
818#endif
819}
820
821VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
822{
823 /* set changed flag first, while entries are in the list and we have them */
824 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
825 VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
826 crVrScrCompositorRectsInvalidate(pCompositor);
827}
828
829VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
830{
831 CrVrScrCompositorRegionsClear(pCompositor, NULL);
832 if (pCompositor->paDstRects)
833 {
834 RTMemFree(pCompositor->paDstRects);
835 pCompositor->paDstRects = NULL;
836 }
837 if (pCompositor->paSrcRects)
838 {
839 RTMemFree(pCompositor->paSrcRects);
840 pCompositor->paSrcRects = NULL;
841 }
842 if (pCompositor->paDstUnstretchedRects)
843 {
844 RTMemFree(pCompositor->paDstUnstretchedRects);
845 pCompositor->paDstUnstretchedRects = NULL;
846 }
847
848 pCompositor->cRects = 0;
849 pCompositor->cRectsBuffer = 0;
850}
851
852VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
853{
854 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
855 PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
856 CrVrScrCompositorIterInit(pCompositor, &CIter);
857
858 while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
859 {
860 CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
861 }
862}
863
864#ifndef IN_RING0
865VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
866{
867 if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
868 return;
869
870 pCompositor->StretchX = StretchX;
871 pCompositor->StretchY = StretchY;
872 crVrScrCompositorRectsInvalidate(pCompositor);
873 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
874}
875#endif
876
877/* regions are valid until the next CrVrScrCompositor call */
878VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
879{
880 int rc = crVrScrCompositorRectsCheckInit(pCompositor);
881 if (!RT_SUCCESS(rc))
882 {
883 WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
884 return rc;
885 }
886
887 Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
888
889 *pcRegions = pCompositor->cRects;
890 if (ppaSrcRegions)
891 *ppaSrcRegions = pCompositor->paSrcRects;
892 if (ppaDstRegions)
893 *ppaDstRegions = pCompositor->paDstRects;
894 if (ppaDstUnstretchedRects)
895 *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
896
897 return VINF_SUCCESS;
898}
899
900typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
901{
902 PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
903 void *pvVisitor;
904} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
905
906static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
907{
908 PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
909 PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
910 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
911 return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
912}
913
914VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
915{
916 VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
917 Data.pfnVisitor = pfnVisitor;
918 Data.pvVisitor = pvVisitor;
919 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
920}
921
922VBOXVREGDECL(int) CrVrScrCompositorClone(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor)
923{
924 /* for simplicity just copy from one to another */
925 CrVrScrCompositorInit(pDstCompositor, CrVrScrCompositorRectGet(pCompositor));
926 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
927 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
928 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
929 int rc = VINF_SUCCESS;
930 uint32_t cRects;
931 const RTRECT *pRects;
932
933 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
934 {
935 /* get source rects, that will be non-stretched and entry pos - pased */
936 rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &pRects);
937 if (!RT_SUCCESS(rc))
938 {
939 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
940 return rc;
941 }
942
943 PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
944 if (!pDstEntry)
945 {
946 WARN(("pfnEntryFor failed"));
947 return VERR_INVALID_STATE;
948 }
949
950 rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, NULL, cRects, pRects, false, NULL);
951 if (!RT_SUCCESS(rc))
952 {
953 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
954 return rc;
955 }
956 }
957
958 return rc;
959}
960
961VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged)
962{
963 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
964 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
965 CrVrScrCompositorIterInit(pCompositor, &CIter);
966 int rc = VINF_SUCCESS;
967 bool fChanged = false;
968
969 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
970 {
971 bool fCurChanged = false;
972
973 rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
974 if (!RT_SUCCESS(rc))
975 {
976 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
977 break;
978 }
979
980 fChanged |= fCurChanged;
981 }
982
983 if (pfChanged)
984 *pfChanged = fChanged;
985
986 return rc;
987}
988
989VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged)
990{
991 int rc = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
992 if (!RT_SUCCESS(rc))
993 {
994 WARN(("CrVrScrCompositorClone failed, rc %d", rc));
995 return rc;
996 }
997
998 rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
999 if (!RT_SUCCESS(rc))
1000 {
1001 WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
1002 CrVrScrCompositorClear(pDstCompositor);
1003 return rc;
1004 }
1005
1006 return VINF_SUCCESS;
1007}
1008
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