VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/GraphicsAdapterImpl.cpp

Last change on this file was 101200, checked in by vboxsync, 8 months ago

Main,FE/Qt: Add the QEMU RAM based framebuffer device as a possible graphics controller for ARM platforms. Allows getting graphics output on guests like OpenSuse 15.4 and Oracle Linux 9 which don't have a compatible VSVGA3 device driver, bugref:10386

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1/* $Id: GraphicsAdapterImpl.cpp 101200 2023-09-20 14:14:26Z vboxsync $ */
2/** @file
3 * Implementation of IGraphicsAdapter in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2004-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_GRAPHICSADAPTER
29
30#include "LoggingNew.h"
31
32#include "GraphicsAdapterImpl.h"
33#include "MachineImpl.h"
34
35#include "AutoStateDep.h"
36#include "AutoCaller.h"
37
38#include <iprt/cpp/utils.h>
39
40
41// constructor / destructor
42/////////////////////////////////////////////////////////////////////////////
43
44GraphicsAdapter::GraphicsAdapter() :
45 mParent(NULL)
46{}
47
48GraphicsAdapter::~GraphicsAdapter()
49{}
50
51HRESULT GraphicsAdapter::FinalConstruct()
52{
53 LogFlowThisFunc(("\n"));
54 return BaseFinalConstruct();
55}
56
57void GraphicsAdapter::FinalRelease()
58{
59 LogFlowThisFunc(("\n"));
60 uninit();
61 BaseFinalRelease();
62}
63
64// public initializer/uninitializer for internal purposes only
65/////////////////////////////////////////////////////////////////////////////
66
67/**
68 * Initializes the graphics adapter object.
69 *
70 * @param aParent Handle of the parent object.
71 */
72HRESULT GraphicsAdapter::init(Machine *aParent)
73{
74 LogFlowThisFunc(("aParent=%p\n", aParent));
75
76 ComAssertRet(aParent, E_INVALIDARG);
77
78 /* Enclose the state transition NotReady->InInit->Ready */
79 AutoInitSpan autoInitSpan(this);
80 AssertReturn(autoInitSpan.isOk(), E_FAIL);
81
82 unconst(mParent) = aParent;
83 /* mPeer is left null */
84
85 mData.allocate();
86
87 /* Confirm a successful initialization */
88 autoInitSpan.setSucceeded();
89
90 return S_OK;
91}
92
93/**
94 * Initializes the graphics adapter object given another graphics adapter
95 * object (a kind of copy constructor). This object shares data with
96 * the object passed as an argument.
97 *
98 * @note This object must be destroyed before the original object
99 * it shares data with is destroyed.
100 *
101 * @note Locks @a aThat object for reading.
102 */
103HRESULT GraphicsAdapter::init(Machine *aParent, GraphicsAdapter *aThat)
104{
105 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
106
107 ComAssertRet(aParent && aThat, E_INVALIDARG);
108
109 /* Enclose the state transition NotReady->InInit->Ready */
110 AutoInitSpan autoInitSpan(this);
111 AssertReturn(autoInitSpan.isOk(), E_FAIL);
112
113 unconst(mParent) = aParent;
114 unconst(mPeer) = aThat;
115
116 AutoCaller thatCaller(aThat);
117 AssertComRCReturnRC(thatCaller.hrc());
118
119 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
120 mData.share(aThat->mData);
121
122 /* Confirm a successful initialization */
123 autoInitSpan.setSucceeded();
124
125 return S_OK;
126}
127
128/**
129 * Initializes the graphics adapter object given another graphics adapter
130 * object (a kind of copy constructor). This object makes a private copy
131 * of data of the original object passed as an argument.
132 *
133 * @note Locks @a aThat object for reading.
134 */
135HRESULT GraphicsAdapter::initCopy(Machine *aParent, GraphicsAdapter *aThat)
136{
137 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
138
139 ComAssertRet(aParent && aThat, E_INVALIDARG);
140
141 /* Enclose the state transition NotReady->InInit->Ready */
142 AutoInitSpan autoInitSpan(this);
143 AssertReturn(autoInitSpan.isOk(), E_FAIL);
144
145 unconst(mParent) = aParent;
146 /* mPeer is left null */
147
148 AutoCaller thatCaller(aThat);
149 AssertComRCReturnRC(thatCaller.hrc());
150
151 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
152 mData.attachCopy(aThat->mData);
153
154 /* Confirm a successful initialization */
155 autoInitSpan.setSucceeded();
156
157 return S_OK;
158}
159
160/**
161 * Uninitializes the instance and sets the ready flag to FALSE.
162 * Called either from FinalRelease() or by the parent when it gets destroyed.
163 */
164void GraphicsAdapter::uninit()
165{
166 LogFlowThisFunc(("\n"));
167
168 /* Enclose the state transition Ready->InUninit->NotReady */
169 AutoUninitSpan autoUninitSpan(this);
170 if (autoUninitSpan.uninitDone())
171 return;
172
173 mData.free();
174
175 unconst(mPeer) = NULL;
176 unconst(mParent) = NULL;
177}
178
179// Wrapped IGraphicsAdapter properties
180/////////////////////////////////////////////////////////////////////////////
181
182HRESULT GraphicsAdapter::getGraphicsControllerType(GraphicsControllerType_T *aGraphicsControllerType)
183{
184 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
185
186 *aGraphicsControllerType = mData->graphicsControllerType;
187
188 return S_OK;
189}
190
191HRESULT GraphicsAdapter::setGraphicsControllerType(GraphicsControllerType_T aGraphicsControllerType)
192{
193 switch (aGraphicsControllerType)
194 {
195 case GraphicsControllerType_Null:
196 case GraphicsControllerType_VBoxVGA:
197#ifdef VBOX_WITH_VMSVGA
198 case GraphicsControllerType_VMSVGA:
199 case GraphicsControllerType_VBoxSVGA:
200#endif
201 case GraphicsControllerType_QemuRamFB:
202 break;
203 default:
204 return setError(E_INVALIDARG, tr("The graphics controller type (%d) is invalid"), aGraphicsControllerType);
205 }
206
207 /* the machine needs to be mutable */
208 AutoMutableStateDependency adep(mParent);
209 if (FAILED(adep.hrc())) return adep.hrc();
210
211 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
212
213 mParent->i_setModified(Machine::IsModified_GraphicsAdapter);
214 mData.backup();
215 mData->graphicsControllerType = aGraphicsControllerType;
216
217 return S_OK;
218}
219
220HRESULT GraphicsAdapter::getVRAMSize(ULONG *aVRAMSize)
221{
222 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
223
224 *aVRAMSize = mData->ulVRAMSizeMB;
225
226 return S_OK;
227}
228
229HRESULT GraphicsAdapter::setVRAMSize(ULONG aVRAMSize)
230{
231 /* check VRAM limits */
232 if (aVRAMSize > SchemaDefs::MaxGuestVRAM)
233 return setError(E_INVALIDARG,
234 tr("Invalid VRAM size: %lu MB (must be in range [%lu, %lu] MB)"),
235 aVRAMSize, SchemaDefs::MinGuestVRAM, SchemaDefs::MaxGuestVRAM);
236
237 /* the machine needs to be mutable */
238 AutoMutableStateDependency adep(mParent);
239 if (FAILED(adep.hrc())) return adep.hrc();
240
241 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
242
243 mParent->i_setModified(Machine::IsModified_GraphicsAdapter);
244 mData.backup();
245 mData->ulVRAMSizeMB = aVRAMSize;
246
247 return S_OK;
248}
249
250HRESULT GraphicsAdapter::getAccelerate3DEnabled(BOOL *aAccelerate3DEnabled)
251{
252 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
253
254 *aAccelerate3DEnabled = mData->fAccelerate3D;
255
256 return S_OK;
257}
258
259HRESULT GraphicsAdapter::setAccelerate3DEnabled(BOOL aAccelerate3DEnabled)
260{
261 /* the machine needs to be mutable */
262 AutoMutableStateDependency adep(mParent);
263 if (FAILED(adep.hrc())) return adep.hrc();
264
265 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
266
267 /** @todo check validity! */
268
269 mParent->i_setModified(Machine::IsModified_GraphicsAdapter);
270 mData.backup();
271 mData->fAccelerate3D = !!aAccelerate3DEnabled;
272
273 return S_OK;
274}
275
276
277HRESULT GraphicsAdapter::getAccelerate2DVideoEnabled(BOOL *aAccelerate2DVideoEnabled)
278{
279 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
280
281 /* bugref:9691 The legacy VHWA acceleration has been disabled completely. */
282 *aAccelerate2DVideoEnabled = FALSE;
283
284 return S_OK;
285}
286
287HRESULT GraphicsAdapter::setAccelerate2DVideoEnabled(BOOL aAccelerate2DVideoEnabled)
288{
289 /* the machine needs to be mutable */
290 AutoMutableStateDependency adep(mParent);
291 if (FAILED(adep.hrc())) return adep.hrc();
292
293 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
294
295 /** @todo check validity! */
296
297 mParent->i_setModified(Machine::IsModified_GraphicsAdapter);
298 mData.backup();
299 mData->fAccelerate2DVideo = !!aAccelerate2DVideoEnabled;
300
301 return S_OK;
302}
303
304HRESULT GraphicsAdapter::getMonitorCount(ULONG *aMonitorCount)
305{
306 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
307
308 *aMonitorCount = mData->cMonitors;
309
310 return S_OK;
311}
312
313HRESULT GraphicsAdapter::setMonitorCount(ULONG aMonitorCount)
314{
315 /* make sure monitor count is a sensible number */
316 if (aMonitorCount < 1 || aMonitorCount > SchemaDefs::MaxGuestMonitors)
317 return setError(E_INVALIDARG,
318 tr("Invalid monitor count: %lu (must be in range [%lu, %lu])"),
319 aMonitorCount, 1, SchemaDefs::MaxGuestMonitors);
320
321 /* the machine needs to be mutable */
322 AutoMutableStateDependency adep(mParent);
323 if (FAILED(adep.hrc())) return adep.hrc();
324
325 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
326
327 mParent->i_setModified(Machine::IsModified_GraphicsAdapter);
328 mData.backup();
329 mData->cMonitors = aMonitorCount;
330
331 return S_OK;
332}
333
334// Wrapped IGraphicsAdapter methods
335/////////////////////////////////////////////////////////////////////////////
336
337// public methods only for internal purposes
338/////////////////////////////////////////////////////////////////////////////
339
340/**
341 * Loads settings from the given machine node.
342 * May be called once right after this object creation.
343 *
344 * @param data Configuration settings.
345 *
346 * @note Locks this object for writing.
347 */
348HRESULT GraphicsAdapter::i_loadSettings(const settings::GraphicsAdapter &data)
349{
350 AutoCaller autoCaller(this);
351 AssertComRCReturnRC(autoCaller.hrc());
352
353 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
354
355 mData.assignCopy(&data);
356
357 return S_OK;
358}
359
360/**
361 * Saves settings to the given machine node.
362 *
363 * @param data Configuration settings.
364 *
365 * @note Locks this object for reading.
366 */
367HRESULT GraphicsAdapter::i_saveSettings(settings::GraphicsAdapter &data)
368{
369 AutoCaller autoCaller(this);
370 AssertComRCReturnRC(autoCaller.hrc());
371
372 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
373
374 data = *mData.data();
375
376 return S_OK;
377}
378
379/**
380 * @note Locks this object for writing.
381 */
382void GraphicsAdapter::i_rollback()
383{
384 /* sanity */
385 AutoCaller autoCaller(this);
386 AssertComRCReturnVoid(autoCaller.hrc());
387
388 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
389
390 mData.rollback();
391}
392
393/**
394 * @note Locks this object for writing, together with the peer object (also
395 * for writing) if there is one.
396 */
397void GraphicsAdapter::i_commit()
398{
399 /* sanity */
400 AutoCaller autoCaller(this);
401 AssertComRCReturnVoid(autoCaller.hrc());
402
403 /* sanity too */
404 AutoCaller peerCaller(mPeer);
405 AssertComRCReturnVoid(peerCaller.hrc());
406
407 /* lock both for writing since we modify both (mPeer is "master" so locked
408 * first) */
409 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
410
411 if (mData.isBackedUp())
412 {
413 mData.commit();
414 if (mPeer)
415 {
416 /* attach new data to the peer and reshare it */
417 mPeer->mData.attach(mData);
418 }
419 }
420}
421
422/**
423 * @note Locks this object for writing, together with the peer object
424 * represented by @a aThat (locked for reading).
425 */
426void GraphicsAdapter::i_copyFrom(GraphicsAdapter *aThat)
427{
428 AssertReturnVoid(aThat != NULL);
429
430 /* sanity */
431 AutoCaller autoCaller(this);
432 AssertComRCReturnVoid(autoCaller.hrc());
433
434 /* sanity too */
435 AutoCaller thatCaller(aThat);
436 AssertComRCReturnVoid(thatCaller.hrc());
437
438 /* peer is not modified, lock it for reading (aThat is "master" so locked
439 * first) */
440 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
441 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
442
443 /* this will back up current data */
444 mData.assignCopy(aThat->mData);
445}
446/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use