Framebuffer.cpp revision 0d1906af822edf875043735798ad1c64f2cdaab2
#
endif /* VBOX_SECURELABEL */// Constructor / destructor * SDL framebuffer constructor. It is called from the main * (i.e. SDL) thread. Therefore it is safe to use SDL calls * @param fFullscreen flag whether we start in fullscreen mode * @param fResizable flag whether the SDL window should be resizable * @param fShowSDLConfig flag whether we print out SDL settings * @param fKeepHostRes flag whether we switch the host screen resolution * when switching to fullscreen or not * @param iFixedWidth fixed SDL width (-1 means not set) * @param iFixedHeight fixed SDL height (-1 means not set) LogFlow((
"VBoxSDLFB::VBoxSDLFB\n"));
/* Start with standard screen dimensions. */ /* memorize the thread that inited us, that's the SDL thread */ /* default to DirectX if nothing else set */ _putenv(
"SDL_VIDEODRIVER=directx");
// _putenv("SDL_VIDEODRIVER=windib"); /* On some X servers the mouse is stuck inside the bottom right corner. RTEnvSet(
"SDL_VIDEO_X11_DGAMOUSE",
"0");
/* output what SDL is capable of */ " Hardware surface support: %s\n" " Window manager available: %s\n" " Screen to screen blits accelerated: %s\n" " Screen to screen colorkey blits accelerated: %s\n" " Screen to screen alpha blits accelerated: %s\n" " Memory to screen blits accelerated: %s\n" " Memory to screen colorkey blits accelerated: %s\n" " Memory to screen alpha blits accelerated: %s\n" " Color fills accelerated: %s\n" " Video memory in kilobytes: %d\n" " Optimal bpp mode: %d\n" "SDL video driver: %s\n",
/** @todo make it as simple as possible. No PNM interpreter here... */ LogFlow((
"VBoxSDLFB::~VBoxSDLFB\n"));
* Returns the current framebuffer width in pixels. * @returns COM status code * @param width Address of result buffer. LogFlow((
"VBoxSDLFB::GetWidth\n"));
* Returns the current framebuffer height in pixels. * @returns COM status code * @param height Address of result buffer. LogFlow((
"VBoxSDLFB::GetHeight\n"));
* Lock the framebuffer (make its address immutable). * @returns COM status code * Unlock the framebuffer. * @returns COM status code * Return the framebuffer start address. * @returns COM status code. * @param address Pointer to result variable. LogFlow((
"VBoxSDLFB::GetAddress\n"));
/* That's actually rather bad. */ * Return the current framebuffer color depth. * @returns COM status code * @param bitsPerPixel Address of result variable LogFlow((
"VBoxSDLFB::GetBitsPerPixel\n"));
/* get the information directly from the surface in use */ * Return the current framebuffer line size in bytes. * @returns COM status code. * @param lineSize Address of result variable. LogFlow((
"VBoxSDLFB::GetBytesPerLine\n"));
/* get the information directly from the surface */ * Returns by how many pixels the guest should shrink its * video mode height values. * @returns COM status code. * @param heightReduction Address of result variable. * Returns a pointer to an alpha-blended overlay used for displaying status * icons above the framebuffer. * @returns COM status code. * @param aOverlay The overlay framebuffer. /* Not yet implemented */ * Returns handle of window where framebuffer context is being drawn * @returns COM status code. * @param winId Handle of associated window. * Notify framebuffer of an update. * @returns COM status code * @param x Update region upper left corner x value. * @param y Update region upper left corner y value. * @param w Update region width in pixels. * @param h Update region height in pixels. * @param finished Address of output flag whether the update * could be fully processed in this call (which * has to return immediately) or VBox should wait * for a call to the update complete API before * continuing with display updates. * The input values are in guest screen coordinates. LogFlow((
"VBoxSDLFB::NotifyUpdate: x = %d, y = %d, w = %d, h = %d\n",
* SDL does not allow us to make this call from any other thread than * the main SDL thread (which initialized the video mode). So we have * to send an event to the main SDL thread and process it there. For * sake of simplicity, we encode all information in the event parameters. // 16 bit is enough for coordinates #
else /* !VBOXSDL_WITH_X11 */ update(x, y, w, h,
true /* fGuestRelative */);
#
endif /* !VBOXSDL_WITH_X11 */ * The Display thread can continue as we will lock the framebuffer * from the SDL thread when we get to actually doing the update. * Request a display resize from the framebuffer. * @returns COM status code. * @param pixelFormat The requested pixel format. * @param vram Pointer to the guest VRAM buffer (can be NULL). * @param bitsPerPixel Color depth in bits. * @param bytesPerLine Size of a scanline in bytes. * @param w New display width in pixels. * @param h New display height in pixels. * @param finished Address of output flag whether the update * could be fully processed in this call (which * has to return immediately) or VBox should wait * for all call to the resize complete API before * continuing with display updates. LogFlowFunc ((
"w=%d, h=%d, pixelFormat=0x%08lX, vram=%p, " * SDL does not allow us to make this call from any other thread than * the main thread (the one which initialized the video mode). So we * have to send an event to the main SDL thread and tell VBox to wait. * Optimize the case when the guest has changed only the VRAM ptr * and the framebuffer uses the guest VRAM as the source bitmap. /* Try multiple times if necessary */ /* we want this request to be processed quickly, so yield the CPU */ * Returns which acceleration operations are supported * @returns COM status code * @param operation acceleration operation code // SDL gives us software surfaces, futile * 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 /* are constraints set? */ /* nope, we don't want that (but still don't freak out if it is set) */ // SDL gives us software surfaces, futile //SDL_UpdateRect(mScreen, x, y, width, height); // SDL gives us software surfaces, futile // Internal public methods * Method that does the actual resize of the guest framebuffer and * then changes the SDL framebuffer setup. (
"Wrong thread! SDL is not threadsafe!\n"));
/* pixel characteristics. if we don't support the format directly, we will * fallback to the indirect 32bpp buffer (mUsesGuestVRAM will remain /* the fallback buffer is always 32bpp */ /* the fallback buffer is always RGB, 32bpp */ case 16:
Rmask =
0x0000F800;
Gmask =
0x000007E0;
Bmask =
0x0000001F;
break;
default:
Rmask =
0x00FF0000;
Gmask =
0x0000FF00;
Bmask =
0x000000FF;
break;
/* first free the current surface */ /* is the guest in a linear framebuffer mode we support? */ /* Create a source surface from guest VRAM. */ /* Create a software surface for which SDL allocates the RAM */ * Same size has been requested and the framebuffer still uses the guest VRAM. * Reset the condition and return. LogFlow((
"VBoxSDL:: the same resolution requested, skipping the resize.\n"));
/* now adjust the SDL resolution */ * Sets SDL video mode. This is independent from guest video * @remarks Must be called from the SDL thread! * 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. #
ifndef RT_OS_OS2 /* doesn't seem to work for some reason... */ * Now we have to check whether there are video mode restrictions /* -1 means that any mode is possible (usually non fullscreen) */ * 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. /* reset the centering offsets */ /* we either have a fixed SDL resolution or we take the guest's */ /* we don't have any extra space by default */ * Now set the screen resolution and get the surface pointer * @todo BPP is not supported! * 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 it didn't work, then we have to go for the original resolution and paint over the guest */ /* we now have some extra space */ /* in case the guest resolution is small enough, we do have a top offset */ /* we also might have to center the guest picture */ * 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 w width in pixels * @param h height in pixels * @param fGuestRelative flag whether the above values are guest relative or screen relative; /* the source and destination rectangles */ /* this is how many pixels we have to cut off from the height for this specific blit */ /* if we have a label and no space for it, we have to cut off a bit */ * If we get a SDL window relative update, we * just perform a full screen update to keep things simple. /* repaint the label if necessary */ * 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; //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); /* hardware surfaces don't need update notifications */ * Repaint the whole framebuffer * @remarks Must be called from the SDL thread! LogFlow((
"VBoxSDLFB::getFullscreen\n"));
* @remarks Must be called from the SDL thread! /* only change the SDL resolution, do not touch the guest framebuffer */ * Return the geometry of the host. This isn't very well tested but it seems * to work at least on Linux hosts. /* -1 means that any mode is possible (usually non fullscreen) */ * 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 * XXX Crude Xinerama hack :-/ * Returns the current x offset of the start of the guest screen * @returns current x offset in pixels /* there can only be an offset for centering */ * Returns the current y offset of the start of the guest screen * @returns current y offset in pixels /* we might have a top offset and a center offset */ * 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 LogFlow((
"VBoxSDLFB:initSecureLabel: new offset: %d pixels, new font: %s, new pointsize: %d\n",
* 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! * 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! * Paint the secure label if required * @param fForce Force the repaint * @remarks must be called from the SDL thread! /* only when the function is present */ /* check if we can skip the paint */ /* first fill the background */ /* make sure to update the screen */ #
endif /* VBOX_SECURELABEL */ * @remarks must be called from the SDL thread! /////////////////////////////////////////////////////////////////////////////////// * 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 * Destructor for the VBoxSDLFBOverlay class. * Perform any initialisation of the overlay that can potentially fail * @returns S_OK on success or the reason for the failure 0x00ff0000,
0x0000ff00,
0x000000ff, 0);
* Returns the current overlay X offset in pixels. * @returns COM status code * @param x Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetX\n"));
* Returns the current overlay height in pixels. * @returns COM status code * @param height Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetY\n"));
* Returns the current overlay width in pixels. In fact, this returns the line size. * @returns COM status code * @param width Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetWidth\n"));
* Returns the current overlay line size in pixels. * @returns COM status code * @param lineSize Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetBytesPerLine\n"));
* Returns the current overlay height in pixels. * @returns COM status code * @param height Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetHeight\n"));
* Returns whether the overlay is currently visible. * @returns COM status code * @param visible Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetVisible\n"));
* Sets whether the overlay is currently visible. * @returns COM status code * @param visible New value. LogFlow((
"VBoxSDLFBOverlay::SetVisible\n"));
* Returns the value of the global alpha channel. * @returns COM status code * @param alpha Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetAlpha\n"));
* Sets whether the overlay is currently visible. * @returns COM status code * @param alpha new value. LogFlow((
"VBoxSDLFBOverlay::SetAlpha\n"));
* Returns the address of the framebuffer bits for writing to. * @returns COM status code * @param alpha Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetAddress\n"));
* Returns the current colour depth. In fact, this is always 32bpp. * @returns COM status code * @param bitsPerPixel Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetBitsPerPixel\n"));
* Returns the current pixel format. In fact, this is always RGB. * @returns COM status code * @param pixelFormat Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetPixelFormat\n"));
* Returns whether the guest VRAM is used directly. In fact, this is always FALSE. * @returns COM status code * @param usesGuestVRAM Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetUsesGuestVRAM\n"));
* Returns the height reduction. In fact, this is always 0. * @returns COM status code * @param heightReduction Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetHeightReduction\n"));
* Returns the overlay for this framebuffer. Obviously, we return NULL here. * @returns COM status code * @param overlay Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetOverlay\n"));
* Returns associated window handle. We return NULL here. * @returns COM status code * @param winId Address of result buffer. LogFlow((
"VBoxSDLFBOverlay::GetWinId\n"));
* Lock the overlay. This should not be used - lock the parent IFramebuffer instead. * @returns COM status code LogFlow((
"VBoxSDLFBOverlay::Lock\n"));
AssertMsgFailed((
"You should not attempt to lock an IFramebufferOverlay object -\n" "lock the parent IFramebuffer object instead.\n"));
* @returns COM status code LogFlow((
"VBoxSDLFBOverlay::Unlock\n"));
AssertMsgFailed((
"You should not attempt to lock an IFramebufferOverlay object -\n" "lock the parent IFramebuffer object instead.\n"));
* 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. * 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. * 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. 0x00ff0000,
0x0000ff00,
0x000000ff, 0);
* 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 /* We currently do not support any acceleration here, and will probably not in the forseeable future. */ * 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. * 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. LogFlow((
"VBoxSDLFBOverlay::SolidFill called\n"));
* Since we currently do not have any way of doing this faster than * the VGA device, we simply false in handled. LogFlow((
"VBoxSDLFBOverlay::CopyScreenBits called.\n"));