VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxFB/Framebuffer.cpp

Last change on this file was 106061, checked in by vboxsync, 7 days ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1/* $Id: Framebuffer.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBoxFB - Implementation of the VBoxDirectFB class.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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#include "VBoxFB.h"
29#include "Framebuffer.h"
30
31NS_IMPL_ISUPPORTS1_CI(VBoxDirectFB, IFramebuffer)
32NS_DECL_CLASSINFO(VBoxDirectFB)
33
34VBoxDirectFB::VBoxDirectFB(IDirectFB *aDFB, IDirectFBSurface *aSurface)
35{
36 dfb = aDFB;
37 surface = aSurface;
38 fbInternalSurface = NULL;
39 fbBufferAddress = NULL;
40 // initialize screen dimensions
41 DFBCHECK(surface->GetSize(surface, (int*)&screenWidth, (int*)&screenHeight));
42 fbWidth = 640;
43 fbHeight = 480;
44 if ((screenWidth != fbWidth) || (screenHeight != fbHeight))
45 {
46 createSurface(fbWidth, fbHeight);
47 }
48 fbSurfaceLocked = 0;
49 PRUint32 bitsPerPixel;
50 GetBitsPerPixel(&bitsPerPixel);
51 fbPitch = fbWidth * (bitsPerPixel / 8);
52}
53
54VBoxDirectFB::~VBoxDirectFB()
55{
56 // free our internal surface
57 if (fbInternalSurface)
58 {
59 DFBCHECK((DFBResult)fbInternalSurface->Release(fbInternalSurface));
60 fbInternalSurface = NULL;
61 }
62}
63
64NS_IMETHODIMP VBoxDirectFB::GetWidth(uint32 *width)
65{
66 if (!width)
67 return NS_ERROR_INVALID_POINTER;
68 *width = fbWidth;
69 return NS_OK;
70}
71
72NS_IMETHODIMP VBoxDirectFB::GetHeight(PRUint32 *height)
73{
74 if (!height)
75 return NS_ERROR_INVALID_POINTER;
76 *height = fbHeight;
77 return NS_OK;
78}
79
80NS_IMETHODIMP VBoxDirectFB::Lock()
81{
82 // do we have an internal framebuffer?
83 if (fbInternalSurface)
84 {
85 if (fbSurfaceLocked)
86 {
87 printf("internal surface already locked!\n");
88 } else
89 {
90 DFBCHECK(fbInternalSurface->Lock(fbInternalSurface,
91 (DFBSurfaceLockFlags)(DSLF_WRITE | DSLF_READ),
92 &fbBufferAddress, (int*)&fbPitch));
93 fbSurfaceLocked = 1;
94 }
95 } else
96 {
97 if (fbSurfaceLocked)
98 {
99 printf("surface already locked!\n");
100 } else
101 {
102 DFBCHECK(surface->Lock(surface, (DFBSurfaceLockFlags)(DSLF_WRITE | DSLF_READ),
103 &fbBufferAddress, (int*)&fbPitch));
104 fbSurfaceLocked = 1;
105 }
106 }
107 return NS_OK;
108}
109
110NS_IMETHODIMP VBoxDirectFB::Unlock()
111{
112 // do we have an internal framebuffer?
113 if (fbInternalSurface)
114 {
115 if (!fbSurfaceLocked)
116 {
117 printf("internal surface not locked!\n");
118 } else
119 {
120 DFBCHECK(fbInternalSurface->Unlock(fbInternalSurface));
121 fbSurfaceLocked = 0;
122 }
123 } else
124 {
125 if (!fbSurfaceLocked)
126 {
127 printf("surface not locked!\n");
128 } else
129 {
130 DFBCHECK(surface->Unlock(surface));
131 fbSurfaceLocked = 0;
132 }
133 }
134 return NS_OK;
135}
136
137NS_IMETHODIMP VBoxDirectFB::GetAddress(PRUint8 **address)
138{
139 if (!address)
140 return NS_ERROR_INVALID_POINTER;
141 *address = (PRUint8 *)fbBufferAddress;
142 return NS_OK;
143}
144
145NS_IMETHODIMP VBoxDirectFB::GetBitsPerPixel(PRUint32 *bitsPerPixel)
146{
147 if (!bitsPerPixel)
148 return NS_ERROR_INVALID_POINTER;
149 DFBSurfacePixelFormat pixelFormat;
150 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
151 switch (pixelFormat)
152 {
153 case DSPF_RGB16:
154 *bitsPerPixel = 16;
155 break;
156 case DSPF_RGB24:
157 *bitsPerPixel = 24;
158 break;
159 case DSPF_RGB32:
160 *bitsPerPixel = 32;
161 break;
162 default:
163 // not good! @@@AH do something!
164 *bitsPerPixel = 16;
165 }
166 return NS_OK;
167}
168
169NS_IMETHODIMP VBoxDirectFB::GetBytesPerLine(PRUint32 *bytesPerLine)
170{
171 if (!bytesPerLine)
172 return NS_ERROR_INVALID_POINTER;
173 *bytesPerLine = fbPitch;
174 return NS_OK;
175}
176
177NS_IMETHODIMP VBoxDirectFB::GetPixelFormat(BitmapFormat_T *pixelFormat)
178{
179 if (!pixelFormat)
180 return NS_ERROR_INVALID_POINTER;
181 *pixelFormat = BitmapFormat_RGBA;
182 return NS_OK;
183}
184
185NS_IMETHODIMP VBoxDirectFB::GetUsesGuestVRAM (PRBool *usesGuestVRAM)
186{
187 if (!usesGuestVRAM)
188 return NS_ERROR_INVALID_POINTER;
189 *usesGuestVRAM = false;
190 return NS_OK;
191}
192
193NS_IMETHODIMP VBoxDirectFB::GetHeightReduction(PRUint32 *heightReduction)
194{
195 if (!heightReduction)
196 return NS_ERROR_INVALID_POINTER;
197 *heightReduction = 0;
198 return NS_OK;
199}
200
201NS_IMETHODIMP VBoxDirectFB::GetOverlay(IFramebufferOverlay **overlay)
202{
203 if (!overlay)
204 return NS_ERROR_INVALID_POINTER;
205 /* Not yet implemented */
206 *overlay = 0;
207 return NS_OK;
208}
209
210NS_IMETHODIMP VBoxDirectFB::GetWinId(PRInt64 *winId)
211{
212 if (!winId)
213 return NS_ERROR_INVALID_POINTER;
214 *winId = 0;
215 return NS_OK;
216}
217
218NS_IMETHODIMP VBoxDirectFB::GetCapabilities(PRUint32 *pcCapabilites, FramebufferCapabilities_T **ppaenmCapabilities)
219{
220 RT_NOREF(pcCapabilites, ppaenmCapabilities);
221 AssertMsgFailed(("Not implemented"));
222 return E_NOTIMPL;
223}
224
225
226NS_IMETHODIMP VBoxDirectFB::NotifyUpdate(PRUint32 x, PRUint32 y,
227 PRUint32 w, PRUint32 h)
228{
229 // we only need to take action if we have a memory framebuffer
230 if (fbInternalSurface)
231 {
232 //printf("blitting %u %u %u %u...\n", x, y, w, h);
233 DFBRectangle blitRectangle;
234 blitRectangle.x = x;
235 blitRectangle.y = y;
236 blitRectangle.w = w;
237 blitRectangle.h = h;
238 if (g_scaleGuest)
239 {
240 DFBRectangle hostRectangle;
241 float factorX = (float)screenWidth / (float)fbWidth;
242 float factorY = (float)screenHeight / (float)fbHeight;
243 hostRectangle.x = (int)((float)blitRectangle.x * factorX);
244 hostRectangle.y = (int)((float)blitRectangle.y * factorY);
245 hostRectangle.w = (int)((float)blitRectangle.w * factorX);
246 hostRectangle.h = (int)((float)blitRectangle.h * factorY);
247 DFBCHECK(surface->StretchBlit(surface, fbInternalSurface,
248 &blitRectangle, &hostRectangle));
249 }
250 else
251 {
252 DFBCHECK(surface->Blit(surface, fbInternalSurface, &blitRectangle,
253 x + ((screenWidth - fbWidth) / 2),
254 y + (screenHeight - fbHeight) / 2));
255 }
256 }
257 return NS_OK;
258}
259
260NS_IMETHODIMP VBoxDirectFB::NotifyUpdateImage(PRUint32 x, PRUint32 y, PRUint32 cx, PRUint32 cy, PRUint32 cbImage, PRUint8 *pbImage)
261{
262 RT_NOREF(x, y, cx, cy, cbImage, pbImage);
263 AssertMsgFailed(("Not implemented"));
264 return E_NOTIMPL;
265}
266
267NS_IMETHODIMP VBoxDirectFB::NotifyChange(PRUint32 idScreen, PRUint32 xOrigin, PRUint32 yOrigin, PRUint32 cx, PRUint32 cy)
268{
269 RT_NOREF(idScreen, xOrigin, yOrigin, cx, cy);
270 AssertMsgFailed(("Not implemented"));
271 return E_NOTIMPL;
272}
273
274NS_IMETHODIMP VBoxDirectFB::RequestResize(PRUint32 aScreenId, PRUint32 pixelFormat, PRUint8 *vram,
275 PRUint32 bitsPerPixel, PRUint32 bytesPerLine,
276 PRUint32 w, PRUint32 h,
277 PRBool *finished)
278{
279 uint32_t needsLocking = fbSurfaceLocked;
280
281 printf("RequestResize: aScreenId = %d, pixelFormat = %d, vram = %p, bitsPerPixel = %d, bytesPerLine = %d, w = %d, h = %d, fbSurfaceLocked = %d\n", aScreenId, pixelFormat, vram, bitsPerPixel, bytesPerLine, w, h, fbSurfaceLocked);
282
283 // we can't work with a locked surface
284 if (needsLocking)
285 {
286 Unlock();
287 }
288
289 // in any case we gotta free a possible internal framebuffer
290 if (fbInternalSurface)
291 {
292 printf("freeing internal surface\n");
293 fbInternalSurface->Release(fbInternalSurface);
294 fbInternalSurface = NULL;
295 }
296
297 // check if we have a fixed host video mode
298 if (g_useFixedVideoMode)
299 {
300 // does the current video mode differ from what the guest wants?
301 if (screenWidth == w && screenHeight == h)
302 printf("requested guest mode matches current host mode!\n");
303 else
304 createSurface(w, h);
305 }
306 else
307 {
308 // we adopt to the guest resolution or the next higher that is available
309 int32_t bestMode = getBestVideoMode(w, h, bitsPerPixel);
310 if (bestMode == -1)
311 {
312 // oh oh oh oh
313 printf("RequestResize: no suitable mode found!\n");
314 return NS_OK;
315 }
316
317 // does the mode differ from what we wanted?
318 if ( g_videoModes[bestMode].width != w
319 || g_videoModes[bestMode].height != h
320 || g_videoModes[bestMode].bpp != bitsPerPixel)
321 {
322 printf("The mode does not fit exactly!\n");
323 createSurface(w, h);
324 }
325 else
326 {
327 printf("The mode fits exactly!\n");
328 }
329 // switch to this mode
330 DFBCHECK(dfb->SetVideoMode(dfb,
331 g_videoModes[bestMode].width,
332 g_videoModes[bestMode].height,
333 g_videoModes[bestMode].bpp));
334 }
335
336 // update dimensions to the new size
337 fbWidth = w;
338 fbHeight = h;
339
340 // clear the screen
341 DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
342
343 // if it was locked before the resize, obtain the lock again
344 if (needsLocking)
345 {
346 Lock();
347 }
348
349 if (finished)
350 *finished = true;
351 return NS_OK;
352}
353
354NS_IMETHODIMP VBoxDirectFB::VideoModeSupported(PRUint32 w, PRUint32 h, PRUint32 bpp, PRBool *supported)
355{
356 RT_NOREF(w, h, bpp);
357 if (!supported)
358 return NS_ERROR_INVALID_POINTER;
359 *supported = true;
360 return NS_OK;
361}
362
363NS_IMETHODIMP VBoxDirectFB::GetVisibleRegion(PRUint8 *rectangles, PRUint32 count, PRUint32 *countCopied)
364{
365 RT_NOREF(count);
366 PRTRECT rects = (PRTRECT)rectangles;
367 if (!rects || !countCopied)
368 return NS_ERROR_INVALID_POINTER;
369 /** @todo */
370 *countCopied = 0;
371 return NS_OK;
372}
373
374NS_IMETHODIMP VBoxDirectFB::SetVisibleRegion(PRUint8 *rectangles, PRUint32 count)
375{
376 RT_NOREF(count);
377 PRTRECT rects = (PRTRECT)rectangles;
378 if (!rects)
379 return NS_ERROR_INVALID_POINTER;
380 /** @todo */
381 return NS_OK;
382}
383
384NS_IMETHODIMP VBoxDirectFB::ProcessVHWACommand(PRUint8 *command, LONG enmCmd, BOOL fGuestCmd)
385{
386 RT_NOREF(command, enmCmd, fGuestCmd);
387 return NS_ERROR_NOT_IMPLEMENTED;
388}
389
390NS_IMETHODIMP VBoxDirectFB::Notify3DEvent(PRUint32 type, PRUint32 cbData, PRUint8 *pbData)
391{
392 RT_NOREF(type, cbData, pbData);
393 return NS_ERROR_NOT_IMPLEMENTED;
394}
395
396int VBoxDirectFB::createSurface(uint32_t w, uint32_t h)
397{
398 printf("creating a new internal surface, w = %u, h = %u...\n", w, h);
399 // create a surface
400 DFBSurfaceDescription dsc;
401 DFBSurfacePixelFormat pixelFormat;
402 dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
403 dsc.width = w;
404 dsc.height = h;
405 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
406 dsc.pixelformat = pixelFormat;
407 DFBCHECK(dfb->CreateSurface(dfb, &dsc, &fbInternalSurface));
408 return 0;
409}
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