VirtualBox

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

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

Darwin port (hope I didn't mess up anything, am very Zzzzz...)

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