VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp@ 470

Last change on this file since 470 was 470, checked in by vboxsync, 18 years ago

Main/Frontends: Changed all interface attributes and method parameters that used to use ULONG to pass pointers around; they now use BYTE * for this purpose (should fix problems for 64-bit targets).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.2 KB
Line 
1/** @file
2 *
3 * VBox frontends: VBoxSDL (simple frontend based on SDL):
4 * Implementation of VBoxSDLFB (SDL framebuffer) class
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung 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 <VBox/com/com.h>
24#include <VBox/com/string.h>
25#include <VBox/com/Guid.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/EventQueue.h>
28#include <VBox/com/VirtualBox.h>
29#include <iprt/stream.h>
30
31using namespace com;
32
33#define LOG_GROUP LOG_GROUP_GUI
34#include <VBox/err.h>
35#include <VBox/log.h>
36#include <stdlib.h>
37#include <signal.h>
38
39#include "VBoxSDL.h"
40#include "Framebuffer.h"
41#include "Ico64x01.h"
42
43#ifdef __LINUX__
44NS_IMPL_ISUPPORTS1_CI(VBoxSDLFB, IFramebuffer)
45NS_DECL_CLASSINFO(VBoxSDLFB)
46NS_IMPL_ISUPPORTS1_CI(VBoxSDLFBOverlay, IFramebufferOverlay)
47NS_DECL_CLASSINFO(VBoxSDLFBOverlay)
48#endif
49
50#ifdef VBOX_SECURELABEL
51/* function pointers */
52extern "C"
53{
54DECLSPEC int (SDLCALL *pTTF_Init)(void);
55DECLSPEC TTF_Font* (SDLCALL *pTTF_OpenFont)(const char *file, int ptsize);
56DECLSPEC SDL_Surface* (SDLCALL *pTTF_RenderUTF8_Solid)(TTF_Font *font, const char *text, SDL_Color fg);
57DECLSPEC void (SDLCALL *pTTF_CloseFont)(TTF_Font *font);
58DECLSPEC void (SDLCALL *pTTF_Quit)(void);
59}
60#endif /* VBOX_SECURELABEL */
61
62//
63// Constructor / destructor
64//
65
66/**
67 * SDL framebuffer constructor. It is called from the main
68 * (i.e. SDL) thread. Therefore it is safe to use SDL calls
69 * here.
70 * @param fFullscreen flag whether we start in fullscreen mode
71 * @param fResizable flag whether the SDL window should be resizable
72 * @param fShowSDLConfig flag whether we print out SDL settings
73 * @param iFixedWidth fixed SDL width (-1 means not set)
74 * @param iFixedHeight fixed SDL height (-1 means not set)
75 */
76VBoxSDLFB::VBoxSDLFB(bool fFullscreen, bool fResizable, bool fShowSDLConfig,
77 uint32_t u32FixedWidth, uint32_t u32FixedHeight, uint32_t u32FixedBPP)
78{
79 int rc;
80 LogFlow(("VBoxSDLFB::VBoxSDLFB\n"));
81
82#if defined (__WIN__)
83 refcnt = 0;
84#endif
85
86 mScreen = NULL;
87 mSurfVRAM = NULL;
88 mfInitialized = false;
89 mfFullscreen = fFullscreen;
90 mTopOffset = 0;
91 mfResizable = fResizable;
92 mfShowSDLConfig = fShowSDLConfig;
93 mFixedSDLWidth = u32FixedWidth;
94 mFixedSDLHeight = u32FixedHeight;
95 mFixedSDLBPP = u32FixedBPP;
96 mCenterXOffset = 0;
97 mCenterYOffset = 0;
98 /* Start with standard screen dimensions. */
99 mGuestXRes = 640;
100 mGuestYRes = 480;
101 mPixelFormat = FramebufferPixelFormat_PixelFormatDefault;
102 mPtrVRAM = NULL;
103 mLineSize = 0;
104#ifdef VBOX_SECURELABEL
105 mLabelFont = NULL;
106 mLabelHeight = 0;
107#endif
108 mWMIcon = NULL;
109
110 /* memorize the thread that inited us, that's the SDL thread */
111 mSdlNativeThread = RTThreadNativeSelf();
112
113 rc = RTCritSectInit(&mUpdateLock);
114 AssertMsg(rc == VINF_SUCCESS, ("Error from RTCritSectInit!\n"));
115
116#ifdef __WIN__
117 /* default to DirectX if nothing else set */
118 if (!getenv("SDL_VIDEODRIVER"))
119 {
120 _putenv("SDL_VIDEODRIVER=directx");
121// _putenv("SDL_VIDEODRIVER=windib");
122 }
123#endif
124#ifdef __LINUX__
125 /* On some X servers the mouse is stuck inside the bottom right corner.
126 * See http://wiki.clug.org.za/wiki/QEMU_mouse_not_working */
127 putenv("SDL_VIDEO_X11_DGAMOUSE=0");
128#endif
129 rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
130 if (rc != 0)
131 {
132 RTPrintf("SDL Error: '%s'\n", SDL_GetError());
133 return;
134 }
135
136#ifdef __LINUX__
137 /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
138 signal(SIGINT, SIG_DFL);
139 signal(SIGQUIT, SIG_DFL);
140#endif
141
142 if (mfShowSDLConfig)
143 {
144 /* output what SDL is capable of */
145 const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
146 Assert(videoInfo);
147 if (videoInfo)
148 {
149 RTPrintf("SDL capabilities:\n"
150 " Hardware surface support: %s\n"
151 " Window manager available: %s\n"
152 " Screen to screen blits accelerated: %s\n"
153 " Screen to screen colorkey blits accelerated: %s\n"
154 " Screen to screen alpha blits accelerated: %s\n"
155 " Memory to screen blits accelerated: %s\n"
156 " Memory to screen colorkey blits accelerated: %s\n"
157 " Memory to screen alpha blits accelerated: %s\n"
158 " Color fills accelerated: %s\n"
159 " Video memory in kilobytes: %d\n"
160 " Optimal bpp mode: %d\n"
161 "SDL video driver: %s\n",
162 videoInfo->hw_available ? "yes" : "no",
163 videoInfo->wm_available ? "yes" : "no",
164 videoInfo->blit_hw ? "yes" : "no",
165 videoInfo->blit_hw_CC ? "yes" : "no",
166 videoInfo->blit_hw_A ? "yes" : "no",
167 videoInfo->blit_sw ? "yes" : "no",
168 videoInfo->blit_sw_CC ? "yes" : "no",
169 videoInfo->blit_sw_A ? "yes" : "no",
170 videoInfo->blit_fill ? "yes" : "no",
171 videoInfo->video_mem,
172 videoInfo->vfmt->BitsPerPixel,
173 getenv("SDL_VIDEODRIVER"));
174 }
175 }
176
177 if (12320 == g_cbIco64x01)
178 {
179 mWMIcon = SDL_AllocSurface(SDL_SWSURFACE, 64, 64, 24, 0xff, 0xff00, 0xff0000, 0);
180 /** @todo make it as simple as possible. No PNM interpreter here... */
181 if (mWMIcon)
182 {
183 memcpy(mWMIcon->pixels, g_abIco64x01+32, g_cbIco64x01-32);
184 SDL_WM_SetIcon(mWMIcon, NULL);
185 }
186 }
187
188 resizeGuest();
189 Assert(mScreen);
190 mfInitialized = true;
191}
192
193VBoxSDLFB::~VBoxSDLFB()
194{
195 LogFlow(("VBoxSDLFB::~VBoxSDLFB\n"));
196 RTCritSectDelete(&mUpdateLock);
197}
198
199
200/**
201 * Returns the current framebuffer width in pixels.
202 *
203 * @returns COM status code
204 * @param width Address of result buffer.
205 */
206STDMETHODIMP VBoxSDLFB::COMGETTER(Width)(ULONG *width)
207{
208 LogFlow(("VBoxSDLFB::GetWidth\n"));
209 if (!width)
210 return E_INVALIDARG;
211 *width = mGuestXRes;
212 return S_OK;
213}
214
215/**
216 * Returns the current framebuffer height in pixels.
217 *
218 * @returns COM status code
219 * @param height Address of result buffer.
220 */
221STDMETHODIMP VBoxSDLFB::COMGETTER(Height)(ULONG *height)
222{
223 LogFlow(("VBoxSDLFB::GetHeight\n"));
224 if (!height)
225 return E_INVALIDARG;
226 *height = mGuestYRes;
227 return S_OK;
228}
229
230/**
231 * Lock the framebuffer (make its address immutable).
232 *
233 * @returns COM status code
234 */
235STDMETHODIMP VBoxSDLFB::Lock()
236{
237 LogFlow(("VBoxSDLFB::Lock\n"));
238 RTCritSectEnter(&mUpdateLock);
239 return S_OK;
240}
241
242/**
243 * Unlock the framebuffer.
244 *
245 * @returns COM status code
246 */
247STDMETHODIMP VBoxSDLFB::Unlock()
248{
249 LogFlow(("VBoxSDLFB::Unlock\n"));
250 RTCritSectLeave(&mUpdateLock);
251 return S_OK;
252}
253
254/**
255 * Return the framebuffer start address.
256 *
257 * @returns COM status code.
258 * @param address Pointer to result variable.
259 */
260STDMETHODIMP VBoxSDLFB::COMGETTER(Address)(BYTE **address)
261{
262 LogFlow(("VBoxSDLFB::GetAddress\n"));
263 if (!address)
264 return E_INVALIDARG;
265
266 if (mSurfVRAM)
267 {
268 *address = (BYTE *) mSurfVRAM->pixels;
269 }
270 else
271 {
272 /* That's actually rather bad. */
273 AssertMsgFailed(("mSurfVRAM is NULL!\n"));
274 return E_FAIL;
275 }
276 LogFlow(("VBoxSDL::GetAddress returning %p\n", *address));
277 return S_OK;
278}
279
280/**
281 * Return the current framebuffer color depth.
282 *
283 * @returns COM status code
284 * @param colorDepth Address of result variable
285 */
286STDMETHODIMP VBoxSDLFB::COMGETTER(ColorDepth)(ULONG *colorDepth)
287{
288 LogFlow(("VBoxSDLFB::GetColorDepth\n"));
289 if (!colorDepth)
290 return E_INVALIDARG;
291 /* get the information directly from the surface in use */
292 Assert(mSurfVRAM);
293 *colorDepth = (ULONG)(mSurfVRAM ? mSurfVRAM->format->BitsPerPixel : 0);
294 return S_OK;
295}
296
297/**
298 * Return the current framebuffer line size in bytes.
299 *
300 * @returns COM status code.
301 * @param lineSize Address of result variable.
302 */
303STDMETHODIMP VBoxSDLFB::COMGETTER(LineSize)(ULONG *lineSize)
304{
305 LogFlow(("VBoxSDLFB::GetLineSize\n"));
306 if (!lineSize)
307 return E_INVALIDARG;
308 /* get the information directly from the surface */
309 Assert(mSurfVRAM);
310 *lineSize = (ULONG)(mSurfVRAM ? mSurfVRAM->pitch : 0);
311 return S_OK;
312}
313
314STDMETHODIMP VBoxSDLFB::COMGETTER(PixelFormat) (FramebufferPixelFormat_T *pixelFormat)
315{
316 if (!pixelFormat)
317 return E_POINTER;
318 *pixelFormat = mPixelFormat;
319 return S_OK;
320}
321
322/**
323 * Returns by how many pixels the guest should shrink its
324 * video mode height values.
325 *
326 * @returns COM status code.
327 * @param heightReduction Address of result variable.
328 */
329STDMETHODIMP VBoxSDLFB::COMGETTER(HeightReduction)(ULONG *heightReduction)
330{
331 if (!heightReduction)
332 return E_POINTER;
333#ifdef VBOX_SECURELABEL
334 *heightReduction = mLabelHeight;
335#else
336 *heightReduction = 0;
337#endif
338 return S_OK;
339}
340
341/**
342 * Returns a pointer to an alpha-blended overlay used for displaying status
343 * icons above the framebuffer.
344 *
345 * @returns COM status code.
346 * @param aOverlay The overlay framebuffer.
347 */
348STDMETHODIMP VBoxSDLFB::COMGETTER(Overlay)(IFramebufferOverlay **aOverlay)
349{
350 if (!aOverlay)
351 return E_POINTER;
352 /* Not yet implemented */
353 *aOverlay = 0;
354 return S_OK;
355}
356
357/**
358 * Notify framebuffer of an update.
359 *
360 * @returns COM status code
361 * @param x Update region upper left corner x value.
362 * @param y Update region upper left corner y value.
363 * @param w Update region width in pixels.
364 * @param h Update region height in pixels.
365 * @param finished Address of output flag whether the update
366 * could be fully processed in this call (which
367 * has to return immediately) or VBox should wait
368 * for a call to the update complete API before
369 * continuing with display updates.
370 */
371STDMETHODIMP VBoxSDLFB::NotifyUpdate(ULONG x, ULONG y,
372 ULONG w, ULONG h, BOOL *finished)
373{
374 /*
375 * The input values are in guest screen coordinates.
376 */
377 LogFlow(("VBoxSDLFB::NotifyUpdate: x = %d, y = %d, w = %d, h = %d\n",
378 x, y, w, h));
379
380#ifdef __LINUX__
381 /*
382 * SDL does not allow us to make this call from any other
383 * thread. So we have to send an event to the main SDL
384 * thread and process it there. For sake of simplicity, we encode
385 * all information in the event parameters.
386 */
387 SDL_Event event;
388 event.type = SDL_USEREVENT;
389 event.user.type = SDL_USER_EVENT_UPDATERECT;
390 // 16 bit is enough for coordinates
391 event.user.data1 = (void*)(x << 16 | y);
392 event.user.data2 = (void*)(w << 16 | h);
393 int rc = SDL_PushEvent(&event);
394 NOREF(rc);
395 AssertMsg(!rc, ("SDL_PushEvent returned SDL error '%s'\n", SDL_GetError()));
396 /* in order to not flood the SDL event queue, yield the CPU */
397 RTThreadYield();
398#else /* !__LINUX__ */
399 update(x, y, w, h, true /* fGuestRelative */);
400#endif /* !__LINUX__ */
401
402 /*
403 * The Display thread can continue as we will lock the framebuffer
404 * from the SDL thread when we get to actually doing the update.
405 */
406 if (finished)
407 *finished = TRUE;
408 return S_OK;
409}
410
411/**
412 * Request a display resize from the framebuffer.
413 *
414 * @returns COM status code.
415 * @param pixelFormat The requested pixel format.
416 * @param vram Pointer to the guest VRAM buffer (can be NULL).
417 * @param lineSize Size of a scanline in bytes.
418 * @param w New display width in pixels.
419 * @param h New display height in pixels.
420 * @param finished Address of output flag whether the update
421 * could be fully processed in this call (which
422 * has to return immediately) or VBox should wait
423 * for all call to the resize complete API before
424 * continuing with display updates.
425 */
426STDMETHODIMP VBoxSDLFB::RequestResize(FramebufferPixelFormat_T pixelFormat, BYTE *vram,
427 ULONG lineSize, ULONG w, ULONG h, BOOL *finished)
428{
429 LogFlow(("VBoxSDLFB::RequestResize: w = %d, h = %d, pixelFormat: %d, vram = %p, lineSize = %d\n",
430 w, h, pixelFormat, vram, lineSize));
431
432 /*
433 * SDL does not allow us to make this call from any other
434 * thread. So we have to send an event to the main SDL
435 * thread and tell VBox to wait.
436 */
437 if (!finished)
438 {
439 AssertMsgFailed(("RequestResize requires the finished flag!\n"));
440 return E_FAIL;
441 }
442 mGuestXRes = w;
443 mGuestYRes = h;
444 mPixelFormat = pixelFormat;
445 mPtrVRAM = vram;
446 mLineSize = lineSize;
447
448 SDL_Event event;
449 event.type = SDL_USEREVENT;
450 event.user.type = SDL_USER_EVENT_RESIZE;
451 int rc = SDL_PushEvent(&event);
452 NOREF(rc);
453 AssertMsg(!rc, ("SDL_PushEvent returned SDL error '%s'\n", SDL_GetError()));
454
455 /* we want this request to be processed quickly, so yield the CPU */
456 RTThreadYield();
457
458 *finished = false;
459
460 return S_OK;
461}
462
463/**
464 * Returns which acceleration operations are supported
465 *
466 * @returns COM status code
467 * @param operation acceleration operation code
468 * @supported result
469 */
470STDMETHODIMP VBoxSDLFB::OperationSupported(FramebufferAccelerationOperation_T operation, BOOL *supported)
471{
472 if (!supported)
473 return E_POINTER;
474
475 // SDL gives us software surfaces, futile
476 *supported = false;
477#if 0
478 switch (operation)
479 {
480 case FramebufferAccelerationOperation_SolidFillAcceleration:
481 *supported = true;
482 break;
483 case FramebufferAccelerationOperation_ScreenCopyAcceleration:
484 *supported = true;
485 break;
486 default:
487 *supported = false;
488 }
489#endif
490 return S_OK;
491}
492
493/**
494 * Returns whether we like the given video mode.
495 *
496 * @returns COM status code
497 * @param width video mode width in pixels
498 * @param height video mode height in pixels
499 * @param bpp video mode bit depth in bits per pixel
500 * @param supported pointer to result variable
501 */
502STDMETHODIMP VBoxSDLFB::VideoModeSupported(ULONG width, ULONG height, ULONG bpp, BOOL *supported)
503{
504 if (!supported)
505 return E_POINTER;
506
507 /* are constraints set? */
508 if ( ( (mMaxScreenWidth != ~(uint32_t)0)
509 && (width > mMaxScreenWidth)
510 || ( (mMaxScreenHeight != ~(uint32_t)0)
511 && (height > mMaxScreenHeight))))
512 {
513 /* nope, we don't want that (but still don't freak out if it is set) */
514#ifdef DEBUG
515 printf("VBoxSDL::VideoModeSupported: we refused mode %dx%dx%d\n", width, height, bpp);
516#endif
517 *supported = false;
518 }
519 else
520 {
521 /* anything will do */
522 *supported = true;
523 }
524 return S_OK;
525}
526
527STDMETHODIMP VBoxSDLFB::SolidFill(ULONG x, ULONG y, ULONG width, ULONG height,
528 ULONG color, BOOL *handled)
529{
530 if (!handled)
531 return E_POINTER;
532 // SDL gives us software surfaces, futile
533#if 0
534 printf("SolidFill: x: %d, y: %d, w: %d, h: %d, color: %d\n", x, y, width, height, color);
535 SDL_Rect rect = { (Sint16)x, (Sint16)y, (Sint16)width, (Sint16)height };
536 SDL_FillRect(mScreen, &rect, color);
537 //SDL_UpdateRect(mScreen, x, y, width, height);
538 *handled = true;
539#else
540 *handled = false;
541#endif
542 return S_OK;
543}
544
545STDMETHODIMP VBoxSDLFB::CopyScreenBits(ULONG xDst, ULONG yDst, ULONG xSrc, ULONG ySrc,
546 ULONG width, ULONG height, BOOL *handled)
547{
548 if (!handled)
549 return E_POINTER;
550 // SDL gives us software surfaces, futile
551#if 0
552 SDL_Rect srcRect = { (Sint16)xSrc, (Sint16)ySrc, (Sint16)width, (Sint16)height };
553 SDL_Rect dstRect = { (Sint16)xDst, (Sint16)yDst, (Sint16)width, (Sint16)height };
554 SDL_BlitSurface(mScreen, &srcRect, mScreen, &dstRect);
555 *handled = true;
556#else
557 *handled = false;
558#endif
559 return S_OK;
560}
561
562
563//
564// Internal public methods
565//
566
567/**
568 * Method that does the actual resize of the guest framebuffer and
569 * then changes the SDL framebuffer setup.
570 */
571void VBoxSDLFB::resizeGuest()
572{
573 LogFlow(("VBoxSDL::resizeGuest() mGuestXRes: %d, mGuestYRes: %d\n", mGuestXRes, mGuestYRes));
574 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
575
576 /* pixel characteristics, default to fallback 32bpp format */
577 int bitsPerPixel = 32;
578 Uint32 Rmask = 0x00FF0000;
579 Uint32 Gmask = 0x0000FF00;
580 Uint32 Bmask = 0x000000FF;
581 Uint32 Amask = 0;
582
583 /* a different format we support directly? */
584 switch (mPixelFormat)
585 {
586 case FramebufferPixelFormat_PixelFormatRGB24:
587 {
588 bitsPerPixel = 24;
589 Rmask = 0x00FF0000;
590 Gmask = 0x0000FF00;
591 Bmask = 0x000000FF;
592 break;
593 }
594
595 case FramebufferPixelFormat_PixelFormatRGB16:
596 {
597 bitsPerPixel = 16;
598 Rmask = 0xF800;
599 Gmask = 0x07E0;
600 Bmask = 0x001F;
601 break;
602 }
603 }
604
605 /* first free the current surface */
606 if (mSurfVRAM)
607 {
608 SDL_FreeSurface(mSurfVRAM);
609 mSurfVRAM = NULL;
610 }
611
612 /* is the guest in a linear framebuffer mode we support? */
613 if (mPixelFormat != FramebufferPixelFormat_PixelFormatDefault)
614 {
615 /* Create a source surface from guest VRAM. */
616 mSurfVRAM = SDL_CreateRGBSurfaceFrom(mPtrVRAM, mGuestXRes, mGuestYRes, bitsPerPixel, mLineSize,
617 Rmask, Gmask, Bmask, Amask);
618 }
619 else
620 {
621 /* Create a software surface for which SDL allocates the RAM */
622 mSurfVRAM = SDL_CreateRGBSurface(SDL_SWSURFACE, mGuestXRes, mGuestYRes, bitsPerPixel,
623 Rmask, Gmask, Bmask, Amask);
624 }
625 LogFlow(("VBoxSDL:: created VRAM surface %p\n", mSurfVRAM));
626
627 /* now adjust the SDL resolution */
628 resizeSDL();
629}
630
631/**
632 * Sets SDL video mode. This is independent from guest video
633 * mode changes.
634 *
635 * @remarks Must be called from the SDL thread!
636 */
637void VBoxSDLFB::resizeSDL(void)
638{
639 LogFlow(("VBoxSDL:resizeSDL\n"));
640
641 /*
642 * We request a hardware surface from SDL so that we can perform
643 * accelerated system memory to VRAM blits. The way video handling
644 * works it that on the one hand we have the screen surface from SDL
645 * and on the other hand we have a software surface that we create
646 * using guest VRAM memory for linear modes and using SDL allocated
647 * system memory for text and non linear graphics modes. We never
648 * directly write to the screen surface but always use SDL blitting
649 * functions to blit from our system memory surface to the VRAM.
650 * Therefore, SDL can take advantage of hardware acceleration.
651 */
652 int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
653 if (mfResizable)
654 sdlFlags |= SDL_RESIZABLE;
655 if (mfFullscreen)
656 sdlFlags |= SDL_FULLSCREEN;
657
658 /*
659 * Now we have to check whether there are video mode restrictions
660 */
661 SDL_Rect **modes;
662 /* Get available fullscreen/hardware modes */
663 modes = SDL_ListModes(NULL, sdlFlags);
664 Assert(modes != NULL);
665 /* -1 means that any mode is possible (usually non fullscreen) */
666 if (modes != (SDL_Rect **)-1)
667 {
668 /*
669 * according to the SDL documentation, the API guarantees that
670 * the modes are sorted from larger to smaller, so we just
671 * take the first entry as the maximum.
672 */
673 mMaxScreenWidth = modes[0]->w;
674 mMaxScreenHeight = modes[0]->h;
675 }
676 else
677 {
678 /* no restriction */
679 mMaxScreenWidth = ~(uint32_t)0;
680 mMaxScreenHeight = ~(uint32_t)0;
681 }
682
683 uint32_t newWidth;
684 uint32_t newHeight;
685
686 /* reset the centering offsets */
687 mCenterXOffset = 0;
688 mCenterYOffset = 0;
689
690 /* we either have a fixed SDL resolution or we take the guest's */
691 if (mFixedSDLWidth != ~(uint32_t)0)
692 {
693 newWidth = mFixedSDLWidth;
694 newHeight = mFixedSDLHeight;
695 }
696 else
697 {
698 newWidth = RT_MIN(mGuestXRes, mMaxScreenWidth);
699#ifdef VBOX_SECURELABEL
700 newHeight = RT_MIN(mGuestYRes + mLabelHeight, mMaxScreenHeight);
701#else
702 newHeight = RT_MIN(mGuestYRes, mMaxScreenHeight);
703#endif
704 }
705
706 /* we don't have any extra space by default */
707 mTopOffset = 0;
708
709 /*
710 * Now set the screen resolution and get the surface pointer
711 * @todo BPP is not supported!
712 */
713 mScreen = SDL_SetVideoMode(newWidth, newHeight, 0, sdlFlags);
714#ifdef VBOX_SECURELABEL
715 /*
716 * For non fixed SDL resolution, the above call tried to add the label height
717 * to the guest height. If it worked, we have an offset. If it didn't the below
718 * code will try again with the original guest resolution.
719 */
720 if (mFixedSDLWidth == ~(uint32_t)0)
721 {
722 /* if it didn't work, then we have to go for the original resolution and paint over the guest */
723 if (!mScreen)
724 {
725 mScreen = SDL_SetVideoMode(newWidth, newHeight - mLabelHeight, 0, sdlFlags);
726 }
727 else
728 {
729 /* we now have some extra space */
730 mTopOffset = mLabelHeight;
731 }
732 }
733 else
734 {
735 /* in case the guest resolution is small enough, we do have a top offset */
736 if (mFixedSDLHeight - mGuestYRes >= mLabelHeight)
737 mTopOffset = mLabelHeight;
738
739 /* we also might have to center the guest picture */
740 if (mFixedSDLWidth > mGuestXRes)
741 mCenterXOffset = (mFixedSDLWidth - mGuestXRes) / 2;
742 if (mFixedSDLHeight > mGuestYRes + mLabelHeight)
743 mCenterYOffset = (mFixedSDLHeight - (mGuestYRes + mLabelHeight)) / 2;
744 }
745#endif
746 AssertMsg(mScreen, ("Error: SDL_SetVideoMode failed!\n"));
747 if (mScreen)
748 {
749#ifdef VBOX_WIN32_UI
750 /* inform the UI code */
751 resizeUI(mScreen->w, mScreen->h);
752#endif
753 if (mfShowSDLConfig)
754 RTPrintf("Resized to %dx%d, screen surface type: %s\n", mScreen->w, mScreen->h,
755 ((mScreen->flags & SDL_HWSURFACE) == 0) ? "software" : "hardware");
756 }
757 repaint();
758}
759
760/**
761 * Update specified framebuffer area. The coordinates can either be
762 * relative to the guest framebuffer or relative to the screen.
763 *
764 * @remarks Must be called from the SDL thread on Linux!
765 * @param x left column
766 * @param y top row
767 * @param w width in pixels
768 * @param h height in pixels
769 * @param fGuestRelative flag whether the above values are guest relative or screen relative;
770 */
771void VBoxSDLFB::update(int x, int y, int w, int h, bool fGuestRelative)
772{
773#ifdef __LINUX__
774 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
775#endif
776 Assert(mScreen);
777 Assert(mSurfVRAM);
778 if (!mScreen || !mSurfVRAM)
779 return;
780
781 /* the source and destination rectangles */
782 SDL_Rect srcRect;
783 SDL_Rect dstRect;
784
785 /* this is how many pixels we have to cut off from the height for this specific blit */
786 int yCutoffGuest = 0;
787
788#ifdef VBOX_SECURELABEL
789 bool fPaintLabel = false;
790 /* if we have a label and no space for it, we have to cut off a bit */
791 if (mLabelHeight && !mTopOffset)
792 {
793 if (y < (int)mLabelHeight)
794 yCutoffGuest = mLabelHeight - y;
795 }
796#endif
797
798 /**
799 * If we get a SDL window relative update, we
800 * just perform a full screen update to keep things simple.
801 *
802 * @todo improve
803 */
804 if (!fGuestRelative)
805 {
806#ifdef VBOX_SECURELABEL
807 /* repaint the label if necessary */
808 if (y < (int)mLabelHeight)
809 fPaintLabel = true;
810#endif
811 x = 0;
812 w = mGuestXRes;
813 y = 0;
814 h = mGuestYRes;
815 }
816
817 srcRect.x = x;
818 srcRect.y = y + yCutoffGuest;
819 srcRect.w = w;
820 srcRect.h = RT_MAX(0, h - yCutoffGuest);
821
822 /*
823 * Destination rectangle is just offset by the label height.
824 * There are two cases though: label height is added to the
825 * guest resolution (mTopOffset == mLabelHeight; yCutoffGuest == 0)
826 * or the label cuts off a portion of the guest screen (mTopOffset == 0;
827 * yCutoffGuest >= 0)
828 */
829 dstRect.x = x + mCenterXOffset;
830#ifdef VBOX_SECURELABEL
831 dstRect.y = RT_MAX(mLabelHeight, y + yCutoffGuest + mTopOffset) + mCenterYOffset;
832#else
833 dstRect.y = y + yCutoffGuest + mTopOffset + mCenterYOffset;
834#endif
835 dstRect.w = w;
836 dstRect.h = RT_MAX(0, h - yCutoffGuest);
837
838 //RTPrintf("y = %d h = %d mapped to srcY %d srcH %d mapped to dstY = %d dstH %d (guestrel: %d, mLabelHeight: %d, mTopOffset: %d)\n",
839 // y, h, srcRect.y, srcRect.h, dstRect.y, dstRect.h, fGuestRelative, mLabelHeight, mTopOffset);
840
841 /*
842 * Now we just blit
843 */
844 SDL_BlitSurface(mSurfVRAM, &srcRect, mScreen, &dstRect);
845 /* hardware surfaces don't need update notifications */
846 if ((mScreen->flags & SDL_HWSURFACE) == 0)
847 SDL_UpdateRect(mScreen, dstRect.x, dstRect.y, dstRect.w, dstRect.h);
848
849#ifdef VBOX_SECURELABEL
850 if (fPaintLabel)
851 paintSecureLabel(0, 0, 0, 0, false);
852#endif
853}
854
855/**
856 * Repaint the whole framebuffer
857 *
858 * @remarks Must be called from the SDL thread!
859 */
860void VBoxSDLFB::repaint()
861{
862 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
863 LogFlow(("VBoxSDLFB::repaint\n"));
864 update(0, 0, mScreen->w, mScreen->h, false /* fGuestRelative */);
865}
866
867bool VBoxSDLFB::getFullscreen()
868{
869 LogFlow(("VBoxSDLFB::getFullscreen\n"));
870 return mfFullscreen;
871}
872
873/**
874 * Toggle fullscreen mode
875 *
876 * @remarks Must be called from the SDL thread!
877 */
878void VBoxSDLFB::setFullscreen(bool fFullscreen)
879{
880 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
881 LogFlow(("VBoxSDLFB::SetFullscreen: fullscreen: %d\n", fFullscreen));
882 mfFullscreen = fFullscreen;
883 /* only change the SDL resolution, do not touch the guest framebuffer */
884 resizeSDL();
885}
886
887
888/**
889 * Returns the current x offset of the start of the guest screen
890 *
891 * @returns current x offset in pixels
892 */
893int VBoxSDLFB::getXOffset()
894{
895 /* there can only be an offset for centering */
896 return mCenterXOffset;
897}
898
899/**
900 * Returns the current y offset of the start of the guest screen
901 *
902 * @returns current y offset in pixels
903 */
904int VBoxSDLFB::getYOffset()
905{
906 /* we might have a top offset and a center offset */
907 return mTopOffset + mCenterYOffset;
908}
909
910#ifdef VBOX_SECURELABEL
911/**
912 * Setup the secure labeling parameters
913 *
914 * @returns VBox status code
915 * @param height height of the secure label area in pixels
916 * @param font file path fo the TrueType font file
917 * @param pointsize font size in points
918 */
919int VBoxSDLFB::initSecureLabel(uint32_t height, char *font, uint32_t pointsize)
920{
921 LogFlow(("VBoxSDLFB:initSecureLabel: new offset: %d pixels, new font: %s, new pointsize: %d\n",
922 height, font, pointsize));
923 mLabelHeight = height;
924 Assert(font);
925 pTTF_Init();
926 mLabelFont = pTTF_OpenFont(font, pointsize);
927 if (!mLabelFont)
928 {
929 AssertMsgFailed(("Failed to open TTF font file %s\n", font));
930 return VERR_OPEN_FAILED;
931 }
932 mSecureLabelColorFG = 0x0000FF00;
933 mSecureLabelColorBG = 0x00FFFF00;
934 repaint();
935 return VINF_SUCCESS;
936}
937
938/**
939 * Set the secure label text and repaint the label
940 *
941 * @param text UTF-8 string of new label
942 * @remarks must be called from the SDL thread!
943 */
944void VBoxSDLFB::setSecureLabelText(const char *text)
945{
946 mSecureLabelText = text;
947 paintSecureLabel(0, 0, 0, 0, true);
948}
949
950/**
951 * Sets the secure label background color.
952 *
953 * @param colorFG encoded RGB value for text
954 * @param colorBG encored RGB value for background
955 * @remarks must be called from the SDL thread!
956 */
957void VBoxSDLFB::setSecureLabelColor(uint32_t colorFG, uint32_t colorBG)
958{
959 mSecureLabelColorFG = colorFG;
960 mSecureLabelColorBG = colorBG;
961 paintSecureLabel(0, 0, 0, 0, true);
962}
963
964/**
965 * Paint the secure label if required
966 *
967 * @param fForce Force the repaint
968 * @remarks must be called from the SDL thread!
969 */
970void VBoxSDLFB::paintSecureLabel(int x, int y, int w, int h, bool fForce)
971{
972#ifdef __LINUX__
973 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
974#endif
975 /* only when the function is present */
976 if (!pTTF_RenderUTF8_Solid)
977 return;
978 /* check if we can skip the paint */
979 if (!fForce && ((uint32_t)y > mLabelHeight))
980 {
981 return;
982 }
983 /* first fill the background */
984 SDL_Rect rect = {0, 0, (Uint16)mScreen->w, (Uint16)mLabelHeight};
985 SDL_FillRect(mScreen, &rect, SDL_MapRGB(mScreen->format,
986 (mSecureLabelColorBG & 0x00FF0000) >> 16, /* red */
987 (mSecureLabelColorBG & 0x0000FF00) >> 8, /* green */
988 mSecureLabelColorBG & 0x000000FF)); /* blue */
989
990 /* now the text */
991 if (mLabelFont != NULL && mSecureLabelText)
992 {
993 SDL_Color clrFg = {(mSecureLabelColorFG & 0x00FF0000) >> 16,
994 (mSecureLabelColorFG & 0x0000FF00) >> 8,
995 mSecureLabelColorFG & 0x000000FF, 0};
996 SDL_Surface *sText = pTTF_RenderUTF8_Solid(mLabelFont, mSecureLabelText.raw(), clrFg);
997 rect.x = 10;
998 SDL_BlitSurface(sText, NULL, mScreen, &rect);
999 SDL_FreeSurface(sText);
1000 }
1001 /* make sure to update the screen */
1002 SDL_UpdateRect(mScreen, 0, 0, mScreen->w, mLabelHeight);
1003}
1004#endif /* VBOX_SECURELABEL */
1005
1006/**
1007 * Terminate SDL
1008 *
1009 * @remarks must be called from the SDL thread!
1010 */
1011void VBoxSDLFB::uninit()
1012{
1013 AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
1014 if (mSurfVRAM)
1015 {
1016 SDL_FreeSurface(mSurfVRAM);
1017 mSurfVRAM = NULL;
1018 }
1019 SDL_QuitSubSystem(SDL_INIT_VIDEO);
1020#ifdef VBOX_SECURELABEL
1021 if (mLabelFont)
1022 pTTF_CloseFont(mLabelFont);
1023 if (pTTF_Quit)
1024 pTTF_Quit();
1025#endif
1026 mScreen = NULL;
1027 if (mWMIcon)
1028 {
1029 SDL_FreeSurface(mWMIcon);
1030 mWMIcon = NULL;
1031 }
1032}
1033
1034// IFramebufferOverlay
1035///////////////////////////////////////////////////////////////////////////////////
1036
1037/**
1038 * Constructor for the VBoxSDLFBOverlay class (IFramebufferOverlay implementation)
1039 *
1040 * @param x Initial X offset for the overlay
1041 * @param y Initial Y offset for the overlay
1042 * @param width Initial width for the overlay
1043 * @param height Initial height for the overlay
1044 * @param visible Whether the overlay is initially visible
1045 * @param alpha Initial alpha channel value for the overlay
1046 */
1047VBoxSDLFBOverlay::VBoxSDLFBOverlay(ULONG x, ULONG y, ULONG width, ULONG height,
1048 BOOL visible, VBoxSDLFB *aParent) :
1049 mOverlayX(x), mOverlayY(y), mOverlayWidth(width),
1050 mOverlayHeight(height), mOverlayVisible(visible),
1051 mParent(aParent)
1052{}
1053
1054/**
1055 * Destructor for the VBoxSDLFBOverlay class.
1056 */
1057VBoxSDLFBOverlay::~VBoxSDLFBOverlay()
1058{
1059 SDL_FreeSurface(mBlendedBits);
1060 SDL_FreeSurface(mOverlayBits);
1061}
1062
1063/**
1064 * Perform any initialisation of the overlay that can potentially fail
1065 *
1066 * @returns S_OK on success or the reason for the failure
1067 */
1068HRESULT VBoxSDLFBOverlay::init()
1069{
1070 mBlendedBits = SDL_CreateRGBSurface(SDL_ANYFORMAT, mOverlayWidth, mOverlayHeight, 32,
1071 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
1072 AssertMsgReturn(mBlendedBits != NULL, ("Failed to create an SDL surface\n"),
1073 E_OUTOFMEMORY);
1074 mOverlayBits = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, mOverlayWidth,
1075 mOverlayHeight, 32, 0x00ff0000, 0x0000ff00,
1076 0x000000ff, 0xff000000);
1077 AssertMsgReturn(mOverlayBits != NULL, ("Failed to create an SDL surface\n"),
1078 E_OUTOFMEMORY);
1079 return S_OK;
1080}
1081
1082/**
1083 * Returns the current overlay X offset in pixels.
1084 *
1085 * @returns COM status code
1086 * @param x Address of result buffer.
1087 */
1088STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(X)(ULONG *x)
1089{
1090 LogFlow(("VBoxSDLFBOverlay::GetX\n"));
1091 if (!x)
1092 return E_INVALIDARG;
1093 *x = mOverlayX;
1094 return S_OK;
1095}
1096
1097/**
1098 * Returns the current overlay height in pixels.
1099 *
1100 * @returns COM status code
1101 * @param height Address of result buffer.
1102 */
1103STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Y)(ULONG *y)
1104{
1105 LogFlow(("VBoxSDLFBOverlay::GetY\n"));
1106 if (!y)
1107 return E_INVALIDARG;
1108 *y = mOverlayY;
1109 return S_OK;
1110}
1111
1112/**
1113 * Returns the current overlay width in pixels. In fact, this returns the line size.
1114 *
1115 * @returns COM status code
1116 * @param width Address of result buffer.
1117 */
1118STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Width)(ULONG *width)
1119{
1120 LogFlow(("VBoxSDLFBOverlay::GetWidth\n"));
1121 if (!width)
1122 return E_INVALIDARG;
1123 *width = mOverlayBits->pitch;
1124 return S_OK;
1125}
1126
1127/**
1128 * Returns the current overlay line size in pixels.
1129 *
1130 * @returns COM status code
1131 * @param lineSize Address of result buffer.
1132 */
1133STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(LineSize)(ULONG *lineSize)
1134{
1135 LogFlow(("VBoxSDLFBOverlay::GetLineSize\n"));
1136 if (!lineSize)
1137 return E_INVALIDARG;
1138 *lineSize = mOverlayBits->pitch;
1139 return S_OK;
1140}
1141
1142/**
1143 * Returns the current overlay height in pixels.
1144 *
1145 * @returns COM status code
1146 * @param height Address of result buffer.
1147 */
1148STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Height)(ULONG *height)
1149{
1150 LogFlow(("VBoxSDLFBOverlay::GetHeight\n"));
1151 if (!height)
1152 return E_INVALIDARG;
1153 *height = mOverlayHeight;
1154 return S_OK;
1155}
1156
1157/**
1158 * Returns whether the overlay is currently visible.
1159 *
1160 * @returns COM status code
1161 * @param visible Address of result buffer.
1162 */
1163STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Visible)(BOOL *visible)
1164{
1165 LogFlow(("VBoxSDLFBOverlay::GetVisible\n"));
1166 if (!visible)
1167 return E_INVALIDARG;
1168 *visible = mOverlayVisible;
1169 return S_OK;
1170}
1171
1172/**
1173 * Sets whether the overlay is currently visible.
1174 *
1175 * @returns COM status code
1176 * @param visible New value.
1177 */
1178STDMETHODIMP VBoxSDLFBOverlay::COMSETTER(Visible)(BOOL visible)
1179{
1180 LogFlow(("VBoxSDLFBOverlay::SetVisible\n"));
1181 mOverlayVisible = visible;
1182 return S_OK;
1183}
1184
1185/**
1186 * Returns the value of the global alpha channel.
1187 *
1188 * @returns COM status code
1189 * @param alpha Address of result buffer.
1190 */
1191STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Alpha)(ULONG *alpha)
1192{
1193 LogFlow(("VBoxSDLFBOverlay::GetAlpha\n"));
1194 return E_NOTIMPL;
1195}
1196
1197/**
1198 * Sets whether the overlay is currently visible.
1199 *
1200 * @returns COM status code
1201 * @param alpha new value.
1202 */
1203STDMETHODIMP VBoxSDLFBOverlay::COMSETTER(Alpha)(ULONG alpha)
1204{
1205 LogFlow(("VBoxSDLFBOverlay::SetAlpha\n"));
1206 return E_NOTIMPL;
1207}
1208
1209/**
1210 * Returns the address of the framebuffer bits for writing to.
1211 *
1212 * @returns COM status code
1213 * @param alpha Address of result buffer.
1214 */
1215STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Address)(ULONG *address)
1216{
1217 LogFlow(("VBoxSDLFBOverlay::GetAddress\n"));
1218 if (!address)
1219 return E_INVALIDARG;
1220 *address = (uintptr_t) mOverlayBits->pixels;
1221 return S_OK;
1222}
1223
1224/**
1225 * Returns the current colour depth. In fact, this is always 32bpp.
1226 *
1227 * @returns COM status code
1228 * @param colorDepth Address of result buffer.
1229 */
1230STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(ColorDepth)(ULONG *colorDepth)
1231{
1232 LogFlow(("VBoxSDLFBOverlay::GetColorDepth\n"));
1233 if (!colorDepth)
1234 return E_INVALIDARG;
1235 *colorDepth = 32;
1236 return S_OK;
1237}
1238
1239/**
1240 * Returns the current pixel format. In fact, this is always RGB32.
1241 *
1242 * @returns COM status code
1243 * @param pixelFormat Address of result buffer.
1244 */
1245STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(PixelFormat)(FramebufferPixelFormat_T *pixelFormat)
1246{
1247 LogFlow(("VBoxSDLFBOverlay::GetPixelFormat\n"));
1248 if (!pixelFormat)
1249 return E_INVALIDARG;
1250 *pixelFormat = FramebufferPixelFormat_PixelFormatRGB32;
1251 return S_OK;
1252}
1253
1254/**
1255 * Returns the height reduction. In fact, this is always 0.
1256 *
1257 * @returns COM status code
1258 * @param heightReduction Address of result buffer.
1259 */
1260STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(HeightReduction)(ULONG *heightReduction)
1261{
1262 LogFlow(("VBoxSDLFBOverlay::GetHeightReduction\n"));
1263 if (!heightReduction)
1264 return E_INVALIDARG;
1265 *heightReduction = 0;
1266 return S_OK;
1267}
1268
1269/**
1270 * Returns the overlay for this framebuffer. Obviously, we return NULL here.
1271 *
1272 * @returns COM status code
1273 * @param overlay Address of result buffer.
1274 */
1275STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Overlay)(IFramebufferOverlay **aOverlay)
1276{
1277 LogFlow(("VBoxSDLFBOverlay::GetOverlay\n"));
1278 if (!aOverlay)
1279 return E_INVALIDARG;
1280 *aOverlay = 0;
1281 return S_OK;
1282}
1283
1284/**
1285 * Lock the overlay. This should not be used - lock the parent IFramebuffer instead.
1286 *
1287 * @returns COM status code
1288 */
1289STDMETHODIMP VBoxSDLFBOverlay::Lock()
1290{
1291 LogFlow(("VBoxSDLFBOverlay::Lock\n"));
1292 AssertMsgFailed(("You should not attempt to lock an IFramebufferOverlay object -\n"
1293 "lock the parent IFramebuffer object instead.\n"));
1294 return E_NOTIMPL;
1295}
1296
1297/**
1298 * Unlock the overlay.
1299 *
1300 * @returns COM status code
1301 */
1302STDMETHODIMP VBoxSDLFBOverlay::Unlock()
1303{
1304 LogFlow(("VBoxSDLFBOverlay::Unlock\n"));
1305 AssertMsgFailed(("You should not attempt to lock an IFramebufferOverlay object -\n"
1306 "lock the parent IFramebuffer object instead.\n"));
1307 return E_NOTIMPL;
1308}
1309
1310/**
1311 * Change the X and Y co-ordinates of the overlay area.
1312 *
1313 * @returns COM status code
1314 * @param x New X co-ordinate.
1315 * @param y New Y co-ordinate.
1316 */
1317STDMETHODIMP VBoxSDLFBOverlay::Move(ULONG x, ULONG y)
1318{
1319 mOverlayX = x;
1320 mOverlayY = y;
1321 return S_OK;
1322}
1323
1324/**
1325 * Notify the overlay that a section of the framebuffer has been redrawn.
1326 *
1327 * @returns COM status code
1328 * @param x X co-ordinate of upper left corner of modified area.
1329 * @param y Y co-ordinate of upper left corner of modified area.
1330 * @param w Width of modified area.
1331 * @param h Height of modified area.
1332 * @retval finished Set if the operation has completed.
1333 *
1334 * All we do here is to send a request to the parent to update the affected area,
1335 * translating between our co-ordinate system and the parent's. It would be have
1336 * been better to call the parent directly, but such is life. We leave bounds
1337 * checking to the parent.
1338 */
1339STDMETHODIMP VBoxSDLFBOverlay::NotifyUpdate(ULONG x, ULONG y,
1340 ULONG w, ULONG h, BOOL *finished)
1341{
1342 return mParent->NotifyUpdate(x + mOverlayX, y + mOverlayY, w, h, finished);
1343}
1344
1345/**
1346 * Change the dimensions of the overlay.
1347 *
1348 * @returns COM status code
1349 * @param pixelFormat Must be FramebufferPixelFormat_PixelFormatRGB32.
1350 * @param vram Must be NULL.
1351 * @param lineSize Ignored.
1352 * @param w New overlay width.
1353 * @param h New overlay height.
1354 * @retval finished Set if the operation has completed.
1355 */
1356STDMETHODIMP VBoxSDLFBOverlay::RequestResize(FramebufferPixelFormat_T pixelFormat,
1357 ULONG vram, ULONG lineSize, ULONG w,
1358 ULONG h, BOOL *finished)
1359{
1360 AssertReturn(pixelFormat == FramebufferPixelFormat_PixelFormatRGB32, E_INVALIDARG);
1361 AssertReturn(vram == 0, E_INVALIDARG);
1362 mOverlayWidth = w;
1363 mOverlayHeight = h;
1364 SDL_FreeSurface(mOverlayBits);
1365 mBlendedBits = SDL_CreateRGBSurface(SDL_ANYFORMAT, mOverlayWidth, mOverlayHeight, 32,
1366 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
1367 AssertMsgReturn(mBlendedBits != NULL, ("Failed to create an SDL surface\n"),
1368 E_OUTOFMEMORY);
1369 mOverlayBits = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, mOverlayWidth,
1370 mOverlayHeight, 32, 0x00ff0000, 0x0000ff00,
1371 0x000000ff, 0xff000000);
1372 AssertMsgReturn(mOverlayBits != NULL, ("Failed to create an SDL surface\n"),
1373 E_OUTOFMEMORY);
1374 return S_OK;
1375}
1376
1377/**
1378 * Queries whether we support a given accelerated opperation. Since we do not currently
1379 * support any accelerated operations, we always return false in supported.
1380 *
1381 * @returns COM status code
1382 * @param operation The operation being queried
1383 * @retval supported Whether or not we support that operation
1384 */
1385STDMETHODIMP VBoxSDLFBOverlay::OperationSupported(FramebufferAccelerationOperation_T
1386 operation, BOOL *supported)
1387{
1388 if (!supported)
1389 return E_POINTER;
1390 /* We currently do not support any acceleration here, and will probably not in
1391 the forseeable future. */
1392 *supported = false;
1393 return S_OK;
1394}
1395
1396/**
1397 * Returns whether we like the given video mode.
1398 *
1399 * @returns COM status code
1400 * @param width video mode width in pixels
1401 * @param height video mode height in pixels
1402 * @param bpp video mode bit depth in bits per pixel
1403 * @retval supported pointer to result variable
1404 *
1405 * Basically, we support anything with 32bpp.
1406 */
1407STDMETHODIMP VBoxSDLFBOverlay::VideoModeSupported(ULONG width, ULONG height, ULONG bpp,
1408 BOOL *supported)
1409{
1410 if (!supported)
1411 return E_POINTER;
1412 if (bpp == 32)
1413 *supported = true;
1414 else
1415 *supported = false;
1416 return S_OK;
1417}
1418
1419/**
1420 * Fill an area of the framebuffer with solid colour
1421 *
1422 * @returns COM status code
1423 * @param x X co-ordinate of the area to fill, top-left corner
1424 * @param y Y co-ordinate of the area to fill, top-left corner
1425 * @param width width of the area to fill
1426 * @param height height of the area to fill
1427 * @param color colour with which to fill the area
1428 * @retval handled whether we support this operation or not
1429 *
1430 * Since we currently do not have any way of doing this faster than
1431 * the VGA device, we simply false in handled.
1432 */
1433STDMETHODIMP VBoxSDLFBOverlay::SolidFill(ULONG x, ULONG y, ULONG width,
1434 ULONG height, ULONG color, BOOL *handled)
1435{
1436 LogFlow(("VBoxSDLFBOverlay::SolidFill called\n"));
1437 if (!handled)
1438 return E_POINTER;
1439 *handled = false;
1440 return S_OK;
1441}
1442
1443/**
1444 * Since we currently do not have any way of doing this faster than
1445 * the VGA device, we simply false in handled.
1446 */
1447STDMETHODIMP VBoxSDLFBOverlay::CopyScreenBits(ULONG xDst, ULONG yDst, ULONG xSrc,
1448 ULONG ySrc, ULONG width,
1449 ULONG height, BOOL *handled)
1450{
1451 LogFlow(("VBoxSDLFBOverlay::CopyScreenBits called.\n"));
1452 if (!handled)
1453 return E_POINTER;
1454 *handled = false;
1455 return S_OK;
1456}
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