VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/window.cpp@ 54026

Last change on this file since 54026 was 54026, checked in by vboxsync, 10 years ago

Host 3D: scaling: reduce number of runtime warnings/assertions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/* $Id: window.cpp 54026 2015-01-29 08:33:49Z vboxsync $ */
2
3/** @file
4 * Presenter API: window class implementation.
5 */
6
7/*
8 * Copyright (C) 2014 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
19#include "server_presenter.h"
20#include <VBox/VBoxOGL.h>
21
22CrFbWindow::CrFbWindow(uint64_t parentId) :
23 mSpuWindow(0),
24 mpCompositor(NULL),
25 mcUpdates(0),
26 mxPos(0),
27 myPos(0),
28 mWidth(0),
29 mHeight(0),
30 mParentId(parentId),
31 mScaleFactorWStorage(1.0),
32 mScaleFactorHStorage(1.0)
33{
34 int rc;
35
36 mFlags.Value = 0;
37
38 rc = RTSemRWCreate(&scaleFactorLock);
39 if (!RT_SUCCESS(rc))
40 WARN(("Unable to initialize scaling factor data lock."));
41}
42
43
44bool CrFbWindow::IsCreated() const
45{
46 return !!mSpuWindow;
47}
48
49bool CrFbWindow::IsVisivle() const
50{
51 return mFlags.fVisible;
52}
53
54
55void CrFbWindow::Destroy()
56{
57 CRASSERT(!mcUpdates);
58
59 if (!mSpuWindow)
60 return;
61
62 cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
63
64 mSpuWindow = 0;
65 mFlags.fDataPresented = 0;
66}
67
68
69int CrFbWindow::Reparent(uint64_t parentId)
70{
71 if (!checkInitedUpdating())
72 {
73 WARN(("err"));
74 return VERR_INVALID_STATE;
75 }
76
77 crDebug("CrFbWindow: reparent to %p (current mxPos=%d, myPos=%d, mWidth=%u, mHeight=%u)",
78 parentId, mxPos, myPos, mWidth, mHeight);
79
80 uint64_t oldParentId = mParentId;
81
82 mParentId = parentId;
83
84 if (mSpuWindow)
85 {
86 if (oldParentId && !parentId && mFlags.fVisible)
87 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
88
89 renderspuSetWindowId(mParentId);
90 renderspuReparentWindow(mSpuWindow);
91 renderspuSetWindowId(cr_server.screen[0].winID);
92
93 if (parentId)
94 {
95 if (mFlags.fVisible)
96 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
97 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
98 }
99 }
100
101 return VINF_SUCCESS;
102}
103
104
105int CrFbWindow::SetVisible(bool fVisible)
106{
107 if (!checkInitedUpdating())
108 {
109 WARN(("err"));
110 return VERR_INVALID_STATE;
111 }
112
113 LOG(("CrWIN: Visible [%d]", fVisible));
114
115 if (!fVisible != !mFlags.fVisible)
116 {
117 mFlags.fVisible = fVisible;
118 if (mSpuWindow && mParentId)
119 {
120 if (fVisible)
121 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
122 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
123 }
124 }
125
126 return VINF_SUCCESS;
127}
128
129
130int CrFbWindow::SetSize(uint32_t width, uint32_t height, bool fForced)
131{
132 if (!fForced && !checkInitedUpdating())
133 {
134 crDebug("CrFbWindow: SetSize request dropped because window is currently updating"
135 "(width=%d, height=%d, mWidth=%d, mHeight=%d).", width, height, mWidth, mHeight);
136 return VERR_INVALID_STATE;
137 }
138
139 if (mWidth != width || mHeight != height || fForced)
140 {
141 GLdouble scaleFactorW, scaleFactorH;
142 uint32_t scaledWidth, scaledHeight;
143
144 /* Reset to default values if operation was unsuccessfull. */
145 if (!GetScaleFactor(&scaleFactorW, &scaleFactorH))
146 scaleFactorW = scaleFactorH = 1.0;
147
148 mFlags.fCompositoEntriesModified = 1;
149
150 /* Keep mWidth and mHeight unchanged (not multiplied by scale factor scalar). */
151 mWidth = width;
152 mHeight = height;
153
154 scaledWidth = (uint32_t)((GLdouble)width * scaleFactorW);
155 scaledHeight = (uint32_t)((GLdouble)height * scaleFactorH);
156
157 if (mSpuWindow)
158 {
159 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, scaledWidth, scaledHeight);
160 crDebug("CrFbWindow: SetSize request performed successfully "
161 "(width=%d, height=%d, scaledWidth=%d, scaledHeight=%d).", width, height, scaledWidth, scaledHeight);
162 }
163 else
164 crDebug("CrFbWindow: SetSize request skipped because mSpuWindow not yet constructed "
165 "(width=%d, height=%d, scaledWidth=%d, scaledHeight=%d).", width, height, scaledWidth, scaledHeight);
166 }
167 else
168 crDebug("CrFbWindow: SetSize request skipped because window arleady has requested size "
169 "(width=%d, height=%d, mWidth=%d, mHeight=%d).", width, height, mWidth, mHeight);
170
171 return VINF_SUCCESS;
172}
173
174
175int CrFbWindow::SetPosition(int32_t x, int32_t y)
176{
177 if (!checkInitedUpdating())
178 {
179 crDebug("CrFbWindow: SetPosition request dropped because window is currently updating (x=%d, y=%d).", x, y);
180 return VERR_INVALID_STATE;
181 }
182
183 LOG(("CrWIN: Pos [%d ; %d]", x, y));
184// always do WindowPosition to ensure window is adjusted properly
185// if (x != mxPos || y != myPos)
186 {
187 mxPos = x;
188 myPos = y;
189 if (mSpuWindow)
190 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
191 crDebug("CrFbWindow: SetPosition performed successfully (x=%d, y=%d).", x, y);
192 }
193
194 return VINF_SUCCESS;
195}
196
197
198int CrFbWindow::SetVisibleRegionsChanged()
199{
200 if (!checkInitedUpdating())
201 {
202 WARN(("err"));
203 return VERR_INVALID_STATE;
204 }
205
206 mFlags.fCompositoEntriesModified = 1;
207 return VINF_SUCCESS;
208}
209
210
211int CrFbWindow::SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
212{
213 if (!checkInitedUpdating())
214 {
215 WARN(("err"));
216 return VERR_INVALID_STATE;
217 }
218
219 mpCompositor = pCompositor;
220 mFlags.fCompositoEntriesModified = 1;
221
222 return VINF_SUCCESS;
223}
224
225
226bool CrFbWindow::SetScaleFactor(GLdouble scaleFactorW, GLdouble scaleFactorH)
227{
228 int rc;
229
230 /* Simple check for input values. */
231 if ( !( (scaleFactorW >= VBOX_OGL_SCALE_FACTOR_MIN && scaleFactorW <= VBOX_OGL_SCALE_FACTOR_MAX)
232 && (scaleFactorH >= VBOX_OGL_SCALE_FACTOR_MIN && scaleFactorH <= VBOX_OGL_SCALE_FACTOR_MAX)))
233 {
234 crDebug("CrFbWindow: attempt to set scale factor out of valid values range: scaleFactorW=%d, scaleFactorH=%d, multiplier=%d.",
235 (int)(scaleFactorW * VBOX_OGL_SCALE_FACTOR_MULTIPLIER), (int)(scaleFactorH * VBOX_OGL_SCALE_FACTOR_MULTIPLIER),
236 (int)VBOX_OGL_SCALE_FACTOR_MULTIPLIER);
237
238 return false;
239 }
240
241 rc = RTSemRWRequestWrite(scaleFactorLock, RT_INDEFINITE_WAIT);
242 if (RT_SUCCESS(rc))
243 {
244 mScaleFactorWStorage = scaleFactorW;
245 mScaleFactorHStorage = scaleFactorH;
246 RTSemRWReleaseWrite(scaleFactorLock);
247
248 crDebug("CrFbWindow: set scale factor: scaleFactorW=%d, scaleFactorH=%d, multiplier=%d.",
249 (int)(scaleFactorW * VBOX_OGL_SCALE_FACTOR_MULTIPLIER), (int)(scaleFactorH * VBOX_OGL_SCALE_FACTOR_MULTIPLIER),
250 (int)VBOX_OGL_SCALE_FACTOR_MULTIPLIER);
251
252 /* Update window geometry. Do not wait for GAs to send SetSize() and SetPosition()
253 * events since they might not be running or installed at all. */
254 SetSize(mWidth, mHeight, true);
255 SetPosition(mxPos, myPos);
256
257 return true;
258 }
259
260 crDebug("CrFbWindow: unable to set scale factor because RW lock cannot be aquired: scaleFactorW=%d, scaleFactorH=%d, multiplier=%d.",
261 (int)(scaleFactorW * VBOX_OGL_SCALE_FACTOR_MULTIPLIER), (int)(scaleFactorH * VBOX_OGL_SCALE_FACTOR_MULTIPLIER),
262 (int)VBOX_OGL_SCALE_FACTOR_MULTIPLIER);
263
264 return false;
265}
266
267
268bool CrFbWindow::GetScaleFactor(GLdouble *scaleFactorW, GLdouble *scaleFactorH)
269{
270 int rc;
271
272 rc = RTSemRWRequestRead(scaleFactorLock, RT_INDEFINITE_WAIT);
273 if (RT_SUCCESS(rc))
274 {
275 *scaleFactorW = mScaleFactorWStorage;
276 *scaleFactorH = mScaleFactorHStorage;
277 RTSemRWReleaseRead(scaleFactorLock);
278 return true;
279 }
280
281 return false;
282}
283
284
285int CrFbWindow::UpdateBegin()
286{
287 ++mcUpdates;
288 if (mcUpdates > 1)
289 return VINF_SUCCESS;
290
291 Assert(!mFlags.fForcePresentOnReenable);
292
293 if (mFlags.fDataPresented)
294 {
295 Assert(mSpuWindow);
296 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
297 mFlags.fForcePresentOnReenable = isPresentNeeded();
298 }
299
300 return VINF_SUCCESS;
301}
302
303
304void CrFbWindow::UpdateEnd()
305{
306 --mcUpdates;
307 Assert(mcUpdates < UINT32_MAX/2);
308 if (mcUpdates)
309 return;
310
311 checkRegions();
312
313 if (mSpuWindow)
314 {
315 bool fPresentNeeded = isPresentNeeded();
316 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
317 {
318 GLdouble scaleFactorW, scaleFactorH;
319 /* Reset to default values if operation was unseccessfull. */
320 if (!GetScaleFactor(&scaleFactorW, &scaleFactorH))
321 scaleFactorW = scaleFactorH = 1.0;
322
323 mFlags.fForcePresentOnReenable = false;
324 if (mpCompositor)
325 {
326 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)mpCompositor, scaleFactorW, scaleFactorH);
327 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
328 }
329 else
330 {
331 VBOXVR_SCR_COMPOSITOR TmpCompositor;
332 RTRECT Rect;
333 Rect.xLeft = 0;
334 Rect.yTop = 0;
335 Rect.xRight = (uint32_t)((GLdouble)mWidth * scaleFactorW);
336 Rect.yBottom = (uint32_t)((GLdouble)mHeight * scaleFactorH);
337 CrVrScrCompositorInit(&TmpCompositor, &Rect);
338 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)&TmpCompositor, scaleFactorW, scaleFactorH);
339 /* this is a cleanup operation
340 * empty compositor is guarantid to be released on VBoxPresentComposition return */
341 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
342 }
343 g_pLed->Asserted.s.fWriting = 1;
344 }
345
346 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
347 * the backend should clean up the compositor as soon as presentation is performed */
348 mFlags.fDataPresented = fPresentNeeded;
349 }
350 else
351 {
352 Assert(!mFlags.fDataPresented);
353 Assert(!mFlags.fForcePresentOnReenable);
354 }
355}
356
357
358uint64_t CrFbWindow::GetParentId()
359{
360 return mParentId;
361}
362
363
364int CrFbWindow::Create()
365{
366 if (mSpuWindow)
367 {
368 //WARN(("window already created"));
369 return VINF_ALREADY_INITIALIZED;
370 }
371
372 CRASSERT(cr_server.fVisualBitsDefault);
373 renderspuSetWindowId(mParentId);
374 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
375 renderspuSetWindowId(cr_server.screen[0].winID);
376 if (mSpuWindow < 0) {
377 WARN(("WindowCreate failed"));
378 return VERR_GENERAL_FAILURE;
379 }
380
381 GLdouble scaleFactorW, scaleFactorH;
382 /* Reset to default values if operation was unseccessfull. */
383 if (!GetScaleFactor(&scaleFactorW, &scaleFactorH))
384 scaleFactorW = scaleFactorH = 1.0;
385
386 uint32_t scaledWidth, scaledHeight;
387
388 scaledWidth = (uint32_t)((GLdouble)mWidth * scaleFactorW);
389 scaledHeight = (uint32_t)((GLdouble)mHeight * scaleFactorH);
390
391 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, scaledWidth, scaledHeight);
392 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
393
394 checkRegions();
395
396 if (mParentId && mFlags.fVisible)
397 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
398
399 return VINF_SUCCESS;
400}
401
402
403CrFbWindow::~CrFbWindow()
404{
405 int rc;
406
407 Destroy();
408
409 rc = RTSemRWDestroy(scaleFactorLock);
410 if (!RT_SUCCESS(rc))
411 WARN(("Unable to release scaling factor data lock."));
412}
413
414
415void CrFbWindow::checkRegions()
416{
417 if (!mSpuWindow)
418 return;
419
420 if (!mFlags.fCompositoEntriesModified)
421 return;
422
423 uint32_t cRects;
424 const RTRECT *pRects;
425 if (mpCompositor)
426 {
427 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
428 if (!RT_SUCCESS(rc))
429 {
430 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
431 cRects = 0;
432 pRects = NULL;
433 }
434 }
435 else
436 {
437 cRects = 0;
438 pRects = NULL;
439 }
440
441 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
442
443 mFlags.fCompositoEntriesModified = 0;
444}
445
446
447bool CrFbWindow::isPresentNeeded()
448{
449 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
450}
451
452
453bool CrFbWindow::checkInitedUpdating()
454{
455 if (!mcUpdates)
456 {
457 WARN(("not updating"));
458 return false;
459 }
460
461 return true;
462}
463
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