VirtualBox

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

Last change on this file since 7449 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/** @file
2 *
3 * VBox frontends: Framebuffer (FB, DirectFB):
4 * Implementation of VBoxDirectFB class
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
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 uint32_t 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(uint32_t *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(uint32_t *address)
129{
130 if (!address)
131 return NS_ERROR_INVALID_POINTER;
132 *address = (uint32_t)fbBufferAddress;
133 return NS_OK;
134}
135
136NS_IMETHODIMP VBoxDirectFB::GetBitsPerPixel(uint32_t *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(uint32_t *bytesPerLine)
161{
162 if (!bytesPerLine)
163 return NS_ERROR_INVALID_POINTER;
164 *bytesPerLine = fbPitch;
165 return NS_OK;
166}
167
168NS_IMETHODIMP VBoxDirectFB::COMGETTER(PixelFormat) (ULONG *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::COMGETTER(UsesGuestVRAM) (BOOL *usesGuestVRAM)
177{
178 if (!usesGuestVRAM)
179 return NS_ERROR_INVALID_POINTER;
180 *usesGuestVRAM = FALSE;
181 return NS_OK;
182}
183
184NS_IMETHODIMP VBoxDirectFB::NotifyUpdate(uint32_t x, uint32_t y,
185 uint32_t w, uint32_t h, PRBool *finished)
186{
187 // we only need to take action if we have a memory framebuffer
188 if (fbInternalSurface)
189 {
190 //printf("blitting %u %u %u %u...\n", x, y, w, h);
191 DFBRectangle blitRectangle;
192 blitRectangle.x = x;
193 blitRectangle.y = y;
194 blitRectangle.w = w;
195 blitRectangle.h = h;
196 if (scaleGuest)
197 {
198 DFBRectangle hostRectangle;
199 float factorX = (float)screenWidth / (float)fbWidth;
200 float factorY = (float)screenHeight / (float)fbHeight;
201 hostRectangle.x = (int)((float)blitRectangle.x * factorX);
202 hostRectangle.y = (int)((float)blitRectangle.y * factorY);
203 hostRectangle.w = (int)((float)blitRectangle.w * factorX);
204 hostRectangle.h = (int)((float)blitRectangle.h * factorY);
205 DFBCHECK(surface->StretchBlit(surface, fbInternalSurface,
206 &blitRectangle, &hostRectangle));
207 } else
208 {
209 DFBCHECK(surface->Blit(surface, fbInternalSurface, &blitRectangle,
210 x + ((screenWidth - fbWidth) / 2),
211 y + (screenHeight - fbHeight) / 2));
212 }
213 }
214 if (finished)
215 *finished = true;
216 return NS_OK;
217}
218
219NS_IMETHODIMP VBoxDirectFB::RequestResize(ULONG aScreenId, ULONG pixelFormat, uint32_t vram,
220 uint32_t bitsPerPixel, uint32_t bytesPerLine,
221 uint32_t w, uint32_t h,
222 PRBool *finished)
223{
224 uint32_t needsLocking = fbSurfaceLocked;
225 uint32_t bitsPerPixel;
226
227 GetBitsPerPixel(&bitsPerPixel);
228 printf("RequestResize: w = %d, h = %d, fbSurfaceLocked = %d\n", w, h, fbSurfaceLocked);
229
230 // we can't work with a locked surface
231 if (needsLocking)
232 {
233 Unlock();
234 }
235
236 // in any case we gotta free a possible internal framebuffer
237 if (fbInternalSurface)
238 {
239 printf("freeing internal surface\n");
240 fbInternalSurface->Release(fbInternalSurface);
241 fbInternalSurface = NULL;
242 }
243
244 // check if we have a fixed host video mode
245 if (useFixedVideoMode)
246 {
247 // does the current video mode differ from what the guest wants?
248 if ((screenWidth == w) && (screenHeight == h))
249 {
250 printf("requested guest mode matches current host mode!\n");
251 } else
252 {
253 createSurface(w, h);
254 }
255 } else
256 {
257 // we adopt to the guest resolution or the next higher that is available
258 int32_t bestMode = getBestVideoMode(w, h, bitsPerPixel);
259 if (bestMode == -1)
260 {
261 // oh oh oh oh
262 printf("RequestResize: no suitable mode found!\n");
263 return NS_OK;
264 }
265
266 // does the mode differ from what we wanted?
267 if ((videoModes[bestMode].width != w) || (videoModes[bestMode].height != h) ||
268 (videoModes[bestMode].bpp != bitsPerPixel))
269 {
270 printf("The mode does not fit exactly!\n");
271 createSurface(w, h);
272 } else
273 {
274 printf("The mode fits exactly!\n");
275 }
276 // switch to this mode
277 DFBCHECK(dfb->SetVideoMode(dfb, videoModes[bestMode].width, videoModes[bestMode].height,
278 videoModes[bestMode].bpp));
279 }
280
281 // update dimensions to the new size
282 fbWidth = w;
283 fbHeight = h;
284
285 // clear the screen
286 DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
287
288 // if it was locked before the resize, obtain the lock again
289 if (needsLocking)
290 {
291 Lock();
292 }
293
294 if (finished)
295 *finished = true;
296 return NS_OK;
297}
298
299int VBoxDirectFB::createSurface(uint32_t w, uint32_t h)
300{
301 printf("creating a new internal surface, w = %u, h = %u...\n", w, h);
302 // create a surface
303 DFBSurfaceDescription dsc;
304 DFBSurfacePixelFormat pixelFormat;
305 dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
306 dsc.width = w;
307 dsc.height = h;
308 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
309 dsc.pixelformat = pixelFormat;
310 DFBCHECK(dfb->CreateSurface(dfb, &dsc, &fbInternalSurface));
311 return 0;
312}
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