VirtualBox

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

Last change on this file since 3160 was 3153, checked in by vboxsync, 17 years ago

Multimonitor support.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#include "VBoxFB.h"
24#include "Framebuffer.h"
25
26NS_IMPL_ISUPPORTS1_CI(VBoxDirectFB, IFramebuffer)
27NS_DECL_CLASSINFO(VBoxDirectFB)
28
29VBoxDirectFB::VBoxDirectFB(IDirectFB *aDFB, IDirectFBSurface *aSurface)
30{
31 dfb = aDFB;
32 surface = aSurface;
33 fbInternalSurface = NULL;
34 fbBufferAddress = NULL;
35 // initialize screen dimensions
36 DFBCHECK(surface->GetSize(surface, (int*)&screenWidth, (int*)&screenHeight));
37 fbWidth = 640;
38 fbHeight = 480;
39 if ((screenWidth != fbWidth) || (screenHeight != fbHeight))
40 {
41 createSurface(fbWidth, fbHeight);
42 }
43 fbSurfaceLocked = 0;
44 uint32_t colorDepth;
45 GetColorDepth(&colorDepth);
46 fbPitch = fbWidth * (colorDepth / 8);
47}
48
49VBoxDirectFB::~VBoxDirectFB()
50{
51 // free our internal surface
52 if (fbInternalSurface)
53 {
54 DFBCHECK(fbInternalSurface->Release(fbInternalSurface));
55 fbInternalSurface = NULL;
56 }
57}
58
59NS_IMETHODIMP VBoxDirectFB::GetWidth(uint32 *width)
60{
61 if (!width)
62 return NS_ERROR_INVALID_POINTER;
63 *width = fbWidth;
64 return NS_OK;
65}
66
67NS_IMETHODIMP VBoxDirectFB::GetHeight(uint32_t *height)
68{
69 if (!height)
70 return NS_ERROR_INVALID_POINTER;
71 *height = fbHeight;
72 return NS_OK;
73}
74
75NS_IMETHODIMP VBoxDirectFB::Lock()
76{
77 // do we have an internal framebuffer?
78 if (fbInternalSurface)
79 {
80 if (fbSurfaceLocked)
81 {
82 printf("internal surface already locked!\n");
83 } else
84 {
85 DFBCHECK(fbInternalSurface->Lock(fbInternalSurface,
86 (DFBSurfaceLockFlags)(DSLF_WRITE | DSLF_READ),
87 &fbBufferAddress, (int*)&fbPitch));
88 fbSurfaceLocked = 1;
89 }
90 } else
91 {
92 if (fbSurfaceLocked)
93 {
94 printf("surface already locked!\n");
95 } else
96 {
97 DFBCHECK(surface->Lock(surface, (DFBSurfaceLockFlags)(DSLF_WRITE | DSLF_READ),
98 &fbBufferAddress, (int*)&fbPitch));
99 fbSurfaceLocked = 1;
100 }
101 }
102 return NS_OK;
103}
104
105NS_IMETHODIMP VBoxDirectFB::Unlock()
106{
107 // do we have an internal framebuffer?
108 if (fbInternalSurface)
109 {
110 if (!fbSurfaceLocked)
111 {
112 printf("internal surface not locked!\n");
113 } else
114 {
115 DFBCHECK(fbInternalSurface->Unlock(fbInternalSurface));
116 fbSurfaceLocked = 0;
117 }
118 } else
119 {
120 if (!fbSurfaceLocked)
121 {
122 printf("surface not locked!\n");
123 } else
124 {
125 DFBCHECK(surface->Unlock(surface));
126 fbSurfaceLocked = 0;
127 }
128 }
129 return NS_OK;
130}
131
132NS_IMETHODIMP VBoxDirectFB::GetAddress(uint32_t *address)
133{
134 if (!address)
135 return NS_ERROR_INVALID_POINTER;
136 *address = (uint32_t)fbBufferAddress;
137 return NS_OK;
138}
139
140NS_IMETHODIMP VBoxDirectFB::GetColorDepth(uint32_t *colorDepth)
141{
142 if (!colorDepth)
143 return NS_ERROR_INVALID_POINTER;
144 DFBSurfacePixelFormat pixelFormat;
145 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
146 switch (pixelFormat)
147 {
148 case DSPF_RGB16:
149 *colorDepth = 16;
150 break;
151 case DSPF_RGB24:
152 *colorDepth = 24;
153 break;
154 case DSPF_RGB32:
155 *colorDepth = 32;
156 break;
157 default:
158 // not good! @@@AH do something!
159 *colorDepth = 16;
160 }
161 return NS_OK;
162}
163
164NS_IMETHODIMP VBoxDirectFB::GetLineSize(uint32_t *lineSize)
165{
166 if (!lineSize)
167 return NS_ERROR_INVALID_POINTER;
168 *lineSize = fbPitch;
169 return NS_OK;
170}
171
172NS_IMETHODIMP VBoxDirectFB::COMGETTER(PixelFormat) (FramebufferPixelFormat_T *pixelFormat)
173{
174 if (!lineSize)
175 return NS_ERROR_INVALID_POINTER;
176 *pixelFormat = FramebufferPixelFormat_PixelFormatDefault;
177 return NS_OK;
178}
179
180NS_IMETHODIMP VBoxDirectFB::NotifyUpdate(uint32_t x, uint32_t y,
181 uint32_t w, uint32_t h, PRBool *finished)
182{
183 // we only need to take action if we have a memory framebuffer
184 if (fbInternalSurface)
185 {
186 //printf("blitting %u %u %u %u...\n", x, y, w, h);
187 DFBRectangle blitRectangle;
188 blitRectangle.x = x;
189 blitRectangle.y = y;
190 blitRectangle.w = w;
191 blitRectangle.h = h;
192 if (scaleGuest)
193 {
194 DFBRectangle hostRectangle;
195 float factorX = (float)screenWidth / (float)fbWidth;
196 float factorY = (float)screenHeight / (float)fbHeight;
197 hostRectangle.x = (int)((float)blitRectangle.x * factorX);
198 hostRectangle.y = (int)((float)blitRectangle.y * factorY);
199 hostRectangle.w = (int)((float)blitRectangle.w * factorX);
200 hostRectangle.h = (int)((float)blitRectangle.h * factorY);
201 DFBCHECK(surface->StretchBlit(surface, fbInternalSurface,
202 &blitRectangle, &hostRectangle));
203 } else
204 {
205 DFBCHECK(surface->Blit(surface, fbInternalSurface, &blitRectangle,
206 x + ((screenWidth - fbWidth) / 2),
207 y + (screenHeight - fbHeight) / 2));
208 }
209 }
210 if (finished)
211 *finished = true;
212 return NS_OK;
213}
214
215NS_IMETHODIMP VBoxDirectFB::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, uint32_t vram, uint32_t lineSize, uint32_t w, uint32_t h,
216 PRBool *finished)
217{
218 uint32_t needsLocking = fbSurfaceLocked;
219 uint32_t colorDepth;
220
221 GetColorDepth(&colorDepth);
222 printf("RequestResize: w = %d, h = %d, fbSurfaceLocked = %d\n", w, h, fbSurfaceLocked);
223
224 // we can't work with a locked surface
225 if (needsLocking)
226 {
227 Unlock();
228 }
229
230 // in any case we gotta free a possible internal framebuffer
231 if (fbInternalSurface)
232 {
233 printf("freeing internal surface\n");
234 fbInternalSurface->Release(fbInternalSurface);
235 fbInternalSurface = NULL;
236 }
237
238 // check if we have a fixed host video mode
239 if (useFixedVideoMode)
240 {
241 // does the current video mode differ from what the guest wants?
242 if ((screenWidth == w) && (screenHeight == h))
243 {
244 printf("requested guest mode matches current host mode!\n");
245 } else
246 {
247 createSurface(w, h);
248 }
249 } else
250 {
251 // we adopt to the guest resolution or the next higher that is available
252 int32_t bestMode = getBestVideoMode(w, h, colorDepth);
253 if (bestMode == -1)
254 {
255 // oh oh oh oh
256 printf("RequestResize: no suitable mode found!\n");
257 return NS_OK;
258 }
259
260 // does the mode differ from what we wanted?
261 if ((videoModes[bestMode].width != w) || (videoModes[bestMode].height != h) ||
262 (videoModes[bestMode].bpp != colorDepth))
263 {
264 printf("The mode does not fit exactly!\n");
265 createSurface(w, h);
266 } else
267 {
268 printf("The mode fits exactly!\n");
269 }
270 // switch to this mode
271 DFBCHECK(dfb->SetVideoMode(dfb, videoModes[bestMode].width, videoModes[bestMode].height,
272 videoModes[bestMode].bpp));
273 }
274
275 // update dimensions to the new size
276 fbWidth = w;
277 fbHeight = h;
278
279 // clear the screen
280 DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
281
282 // if it was locked before the resize, obtain the lock again
283 if (needsLocking)
284 {
285 Lock();
286 }
287
288 if (finished)
289 *finished = true;
290 return NS_OK;
291}
292
293int VBoxDirectFB::createSurface(uint32_t w, uint32_t h)
294{
295 printf("creating a new internal surface, w = %u, h = %u...\n", w, h);
296 // create a surface
297 DFBSurfaceDescription dsc;
298 DFBSurfacePixelFormat pixelFormat;
299 dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
300 dsc.width = w;
301 dsc.height = h;
302 DFBCHECK(surface->GetPixelFormat(surface, &pixelFormat));
303 dsc.pixelformat = pixelFormat;
304 DFBCHECK(dfb->CreateSurface(dfb, &dsc, &fbInternalSurface));
305 return 0;
306}
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