VirtualBox

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

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

Host 3D: prepare for content scaling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: window.cpp 53814 2015-01-15 11:00:51Z 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 mScaleFactorStorage(1)
32{
33 mFlags.Value = 0;
34}
35
36
37bool CrFbWindow::IsCreated() const
38{
39 return !!mSpuWindow;
40}
41
42bool CrFbWindow::IsVisivle() const
43{
44 return mFlags.fVisible;
45}
46
47
48void CrFbWindow::Destroy()
49{
50 CRASSERT(!mcUpdates);
51
52 if (!mSpuWindow)
53 return;
54
55 cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
56
57 mSpuWindow = 0;
58 mFlags.fDataPresented = 0;
59}
60
61
62int CrFbWindow::Reparent(uint64_t parentId)
63{
64 if (!checkInitedUpdating())
65 {
66 WARN(("err"));
67 return VERR_INVALID_STATE;
68 }
69
70 crDebug("CrFbWindow: reparent to %p (current mxPos=%d, myPos=%d, mWidth=%u, mHeight=%u)",
71 parentId, mxPos, myPos, mWidth, mHeight);
72
73 uint64_t oldParentId = mParentId;
74
75 mParentId = parentId;
76
77 if (mSpuWindow)
78 {
79 if (oldParentId && !parentId && mFlags.fVisible)
80 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
81
82 renderspuSetWindowId(mParentId);
83 renderspuReparentWindow(mSpuWindow);
84 renderspuSetWindowId(cr_server.screen[0].winID);
85
86 if (parentId)
87 {
88 if (mFlags.fVisible)
89 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
90 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
91 }
92 }
93
94 return VINF_SUCCESS;
95}
96
97
98int CrFbWindow::SetVisible(bool fVisible)
99{
100 if (!checkInitedUpdating())
101 {
102 WARN(("err"));
103 return VERR_INVALID_STATE;
104 }
105
106 LOG(("CrWIN: Visible [%d]", fVisible));
107
108 if (!fVisible != !mFlags.fVisible)
109 {
110 mFlags.fVisible = fVisible;
111 if (mSpuWindow && mParentId)
112 {
113 if (fVisible)
114 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
115 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
116 }
117 }
118
119 return VINF_SUCCESS;
120}
121
122
123int CrFbWindow::SetSize(uint32_t width, uint32_t height)
124{
125 if (!checkInitedUpdating())
126 {
127 WARN(("err"));
128 return VERR_INVALID_STATE;
129 }
130
131 if (mWidth != width || mHeight != height)
132 {
133 GLdouble scaleFactor = GetScaleFactor();
134
135 mFlags.fCompositoEntriesModified = 1;
136 mWidth = scaleFactor ? (uint32_t)((GLdouble)width * scaleFactor) : width;
137 mHeight = scaleFactor ? (uint32_t)((GLdouble)height * scaleFactor) : height;
138
139 LOG(("CrWIN: Size [%d ; %d]", width, height));
140
141 if (mSpuWindow)
142 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
143 }
144
145 return VINF_SUCCESS;
146}
147
148
149int CrFbWindow::SetPosition(int32_t x, int32_t y)
150{
151 if (!checkInitedUpdating())
152 {
153 WARN(("err"));
154 return VERR_INVALID_STATE;
155 }
156
157 LOG(("CrWIN: Pos [%d ; %d]", x, y));
158// always do WindowPosition to ensure window is adjusted properly
159// if (x != mxPos || y != myPos)
160 {
161 mxPos = x;
162 myPos = y;
163 if (mSpuWindow)
164 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
165 }
166
167 return VINF_SUCCESS;
168}
169
170
171int CrFbWindow::SetVisibleRegionsChanged()
172{
173 if (!checkInitedUpdating())
174 {
175 WARN(("err"));
176 return VERR_INVALID_STATE;
177 }
178
179 mFlags.fCompositoEntriesModified = 1;
180 return VINF_SUCCESS;
181}
182
183
184int CrFbWindow::SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
185{
186 if (!checkInitedUpdating())
187 {
188 WARN(("err"));
189 return VERR_INVALID_STATE;
190 }
191
192 mpCompositor = pCompositor;
193 mFlags.fCompositoEntriesModified = 1;
194
195 return VINF_SUCCESS;
196}
197
198
199void CrFbWindow::SetScaleFactor(GLdouble scaleFactor)
200{
201 ASMAtomicWriteU32(&mScaleFactorStorage, (uint32_t)scaleFactor);
202}
203
204
205GLdouble CrFbWindow::GetScaleFactor()
206{
207 return (GLdouble)ASMAtomicReadU32(&mScaleFactorStorage);
208}
209
210
211int CrFbWindow::UpdateBegin()
212{
213 ++mcUpdates;
214 if (mcUpdates > 1)
215 return VINF_SUCCESS;
216
217 Assert(!mFlags.fForcePresentOnReenable);
218
219 if (mFlags.fDataPresented)
220 {
221 Assert(mSpuWindow);
222 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
223 mFlags.fForcePresentOnReenable = isPresentNeeded();
224 }
225
226 return VINF_SUCCESS;
227}
228
229
230void CrFbWindow::UpdateEnd()
231{
232 --mcUpdates;
233 Assert(mcUpdates < UINT32_MAX/2);
234 if (mcUpdates)
235 return;
236
237 checkRegions();
238
239 if (mSpuWindow)
240 {
241 bool fPresentNeeded = isPresentNeeded();
242 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
243 {
244 GLdouble scaleFactor = GetScaleFactor();
245
246 mFlags.fForcePresentOnReenable = false;
247 if (mpCompositor)
248 {
249 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)mpCompositor, scaleFactor, scaleFactor);
250 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
251 }
252 else
253 {
254 VBOXVR_SCR_COMPOSITOR TmpCompositor;
255 RTRECT Rect;
256 Rect.xLeft = 0;
257 Rect.yTop = 0;
258 Rect.xRight = mWidth;
259 Rect.yBottom = mHeight;
260 CrVrScrCompositorInit(&TmpCompositor, &Rect);
261 CrVrScrCompositorSetStretching((VBOXVR_SCR_COMPOSITOR *)&TmpCompositor, scaleFactor, scaleFactor);
262 /* this is a cleanup operation
263 * empty compositor is guarantid to be released on VBoxPresentComposition return */
264 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
265 }
266 g_pLed->Asserted.s.fWriting = 1;
267 }
268
269 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
270 * the backend should clean up the compositor as soon as presentation is performed */
271 mFlags.fDataPresented = fPresentNeeded;
272 }
273 else
274 {
275 Assert(!mFlags.fDataPresented);
276 Assert(!mFlags.fForcePresentOnReenable);
277 }
278}
279
280
281uint64_t CrFbWindow::GetParentId()
282{
283 return mParentId;
284}
285
286
287int CrFbWindow::Create()
288{
289 if (mSpuWindow)
290 {
291 //WARN(("window already created"));
292 return VINF_ALREADY_INITIALIZED;
293 }
294
295 CRASSERT(cr_server.fVisualBitsDefault);
296 renderspuSetWindowId(mParentId);
297 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
298 renderspuSetWindowId(cr_server.screen[0].winID);
299 if (mSpuWindow < 0) {
300 WARN(("WindowCreate failed"));
301 return VERR_GENERAL_FAILURE;
302 }
303
304 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
305 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
306
307 checkRegions();
308
309 if (mParentId && mFlags.fVisible)
310 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
311
312 return VINF_SUCCESS;
313}
314
315
316CrFbWindow::~CrFbWindow()
317{
318 Destroy();
319}
320
321
322void CrFbWindow::checkRegions()
323{
324 if (!mSpuWindow)
325 return;
326
327 if (!mFlags.fCompositoEntriesModified)
328 return;
329
330 uint32_t cRects;
331 const RTRECT *pRects;
332 if (mpCompositor)
333 {
334 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
335 if (!RT_SUCCESS(rc))
336 {
337 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
338 cRects = 0;
339 pRects = NULL;
340 }
341 }
342 else
343 {
344 cRects = 0;
345 pRects = NULL;
346 }
347
348 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
349
350 mFlags.fCompositoEntriesModified = 0;
351}
352
353
354bool CrFbWindow::isPresentNeeded()
355{
356 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
357}
358
359
360bool CrFbWindow::checkInitedUpdating()
361{
362 if (!mcUpdates)
363 {
364 WARN(("not updating"));
365 return false;
366 }
367
368 return true;
369}
370
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