VirtualBox

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

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

3D: scaling: add simple check for input values to scale factor setter.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: window.cpp 53817 2015-01-15 12:06:52Z 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
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)
131{
132 if (!checkInitedUpdating())
133 {
134 WARN(("err"));
135 return VERR_INVALID_STATE;
136 }
137
138 if (mWidth != width || mHeight != height)
139 {
140 GLdouble scaleFactorW, scaleFactorH;
141
142 /* Reset to default values if operation was unsuccessfull. */
143 if (!GetScaleFactor(&scaleFactorW, &scaleFactorH))
144 scaleFactorW = scaleFactorH = 1.0;
145
146 mFlags.fCompositoEntriesModified = 1;
147 mWidth = scaleFactorW ? (uint32_t)((GLdouble)width * scaleFactorW) : width;
148 mHeight = scaleFactorH ? (uint32_t)((GLdouble)height * scaleFactorH) : height;
149
150 LOG(("CrWIN: Size [%d ; %d]", width, height));
151
152 if (mSpuWindow)
153 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
154 }
155
156 return VINF_SUCCESS;
157}
158
159
160int CrFbWindow::SetPosition(int32_t x, int32_t y)
161{
162 if (!checkInitedUpdating())
163 {
164 WARN(("err"));
165 return VERR_INVALID_STATE;
166 }
167
168 LOG(("CrWIN: Pos [%d ; %d]", x, y));
169// always do WindowPosition to ensure window is adjusted properly
170// if (x != mxPos || y != myPos)
171 {
172 mxPos = x;
173 myPos = y;
174 if (mSpuWindow)
175 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
176 }
177
178 return VINF_SUCCESS;
179}
180
181
182int CrFbWindow::SetVisibleRegionsChanged()
183{
184 if (!checkInitedUpdating())
185 {
186 WARN(("err"));
187 return VERR_INVALID_STATE;
188 }
189
190 mFlags.fCompositoEntriesModified = 1;
191 return VINF_SUCCESS;
192}
193
194
195int CrFbWindow::SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
196{
197 if (!checkInitedUpdating())
198 {
199 WARN(("err"));
200 return VERR_INVALID_STATE;
201 }
202
203 mpCompositor = pCompositor;
204 mFlags.fCompositoEntriesModified = 1;
205
206 return VINF_SUCCESS;
207}
208
209
210bool CrFbWindow::SetScaleFactor(GLdouble scaleFactorW, GLdouble scaleFactorH)
211{
212 int rc;
213
214 /* Simple check for input values. */
215 if ( !(scaleFactorW > 0 && scaleFactorW > 0) )
216 return false;
217
218 rc = RTSemRWRequestWrite(scaleFactorLock, RT_INDEFINITE_WAIT);
219 if (RT_SUCCESS(rc))
220 {
221 mScaleFactorWStorage = scaleFactorW;
222 mScaleFactorHStorage = scaleFactorH;
223 RTSemRWReleaseWrite(scaleFactorLock);
224 return true;
225 }
226
227 return false;
228}
229
230
231bool CrFbWindow::GetScaleFactor(GLdouble *scaleFactorW, GLdouble *scaleFactorH)
232{
233 int rc;
234
235 rc = RTSemRWRequestRead(scaleFactorLock, RT_INDEFINITE_WAIT);
236 if (RT_SUCCESS(rc))
237 {
238 *scaleFactorW = mScaleFactorWStorage;
239 *scaleFactorH = mScaleFactorHStorage;
240 RTSemRWReleaseRead(scaleFactorLock);
241 return true;
242 }
243
244 return false;
245}
246
247
248int CrFbWindow::UpdateBegin()
249{
250 ++mcUpdates;
251 if (mcUpdates > 1)
252 return VINF_SUCCESS;
253
254 Assert(!mFlags.fForcePresentOnReenable);
255
256 if (mFlags.fDataPresented)
257 {
258 Assert(mSpuWindow);
259 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
260 mFlags.fForcePresentOnReenable = isPresentNeeded();
261 }
262
263 return VINF_SUCCESS;
264}
265
266
267void CrFbWindow::UpdateEnd()
268{
269 --mcUpdates;
270 Assert(mcUpdates < UINT32_MAX/2);
271 if (mcUpdates)
272 return;
273
274 checkRegions();
275
276 if (mSpuWindow)
277 {
278 bool fPresentNeeded = isPresentNeeded();
279 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
280 {
281 GLdouble scaleFactorW, scaleFactorH;
282 /* Reset to default values if operation was unseccessfull. */
283 if (!GetScaleFactor(&scaleFactorW, &scaleFactorH))
284 scaleFactorW = scaleFactorH = 1.0;
285
286 mFlags.fForcePresentOnReenable = false;
287 if (mpCompositor)
288 {
289 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)mpCompositor, scaleFactorW, scaleFactorH);
290 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
291 }
292 else
293 {
294 VBOXVR_SCR_COMPOSITOR TmpCompositor;
295 RTRECT Rect;
296 Rect.xLeft = 0;
297 Rect.yTop = 0;
298 Rect.xRight = mWidth;
299 Rect.yBottom = mHeight;
300 CrVrScrCompositorInit(&TmpCompositor, &Rect);
301 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)&TmpCompositor, scaleFactorW, scaleFactorH);
302 /* this is a cleanup operation
303 * empty compositor is guarantid to be released on VBoxPresentComposition return */
304 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
305 }
306 g_pLed->Asserted.s.fWriting = 1;
307 }
308
309 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
310 * the backend should clean up the compositor as soon as presentation is performed */
311 mFlags.fDataPresented = fPresentNeeded;
312 }
313 else
314 {
315 Assert(!mFlags.fDataPresented);
316 Assert(!mFlags.fForcePresentOnReenable);
317 }
318}
319
320
321uint64_t CrFbWindow::GetParentId()
322{
323 return mParentId;
324}
325
326
327int CrFbWindow::Create()
328{
329 if (mSpuWindow)
330 {
331 //WARN(("window already created"));
332 return VINF_ALREADY_INITIALIZED;
333 }
334
335 CRASSERT(cr_server.fVisualBitsDefault);
336 renderspuSetWindowId(mParentId);
337 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
338 renderspuSetWindowId(cr_server.screen[0].winID);
339 if (mSpuWindow < 0) {
340 WARN(("WindowCreate failed"));
341 return VERR_GENERAL_FAILURE;
342 }
343
344 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
345 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
346
347 checkRegions();
348
349 if (mParentId && mFlags.fVisible)
350 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
351
352 return VINF_SUCCESS;
353}
354
355
356CrFbWindow::~CrFbWindow()
357{
358 int rc;
359
360 Destroy();
361
362 rc = RTSemRWDestroy(scaleFactorLock);
363 if (!RT_SUCCESS(rc))
364 WARN(("Unable to release scaling factor data lock."));
365}
366
367
368void CrFbWindow::checkRegions()
369{
370 if (!mSpuWindow)
371 return;
372
373 if (!mFlags.fCompositoEntriesModified)
374 return;
375
376 uint32_t cRects;
377 const RTRECT *pRects;
378 if (mpCompositor)
379 {
380 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
381 if (!RT_SUCCESS(rc))
382 {
383 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
384 cRects = 0;
385 pRects = NULL;
386 }
387 }
388 else
389 {
390 cRects = 0;
391 pRects = NULL;
392 }
393
394 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
395
396 mFlags.fCompositoEntriesModified = 0;
397}
398
399
400bool CrFbWindow::isPresentNeeded()
401{
402 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
403}
404
405
406bool CrFbWindow::checkInitedUpdating()
407{
408 if (!mcUpdates)
409 {
410 WARN(("not updating"));
411 return false;
412 }
413
414 return true;
415}
416
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