VirtualBox

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

Last change on this file since 94725 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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