📄 sdl_directfb_video.c
字号:
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_DirectFB_video.c,v 1.2 2002/04/22 21:38:04 wmay Exp $";
#endif
/* DirectFB video driver implementation.
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <directfb.h>
#include "SDL.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels_c.h"
#include "SDL_events_c.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_events.h"
/* Initialization/Query functions */
static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color *colors);
static void DirectFB_VideoQuit(_THIS);
/* Hardware surface functions */
static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface);
static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface);
static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface);
static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface);
static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);
static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface);
/* Various screen update functions available */
static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects);
/* This is the rect EnumModes2 uses */
struct DirectFBEnumRect {
SDL_Rect r;
struct DirectFBEnumRect* next;
};
static struct DirectFBEnumRect *enumlists[NUM_MODELISTS];
/* DirectFB driver bootstrap functions */
static int DirectFB_Available(void)
{
return 1;
}
static void DirectFB_DeleteDevice(SDL_VideoDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_VideoDevice *DirectFB_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
if (device)
{
memset (device, 0, (sizeof *device));
device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden));
}
if (device == NULL || device->hidden == NULL)
{
SDL_OutOfMemory();
if (device)
{
free (device);
}
return(0);
}
memset (device->hidden, 0, sizeof (*device->hidden));
/* Set the function pointers */
device->VideoInit = DirectFB_VideoInit;
device->ListModes = DirectFB_ListModes;
device->SetVideoMode = DirectFB_SetVideoMode;
device->SetColors = DirectFB_SetColors;
device->UpdateRects = NULL;
device->VideoQuit = DirectFB_VideoQuit;
device->AllocHWSurface = DirectFB_AllocHWSurface;
device->CheckHWBlit = DirectFB_CheckHWBlit;
device->FillHWRect = DirectFB_FillHWRect;
device->SetHWColorKey = DirectFB_SetHWColorKey;
device->SetHWAlpha = DirectFB_SetHWAlpha;
device->LockHWSurface = DirectFB_LockHWSurface;
device->UnlockHWSurface = DirectFB_UnlockHWSurface;
device->FlipHWSurface = DirectFB_FlipHWSurface;
device->FreeHWSurface = DirectFB_FreeHWSurface;
device->SetCaption = NULL;
device->SetIcon = NULL;
device->IconifyWindow = NULL;
device->GrabInput = NULL;
device->GetWMInfo = NULL;
device->InitOSKeymap = DirectFB_InitOSKeymap;
device->PumpEvents = DirectFB_PumpEvents;
device->free = DirectFB_DeleteDevice;
return device;
}
VideoBootStrap DirectFB_bootstrap = {
"directfb", "DirectFB",
DirectFB_Available, DirectFB_CreateDevice
};
static DFBEnumerationResult EnumModesCallback (unsigned int width,
unsigned int height,
unsigned int bpp,
void *data)
{
SDL_VideoDevice *this = (SDL_VideoDevice *)data;
struct DirectFBEnumRect *enumrect;
switch (bpp)
{
case 8:
case 15:
case 16:
case 24:
case 32:
bpp /= 8; --bpp;
++HIDDEN->SDL_nummodes[bpp];
enumrect = (struct DirectFBEnumRect*)malloc(sizeof(struct DirectFBEnumRect));
if ( !enumrect )
{
SDL_OutOfMemory();
return DFENUM_CANCEL;
}
enumrect->r.x = 0;
enumrect->r.y = 0;
enumrect->r.w = width;
enumrect->r.h = height;
enumrect->next = enumlists[bpp];
enumlists[bpp] = enumrect;
break;
}
return DFENUM_OK;
}
struct private_hwdata {
IDirectFBSurface *surface;
};
void SetDirectFBerror (const char *function, DFBResult code)
{
const char *error = DirectFBErrorString (code);
if (error)
SDL_SetError("%s: %s", function, error);
else
SDL_SetError("Unknown error code from %s", function);
}
static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format)
{
if (format->Rmask && format->Gmask && format->Bmask)
{
switch (format->BitsPerPixel)
{
case 16:
if (format->Rmask == 0xF800 &&
format->Gmask == 0x07E0 &&
format->Bmask == 0x001F)
return DSPF_RGB16;
/* fall through */
case 15:
if (format->Rmask == 0x7C00 &&
format->Gmask == 0x03E0 &&
format->Bmask == 0x001F)
return DSPF_RGB15;
break;
case 24:
if (format->Rmask == 0xFF0000 &&
format->Gmask == 0x00FF00 &&
format->Bmask == 0x0000FF)
return DSPF_RGB24;
break;
case 32:
if (format->Rmask == 0xFF0000 &&
format->Gmask == 0x00FF00 &&
format->Bmask == 0x0000FF)
{
if (format->Amask == 0xFF000000)
return DSPF_ARGB;
else
return DSPF_RGB32;
}
break;
}
}
else
{
switch (format->BitsPerPixel)
{
case 15:
return DSPF_RGB15;
case 16:
return DSPF_RGB16;
case 24:
return DSPF_RGB24;
case 32:
return DSPF_RGB32;
}
}
return DSPF_UNKNOWN;
}
static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format)
{
format->BitsPerPixel = 0;
format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
switch (pixelformat)
{
case DSPF_A8:
format->Amask = 0x000000FF;
break;
case DSPF_RGB15:
format->Rmask = 0x00007C00;
format->Gmask = 0x000003E0;
format->Bmask = 0x0000001F;
break;
case DSPF_RGB16:
format->Rmask = 0x0000F800;
format->Gmask = 0x000007E0;
format->Bmask = 0x0000001F;
break;
case DSPF_ARGB:
format->Amask = 0xFF000000;
/* fall through */
case DSPF_RGB24:
case DSPF_RGB32:
format->Rmask = 0x00FF0000;
format->Gmask = 0x0000FF00;
format->Bmask = 0x000000FF;
break;
default:
return -1;
}
format->BitsPerPixel = DFB_BITS_PER_PIXEL(pixelformat);
return 0;
}
int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
int i, j;
DFBResult ret;
IDirectFB *dfb;
DFBCardCapabilities caps;
IDirectFBDisplayLayer *layer;
DFBDisplayLayerConfig dlc;
IDirectFBEventBuffer *eventbuffer;
ret = DirectFBInit (NULL, NULL);
if (ret)
{
SetDirectFBerror ("DirectFBInit", ret);
return -1;
}
ret = DirectFBCreate (&dfb);
if (ret)
{
SetDirectFBerror ("DirectFBCreate", ret);
return -1;
}
ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer);
if (ret)
{
SetDirectFBerror ("dfb->GetDisplayLayer", ret);
dfb->Release (dfb);
return -1;
}
ret = dfb->CreateEventBuffer (dfb, DICAPS_ALL, &eventbuffer);
if (ret)
{
SetDirectFBerror ("dfb->CreateEventBuffer", ret);
layer->Release (layer);
dfb->Release (dfb);
return -1;
}
layer->EnableCursor (layer, 1);
/* Query layer configuration to determine the current mode and pixelformat */
layer->GetConfiguration (layer, &dlc);
if (DFBToSDLPixelFormat (dlc.pixelformat, vformat))
{
SDL_SetError ("Unsupported pixelformat");
layer->Release (layer);
dfb->Release (dfb);
return -1;
}
/* Enumerate the available fullscreen modes */
for ( i=0; i<NUM_MODELISTS; ++i )
enumlists[i] = NULL;
ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this);
if (ret)
{
SetDirectFBerror ("dfb->EnumVideoModes", ret);
layer->Release (layer);
dfb->Release (dfb);
return(-1);
}
for ( i=0; i<NUM_MODELISTS; ++i )
{
struct DirectFBEnumRect *rect;
HIDDEN->SDL_modelist[i] = (SDL_Rect **) malloc
((HIDDEN->SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
if ( HIDDEN->SDL_modelist[i] == NULL )
{
SDL_OutOfMemory();
return(-1);
}
for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next )
{
HIDDEN->SDL_modelist[i][j]=(SDL_Rect *)rect;
}
HIDDEN->SDL_modelist[i][j] = NULL;
}
/* Query card capabilities to get the video memory size */
dfb->GetCardCapabilities (dfb, &caps);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -