VirtualBox

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

Last change on this file since 97961 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.7 KB
Line 
1/* $Id: Framebuffer.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * VBoxFB - implementation of VBoxDirectFB class.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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(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 (PRUint32 *pixelFormat)
178{
179 if (!pixelFormat)
180 return NS_ERROR_INVALID_POINTER;
181 *pixelFormat = FramebufferPixelFormat_FOURCC_RGB;
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::NotifyUpdate(PRUint32 x, PRUint32 y,
219 PRUint32 w, PRUint32 h)
220{
221 // we only need to take action if we have a memory framebuffer
222 if (fbInternalSurface)
223 {
224 //printf("blitting %u %u %u %u...\n", x, y, w, h);
225 DFBRectangle blitRectangle;
226 blitRectangle.x = x;
227 blitRectangle.y = y;
228 blitRectangle.w = w;
229 blitRectangle.h = h;
230 if (scaleGuest)
231 {
232 DFBRectangle hostRectangle;
233 float factorX = (float)screenWidth / (float)fbWidth;
234 float factorY = (float)screenHeight / (float)fbHeight;
235 hostRectangle.x = (int)((float)blitRectangle.x * factorX);
236 hostRectangle.y = (int)((float)blitRectangle.y * factorY);
237 hostRectangle.w = (int)((float)blitRectangle.w * factorX);
238 hostRectangle.h = (int)((float)blitRectangle.h * factorY);
239 DFBCHECK(surface->StretchBlit(surface, fbInternalSurface,
240 &blitRectangle, &hostRectangle));
241 }
242 else
243 {
244 DFBCHECK(surface->Blit(surface, fbInternalSurface, &blitRectangle,
245 x + ((screenWidth - fbWidth) / 2),
246 y + (screenHeight - fbHeight) / 2));
247 }
248 }
249 return NS_OK;
250}
251
252NS_IMETHODIMP VBoxDirectFB::RequestResize(PRUint32 aScreenId, PRUint32 pixelFormat, PRUint8 *vram,
253 PRUint32 bitsPerPixel, PRUint32 bytesPerLine,
254 PRUint32 w, PRUint32 h,
255 PRBool *finished)
256{
257 uint32_t needsLocking = fbSurfaceLocked;
258
259 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);
260
261 // we can't work with a locked surface
262 if (needsLocking)
263 {
264 Unlock();
265 }
266
267 // in any case we gotta free a possible internal framebuffer
268 if (fbInternalSurface)
269 {
270 printf("freeing internal surface\n");
271 fbInternalSurface->Release(fbInternalSurface);
272 fbInternalSurface = NULL;
273 }
274
275 // check if we have a fixed host video mode
276 if (useFixedVideoMode)
277 {
278 // does the current video mode differ from what the guest wants?
279 if ((screenWidth == w) && (screenHeight == h))
280 {
281 printf("requested guest mode matches current host mode!\n");
282 } else
283 {
284 createSurface(w, h);
285 }
286 } else
287 {
288 // we adopt to the guest resolution or the next higher that is available
289 int32_t bestMode = getBestVideoMode(w, h, bitsPerPixel);
290 if (bestMode == -1)
291 {
292 // oh oh oh oh
293 printf("RequestResize: no suitable mode found!\n");
294 return NS_OK;
295 }
296
297 // does the mode differ from what we wanted?
298 if ((videoModes[bestMode].width != w) || (videoModes[bestMode].height != h) ||
299 (videoModes[bestMode].bpp != bitsPerPixel))
300 {
301 printf("The mode does not fit exactly!\n");
302 createSurface(w, h);
303 } else
304 {
305 printf("The mode fits exactly!\n");
306 }
307 // switch to this mode
308 DFBCHECK(dfb->SetVideoMode(dfb, videoModes[bestMode].width, videoModes[bestMode].height,
309 videoModes[bestMode].bpp));
310 }
311
312 // update dimensions to the new size
313 fbWidth = w;
314 fbHeight = h;
315
316 // clear the screen
317 DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
318
319 // if it was locked before the resize, obtain the lock again
320 if (needsLocking)
321 {
322 Lock();
323 }
324
325 if (finished)
326 *finished = true;
327 return NS_OK;
328}
329
330NS_IMETHODIMP VBoxDirectFB::VideoModeSupported(PRUint32 w, PRUint32 h, PRUint32 bpp, PRBool *supported)
331{
332 if (!supported)
333 return NS_ERROR_INVALID_POINTER;
334 *supported = true;
335 return NS_OK;
336}
337
338NS_IMETHODIMP VBoxDirectFB::GetVisibleRegion(PRUint8 *rectangles, PRUint32 count, PRUint32 *countCopied)
339{
340 PRTRECT rects = (PRTRECT)rectangles;
341
342 if (!rects || !countCopied)
343 return NS_ERROR_INVALID_POINTER;
344 /** @todo */
345 *countCopied = 0;
346 return NS_OK;
347}
348
349NS_IMETHODIMP VBoxDirectFB::SetVisibleRegion(PRUint8 *rectangles, PRUint32 count)
350{
351 PRTRECT rects = (PRTRECT)rectangles;
352
353 if (!rects)
354 return NS_ERROR_INVALID_POINTER;
355 /** @todo */
356 return NS_OK;
357}
358
359NS_IMETHODIMP VBoxDirectFB::ProcessVHWACommand(PRUint8 *command, LONG enmCmd, BOOL fGuestCmd)
360{
361 RT_NOREF(command, enmCmd, fGuestCmd);
362 return NS_ERROR_NOT_IMPLEMENTED;
363}
364
365NS_IMETHODIMP VBoxDirectFB::Notify3DEvent(PRUint32 type, PRUint8 *reserved)
366{
367 return NS_ERROR_NOT_IMPLEMENTED;
368}
369
370int VBoxDirectFB::createSurface(uint32_t w, uint32_t h)
371{
372 printf("creating a new internal surface, w = %u, h = %u...\n", w, h);
373 // create a surface
374 DFBSurfaceDescription dsc;
375 DFBSurfacePixelFormat pixelFormat;
376 dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
377 dsc.width = w;
378 dsc.height = h;
379 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
380 dsc.pixelformat = pixelFormat;
381 DFBCHECK(dfb->CreateSurface(dfb, &dsc, &fbInternalSurface));
382 return 0;
383}
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