Framebuffer.cpp revision 0c04bf3d366953a24840080b5f7be34d9406a7dc
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/** @file
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * VBox frontends: VBoxSDL (simple frontend based on SDL):
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Implementation of VBoxSDLFB (SDL framebuffer) class
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/*
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Copyright (C) 2006-2007 innotek GmbH
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * This file is part of VirtualBox Open Source Edition (OSE), as
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * available from http://www.virtualbox.org. This file is free software;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * you can redistribute it and/or modify it under the terms of the GNU
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * General Public License as published by the Free Software Foundation,
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * distribution. VirtualBox OSE is distributed in the hope that it will
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * be useful, but WITHOUT ANY WARRANTY of any kind.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * If you received this file as part of a commercial VirtualBox
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * distribution, then only the terms of your commercial VirtualBox
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * license agreement apply instead of the previous paragraph.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/com.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/string.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/Guid.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/ErrorInfo.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/EventQueue.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/com/VirtualBox.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <iprt/stream.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef RT_OS_OS2
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley# undef RT_MAX
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley// from <iprt/cdefs.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley# define RT_MAX(Value1, Value2) ((Value1) >= (Value2) ? (Value1) : (Value2))
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elleyusing namespace com;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#define LOG_GROUP LOG_GROUP_GUI
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/err.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <VBox/log.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <stdlib.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include <signal.h>
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include "VBoxSDL.h"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include "Framebuffer.h"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#include "Ico64x01.h"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#if defined(VBOX_WITH_XPCOM)
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyNS_IMPL_ISUPPORTS1_CI(VBoxSDLFB, IFramebuffer)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir ElleyNS_DECL_CLASSINFO(VBoxSDLFB)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir ElleyNS_IMPL_ISUPPORTS1_CI(VBoxSDLFBOverlay, IFramebufferOverlay)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir ElleyNS_DECL_CLASSINFO(VBoxSDLFBOverlay)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef VBOX_SECURELABEL
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/* function pointers */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elleyextern "C"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyDECLSPEC int (SDLCALL *pTTF_Init)(void);
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyDECLSPEC TTF_Font* (SDLCALL *pTTF_OpenFont)(const char *file, int ptsize);
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyDECLSPEC SDL_Surface* (SDLCALL *pTTF_RenderUTF8_Solid)(TTF_Font *font, const char *text, SDL_Color fg);
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyDECLSPEC void (SDLCALL *pTTF_CloseFont)(TTF_Font *font);
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyDECLSPEC void (SDLCALL *pTTF_Quit)(void);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif /* VBOX_SECURELABEL */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley//
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley// Constructor / destructor
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley//
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * SDL framebuffer constructor. It is called from the main
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * (i.e. SDL) thread. Therefore it is safe to use SDL calls
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * here.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param fFullscreen flag whether we start in fullscreen mode
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param fResizable flag whether the SDL window should be resizable
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param fShowSDLConfig flag whether we print out SDL settings
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param iFixedWidth fixed SDL width (-1 means not set)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param iFixedHeight fixed SDL height (-1 means not set)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleyVBoxSDLFB::VBoxSDLFB(bool fFullscreen, bool fResizable, bool fShowSDLConfig,
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley uint32_t u32FixedWidth, uint32_t u32FixedHeight, uint32_t u32FixedBPP)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley int rc;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley LogFlow(("VBoxSDLFB::VBoxSDLFB\n"));
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley#if defined (RT_OS_WINDOWS)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley refcnt = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mScreen = NULL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mSurfVRAM = NULL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mfInitialized = false;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mfFullscreen = fFullscreen;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mTopOffset = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mfResizable = fResizable;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mfShowSDLConfig = fShowSDLConfig;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mFixedSDLWidth = u32FixedWidth;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mFixedSDLHeight = u32FixedHeight;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mFixedSDLBPP = u32FixedBPP;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mDefaultSDLBPP = 32;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mCenterXOffset = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mCenterYOffset = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* Start with standard screen dimensions. */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mGuestXRes = 640;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mGuestYRes = 480;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mPixelFormat = FramebufferPixelFormat_PixelFormatOpaque;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mPtrVRAM = NULL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mLineSize = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef VBOX_SECURELABEL
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mLabelFont = NULL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mLabelHeight = 0;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mWMIcon = NULL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* memorize the thread that inited us, that's the SDL thread */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mSdlNativeThread = RTThreadNativeSelf();
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley rc = RTCritSectInit(&mUpdateLock);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley AssertMsg(rc == VINF_SUCCESS, ("Error from RTCritSectInit!\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef RT_OS_WINDOWS
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* default to DirectX if nothing else set */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (!getenv("SDL_VIDEODRIVER"))
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley {
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley _putenv("SDL_VIDEODRIVER=directx");
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley// _putenv("SDL_VIDEODRIVER=windib");
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley }
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef RT_OS_LINUX
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* On some X servers the mouse is stuck inside the bottom right corner.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * See http://wiki.clug.org.za/wiki/QEMU_mouse_not_working */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley setenv("SDL_VIDEO_X11_DGAMOUSE", "0", 1);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (rc != 0)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley {
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley RTPrintf("SDL Error: '%s'\n", SDL_GetError());
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley }
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#ifdef RT_OS_LINUX
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley signal(SIGINT, SIG_DFL);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley signal(SIGQUIT, SIG_DFL);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley#endif
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley Assert(videoInfo);
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley if (videoInfo)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley {
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley switch (videoInfo->vfmt->BitsPerPixel)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley {
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley case 16: mDefaultSDLBPP = 16; break;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley case 24: mDefaultSDLBPP = 24; break;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley default:
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley case 32: mDefaultSDLBPP = 32; break;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley }
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley /* output what SDL is capable of */
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley if (mfShowSDLConfig)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley RTPrintf("SDL capabilities:\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Hardware surface support: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Window manager available: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Screen to screen blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Screen to screen colorkey blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Screen to screen alpha blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Memory to screen blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Memory to screen colorkey blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Memory to screen alpha blits accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Color fills accelerated: %s\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Video memory in kilobytes: %d\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley " Optimal bpp mode: %d\n"
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley "SDL video driver: %s\n",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->hw_available ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->wm_available ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_hw ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_hw_CC ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_hw_A ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_sw ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_sw_CC ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_sw_A ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->blit_fill ? "yes" : "no",
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->video_mem,
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley videoInfo->vfmt->BitsPerPixel,
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley getenv("SDL_VIDEODRIVER"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley }
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (12320 == g_cbIco64x01)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley {
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley mWMIcon = SDL_AllocSurface(SDL_SWSURFACE, 64, 64, 24, 0xff, 0xff00, 0xff0000, 0);
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley /** @todo make it as simple as possible. No PNM interpreter here... */
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley if (mWMIcon)
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley {
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley memcpy(mWMIcon->pixels, g_abIco64x01+32, g_cbIco64x01-32);
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley SDL_WM_SetIcon(mWMIcon, NULL);
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley }
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley }
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley resizeGuest();
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley Assert(mScreen);
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley mfInitialized = true;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley}
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir ElleyVBoxSDLFB::~VBoxSDLFB()
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::~VBoxSDLFB\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley RTCritSectDelete(&mUpdateLock);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Returns the current framebuffer width in pixels.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param width Address of result buffer.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(Width)(ULONG *width)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::GetWidth\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (!width)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return E_INVALIDARG;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *width = mGuestXRes;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return S_OK;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Returns the current framebuffer height in pixels.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param height Address of result buffer.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(Height)(ULONG *height)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::GetHeight\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (!height)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return E_INVALIDARG;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *height = mGuestYRes;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley return S_OK;
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley}
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley
ff4b603cc14ea6ea15caaf89a03e927920124af4Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Lock the framebuffer (make its address immutable).
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleySTDMETHODIMP VBoxSDLFB::Lock()
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::Lock\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley RTCritSectEnter(&mUpdateLock);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return S_OK;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Unlock the framebuffer.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleySTDMETHODIMP VBoxSDLFB::Unlock()
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::Unlock\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley RTCritSectLeave(&mUpdateLock);
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return S_OK;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Return the framebuffer start address.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param address Pointer to result variable.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley */
64074e584a56611d7563667e0fcdadd215b0c922Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(Address)(BYTE **address)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDLFB::GetAddress\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (!address)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return E_INVALIDARG;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (mSurfVRAM)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley {
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *address = (BYTE *) mSurfVRAM->pixels;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley }
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley else
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley {
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley /* That's actually rather bad. */
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley AssertMsgFailed(("mSurfVRAM is NULL!\n"));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return E_FAIL;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley }
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley LogFlow(("VBoxSDL::GetAddress returning %p\n", *address));
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley return S_OK;
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley}
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley/**
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * Return the current framebuffer color depth.
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley *
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @returns COM status code
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley * @param colorDepth Address of result variable
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley */
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(ColorDepth)(ULONG *colorDepth)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley{
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley LogFlow(("VBoxSDLFB::GetColorDepth\n"));
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley if (!colorDepth)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return E_INVALIDARG;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley /* get the information directly from the surface in use */
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley Assert(mSurfVRAM);
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *colorDepth = (ULONG)(mSurfVRAM ? mSurfVRAM->format->BitsPerPixel : 0);
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return S_OK;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley}
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley/**
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * Return the current framebuffer line size in bytes.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * @returns COM status code.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * @param lineSize Address of result variable.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley */
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(LineSize)(ULONG *lineSize)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley{
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley LogFlow(("VBoxSDLFB::GetLineSize\n"));
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley if (!lineSize)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return E_INVALIDARG;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley /* get the information directly from the surface */
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley Assert(mSurfVRAM);
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *lineSize = (ULONG)(mSurfVRAM ? mSurfVRAM->pitch : 0);
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return S_OK;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley}
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(PixelFormat) (FramebufferPixelFormat_T *pixelFormat)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley{
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley if (!pixelFormat)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return E_POINTER;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *pixelFormat = mPixelFormat;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return S_OK;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley}
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley/**
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * Returns by how many pixels the guest should shrink its
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * video mode height values.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * @returns COM status code.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley * @param heightReduction Address of result variable.
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley */
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(HeightReduction)(ULONG *heightReduction)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley{
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley if (!heightReduction)
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return E_POINTER;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley#ifdef VBOX_SECURELABEL
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *heightReduction = mLabelHeight;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley#else
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley *heightReduction = 0;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley#endif
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley return S_OK;
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley}
9bda5ab39fc3429191e2272a8be62e230677ecb1Yassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley/**
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * Returns a pointer to an alpha-blended overlay used for displaying status
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * icons above the framebuffer.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley *
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @returns COM status code.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param aOverlay The overlay framebuffer.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir ElleySTDMETHODIMP VBoxSDLFB::COMGETTER(Overlay)(IFramebufferOverlay **aOverlay)
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley{
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley if (!aOverlay)
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley return E_POINTER;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley /* Not yet implemented */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley *aOverlay = 0;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley return S_OK;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley}
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley/**
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * Notify framebuffer of an update.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley *
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @returns COM status code
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param x Update region upper left corner x value.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param y Update region upper left corner y value.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param w Update region width in pixels.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param h Update region height in pixels.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param finished Address of output flag whether the update
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * could be fully processed in this call (which
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * has to return immediately) or VBox should wait
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * for a call to the update complete API before
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * continuing with display updates.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir ElleySTDMETHODIMP VBoxSDLFB::NotifyUpdate(ULONG x, ULONG y,
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley ULONG w, ULONG h, BOOL *finished)
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley{
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley /*
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * The input values are in guest screen coordinates.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley LogFlow(("VBoxSDLFB::NotifyUpdate: x = %d, y = %d, w = %d, h = %d\n",
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley x, y, w, h));
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley#ifdef RT_OS_LINUX
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley /*
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * SDL does not allow us to make this call from any other thread than
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * the main SDL thread (which initialized the video mode). So we have
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * to send an event to the main SDL thread and process it there. For
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * sake of simplicity, we encode all information in the event parameters.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley SDL_Event event;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley event.type = SDL_USEREVENT;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley event.user.type = SDL_USER_EVENT_UPDATERECT;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley // 16 bit is enough for coordinates
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley event.user.data1 = (void*)(x << 16 | y);
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley event.user.data2 = (void*)(w << 16 | h);
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley PushNotifyUpdateEvent(&event);
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley#else /* !RT_OS_LINUX */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley update(x, y, w, h, true /* fGuestRelative */);
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley#endif /* !RT_OS_LINUX */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley /*
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * The Display thread can continue as we will lock the framebuffer
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * from the SDL thread when we get to actually doing the update.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley if (finished)
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley *finished = TRUE;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley return S_OK;
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley}
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley/**
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * Request a display resize from the framebuffer.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley *
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @returns COM status code.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param pixelFormat The requested pixel format.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param vram Pointer to the guest VRAM buffer (can be NULL).
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param lineSize Size of a scanline in bytes.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param w New display width in pixels.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param h New display height in pixels.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * @param finished Address of output flag whether the update
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * could be fully processed in this call (which
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * has to return immediately) or VBox should wait
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * for all call to the resize complete API before
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * continuing with display updates.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir ElleySTDMETHODIMP VBoxSDLFB::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, BYTE *vram,
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley ULONG lineSize, ULONG w, ULONG h, BOOL *finished)
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley{
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley LogFlow(("VBoxSDLFB::RequestResize: w = %d, h = %d, pixelFormat: %d, vram = %p, lineSize = %d\n",
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley w, h, pixelFormat, vram, lineSize));
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley /*
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * SDL does not allow us to make this call from any other thread than
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * the main thread (the one which initialized the video mode). So we
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley * have to send an event to the main SDL thread and tell VBox to wait.
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley */
eb0cde4e6dfdbda08588860534f7ece5776ec3afYassir Elley if (!finished)
{
AssertMsgFailed(("RequestResize requires the finished flag!\n"));
return E_FAIL;
}
mGuestXRes = w;
mGuestYRes = h;
mPixelFormat = pixelFormat;
mPtrVRAM = vram;
mLineSize = lineSize;
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.type = SDL_USER_EVENT_RESIZE;
/* Try multiple times if necessary */
PushSDLEventForSure(&event);
/* we want this request to be processed quickly, so yield the CPU */
RTThreadYield();
*finished = false;
return S_OK;
}
/**
* Returns which acceleration operations are supported
*
* @returns COM status code
* @param operation acceleration operation code
* @supported result
*/
STDMETHODIMP VBoxSDLFB::OperationSupported(FramebufferAccelerationOperation_T operation, BOOL *supported)
{
if (!supported)
return E_POINTER;
// SDL gives us software surfaces, futile
*supported = false;
#if 0
switch (operation)
{
case FramebufferAccelerationOperation_SolidFillAcceleration:
*supported = true;
break;
case FramebufferAccelerationOperation_ScreenCopyAcceleration:
*supported = true;
break;
default:
*supported = false;
}
#endif
return S_OK;
}
/**
* Returns whether we like the given video mode.
*
* @returns COM status code
* @param width video mode width in pixels
* @param height video mode height in pixels
* @param bpp video mode bit depth in bits per pixel
* @param supported pointer to result variable
*/
STDMETHODIMP VBoxSDLFB::VideoModeSupported(ULONG width, ULONG height, ULONG bpp, BOOL *supported)
{
if (!supported)
return E_POINTER;
/* are constraints set? */
if ( ( (mMaxScreenWidth != ~(uint32_t)0)
&& (width > mMaxScreenWidth)
|| ( (mMaxScreenHeight != ~(uint32_t)0)
&& (height > mMaxScreenHeight))))
{
/* nope, we don't want that (but still don't freak out if it is set) */
#ifdef DEBUG
printf("VBoxSDL::VideoModeSupported: we refused mode %dx%dx%d\n", width, height, bpp);
#endif
*supported = false;
}
else
{
/* anything will do */
*supported = true;
}
return S_OK;
}
STDMETHODIMP VBoxSDLFB::SolidFill(ULONG x, ULONG y, ULONG width, ULONG height,
ULONG color, BOOL *handled)
{
if (!handled)
return E_POINTER;
// SDL gives us software surfaces, futile
#if 0
printf("SolidFill: x: %d, y: %d, w: %d, h: %d, color: %d\n", x, y, width, height, color);
SDL_Rect rect = { (Sint16)x, (Sint16)y, (Sint16)width, (Sint16)height };
SDL_FillRect(mScreen, &rect, color);
//SDL_UpdateRect(mScreen, x, y, width, height);
*handled = true;
#else
*handled = false;
#endif
return S_OK;
}
STDMETHODIMP VBoxSDLFB::CopyScreenBits(ULONG xDst, ULONG yDst, ULONG xSrc, ULONG ySrc,
ULONG width, ULONG height, BOOL *handled)
{
if (!handled)
return E_POINTER;
// SDL gives us software surfaces, futile
#if 0
SDL_Rect srcRect = { (Sint16)xSrc, (Sint16)ySrc, (Sint16)width, (Sint16)height };
SDL_Rect dstRect = { (Sint16)xDst, (Sint16)yDst, (Sint16)width, (Sint16)height };
SDL_BlitSurface(mScreen, &srcRect, mScreen, &dstRect);
*handled = true;
#else
*handled = false;
#endif
return S_OK;
}
STDMETHODIMP VBoxSDLFB::GetVisibleRegion(BYTE *aRectangles, ULONG aCount,
ULONG *aCountCopied)
{
PRTRECT rects = (PRTRECT)aRectangles;
if (!rects)
return E_POINTER;
/// @todo
NOREF(aCount);
NOREF(aCountCopied);
return S_OK;
}
STDMETHODIMP VBoxSDLFB::SetVisibleRegion(BYTE *aRectangles, ULONG aCount)
{
PRTRECT rects = (PRTRECT)aRectangles;
if (!rects)
return E_POINTER;
/// @todo
NOREF(aCount);
return S_OK;
}
//
// Internal public methods
//
/**
* Method that does the actual resize of the guest framebuffer and
* then changes the SDL framebuffer setup.
*/
void VBoxSDLFB::resizeGuest()
{
LogFlow(("VBoxSDL::resizeGuest() mGuestXRes: %d, mGuestYRes: %d\n", mGuestXRes, mGuestYRes));
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
int cBitsPerPixel = 32;
uint32_t Rmask, Gmask, Bmask, Amask = 0;
/* pixel characteristics, default to fallback 32bpp format */
if (mPixelFormat == FramebufferPixelFormat_PixelFormatRGB16)
cBitsPerPixel = 16;
else if (mPixelFormat == FramebufferPixelFormat_PixelFormatRGB24)
cBitsPerPixel = 24;
switch (cBitsPerPixel)
{
case 16: Rmask = 0x0000F800; Gmask = 0x000007E0; Bmask = 0x0000001F; break;
default: Rmask = 0x00FF0000; Gmask = 0x0000FF00; Bmask = 0x000000FF; break;
}
/* first free the current surface */
if (mSurfVRAM)
{
SDL_FreeSurface(mSurfVRAM);
mSurfVRAM = NULL;
}
/* is the guest in a linear framebuffer mode we support? */
if (mPixelFormat != FramebufferPixelFormat_PixelFormatOpaque)
{
/* Create a source surface from guest VRAM. */
mSurfVRAM = SDL_CreateRGBSurfaceFrom(mPtrVRAM, mGuestXRes, mGuestYRes, cBitsPerPixel,
mLineSize, Rmask, Gmask, Bmask, Amask);
}
else
{
/* Create a software surface for which SDL allocates the RAM */
mSurfVRAM = SDL_CreateRGBSurface(SDL_SWSURFACE, mGuestXRes, mGuestYRes, cBitsPerPixel,
Rmask, Gmask, Bmask, Amask);
}
LogFlow(("VBoxSDL:: created VRAM surface %p\n", mSurfVRAM));
/* now adjust the SDL resolution */
resizeSDL();
}
/**
* Sets SDL video mode. This is independent from guest video
* mode changes.
*
* @remarks Must be called from the SDL thread!
*/
void VBoxSDLFB::resizeSDL(void)
{
LogFlow(("VBoxSDL:resizeSDL\n"));
/*
* We request a hardware surface from SDL so that we can perform
* accelerated system memory to VRAM blits. The way video handling
* works it that on the one hand we have the screen surface from SDL
* and on the other hand we have a software surface that we create
* using guest VRAM memory for linear modes and using SDL allocated
* system memory for text and non linear graphics modes. We never
* directly write to the screen surface but always use SDL blitting
* functions to blit from our system memory surface to the VRAM.
* Therefore, SDL can take advantage of hardware acceleration.
*/
int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
if (mfResizable)
sdlFlags |= SDL_RESIZABLE;
if (mfFullscreen)
sdlFlags |= SDL_FULLSCREEN;
/*
* Now we have to check whether there are video mode restrictions
*/
SDL_Rect **modes;
/* Get available fullscreen/hardware modes */
modes = SDL_ListModes(NULL, sdlFlags);
Assert(modes != NULL);
/* -1 means that any mode is possible (usually non fullscreen) */
if (modes != (SDL_Rect **)-1)
{
/*
* according to the SDL documentation, the API guarantees that
* the modes are sorted from larger to smaller, so we just
* take the first entry as the maximum.
*/
mMaxScreenWidth = modes[0]->w;
mMaxScreenHeight = modes[0]->h;
}
else
{
/* no restriction */
mMaxScreenWidth = ~(uint32_t)0;
mMaxScreenHeight = ~(uint32_t)0;
}
uint32_t newWidth;
uint32_t newHeight;
/* reset the centering offsets */
mCenterXOffset = 0;
mCenterYOffset = 0;
/* we either have a fixed SDL resolution or we take the guest's */
if (mFixedSDLWidth != ~(uint32_t)0)
{
newWidth = mFixedSDLWidth;
newHeight = mFixedSDLHeight;
}
else
{
newWidth = RT_MIN(mGuestXRes, mMaxScreenWidth);
#ifdef VBOX_SECURELABEL
newHeight = RT_MIN(mGuestYRes + mLabelHeight, mMaxScreenHeight);
#else
newHeight = RT_MIN(mGuestYRes, mMaxScreenHeight);
#endif
}
/* we don't have any extra space by default */
mTopOffset = 0;
/*
* Now set the screen resolution and get the surface pointer
* @todo BPP is not supported!
*/
mScreen = SDL_SetVideoMode(newWidth, newHeight, 0, sdlFlags);
#ifdef VBOX_SECURELABEL
/*
* For non fixed SDL resolution, the above call tried to add the label height
* to the guest height. If it worked, we have an offset. If it didn't the below
* code will try again with the original guest resolution.
*/
if (mFixedSDLWidth == ~(uint32_t)0)
{
/* if it didn't work, then we have to go for the original resolution and paint over the guest */
if (!mScreen)
{
mScreen = SDL_SetVideoMode(newWidth, newHeight - mLabelHeight, 0, sdlFlags);
}
else
{
/* we now have some extra space */
mTopOffset = mLabelHeight;
}
}
else
{
/* in case the guest resolution is small enough, we do have a top offset */
if (mFixedSDLHeight - mGuestYRes >= mLabelHeight)
mTopOffset = mLabelHeight;
/* we also might have to center the guest picture */
if (mFixedSDLWidth > mGuestXRes)
mCenterXOffset = (mFixedSDLWidth - mGuestXRes) / 2;
if (mFixedSDLHeight > mGuestYRes + mLabelHeight)
mCenterYOffset = (mFixedSDLHeight - (mGuestYRes + mLabelHeight)) / 2;
}
#endif
AssertMsg(mScreen, ("Error: SDL_SetVideoMode failed!\n"));
if (mScreen)
{
#ifdef VBOX_WIN32_UI
/* inform the UI code */
resizeUI(mScreen->w, mScreen->h);
#endif
if (mfShowSDLConfig)
RTPrintf("Resized to %dx%d, screen surface type: %s\n", mScreen->w, mScreen->h,
((mScreen->flags & SDL_HWSURFACE) == 0) ? "software" : "hardware");
}
repaint();
}
/**
* Update specified framebuffer area. The coordinates can either be
* relative to the guest framebuffer or relative to the screen.
*
* @remarks Must be called from the SDL thread on Linux!
* @param x left column
* @param y top row
* @param w width in pixels
* @param h height in pixels
* @param fGuestRelative flag whether the above values are guest relative or screen relative;
*/
void VBoxSDLFB::update(int x, int y, int w, int h, bool fGuestRelative)
{
#ifdef RT_OS_LINUX
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
#endif
Assert(mScreen);
Assert(mSurfVRAM);
if (!mScreen || !mSurfVRAM)
return;
/* the source and destination rectangles */
SDL_Rect srcRect;
SDL_Rect dstRect;
/* this is how many pixels we have to cut off from the height for this specific blit */
int yCutoffGuest = 0;
#ifdef VBOX_SECURELABEL
bool fPaintLabel = false;
/* if we have a label and no space for it, we have to cut off a bit */
if (mLabelHeight && !mTopOffset)
{
if (y < (int)mLabelHeight)
yCutoffGuest = mLabelHeight - y;
}
#endif
/**
* If we get a SDL window relative update, we
* just perform a full screen update to keep things simple.
*
* @todo improve
*/
if (!fGuestRelative)
{
#ifdef VBOX_SECURELABEL
/* repaint the label if necessary */
if (y < (int)mLabelHeight)
fPaintLabel = true;
#endif
x = 0;
w = mGuestXRes;
y = 0;
h = mGuestYRes;
}
srcRect.x = x;
srcRect.y = y + yCutoffGuest;
srcRect.w = w;
srcRect.h = RT_MAX(0, h - yCutoffGuest);
/*
* Destination rectangle is just offset by the label height.
* There are two cases though: label height is added to the
* guest resolution (mTopOffset == mLabelHeight; yCutoffGuest == 0)
* or the label cuts off a portion of the guest screen (mTopOffset == 0;
* yCutoffGuest >= 0)
*/
dstRect.x = x + mCenterXOffset;
#ifdef VBOX_SECURELABEL
dstRect.y = RT_MAX(mLabelHeight, y + yCutoffGuest + mTopOffset) + mCenterYOffset;
#else
dstRect.y = y + yCutoffGuest + mTopOffset + mCenterYOffset;
#endif
dstRect.w = w;
dstRect.h = RT_MAX(0, h - yCutoffGuest);
//RTPrintf("y = %d h = %d mapped to srcY %d srcH %d mapped to dstY = %d dstH %d (guestrel: %d, mLabelHeight: %d, mTopOffset: %d)\n",
// y, h, srcRect.y, srcRect.h, dstRect.y, dstRect.h, fGuestRelative, mLabelHeight, mTopOffset);
/*
* Now we just blit
*/
SDL_BlitSurface(mSurfVRAM, &srcRect, mScreen, &dstRect);
/* hardware surfaces don't need update notifications */
if ((mScreen->flags & SDL_HWSURFACE) == 0)
SDL_UpdateRect(mScreen, dstRect.x, dstRect.y, dstRect.w, dstRect.h);
#ifdef VBOX_SECURELABEL
if (fPaintLabel)
paintSecureLabel(0, 0, 0, 0, false);
#endif
}
/**
* Repaint the whole framebuffer
*
* @remarks Must be called from the SDL thread!
*/
void VBoxSDLFB::repaint()
{
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
LogFlow(("VBoxSDLFB::repaint\n"));
update(0, 0, mScreen->w, mScreen->h, false /* fGuestRelative */);
}
bool VBoxSDLFB::getFullscreen()
{
LogFlow(("VBoxSDLFB::getFullscreen\n"));
return mfFullscreen;
}
/**
* Toggle fullscreen mode
*
* @remarks Must be called from the SDL thread!
*/
void VBoxSDLFB::setFullscreen(bool fFullscreen)
{
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
LogFlow(("VBoxSDLFB::SetFullscreen: fullscreen: %d\n", fFullscreen));
mfFullscreen = fFullscreen;
/* only change the SDL resolution, do not touch the guest framebuffer */
resizeSDL();
}
/**
* Returns the current x offset of the start of the guest screen
*
* @returns current x offset in pixels
*/
int VBoxSDLFB::getXOffset()
{
/* there can only be an offset for centering */
return mCenterXOffset;
}
/**
* Returns the current y offset of the start of the guest screen
*
* @returns current y offset in pixels
*/
int VBoxSDLFB::getYOffset()
{
/* we might have a top offset and a center offset */
return mTopOffset + mCenterYOffset;
}
#ifdef VBOX_SECURELABEL
/**
* Setup the secure labeling parameters
*
* @returns VBox status code
* @param height height of the secure label area in pixels
* @param font file path fo the TrueType font file
* @param pointsize font size in points
*/
int VBoxSDLFB::initSecureLabel(uint32_t height, char *font, uint32_t pointsize)
{
LogFlow(("VBoxSDLFB:initSecureLabel: new offset: %d pixels, new font: %s, new pointsize: %d\n",
height, font, pointsize));
mLabelHeight = height;
Assert(font);
pTTF_Init();
mLabelFont = pTTF_OpenFont(font, pointsize);
if (!mLabelFont)
{
AssertMsgFailed(("Failed to open TTF font file %s\n", font));
return VERR_OPEN_FAILED;
}
mSecureLabelColorFG = 0x0000FF00;
mSecureLabelColorBG = 0x00FFFF00;
repaint();
return VINF_SUCCESS;
}
/**
* Set the secure label text and repaint the label
*
* @param text UTF-8 string of new label
* @remarks must be called from the SDL thread!
*/
void VBoxSDLFB::setSecureLabelText(const char *text)
{
mSecureLabelText = text;
paintSecureLabel(0, 0, 0, 0, true);
}
/**
* Sets the secure label background color.
*
* @param colorFG encoded RGB value for text
* @param colorBG encored RGB value for background
* @remarks must be called from the SDL thread!
*/
void VBoxSDLFB::setSecureLabelColor(uint32_t colorFG, uint32_t colorBG)
{
mSecureLabelColorFG = colorFG;
mSecureLabelColorBG = colorBG;
paintSecureLabel(0, 0, 0, 0, true);
}
/**
* Paint the secure label if required
*
* @param fForce Force the repaint
* @remarks must be called from the SDL thread!
*/
void VBoxSDLFB::paintSecureLabel(int x, int y, int w, int h, bool fForce)
{
#ifdef RT_OS_LINUX
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
#endif
/* only when the function is present */
if (!pTTF_RenderUTF8_Solid)
return;
/* check if we can skip the paint */
if (!fForce && ((uint32_t)y > mLabelHeight))
{
return;
}
/* first fill the background */
SDL_Rect rect = {0, 0, (Uint16)mScreen->w, (Uint16)mLabelHeight};
SDL_FillRect(mScreen, &rect, SDL_MapRGB(mScreen->format,
(mSecureLabelColorBG & 0x00FF0000) >> 16, /* red */
(mSecureLabelColorBG & 0x0000FF00) >> 8, /* green */
mSecureLabelColorBG & 0x000000FF)); /* blue */
/* now the text */
if (mLabelFont != NULL && mSecureLabelText)
{
SDL_Color clrFg = {(mSecureLabelColorFG & 0x00FF0000) >> 16,
(mSecureLabelColorFG & 0x0000FF00) >> 8,
mSecureLabelColorFG & 0x000000FF, 0};
SDL_Surface *sText = pTTF_RenderUTF8_Solid(mLabelFont, mSecureLabelText.raw(), clrFg);
rect.x = 10;
SDL_BlitSurface(sText, NULL, mScreen, &rect);
SDL_FreeSurface(sText);
}
/* make sure to update the screen */
SDL_UpdateRect(mScreen, 0, 0, mScreen->w, mLabelHeight);
}
#endif /* VBOX_SECURELABEL */
/**
* Terminate SDL
*
* @remarks must be called from the SDL thread!
*/
void VBoxSDLFB::uninit()
{
AssertMsg(mSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
if (mSurfVRAM)
{
SDL_FreeSurface(mSurfVRAM);
mSurfVRAM = NULL;
}
SDL_QuitSubSystem(SDL_INIT_VIDEO);
#ifdef VBOX_SECURELABEL
if (mLabelFont)
pTTF_CloseFont(mLabelFont);
if (pTTF_Quit)
pTTF_Quit();
#endif
mScreen = NULL;
if (mWMIcon)
{
SDL_FreeSurface(mWMIcon);
mWMIcon = NULL;
}
}
// IFramebufferOverlay
///////////////////////////////////////////////////////////////////////////////////
/**
* Constructor for the VBoxSDLFBOverlay class (IFramebufferOverlay implementation)
*
* @param x Initial X offset for the overlay
* @param y Initial Y offset for the overlay
* @param width Initial width for the overlay
* @param height Initial height for the overlay
* @param visible Whether the overlay is initially visible
* @param alpha Initial alpha channel value for the overlay
*/
VBoxSDLFBOverlay::VBoxSDLFBOverlay(ULONG x, ULONG y, ULONG width, ULONG height,
BOOL visible, VBoxSDLFB *aParent) :
mOverlayX(x), mOverlayY(y), mOverlayWidth(width),
mOverlayHeight(height), mOverlayVisible(visible),
mParent(aParent)
{}
/**
* Destructor for the VBoxSDLFBOverlay class.
*/
VBoxSDLFBOverlay::~VBoxSDLFBOverlay()
{
SDL_FreeSurface(mBlendedBits);
SDL_FreeSurface(mOverlayBits);
}
/**
* Perform any initialisation of the overlay that can potentially fail
*
* @returns S_OK on success or the reason for the failure
*/
HRESULT VBoxSDLFBOverlay::init()
{
mBlendedBits = SDL_CreateRGBSurface(SDL_ANYFORMAT, mOverlayWidth, mOverlayHeight, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0);
AssertMsgReturn(mBlendedBits != NULL, ("Failed to create an SDL surface\n"),
E_OUTOFMEMORY);
mOverlayBits = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, mOverlayWidth,
mOverlayHeight, 32, 0x00ff0000, 0x0000ff00,
0x000000ff, 0xff000000);
AssertMsgReturn(mOverlayBits != NULL, ("Failed to create an SDL surface\n"),
E_OUTOFMEMORY);
return S_OK;
}
/**
* Returns the current overlay X offset in pixels.
*
* @returns COM status code
* @param x Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(X)(ULONG *x)
{
LogFlow(("VBoxSDLFBOverlay::GetX\n"));
if (!x)
return E_INVALIDARG;
*x = mOverlayX;
return S_OK;
}
/**
* Returns the current overlay height in pixels.
*
* @returns COM status code
* @param height Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Y)(ULONG *y)
{
LogFlow(("VBoxSDLFBOverlay::GetY\n"));
if (!y)
return E_INVALIDARG;
*y = mOverlayY;
return S_OK;
}
/**
* Returns the current overlay width in pixels. In fact, this returns the line size.
*
* @returns COM status code
* @param width Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Width)(ULONG *width)
{
LogFlow(("VBoxSDLFBOverlay::GetWidth\n"));
if (!width)
return E_INVALIDARG;
*width = mOverlayBits->pitch;
return S_OK;
}
/**
* Returns the current overlay line size in pixels.
*
* @returns COM status code
* @param lineSize Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(LineSize)(ULONG *lineSize)
{
LogFlow(("VBoxSDLFBOverlay::GetLineSize\n"));
if (!lineSize)
return E_INVALIDARG;
*lineSize = mOverlayBits->pitch;
return S_OK;
}
/**
* Returns the current overlay height in pixels.
*
* @returns COM status code
* @param height Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Height)(ULONG *height)
{
LogFlow(("VBoxSDLFBOverlay::GetHeight\n"));
if (!height)
return E_INVALIDARG;
*height = mOverlayHeight;
return S_OK;
}
/**
* Returns whether the overlay is currently visible.
*
* @returns COM status code
* @param visible Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Visible)(BOOL *visible)
{
LogFlow(("VBoxSDLFBOverlay::GetVisible\n"));
if (!visible)
return E_INVALIDARG;
*visible = mOverlayVisible;
return S_OK;
}
/**
* Sets whether the overlay is currently visible.
*
* @returns COM status code
* @param visible New value.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMSETTER(Visible)(BOOL visible)
{
LogFlow(("VBoxSDLFBOverlay::SetVisible\n"));
mOverlayVisible = visible;
return S_OK;
}
/**
* Returns the value of the global alpha channel.
*
* @returns COM status code
* @param alpha Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Alpha)(ULONG *alpha)
{
LogFlow(("VBoxSDLFBOverlay::GetAlpha\n"));
return E_NOTIMPL;
}
/**
* Sets whether the overlay is currently visible.
*
* @returns COM status code
* @param alpha new value.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMSETTER(Alpha)(ULONG alpha)
{
LogFlow(("VBoxSDLFBOverlay::SetAlpha\n"));
return E_NOTIMPL;
}
/**
* Returns the address of the framebuffer bits for writing to.
*
* @returns COM status code
* @param alpha Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Address)(ULONG *address)
{
LogFlow(("VBoxSDLFBOverlay::GetAddress\n"));
if (!address)
return E_INVALIDARG;
*address = (uintptr_t) mOverlayBits->pixels;
return S_OK;
}
/**
* Returns the current colour depth. In fact, this is always 32bpp.
*
* @returns COM status code
* @param colorDepth Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(ColorDepth)(ULONG *colorDepth)
{
LogFlow(("VBoxSDLFBOverlay::GetColorDepth\n"));
if (!colorDepth)
return E_INVALIDARG;
*colorDepth = 32;
return S_OK;
}
/**
* Returns the current pixel format. In fact, this is always RGB32.
*
* @returns COM status code
* @param pixelFormat Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(PixelFormat)(FramebufferPixelFormat_T *pixelFormat)
{
LogFlow(("VBoxSDLFBOverlay::GetPixelFormat\n"));
if (!pixelFormat)
return E_INVALIDARG;
*pixelFormat = FramebufferPixelFormat_PixelFormatRGB32;
return S_OK;
}
/**
* Returns the height reduction. In fact, this is always 0.
*
* @returns COM status code
* @param heightReduction Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(HeightReduction)(ULONG *heightReduction)
{
LogFlow(("VBoxSDLFBOverlay::GetHeightReduction\n"));
if (!heightReduction)
return E_INVALIDARG;
*heightReduction = 0;
return S_OK;
}
/**
* Returns the overlay for this framebuffer. Obviously, we return NULL here.
*
* @returns COM status code
* @param overlay Address of result buffer.
*/
STDMETHODIMP VBoxSDLFBOverlay::COMGETTER(Overlay)(IFramebufferOverlay **aOverlay)
{
LogFlow(("VBoxSDLFBOverlay::GetOverlay\n"));
if (!aOverlay)
return E_INVALIDARG;
*aOverlay = 0;
return S_OK;
}
/**
* Lock the overlay. This should not be used - lock the parent IFramebuffer instead.
*
* @returns COM status code
*/
STDMETHODIMP VBoxSDLFBOverlay::Lock()
{
LogFlow(("VBoxSDLFBOverlay::Lock\n"));
AssertMsgFailed(("You should not attempt to lock an IFramebufferOverlay object -\n"
"lock the parent IFramebuffer object instead.\n"));
return E_NOTIMPL;
}
/**
* Unlock the overlay.
*
* @returns COM status code
*/
STDMETHODIMP VBoxSDLFBOverlay::Unlock()
{
LogFlow(("VBoxSDLFBOverlay::Unlock\n"));
AssertMsgFailed(("You should not attempt to lock an IFramebufferOverlay object -\n"
"lock the parent IFramebuffer object instead.\n"));
return E_NOTIMPL;
}
/**
* Change the X and Y co-ordinates of the overlay area.
*
* @returns COM status code
* @param x New X co-ordinate.
* @param y New Y co-ordinate.
*/
STDMETHODIMP VBoxSDLFBOverlay::Move(ULONG x, ULONG y)
{
mOverlayX = x;
mOverlayY = y;
return S_OK;
}
/**
* Notify the overlay that a section of the framebuffer has been redrawn.
*
* @returns COM status code
* @param x X co-ordinate of upper left corner of modified area.
* @param y Y co-ordinate of upper left corner of modified area.
* @param w Width of modified area.
* @param h Height of modified area.
* @retval finished Set if the operation has completed.
*
* All we do here is to send a request to the parent to update the affected area,
* translating between our co-ordinate system and the parent's. It would be have
* been better to call the parent directly, but such is life. We leave bounds
* checking to the parent.
*/
STDMETHODIMP VBoxSDLFBOverlay::NotifyUpdate(ULONG x, ULONG y,
ULONG w, ULONG h, BOOL *finished)
{
return mParent->NotifyUpdate(x + mOverlayX, y + mOverlayY, w, h, finished);
}
/**
* Change the dimensions of the overlay.
*
* @returns COM status code
* @param pixelFormat Must be FramebufferPixelFormat_PixelFormatRGB32.
* @param vram Must be NULL.
* @param lineSize Ignored.
* @param w New overlay width.
* @param h New overlay height.
* @retval finished Set if the operation has completed.
*/
STDMETHODIMP VBoxSDLFBOverlay::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat,
ULONG vram, ULONG lineSize, ULONG w,
ULONG h, BOOL *finished)
{
AssertReturn(pixelFormat == FramebufferPixelFormat_PixelFormatRGB32, E_INVALIDARG);
AssertReturn(vram == 0, E_INVALIDARG);
mOverlayWidth = w;
mOverlayHeight = h;
SDL_FreeSurface(mOverlayBits);
mBlendedBits = SDL_CreateRGBSurface(SDL_ANYFORMAT, mOverlayWidth, mOverlayHeight, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0);
AssertMsgReturn(mBlendedBits != NULL, ("Failed to create an SDL surface\n"),
E_OUTOFMEMORY);
mOverlayBits = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, mOverlayWidth,
mOverlayHeight, 32, 0x00ff0000, 0x0000ff00,
0x000000ff, 0xff000000);
AssertMsgReturn(mOverlayBits != NULL, ("Failed to create an SDL surface\n"),
E_OUTOFMEMORY);
return S_OK;
}
/**
* Queries whether we support a given accelerated opperation. Since we do not currently
* support any accelerated operations, we always return false in supported.
*
* @returns COM status code
* @param operation The operation being queried
* @retval supported Whether or not we support that operation
*/
STDMETHODIMP VBoxSDLFBOverlay::OperationSupported(FramebufferAccelerationOperation_T
operation, BOOL *supported)
{
if (!supported)
return E_POINTER;
/* We currently do not support any acceleration here, and will probably not in
the forseeable future. */
*supported = false;
return S_OK;
}
/**
* Returns whether we like the given video mode.
*
* @returns COM status code
* @param width video mode width in pixels
* @param height video mode height in pixels
* @param bpp video mode bit depth in bits per pixel
* @retval supported pointer to result variable
*
* Basically, we support anything with 32bpp.
*/
STDMETHODIMP VBoxSDLFBOverlay::VideoModeSupported(ULONG width, ULONG height, ULONG bpp,
BOOL *supported)
{
if (!supported)
return E_POINTER;
if (bpp == 32)
*supported = true;
else
*supported = false;
return S_OK;
}
/**
* Fill an area of the framebuffer with solid colour
*
* @returns COM status code
* @param x X co-ordinate of the area to fill, top-left corner
* @param y Y co-ordinate of the area to fill, top-left corner
* @param width width of the area to fill
* @param height height of the area to fill
* @param color colour with which to fill the area
* @retval handled whether we support this operation or not
*
* Since we currently do not have any way of doing this faster than
* the VGA device, we simply false in handled.
*/
STDMETHODIMP VBoxSDLFBOverlay::SolidFill(ULONG x, ULONG y, ULONG width,
ULONG height, ULONG color, BOOL *handled)
{
LogFlow(("VBoxSDLFBOverlay::SolidFill called\n"));
if (!handled)
return E_POINTER;
*handled = false;
return S_OK;
}
/**
* Since we currently do not have any way of doing this faster than
* the VGA device, we simply false in handled.
*/
STDMETHODIMP VBoxSDLFBOverlay::CopyScreenBits(ULONG xDst, ULONG yDst, ULONG xSrc,
ULONG ySrc, ULONG width,
ULONG height, BOOL *handled)
{
LogFlow(("VBoxSDLFBOverlay::CopyScreenBits called.\n"));
if (!handled)
return E_POINTER;
*handled = false;
return S_OK;
}