VirtualBox

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

Last change on this file since 45733 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

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