326 lines
9.0 KiB
C++
326 lines
9.0 KiB
C++
/*
|
|
* \brief Genode-specific video backend
|
|
* \author Stefan Kalkowski
|
|
* \date 2008-12-12
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) <2008> Stefan Kalkowski
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use,
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include <base/printf.h>
|
|
#include <base/env.h>
|
|
#include <framebuffer_session/connection.h>
|
|
|
|
extern "C" {
|
|
|
|
#include <SDL/SDL.h>
|
|
#include <SDL/SDL_video.h>
|
|
#include <SDL/SDL_mouse.h>
|
|
#include "SDL_sysvideo.h"
|
|
#include "SDL_pixels_c.h"
|
|
#include "SDL_events_c.h"
|
|
#include "SDL_genode_fb_events.h"
|
|
#include "SDL_genode_fb_video.h"
|
|
|
|
static Framebuffer::Connection *framebuffer = 0;
|
|
static Framebuffer::Mode scr_mode;
|
|
static SDL_Rect *modes[2];
|
|
static SDL_Rect df_mode;
|
|
|
|
/***************************************
|
|
* Genode_Fb driver bootstrap functions
|
|
**************************************/
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int Genode_Fb_Available(void) {
|
|
if(framebuffer == 0)
|
|
framebuffer = new(Genode::env()->heap()) Framebuffer::Connection();
|
|
if (!framebuffer->cap().valid())
|
|
{
|
|
PERR("Couldn't get framebuffer session!");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static void Genode_Fb_DeleteDevice(SDL_VideoDevice *device)
|
|
{
|
|
PDBG("Free framebuffer session object");
|
|
if(framebuffer != 0)
|
|
delete framebuffer;
|
|
framebuffer = 0;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static SDL_VideoDevice *Genode_Fb_CreateDevice(int devindex)
|
|
{
|
|
SDL_VideoDevice *device;
|
|
|
|
/* Initialize all variables that we clean on shutdown */
|
|
device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
|
|
if ( device ) {
|
|
SDL_memset(device, 0, (sizeof *device));
|
|
device->hidden = (struct SDL_PrivateVideoData *)
|
|
SDL_malloc((sizeof *device->hidden));
|
|
}
|
|
if ( (device == 0) || (device->hidden == 0) ) {
|
|
SDL_OutOfMemory();
|
|
if ( device ) {
|
|
SDL_free(device);
|
|
}
|
|
return(0);
|
|
}
|
|
SDL_memset(device->hidden, 0, (sizeof *device->hidden));
|
|
|
|
/* Set the function pointers */
|
|
device->VideoInit = Genode_Fb_VideoInit;
|
|
device->ListModes = Genode_Fb_ListModes;
|
|
device->SetVideoMode = Genode_Fb_SetVideoMode;
|
|
device->SetColors = Genode_Fb_SetColors;
|
|
device->UpdateRects = Genode_Fb_UpdateRects;
|
|
device->VideoQuit = Genode_Fb_VideoQuit;
|
|
device->AllocHWSurface = Genode_Fb_AllocHWSurface;
|
|
device->LockHWSurface = Genode_Fb_LockHWSurface;
|
|
device->UnlockHWSurface = Genode_Fb_UnlockHWSurface;
|
|
device->FreeHWSurface = Genode_Fb_FreeHWSurface;
|
|
device->InitOSKeymap = Genode_Fb_InitOSKeymap;
|
|
device->PumpEvents = Genode_Fb_PumpEvents;
|
|
device->free = Genode_Fb_DeleteDevice;
|
|
device->CreateYUVOverlay = 0;
|
|
device->CheckHWBlit = 0;
|
|
device->FillHWRect = 0;
|
|
device->SetHWColorKey = 0;
|
|
device->SetHWAlpha = 0;
|
|
device->FlipHWSurface = 0;
|
|
device->SetCaption = 0;
|
|
device->SetIcon = 0;
|
|
device->IconifyWindow = 0;
|
|
device->GrabInput = 0;
|
|
device->GetWMInfo = 0;
|
|
return device;
|
|
}
|
|
|
|
|
|
VideoBootStrap Genode_fb_bootstrap = {
|
|
"Genode_Fb", "SDL genode_fb video driver",
|
|
Genode_Fb_Available, Genode_Fb_CreateDevice
|
|
};
|
|
|
|
|
|
/*****************
|
|
* Functionality
|
|
****************/
|
|
|
|
/**
|
|
* Initialize the native video subsystem, filling 'vformat' with the
|
|
* "best" display pixel format, returning 0 or -1 if there's an error.
|
|
*/
|
|
int Genode_Fb_VideoInit(SDL_VideoDevice *t, SDL_PixelFormat *vformat)
|
|
{
|
|
if(framebuffer == 0)
|
|
{
|
|
PERR("Framebuffer isn't initialized!");
|
|
return -1;
|
|
}
|
|
|
|
/* Get the framebuffer size and mode infos */
|
|
scr_mode = framebuffer->mode();
|
|
t->info.current_w = scr_mode.width();
|
|
t->info.current_h = scr_mode.height();
|
|
PDBG("Framebuffer has width=%d and height=%d",
|
|
t->info.current_w, t->info.current_h);
|
|
|
|
/* set mode specific values */
|
|
switch(scr_mode.format())
|
|
{
|
|
case Framebuffer::Mode::RGB565:
|
|
PDBG("We use pixelformat rgb565.");
|
|
vformat->BitsPerPixel = 16;
|
|
vformat->BytesPerPixel = scr_mode.bytes_per_pixel();
|
|
vformat->Rmask = 0x0000f800;
|
|
vformat->Gmask = 0x000007e0;
|
|
vformat->Bmask = 0x0000001f;
|
|
break;
|
|
default:
|
|
SDL_SetError("Couldn't get console mode info");
|
|
Genode_Fb_VideoQuit(t);
|
|
return -1;
|
|
}
|
|
modes[0] = &df_mode;
|
|
df_mode.w = scr_mode.width();
|
|
df_mode.h = scr_mode.height();
|
|
modes[1] = 0;
|
|
|
|
/* Map the buffer */
|
|
Genode::Dataspace_capability fb_ds_cap = framebuffer->dataspace();
|
|
if (!fb_ds_cap.valid()) {
|
|
PERR("Could not request dataspace for frame buffer");
|
|
return -1;
|
|
}
|
|
t->hidden->buffer = Genode::env()->rm_session()->attach(fb_ds_cap);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* List the available video modes for the given pixel format,
|
|
* sorted from largest to smallest.
|
|
*/
|
|
SDL_Rect **Genode_Fb_ListModes(SDL_VideoDevice *t,
|
|
SDL_PixelFormat *format,
|
|
Uint32 flags)
|
|
{
|
|
if(format->BitsPerPixel != 16)
|
|
return (SDL_Rect **) 0;
|
|
return modes;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the requested video mode, returning a surface which will be
|
|
* set to the SDL_VideoSurface. The width and height will already
|
|
* be verified by ListModes(), and the video subsystem is free to
|
|
* set the mode to a supported bit depth different from the one
|
|
* specified -- the desired bpp will be emulated with a shadow
|
|
* surface if necessary. If a new mode is returned, this function
|
|
* should take care of cleaning up the current mode.
|
|
*/
|
|
SDL_Surface *Genode_Fb_SetVideoMode(SDL_VideoDevice *t,
|
|
SDL_Surface *current,
|
|
int width, int height,
|
|
int bpp, Uint32 flags)
|
|
{
|
|
PDBG("Set video mode to: width=%d height=%d bpp=%d",
|
|
width, height, bpp);
|
|
|
|
if ( ! t->hidden->buffer ) {
|
|
PERR("No buffer for requested mode");
|
|
return(0);
|
|
}
|
|
SDL_memset(t->hidden->buffer, 0, width * height * (bpp / 8));
|
|
|
|
/* Allocate the new pixel format for the screen */
|
|
if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
|
|
PERR("Couldn't allocate new pixel format for requested mode");
|
|
return(0);
|
|
}
|
|
|
|
/* Set up the new mode framebuffer */
|
|
current->flags = flags & SDL_FULLSCREEN;
|
|
t->hidden->w = current->w = width;
|
|
t->hidden->h = current->h = height;
|
|
current->pitch = current->w * (bpp / 8);
|
|
current->pixels = t->hidden->buffer;
|
|
return(current);
|
|
}
|
|
|
|
|
|
/**
|
|
* We don't actually allow hardware surfaces other than the main one
|
|
*/
|
|
static int Genode_Fb_AllocHWSurface(SDL_VideoDevice *t,
|
|
SDL_Surface *surface)
|
|
{
|
|
PDBG("Not supported yet ...");
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void Genode_Fb_FreeHWSurface(SDL_VideoDevice *t,
|
|
SDL_Surface *surface)
|
|
{
|
|
PDBG("Not supported yet ...");
|
|
}
|
|
|
|
|
|
/**
|
|
* We need to wait for vertical retrace on page flipped displays
|
|
*/
|
|
static int Genode_Fb_LockHWSurface(SDL_VideoDevice *t,
|
|
SDL_Surface *surface)
|
|
{
|
|
PDBG("Not supported yet ...");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void Genode_Fb_UnlockHWSurface(SDL_VideoDevice *t,
|
|
SDL_Surface *surface)
|
|
{
|
|
PDBG("Not supported yet ...");
|
|
}
|
|
|
|
|
|
static void Genode_Fb_UpdateRects(SDL_VideoDevice *t, int numrects,
|
|
SDL_Rect *rects)
|
|
{
|
|
int i;
|
|
for(i=0;i<numrects;i++)
|
|
framebuffer->refresh(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) }
|
|
* of the physical palette to those in 'colors'. If the device is
|
|
* using a software palette (SDL_HWPALETTE not set), then the
|
|
* changes are reflected in the logical palette of the screen
|
|
* as well.
|
|
* The return value is 1 if all entries could be set properly
|
|
* or 0 otherwise.
|
|
*/
|
|
int Genode_Fb_SetColors(SDL_VideoDevice *t, int firstcolor,
|
|
int ncolors, SDL_Color *colors)
|
|
{
|
|
PWRN("Not implemented yet");
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
*Note: If we are terminated, this could be called in the middle of
|
|
* another SDL video routine -- notably UpdateRects.
|
|
*/
|
|
void Genode_Fb_VideoQuit(SDL_VideoDevice *t)
|
|
{
|
|
PDBG("Quit video device ...");
|
|
if (t->screen->pixels != 0)
|
|
{
|
|
SDL_free(t->screen->pixels);
|
|
t->screen->pixels = 0;
|
|
}
|
|
}
|
|
|
|
} //extern "C"
|