git-svn-id: svn://kolibrios.org@8210 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
maxcodehack 2020-11-17 07:20:00 +00:00
parent 4695ec6c92
commit ab5677a586
65 changed files with 20255 additions and 0 deletions

View File

@ -0,0 +1,297 @@
#include "SDL_audio.h"
#include <menuet/os.h>
#include <stdlib.h>
#include <string.h>
#include <sound.h>
#include <stdio.h>
static void GetNotify(__u32* event)
{
__asm__("int $0x40" :: "a"(68),"b"(14),"c"(event));
}
static int CreateThread(void* fn, char* p_stack)
{
int res;
__asm__("int $0x40" : "=a"(res) : "a"(51),"b"(1),"c"(fn),"d"(p_stack));
return res;
}
static char pinfo[1024];
static int GetProcessInfo(int slot)
{
int res;
__asm__("int $0x40" : "=a"(res) : "a"(9),"b"(pinfo),"c"(slot));
return res;
}
static void ActivateWnd(int slot)
{
__asm__("int $0x40" :: "a"(18),"b"(3),"c"(slot));
}
static void Yield(void)
{
__asm__("int $0x40" :: "a"(68),"b"(1));
}
static int bInitialized=0;
static SNDBUF hBuff=0;
static char* data=NULL;
static int audio_tid=0;
static int main_slot;
static __u32 main_tid;
static char audio_thread_stack[40960];
static __u32 used_format=0;
static volatile int mix_size=0;
static void (*callback)(void* userdata, Uint8* stream, int len);
static void* userdata;
int SDL_AudioInit(const char* driver_name)
{
if (bInitialized)
{
SDL_SetError("audio already initialized");
return -1;
}
int ver;
if (InitSound(&ver))
{
SDL_printf("Warning: cannot load drivers, sound output will be disabled\n");
return 0;
}
bInitialized = 1;
return 0;
}
void SDL_AudioQuit(void)
{
}
char* SDL_AudioDriverName(char* namebuf, int maxlen)
{
if (!bInitialized)
return NULL;
strncpy(namebuf,"KolibriAudio",maxlen);
return namebuf;
}
#define AUDIO_SUSPEND 1
#define AUDIO_RESUME 2
#define AUDIO_DIE 3
static volatile int audio_command=0,audio_response=0,bLocked=0,bInCallback=0;
static void audio_thread(void)
{
SDL_printf("audio_thread created\n");
int bPaused;
__u32 event[6];
// initialize
if (CreateBuffer(used_format|PCM_RING, 0, &hBuff))
{
audio_response=1;
__menuet__sys_exit();
}
GetBufferSize(hBuff, &mix_size);
SDL_printf("buffer created, size is %d\n",mix_size);
mix_size >>= 1;
data = malloc(mix_size);
audio_response=1;
if (!data) __menuet__sys_exit();
// wait for resume
while (audio_command!=AUDIO_RESUME)
Yield();
// initialize
/* bInCallback=1;
callback(userdata,data,mix_size);
SetBuffer(hBuff,data,0,mix_size);
callback(userdata,data,mix_size);
SetBuffer(hBuff,data,mix_size,mix_size);
bInCallback=0;*/
audio_command=0;
bPaused=0;
audio_response=1;
PlayBuffer(hBuff,0);
// main loop
for (;;)
{
if (audio_command==AUDIO_RESUME)
{
PlayBuffer(hBuff,0);
audio_command = 0;
bPaused = 0;
audio_response = 1;
}
else if (audio_command==AUDIO_SUSPEND)
{
StopBuffer(hBuff);
audio_command = 0;
bPaused = 1;
audio_response = 1;
}
else if (audio_command==AUDIO_DIE)
{
audio_response = 1;
StopBuffer(hBuff);
DestroyBuffer(hBuff);
__menuet__sys_exit();
}
else
{
GetProcessInfo(main_slot);
if (pinfo[0x32]==9 || *(__u32*)(pinfo+0x1E)!=main_tid)
{
audio_command = AUDIO_DIE;
continue;
}
}
if (bPaused)
__menuet__delay100(5);
else
{
GetNotify(event);
if (event[0] != 0xFF000001)
continue;
while (bLocked)
Yield();
bInCallback=1;
callback(userdata,data,mix_size);
bInCallback=0;
SetBuffer(hBuff,data,event[3],mix_size);
}
}
}
int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained)
{
if (!bInitialized)
{
SDL_SetError("Audio device was not initialized");
return -1;
}
if (!obtained)
{
SDL_SetError("Audio format: software emulation is not supported");
return -1;
}
if (used_format)
{
SDL_SetError("Audio device was already opened");
return -1;
}
memcpy(obtained,desired,sizeof(SDL_AudioSpec));
switch (desired->freq)
{
#define HANDLE_FREQ(freq,symb) \
case freq: \
switch (desired->channels) \
{ \
case 1: \
switch (desired->format) \
{ \
case AUDIO_U8: \
case AUDIO_S8: \
used_format = PCM_1_8_##symb; \
break; \
case AUDIO_U16SYS: \
case AUDIO_S16SYS: \
used_format = PCM_1_16_##symb; \
break; \
} \
break; \
case 2: \
switch (desired->format) \
{ \
case AUDIO_U8: \
case AUDIO_S8: \
used_format = PCM_2_8_##symb; \
break; \
case AUDIO_U16SYS: \
case AUDIO_S16SYS: \
used_format = PCM_2_16_##symb; \
break; \
} \
break; \
} \
break;
HANDLE_FREQ(48000,48);
HANDLE_FREQ(44100,44);
HANDLE_FREQ(32000,32);
HANDLE_FREQ(24000,24);
HANDLE_FREQ(22050,22);
HANDLE_FREQ(16000,16);
HANDLE_FREQ(12000,12);
HANDLE_FREQ(11025,11);
HANDLE_FREQ(8000,8);
}
if (!used_format)
{
SDL_SetError("Unknown audio format");
return -1;
}
callback=desired->callback;
userdata=desired->userdata;
GetProcessInfo(-1);
main_tid = *(__u32*)(pinfo+0x1E);
for (main_slot=0;;main_slot++)
{
GetProcessInfo(main_slot);
if (pinfo[0x32]!=9 && *(__u32*)(pinfo+0x1E)==main_tid)
break;
}
audio_tid=CreateThread(audio_thread,audio_thread_stack+40960);
if (audio_tid<0)
{
SDL_SetError("Cannot create audio thread");
return -1;
}
ActivateWnd(main_slot);
while (!audio_response)
Yield();
if (!hBuff)
{
SDL_SetError("Cannot create audio buffer");
return -1;
}
if (!data)
{
SDL_SetError("Cannot allocate audio buffer");
return -1;
}
obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0);
obtained->size = mix_size;
obtained->samples = obtained->size / obtained->channels;
if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS)
obtained->samples /= 2;
SDL_printf("obtained size is %d, samples %d\n",obtained->size,
obtained->samples);
return 0;
}
void SDL_CloseAudio(void)
{
if (!audio_tid) return;
audio_response = 0;
audio_command = AUDIO_DIE;
while (!audio_response)
Yield();
free(data);
used_format = 0;
}
void SDL_PauseAudio(int pause_on)
{
if (!audio_tid) return;
audio_response = 0;
audio_command = pause_on?AUDIO_SUSPEND:AUDIO_RESUME;
while (!audio_response)
Yield();
}
void SDL_LockAudio(void)
{
if (!audio_tid) return;
bLocked = 1;
while (bInCallback)
Yield();
}
void SDL_UnlockAudio(void)
{
bLocked = 0;
}

View File

@ -0,0 +1,105 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Functions for dynamically reading and writing endian-specific values */
#include "SDL_endian.h"
Uint16 SDL_ReadLE16 (SDL_RWops *src)
{
Uint16 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapLE16(value));
}
Uint16 SDL_ReadBE16 (SDL_RWops *src)
{
Uint16 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapBE16(value));
}
Uint32 SDL_ReadLE32 (SDL_RWops *src)
{
Uint32 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapLE32(value));
}
Uint32 SDL_ReadBE32 (SDL_RWops *src)
{
Uint32 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapBE32(value));
}
Uint64 SDL_ReadLE64 (SDL_RWops *src)
{
Uint64 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapLE64(value));
}
Uint64 SDL_ReadBE64 (SDL_RWops *src)
{
Uint64 value;
SDL_RWread(src, &value, (sizeof value), 1);
return(SDL_SwapBE64(value));
}
int SDL_WriteLE16 (SDL_RWops *dst, Uint16 value)
{
value = SDL_SwapLE16(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}
int SDL_WriteBE16 (SDL_RWops *dst, Uint16 value)
{
value = SDL_SwapBE16(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}
int SDL_WriteLE32 (SDL_RWops *dst, Uint32 value)
{
value = SDL_SwapLE32(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}
int SDL_WriteBE32 (SDL_RWops *dst, Uint32 value)
{
value = SDL_SwapBE32(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}
int SDL_WriteLE64 (SDL_RWops *dst, Uint64 value)
{
value = SDL_SwapLE64(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}
int SDL_WriteBE64 (SDL_RWops *dst, Uint64 value)
{
value = SDL_SwapBE64(value);
return(SDL_RWwrite(dst, &value, (sizeof value), 1));
}

View File

@ -0,0 +1,91 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Application focus/iconification handling code for SDL */
#include <stdio.h>
#include <string.h>
#include "SDL_events.h"
#include "SDL_events_c.h"
/* These are static for our active event handling code */
static Uint8 SDL_appstate = 0;
/* Public functions */
int SDL_AppActiveInit(void)
{
/* Start completely active */
SDL_appstate = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS);
/* That's it! */
return(0);
}
Uint8 SDL_GetAppState(void)
{
return(SDL_appstate);
}
/* This is global for SDL_eventloop.c */
int SDL_PrivateAppActive(Uint8 gain, Uint8 state)
{
int posted;
Uint8 new_state;
/* Modify the current state with the given mask */
if ( gain ) {
new_state = (SDL_appstate | state);
} else {
new_state = (SDL_appstate & ~state);
}
/* Drop events that don't change state */
if ( new_state == SDL_appstate ) {
return(0);
}
/* Update internal active state */
SDL_appstate = new_state;
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[SDL_ACTIVEEVENT] == SDL_ENABLE ) {
SDL_Event event;
memset(&event, 0, sizeof(event));
event.type = SDL_ACTIVEEVENT;
event.active.gain = gain;
event.active.state = state;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
/* If we lost keyboard focus, post key-up events */
if ( (state & SDL_APPINPUTFOCUS) && !gain ) {
SDL_ResetKeyboard();
}
return(posted);
}

View File

@ -0,0 +1,471 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General event handling code for SDL */
#include <stdio.h>
#include <string.h>
#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_mutex.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_timer_c.h"
#ifndef DISABLE_JOYSTICK
#include "SDL_joystick_c.h"
#endif
#ifndef ENABLE_X11
#define DISABLE_X11
#endif
#include "SDL_syswm.h"
#include "SDL_sysevents.h"
/* Public data -- the event filter */
SDL_EventFilter SDL_EventOK = NULL;
Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
static Uint32 SDL_eventstate = 0;
/* Private data -- event queue */
#define MAXEVENTS 128
static struct {
SDL_mutex *lock;
int active;
int head;
int tail;
SDL_Event event[MAXEVENTS];
int wmmsg_next;
struct SDL_SysWMmsg wmmsg[MAXEVENTS];
} SDL_EventQ;
/* Private data -- event locking structure */
static struct {
SDL_mutex *lock;
int safe;
} SDL_EventLock;
/* Thread functions */
static SDL_Thread *SDL_EventThread = NULL; /* Thread handle */
static Uint32 event_thread; /* The event thread id */
void SDL_Lock_EventThread(void)
{
if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) {
/* Grab lock and spin until we're sure event thread stopped */
SDL_mutexP(SDL_EventLock.lock);
while ( ! SDL_EventLock.safe ) {
SDL_Delay(1);
}
}
}
void SDL_Unlock_EventThread(void)
{
if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) {
SDL_mutexV(SDL_EventLock.lock);
}
}
static int SDL_GobbleEvents(void *unused)
{
SDL_SetTimerThreaded(2);
event_thread = SDL_ThreadID();
while ( SDL_EventQ.active ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
/* Get events from the video subsystem */
if ( video ) {
video->PumpEvents(this);
}
/* Queue pending key-repeat events */
SDL_CheckKeyRepeat();
#ifndef DISABLE_JOYSTICK
/* Check for joystick state change */
if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) {
SDL_JoystickUpdate();
}
#endif
/* Give up the CPU for the rest of our timeslice */
SDL_EventLock.safe = 1;
if( SDL_timer_running ) {
SDL_ThreadedTimerCheck();
}
SDL_Delay(1);
/* Check for event locking.
On the P of the lock mutex, if the lock is held, this thread
will wait until the lock is released before continuing. The
safe flag will be set, meaning that the other thread can go
about it's business. The safe flag is reset before the V,
so as soon as the mutex is free, other threads can see that
it's not safe to interfere with the event thread.
*/
SDL_mutexP(SDL_EventLock.lock);
SDL_EventLock.safe = 0;
SDL_mutexV(SDL_EventLock.lock);
}
SDL_SetTimerThreaded(0);
event_thread = 0;
return(0);
}
static int SDL_StartEventThread(Uint32 flags)
{
/* Reset everything to zero */
SDL_EventThread = NULL;
memset(&SDL_EventLock, 0, sizeof(SDL_EventLock));
/* Create the lock and set ourselves active */
#ifndef DISABLE_THREADS
SDL_EventQ.lock = SDL_CreateMutex();
if ( SDL_EventQ.lock == NULL ) {
#ifdef macintosh /* On MacOS 7/8, you can't multithread, so no lock needed */
;
#else
return(-1);
#endif
}
#endif /* !DISABLE_THREADS */
SDL_EventQ.active = 1;
if ( (flags&SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
SDL_EventLock.lock = SDL_CreateMutex();
if ( SDL_EventLock.lock == NULL ) {
return(-1);
}
SDL_EventLock.safe = 0;
SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL);
if ( SDL_EventThread == NULL ) {
return(-1);
}
} else {
event_thread = 0;
}
return(0);
}
static void SDL_StopEventThread(void)
{
SDL_EventQ.active = 0;
if ( SDL_EventThread ) {
SDL_WaitThread(SDL_EventThread, NULL);
SDL_EventThread = NULL;
SDL_DestroyMutex(SDL_EventLock.lock);
}
SDL_DestroyMutex(SDL_EventQ.lock);
}
Uint32 SDL_EventThreadID(void)
{
return(event_thread);
}
/* Public functions */
void SDL_StopEventLoop(void)
{
/* Halt the event thread, if running */
SDL_StopEventThread();
/* Clean out EventQ */
SDL_EventQ.head = 0;
SDL_EventQ.tail = 0;
SDL_EventQ.wmmsg_next = 0;
}
/* This function (and associated calls) may be called more than once */
int SDL_StartEventLoop(Uint32 flags)
{
int retcode;
/* Clean out the event queue */
SDL_EventThread = NULL;
SDL_EventQ.lock = NULL;
SDL_StopEventLoop();
/* No filter to start with, process most event types */
SDL_EventOK = NULL;
memset(SDL_ProcessEvents,SDL_ENABLE,sizeof(SDL_ProcessEvents));
SDL_eventstate = ~0;
/* It's not save to call SDL_EventState() yet */
SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT);
SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE;
/* Initialize event handlers */
retcode = 0;
retcode += SDL_AppActiveInit();
retcode += SDL_KeyboardInit();
retcode += SDL_MouseInit();
retcode += SDL_QuitInit();
if ( retcode < 0 ) {
/* We don't expect them to fail, but... */
return(-1);
}
/* Create the lock and event thread */
if ( SDL_StartEventThread(flags) < 0 ) {
SDL_StopEventLoop();
return(-1);
}
return(0);
}
/* Add an event to the event queue -- called with the queue locked */
static int SDL_AddEvent(SDL_Event *event)
{
int tail, added;
tail = (SDL_EventQ.tail+1)%MAXEVENTS;
if ( tail == SDL_EventQ.head ) {
/* Overflow, drop event */
added = 0;
} else {
SDL_EventQ.event[SDL_EventQ.tail] = *event;
if (event->type == SDL_SYSWMEVENT) {
/* Note that it's possible to lose an event */
int next = SDL_EventQ.wmmsg_next;
SDL_EventQ.wmmsg[next] = *event->syswm.msg;
SDL_EventQ.event[SDL_EventQ.tail].syswm.msg =
&SDL_EventQ.wmmsg[next];
SDL_EventQ.wmmsg_next = (next+1)%MAXEVENTS;
}
SDL_EventQ.tail = tail;
added = 1;
}
return(added);
}
/* Cut an event, and return the next valid spot, or the tail */
/* -- called with the queue locked */
static int SDL_CutEvent(int spot)
{
if ( spot == SDL_EventQ.head ) {
SDL_EventQ.head = (SDL_EventQ.head+1)%MAXEVENTS;
return(SDL_EventQ.head);
} else
if ( (spot+1)%MAXEVENTS == SDL_EventQ.tail ) {
SDL_EventQ.tail = spot;
return(SDL_EventQ.tail);
} else
/* We cut the middle -- shift everything over */
{
int here, next;
/* This can probably be optimized with memcpy() -- careful! */
if ( --SDL_EventQ.tail < 0 ) {
SDL_EventQ.tail = MAXEVENTS-1;
}
for ( here=spot; here != SDL_EventQ.tail; here = next ) {
next = (here+1)%MAXEVENTS;
SDL_EventQ.event[here] = SDL_EventQ.event[next];
}
return(spot);
}
/* NOTREACHED */
}
/* Lock the event queue, take a peep at it, and unlock it */
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action,
Uint32 mask)
{
int i, used;
/* Don't look after we've quit */
if ( ! SDL_EventQ.active ) {
return(0);
}
/* Lock the event queue */
used = 0;
if ( SDL_mutexP(SDL_EventQ.lock) == 0 ) {
if ( action == SDL_ADDEVENT ) {
for ( i=0; i<numevents; ++i ) {
used += SDL_AddEvent(&events[i]);
}
} else {
SDL_Event tmpevent;
int spot;
/* If 'events' is NULL, just see if they exist */
if ( events == NULL ) {
action = SDL_PEEKEVENT;
numevents = 1;
events = &tmpevent;
}
spot = SDL_EventQ.head;
while ((used < numevents)&&(spot != SDL_EventQ.tail)) {
if ( mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type) ) {
events[used++] = SDL_EventQ.event[spot];
if ( action == SDL_GETEVENT ) {
spot = SDL_CutEvent(spot);
} else {
spot = (spot+1)%MAXEVENTS;
}
} else {
spot = (spot+1)%MAXEVENTS;
}
}
}
SDL_mutexV(SDL_EventQ.lock);
} else {
SDL_SetError("Couldn't lock event queue");
used = -1;
}
return(used);
}
/* Run the system dependent event loops */
void SDL_PumpEvents(void)
{
if ( !SDL_EventThread ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
/* Get events from the video subsystem */
if ( video ) {
video->PumpEvents(this);
}
/* Queue pending key-repeat events */
SDL_CheckKeyRepeat();
#ifndef DISABLE_JOYSTICK
/* Check for joystick state change */
if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) {
SDL_JoystickUpdate();
}
#endif
}
}
/* Public functions */
int SDL_PollEvent (SDL_Event *event)
{
SDL_PumpEvents();
return(SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS));
}
int SDL_WaitEvent (SDL_Event *event)
{
while ( 1 ) {
SDL_PumpEvents();
switch(SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) {
case -1: return -1;
case 1: return 1;
case 0: SDL_Delay(10);
}
}
}
int SDL_PushEvent(SDL_Event *event)
{
return(SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0));
}
void SDL_SetEventFilter (SDL_EventFilter filter)
{
SDL_Event bitbucket;
/* Set filter and discard pending events */
SDL_EventOK = filter;
while ( SDL_PollEvent(&bitbucket) > 0 )
;
}
SDL_EventFilter SDL_GetEventFilter(void)
{
return(SDL_EventOK);
}
Uint8 SDL_EventState (Uint8 type, int state)
{
SDL_Event bitbucket;
Uint8 current_state;
/* If SDL_ALLEVENTS was specified... */
if ( type == 0xFF ) {
current_state = SDL_IGNORE;
for ( type=0; type<SDL_NUMEVENTS; ++type ) {
if ( SDL_ProcessEvents[type] != SDL_IGNORE ) {
current_state = SDL_ENABLE;
}
SDL_ProcessEvents[type] = state;
if ( state == SDL_ENABLE ) {
SDL_eventstate |= (0x00000001 << (type));
} else {
SDL_eventstate &= ~(0x00000001 << (type));
}
}
while ( SDL_PollEvent(&bitbucket) > 0 )
;
return(current_state);
}
/* Just set the state for one event type */
current_state = SDL_ProcessEvents[type];
switch (state) {
case SDL_IGNORE:
case SDL_ENABLE:
/* Set state and discard pending events */
SDL_ProcessEvents[type] = state;
if ( state == SDL_ENABLE ) {
SDL_eventstate |= (0x00000001 << (type));
} else {
SDL_eventstate &= ~(0x00000001 << (type));
}
while ( SDL_PollEvent(&bitbucket) > 0 )
;
break;
default:
/* Querying state? */
break;
}
return(current_state);
}
/* This is a generic event handler.
*/
int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message)
{
int posted;
posted = 0;
if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
SDL_Event event;
memset(&event, 0, sizeof(event));
event.type = SDL_SYSWMEVENT;
event.syswm.msg = message;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
/* Update internal event state */
return(posted);
}

View File

@ -0,0 +1,78 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_events_c.h,v 1.2 2001/04/26 16:50:17 hercules Exp $";
#endif
/* Useful functions and variables from SDL_events.c */
#include "SDL_events.h"
/* Start and stop the event processing loop */
extern int SDL_StartEventLoop(Uint32 flags);
extern void SDL_StopEventLoop(void);
extern void SDL_QuitInterrupt(void);
extern void SDL_Lock_EventThread();
extern void SDL_Unlock_EventThread();
extern Uint32 SDL_EventThreadID(void);
/* Event handler init routines */
extern int SDL_AppActiveInit(void);
extern int SDL_KeyboardInit(void);
extern int SDL_MouseInit(void);
extern int SDL_QuitInit(void);
/* The event filter function */
extern SDL_EventFilter SDL_EventOK;
/* The array of event processing states */
extern Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
/* Internal event queueing functions
(from SDL_active.c, SDL_mouse.c, SDL_keyboard.c, SDL_quit.c, SDL_events.c)
*/
extern int SDL_PrivateAppActive(Uint8 gain, Uint8 state);
extern int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative,
Sint16 x, Sint16 y);
extern int SDL_PrivateMouseButton(Uint8 state, Uint8 button,Sint16 x,Sint16 y);
extern int SDL_PrivateKeyboard(Uint8 state, SDL_keysym *key);
extern int SDL_PrivateResize(int w, int h);
extern int SDL_PrivateExpose(void);
extern int SDL_PrivateQuit(void);
extern int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message);
/* Used by the activity event handler to remove mouse focus */
extern void SDL_MouseFocus(int focus);
/* Used by the activity event handler to remove keyboard focus */
extern void SDL_ResetKeyboard(void);
/* Used by the event loop to queue pending keyboard repeat events */
extern void SDL_CheckKeyRepeat(void);
/* Used by the OS keyboard code to detect whether or not to do UNICODE */
#ifndef DEFAULT_UNICODE_TRANSLATION
#define DEFAULT_UNICODE_TRANSLATION 0 /* Default off because of overhead */
#endif
extern int SDL_TranslateUNICODE;

View File

@ -0,0 +1,51 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Refresh event handling code for SDL */
#include "SDL_events.h"
#include "SDL_events_c.h"
/* This is global for SDL_eventloop.c */
int SDL_PrivateExpose(void)
{
int posted;
SDL_Event events[32];
/* Pull out all old refresh events */
SDL_PeepEvents(events, sizeof(events)/sizeof(events[0]),
SDL_GETEVENT, SDL_VIDEOEXPOSEMASK);
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[SDL_VIDEOEXPOSE] == SDL_ENABLE ) {
SDL_Event event;
event.type = SDL_VIDEOEXPOSE;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
return(posted);
}

View File

@ -0,0 +1,560 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General keyboard handling code for SDL */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_events.h"
#include "SDL_timer.h"
#include "SDL_events_c.h"
#include "SDL_sysevents.h"
/* Global keystate information */
static Uint8 SDL_KeyState[SDLK_LAST];
static SDLMod SDL_ModState;
int SDL_TranslateUNICODE = 0;
static char *keynames[SDLK_LAST]; /* Array of keycode names */
/*
* jk 991215 - added
*/
struct {
int firsttime; /* if we check against the delay or repeat value */
int delay; /* the delay before we start repeating */
int interval; /* the delay between key repeat events */
Uint32 timestamp; /* the time the first keydown event occurred */
SDL_Event evt; /* the event we are supposed to repeat */
} SDL_KeyRepeat;
/* Public functions */
int SDL_KeyboardInit(void)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
Uint16 i;
/* Set default mode of UNICODE translation */
SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
/* Initialize the tables */
SDL_ModState = KMOD_NONE;
for ( i=0; i<SDL_TABLESIZE(keynames); ++i )
keynames[i] = NULL;
for ( i=0; i<SDL_TABLESIZE(SDL_KeyState); ++i )
SDL_KeyState[i] = SDL_RELEASED;
video->InitOSKeymap(this);
SDL_EnableKeyRepeat(0, 0);
/* Fill in the blanks in keynames */
keynames[SDLK_BACKSPACE] = "backspace";
keynames[SDLK_TAB] = "tab";
keynames[SDLK_CLEAR] = "clear";
keynames[SDLK_RETURN] = "return";
keynames[SDLK_PAUSE] = "pause";
keynames[SDLK_ESCAPE] = "escape";
keynames[SDLK_SPACE] = "space";
keynames[SDLK_EXCLAIM] = "!";
keynames[SDLK_QUOTEDBL] = "\"";
keynames[SDLK_HASH] = "#";
keynames[SDLK_DOLLAR] = "$";
keynames[SDLK_AMPERSAND] = "&";
keynames[SDLK_QUOTE] = "'";
keynames[SDLK_LEFTPAREN] = "(";
keynames[SDLK_RIGHTPAREN] = ")";
keynames[SDLK_ASTERISK] = "*";
keynames[SDLK_PLUS] = "+";
keynames[SDLK_COMMA] = ",";
keynames[SDLK_MINUS] = "-";
keynames[SDLK_PERIOD] = ".";
keynames[SDLK_SLASH] = "/";
keynames[SDLK_0] = "0";
keynames[SDLK_1] = "1";
keynames[SDLK_2] = "2";
keynames[SDLK_3] = "3";
keynames[SDLK_4] = "4";
keynames[SDLK_5] = "5";
keynames[SDLK_6] = "6";
keynames[SDLK_7] = "7";
keynames[SDLK_8] = "8";
keynames[SDLK_9] = "9";
keynames[SDLK_COLON] = ":";
keynames[SDLK_SEMICOLON] = ";";
keynames[SDLK_LESS] = "<";
keynames[SDLK_EQUALS] = "=";
keynames[SDLK_GREATER] = ">";
keynames[SDLK_QUESTION] = "?";
keynames[SDLK_AT] = "@";
keynames[SDLK_LEFTBRACKET] = "[";
keynames[SDLK_BACKSLASH] = "\\";
keynames[SDLK_RIGHTBRACKET] = "]";
keynames[SDLK_CARET] = "^";
keynames[SDLK_UNDERSCORE] = "_";
keynames[SDLK_BACKQUOTE] = "`";
keynames[SDLK_a] = "a";
keynames[SDLK_b] = "b";
keynames[SDLK_c] = "c";
keynames[SDLK_d] = "d";
keynames[SDLK_e] = "e";
keynames[SDLK_f] = "f";
keynames[SDLK_g] = "g";
keynames[SDLK_h] = "h";
keynames[SDLK_i] = "i";
keynames[SDLK_j] = "j";
keynames[SDLK_k] = "k";
keynames[SDLK_l] = "l";
keynames[SDLK_m] = "m";
keynames[SDLK_n] = "n";
keynames[SDLK_o] = "o";
keynames[SDLK_p] = "p";
keynames[SDLK_q] = "q";
keynames[SDLK_r] = "r";
keynames[SDLK_s] = "s";
keynames[SDLK_t] = "t";
keynames[SDLK_u] = "u";
keynames[SDLK_v] = "v";
keynames[SDLK_w] = "w";
keynames[SDLK_x] = "x";
keynames[SDLK_y] = "y";
keynames[SDLK_z] = "z";
keynames[SDLK_DELETE] = "delete";
keynames[SDLK_WORLD_0] = "world 0";
keynames[SDLK_WORLD_1] = "world 1";
keynames[SDLK_WORLD_2] = "world 2";
keynames[SDLK_WORLD_3] = "world 3";
keynames[SDLK_WORLD_4] = "world 4";
keynames[SDLK_WORLD_5] = "world 5";
keynames[SDLK_WORLD_6] = "world 6";
keynames[SDLK_WORLD_7] = "world 7";
keynames[SDLK_WORLD_8] = "world 8";
keynames[SDLK_WORLD_9] = "world 9";
keynames[SDLK_WORLD_10] = "world 10";
keynames[SDLK_WORLD_11] = "world 11";
keynames[SDLK_WORLD_12] = "world 12";
keynames[SDLK_WORLD_13] = "world 13";
keynames[SDLK_WORLD_14] = "world 14";
keynames[SDLK_WORLD_15] = "world 15";
keynames[SDLK_WORLD_16] = "world 16";
keynames[SDLK_WORLD_17] = "world 17";
keynames[SDLK_WORLD_18] = "world 18";
keynames[SDLK_WORLD_19] = "world 19";
keynames[SDLK_WORLD_20] = "world 20";
keynames[SDLK_WORLD_21] = "world 21";
keynames[SDLK_WORLD_22] = "world 22";
keynames[SDLK_WORLD_23] = "world 23";
keynames[SDLK_WORLD_24] = "world 24";
keynames[SDLK_WORLD_25] = "world 25";
keynames[SDLK_WORLD_26] = "world 26";
keynames[SDLK_WORLD_27] = "world 27";
keynames[SDLK_WORLD_28] = "world 28";
keynames[SDLK_WORLD_29] = "world 29";
keynames[SDLK_WORLD_30] = "world 30";
keynames[SDLK_WORLD_31] = "world 31";
keynames[SDLK_WORLD_32] = "world 32";
keynames[SDLK_WORLD_33] = "world 33";
keynames[SDLK_WORLD_34] = "world 34";
keynames[SDLK_WORLD_35] = "world 35";
keynames[SDLK_WORLD_36] = "world 36";
keynames[SDLK_WORLD_37] = "world 37";
keynames[SDLK_WORLD_38] = "world 38";
keynames[SDLK_WORLD_39] = "world 39";
keynames[SDLK_WORLD_40] = "world 40";
keynames[SDLK_WORLD_41] = "world 41";
keynames[SDLK_WORLD_42] = "world 42";
keynames[SDLK_WORLD_43] = "world 43";
keynames[SDLK_WORLD_44] = "world 44";
keynames[SDLK_WORLD_45] = "world 45";
keynames[SDLK_WORLD_46] = "world 46";
keynames[SDLK_WORLD_47] = "world 47";
keynames[SDLK_WORLD_48] = "world 48";
keynames[SDLK_WORLD_49] = "world 49";
keynames[SDLK_WORLD_50] = "world 50";
keynames[SDLK_WORLD_51] = "world 51";
keynames[SDLK_WORLD_52] = "world 52";
keynames[SDLK_WORLD_53] = "world 53";
keynames[SDLK_WORLD_54] = "world 54";
keynames[SDLK_WORLD_55] = "world 55";
keynames[SDLK_WORLD_56] = "world 56";
keynames[SDLK_WORLD_57] = "world 57";
keynames[SDLK_WORLD_58] = "world 58";
keynames[SDLK_WORLD_59] = "world 59";
keynames[SDLK_WORLD_60] = "world 60";
keynames[SDLK_WORLD_61] = "world 61";
keynames[SDLK_WORLD_62] = "world 62";
keynames[SDLK_WORLD_63] = "world 63";
keynames[SDLK_WORLD_64] = "world 64";
keynames[SDLK_WORLD_65] = "world 65";
keynames[SDLK_WORLD_66] = "world 66";
keynames[SDLK_WORLD_67] = "world 67";
keynames[SDLK_WORLD_68] = "world 68";
keynames[SDLK_WORLD_69] = "world 69";
keynames[SDLK_WORLD_70] = "world 70";
keynames[SDLK_WORLD_71] = "world 71";
keynames[SDLK_WORLD_72] = "world 72";
keynames[SDLK_WORLD_73] = "world 73";
keynames[SDLK_WORLD_74] = "world 74";
keynames[SDLK_WORLD_75] = "world 75";
keynames[SDLK_WORLD_76] = "world 76";
keynames[SDLK_WORLD_77] = "world 77";
keynames[SDLK_WORLD_78] = "world 78";
keynames[SDLK_WORLD_79] = "world 79";
keynames[SDLK_WORLD_80] = "world 80";
keynames[SDLK_WORLD_81] = "world 81";
keynames[SDLK_WORLD_82] = "world 82";
keynames[SDLK_WORLD_83] = "world 83";
keynames[SDLK_WORLD_84] = "world 84";
keynames[SDLK_WORLD_85] = "world 85";
keynames[SDLK_WORLD_86] = "world 86";
keynames[SDLK_WORLD_87] = "world 87";
keynames[SDLK_WORLD_88] = "world 88";
keynames[SDLK_WORLD_89] = "world 89";
keynames[SDLK_WORLD_90] = "world 90";
keynames[SDLK_WORLD_91] = "world 91";
keynames[SDLK_WORLD_92] = "world 92";
keynames[SDLK_WORLD_93] = "world 93";
keynames[SDLK_WORLD_94] = "world 94";
keynames[SDLK_WORLD_95] = "world 95";
keynames[SDLK_KP0] = "[0]";
keynames[SDLK_KP1] = "[1]";
keynames[SDLK_KP2] = "[2]";
keynames[SDLK_KP3] = "[3]";
keynames[SDLK_KP4] = "[4]";
keynames[SDLK_KP5] = "[5]";
keynames[SDLK_KP6] = "[6]";
keynames[SDLK_KP7] = "[7]";
keynames[SDLK_KP8] = "[8]";
keynames[SDLK_KP9] = "[9]";
keynames[SDLK_KP_PERIOD] = "[.]";
keynames[SDLK_KP_DIVIDE] = "[/]";
keynames[SDLK_KP_MULTIPLY] = "[*]";
keynames[SDLK_KP_MINUS] = "[-]";
keynames[SDLK_KP_PLUS] = "[+]";
keynames[SDLK_KP_ENTER] = "enter";
keynames[SDLK_KP_EQUALS] = "equals";
keynames[SDLK_UP] = "up";
keynames[SDLK_DOWN] = "down";
keynames[SDLK_RIGHT] = "right";
keynames[SDLK_LEFT] = "left";
keynames[SDLK_DOWN] = "down";
keynames[SDLK_INSERT] = "insert";
keynames[SDLK_HOME] = "home";
keynames[SDLK_END] = "end";
keynames[SDLK_PAGEUP] = "page up";
keynames[SDLK_PAGEDOWN] = "page down";
keynames[SDLK_F1] = "f1";
keynames[SDLK_F2] = "f2";
keynames[SDLK_F3] = "f3";
keynames[SDLK_F4] = "f4";
keynames[SDLK_F5] = "f5";
keynames[SDLK_F6] = "f6";
keynames[SDLK_F7] = "f7";
keynames[SDLK_F8] = "f8";
keynames[SDLK_F9] = "f9";
keynames[SDLK_F10] = "f10";
keynames[SDLK_F11] = "f11";
keynames[SDLK_F12] = "f12";
keynames[SDLK_F13] = "f13";
keynames[SDLK_F14] = "f14";
keynames[SDLK_F15] = "f15";
keynames[SDLK_NUMLOCK] = "numlock";
keynames[SDLK_CAPSLOCK] = "caps lock";
keynames[SDLK_SCROLLOCK] = "scroll lock";
keynames[SDLK_RSHIFT] = "right shift";
keynames[SDLK_LSHIFT] = "left shift";
keynames[SDLK_RCTRL] = "right ctrl";
keynames[SDLK_LCTRL] = "left ctrl";
keynames[SDLK_RALT] = "right alt";
keynames[SDLK_LALT] = "left alt";
keynames[SDLK_RMETA] = "right meta";
keynames[SDLK_LMETA] = "left meta";
keynames[SDLK_LSUPER] = "left super"; /* "Windows" keys */
keynames[SDLK_RSUPER] = "right super";
keynames[SDLK_MODE] = "alt gr";
keynames[SDLK_COMPOSE] = "compose";
keynames[SDLK_HELP] = "help";
keynames[SDLK_PRINT] = "print screen";
keynames[SDLK_SYSREQ] = "sys req";
keynames[SDLK_BREAK] = "break";
keynames[SDLK_MENU] = "menu";
keynames[SDLK_POWER] = "power";
keynames[SDLK_EURO] = "euro";
/* Done. Whew. */
return(0);
}
/* We lost the keyboard, so post key up messages for all pressed keys */
void SDL_ResetKeyboard(void)
{
SDL_keysym keysym;
SDLKey key;
memset(&keysym, 0, (sizeof keysym));
for ( key=SDLK_FIRST; key<SDLK_LAST; ++key ) {
if ( SDL_KeyState[key] == SDL_PRESSED ) {
keysym.sym = key;
SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
}
}
SDL_KeyRepeat.timestamp = 0;
}
int SDL_EnableUNICODE(int enable)
{
int old_mode;
old_mode = SDL_TranslateUNICODE;
if ( enable >= 0 ) {
SDL_TranslateUNICODE = enable;
}
return(old_mode);
}
Uint8 * SDL_GetKeyState (int *numkeys)
{
if ( numkeys != (int *)0 )
*numkeys = SDLK_LAST;
return(SDL_KeyState);
}
SDLMod SDL_GetModState (void)
{
return(SDL_ModState);
}
void SDL_SetModState (SDLMod modstate)
{
SDL_ModState = modstate;
}
char *SDL_GetKeyName(SDLKey key)
{
char *keyname;
keyname = NULL;
if ( key < SDLK_LAST ) {
keyname = keynames[key];
}
if ( keyname == NULL ) {
keyname = "unknown key";
}
return(keyname);
}
/* These are global for SDL_eventloop.c */
int SDL_PrivateKeyboard(Uint8 state, SDL_keysym *keysym)
{
SDL_Event event;
int posted, repeatable;
Uint16 modstate;
memset(&event, 0, sizeof(event));
/* Set up the keysym */
modstate = (Uint16)SDL_ModState;
repeatable = 0;
if ( state == SDL_PRESSED ) {
keysym->mod = (SDLMod)modstate;
switch (keysym->sym) {
case SDLK_NUMLOCK:
modstate ^= KMOD_NUM;
if ( ! (modstate&KMOD_NUM) )
state = SDL_RELEASED;
keysym->mod = (SDLMod)modstate;
break;
case SDLK_CAPSLOCK:
modstate ^= KMOD_CAPS;
if ( ! (modstate&KMOD_CAPS) )
state = SDL_RELEASED;
keysym->mod = (SDLMod)modstate;
break;
case SDLK_LCTRL:
modstate |= KMOD_LCTRL;
break;
case SDLK_RCTRL:
modstate |= KMOD_RCTRL;
break;
case SDLK_LSHIFT:
modstate |= KMOD_LSHIFT;
break;
case SDLK_RSHIFT:
modstate |= KMOD_RSHIFT;
break;
case SDLK_LALT:
modstate |= KMOD_LALT;
break;
case SDLK_RALT:
modstate |= KMOD_RALT;
break;
case SDLK_LMETA:
modstate |= KMOD_LMETA;
break;
case SDLK_RMETA:
modstate |= KMOD_RMETA;
break;
case SDLK_MODE:
modstate |= KMOD_MODE;
break;
default:
repeatable = 1;
break;
}
} else {
switch (keysym->sym) {
case SDLK_NUMLOCK:
case SDLK_CAPSLOCK:
/* Only send keydown events */
return(0);
case SDLK_LCTRL:
modstate &= ~KMOD_LCTRL;
break;
case SDLK_RCTRL:
modstate &= ~KMOD_RCTRL;
break;
case SDLK_LSHIFT:
modstate &= ~KMOD_LSHIFT;
break;
case SDLK_RSHIFT:
modstate &= ~KMOD_RSHIFT;
break;
case SDLK_LALT:
modstate &= ~KMOD_LALT;
break;
case SDLK_RALT:
modstate &= ~KMOD_RALT;
break;
case SDLK_LMETA:
modstate &= ~KMOD_LMETA;
break;
case SDLK_RMETA:
modstate &= ~KMOD_RMETA;
break;
case SDLK_MODE:
modstate &= ~KMOD_MODE;
break;
default:
break;
}
keysym->mod = (SDLMod)modstate;
}
/* Figure out what type of event this is */
switch (state) {
case SDL_PRESSED:
event.type = SDL_KEYDOWN;
break;
case SDL_RELEASED:
event.type = SDL_KEYUP;
/*
* jk 991215 - Added
*/
if ( SDL_KeyRepeat.timestamp ) {
SDL_KeyRepeat.timestamp = 0;
}
break;
default:
/* Invalid state -- bail */
return(0);
}
// /* Drop events that don't change state */
// if ( SDL_KeyState[keysym->sym] == state ) {
// return(0);
// }
/* Update internal keyboard state */
SDL_ModState = (SDLMod)modstate;
SDL_KeyState[keysym->sym] = state;
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) {
event.key.state = state;
event.key.keysym = *keysym;
if ( (SDL_EventOK == NULL) || SDL_EventOK(&event) ) {
posted = 1;
/*
* jk 991215 - Added
*/
if (repeatable && (SDL_KeyRepeat.delay != 0)) {
SDL_KeyRepeat.evt = event;
SDL_KeyRepeat.firsttime = 1;
SDL_KeyRepeat.timestamp=SDL_GetTicks();
}
SDL_PushEvent(&event);
}
}
return(posted);
}
/*
* jk 991215 - Added
*/
void SDL_CheckKeyRepeat(void)
{
/* if ( SDL_KeyRepeat.timestamp ) {
Uint32 now, interval;
now = SDL_GetTicks();
interval = (now - SDL_KeyRepeat.timestamp);
if ( SDL_KeyRepeat.firsttime ) {
if ( interval > (Uint32)SDL_KeyRepeat.delay ) {
SDL_KeyRepeat.timestamp = now;
SDL_KeyRepeat.firsttime = 0;
}
} else {
if ( interval > (Uint32)SDL_KeyRepeat.interval ) {
SDL_KeyRepeat.timestamp = now;
SDL_PushEvent(&SDL_KeyRepeat.evt);
}
}
}*/
}
int SDL_EnableKeyRepeat(int delay, int interval)
{
if ( (delay < 0) || (interval < 0) ) {
SDL_SetError("keyboard repeat value less than zero");
return(-1);
}
SDL_KeyRepeat.firsttime = 0;
SDL_KeyRepeat.delay = delay;
SDL_KeyRepeat.interval = interval;
SDL_KeyRepeat.timestamp = 0;
return(0);
}

View File

@ -0,0 +1,246 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General mouse handling code for SDL */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_cursor_c.h"
#include "SDL_sysvideo.h"
/* These are static for our mouse handling code */
static Sint16 SDL_MouseX = 0;
static Sint16 SDL_MouseY = 0;
static Sint16 SDL_DeltaX = 0;
static Sint16 SDL_DeltaY = 0;
static Uint8 SDL_ButtonState = 0;
/* Public functions */
int SDL_MouseInit(void)
{
/* The mouse is at (0,0) */
SDL_MouseX = 0;
SDL_MouseY = 0;
SDL_DeltaX = 0;
SDL_DeltaY = 0;
SDL_ButtonState = 0;
/* That's it! */
return(0);
}
Uint8 SDL_GetMouseState (int *x, int *y)
{
if ( x )
*x = SDL_MouseX;
if ( y )
*y = SDL_MouseY;
return(SDL_ButtonState);
}
Uint8 SDL_GetRelativeMouseState (int *x, int *y)
{
if ( x )
*x = SDL_DeltaX;
if ( y )
*y = SDL_DeltaY;
SDL_DeltaX = 0;
SDL_DeltaY = 0;
return(SDL_ButtonState);
}
static void ClipOffset(Sint16 *x, Sint16 *y)
{
/* This clips absolute mouse coordinates when the apparent
display surface is smaller than the real display surface.
*/
if ( SDL_VideoSurface->offset ) {
*y -= SDL_VideoSurface->offset/SDL_VideoSurface->pitch;
*x -= (SDL_VideoSurface->offset%SDL_VideoSurface->pitch)/
SDL_VideoSurface->format->BytesPerPixel;
}
}
/* These are global for SDL_eventloop.c */
int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y)
{
int posted;
Uint16 X, Y;
Sint16 Xrel;
Sint16 Yrel;
/* Don't handle mouse motion if there's no cursor surface */
if ( SDL_VideoSurface == NULL ) {
return(0);
}
/* Default buttonstate is the current one */
if ( ! buttonstate ) {
buttonstate = SDL_ButtonState;
}
Xrel = x;
Yrel = y;
if ( relative ) {
/* Push the cursor around */
x = (SDL_MouseX+x);
y = (SDL_MouseY+y);
} else {
/* Do we need to clip {x,y} ? */
ClipOffset(&x, &y);
}
/* Mouse coordinates range from 0 - width-1 and 0 - height-1 */
if ( x < 0 )
X = 0;
else
if ( x >= SDL_VideoSurface->w )
X = SDL_VideoSurface->w-1;
else
X = (Uint16)x;
if ( y < 0 )
Y = 0;
else
if ( y >= SDL_VideoSurface->h )
Y = SDL_VideoSurface->h-1;
else
Y = (Uint16)y;
/* If not relative mode, generate relative motion from clamped X/Y.
This prevents lots of extraneous large delta relative motion when
the screen is windowed mode and the mouse is outside the window.
*/
if ( ! relative ) {
Xrel = X-SDL_MouseX;
Yrel = Y-SDL_MouseY;
}
/* Update internal mouse state */
SDL_ButtonState = buttonstate;
SDL_MouseX = X;
SDL_MouseY = Y;
SDL_DeltaX += Xrel;
SDL_DeltaY += Yrel;
SDL_MoveCursor(SDL_MouseX, SDL_MouseY);
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE ) {
SDL_Event event;
memset(&event, 0, sizeof(event));
event.type = SDL_MOUSEMOTION;
event.motion.state = buttonstate;
event.motion.x = X;
event.motion.y = Y;
event.motion.xrel = Xrel;
event.motion.yrel = Yrel;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
return(posted);
}
int SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, Sint16 y)
{
SDL_Event event;
int posted;
int move_mouse;
Uint8 buttonstate;
memset(&event, 0, sizeof(event));
/* Check parameters */
if ( x || y ) {
ClipOffset(&x, &y);
move_mouse = 1;
/* Mouse coordinates range from 0 - width-1 and 0 - height-1 */
if ( x < 0 )
x = 0;
else
if ( x >= SDL_VideoSurface->w )
x = SDL_VideoSurface->w-1;
if ( y < 0 )
y = 0;
else
if ( y >= SDL_VideoSurface->h )
y = SDL_VideoSurface->h-1;
} else {
move_mouse = 0;
}
if ( ! x )
x = SDL_MouseX;
if ( ! y )
y = SDL_MouseY;
/* Figure out which event to perform */
buttonstate = SDL_ButtonState;
switch ( state ) {
case SDL_PRESSED:
event.type = SDL_MOUSEBUTTONDOWN;
buttonstate |= SDL_BUTTON(button);
break;
case SDL_RELEASED:
event.type = SDL_MOUSEBUTTONUP;
buttonstate &= ~SDL_BUTTON(button);
break;
default:
/* Invalid state -- bail */
return(0);
}
/* Update internal mouse state */
SDL_ButtonState = buttonstate;
if ( move_mouse ) {
SDL_MouseX = x;
SDL_MouseY = y;
/* We don't wan't the cursor because MenuetOS doesn't allow
hiding mouse cursor */
// uncommented for KolibriOS
SDL_MoveCursor(SDL_MouseX, SDL_MouseY);
}
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) {
event.button.state = state;
event.button.button = button;
event.button.x = x;
event.button.y = y;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
return(posted);
}

View File

@ -0,0 +1,79 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General quit handling code for SDL */
#include <stdio.h>
#ifndef NO_SIGNAL_H
#include <signal.h>
#endif
#include "SDL_events.h"
#include "SDL_events_c.h"
#ifndef NO_SIGNAL_H
static void SDL_HandleSIG(int sig)
{
/* Reset the signal handler */
signal(sig, SDL_HandleSIG);
/* Signal a quit interrupt */
SDL_PrivateQuit();
}
#endif /* NO_SIGNAL_H */
/* Public functions */
int SDL_QuitInit(void)
{
#ifndef NO_SIGNAL_H
void (*ohandler)(int);
/* Both SIGINT and SIGTERM are translated into quit interrupts */
ohandler = signal(SIGINT, SDL_HandleSIG);
if ( ohandler != SIG_DFL )
signal(SIGINT, ohandler);
ohandler = signal(SIGTERM, SDL_HandleSIG);
if ( ohandler != SIG_DFL )
signal(SIGTERM, ohandler);
#endif /* NO_SIGNAL_H */
/* That's it! */
return(0);
}
/* This function returns 1 if it's okay to close the application window */
int SDL_PrivateQuit(void)
{
int posted;
posted = 0;
if ( SDL_ProcessEvents[SDL_QUIT] == SDL_ENABLE ) {
SDL_Event event;
event.type = SDL_QUIT;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
return(posted);
}

View File

@ -0,0 +1,72 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Resize event handling code for SDL */
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_sysvideo.h"
/* Keep the last resize event so we don't post duplicates */
static struct {
int w;
int h;
} last_resize;
/* This is global for SDL_eventloop.c */
int SDL_PrivateResize(int w, int h)
{
int posted;
SDL_Event events[32];
/* See if this event would change the video surface */
if ( !w || !h ||
((last_resize.w == w) && (last_resize.h == h)) ) {
return(0);
}
last_resize.w = w;
last_resize.h = h;
if ( ! SDL_VideoSurface ||
((w == SDL_VideoSurface->w) && (h == SDL_VideoSurface->h)) ) {
return(0);
}
/* Pull out all old resize events */
SDL_PeepEvents(events, sizeof(events)/sizeof(events[0]),
SDL_GETEVENT, SDL_VIDEORESIZEMASK);
/* Post the event, if desired */
posted = 0;
if ( SDL_ProcessEvents[SDL_VIDEORESIZE] == SDL_ENABLE ) {
SDL_Event event;
event.type = SDL_VIDEORESIZE;
event.resize.w = w;
event.resize.h = h;
if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
posted = 1;
SDL_PushEvent(&event);
}
}
return(posted);
}

View File

@ -0,0 +1,46 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_sysevents.h,v 1.2 2001/04/26 16:50:17 hercules Exp $";
#endif
#include "SDL_sysvideo.h"
/* Useful functions and variables from SDL_sysevents.c */
#ifdef __BEOS__ /* The Be event loop runs in a separate thread */
#define MUST_THREAD_EVENTS
#endif
#ifdef WIN32UNDEFINED /* Win32 doesn't allow a separate event thread */
#define CANT_THREAD_EVENTS
#endif
#ifdef macintosh /* MacOS 7/8 don't support preemptive multi-tasking */
#define CANT_THREAD_EVENTS
#endif
#ifdef __MENUETOS__
#define CANT_THREAD_EVENTS
#endif

View File

@ -0,0 +1,207 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* This file provides a general interface for SDL to read and write
data sources. It can easily be extended to files, memory, etc.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_rwops.h"
/* Functions to read/write stdio file pointers */
static int stdio_seek(SDL_RWops *context, int offset, int whence)
{
if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 )
{
return(ftell(context->hidden.stdio.fp));
} else {
SDL_Error(SDL_EFSEEK);
return(-1);
}
}
static int stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum)
{
size_t nread;
nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
if ( nread == 0 && ferror(context->hidden.stdio.fp) )
{
SDL_Error(SDL_EFREAD);
}
return(nread);
}
static int stdio_write(SDL_RWops *context, const void *ptr, int size, int num)
{
size_t nwrote;
nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
if ( nwrote == 0 && ferror(context->hidden.stdio.fp) )
{
SDL_Error(SDL_EFWRITE);
}
return(nwrote);
}
static int stdio_close(SDL_RWops *context)
{
if ( context )
{
if ( context->hidden.stdio.autoclose )
{
fclose(context->hidden.stdio.fp);
}
free(context);
}
return(0);
}
static int mem_seek(SDL_RWops *context, int offset, int whence)
{
Uint8 *newpos;
switch (whence)
{
case SEEK_SET:
newpos = context->hidden.mem.base+offset;
break;
case SEEK_CUR:
newpos = context->hidden.mem.here+offset;
break;
case SEEK_END:
newpos = context->hidden.mem.stop+offset;
break;
default:
SDL_SetError("Unknown value for 'whence'");
return(-1);
}
if ( newpos < context->hidden.mem.base )
{
newpos = context->hidden.mem.base;
}
if ( newpos > context->hidden.mem.stop )
{
newpos = context->hidden.mem.stop;
}
context->hidden.mem.here = newpos;
return(context->hidden.mem.here-context->hidden.mem.base);
}
static int mem_read(SDL_RWops *context, void *ptr, int size, int maxnum)
{
int num;
num = maxnum;
if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop )
{
num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
}
memcpy(ptr, context->hidden.mem.here, num*size);
context->hidden.mem.here += num*size;
return(num);
}
static int mem_write(SDL_RWops *context, const void *ptr, int size, int num)
{
if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop )
{
num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
}
memcpy(context->hidden.mem.here, ptr, num*size);
context->hidden.mem.here += num*size;
return(num);
}
static int mem_close(SDL_RWops *context)
{
if ( context )
{
free(context);
}
return(0);
}
SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
{
FILE *fp;
SDL_RWops *rwops;
rwops = NULL;
fp = fopen(file, mode);
if ( fp == NULL )
{
SDL_SetError("Couldn't open %s", file);
} else {
rwops = SDL_RWFromFP(fp, 1);
}
return(rwops);
}
SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose)
{
SDL_RWops *rwops;
rwops = SDL_AllocRW();
if ( rwops != NULL )
{
rwops->seek = stdio_seek;
rwops->read = stdio_read;
rwops->write = stdio_write;
rwops->close = stdio_close;
rwops->hidden.stdio.fp = fp;
rwops->hidden.stdio.autoclose = autoclose;
}
return(rwops);
}
SDL_RWops *SDL_RWFromMem(void *mem, int size)
{
SDL_RWops *rwops;
rwops = SDL_AllocRW();
if ( rwops != NULL )
{
rwops->seek = mem_seek;
rwops->read = mem_read;
rwops->write = mem_write;
rwops->close = mem_close;
rwops->hidden.mem.base = (Uint8 *)mem;
rwops->hidden.mem.here = rwops->hidden.mem.base;
rwops->hidden.mem.stop = rwops->hidden.mem.base+size;
}
return(rwops);
}
SDL_RWops *SDL_AllocRW(void)
{
SDL_RWops *area;
area = (SDL_RWops *)malloc(sizeof *area);
if ( area == NULL )
{
SDL_OutOfMemory();
}
return(area);
}
void SDL_FreeRW(SDL_RWops *area)
{
free(area);
}

View File

@ -0,0 +1,101 @@
/*
Header definitions for the MMX routines for the HERMES library
Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk)
This source code is licensed under the GNU LGPL
Please refer to the file COPYING.LIB contained in the distribution for
licensing conditions
*/
#ifndef __HERMES_HEAD_MMX__
#define __HERMES_HEAD_MMX__
/* If you cannot stand ifdefs, then please do not look into this file, it's
going to end your life :) */
#ifdef X86_ASSEMBLER
#ifdef __cplusplus
extern "C" {
#endif
void STACKCALL ConvertMMX(HermesConverterInterface *);
void STACKCALL ClearMMX_32(HermesClearInterface *);
void STACKCALL ClearMMX_24(HermesClearInterface *);
void STACKCALL ClearMMX_16(HermesClearInterface *);
void STACKCALL ClearMMX_8(HermesClearInterface *);
void ConvertMMXpII32_24RGB888();
void ConvertMMXpII32_16RGB565();
void ConvertMMXpII32_16BGR565();
void ConvertMMXpII32_16RGB555();
void ConvertMMXpII32_16BGR565();
void ConvertMMXpII32_16BGR555();
void ConvertMMXp32_16RGB555();
#ifdef __cplusplus
}
#endif
/* Fix the underscore business with ELF compilers */
#if defined(__ELF__) && defined(__GNUC__)
#ifdef __cplusplus
extern "C" {
#endif
void ConvertMMX(HermesConverterInterface *) __attribute__ ((alias ("_ConvertMMX")));
#if 0
void ClearMMX_32(HermesClearInterface *) __attribute__ ((alias ("_ClearMMX_32")));
void ClearMMX_24(HermesClearInterface *) __attribute__ ((alias ("_ClearMMX_24")));
void ClearMMX_16(HermesClearInterface *) __attribute__ ((alias ("_ClearMMX_16")));
void ClearMMX_8(HermesClearInterface *) __attribute__ ((alias ("_ClearMMX_8")));
void ConvertMMXp32_16RGB555() __attribute__ ((alias ("_ConvertMMXp32_16RGB555")));
#endif
void ConvertMMXpII32_24RGB888() __attribute__ ((alias ("_ConvertMMXpII32_24RGB888")));
void ConvertMMXpII32_16RGB565() __attribute__ ((alias ("_ConvertMMXpII32_16RGB565")));
void ConvertMMXpII32_16BGR565() __attribute__ ((alias ("_ConvertMMXpII32_16BGR565")));
void ConvertMMXpII32_16RGB555() __attribute__ ((alias ("_ConvertMMXpII32_16RGB555")));
void ConvertMMXpII32_16BGR555() __attribute__ ((alias ("_ConvertMMXpII32_16BGR555")));
#ifdef __cplusplus
}
#endif
#endif /* ELF and GNUC */
/* Make it work with Watcom */
#ifdef __WATCOMC__
#pragma warning 601 9
#pragma aux ConvertMMX "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearMMX_32 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearMMX_24 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearMMX_16 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearMMX_8 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ConvertMMXpII32_24RGB888 "_*"
#pragma aux ConvertMMXpII32_16RGB565 "_*"
#pragma aux ConvertMMXpII32_16BGR565 "_*"
#pragma aux ConvertMMXpII32_16RGB555 "_*"
#pragma aux ConvertMMXpII32_16BGR555 "_*"
#pragma aux ConvertMMXp32_16RGB555 "_*"
#endif /* WATCOM */
#endif /* X86_ASSEMBLER */
#endif

View File

@ -0,0 +1,195 @@
/*
Header definitions for the x86 routines for the HERMES library
Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at)
This source code is licensed under the GNU LGPL
Please refer to the file COPYING.LIB contained in the distribution for
licensing conditions
*/
#ifndef __HERMES_HEAD_X86__
#define __HERMES_HEAD_X86__
#ifdef X86_ASSEMBLER
/* If you can't stand IFDEFS, then close your eyes now, please :) */
/* Ok, we start with normal function definitions */
#ifdef __cplusplus
extern "C" {
#endif
void STACKCALL ConvertX86(HermesConverterInterface *);
void STACKCALL ClearX86_32(HermesClearInterface *);
void STACKCALL ClearX86_24(HermesClearInterface *);
void STACKCALL ClearX86_16(HermesClearInterface *);
void STACKCALL ClearX86_8(HermesClearInterface *);
int STACKCALL Hermes_X86_CPU();
void ConvertX86p32_32BGR888();
void ConvertX86p32_32RGBA888();
void ConvertX86p32_32BGRA888();
void ConvertX86p32_24RGB888();
void ConvertX86p32_24BGR888();
void ConvertX86p32_16RGB565();
void ConvertX86p32_16BGR565();
void ConvertX86p32_16RGB555();
void ConvertX86p32_16BGR555();
void ConvertX86p32_8RGB332();
void ConvertX86p16_32RGB888();
void ConvertX86p16_32BGR888();
void ConvertX86p16_32RGBA888();
void ConvertX86p16_32BGRA888();
void ConvertX86p16_24RGB888();
void ConvertX86p16_24BGR888();
void ConvertX86p16_16BGR565();
void ConvertX86p16_16RGB555();
void ConvertX86p16_16BGR555();
void ConvertX86p16_8RGB332();
void CopyX86p_4byte();
void CopyX86p_3byte();
void CopyX86p_2byte();
void CopyX86p_1byte();
void ConvertX86pI8_32();
void ConvertX86pI8_24();
void ConvertX86pI8_16();
extern int32 ConvertX86p16_32RGB888_LUT_X86[512];
extern int32 ConvertX86p16_32BGR888_LUT_X86[512];
extern int32 ConvertX86p16_32RGBA888_LUT_X86[512];
extern int32 ConvertX86p16_32BGRA888_LUT_X86[512];
#ifdef __cplusplus
}
#endif
/* Now fix up the ELF underscore problem */
#if defined(__ELF__) && defined(__GNUC__)
#ifdef __cplusplus
extern "C" {
#endif
int Hermes_X86_CPU() __attribute__ ((alias ("_Hermes_X86_CPU")));
void ConvertX86(HermesConverterInterface *) __attribute__ ((alias ("_ConvertX86")));
#if 0
void ClearX86_32(HermesClearInterface *) __attribute__ ((alias ("_ClearX86_32")));
void ClearX86_24(HermesClearInterface *) __attribute__ ((alias ("_ClearX86_24")));
void ClearX86_16(HermesClearInterface *) __attribute__ ((alias ("_ClearX86_16")));
void ClearX86_8(HermesClearInterface *) __attribute__ ((alias ("_ClearX86_8")));
#endif
void ConvertX86p32_32BGR888() __attribute__ ((alias ("_ConvertX86p32_32BGR888")));
void ConvertX86p32_32RGBA888() __attribute__ ((alias ("_ConvertX86p32_32RGBA888")));
void ConvertX86p32_32BGRA888() __attribute__ ((alias ("_ConvertX86p32_32BGRA888")));
void ConvertX86p32_24RGB888() __attribute__ ((alias ("_ConvertX86p32_24RGB888")));
void ConvertX86p32_24BGR888() __attribute__ ((alias ("_ConvertX86p32_24BGR888")));
void ConvertX86p32_16RGB565() __attribute__ ((alias ("_ConvertX86p32_16RGB565")));
void ConvertX86p32_16BGR565() __attribute__ ((alias ("_ConvertX86p32_16BGR565")));
void ConvertX86p32_16RGB555() __attribute__ ((alias ("_ConvertX86p32_16RGB555")));
void ConvertX86p32_16BGR555() __attribute__ ((alias ("_ConvertX86p32_16BGR555")));
void ConvertX86p32_8RGB332() __attribute__ ((alias ("_ConvertX86p32_8RGB332")));
#if 0
void ConvertX86p16_32RGB888() __attribute__ ((alias ("_ConvertX86p16_32RGB888")));
void ConvertX86p16_32BGR888() __attribute__ ((alias ("_ConvertX86p16_32BGR888")));
void ConvertX86p16_32RGBA888() __attribute__ ((alias ("_ConvertX86p16_32RGBA888")));
void ConvertX86p16_32BGRA888() __attribute__ ((alias ("_ConvertX86p16_32BGRA888")));
void ConvertX86p16_24RGB888() __attribute__ ((alias ("_ConvertX86p16_24RGB888")));
void ConvertX86p16_24BGR888() __attribute__ ((alias ("_ConvertX86p16_24BGR888")));
#endif
void ConvertX86p16_16BGR565() __attribute__ ((alias ("_ConvertX86p16_16BGR565")));
void ConvertX86p16_16RGB555() __attribute__ ((alias ("_ConvertX86p16_16RGB555")));
void ConvertX86p16_16BGR555() __attribute__ ((alias ("_ConvertX86p16_16BGR555")));
void ConvertX86p16_8RGB332() __attribute__ ((alias ("_ConvertX86p16_8RGB332")));
#if 0
void CopyX86p_4byte() __attribute__ ((alias ("_CopyX86p_4byte")));
void CopyX86p_3byte() __attribute__ ((alias ("_CopyX86p_3byte")));
void CopyX86p_2byte() __attribute__ ((alias ("_CopyX86p_2byte")));
void CopyX86p_1byte() __attribute__ ((alias ("_CopyX86p_1byte")));
void ConvertX86pI8_32() __attribute__ ((alias ("_ConvertX86pI8_32")));
void ConvertX86pI8_24() __attribute__ ((alias ("_ConvertX86pI8_24")));
void ConvertX86pI8_16() __attribute__ ((alias ("_ConvertX86pI8_16")));
extern int32 ConvertX86p16_32RGB888_LUT_X86[512] __attribute__ ((alias ("_ConvertX86p16_32RGB888_LUT_X86")));
extern int32 ConvertX86p16_32BGR888_LUT_X86[512] __attribute__ ((alias ("_ConvertX86p16_32BGR888_LUT_X86")));
extern int32 ConvertX86p16_32RGBA888_LUT_X86[512] __attribute__ ((alias ("_ConvertX86p16_32RGBA888_LUT_X86")));
extern int32 ConvertX86p16_32BGRA888_LUT_X86[512] __attribute__ ((alias ("_ConvertX86p16_32BGRA888_LUT_X86")));
#endif
#ifdef __cplusplus
}
#endif
#endif /* ELF & GNU */
/* Make it run with WATCOM C */
#ifdef __WATCOMC__
#pragma warning 601 9
#pragma aux Hermes_X86_CPU "_*"
#pragma aux ConvertX86 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearX86_32 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearX86_24 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearX86_16 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ClearX86_8 "_*" modify [EAX EBX ECX EDX ESI EDI]
#pragma aux ConvertX86p32_32BGR888 "_*"
#pragma aux ConvertX86p32_32RGBA888 "_*"
#pragma aux ConvertX86p32_32BGRA888 "_*"
#pragma aux ConvertX86p32_24RGB888 "_*"
#pragma aux ConvertX86p32_24BGR888 "_*"
#pragma aux ConvertX86p32_16RGB565 "_*"
#pragma aux ConvertX86p32_16BGR565 "_*"
#pragma aux ConvertX86p32_16RGB555 "_*"
#pragma aux ConvertX86p32_16BGR555 "_*"
#pragma aux ConvertX86p32_8RGB332 "_*"
#pragma aux ConvertX86p16_32RGB888 "_*"
#pragma aux ConvertX86p16_32BGR888 "_*"
#pragma aux ConvertX86p16_32RGBA888 "_*"
#pragma aux ConvertX86p16_32BGRA888 "_*"
#pragma aux ConvertX86p16_24RGB888 "_*"
#pragma aux ConvertX86p16_24BGR888 "_*"
#pragma aux ConvertX86p16_16BGR565 "_*"
#pragma aux ConvertX86p16_16RGB555 "_*"
#pragma aux ConvertX86p16_16BGR555 "_*"
#pragma aux ConvertX86p16_8RGB332 "_*"
#pragma aux CopyX86p_4byte "_*"
#pragma aux CopyX86p_3byte "_*"
#pragma aux CopyX86p_2byte "_*"
#pragma aux CopyX86p_1byte "_*"
#pragma aux ConvertX86pI8_32 "_*"
#pragma aux ConvertX86pI8_24 "_*"
#pragma aux ConvertX86pI8_16 "_*"
#pragma aux ConvertX86p16_32RGB888_LUT_X86 "_*"
#pragma aux ConvertX86p16_32BGR888_LUT_X86 "_*"
#pragma aux ConvertX86p16_32RGBA888_LUT_X86 "_*"
#pragma aux ConvertX86p16_32BGRA888_LUT_X86 "_*"
#endif /* __WATCOMC__ */
#endif /* X86_ASSEMBLER */
#endif

View File

@ -0,0 +1,74 @@
;
; mmx format converter main loops for HERMES
; Some routines Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk)
; This source code is licensed under the GNU LGPL
;
; Please refer to the file COPYING.LIB contained in the distribution for
; licensing conditions
;
BITS 32
GLOBAL _ConvertMMX
GLOBAL _mmxreturn
SECTION .text
;; _ConvertMMX:
;; [ESP+8] ConverterInfo*
;; --------------------------------------------------------------------------
;; ConverterInfo (ebp+..)
;; 0: void *s_pixels
;; 4: int s_width
;; 8: int s_height
;; 12: int s_add
;; 16: void *d_pixels
;; 20: int d_width
;; 24: int d_height
;; 28: int d_add
;; 32: void (*converter_function)()
;; 36: int32 *lookup
_ConvertMMX:
push ebp
mov ebp,esp
; Save the registers used by the blitters, necessary for optimized code
pusha
mov eax,[ebp+8]
cmp dword [eax+4],BYTE 0
je endconvert
mov ebp,eax
mov esi,[ebp+0]
mov edi,[ebp+16]
y_loop:
mov ecx,[ebp+4]
jmp [ebp+32]
_mmxreturn:
add esi,[ebp+12]
add edi,[ebp+28]
dec dword [ebp+8]
jnz y_loop
; Restore the registers used by the blitters, necessary for optimized code
popa
pop ebp
endconvert:
emms
ret

View File

@ -0,0 +1,386 @@
;
; pII-optimised MMX format converters for HERMES
; Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk)
; and (c) 1999 Jonathan Matthew (jmatthew@uq.net.au)
; This source code is licensed under the GNU LGPL
;
; Please refer to the file COPYING.LIB contained in the distribution for
; licensing conditions
;
; COPYRIGHT NOTICE
;
; This file partly contains code that is (c) Intel Corporation, specifically
; the mode detection routine, and the converter to 15 bit (8 pixel
; conversion routine from the mmx programming tutorial pages).
;
;
; These routines aren't exactly pII optimised - it's just that as they
; are, they're terrible on p5 MMXs, but less so on pIIs. Someone needs to
; optimise them for p5 MMXs..
BITS 32
GLOBAL _ConvertMMXpII32_24RGB888
GLOBAL _ConvertMMXpII32_16RGB565
GLOBAL _ConvertMMXpII32_16BGR565
GLOBAL _ConvertMMXpII32_16RGB555
GLOBAL _ConvertMMXpII32_16BGR555
EXTERN _mmxreturn
SECTION .data
ALIGN 8
;; Constants for conversion routines
mmx32_rgb888_mask dd 00ffffffh,00ffffffh
mmx32_rgb565_b dd 000000f8h, 000000f8h
mmx32_rgb565_g dd 0000fc00h, 0000fc00h
mmx32_rgb565_r dd 00f80000h, 00f80000h
mmx32_rgb555_rb dd 00f800f8h,00f800f8h
mmx32_rgb555_g dd 0000f800h,0000f800h
mmx32_rgb555_mul dd 20000008h,20000008h
mmx32_bgr555_mul dd 00082000h,00082000h
SECTION .text
_ConvertMMXpII32_24RGB888:
; set up mm6 as the mask, mm7 as zero
movq mm6, qword [mmx32_rgb888_mask]
pxor mm7, mm7
mov edx, ecx ; save ecx
and ecx, 0fffffffch ; clear lower two bits
jnz .L1
jmp .L2
.L1:
movq mm0, [esi] ; A R G B a r g b
pand mm0, mm6 ; 0 R G B 0 r g b
movq mm1, [esi+8] ; A R G B a r g b
pand mm1, mm6 ; 0 R G B 0 r g b
movq mm2, mm0 ; 0 R G B 0 r g b
punpckhdq mm2, mm7 ; 0 0 0 0 0 R G B
punpckldq mm0, mm7 ; 0 0 0 0 0 r g b
psllq mm2, 24 ; 0 0 R G B 0 0 0
por mm0, mm2 ; 0 0 R G B r g b
movq mm3, mm1 ; 0 R G B 0 r g b
psllq mm3, 48 ; g b 0 0 0 0 0 0
por mm0, mm3 ; g b R G B r g b
movq mm4, mm1 ; 0 R G B 0 r g b
punpckhdq mm4, mm7 ; 0 0 0 0 0 R G B
punpckldq mm1, mm7 ; 0 0 0 0 0 r g b
psrlq mm1, 16 ; 0 0 0 R G B 0 r
psllq mm4, 8 ; 0 0 0 0 R G B 0
por mm1, mm4 ; 0 0 0 0 R G B r
movq [edi], mm0
add esi, BYTE 16
movd [edi+8], mm1
add edi, BYTE 12
sub ecx, BYTE 4
jnz .L1
.L2:
mov ecx, edx
and ecx, BYTE 3
jz .L4
.L3:
mov al, [esi]
mov bl, [esi+1]
mov dl, [esi+2]
mov [edi], al
mov [edi+1], bl
mov [edi+2], dl
add esi, BYTE 4
add edi, BYTE 3
dec ecx
jnz .L3
.L4:
jmp _mmxreturn
_ConvertMMXpII32_16RGB565:
; set up masks
movq mm5, [mmx32_rgb565_b]
movq mm6, [mmx32_rgb565_g]
movq mm7, [mmx32_rgb565_r]
mov edx, ecx
shr ecx, 2
jnz .L1
jmp .L2 ; not necessary at the moment, but doesn't hurt (much)
.L1:
movq mm0, [esi] ; argb
movq mm1, mm0 ; argb
pand mm0, mm6 ; 00g0
movq mm3, mm1 ; argb
pand mm1, mm5 ; 000b
pand mm3, mm7 ; 0r00
pslld mm1, 2 ; 0 0 000000bb bbb00000
por mm0, mm1 ; 0 0 ggggggbb bbb00000
psrld mm0, 5 ; 0 0 00000ggg gggbbbbb
movq mm4, [esi+8] ; argb
movq mm2, mm4 ; argb
pand mm4, mm6 ; 00g0
movq mm1, mm2 ; argb
pand mm2, mm5 ; 000b
pand mm1, mm7 ; 0r00
pslld mm2, 2 ; 0 0 000000bb bbb00000
por mm4, mm2 ; 0 0 ggggggbb bbb00000
psrld mm4, 5 ; 0 0 00000ggg gggbbbbb
packuswb mm3, mm1 ; R 0 r 0
packssdw mm0, mm4 ; as above.. ish
por mm0, mm3 ; done.
movq [edi], mm0
add esi, 16
add edi, 8
dec ecx
jnz .L1
.L2:
mov ecx, edx
and ecx, BYTE 3
jz .L4
.L3:
mov al, [esi]
mov bh, [esi+1]
mov ah, [esi+2]
shr al, 3
and eax, 0F81Fh ; BYTE?
shr ebx, 5
and ebx, 07E0h ; BYTE?
add eax, ebx
mov [edi], al
mov [edi+1], ah
add esi, BYTE 4
add edi, BYTE 2
dec ecx
jnz .L3
.L4:
jmp _mmxreturn
_ConvertMMXpII32_16BGR565:
movq mm5, [mmx32_rgb565_r]
movq mm6, [mmx32_rgb565_g]
movq mm7, [mmx32_rgb565_b]
mov edx, ecx
shr ecx, 2
jnz .L1
jmp .L2
.L1:
movq mm0, [esi] ; a r g b
movq mm1, mm0 ; a r g b
pand mm0, mm6 ; 0 0 g 0
movq mm3, mm1 ; a r g b
pand mm1, mm5 ; 0 r 0 0
pand mm3, mm7 ; 0 0 0 b
psllq mm3, 16 ; 0 b 0 0
psrld mm1, 14 ; 0 0 000000rr rrr00000
por mm0, mm1 ; 0 0 ggggggrr rrr00000
psrld mm0, 5 ; 0 0 00000ggg gggrrrrr
movq mm4, [esi+8] ; a r g b
movq mm2, mm4 ; a r g b
pand mm4, mm6 ; 0 0 g 0
movq mm1, mm2 ; a r g b
pand mm2, mm5 ; 0 r 0 0
pand mm1, mm7 ; 0 0 0 b
psllq mm1, 16 ; 0 b 0 0
psrld mm2, 14 ; 0 0 000000rr rrr00000
por mm4, mm2 ; 0 0 ggggggrr rrr00000
psrld mm4, 5 ; 0 0 00000ggg gggrrrrr
packuswb mm3, mm1 ; BBBBB000 00000000 bbbbb000 00000000
packssdw mm0, mm4 ; 00000GGG GGGRRRRR 00000GGG GGGRRRRR
por mm0, mm3 ; BBBBBGGG GGGRRRRR bbbbbggg gggrrrrr
movq [edi], mm0
add esi, BYTE 16
add edi, BYTE 8
dec ecx
jnz .L1
.L2:
and edx, BYTE 3
jz .L4
.L3:
mov al, [esi+2]
mov bh, [esi+1]
mov ah, [esi]
shr al, 3
and eax, 0F81Fh ; BYTE ?
shr ebx, 5
and ebx, 07E0h ; BYTE ?
add eax, ebx
mov [edi], al
mov [edi+1], ah
add esi, BYTE 4
add edi, BYTE 2
dec edx
jnz .L3
.L4:
jmp _mmxreturn
_ConvertMMXpII32_16BGR555:
; the 16BGR555 converter is identical to the RGB555 one,
; except it uses a different multiplier for the pmaddwd
; instruction. cool huh.
movq mm7, qword [mmx32_bgr555_mul]
jmp _convert_bgr555_cheat
; This is the same as the Intel version.. they obviously went to
; much more trouble to expand/coil the loop than I did, so theirs
; would almost certainly be faster, even if only a little.
; I did rename 'mmx32_rgb555_add' to 'mmx32_rgb555_mul', which is
; (I think) a more accurate name..
_ConvertMMXpII32_16RGB555:
movq mm7,qword [mmx32_rgb555_mul]
_convert_bgr555_cheat:
movq mm6,qword [mmx32_rgb555_g]
mov edx,ecx ; Save ecx
and ecx,BYTE 0fffffff8h ; clear lower three bits
jnz .L_OK
jmp .L2
.L_OK:
movq mm2,[esi+8]
movq mm0,[esi]
movq mm3,mm2
pand mm3,qword [mmx32_rgb555_rb]
movq mm1,mm0
pand mm1,qword [mmx32_rgb555_rb]
pmaddwd mm3,mm7
pmaddwd mm1,mm7
pand mm2,mm6
.L1:
movq mm4,[esi+24]
pand mm0,mm6
movq mm5,[esi+16]
por mm3,mm2
psrld mm3,6
por mm1,mm0
movq mm0,mm4
psrld mm1,6
pand mm0,qword [mmx32_rgb555_rb]
packssdw mm1,mm3
movq mm3,mm5
pmaddwd mm0,mm7
pand mm3,qword [mmx32_rgb555_rb]
pand mm4,mm6
movq [edi],mm1
pmaddwd mm3,mm7
add esi,BYTE 32
por mm4,mm0
pand mm5,mm6
psrld mm4,6
movq mm2,[esi+8]
por mm5,mm3
movq mm0,[esi]
psrld mm5,6
movq mm3,mm2
movq mm1,mm0
pand mm3,qword [mmx32_rgb555_rb]
packssdw mm5,mm4
pand mm1,qword [mmx32_rgb555_rb]
pand mm2,mm6
movq [edi+8],mm5
pmaddwd mm3,mm7
pmaddwd mm1,mm7
add edi,BYTE 16
sub ecx,BYTE 8
jz .L2
jmp .L1
.L2:
mov ecx,edx
and ecx,BYTE 7
jz .L4
.L3:
mov ebx,[esi]
add esi,BYTE 4
mov eax,ebx
mov edx,ebx
shr eax,3
shr edx,6
and eax,BYTE 0000000000011111b
and edx, 0000001111100000b
shr ebx,9
or eax,edx
and ebx, 0111110000000000b
or eax,ebx
mov [edi],ax
add edi,BYTE 2
dec ecx
jnz .L3
.L4:
jmp _mmxreturn

View File

@ -0,0 +1,126 @@
;
; x86 format converters for HERMES
; Some routines Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at)
; This source code is licensed under the GNU LGPL
;
; Please refer to the file COPYING.LIB contained in the distribution for
; licensing conditions
;
; Most routines are (c) Glenn Fiedler (ptc@gaffer.org), used with permission
;
BITS 32
GLOBAL _ConvertX86
GLOBAL _x86return
GLOBAL _Hermes_X86_CPU
SECTION .data
cpu_flags dd 0
SECTION .text
;; _ConvertX86:
;; [ESP+8] ConverterInfo*
;; --------------------------------------------------------------------------
;; ConverterInfo (ebp+..)
;; 0: void *s_pixels
;; 4: int s_width
;; 8: int s_height
;; 12: int s_add
;; 16: void *d_pixels
;; 20: int d_width
;; 24: int d_height
;; 28: int d_add
;; 32: void (*converter_function)()
;; 36: int32 *lookup
_ConvertX86:
push ebp
mov ebp,esp
; Save the registers used by the blitters, necessary for optimized code
pusha
mov eax,[ebp+8]
cmp dword [eax+4],BYTE 0
je endconvert
mov ebp,eax
mov esi,[ebp+0]
mov edi,[ebp+16]
y_loop:
mov ecx,[ebp+4]
jmp [ebp+32]
_x86return:
add esi,[ebp+12]
add edi,[ebp+28]
dec dword [ebp+8]
jnz y_loop
; Restore the registers used by the blitters, necessary for optimized code
popa
pop ebp
endconvert:
ret
;; Hermes_X86_CPU returns the CPUID flags in eax
_Hermes_X86_CPU:
pushfd
pop eax
mov ecx,eax
xor eax,040000h
push eax
popfd
pushfd
pop eax
xor eax,ecx
jz .L1 ; Processor is 386
push ecx
popfd
mov eax,ecx
xor eax,200000h
push eax
popfd
pushfd
pop eax
xor eax,ecx
je .L1
pusha
mov eax,1
cpuid
mov [cpu_flags],edx
popa
mov eax,[cpu_flags]
.L1:
xor eax,eax
ret

View File

@ -0,0 +1,496 @@
;
; x86 format converters for HERMES
; Copyright (c) 1998 Glenn Fielder (gaffer@gaffer.org)
; This source code is licensed under the GNU LGPL
;
; Please refer to the file COPYING.LIB contained in the distribution for
; licensing conditions
;
; Routines adjusted for Hermes by Christian Nentwich (brn@eleet.mcb.at)
; Used with permission.
;
BITS 32
GLOBAL _ConvertX86p16_32RGB888
GLOBAL _ConvertX86p16_32BGR888
GLOBAL _ConvertX86p16_32RGBA888
GLOBAL _ConvertX86p16_32BGRA888
GLOBAL _ConvertX86p16_24RGB888
GLOBAL _ConvertX86p16_24BGR888
GLOBAL _ConvertX86p16_16BGR565
GLOBAL _ConvertX86p16_16RGB555
GLOBAL _ConvertX86p16_16BGR555
GLOBAL _ConvertX86p16_8RGB332
EXTERN _ConvertX86
EXTERN _x86return
SECTION .text
_ConvertX86p16_16BGR565:
; check short
cmp ecx,BYTE 16
ja .L3
.L1 ; short loop
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
and ebx,11111100000b
shl edx,11
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
jnz .L1
.L2
jmp _x86return
.L3 ; head
mov eax,edi
and eax,BYTE 11b
jz .L4
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
and ebx,11111100000b
shl edx,11
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
.L4 ; save count
push ecx
; unroll twice
shr ecx,1
; point arrays to end
lea esi,[esi+ecx*4]
lea edi,[edi+ecx*4]
; negative counter
neg ecx
jmp SHORT .L6
.L5 mov [edi+ecx*4-4],eax
.L6 mov eax,[esi+ecx*4]
mov ebx,[esi+ecx*4]
and eax,07E007E0h
mov edx,[esi+ecx*4]
and ebx,0F800F800h
shr ebx,11
and edx,001F001Fh
shl edx,11
add eax,ebx
add eax,edx
inc ecx
jnz .L5
mov [edi+ecx*4-4],eax
; tail
pop ecx
and ecx,BYTE 1
jz .L7
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
and ebx,11111100000b
shl edx,11
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
.L7
jmp _x86return
_ConvertX86p16_16RGB555:
; check short
cmp ecx,BYTE 32
ja .L3
.L1 ; short loop
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
shr ebx,1
and ebx, 0111111111100000b
and eax,BYTE 0000000000011111b
add eax,ebx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
jnz .L1
.L2
jmp _x86return
.L3 ; head
mov eax,edi
and eax,BYTE 11b
jz .L4
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
shr ebx,1
and ebx, 0111111111100000b
and eax,BYTE 0000000000011111b
add eax,ebx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
.L4 ; save ebp
push ebp
; save count
push ecx
; unroll four times
shr ecx,2
; point arrays to end
lea esi,[esi+ecx*8]
lea edi,[edi+ecx*8]
; negative counter
xor ebp,ebp
sub ebp,ecx
.L5 mov eax,[esi+ebp*8] ; agi?
mov ecx,[esi+ebp*8+4]
mov ebx,eax
mov edx,ecx
and eax,0FFC0FFC0h
and ecx,0FFC0FFC0h
shr eax,1
and ebx,001F001Fh
shr ecx,1
and edx,001F001Fh
add eax,ebx
add ecx,edx
mov [edi+ebp*8],eax
mov [edi+ebp*8+4],ecx
inc ebp
jnz .L5
; tail
pop ecx
.L6 and ecx,BYTE 11b
jz .L7
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
shr ebx,1
and ebx, 0111111111100000b
and eax,BYTE 0000000000011111b
add eax,ebx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
jmp SHORT .L6
.L7 pop ebp
jmp _x86return
_ConvertX86p16_16BGR555:
; check short
cmp ecx,BYTE 16
ja .L3
.L1 ; short loop
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
shr ebx,1
and ebx,1111100000b
shl edx,10
and edx,0111110000000000b
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
jnz .L1
.L2
jmp _x86return
.L3 ; head
mov eax,edi
and eax,BYTE 11b
jz .L4
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
shr ebx,1
and ebx,1111100000b
shl edx,10
and edx,0111110000000000b
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
dec ecx
.L4 ; save count
push ecx
; unroll twice
shr ecx,1
; point arrays to end
lea esi,[esi+ecx*4]
lea edi,[edi+ecx*4]
; negative counter
neg ecx
jmp SHORT .L6
.L5 mov [edi+ecx*4-4],eax
.L6 mov eax,[esi+ecx*4]
shr eax,1
mov ebx,[esi+ecx*4]
and eax,03E003E0h
mov edx,[esi+ecx*4]
and ebx,0F800F800h
shr ebx,11
and edx,001F001Fh
shl edx,10
add eax,ebx
add eax,edx
inc ecx
jnz .L5
mov [edi+ecx*4-4],eax
; tail
pop ecx
and ecx,BYTE 1
jz .L7
mov al,[esi]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
shr eax,11
and eax,BYTE 11111b
shr ebx,1
and ebx,1111100000b
shl edx,10
and edx,0111110000000000b
add eax,ebx
add eax,edx
mov [edi],al
mov [edi+1],ah
add esi,BYTE 2
add edi,BYTE 2
.L7
jmp _x86return
_ConvertX86p16_8RGB332:
; check short
cmp ecx,BYTE 16
ja .L3
.L1 ; short loop
mov al,[esi+0]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
and eax,BYTE 11000b ; blue
shr eax,3
and ebx,11100000000b ; green
shr ebx,6
and edx,1110000000000000b ; red
shr edx,8
add eax,ebx
add eax,edx
mov [edi],al
add esi,BYTE 2
inc edi
dec ecx
jnz .L1
.L2
jmp _x86return
.L3 mov eax,edi
and eax,BYTE 11b
jz .L4
mov al,[esi+0]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
and eax,BYTE 11000b ; blue
shr eax,3
and ebx,11100000000b ; green
shr ebx,6
and edx,1110000000000000b ; red
shr edx,8
add eax,ebx
add eax,edx
mov [edi],al
add esi,BYTE 2
inc edi
dec ecx
jmp SHORT .L3
.L4 ; save ebp
push ebp
; save count
push ecx
; unroll 4 times
shr ecx,2
; prestep
mov dl,[esi+0]
mov bl,[esi+1]
mov dh,[esi+2]
.L5 shl edx,16
mov bh,[esi+3]
shl ebx,16
mov dl,[esi+4]
mov dh,[esi+6]
mov bl,[esi+5]
and edx,00011000000110000001100000011000b
mov bh,[esi+7]
ror edx,16+3
mov eax,ebx ; setup eax for reds
and ebx,00000111000001110000011100000111b
and eax,11100000111000001110000011100000b ; reds
ror ebx,16-2
add esi,BYTE 8
ror eax,16
add edi,BYTE 4
add eax,ebx
mov bl,[esi+1] ; greens
add eax,edx
mov dl,[esi+0] ; blues
mov [edi-4],eax
mov dh,[esi+2]
dec ecx
jnz .L5
; check tail
pop ecx
and ecx,BYTE 11b
jz .L7
.L6 ; tail
mov al,[esi+0]
mov ah,[esi+1]
mov ebx,eax
mov edx,eax
and eax,BYTE 11000b ; blue
shr eax,3
and ebx,11100000000b ; green
shr ebx,6
and edx,1110000000000000b ; red
shr edx,8
add eax,ebx
add eax,edx
mov [edi],al
add esi,BYTE 2
inc edi
dec ecx
jnz .L6
.L7 pop ebp
jmp _x86return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_joystick_c.h,v 1.2 2001/04/26 16:50:17 hercules Exp $";
#endif
/* Useful functions and variables from SDL_joystick.c */
#include "SDL_joystick.h"
/* The number of available joysticks on the system */
extern Uint8 SDL_numjoysticks;
/* Internal event queueing functions */
extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick,
Uint8 axis, Sint16 value);
extern int SDL_PrivateJoystickBall(SDL_Joystick *joystick,
Uint8 ball, Sint16 xrel, Sint16 yrel);
extern int SDL_PrivateJoystickHat(SDL_Joystick *joystick,
Uint8 hat, Uint8 value);
extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick,
Uint8 button, Uint8 state);

View File

@ -0,0 +1,86 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_sysjoystick.h,v 1.2 2001/04/26 16:50:17 hercules Exp $";
#endif
/* This is the system specific header for the SDL joystick API */
#include "SDL_joystick.h"
/* The SDL joystick structure */
struct _SDL_Joystick {
Uint8 index; /* Device index */
const char *name; /* Joystick name - system dependent */
int naxes; /* Number of axis controls on the joystick */
Sint16 *axes; /* Current axis states */
int nhats; /* Number of hats on the joystick */
Uint8 *hats; /* Current hat states */
int nballs; /* Number of trackballs on the joystick */
struct balldelta {
int dx;
int dy;
} *balls; /* Current ball motion deltas */
int nbuttons; /* Number of buttons on the joystick */
Uint8 *buttons; /* Current button states */
struct joystick_hwdata *hwdata; /* Driver dependent information */
int ref_count; /* Reference count for multiple opens */
};
/* Function to scan the system for joysticks.
* Joystick 0 should be the system default joystick.
* This function should return the number of available joysticks, or -1
* on an unrecoverable fatal error.
*/
extern int SDL_SYS_JoystickInit(void);
/* Function to get the device-dependent name of a joystick */
extern const char *SDL_SYS_JoystickName(int index);
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
extern int SDL_SYS_JoystickOpen(SDL_Joystick *joystick);
/* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state.
*/
extern void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick);
/* Function to close a joystick after use */
extern void SDL_SYS_JoystickClose(SDL_Joystick *joystick);
/* Function to perform any system-specific joystick related cleanup */
extern void SDL_SYS_JoystickQuit(void);

View File

@ -0,0 +1,222 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_syscond.c
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
implementation, written by Christopher Tate and Owen Smith. Thanks!
*/
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
struct SDL_cond
{
SDL_mutex *lock;
int waiting;
int signals;
SDL_sem *wait_sem;
SDL_sem *wait_done;
};
/* Create a condition variable */
SDL_cond * SDL_CreateCond(void)
{
SDL_cond *cond;
cond = (SDL_cond *) malloc(sizeof(SDL_cond));
if ( cond ) {
cond->lock = SDL_CreateMutex();
cond->wait_sem = SDL_CreateSemaphore(0);
cond->wait_done = SDL_CreateSemaphore(0);
cond->waiting = cond->signals = 0;
if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
SDL_DestroyCond(cond);
cond = NULL;
}
} else {
SDL_OutOfMemory();
}
return(cond);
}
/* Destroy a condition variable */
void SDL_DestroyCond(SDL_cond *cond)
{
if ( cond ) {
if ( cond->wait_sem ) {
SDL_DestroySemaphore(cond->wait_sem);
}
if ( cond->wait_done ) {
SDL_DestroySemaphore(cond->wait_done);
}
if ( cond->lock ) {
SDL_DestroyMutex(cond->lock);
}
free(cond);
}
}
/* Restart one of the threads that are waiting on the condition variable */
int SDL_CondSignal(SDL_cond *cond)
{
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
SDL_LockMutex(cond->lock);
if ( cond->waiting > cond->signals ) {
++cond->signals;
SDL_SemPost(cond->wait_sem);
SDL_UnlockMutex(cond->lock);
SDL_SemWait(cond->wait_done);
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Restart all threads that are waiting on the condition variable */
int SDL_CondBroadcast(SDL_cond *cond)
{
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
SDL_LockMutex(cond->lock);
if ( cond->waiting > cond->signals ) {
int i, num_waiting;
num_waiting = (cond->waiting - cond->signals);
cond->signals = cond->waiting;
for ( i=0; i<num_waiting; ++i ) {
SDL_SemPost(cond->wait_sem);
}
/* Now all released threads are blocked here, waiting for us.
Collect them all (and win fabulous prizes!) :-)
*/
SDL_UnlockMutex(cond->lock);
for ( i=0; i<num_waiting; ++i ) {
SDL_SemWait(cond->wait_done);
}
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Wait on the condition variable for at most 'ms' milliseconds.
The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait.
Typical use:
Thread A:
SDL_LockMutex(lock);
while ( ! condition ) {
SDL_CondWait(cond);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_UnlockMutex(lock);
*/
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{
int retval;
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* Obtain the protection mutex, and increment the number of waiters.
This allows the signal mechanism to only perform a signal if there
are waiting threads.
*/
SDL_LockMutex(cond->lock);
++cond->waiting;
SDL_UnlockMutex(cond->lock);
/* Unlock the mutex, as is required by condition variable semantics */
SDL_UnlockMutex(mutex);
/* Wait for a signal */
if ( ms == SDL_MUTEX_MAXWAIT ) {
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore
if we are stopped between the mutex unlock and semaphore wait,
giving a deadlock. See the following URL for details:
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
*/
SDL_LockMutex(cond->lock);
if ( cond->signals > 0 ) {
/* If we timed out, we need to eat a condition signal */
if ( retval > 0 ) {
SDL_SemWait(cond->wait_sem);
}
/* We always notify the signal thread that we are done */
SDL_SemPost(cond->wait_done);
/* Signal handshake complete */
--cond->signals;
}
--cond->waiting;
SDL_UnlockMutex(cond->lock);
/* Lock the mutex, as is required by condition variable semantics */
SDL_LockMutex(mutex);
return retval;
}
/* Wait on the condition variable forever */
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}

View File

@ -0,0 +1,25 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_syscond_c.h
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/

View File

@ -0,0 +1,136 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_sysmutex.c
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* An implementation of mutexes using semaphores */
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
struct SDL_mutex {
int recursive;
Uint32 owner;
SDL_sem *sem;
};
/* Create a mutex */
SDL_mutex *SDL_CreateMutex(void)
{
SDL_mutex *mutex;
/* Allocate mutex memory */
mutex = (SDL_mutex *)malloc(sizeof(*mutex));
if ( mutex ) {
/* Create the mutex semaphore, with initial value 1 */
mutex->sem = SDL_CreateSemaphore(1);
mutex->recursive = 0;
mutex->owner = 0;
if ( ! mutex->sem ) {
free(mutex);
mutex = NULL;
}
} else {
SDL_OutOfMemory();
}
return mutex;
}
/* Free the mutex */
void SDL_DestroyMutex(SDL_mutex *mutex)
{
if ( mutex ) {
if ( mutex->sem ) {
SDL_DestroySemaphore(mutex->sem);
}
free(mutex);
}
}
/* Lock the semaphore */
int SDL_mutexP(SDL_mutex *mutex)
{
#ifdef DISABLE_THREADS
return 0;
#else
Uint32 this_thread;
if ( mutex == NULL ) {
SDL_SetError("Passed a NULL mutex");
return -1;
}
this_thread = SDL_ThreadID();
if ( mutex->owner == this_thread ) {
++mutex->recursive;
} else {
/* The order of operations is important.
We set the locking thread id after we obtain the lock
so unlocks from other threads will fail.
*/
SDL_SemWait(mutex->sem);
mutex->owner = this_thread;
mutex->recursive = 0;
}
return 0;
#endif /* DISABLE_THREADS */
}
/* Unlock the mutex */
int SDL_mutexV(SDL_mutex *mutex)
{
#ifdef DISABLE_THREADS
return 0;
#else
if ( mutex == NULL ) {
SDL_SetError("Passed a NULL mutex");
return -1;
}
/* If we don't own the mutex, we can't unlock it */
if ( SDL_ThreadID() != mutex->owner ) {
SDL_SetError("mutex not owned by this thread");
return -1;
}
if ( mutex->recursive ) {
--mutex->recursive;
} else {
/* The order of operations is important.
First reset the owner so another thread doesn't lock
the mutex and set the ownership before we reset it,
then release the lock semaphore.
*/
mutex->owner = 0;
SDL_SemPost(mutex->sem);
}
return 0;
#endif /* DISABLE_THREADS */
}

View File

@ -0,0 +1,25 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_sysmutex_c.h
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/

View File

@ -0,0 +1,213 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_syssem.c
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* An implementation of semaphores using mutexes and condition variables */
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
#ifdef DISABLE_THREADS
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_SetError("SDL not configured with thread support");
return (SDL_sem *)0;
}
void SDL_DestroySemaphore(SDL_sem *sem)
{
return;
}
int SDL_SemTryWait(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
int SDL_SemWait(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
Uint32 SDL_SemValue(SDL_sem *sem)
{
return 0;
}
int SDL_SemPost(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
#else
struct SDL_semaphore
{
Uint32 count;
Uint32 waiters_count;
SDL_mutex *count_lock;
SDL_cond *count_nonzero;
};
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_sem *sem;
sem = (SDL_sem *)malloc(sizeof(*sem));
if ( ! sem ) {
SDL_OutOfMemory();
return(0);
}
sem->count = initial_value;
sem->waiters_count = 0;
sem->count_lock = SDL_CreateMutex();
sem->count_nonzero = SDL_CreateCond();
if ( ! sem->count_lock || ! sem->count_nonzero ) {
SDL_DestroySemaphore(sem);
return(0);
}
return(sem);
}
/* WARNING:
You cannot call this function when another thread is using the semaphore.
*/
void SDL_DestroySemaphore(SDL_sem *sem)
{
if ( sem ) {
sem->count = 0xFFFFFFFF;
while ( sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
SDL_Delay(10);
}
SDL_DestroyCond(sem->count_nonzero);
SDL_mutexP(sem->count_lock);
SDL_mutexV(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
free(sem);
}
}
int SDL_SemTryWait(SDL_sem *sem)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
retval = SDL_MUTEX_TIMEDOUT;
SDL_LockMutex(sem->count_lock);
if ( sem->count > 0 ) {
--sem->count;
retval = 0;
}
SDL_UnlockMutex(sem->count_lock);
return retval;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
/* A timeout of 0 is an easy case */
if ( timeout == 0 ) {
return SDL_SemTryWait(sem);
}
SDL_LockMutex(sem->count_lock);
++sem->waiters_count;
retval = 0;
while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
retval = SDL_CondWaitTimeout(sem->count_nonzero,
sem->count_lock, timeout);
}
--sem->waiters_count;
--sem->count;
SDL_UnlockMutex(sem->count_lock);
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32 SDL_SemValue(SDL_sem *sem)
{
Uint32 value;
value = 0;
if ( sem ) {
SDL_LockMutex(sem->count_lock);
value = sem->count;
SDL_UnlockMutex(sem->count_lock);
}
return value;
}
int SDL_SemPost(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
SDL_LockMutex(sem->count_lock);
if ( sem->waiters_count > 0 ) {
SDL_CondSignal(sem->count_nonzero);
}
++sem->count;
SDL_UnlockMutex(sem->count_lock);
return 0;
}
#endif /* DISABLE_THREADS */

View File

@ -0,0 +1,25 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_syssem_c.h
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/

View File

@ -0,0 +1,58 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_systhread.c
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Thread management routines for SDL */
#include "SDL_error.h"
#include "SDL_thread.h"
#include "SDL_systhread.h"
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
SDL_SetError("Threads are not supported on this platform");
return(-1);
}
void SDL_SYS_SetupThread(void)
{
return;
}
Uint32 SDL_ThreadID(void)
{
return(0);
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
return;
}
void SDL_SYS_KillThread(SDL_Thread *thread)
{
return;
}

View File

@ -0,0 +1,48 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_systhread.h,v 1.2 2001/04/26 16:50:17 hercules Exp $";
#endif
/* These are functions that need to be implemented by a port of SDL */
#include "SDL_thread_c.h"
/* This function creates a thread, passing args to SDL_RunThread(),
saves a system-dependent thread id in thread->id, and returns 0
on success.
*/
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args);
/* This function does any necessary setup in the child thread */
extern void SDL_SYS_SetupThread(void);
/* This function waits for the thread to finish and frees any data
allocated by SDL_SYS_CreateThread()
*/
extern void SDL_SYS_WaitThread(SDL_Thread *thread);
/* This function kills the thread and returns */
extern void SDL_SYS_KillThread(SDL_Thread *thread);

View File

@ -0,0 +1,29 @@
/* WARNING: This file was automatically generated!
* Original: ./src/thread/generic/SDL_systhread_c.h
*/
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Stub until we implement threads on this platform */
typedef int SYS_ThreadHandle;
#define DISABLE_THREADS

View File

@ -0,0 +1,296 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* System independent thread management routines for SDL */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_mutex.h"
#include "SDL_thread.h"
#include "SDL_thread_c.h"
#include "SDL_systhread.h"
#define ARRAY_CHUNKSIZE 32
/* The array of threads currently active in the application
(except the main thread)
The manipulation of an array here is safer than using a linked list.
*/
static int SDL_maxthreads = 0;
static int SDL_numthreads = 0;
static SDL_Thread **SDL_Threads = NULL;
static SDL_mutex *thread_lock = NULL;
int _creating_thread_lock = 0;
int SDL_ThreadsInit(void)
{
int retval;
retval = 0;
/* Set the thread lock creation flag so that we can reuse an
existing lock on the system - since this mutex never gets
destroyed (see SDL_ThreadsQuit()), we want to reuse it.
*/
_creating_thread_lock = 1;
thread_lock = SDL_CreateMutex();
_creating_thread_lock = 0;
if ( thread_lock == NULL ) {
retval = -1;
}
return(retval);
}
/* This should never be called...
If this is called by SDL_Quit(), we don't know whether or not we should
clean up threads here. If any threads are still running after this call,
they will no longer have access to any per-thread data.
*/
void SDL_ThreadsQuit()
{
SDL_mutex *mutex;
mutex = thread_lock;
thread_lock = NULL;
if ( mutex != NULL ) {
SDL_DestroyMutex(mutex);
}
}
/* Routines for manipulating the thread list */
static void SDL_AddThread(SDL_Thread *thread)
{
SDL_Thread **threads;
/* WARNING:
If the very first threads are created simultaneously, then
there could be a race condition causing memory corruption.
In practice, this isn't a problem because by definition there
is only one thread running the first time this is called.
*/
if ( thread_lock == NULL ) {
if ( SDL_ThreadsInit() < 0 ) {
return;
}
}
SDL_mutexP(thread_lock);
/* Expand the list of threads, if necessary */
#ifdef DEBUG_THREADS
printf("Adding thread (%d already - %d max)\n",
SDL_numthreads, SDL_maxthreads);
#endif
if ( SDL_numthreads == SDL_maxthreads ) {
threads=(SDL_Thread **)malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)*
(sizeof *threads));
if ( threads == NULL ) {
SDL_OutOfMemory();
goto done;
}
memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
SDL_maxthreads += ARRAY_CHUNKSIZE;
if ( SDL_Threads ) {
free(SDL_Threads);
}
SDL_Threads = threads;
}
SDL_Threads[SDL_numthreads++] = thread;
done:
SDL_mutexV(thread_lock);
}
static void SDL_DelThread(SDL_Thread *thread)
{
int i;
if ( thread_lock ) {
SDL_mutexP(thread_lock);
for ( i=0; i<SDL_numthreads; ++i ) {
if ( thread == SDL_Threads[i] ) {
break;
}
}
if ( i < SDL_numthreads ) {
--SDL_numthreads;
while ( i < SDL_numthreads ) {
SDL_Threads[i] = SDL_Threads[i+1];
++i;
}
#ifdef DEBUG_THREADS
printf("Deleting thread (%d left - %d max)\n",
SDL_numthreads, SDL_maxthreads);
#endif
}
SDL_mutexV(thread_lock);
}
}
/* The default (non-thread-safe) global error variable */
static SDL_error SDL_global_error;
/* Routine to get the thread-specific error variable */
SDL_error *SDL_GetErrBuf(void)
{
SDL_error *errbuf;
errbuf = &SDL_global_error;
if ( SDL_Threads ) {
int i;
Uint32 this_thread;
this_thread = SDL_ThreadID();
SDL_mutexP(thread_lock);
for ( i=0; i<SDL_numthreads; ++i ) {
if ( this_thread == SDL_Threads[i]->threadid ) {
errbuf = &SDL_Threads[i]->errbuf;
break;
}
}
SDL_mutexV(thread_lock);
}
return(errbuf);
}
/* Arguments and callback to setup and run the user thread function */
typedef struct {
int (*func)(void *);
void *data;
SDL_Thread *info;
SDL_sem *wait;
} thread_args;
void SDL_RunThread(void *data)
{
thread_args *args;
int (*userfunc)(void *);
void *userdata;
int *statusloc;
/* Perform any system-dependent setup
- this function cannot fail, and cannot use SDL_SetError()
*/
SDL_SYS_SetupThread();
/* Get the thread id */
args = (thread_args *)data;
args->info->threadid = SDL_ThreadID();
/* Figure out what function to run */
userfunc = args->func;
userdata = args->data;
statusloc = &args->info->status;
/* Wake up the parent thread */
SDL_SemPost(args->wait);
/* Run the function */
*statusloc = userfunc(userdata);
}
SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
{
SDL_Thread *thread;
thread_args *args;
int ret;
/* Allocate memory for the thread info structure */
thread = (SDL_Thread *)malloc(sizeof(*thread));
if ( thread == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
memset(thread, 0, (sizeof *thread));
thread->status = -1;
/* Set up the arguments for the thread */
args = (thread_args *)malloc(sizeof(*args));
if ( args == NULL ) {
SDL_OutOfMemory();
free(thread);
return(NULL);
}
args->func = fn;
args->data = data;
args->info = thread;
args->wait = SDL_CreateSemaphore(0);
if ( args->wait == NULL ) {
free(thread);
free(args);
return(NULL);
}
/* Add the thread to the list of available threads */
SDL_AddThread(thread);
/* Create the thread and go! */
ret = SDL_SYS_CreateThread(thread, args);
if ( ret >= 0 ) {
/* Wait for the thread function to use arguments */
SDL_SemWait(args->wait);
} else {
/* Oops, failed. Gotta free everything */
SDL_DelThread(thread);
free(thread);
thread = NULL;
}
SDL_DestroySemaphore(args->wait);
free(args);
/* Everything is running now */
return(thread);
}
void SDL_WaitThread(SDL_Thread *thread, int *status)
{
if ( thread ) {
SDL_SYS_WaitThread(thread);
if ( status ) {
*status = thread->status;
}
SDL_DelThread(thread);
free(thread);
}
}
Uint32 SDL_GetThreadID(SDL_Thread *thread)
{
Uint32 id;
if ( thread ) {
id = thread->threadid;
} else {
id = SDL_ThreadID();
}
return(id);
}
void SDL_KillThread(SDL_Thread *thread)
{
if ( thread ) {
SDL_SYS_KillThread(thread);
SDL_WaitThread(thread, NULL);
}
}

View File

@ -0,0 +1,44 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifndef _SDL_thread_c_h
#define _SDL_thread_c_h
#include "SDL_error_c.h"
#include "SDL_systhread_c.h"
/* This is the system-independent thread info structure */
struct SDL_Thread {
Uint32 threadid;
SYS_ThreadHandle handle;
int status;
SDL_error errbuf;
void *data;
};
/* This is the function called to run a thread */
extern void SDL_RunThread(void *data);
/* Routine to get the thread-specific error variable */
extern SDL_error *SDL_GetErrBuf(void);
#endif /* _SDL_thread_c_h */

View File

@ -0,0 +1,46 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998 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
5635-34 Springhouse Dr.
Pleasanton, CA 94588 (USA)
slouken@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_systimer.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* The system dependent timer handling functions */
#include "SDL_timer.h"
#include "SDL_timer_c.h"
/* Initialize the system dependent timer subsystem */
extern int SDL_SYS_TimerInit(void);
/* Quit the system dependent timer subsystem */
extern void SDL_SYS_TimerQuit(void);
/* Start a timer set up by SDL_SetTimer() */
extern int SDL_SYS_StartTimer(void);
/* Stop a previously started timer */
extern void SDL_SYS_StopTimer(void);

View File

@ -0,0 +1,281 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998 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
5635-34 Springhouse Dr.
Pleasanton, CA 94588 (USA)
slouken@devolution.com
*/
#include <stdlib.h>
#include <stdio.h> /* For the definition of NULL */
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_timer_c.h"
#include "SDL_mutex.h"
#include "SDL_systimer.h"
/* #define DEBUG_TIMERS */
int SDL_timer_started = 0;
int SDL_timer_running = 0;
/* Data to handle a single periodic alarm */
Uint32 SDL_alarm_interval = 0;
SDL_TimerCallback SDL_alarm_callback;
static SDL_bool list_changed = SDL_FALSE;
/* Data used for a thread-based timer */
static int SDL_timer_threaded = 0;
struct _SDL_TimerID {
Uint32 interval;
SDL_NewTimerCallback cb;
void *param;
Uint32 last_alarm;
struct _SDL_TimerID *next;
};
static SDL_TimerID SDL_timers = NULL;
static Uint32 num_timers = 0;
static SDL_mutex *SDL_timer_mutex;
/* Set whether or not the timer should use a thread.
This should not be called while the timer subsystem is running.
*/
int SDL_SetTimerThreaded(int value)
{
int retval;
if ( SDL_timer_started ) {
SDL_SetError("Timer already initialized");
retval = -1;
} else {
retval = 0;
SDL_timer_threaded = value;
}
return retval;
}
int SDL_TimerInit(void)
{
int retval;
SDL_timer_running = 0;
SDL_SetTimer(0, NULL);
retval = 0;
if ( ! SDL_timer_threaded ) {
retval = SDL_SYS_TimerInit();
}
if ( SDL_timer_threaded ) {
SDL_timer_mutex = SDL_CreateMutex();
}
SDL_timer_started = 1;
return(retval);
}
void SDL_TimerQuit(void)
{
SDL_SetTimer(0, NULL);
if ( SDL_timer_threaded < 2 ) {
SDL_SYS_TimerQuit();
}
if ( SDL_timer_threaded ) {
SDL_DestroyMutex(SDL_timer_mutex);
}
SDL_timer_started = 0;
SDL_timer_threaded = 0;
}
void SDL_ThreadedTimerCheck(void)
{
Uint32 now, ms;
SDL_TimerID t, prev, next;
int removed;
now = SDL_GetTicks();
SDL_mutexP(SDL_timer_mutex);
for ( prev = NULL, t = SDL_timers; t; t = next ) {
removed = 0;
ms = t->interval - SDL_TIMESLICE;
next = t->next;
if ( (t->last_alarm < now) && ((now - t->last_alarm) > ms) ) {
if ( (now - t->last_alarm) < t->interval ) {
t->last_alarm += t->interval;
} else {
t->last_alarm = now;
}
list_changed = SDL_FALSE;
#ifdef DEBUG_TIMERS
printf("Executing timer %p (thread = %d)\n",
t, SDL_ThreadID());
#endif
SDL_mutexV(SDL_timer_mutex);
ms = t->cb(t->interval, t->param);
SDL_mutexP(SDL_timer_mutex);
if ( list_changed ) {
/* Abort, list of timers has been modified */
break;
}
if ( ms != t->interval ) {
if ( ms ) {
t->interval = ROUND_RESOLUTION(ms);
} else { /* Remove the timer from the linked list */
#ifdef DEBUG_TIMERS
printf("SDL: Removing timer %p\n", t);
#endif
if ( prev ) {
prev->next = next;
} else {
SDL_timers = next;
}
free(t);
-- num_timers;
removed = 1;
}
}
}
/* Don't update prev if the timer has disappeared */
if ( ! removed ) {
prev = t;
}
}
SDL_mutexV(SDL_timer_mutex);
}
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
{
SDL_TimerID t;
if ( ! SDL_timer_mutex ) {
if ( SDL_timer_started ) {
SDL_SetError("This platform doesn't support multiple timers");
} else {
SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first");
}
return NULL;
}
if ( ! SDL_timer_threaded ) {
SDL_SetError("Multiple timers require threaded events!");
return NULL;
}
SDL_mutexP(SDL_timer_mutex);
t = (SDL_TimerID) malloc(sizeof(struct _SDL_TimerID));
if ( t ) {
t->interval = ROUND_RESOLUTION(interval);
t->cb = callback;
t->param = param;
t->last_alarm = SDL_GetTicks();
t->next = SDL_timers;
SDL_timers = t;
++ num_timers;
list_changed = SDL_TRUE;
SDL_timer_running = 1;
}
#ifdef DEBUG_TIMERS
printf("SDL_AddTimer(%d) = %08x num_timers = %d\n", interval, (Uint32)t, num_timers);
#endif
SDL_mutexV(SDL_timer_mutex);
return t;
}
SDL_bool SDL_RemoveTimer(SDL_TimerID id)
{
SDL_TimerID t, prev = NULL;
SDL_bool removed;
removed = SDL_FALSE;
SDL_mutexP(SDL_timer_mutex);
/* Look for id in the linked list of timers */
for (t = SDL_timers; t; prev=t, t = t->next ) {
if ( t == id ) {
if(prev) {
prev->next = t->next;
} else {
SDL_timers = t->next;
}
free(t);
-- num_timers;
removed = SDL_TRUE;
list_changed = SDL_TRUE;
break;
}
}
#ifdef DEBUG_TIMERS
printf("SDL_RemoveTimer(%08x) = %d num_timers = %d thread = %d\n", (Uint32)id, removed, num_timers, SDL_ThreadID());
#endif
SDL_mutexV(SDL_timer_mutex);
return removed;
}
static void SDL_RemoveAllTimers(SDL_TimerID t)
{
SDL_TimerID freeme;
/* Changed to non-recursive implementation.
The recursive implementation is elegant, but subject to
stack overflow if there are lots and lots of timers.
*/
while ( t ) {
freeme = t;
t = t->next;
free(freeme);
}
}
/* Old style callback functions are wrapped through this */
static Uint32 callback_wrapper(Uint32 ms, void *param)
{
SDL_TimerCallback func = (SDL_TimerCallback) param;
return (*func)(ms);
}
int SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback)
{
int retval;
#ifdef DEBUG_TIMERS
printf("SDL_SetTimer(%d)\n", ms);
#endif
retval = 0;
if ( SDL_timer_running ) { /* Stop any currently running timer */
SDL_timer_running = 0;
if ( SDL_timer_threaded ) {
SDL_mutexP(SDL_timer_mutex);
SDL_RemoveAllTimers(SDL_timers);
SDL_timers = NULL;
SDL_mutexV(SDL_timer_mutex);
} else {
SDL_SYS_StopTimer();
}
}
if ( ms ) {
if ( SDL_timer_threaded ) {
retval = (SDL_AddTimer(ms, callback_wrapper,
(void *)callback) != NULL);
} else {
SDL_timer_running = 1;
SDL_alarm_interval = ms;
SDL_alarm_callback = callback;
retval = SDL_SYS_StartTimer();
}
}
return retval;
}

View File

@ -0,0 +1,52 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998 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
5635-34 Springhouse Dr.
Pleasanton, CA 94588 (USA)
slouken@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_timer_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Useful functions and variables from SDL_timer.c */
#include "SDL_timer.h"
#define ROUND_RESOLUTION(X) \
(((X+TIMER_RESOLUTION-1)/TIMER_RESOLUTION)*TIMER_RESOLUTION)
extern int SDL_timer_started;
extern int SDL_timer_running;
/* Data to handle a single periodic alarm */
extern Uint32 SDL_alarm_interval;
extern SDL_TimerCallback SDL_alarm_callback;
/* Set whether or not the timer should use a thread.
This should be called while the timer subsystem is running.
*/
extern int SDL_SetTimerThreaded(int value);
extern int SDL_TimerInit(void);
extern void SDL_TimerQuit(void);
/* This function is called from the SDL event thread if it is available */
extern void SDL_ThreadedTimerCheck(void);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_RLEaccel_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Useful functions and variables from SDL_RLEaccel.c */
extern int SDL_RLESurface(SDL_Surface *surface);
extern int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);
extern int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);
extern void SDL_UnRLESurface(SDL_Surface *surface, int recode);

View File

@ -0,0 +1,289 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_blit.h"
#include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h"
#include "SDL_memops.h"
/* The general purpose software blit routine */
static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
int okay;
int src_locked;
int dst_locked;
/* Everything is okay at the beginning... */
okay = 1;
/* Lock the destination if it's in hardware */
dst_locked = 0;
if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
if ( video->LockHWSurface(this, dst) < 0 ) {
okay = 0;
} else {
dst_locked = 1;
}
}
/* Lock the source if it's in hardware */
src_locked = 0;
if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
if ( video->LockHWSurface(this, src) < 0 ) {
okay = 0;
} else {
src_locked = 1;
}
}
/* Unencode the destination if it's RLE encoded */
if ( dst->flags & SDL_RLEACCEL ) {
SDL_UnRLESurface(dst, 1);
dst->flags |= SDL_RLEACCEL; /* save accel'd state */
}
/* Set up source and destination buffer pointers, and BLIT! */
if ( okay && srcrect->w && srcrect->h ) {
SDL_BlitInfo info;
SDL_loblit RunBlit;
/* Set up the blit information */
info.s_pixels = (Uint8 *)src->pixels + src->offset +
(Uint16)srcrect->y*src->pitch +
(Uint16)srcrect->x*src->format->BytesPerPixel;
info.s_width = srcrect->w;
info.s_height = srcrect->h;
info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
(Uint16)dstrect->y*dst->pitch +
(Uint16)dstrect->x*dst->format->BytesPerPixel;
info.d_width = dstrect->w;
info.d_height = dstrect->h;
info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
info.aux_data = src->map->sw_data->aux_data;
info.src = src->format;
info.table = src->map->table;
info.dst = dst->format;
RunBlit = src->map->sw_data->blit;
/* Run the actual software blit */
RunBlit(&info);
}
/* Re-encode the destination if it's RLE encoded */
if ( dst->flags & SDL_RLEACCEL ) {
dst->flags &= ~SDL_RLEACCEL; /* stop lying */
SDL_RLESurface(dst);
}
/* We need to unlock the surfaces if they're locked */
if ( dst_locked ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
video->UnlockHWSurface(this, dst);
} else
if ( src_locked ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
video->UnlockHWSurface(this, src);
}
/* Blit is done! */
return(okay ? 0 : -1);
}
static void SDL_BlitCopy(SDL_BlitInfo *info)
{
Uint8 *src, *dst;
int w, h;
int srcskip, dstskip;
w = info->d_width*info->dst->BytesPerPixel;
h = info->d_height;
src = info->s_pixels;
dst = info->d_pixels;
srcskip = w+info->s_skip;
dstskip = w+info->d_skip;
while ( h-- ) {
SDL_memcpy(dst, src, w);
src += srcskip;
dst += dstskip;
}
}
static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
{
Uint8 *src, *dst;
int w, h;
int srcskip, dstskip;
w = info->d_width*info->dst->BytesPerPixel;
h = info->d_height;
src = info->s_pixels;
dst = info->d_pixels;
srcskip = w+info->s_skip;
dstskip = w+info->d_skip;
if ( dst < src ) {
while ( h-- ) {
SDL_memcpy(dst, src, w);
src += srcskip;
dst += dstskip;
}
} else {
src += ((h-1) * srcskip);
dst += ((h-1) * dstskip);
while ( h-- ) {
SDL_revcpy(dst, src, w);
src -= srcskip;
dst -= dstskip;
}
}
}
/* Figure out which of many blit routines to set up on a surface */
int SDL_CalculateBlit(SDL_Surface *surface)
{
int blit_index;
/* Clean everything out to start */
if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
SDL_UnRLESurface(surface, 1);
}
surface->map->sw_blit = NULL;
/* Figure out if an accelerated hardware blit is possible */
surface->flags &= ~SDL_HWACCEL;
if ( surface->map->identity ) {
int hw_blit_ok;
if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
/* We only support accelerated blitting to hardware */
if ( surface->map->dst->flags & SDL_HWSURFACE ) {
hw_blit_ok = current_video->info.blit_hw;
} else {
hw_blit_ok = 0;
}
if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
hw_blit_ok = current_video->info.blit_hw_CC;
}
if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
hw_blit_ok = current_video->info.blit_hw_A;
}
} else {
/* We only support accelerated blitting to hardware */
if ( surface->map->dst->flags & SDL_HWSURFACE ) {
hw_blit_ok = current_video->info.blit_sw;
} else {
hw_blit_ok = 0;
}
if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
hw_blit_ok = current_video->info.blit_sw_CC;
}
if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
hw_blit_ok = current_video->info.blit_sw_A;
}
}
if ( hw_blit_ok ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
video->CheckHWBlit(this, surface, surface->map->dst);
}
}
/* Get the blit function index, based on surface mode */
/* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
blit_index = 0;
blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
if ( surface->flags & SDL_SRCALPHA
&& (surface->format->alpha != SDL_ALPHA_OPAQUE
|| surface->format->Amask) ) {
blit_index |= 2;
}
/* Check for special "identity" case -- copy blit */
if ( surface->map->identity && blit_index == 0 ) {
surface->map->sw_data->blit = SDL_BlitCopy;
/* Handle overlapping blits on the same surface */
if ( surface == surface->map->dst ) {
surface->map->sw_data->blit = SDL_BlitCopyOverlap;
}
} else {
if ( surface->format->BitsPerPixel < 8 ) {
surface->map->sw_data->blit =
SDL_CalculateBlit0(surface, blit_index);
} else {
switch ( surface->format->BytesPerPixel ) {
case 1:
surface->map->sw_data->blit =
SDL_CalculateBlit1(surface, blit_index);
break;
case 2:
case 3:
case 4:
surface->map->sw_data->blit =
SDL_CalculateBlitN(surface, blit_index);
break;
default:
surface->map->sw_data->blit = NULL;
break;
}
}
}
/* Make sure we have a blit function */
if ( surface->map->sw_data->blit == NULL ) {
SDL_InvalidateMap(surface->map);
SDL_SetError("Blit combination not supported");
return(-1);
}
/* Choose software blitting function */
if(surface->flags & SDL_RLEACCELOK
&& (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
if(surface->map->identity
&& (blit_index == 1
|| (blit_index == 3 && !surface->format->Amask))) {
if ( SDL_RLESurface(surface) == 0 )
surface->map->sw_blit = SDL_RLEBlit;
} else if(blit_index == 2 && surface->format->Amask) {
if ( SDL_RLESurface(surface) == 0 )
surface->map->sw_blit = SDL_RLEAlphaBlit;
}
}
if ( surface->map->sw_blit == NULL ) {
surface->map->sw_blit = SDL_SoftBlit;
}
return(0);
}

View File

@ -0,0 +1,437 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_blit.h,v 1.3 2001/07/07 20:20:16 hercules Exp $";
#endif
#ifndef _SDL_blit_h
#define _SDL_blit_h
#include "SDL_endian.h"
/* The structure passed to the low level blit functions */
typedef struct {
Uint8 *s_pixels;
int s_width;
int s_height;
int s_skip;
Uint8 *d_pixels;
int d_width;
int d_height;
int d_skip;
void *aux_data;
SDL_PixelFormat *src;
Uint8 *table;
SDL_PixelFormat *dst;
} SDL_BlitInfo;
/* The type definition for the low level blit functions */
typedef void (*SDL_loblit)(SDL_BlitInfo *info);
/* This is the private info structure for software accelerated blits */
struct private_swaccel {
SDL_loblit blit;
void *aux_data;
};
/* Blit mapping definition */
typedef struct SDL_BlitMap {
SDL_Surface *dst;
int identity;
Uint8 *table;
SDL_blit hw_blit;
SDL_blit sw_blit;
struct private_hwaccel *hw_data;
struct private_swaccel *sw_data;
/* the version count matches the destination; mismatch indicates
an invalid mapping */
unsigned int format_version;
} SDL_BlitMap;
/* Definitions for special global blit functions */
#include "SDL_blit_A.h"
/* Functions found in SDL_blit.c */
extern int SDL_CalculateBlit(SDL_Surface *surface);
/* Functions found in SDL_blit_{0,1,N,A}.c */
extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex);
extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex);
extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex);
extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex);
/*
* Useful macros for blitting routines
*/
#define FORMAT_EQUAL(A, B) \
((A)->BitsPerPixel == (B)->BitsPerPixel \
&& ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask))
/* Load pixel of the specified format from a buffer and get its R-G-B values */
/* FIXME: rescale values to 0..255 here? */
#define RGB_FROM_PIXEL(pixel, fmt, r, g, b) \
{ \
r = (((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \
g = (((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \
b = (((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \
}
#define RGB_FROM_RGB565(pixel, r, g, b) \
{ \
r = (((pixel&0xF800)>>11)<<3); \
g = (((pixel&0x07E0)>>5)<<2); \
b = ((pixel&0x001F)<<3); \
}
#define RGB_FROM_RGB555(pixel, r, g, b) \
{ \
r = (((pixel&0x7C00)>>10)<<3); \
g = (((pixel&0x03E0)>>5)<<3); \
b = ((pixel&0x001F)<<3); \
}
#define RGB_FROM_RGB888(pixel, r, g, b) \
{ \
r = ((pixel&0xFF0000)>>16); \
g = ((pixel&0xFF00)>>8); \
b = (pixel&0xFF); \
}
#define RETRIEVE_RGB_PIXEL(buf, bpp, pixel) \
do { \
switch (bpp) { \
case 2: \
pixel = *((Uint16 *)(buf)); \
break; \
\
case 3: { \
Uint8 *B = (Uint8 *)(buf); \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
} else { \
pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
} \
} \
break; \
\
case 4: \
pixel = *((Uint32 *)(buf)); \
break; \
\
default: \
pixel = 0; /* appease gcc */ \
break; \
} \
} while(0)
#define DISEMBLE_RGB(buf, bpp, fmt, pixel, r, g, b) \
do { \
switch (bpp) { \
case 2: \
pixel = *((Uint16 *)(buf)); \
break; \
\
case 3: { \
Uint8 *B = (Uint8 *)buf; \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
} else { \
pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
} \
} \
break; \
\
case 4: \
pixel = *((Uint32 *)(buf)); \
break; \
\
default: \
pixel = 0; /* prevent gcc from complaining */ \
break; \
} \
RGB_FROM_PIXEL(pixel, fmt, r, g, b); \
} while(0)
/* Assemble R-G-B values into a specified pixel format and store them */
#define PIXEL_FROM_RGB(pixel, fmt, r, g, b) \
{ \
pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \
((g>>fmt->Gloss)<<fmt->Gshift)| \
((b>>fmt->Bloss)<<fmt->Bshift); \
}
#define RGB565_FROM_RGB(pixel, r, g, b) \
{ \
pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \
}
#define RGB555_FROM_RGB(pixel, r, g, b) \
{ \
pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \
}
#define RGB888_FROM_RGB(pixel, r, g, b) \
{ \
pixel = (r<<16)|(g<<8)|b; \
}
#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \
{ \
switch (bpp) { \
case 2: { \
Uint16 pixel; \
\
PIXEL_FROM_RGB(pixel, fmt, r, g, b); \
*((Uint16 *)(buf)) = pixel; \
} \
break; \
\
case 3: { \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
*((buf)+fmt->Rshift/8) = r; \
*((buf)+fmt->Gshift/8) = g; \
*((buf)+fmt->Bshift/8) = b; \
} else { \
*((buf)+2-fmt->Rshift/8) = r; \
*((buf)+2-fmt->Gshift/8) = g; \
*((buf)+2-fmt->Bshift/8) = b; \
} \
} \
break; \
\
case 4: { \
Uint32 pixel; \
\
PIXEL_FROM_RGB(pixel, fmt, r, g, b); \
*((Uint32 *)(buf)) = pixel; \
} \
break; \
} \
}
#define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask) \
{ \
switch (bpp) { \
case 2: { \
Uint16 *bufp; \
Uint16 pixel; \
\
bufp = (Uint16 *)buf; \
PIXEL_FROM_RGB(pixel, fmt, r, g, b); \
*bufp = pixel | (*bufp & Amask); \
} \
break; \
\
case 3: { \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
*((buf)+fmt->Rshift/8) = r; \
*((buf)+fmt->Gshift/8) = g; \
*((buf)+fmt->Bshift/8) = b; \
} else { \
*((buf)+2-fmt->Rshift/8) = r; \
*((buf)+2-fmt->Gshift/8) = g; \
*((buf)+2-fmt->Bshift/8) = b; \
} \
} \
break; \
\
case 4: { \
Uint32 *bufp; \
Uint32 pixel; \
\
bufp = (Uint32 *)buf; \
PIXEL_FROM_RGB(pixel, fmt, r, g, b); \
*bufp = pixel | (*bufp & Amask); \
} \
break; \
} \
}
/* FIXME: Should we rescale alpha into 0..255 here? */
#define RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \
{ \
r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \
g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \
b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \
a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \
}
#define RGBA_FROM_8888(pixel, fmt, r, g, b, a) \
{ \
r = (pixel&fmt->Rmask)>>fmt->Rshift; \
g = (pixel&fmt->Gmask)>>fmt->Gshift; \
b = (pixel&fmt->Bmask)>>fmt->Bshift; \
a = (pixel&fmt->Amask)>>fmt->Ashift; \
}
#define RGBA_FROM_RGBA8888(pixel, r, g, b, a) \
{ \
r = (pixel>>24); \
g = ((pixel>>16)&0xFF); \
b = ((pixel>>8)&0xFF); \
a = (pixel&0xFF); \
}
#define RGBA_FROM_ARGB8888(pixel, r, g, b, a) \
{ \
r = ((pixel>>16)&0xFF); \
g = ((pixel>>8)&0xFF); \
b = (pixel&0xFF); \
a = (pixel>>24); \
}
#define RGBA_FROM_ABGR8888(pixel, r, g, b, a) \
{ \
r = (pixel&0xFF); \
g = ((pixel>>8)&0xFF); \
b = ((pixel>>16)&0xFF); \
a = (pixel>>24); \
}
#define DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \
do { \
switch (bpp) { \
case 2: \
pixel = *((Uint16 *)(buf)); \
break; \
\
case 3: {/* FIXME: broken code (no alpha) */ \
Uint8 *b = (Uint8 *)buf; \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
pixel = b[0] + (b[1] << 8) + (b[2] << 16); \
} else { \
pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \
} \
} \
break; \
\
case 4: \
pixel = *((Uint32 *)(buf)); \
break; \
\
default: \
pixel = 0; /* stop gcc complaints */ \
break; \
} \
RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \
pixel &= ~fmt->Amask; \
} while(0)
/* FIXME: this isn't correct, especially for Alpha (maximum != 255) */
#define PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \
{ \
pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \
((g>>fmt->Gloss)<<fmt->Gshift)| \
((b>>fmt->Bloss)<<fmt->Bshift)| \
((a<<fmt->Aloss)<<fmt->Ashift); \
}
#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \
{ \
switch (bpp) { \
case 2: { \
Uint16 pixel; \
\
PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \
*((Uint16 *)(buf)) = pixel; \
} \
break; \
\
case 3: { /* FIXME: broken code (no alpha) */ \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
*((buf)+fmt->Rshift/8) = r; \
*((buf)+fmt->Gshift/8) = g; \
*((buf)+fmt->Bshift/8) = b; \
} else { \
*((buf)+2-fmt->Rshift/8) = r; \
*((buf)+2-fmt->Gshift/8) = g; \
*((buf)+2-fmt->Bshift/8) = b; \
} \
} \
break; \
\
case 4: { \
Uint32 pixel; \
\
PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \
*((Uint32 *)(buf)) = pixel; \
} \
break; \
} \
}
/* Blend the RGB values of two pixels based on a source alpha value */
#define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \
do { \
dR = (((sR-dR)*(A))>>8)+dR; \
dG = (((sG-dG)*(A))>>8)+dG; \
dB = (((sB-dB)*(A))>>8)+dB; \
} while(0)
/* This is a very useful loop for optimizing blitters */
#define USE_DUFFS_LOOP
#ifdef USE_DUFFS_LOOP
/* 8-times unrolled loop */
#define DUFFS_LOOP8(pixel_copy_increment, width) \
{ int n = (width+7)/8; \
switch (width & 7) { \
case 0: do { pixel_copy_increment; \
case 7: pixel_copy_increment; \
case 6: pixel_copy_increment; \
case 5: pixel_copy_increment; \
case 4: pixel_copy_increment; \
case 3: pixel_copy_increment; \
case 2: pixel_copy_increment; \
case 1: pixel_copy_increment; \
} while ( --n > 0 ); \
} \
}
/* 4-times unrolled loop */
#define DUFFS_LOOP4(pixel_copy_increment, width) \
{ int n = (width+3)/4; \
switch (width & 3) { \
case 0: do { pixel_copy_increment; \
case 3: pixel_copy_increment; \
case 2: pixel_copy_increment; \
case 1: pixel_copy_increment; \
} while ( --n > 0 ); \
} \
}
/* Use the 8-times version of the loop by default */
#define DUFFS_LOOP(pixel_copy_increment, width) \
DUFFS_LOOP8(pixel_copy_increment, width)
#else
/* Don't use Duff's device to unroll loops */
#define DUFFS_LOOP(pixel_copy_increment, width) \
{ int n; \
for ( n=width; n > 0; --n ) { \
pixel_copy_increment; \
} \
}
#define DUFFS_LOOP8(pixel_copy_increment, width) \
DUFFS_LOOP(pixel_copy_increment, width)
#define DUFFS_LOOP4(pixel_copy_increment, width) \
DUFFS_LOOP(pixel_copy_increment, width)
#endif /* USE_DUFFS_LOOP */
/* Prevent Visual C++ 6.0 from printing out stupid warnings */
#if defined(_MSC_VER) && (_MSC_VER >= 600)
#pragma warning(disable: 4550)
#endif
#endif /* _SDL_blit_h */

View File

@ -0,0 +1,471 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#include <stdio.h>
#include <string.h>
#include "SDL_types.h"
#include "SDL_video.h"
#include "SDL_blit.h"
/* Functions to blit from bitmaps to other surfaces */
static void BlitBto1(SDL_BlitInfo *info)
{
int c;
int width, height;
Uint8 *src, *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = info->d_pixels;
dstskip = info->d_skip;
map = info->table;
srcskip += width-(width+7)/8;
if ( map ) {
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
*dst = map[bit];
}
dst++;
byte <<= 1;
}
src += srcskip;
dst += dstskip;
}
} else {
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
*dst = bit;
}
dst++;
byte <<= 1;
}
src += srcskip;
dst += dstskip;
}
}
}
static void BlitBto2(SDL_BlitInfo *info)
{
int c;
int width, height;
Uint8 *src;
Uint16 *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = (Uint16 *)info->d_pixels;
dstskip = info->d_skip/2;
map = (Uint16 *)info->table;
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
*dst = map[bit];
}
byte <<= 1;
dst++;
}
src += srcskip;
dst += dstskip;
}
}
static void BlitBto3(SDL_BlitInfo *info)
{
int c, o;
int width, height;
Uint8 *src, *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = info->d_pixels;
dstskip = info->d_skip;
map = info->table;
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
o = bit * 4;
dst[0] = map[o++];
dst[1] = map[o++];
dst[2] = map[o++];
}
byte <<= 1;
dst += 3;
}
src += srcskip;
dst += dstskip;
}
}
static void BlitBto4(SDL_BlitInfo *info)
{
int width, height;
Uint8 *src;
Uint32 *map, *dst;
int srcskip, dstskip;
int c;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = (Uint32 *)info->d_pixels;
dstskip = info->d_skip/4;
map = (Uint32 *)info->table;
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
*dst = map[bit];
}
byte <<= 1;
dst++;
}
src += srcskip;
dst += dstskip;
}
}
static void BlitBto1Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint8 *dst = info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
Uint32 ckey = info->src->colorkey;
Uint8 *palmap = info->table;
int c;
/* Set up some basic variables */
srcskip += width-(width+7)/8;
if ( palmap ) {
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
*dst = palmap[bit];
}
dst++;
byte <<= 1;
}
src += srcskip;
dst += dstskip;
}
} else {
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
*dst = bit;
}
dst++;
byte <<= 1;
}
src += srcskip;
dst += dstskip;
}
}
}
static void BlitBto2Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
Uint32 ckey = info->src->colorkey;
Uint8 *palmap = info->table;
int c;
/* Set up some basic variables */
srcskip += width-(width+7)/8;
dstskip /= 2;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
*dstp=((Uint16 *)palmap)[bit];
}
byte <<= 1;
dstp++;
}
src += srcskip;
dstp += dstskip;
}
}
static void BlitBto3Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint8 *dst = info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
Uint32 ckey = info->src->colorkey;
Uint8 *palmap = info->table;
int c;
/* Set up some basic variables */
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
memcpy(dst, &palmap[bit*4], 3);
}
byte <<= 1;
dst += 3;
}
src += srcskip;
dst += dstskip;
}
}
static void BlitBto4Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint32 *dstp = (Uint32 *)info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
Uint32 ckey = info->src->colorkey;
Uint8 *palmap = info->table;
int c;
/* Set up some basic variables */
srcskip += width-(width+7)/8;
dstskip /= 4;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
*dstp=((Uint32 *)palmap)[bit];
}
byte <<= 1;
dstp++;
}
src += srcskip;
dstp += dstskip;
}
}
static void BlitBtoNAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint8 *dst = info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
const SDL_Color *srcpal = info->src->palette->colors;
SDL_PixelFormat *dstfmt = info->dst;
int dstbpp;
int c;
const int A = info->src->alpha;
/* Set up some basic variables */
dstbpp = dstfmt->BytesPerPixel;
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( 1 ) {
Uint32 pixel;
unsigned sR, sG, sB;
unsigned dR, dG, dB;
sR = srcpal[bit].r;
sG = srcpal[bit].g;
sB = srcpal[bit].b;
DISEMBLE_RGB(dst, dstbpp, dstfmt,
pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
}
byte <<= 1;
dst += dstbpp;
}
src += srcskip;
dst += dstskip;
}
}
static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
Uint8 *dst = info->d_pixels;
int srcskip = info->s_skip;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
const SDL_Color *srcpal = srcfmt->palette->colors;
int dstbpp;
int c;
const int A = srcfmt->alpha;
Uint32 ckey = srcfmt->colorkey;
/* Set up some basic variables */
dstbpp = dstfmt->BytesPerPixel;
srcskip += width-(width+7)/8;
while ( height-- ) {
Uint8 byte = 0, bit;
for ( c=0; c<width; ++c ) {
if ( (c&7) == 0 ) {
byte = *src++;
}
bit = (byte&0x80)>>7;
if ( bit != ckey ) {
int sR, sG, sB;
int dR, dG, dB;
Uint32 pixel;
sR = srcpal[bit].r;
sG = srcpal[bit].g;
sB = srcpal[bit].b;
DISEMBLE_RGB(dst, dstbpp, dstfmt,
pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
}
byte <<= 1;
dst += dstbpp;
}
src += srcskip;
dst += dstskip;
}
}
static SDL_loblit bitmap_blit[] = {
NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4
};
static SDL_loblit colorkey_blit[] = {
NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key
};
SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index)
{
int which;
if ( surface->map->dst->format->BitsPerPixel < 8 ) {
which = 0;
} else {
which = surface->map->dst->format->BytesPerPixel;
}
switch(blit_index) {
case 0: /* copy */
return bitmap_blit[which];
case 1: /* colorkey */
return colorkey_blit[which];
case 2: /* alpha */
return which >= 2 ? BlitBtoNAlpha : NULL;
case 4: /* alpha + colorkey */
return which >= 2 ? BlitBtoNAlphaKey : NULL;
}
return NULL;
}

View File

@ -0,0 +1,526 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#include <stdio.h>
#include "SDL_types.h"
#include "SDL_video.h"
#include "SDL_blit.h"
#include "SDL_sysvideo.h"
#include "SDL_endian.h"
/* Functions to blit from 8-bit surfaces to other surfaces */
static void Blit1to1(SDL_BlitInfo *info)
{
#ifndef USE_DUFFS_LOOP
int c;
#endif
int width, height;
Uint8 *src, *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = info->d_pixels;
dstskip = info->d_skip;
map = info->table;
while ( height-- ) {
#ifdef USE_DUFFS_LOOP
DUFFS_LOOP(
{
*dst = map[*src];
}
dst++;
src++;
, width);
#else
for ( c=width; c; --c ) {
*dst = map[*src];
dst++;
src++;
}
#endif
src += srcskip;
dst += dstskip;
}
}
/* This is now endian dependent */
#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
#define HI 1
#define LO 0
#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
#define HI 0
#define LO 1
#endif
static void Blit1to2(SDL_BlitInfo *info)
{
#ifndef USE_DUFFS_LOOP
int c;
#endif
int width, height;
Uint8 *src, *dst;
Uint16 *map;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = info->d_pixels;
dstskip = info->d_skip;
map = (Uint16 *)info->table;
#ifdef USE_DUFFS_LOOP
while ( height-- ) {
DUFFS_LOOP(
{
*(Uint16 *)dst = map[*src++];
dst += 2;
},
width);
src += srcskip;
dst += dstskip;
}
#else
/* Memory align at 4-byte boundary, if necessary */
if ( (long)dst & 0x03 ) {
/* Don't do anything if width is 0 */
if ( width == 0 ) {
return;
}
--width;
while ( height-- ) {
/* Perform copy alignment */
*(Uint16 *)dst = map[*src++];
dst += 2;
/* Copy in 4 pixel chunks */
for ( c=width/4; c; --c ) {
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
}
/* Get any leftovers */
switch (width & 3) {
case 3:
*(Uint16 *)dst = map[*src++];
dst += 2;
case 2:
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
break;
case 1:
*(Uint16 *)dst = map[*src++];
dst += 2;
break;
}
src += srcskip;
dst += dstskip;
}
} else {
while ( height-- ) {
/* Copy in 4 pixel chunks */
for ( c=width/4; c; --c ) {
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
}
/* Get any leftovers */
switch (width & 3) {
case 3:
*(Uint16 *)dst = map[*src++];
dst += 2;
case 2:
*(Uint32 *)dst =
(map[src[HI]]<<16)|(map[src[LO]]);
src += 2;
dst += 4;
break;
case 1:
*(Uint16 *)dst = map[*src++];
dst += 2;
break;
}
src += srcskip;
dst += dstskip;
}
}
#endif /* USE_DUFFS_LOOP */
}
static void Blit1to3(SDL_BlitInfo *info)
{
#ifndef USE_DUFFS_LOOP
int c;
#endif
int o;
int width, height;
Uint8 *src, *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = info->d_pixels;
dstskip = info->d_skip;
map = info->table;
while ( height-- ) {
#ifdef USE_DUFFS_LOOP
DUFFS_LOOP(
{
o = *src * 4;
dst[0] = map[o++];
dst[1] = map[o++];
dst[2] = map[o++];
}
src++;
dst += 3;
, width);
#else
for ( c=width; c; --c ) {
o = *src * 4;
dst[0] = map[o++];
dst[1] = map[o++];
dst[2] = map[o++];
src++;
dst += 3;
}
#endif /* USE_DUFFS_LOOP */
src += srcskip;
dst += dstskip;
}
}
static void Blit1to4(SDL_BlitInfo *info)
{
#ifndef USE_DUFFS_LOOP
int c;
#endif
int width, height;
Uint8 *src;
Uint32 *map, *dst;
int srcskip, dstskip;
/* Set up some basic variables */
width = info->d_width;
height = info->d_height;
src = info->s_pixels;
srcskip = info->s_skip;
dst = (Uint32 *)info->d_pixels;
dstskip = info->d_skip/4;
map = (Uint32 *)info->table;
while ( height-- ) {
#ifdef USE_DUFFS_LOOP
DUFFS_LOOP(
*dst++ = map[*src++];
, width);
#else
for ( c=width/4; c; --c ) {
*dst++ = map[*src++];
*dst++ = map[*src++];
*dst++ = map[*src++];
*dst++ = map[*src++];
}
switch ( width & 3 ) {
case 3:
*dst++ = map[*src++];
case 2:
*dst++ = map[*src++];
case 1:
*dst++ = map[*src++];
}
#endif /* USE_DUFFS_LOOP */
src += srcskip;
dst += dstskip;
}
}
static void Blit1to1Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
Uint8 *palmap = info->table;
Uint32 ckey = info->src->colorkey;
if ( palmap ) {
while ( height-- ) {
DUFFS_LOOP(
{
if ( *src != ckey ) {
*dst = palmap[*src];
}
dst++;
src++;
},
width);
src += srcskip;
dst += dstskip;
}
} else {
while ( height-- ) {
DUFFS_LOOP(
{
if ( *src != ckey ) {
*dst = *src;
}
dst++;
src++;
},
width);
src += srcskip;
dst += dstskip;
}
}
}
static void Blit1to2Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip;
Uint16 *palmap = (Uint16 *)info->table;
Uint32 ckey = info->src->colorkey;
/* Set up some basic variables */
dstskip /= 2;
while ( height-- ) {
DUFFS_LOOP(
{
if ( *src != ckey ) {
*dstp=palmap[*src];
}
src++;
dstp++;
},
width);
src += srcskip;
dstp += dstskip;
}
}
static void Blit1to3Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
Uint8 *palmap = info->table;
Uint32 ckey = info->src->colorkey;
int o;
while ( height-- ) {
DUFFS_LOOP(
{
if ( *src != ckey ) {
o = *src * 4;
dst[0] = palmap[o++];
dst[1] = palmap[o++];
dst[2] = palmap[o++];
}
src++;
dst += 3;
},
width);
src += srcskip;
dst += dstskip;
}
}
static void Blit1to4Key(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint32 *dstp = (Uint32 *)info->d_pixels;
int dstskip = info->d_skip;
Uint32 *palmap = (Uint32 *)info->table;
Uint32 ckey = info->src->colorkey;
/* Set up some basic variables */
dstskip /= 4;
while ( height-- ) {
DUFFS_LOOP(
{
if ( *src != ckey ) {
*dstp = palmap[*src];
}
src++;
dstp++;
},
width);
src += srcskip;
dstp += dstskip;
}
}
static void Blit1toNAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *dstfmt = info->dst;
const SDL_Color *srcpal = info->src->palette->colors;
int dstbpp;
const int A = info->src->alpha;
/* Set up some basic variables */
dstbpp = dstfmt->BytesPerPixel;
while ( height-- ) {
int sR, sG, sB;
int dR, dG, dB;
DUFFS_LOOP4(
{
Uint32 pixel;
sR = srcpal[*src].r;
sG = srcpal[*src].g;
sB = srcpal[*src].b;
DISEMBLE_RGB(dst, dstbpp, dstfmt,
pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
src++;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
static void Blit1toNAlphaKey(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
const SDL_Color *srcpal = info->src->palette->colors;
Uint32 ckey = srcfmt->colorkey;
int dstbpp;
const int A = srcfmt->alpha;
/* Set up some basic variables */
dstbpp = dstfmt->BytesPerPixel;
while ( height-- ) {
int sR, sG, sB;
int dR, dG, dB;
DUFFS_LOOP(
{
if ( *src != ckey ) {
Uint32 pixel;
sR = srcpal[*src].r;
sG = srcpal[*src].g;
sB = srcpal[*src].b;
DISEMBLE_RGB(dst, dstbpp, dstfmt,
pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
}
src++;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
static SDL_loblit one_blit[] = {
NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
};
static SDL_loblit one_blitkey[] = {
NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
};
SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index)
{
int which;
SDL_PixelFormat *dstfmt;
dstfmt = surface->map->dst->format;
if ( dstfmt->BitsPerPixel < 8 ) {
which = 0;
} else {
which = dstfmt->BytesPerPixel;
}
switch(blit_index) {
case 0: /* copy */
return one_blit[which];
case 1: /* colorkey */
return one_blitkey[which];
case 2: /* alpha */
/* Supporting 8bpp->8bpp alpha is doable but requires lots of
tables which consume space and takes time to precompute,
so is better left to the user */
return which >= 2 ? Blit1toNAlpha : NULL;
case 3: /* alpha + colorkey */
return which >= 2 ? Blit1toNAlphaKey : NULL;
}
return NULL;
}

View File

@ -0,0 +1,772 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#include <stdio.h>
#include "SDL_types.h"
#include "SDL_video.h"
#include "SDL_blit.h"
/* Functions to perform alpha blended blitting */
/* N->1 blending with per-surface alpha */
static void BlitNto1SurfaceAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
Uint8 *palmap = info->table;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp = srcfmt->BytesPerPixel;
const unsigned A = srcfmt->alpha;
while ( height-- ) {
DUFFS_LOOP4(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
dR = dstfmt->palette->colors[*dst].r;
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
dR &= 0xff;
dG &= 0xff;
dB &= 0xff;
/* Pack RGB into 8bit pixel */
if ( palmap == NULL ) {
*dst =((dR>>5)<<(3+2))|
((dG>>5)<<(2))|
((dB>>6)<<(0));
} else {
*dst = palmap[((dR>>5)<<(3+2))|
((dG>>5)<<(2)) |
((dB>>6)<<(0))];
}
dst++;
src += srcbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
/* N->1 blending with pixel alpha */
static void BlitNto1PixelAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
Uint8 *palmap = info->table;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp = srcfmt->BytesPerPixel;
/* FIXME: fix alpha bit field expansion here too? */
while ( height-- ) {
DUFFS_LOOP4(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned sA;
unsigned dR;
unsigned dG;
unsigned dB;
DISEMBLE_RGBA(src,srcbpp,srcfmt,pixel,sR,sG,sB,sA);
dR = dstfmt->palette->colors[*dst].r;
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
dR &= 0xff;
dG &= 0xff;
dB &= 0xff;
/* Pack RGB into 8bit pixel */
if ( palmap == NULL ) {
*dst =((dR>>5)<<(3+2))|
((dG>>5)<<(2))|
((dB>>6)<<(0));
} else {
*dst = palmap[((dR>>5)<<(3+2))|
((dG>>5)<<(2)) |
((dB>>6)<<(0)) ];
}
dst++;
src += srcbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
/* colorkeyed N->1 blending with per-surface alpha */
static void BlitNto1SurfaceAlphaKey(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
Uint8 *palmap = info->table;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp = srcfmt->BytesPerPixel;
Uint32 ckey = srcfmt->colorkey;
const int A = srcfmt->alpha;
while ( height-- ) {
DUFFS_LOOP(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
if ( pixel != ckey ) {
dR = dstfmt->palette->colors[*dst].r;
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
dR &= 0xff;
dG &= 0xff;
dB &= 0xff;
/* Pack RGB into 8bit pixel */
if ( palmap == NULL ) {
*dst =((dR>>5)<<(3+2))|
((dG>>5)<<(2)) |
((dB>>6)<<(0));
} else {
*dst = palmap[((dR>>5)<<(3+2))|
((dG>>5)<<(2)) |
((dB>>6)<<(0)) ];
}
}
dst++;
src += srcbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */
static void BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint32 *srcp = (Uint32 *)info->s_pixels;
int srcskip = info->s_skip >> 2;
Uint32 *dstp = (Uint32 *)info->d_pixels;
int dstskip = info->d_skip >> 2;
while(height--) {
DUFFS_LOOP4({
Uint32 s = *srcp++;
Uint32 d = *dstp;
*dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)
+ (s & d & 0x00010101)) | 0xff000000;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
/* fast RGB888->(A)RGB888 blending with surface alpha */
static void BlitRGBtoRGBSurfaceAlpha(SDL_BlitInfo *info)
{
unsigned alpha = info->src->alpha;
if(alpha == 128) {
BlitRGBtoRGBSurfaceAlpha128(info);
} else {
int width = info->d_width;
int height = info->d_height;
Uint32 *srcp = (Uint32 *)info->s_pixels;
int srcskip = info->s_skip >> 2;
Uint32 *dstp = (Uint32 *)info->d_pixels;
int dstskip = info->d_skip >> 2;
while(height--) {
DUFFS_LOOP4({
Uint32 s;
Uint32 d;
Uint32 s1;
Uint32 d1;
s = *srcp;
d = *dstp;
s1 = s & 0xff00ff;
d1 = d & 0xff00ff;
d1 = (d1 + ((s1 - d1) * alpha >> 8))
& 0xff00ff;
s &= 0xff00;
d &= 0xff00;
d = (d + ((s - d) * alpha >> 8)) & 0xff00;
*dstp = d1 | d | 0xff000000;
++srcp;
++dstp;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
}
/* fast ARGB888->(A)RGB888 blending with pixel alpha */
static void BlitRGBtoRGBPixelAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint32 *srcp = (Uint32 *)info->s_pixels;
int srcskip = info->s_skip >> 2;
Uint32 *dstp = (Uint32 *)info->d_pixels;
int dstskip = info->d_skip >> 2;
while(height--) {
DUFFS_LOOP4({
Uint32 dalpha;
Uint32 d;
Uint32 s1;
Uint32 d1;
Uint32 s = *srcp;
Uint32 alpha = s >> 24;
/* FIXME: Here we special-case opaque alpha since the
compositioning used (>>8 instead of /255) doesn't handle
it correctly. Also special-case alpha=0 for speed?
Benchmark this! */
if(alpha == SDL_ALPHA_OPAQUE) {
*dstp = (s & 0x00ffffff) | (*dstp & 0xff000000);
} else {
/*
* take out the middle component (green), and process
* the other two in parallel. One multiply less.
*/
d = *dstp;
dalpha = d & 0xff000000;
s1 = s & 0xff00ff;
d1 = d & 0xff00ff;
d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;
s &= 0xff00;
d &= 0xff00;
d = (d + ((s - d) * alpha >> 8)) & 0xff00;
*dstp = d1 | d | dalpha;
}
++srcp;
++dstp;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
/* 16bpp special case for per-surface alpha=50%: blend 2 pixels in parallel */
/* blend a single 16 bit pixel at 50% */
#define BLEND16_50(d, s, mask) \
((((s & mask) + (d & mask)) >> 1) + (s & d & (~mask & 0xffff)))
/* blend two 16 bit pixels at 50% */
#define BLEND2x16_50(d, s, mask) \
(((s & (mask | mask << 16)) >> 1) + ((d & (mask | mask << 16)) >> 1) \
+ (s & d & (~(mask | mask << 16))))
static void Blit16to16SurfaceAlpha128(SDL_BlitInfo *info, Uint16 mask)
{
int width = info->d_width;
int height = info->d_height;
Uint16 *srcp = (Uint16 *)info->s_pixels;
int srcskip = info->s_skip >> 1;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip >> 1;
while(height--) {
if(((unsigned long)srcp ^ (unsigned long)dstp) & 2) {
/*
* Source and destination not aligned, pipeline it.
* This is mostly a win for big blits but no loss for
* small ones
*/
Uint32 prev_sw;
int w = width;
/* handle odd destination */
if((unsigned long)dstp & 2) {
Uint16 d = *dstp, s = *srcp;
*dstp = BLEND16_50(d, s, mask);
dstp++;
srcp++;
w--;
}
srcp++; /* srcp is now 32-bit aligned */
/* bootstrap pipeline with first halfword */
prev_sw = ((Uint32 *)srcp)[-1];
while(w > 1) {
Uint32 sw, dw, s;
sw = *(Uint32 *)srcp;
dw = *(Uint32 *)dstp;
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
s = (prev_sw << 16) + (sw >> 16);
else
s = (prev_sw >> 16) + (sw << 16);
prev_sw = sw;
*(Uint32 *)dstp = BLEND2x16_50(dw, s, mask);
dstp += 2;
srcp += 2;
w -= 2;
}
/* final pixel if any */
if(w) {
Uint16 d = *dstp, s;
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
s = prev_sw;
else
s = prev_sw >> 16;
*dstp = BLEND16_50(d, s, mask);
srcp++;
dstp++;
}
srcp += srcskip - 1;
dstp += dstskip;
} else {
/* source and destination are aligned */
int w = width;
/* first odd pixel? */
if((unsigned long)srcp & 2) {
Uint16 d = *dstp, s = *srcp;
*dstp = BLEND16_50(d, s, mask);
srcp++;
dstp++;
w--;
}
/* srcp and dstp are now 32-bit aligned */
while(w > 1) {
Uint32 sw = *(Uint32 *)srcp;
Uint32 dw = *(Uint32 *)dstp;
*(Uint32 *)dstp = BLEND2x16_50(dw, sw, mask);
srcp += 2;
dstp += 2;
w -= 2;
}
/* last odd pixel? */
if(w) {
Uint16 d = *dstp, s = *srcp;
*dstp = BLEND16_50(d, s, mask);
srcp++;
dstp++;
}
srcp += srcskip;
dstp += dstskip;
}
}
}
/* fast RGB565->RGB565 blending with surface alpha */
static void Blit565to565SurfaceAlpha(SDL_BlitInfo *info)
{
unsigned alpha = info->src->alpha;
if(alpha == 128) {
Blit16to16SurfaceAlpha128(info, 0xf7de);
} else {
int width = info->d_width;
int height = info->d_height;
Uint16 *srcp = (Uint16 *)info->s_pixels;
int srcskip = info->s_skip >> 1;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip >> 1;
alpha >>= 3; /* downscale alpha to 5 bits */
while(height--) {
DUFFS_LOOP4({
Uint32 s = *srcp++;
Uint32 d = *dstp;
/*
* shift out the middle component (green) to
* the high 16 bits, and process all three RGB
* components at the same time.
*/
s = (s | s << 16) & 0x07e0f81f;
d = (d | d << 16) & 0x07e0f81f;
d += (s - d) * alpha >> 5;
d &= 0x07e0f81f;
*dstp++ = d | d >> 16;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
}
/* fast RGB555->RGB555 blending with surface alpha */
static void Blit555to555SurfaceAlpha(SDL_BlitInfo *info)
{
unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */
if(alpha == 128) {
Blit16to16SurfaceAlpha128(info, 0xfbde);
} else {
int width = info->d_width;
int height = info->d_height;
Uint16 *srcp = (Uint16 *)info->s_pixels;
int srcskip = info->s_skip >> 1;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip >> 1;
alpha >>= 3; /* downscale alpha to 5 bits */
while(height--) {
DUFFS_LOOP4({
Uint32 s = *srcp++;
Uint32 d = *dstp;
/*
* shift out the middle component (green) to
* the high 16 bits, and process all three RGB
* components at the same time.
*/
s = (s | s << 16) & 0x03e07c1f;
d = (d | d << 16) & 0x03e07c1f;
d += (s - d) * alpha >> 5;
d &= 0x03e07c1f;
*dstp++ = d | d >> 16;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
}
/* fast ARGB8888->RGB565 blending with pixel alpha */
static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint32 *srcp = (Uint32 *)info->s_pixels;
int srcskip = info->s_skip >> 2;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip >> 1;
while(height--) {
DUFFS_LOOP4({
Uint32 s = *srcp;
unsigned alpha = s >> 27; /* downscale alpha to 5 bits */
/* FIXME: Here we special-case opaque alpha since the
compositioning used (>>8 instead of /255) doesn't handle
it correctly. Also special-case alpha=0 for speed?
Benchmark this! */
if(alpha == (SDL_ALPHA_OPAQUE >> 3)) {
*dstp = (s >> 8 & 0xf800) + (s >> 5 & 0x7e0)
+ (s >> 3 & 0x1f);
} else {
Uint32 d = *dstp;
/*
* convert source and destination to G0RAB65565
* and blend all components at the same time
*/
s = ((s & 0xfc00) << 11) + (s >> 8 & 0xf800)
+ (s >> 3 & 0x1f);
d = (d | d << 16) & 0x07e0f81f;
d += (s - d) * alpha >> 5;
d &= 0x07e0f81f;
*dstp = d | d >> 16;
}
srcp++;
dstp++;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
/* fast ARGB8888->RGB555 blending with pixel alpha */
static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint32 *srcp = (Uint32 *)info->s_pixels;
int srcskip = info->s_skip >> 2;
Uint16 *dstp = (Uint16 *)info->d_pixels;
int dstskip = info->d_skip >> 1;
while(height--) {
DUFFS_LOOP4({
unsigned alpha;
Uint32 s = *srcp;
alpha = s >> 27; /* downscale alpha to 5 bits */
/* FIXME: Here we special-case opaque alpha since the
compositioning used (>>8 instead of /255) doesn't handle
it correctly. Also special-case alpha=0 for speed?
Benchmark this! */
if(alpha == (SDL_ALPHA_OPAQUE >> 3)) {
*dstp = (s >> 9 & 0x7c00) + (s >> 6 & 0x3e0)
+ (s >> 3 & 0x1f);
} else {
Uint32 d = *dstp;
/*
* convert source and destination to G0RAB65565
* and blend all components at the same time
*/
s = ((s & 0xf800) << 10) + (s >> 9 & 0x7c00)
+ (s >> 3 & 0x1f);
d = (d | d << 16) & 0x03e07c1f;
d += (s - d) * alpha >> 5;
d &= 0x03e07c1f;
*dstp = d | d >> 16;
}
srcp++;
dstp++;
}, width);
srcp += srcskip;
dstp += dstskip;
}
}
/* General (slow) N->N blending with per-surface alpha */
static void BlitNtoNSurfaceAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp = srcfmt->BytesPerPixel;
int dstbpp = dstfmt->BytesPerPixel;
unsigned sA = srcfmt->alpha;
unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0;
while ( height-- ) {
DUFFS_LOOP4(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
DISEMBLE_RGB(dst, dstbpp, dstfmt, pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
src += srcbpp;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
/* General (slow) colorkeyed N->N blending with per-surface alpha */
static void BlitNtoNSurfaceAlphaKey(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
Uint32 ckey = srcfmt->colorkey;
int srcbpp = srcfmt->BytesPerPixel;
int dstbpp = dstfmt->BytesPerPixel;
unsigned sA = srcfmt->alpha;
unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0;
while ( height-- ) {
DUFFS_LOOP4(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
RETRIEVE_RGB_PIXEL(src, srcbpp, pixel);
if(pixel != ckey) {
RGB_FROM_PIXEL(pixel, srcfmt, sR, sG, sB);
DISEMBLE_RGB(dst, dstbpp, dstfmt, pixel, dR, dG, dB);
ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
}
src += srcbpp;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
/* General (slow) N->N blending with pixel alpha */
static void BlitNtoNPixelAlpha(SDL_BlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp;
int dstbpp;
/* Set up some basic variables */
srcbpp = srcfmt->BytesPerPixel;
dstbpp = dstfmt->BytesPerPixel;
/* FIXME: for 8bpp source alpha, this doesn't get opaque values
quite right. for <8bpp source alpha, it gets them very wrong
(check all macros!)
It is unclear whether there is a good general solution that doesn't
need a branch (or a divide). */
while ( height-- ) {
DUFFS_LOOP4(
{
Uint32 pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
unsigned sA;
unsigned dA;
DISEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA);
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
src += srcbpp;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index)
{
SDL_PixelFormat *sf = surface->format;
SDL_PixelFormat *df = surface->map->dst->format;
if(sf->Amask == 0) {
if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
if(df->BytesPerPixel == 1)
return BlitNto1SurfaceAlphaKey;
else
return BlitNtoNSurfaceAlphaKey;
} else {
/* Per-surface alpha blits */
switch(df->BytesPerPixel) {
case 1:
return BlitNto1SurfaceAlpha;
case 2:
if(surface->map->identity) {
if(df->Gmask == 0x7e0)
return Blit565to565SurfaceAlpha;
else if(df->Gmask == 0x3e0)
return Blit555to555SurfaceAlpha;
}
return BlitNtoNSurfaceAlpha;
case 4:
if(sf->Rmask == df->Rmask
&& sf->Gmask == df->Gmask
&& sf->Bmask == df->Bmask
&& (sf->Rmask | sf->Gmask | sf->Bmask) == 0xffffff
&& sf->BytesPerPixel == 4)
return BlitRGBtoRGBSurfaceAlpha;
else
return BlitNtoNSurfaceAlpha;
case 3:
default:
return BlitNtoNSurfaceAlpha;
}
}
} else {
/* Per-pixel alpha blits */
switch(df->BytesPerPixel) {
case 1:
return BlitNto1PixelAlpha;
case 2:
if(sf->BytesPerPixel == 4 && sf->Amask == 0xff000000
&& sf->Gmask == 0xff00
&& ((sf->Rmask == 0xff && df->Rmask == 0x1f)
|| (sf->Bmask == 0xff && df->Bmask == 0x1f))) {
if(df->Gmask == 0x7e0)
return BlitARGBto565PixelAlpha;
else if(df->Gmask == 0x3e0)
return BlitARGBto555PixelAlpha;
}
return BlitNtoNPixelAlpha;
case 4:
if(sf->Amask == 0xff000000
&& sf->Rmask == df->Rmask
&& sf->Gmask == df->Gmask
&& sf->Bmask == df->Bmask
&& sf->BytesPerPixel == 4)
return BlitRGBtoRGBPixelAlpha;
return BlitNtoNPixelAlpha;
case 3:
default:
return BlitNtoNPixelAlpha;
}
}
}

View File

@ -0,0 +1,30 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_blit_A.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Functions from SDL_blitalpha.c */
extern void SDL_BlitAlpha(SDL_BlitInfo *info);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,523 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifndef DISABLE_FILE
/*
Code to load and save surfaces in Windows BMP format.
Why support BMP format? Well, it's a native format for Windows, and
most image processing programs can read and write it. It would be nice
to be able to have at least one image format that we can natively load
and save, and since PNG is so complex that it would bloat the library,
BMP is a good alternative.
This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp.
*/
#include <string.h>
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_endian.h"
/* Compression encodings for BMP files */
#ifndef BI_RGB
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#endif
SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc)
{
int was_error;
long fp_offset;
int bmpPitch;
int i, pad;
SDL_Surface *surface;
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
SDL_Palette *palette;
Uint8 *bits;
int ExpandBMP;
/* The Win32 BMP file header (14 bytes) */
char magic[2];
Uint32 bfSize;
Uint16 bfReserved1;
Uint16 bfReserved2;
Uint32 bfOffBits;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
Uint32 biSize;
Sint32 biWidth;
Sint32 biHeight;
Uint16 biPlanes;
Uint16 biBitCount;
Uint32 biCompression;
Uint32 biSizeImage;
Sint32 biXPelsPerMeter;
Sint32 biYPelsPerMeter;
Uint32 biClrUsed;
Uint32 biClrImportant;
/* Make sure we are passed a valid data source */
surface = NULL;
was_error = 0;
if ( src == NULL ) {
was_error = 1;
goto done;
}
/* Read in the BMP file header */
fp_offset = SDL_RWtell(src);
SDL_ClearError();
if ( SDL_RWread(src, magic, 1, 2) != 2 ) {
SDL_Error(SDL_EFREAD);
was_error = 1;
goto done;
}
if ( strncmp(magic, "BM", 2) != 0 ) {
SDL_SetError("File is not a Windows BMP file");
was_error = 1;
goto done;
}
bfSize = SDL_ReadLE32(src);
bfReserved1 = SDL_ReadLE16(src);
bfReserved2 = SDL_ReadLE16(src);
bfOffBits = SDL_ReadLE32(src);
/* Read the Win32 BITMAPINFOHEADER */
biSize = SDL_ReadLE32(src);
if ( biSize == 12 ) {
biWidth = (Uint32)SDL_ReadLE16(src);
biHeight = (Uint32)SDL_ReadLE16(src);
biPlanes = SDL_ReadLE16(src);
biBitCount = SDL_ReadLE16(src);
biCompression = BI_RGB;
biSizeImage = 0;
biXPelsPerMeter = 0;
biYPelsPerMeter = 0;
biClrUsed = 0;
biClrImportant = 0;
} else {
biWidth = SDL_ReadLE32(src);
biHeight = SDL_ReadLE32(src);
biPlanes = SDL_ReadLE16(src);
biBitCount = SDL_ReadLE16(src);
biCompression = SDL_ReadLE32(src);
biSizeImage = SDL_ReadLE32(src);
biXPelsPerMeter = SDL_ReadLE32(src);
biYPelsPerMeter = SDL_ReadLE32(src);
biClrUsed = SDL_ReadLE32(src);
biClrImportant = SDL_ReadLE32(src);
}
/* Check for read error */
if ( strcmp(SDL_GetError(), "") != 0 ) {
was_error = 1;
goto done;
}
/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
switch (biBitCount) {
case 1:
case 4:
ExpandBMP = biBitCount;
biBitCount = 8;
break;
default:
ExpandBMP = 0;
break;
}
/* We don't support any BMP compression right now */
Rmask = Gmask = Bmask = 0;
switch (biCompression) {
case BI_RGB:
/* If there are no masks, use the defaults */
if ( bfOffBits == (14+biSize) ) {
/* Default values for the BMP format */
switch (biBitCount) {
case 15:
case 16:
Rmask = 0x7C00;
Gmask = 0x03E0;
Bmask = 0x001F;
break;
case 24:
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Rmask = 0x000000FF;
Gmask = 0x0000FF00;
Bmask = 0x00FF0000;
break;
#endif
case 32:
Rmask = 0x00FF0000;
Gmask = 0x0000FF00;
Bmask = 0x000000FF;
break;
default:
break;
}
break;
}
/* Fall through -- read the RGB masks */
case BI_BITFIELDS:
switch (biBitCount) {
case 15:
case 16:
case 32:
Rmask = SDL_ReadLE32(src);
Gmask = SDL_ReadLE32(src);
Bmask = SDL_ReadLE32(src);
break;
default:
break;
}
break;
default:
SDL_SetError("Compressed BMP files not supported");
was_error = 1;
goto done;
}
/* Create a compatible surface, note that the colors are RGB ordered */
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0);
if ( surface == NULL ) {
was_error = 1;
goto done;
}
/* Load the palette, if any */
palette = (surface->format)->palette;
if ( palette ) {
if ( biClrUsed == 0 ) {
biClrUsed = 1 << biBitCount;
}
if ( biSize == 12 ) {
for ( i = 0; i < (int)biClrUsed; ++i ) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);
SDL_RWread(src, &palette->colors[i].r, 1, 1);
palette->colors[i].unused = 0;
}
} else {
for ( i = 0; i < (int)biClrUsed; ++i ) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);
SDL_RWread(src, &palette->colors[i].r, 1, 1);
SDL_RWread(src, &palette->colors[i].unused, 1, 1);
}
}
palette->ncolors = biClrUsed;
}
/* Read the surface pixels. Note that the bmp image is upside down */
if ( SDL_RWseek(src, fp_offset+bfOffBits, SEEK_SET) < 0 ) {
SDL_Error(SDL_EFSEEK);
was_error = 1;
goto done;
}
bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
switch (ExpandBMP) {
case 1:
bmpPitch = (biWidth + 7) >> 3;
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
break;
case 4:
bmpPitch = (biWidth + 1) >> 1;
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
break;
default:
pad = ((surface->pitch%4) ?
(4-(surface->pitch%4)) : 0);
break;
}
while ( bits > (Uint8 *)surface->pixels ) {
bits -= surface->pitch;
switch (ExpandBMP) {
case 1:
case 4: {
Uint8 pixel = 0;
int shift = (8-ExpandBMP);
for ( i=0; i<surface->w; ++i ) {
if ( i%(8/ExpandBMP) == 0 ) {
if ( !SDL_RWread(src, &pixel, 1, 1) ) {
SDL_SetError(
"Error reading from BMP");
was_error = 1;
goto done;
}
}
*(bits+i) = (pixel>>shift);
pixel <<= ExpandBMP;
} }
break;
default:
if ( SDL_RWread(src, bits, 1, surface->pitch)
!= surface->pitch ) {
SDL_Error(SDL_EFREAD);
was_error = 1;
goto done;
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
/* Byte-swap the pixels if needed. Note that the 24bpp
case has already been taken care of above. */
switch(biBitCount) {
case 15:
case 16: {
Uint16 *pix = (Uint16 *)bits;
for(i = 0; i < surface->w; i++)
pix[i] = SDL_Swap16(pix[i]);
break;
}
case 32: {
Uint32 *pix = (Uint32 *)bits;
for(i = 0; i < surface->w; i++)
pix[i] = SDL_Swap32(pix[i]);
break;
}
}
#endif
break;
}
/* Skip padding bytes, ugh */
if ( pad ) {
Uint8 padbyte;
for ( i=0; i<pad; ++i ) {
SDL_RWread(src, &padbyte, 1, 1);
}
}
}
done:
if ( was_error ) {
if ( surface ) {
SDL_FreeSurface(surface);
}
surface = NULL;
}
if ( freesrc && src ) {
SDL_RWclose(src);
}
return(surface);
}
int SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst)
{
long fp_offset;
int i, pad;
SDL_Surface *surface;
Uint8 *bits;
/* The Win32 BMP file header (14 bytes) */
char magic[2] = { 'B', 'M' };
Uint32 bfSize;
Uint16 bfReserved1;
Uint16 bfReserved2;
Uint32 bfOffBits;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
Uint32 biSize;
Sint32 biWidth;
Sint32 biHeight;
Uint16 biPlanes;
Uint16 biBitCount;
Uint32 biCompression;
Uint32 biSizeImage;
Sint32 biXPelsPerMeter;
Sint32 biYPelsPerMeter;
Uint32 biClrUsed;
Uint32 biClrImportant;
/* Make sure we have somewhere to save */
surface = NULL;
if ( dst ) {
if ( saveme->format->palette ) {
if ( saveme->format->BitsPerPixel == 8 ) {
surface = saveme;
} else {
SDL_SetError("%d bpp BMP files not supported",
saveme->format->BitsPerPixel);
}
}
else if ( (saveme->format->BitsPerPixel == 24) &&
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
(saveme->format->Rmask == 0x00FF0000) &&
(saveme->format->Gmask == 0x0000FF00) &&
(saveme->format->Bmask == 0x000000FF)
#else
(saveme->format->Rmask == 0x000000FF) &&
(saveme->format->Gmask == 0x0000FF00) &&
(saveme->format->Bmask == 0x00FF0000)
#endif
) {
surface = saveme;
} else {
SDL_Rect bounds;
/* Convert to 24 bits per pixel */
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
saveme->w, saveme->h, 24,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
0x00FF0000, 0x0000FF00, 0x000000FF,
#else
0x000000FF, 0x0000FF00, 0x00FF0000,
#endif
0);
if ( surface != NULL ) {
bounds.x = 0;
bounds.y = 0;
bounds.w = saveme->w;
bounds.h = saveme->h;
if ( SDL_LowerBlit(saveme, &bounds, surface,
&bounds) < 0 ) {
SDL_FreeSurface(surface);
SDL_SetError(
"Couldn't convert image to 24 bpp");
surface = NULL;
}
}
}
}
if ( surface && (SDL_LockSurface(surface) == 0) ) {
/* Set the BMP file header values */
bfSize = 0; /* We'll write this when we're done */
bfReserved1 = 0;
bfReserved2 = 0;
bfOffBits = 0; /* We'll write this when we're done */
/* Write the BMP file header values */
fp_offset = SDL_RWtell(dst);
SDL_ClearError();
SDL_RWwrite(dst, magic, 2, 1);
SDL_WriteLE32(dst, bfSize);
SDL_WriteLE16(dst, bfReserved1);
SDL_WriteLE16(dst, bfReserved2);
SDL_WriteLE32(dst, bfOffBits);
/* Set the BMP info values */
biSize = 40;
biWidth = surface->w;
biHeight = surface->h;
biPlanes = 1;
biBitCount = surface->format->BitsPerPixel;
biCompression = BI_RGB;
biSizeImage = surface->h*surface->pitch;
biXPelsPerMeter = 0;
biYPelsPerMeter = 0;
if ( surface->format->palette ) {
biClrUsed = surface->format->palette->ncolors;
} else {
biClrUsed = 0;
}
biClrImportant = 0;
/* Write the BMP info values */
SDL_WriteLE32(dst, biSize);
SDL_WriteLE32(dst, biWidth);
SDL_WriteLE32(dst, biHeight);
SDL_WriteLE16(dst, biPlanes);
SDL_WriteLE16(dst, biBitCount);
SDL_WriteLE32(dst, biCompression);
SDL_WriteLE32(dst, biSizeImage);
SDL_WriteLE32(dst, biXPelsPerMeter);
SDL_WriteLE32(dst, biYPelsPerMeter);
SDL_WriteLE32(dst, biClrUsed);
SDL_WriteLE32(dst, biClrImportant);
/* Write the palette (in BGR color order) */
if ( surface->format->palette ) {
SDL_Color *colors;
int ncolors;
colors = surface->format->palette->colors;
ncolors = surface->format->palette->ncolors;
for ( i=0; i<ncolors; ++i ) {
SDL_RWwrite(dst, &colors[i].b, 1, 1);
SDL_RWwrite(dst, &colors[i].g, 1, 1);
SDL_RWwrite(dst, &colors[i].r, 1, 1);
SDL_RWwrite(dst, &colors[i].unused, 1, 1);
}
}
/* Write the bitmap offset */
bfOffBits = SDL_RWtell(dst)-fp_offset;
if ( SDL_RWseek(dst, fp_offset+10, SEEK_SET) < 0 ) {
SDL_Error(SDL_EFSEEK);
}
SDL_WriteLE32(dst, bfOffBits);
if ( SDL_RWseek(dst, fp_offset+bfOffBits, SEEK_SET) < 0 ) {
SDL_Error(SDL_EFSEEK);
}
/* Write the bitmap image upside down */
bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
pad = ((surface->pitch%4) ? (4-(surface->pitch%4)) : 0);
while ( bits > (Uint8 *)surface->pixels ) {
bits -= surface->pitch;
if ( SDL_RWwrite(dst, bits, 1, surface->pitch)
!= surface->pitch) {
SDL_Error(SDL_EFWRITE);
break;
}
if ( pad ) {
const Uint8 padbyte = 0;
for ( i=0; i<pad; ++i ) {
SDL_RWwrite(dst, &padbyte, 1, 1);
}
}
}
/* Write the BMP file size */
bfSize = SDL_RWtell(dst)-fp_offset;
if ( SDL_RWseek(dst, fp_offset+2, SEEK_SET) < 0 ) {
SDL_Error(SDL_EFSEEK);
}
SDL_WriteLE32(dst, bfSize);
if ( SDL_RWseek(dst, fp_offset+bfSize, SEEK_SET) < 0 ) {
SDL_Error(SDL_EFSEEK);
}
/* Close it up.. */
SDL_UnlockSurface(surface);
if ( surface != saveme ) {
SDL_FreeSurface(surface);
}
}
if ( freedst && dst ) {
SDL_RWclose(dst);
}
return((strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
}
#endif /* ENABLE_FILE */

View File

@ -0,0 +1,742 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General cursor handling code for SDL */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_mutex.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "SDL_blit.h"
#include "SDL_events_c.h"
#include "SDL_sysvideo.h"
#include "SDL_sysevents.h"
#include "SDL_cursor_c.h"
#include "SDL_pixels_c.h"
#include "default_cursor.h"
/* These are static for our cursor handling code */
volatile int SDL_cursorstate = 0;
SDL_Cursor *SDL_cursor = NULL;
static SDL_Cursor *SDL_defcursor = NULL;
SDL_mutex *SDL_cursorlock = NULL;
/* Public functions */
void SDL_CursorQuit(void)
{
if ( SDL_cursor != NULL ) {
SDL_Cursor *cursor;
SDL_cursorstate &= ~CURSOR_VISIBLE;
if ( SDL_cursor != SDL_defcursor ) {
SDL_FreeCursor(SDL_cursor);
}
SDL_cursor = NULL;
if ( SDL_defcursor != NULL ) {
cursor = SDL_defcursor;
SDL_defcursor = NULL;
SDL_FreeCursor(cursor);
}
}
if ( SDL_cursorlock != NULL ) {
SDL_DestroyMutex(SDL_cursorlock);
SDL_cursorlock = NULL;
}
}
int SDL_CursorInit(Uint32 multithreaded)
{
/* We don't have mouse focus, and the cursor isn't drawn yet */
SDL_cursorstate = CURSOR_VISIBLE;
/* Create the default cursor */
if ( SDL_defcursor == NULL ) {
SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask,
DEFAULT_CWIDTH, DEFAULT_CHEIGHT,
DEFAULT_CHOTX, DEFAULT_CHOTY);
SDL_SetCursor(SDL_defcursor);
}
/* Create a lock if necessary */
if ( multithreaded ) {
SDL_cursorlock = SDL_CreateMutex();
}
/* That's it! */
return(0);
}
/* Multi-thread support for cursors */
#ifndef SDL_LockCursor
void SDL_LockCursor(void)
{
if ( SDL_cursorlock ) {
SDL_mutexP(SDL_cursorlock);
}
}
#endif
#ifndef SDL_UnlockCursor
void SDL_UnlockCursor(void)
{
if ( SDL_cursorlock ) {
SDL_mutexV(SDL_cursorlock);
}
}
#endif
/* Software cursor drawing support */
SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask,
int w, int h, int hot_x, int hot_y)
{
SDL_VideoDevice *video = current_video;
int savelen;
int i;
SDL_Cursor *cursor;
/* Make sure the width is a multiple of 8 */
w = ((w+7)&~7);
/* Sanity check the hot spot */
if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) {
SDL_SetError("Cursor hot spot doesn't lie within cursor");
return(NULL);
}
/* Allocate memory for the cursor */
cursor = (SDL_Cursor *)malloc(sizeof *cursor);
if ( cursor == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
savelen = (w*4)*h;
cursor->area.x = 0;
cursor->area.y = 0;
cursor->area.w = w;
cursor->area.h = h;
cursor->hot_x = hot_x;
cursor->hot_y = hot_y;
cursor->data = (Uint8 *)malloc((w/8)*h*2);
cursor->mask = cursor->data+((w/8)*h);
cursor->save[0] = (Uint8 *)malloc(savelen*2);
cursor->save[1] = cursor->save[0] + savelen;
cursor->wm_cursor = NULL;
if ( ! cursor->data || ! cursor->save[0] ) {
SDL_FreeCursor(cursor);
SDL_OutOfMemory();
return(NULL);
}
for ( i=((w/8)*h)-1; i>=0; --i ) {
cursor->data[i] = data[i];
cursor->mask[i] = mask[i] | data[i];
}
memset(cursor->save[0], 0, savelen*2);
/* If the window manager gives us a good cursor, we're done! */
if ( video->CreateWMCursor ) {
cursor->wm_cursor = video->CreateWMCursor(video, data, mask,
w, h, hot_x, hot_y);
} else {
cursor->wm_cursor = NULL;
}
return(cursor);
}
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
if this is desired for any reason. This is used when setting
the video mode and when the SDL window gains the mouse focus.
*/
void SDL_SetCursor (SDL_Cursor *cursor)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
/* Make sure that the video subsystem has been initialized */
if ( ! video ) {
return;
}
/* Prevent the event thread from moving the mouse */
SDL_LockCursor();
/* Set the new cursor */
if ( cursor && (cursor != SDL_cursor) ) {
/* Erase the current mouse position */
if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
SDL_EraseCursor(SDL_VideoSurface);
} else if ( video->MoveWMCursor ) {
/* If the video driver is moving the cursor directly,
it needs to hide the old cursor before (possibly)
showing the new one. (But don't erase NULL cursor)
*/
if ( SDL_cursor ) {
video->ShowWMCursor(this, NULL);
}
}
SDL_cursor = cursor;
}
/* Draw the new mouse cursor */
if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) {
/* Use window manager cursor if possible */
if ( SDL_cursor->wm_cursor &&
video->ShowWMCursor(this, SDL_cursor->wm_cursor) )
SDL_cursorstate &= ~CURSOR_USINGSW;
else {
SDL_cursorstate |= CURSOR_USINGSW;
if ( video->ShowWMCursor ) {
video->ShowWMCursor(this, NULL);
}
{ int x, y;
SDL_GetMouseState(&x, &y);
SDL_cursor->area.x = (x - SDL_cursor->hot_x);
SDL_cursor->area.y = (y - SDL_cursor->hot_y);
}
SDL_DrawCursor(SDL_VideoSurface);
}
} else {
/* Erase window manager mouse (cursor not visible) */
if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) {
SDL_EraseCursor(SDL_VideoSurface);
} else {
if ( video ) {
video->ShowWMCursor(this, NULL);
}
}
}
SDL_UnlockCursor();
}
SDL_Cursor * SDL_GetCursor (void)
{
return(SDL_cursor);
}
void SDL_FreeCursor (SDL_Cursor *cursor)
{
if ( cursor ) {
if ( cursor == SDL_cursor ) {
SDL_SetCursor(SDL_defcursor);
}
if ( cursor != SDL_defcursor ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
if ( cursor->data ) {
free(cursor->data);
}
if ( cursor->save[0] ) {
free(cursor->save[0]);
}
if ( video && cursor->wm_cursor ) {
video->FreeWMCursor(this, cursor->wm_cursor);
}
free(cursor);
}
}
}
int SDL_ShowCursor (int toggle)
{
int showing;
showing = (SDL_cursorstate & CURSOR_VISIBLE);
if ( toggle >= 0 ) {
SDL_LockCursor();
if ( toggle ) {
SDL_cursorstate |= CURSOR_VISIBLE;
} else {
SDL_cursorstate &= ~CURSOR_VISIBLE;
}
SDL_UnlockCursor();
if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
SDL_SetCursor(NULL);
if ( video && video->CheckMouseMode ) {
video->CheckMouseMode(this);
}
}
} else {
/* Query current state */ ;
}
return(showing ? 1 : 0);
}
void SDL_WarpMouse (Uint16 x, Uint16 y)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
/* This generates a mouse motion event */
if ( video->WarpWMCursor ) {
video->WarpWMCursor(this, x, y);
} else {
x += (this->screen->offset % this->screen->pitch) /
this->screen->format->BytesPerPixel;
y += (this->screen->offset / this->screen->pitch);
SDL_PrivateMouseMotion(0, 0, x, y);
}
}
void SDL_MoveCursor(int x, int y)
{
SDL_VideoDevice *video = current_video;
/* Erase and update the current mouse position */
if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
/* Erase and redraw mouse cursor in new position */
SDL_LockCursor();
SDL_EraseCursor(SDL_VideoSurface);
SDL_cursor->area.x = (x - SDL_cursor->hot_x);
SDL_cursor->area.y = (y - SDL_cursor->hot_y);
SDL_DrawCursor(SDL_VideoSurface);
SDL_UnlockCursor();
} else if ( video->MoveWMCursor ) {
video->MoveWMCursor(video, x, y);
}
}
/* Keep track of the current cursor colors */
static int palette_changed = 1;
static Uint32 pixels8[2];
void SDL_CursorPaletteChanged(void)
{
palette_changed = 1;
}
void SDL_MouseRect(SDL_Rect *area)
{
int clip_diff;
*area = SDL_cursor->area;
if ( area->x < 0 ) {
area->w += area->x;
area->x = 0;
}
if ( area->y < 0 ) {
area->h += area->y;
area->y = 0;
}
clip_diff = (area->x+area->w)-SDL_VideoSurface->w;
if ( clip_diff > 0 ) {
area->w = area->w < clip_diff ? 0 : area->w-clip_diff;
}
clip_diff = (area->y+area->h)-SDL_VideoSurface->h;
if ( clip_diff > 0 ) {
area->h = area->h < clip_diff ? 0 : area->h-clip_diff;
}
}
static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area)
{
const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
int i, w, h;
Uint8 *data, datab;
Uint8 *mask, maskb;
data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
switch (screen->format->BytesPerPixel) {
case 1: {
Uint8 *dst;
int dstskip;
if ( palette_changed ) {
pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
palette_changed = 0;
}
dst = (Uint8 *)screen->pixels +
(SDL_cursor->area.y+area->y)*screen->pitch +
SDL_cursor->area.x;
dstskip = screen->pitch-area->w;
for ( h=area->h; h; h-- ) {
for ( w=area->w/8; w; w-- ) {
maskb = *mask++;
datab = *data++;
for ( i=0; i<8; ++i ) {
if ( maskb & 0x80 ) {
*dst = pixels8[datab>>7];
}
maskb <<= 1;
datab <<= 1;
dst++;
}
}
dst += dstskip;
}
}
break;
case 2: {
Uint16 *dst;
int dstskip;
dst = (Uint16 *)screen->pixels +
(SDL_cursor->area.y+area->y)*screen->pitch/2 +
SDL_cursor->area.x;
dstskip = (screen->pitch/2)-area->w;
for ( h=area->h; h; h-- ) {
for ( w=area->w/8; w; w-- ) {
maskb = *mask++;
datab = *data++;
for ( i=0; i<8; ++i ) {
if ( maskb & 0x80 ) {
*dst = pixels[datab>>7];
}
maskb <<= 1;
datab <<= 1;
dst++;
}
}
dst += dstskip;
}
}
break;
case 3: {
Uint8 *dst;
int dstskip;
dst = (Uint8 *)screen->pixels +
(SDL_cursor->area.y+area->y)*screen->pitch +
SDL_cursor->area.x*3;
dstskip = screen->pitch-area->w*3;
for ( h=area->h; h; h-- ) {
for ( w=area->w/8; w; w-- ) {
maskb = *mask++;
datab = *data++;
for ( i=0; i<8; ++i ) {
if ( maskb & 0x80 ) {
memset(dst,pixels[datab>>7],3);
}
maskb <<= 1;
datab <<= 1;
dst += 3;
}
}
dst += dstskip;
}
}
break;
case 4: {
Uint32 *dst;
int dstskip;
dst = (Uint32 *)screen->pixels +
(SDL_cursor->area.y+area->y)*screen->pitch/4 +
SDL_cursor->area.x;
dstskip = (screen->pitch/4)-area->w;
for ( h=area->h; h; h-- ) {
for ( w=area->w/8; w; w-- ) {
maskb = *mask++;
datab = *data++;
for ( i=0; i<8; ++i ) {
if ( maskb & 0x80 ) {
*dst = pixels[datab>>7];
}
maskb <<= 1;
datab <<= 1;
dst++;
}
}
dst += dstskip;
}
}
break;
}
}
static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area)
{
const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
int h;
int x, minx, maxx;
Uint8 *data, datab = 0;
Uint8 *mask, maskb = 0;
Uint8 *dst;
int dstbpp, dstskip;
data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
dstbpp = screen->format->BytesPerPixel;
dst = (Uint8 *)screen->pixels +
(SDL_cursor->area.y+area->y)*screen->pitch +
SDL_cursor->area.x*dstbpp;
dstskip = screen->pitch-SDL_cursor->area.w*dstbpp;
minx = area->x;
maxx = area->x+area->w;
if ( screen->format->BytesPerPixel == 1 ) {
if ( palette_changed ) {
pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
palette_changed = 0;
}
for ( h=area->h; h; h-- ) {
for ( x=0; x<SDL_cursor->area.w; ++x ) {
if ( (x%8) == 0 ) {
maskb = *mask++;
datab = *data++;
}
if ( (x >= minx) && (x < maxx) ) {
if ( maskb & 0x80 ) {
memset(dst, pixels8[datab>>7], dstbpp);
}
}
maskb <<= 1;
datab <<= 1;
dst += dstbpp;
}
dst += dstskip;
}
} else {
for ( h=area->h; h; h-- ) {
for ( x=0; x<SDL_cursor->area.w; ++x ) {
if ( (x%8) == 0 ) {
maskb = *mask++;
datab = *data++;
}
if ( (x >= minx) && (x < maxx) ) {
if ( maskb & 0x80 ) {
memset(dst, pixels[datab>>7], dstbpp);
}
}
maskb <<= 1;
datab <<= 1;
dst += dstbpp;
}
dst += dstskip;
}
}
}
/* This handles the ugly work of converting the saved cursor background from
the pixel format of the shadow surface to that of the video surface.
This is only necessary when blitting from a shadow surface of a different
pixel format than the video surface, and using a software rendered cursor.
*/
static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h)
{
SDL_BlitInfo info;
SDL_loblit RunBlit;
/* Make sure we can steal the blit mapping */
if ( screen->map->dst != SDL_VideoSurface ) {
return;
}
/* Set up the blit information */
info.s_pixels = SDL_cursor->save[1];
info.s_width = w;
info.s_height = h;
info.s_skip = 0;
info.d_pixels = SDL_cursor->save[0];
info.d_width = w;
info.d_height = h;
info.d_skip = 0;
info.aux_data = screen->map->sw_data->aux_data;
info.src = screen->format;
info.table = screen->map->table;
info.dst = SDL_VideoSurface->format;
RunBlit = screen->map->sw_data->blit;
/* Run the actual software blit */
RunBlit(&info);
}
void SDL_DrawCursorNoLock(SDL_Surface *screen)
{
SDL_Rect area;
/* Get the mouse rectangle, clipped to the screen */
SDL_MouseRect(&area);
if ( (area.w == 0) || (area.h == 0) ) {
return;
}
/* Copy mouse background */
{ int w, h, screenbpp;
Uint8 *src, *dst;
/* Set up the copy pointers */
screenbpp = screen->format->BytesPerPixel;
if ( (screen == SDL_VideoSurface) ||
FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
dst = SDL_cursor->save[0];
} else {
dst = SDL_cursor->save[1];
}
src = (Uint8 *)screen->pixels + area.y * screen->pitch +
area.x * screenbpp;
/* Perform the copy */
w = area.w*screenbpp;
h = area.h;
while ( h-- ) {
memcpy(dst, src, w);
dst += w;
src += screen->pitch;
}
}
/* Draw the mouse cursor */
area.x -= SDL_cursor->area.x;
area.y -= SDL_cursor->area.y;
if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) {
SDL_DrawCursorFast(screen, &area);
} else {
SDL_DrawCursorSlow(screen, &area);
}
}
void SDL_DrawCursor(SDL_Surface *screen)
{
/* Lock the screen if necessary */
if ( screen == NULL ) {
return;
}
if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
return;
}
}
SDL_DrawCursorNoLock(screen);
/* Unlock the screen and update if necessary */
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
if ( (screen == SDL_VideoSurface) &&
((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
SDL_Rect area;
SDL_MouseRect(&area);
/* This can be called before a video mode is set */
if ( video->UpdateRects ) {
video->UpdateRects(this, 1, &area);
}
}
}
void SDL_EraseCursorNoLock(SDL_Surface *screen)
{
SDL_Rect area;
/* Get the mouse rectangle, clipped to the screen */
SDL_MouseRect(&area);
if ( (area.w == 0) || (area.h == 0) ) {
return;
}
/* Copy mouse background */
{ int w, h, screenbpp;
Uint8 *src, *dst;
/* Set up the copy pointers */
screenbpp = screen->format->BytesPerPixel;
if ( (screen == SDL_VideoSurface) ||
FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
src = SDL_cursor->save[0];
} else {
src = SDL_cursor->save[1];
}
dst = (Uint8 *)screen->pixels + area.y * screen->pitch +
area.x * screenbpp;
/* Perform the copy */
w = area.w*screenbpp;
h = area.h;
while ( h-- ) {
memcpy(dst, src, w);
src += w;
dst += screen->pitch;
}
/* Perform pixel conversion on cursor background */
if ( src > SDL_cursor->save[1] ) {
SDL_ConvertCursorSave(screen, area.w, area.h);
}
}
}
void SDL_EraseCursor(SDL_Surface *screen)
{
/* Lock the screen if necessary */
if ( screen == NULL ) {
return;
}
if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
return;
}
}
SDL_EraseCursorNoLock(screen);
/* Unlock the screen and update if necessary */
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
if ( (screen == SDL_VideoSurface) &&
((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
SDL_Rect area;
SDL_MouseRect(&area);
if ( video->UpdateRects ) {
video->UpdateRects(this, 1, &area);
}
}
}
/* Reset the cursor on video mode change
FIXME: Keep track of all cursors, and reset them all.
*/
void SDL_ResetCursor(void)
{
int savelen;
if ( SDL_cursor ) {
savelen = SDL_cursor->area.w*4*SDL_cursor->area.h;
SDL_cursor->area.x = 0;
SDL_cursor->area.y = 0;
memset(SDL_cursor->save[0], 0, savelen);
}
}

View File

@ -0,0 +1,77 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_cursor_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Useful variables and functions from SDL_cursor.c */
#include "SDL_mouse.h"
extern int SDL_CursorInit(Uint32 flags);
extern void SDL_CursorPaletteChanged(void);
extern void SDL_DrawCursor(SDL_Surface *screen);
extern void SDL_DrawCursorNoLock(SDL_Surface *screen);
extern void SDL_EraseCursor(SDL_Surface *screen);
extern void SDL_EraseCursorNoLock(SDL_Surface *screen);
extern void SDL_UpdateCursor(SDL_Surface *screen);
extern void SDL_ResetCursor(void);
extern void SDL_MoveCursor(int x, int y);
extern void SDL_CursorQuit(void);
#define INLINE_MOUSELOCK
#ifdef INLINE_MOUSELOCK
/* Inline (macro) versions of the mouse lock functions */
#include "SDL_mutex.h"
extern SDL_mutex *SDL_cursorlock;
#define SDL_LockCursor() \
do { \
if ( SDL_cursorlock ) { \
SDL_mutexP(SDL_cursorlock); \
} \
} while ( 0 )
#define SDL_UnlockCursor() \
do { \
if ( SDL_cursorlock ) { \
SDL_mutexV(SDL_cursorlock); \
} \
} while ( 0 )
#else
extern void SDL_LockCursor(void);
extern void SDL_UnlockCursor(void);
#endif /* INLINE_MOUSELOCK */
/* Only for low-level mouse cursor drawing */
extern SDL_Cursor *SDL_cursor;
extern void SDL_MouseRect(SDL_Rect *area);
/* State definitions for the SDL cursor */
#define CURSOR_VISIBLE 0x01
#define CURSOR_USINGSW 0x10
#define SHOULD_DRAWCURSOR(X) \
(((X)&(CURSOR_VISIBLE|CURSOR_USINGSW)) == \
(CURSOR_VISIBLE|CURSOR_USINGSW))
extern volatile int SDL_cursorstate;

View File

@ -0,0 +1,238 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* Gamma correction support */
#define USE_MATH_H /* Used for calculating gamma ramps */
#ifdef USE_MATH_H
#include <math.h>
#endif
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_sysvideo.h"
#ifdef USE_MATH_H
static void CalculateGammaRamp(float gamma, Uint16 *ramp)
{
int i;
/* 0.0 gamma is all black */
if ( gamma <= 0.0 ) {
for ( i=0; i<256; ++i ) {
ramp[i] = 0;
}
return;
} else
/* 1.0 gamma is identity */
if ( gamma == 1.0 ) {
for ( i=0; i<256; ++i ) {
ramp[i] = (i << 8) | i;
}
return;
} else
/* Calculate a real gamma ramp */
{ int value;
gamma = 1.0f / gamma;
for ( i=0; i<256; ++i ) {
value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5);
if ( value > 65535 ) {
value = 65535;
}
ramp[i] = (Uint16)value;
}
}
}
static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp)
{
/* The following is adapted from a post by Garrett Bass on OpenGL
Gamedev list, March 4, 2000.
*/
float sum = 0.0;
int i, count = 0;
*gamma = 1.0;
for ( i = 1; i < 256; ++i ) {
if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
double B = (double)i / 256.0;
double A = ramp[i] / 65535.0;
sum += (float) ( log(A) / log(B) );
count++;
}
}
if ( count && sum ) {
*gamma = 1.0f / (sum / count);
}
}
#endif /* USE_MATH_H */
int SDL_SetGamma(float red, float green, float blue)
{
int succeeded;
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
succeeded = -1;
#ifdef USE_MATH_H
/* Prefer using SetGammaRamp(), as it's more flexible */
{
Uint16 ramp[3][256];
CalculateGammaRamp(red, ramp[0]);
CalculateGammaRamp(green, ramp[1]);
CalculateGammaRamp(blue, ramp[2]);
succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
}
#else
SDL_SetError("Gamma correction not supported");
#endif
if ( (succeeded < 0) && video->SetGamma ) {
SDL_ClearError();
succeeded = video->SetGamma(this, red, green, blue);
}
return succeeded;
}
/* Calculating the gamma by integrating the gamma ramps isn't exact,
so this function isn't officially supported.
*/
int SDL_GetGamma(float *red, float *green, float *blue)
{
int succeeded;
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
succeeded = -1;
#ifdef USE_MATH_H
/* Prefer using GetGammaRamp(), as it's more flexible */
{
Uint16 ramp[3][256];
succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
if ( succeeded >= 0 ) {
CalculateGammaFromRamp(red, ramp[0]);
CalculateGammaFromRamp(green, ramp[1]);
CalculateGammaFromRamp(blue, ramp[2]);
}
}
#else
SDL_SetError("Gamma correction not supported");
#endif
if ( (succeeded < 0) && video->GetGamma ) {
SDL_ClearError();
succeeded = video->GetGamma(this, red, green, blue);
}
return succeeded;
}
int SDL_SetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
{
int succeeded;
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
SDL_Surface *screen = SDL_PublicSurface;
/* Verify the screen parameter */
if ( !screen ) {
SDL_SetError("No video mode has been set");
return -1;
}
/* Lazily allocate the gamma tables */
if ( ! video->gamma ) {
SDL_GetGammaRamp(0, 0, 0);
}
/* Fill the gamma table with the new values */
if ( red ) {
memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma));
}
if ( green ) {
memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma));
}
if ( blue ) {
memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma));
}
/* Gamma correction always possible on split palettes */
if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
SDL_Palette *pal = screen->format->palette;
/* If physical palette has been set independently, use it */
if(video->physpal)
pal = video->physpal;
SDL_SetPalette(screen, SDL_PHYSPAL,
pal->colors, 0, pal->ncolors);
return 0;
}
/* Try to set the gamma ramp in the driver */
succeeded = -1;
if ( video->SetGammaRamp ) {
succeeded = video->SetGammaRamp(this, video->gamma);
} else {
SDL_SetError("Gamma ramp manipulation not supported");
}
return succeeded;
}
int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
/* Lazily allocate the gamma table */
if ( ! video->gamma ) {
video->gamma = malloc(3*256*sizeof(*video->gamma));
if ( ! video->gamma ) {
SDL_OutOfMemory();
return -1;
}
if ( video->GetGammaRamp ) {
/* Get the real hardware gamma */
video->GetGammaRamp(this, video->gamma);
} else {
/* Assume an identity gamma */
int i;
for ( i=0; i<256; ++i ) {
video->gamma[0*256+i] = (i << 8) | i;
video->gamma[1*256+i] = (i << 8) | i;
video->gamma[2*256+i] = (i << 8) | i;
}
}
}
/* Just copy from our internal table */
if ( red ) {
memcpy(red, &video->gamma[0*256], 256*sizeof(*red));
}
if ( green ) {
memcpy(green, &video->gamma[1*256], 256*sizeof(*green));
}
if ( blue ) {
memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue));
}
return 0;
}

View File

@ -0,0 +1,341 @@
/* list of OpenGL functions sorted alphabetically
If you need to use a GL function from the SDL video subsystem,
change it's entry from SDL_PROC_UNUSED to SDL_PROC and rebuild.
*/
#define SDL_PROC_UNUSED(ret,func,params)
SDL_PROC_UNUSED(void,glAccum,(GLenum,GLfloat))
SDL_PROC_UNUSED(void,glAlphaFunc,(GLenum,GLclampf))
SDL_PROC_UNUSED(GLboolean,glAreTexturesResident,(GLsizei,const GLuint*,GLboolean*))
SDL_PROC_UNUSED(void,glArrayElement,(GLint))
SDL_PROC(void,glBegin,(GLenum))
SDL_PROC(void,glBindTexture,(GLenum,GLuint))
SDL_PROC_UNUSED(void,glBitmap,(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte*))
SDL_PROC(void,glBlendFunc,(GLenum,GLenum))
SDL_PROC_UNUSED(void,glCallList,(GLuint))
SDL_PROC_UNUSED(void,glCallLists,(GLsizei,GLenum,const GLvoid*))
SDL_PROC_UNUSED(void,glClear,(GLbitfield))
SDL_PROC_UNUSED(void,glClearAccum,(GLfloat,GLfloat,GLfloat,GLfloat))
SDL_PROC_UNUSED(void,glClearColor,(GLclampf,GLclampf,GLclampf,GLclampf))
SDL_PROC_UNUSED(void,glClearDepth,(GLclampd))
SDL_PROC_UNUSED(void,glClearIndex,(GLfloat))
SDL_PROC_UNUSED(void,glClearStencil,(GLint))
SDL_PROC_UNUSED(void,glClipPlane,(GLenum,const GLdouble*))
SDL_PROC_UNUSED(void,glColor3b,(GLbyte,GLbyte,GLbyte))
SDL_PROC_UNUSED(void,glColor3bv,(const GLbyte*))
SDL_PROC_UNUSED(void,glColor3d,(GLdouble,GLdouble,GLdouble))
SDL_PROC_UNUSED(void,glColor3dv,(const GLdouble*))
SDL_PROC_UNUSED(void,glColor3f,(GLfloat,GLfloat,GLfloat))
SDL_PROC_UNUSED(void,glColor3fv,(const GLfloat*))
SDL_PROC_UNUSED(void,glColor3i,(GLint,GLint,GLint))
SDL_PROC_UNUSED(void,glColor3iv,(const GLint*))
SDL_PROC_UNUSED(void,glColor3s,(GLshort,GLshort,GLshort))
SDL_PROC_UNUSED(void,glColor3sv,(const GLshort*))
SDL_PROC_UNUSED(void,glColor3ub,(GLubyte,GLubyte,GLubyte))
SDL_PROC_UNUSED(void,glColor3ubv,(const GLubyte*))
SDL_PROC_UNUSED(void,glColor3ui,(GLuint,GLuint,GLuint))
SDL_PROC_UNUSED(void,glColor3uiv,(const GLuint*))
SDL_PROC_UNUSED(void,glColor3us,(GLushort,GLushort,GLushort))
SDL_PROC_UNUSED(void,glColor3usv,(const GLushort*))
SDL_PROC_UNUSED(void,glColor4b,(GLbyte,GLbyte,GLbyte,GLbyte))
SDL_PROC_UNUSED(void,glColor4bv,(const GLbyte*))
SDL_PROC_UNUSED(void,glColor4d,(GLdouble,GLdouble,GLdouble,GLdouble))
SDL_PROC_UNUSED(void,glColor4dv,(const GLdouble*))
SDL_PROC(void,glColor4f,(GLfloat,GLfloat,GLfloat,GLfloat))
SDL_PROC_UNUSED(void,glColor4fv,(const GLfloat*))
SDL_PROC_UNUSED(void,glColor4i,(GLint,GLint,GLint,GLint))
SDL_PROC_UNUSED(void,glColor4iv,(const GLint*))
SDL_PROC_UNUSED(void,glColor4s,(GLshort,GLshort,GLshort,GLshort))
SDL_PROC_UNUSED(void,glColor4sv,(const GLshort*))
SDL_PROC_UNUSED(void,glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
SDL_PROC_UNUSED(void,glColor4ubv,(const GLubyte *v))
SDL_PROC_UNUSED(void,glColor4ui,(GLuint red, GLuint green, GLuint blue, GLuint alpha))
SDL_PROC_UNUSED(void,glColor4uiv,(const GLuint *v))
SDL_PROC_UNUSED(void,glColor4us,(GLushort red, GLushort green, GLushort blue, GLushort alpha))
SDL_PROC_UNUSED(void,glColor4usv,(const GLushort *v))
SDL_PROC_UNUSED(void,glColorMask,(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha))
SDL_PROC_UNUSED(void,glColorMaterial,(GLenum face, GLenum mode))
SDL_PROC_UNUSED(void,glColorPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer))
SDL_PROC_UNUSED(void,glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type))
SDL_PROC(void,glCopyTexImage1D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border))
SDL_PROC_UNUSED(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border))
SDL_PROC_UNUSED(void,glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width))
SDL_PROC_UNUSED(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height))
SDL_PROC_UNUSED(void,glCullFace,(GLenum mode))
SDL_PROC_UNUSED(void,glDeleteLists,(GLuint list, GLsizei range))
SDL_PROC_UNUSED(void,glDeleteTextures,(GLsizei n, const GLuint *textures))
SDL_PROC_UNUSED(void,glDepthFunc,(GLenum func))
SDL_PROC_UNUSED(void,glDepthMask,(GLboolean flag))
SDL_PROC_UNUSED(void,glDepthRange,(GLclampd zNear, GLclampd zFar))
SDL_PROC(void,glDisable,(GLenum cap))
SDL_PROC_UNUSED(void,glDisableClientState,(GLenum array))
SDL_PROC_UNUSED(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count))
SDL_PROC_UNUSED(void,glDrawBuffer,(GLenum mode))
SDL_PROC_UNUSED(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices))
SDL_PROC_UNUSED(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels))
SDL_PROC_UNUSED(void,glEdgeFlag,(GLboolean flag))
SDL_PROC_UNUSED(void,glEdgeFlagPointer,(GLsizei stride, const GLvoid *pointer))
SDL_PROC_UNUSED(void,glEdgeFlagv,(const GLboolean *flag))
SDL_PROC(void,glEnable,(GLenum cap))
SDL_PROC_UNUSED(void,glEnableClientState,(GLenum array))
SDL_PROC(void,glEnd,(void))
SDL_PROC_UNUSED(void,glEndList,(void))
SDL_PROC_UNUSED(void,glEvalCoord1d,(GLdouble u))
SDL_PROC_UNUSED(void,glEvalCoord1dv,(const GLdouble *u))
SDL_PROC_UNUSED(void,glEvalCoord1f,(GLfloat u))
SDL_PROC_UNUSED(void,glEvalCoord1fv,(const GLfloat *u))
SDL_PROC_UNUSED(void,glEvalCoord2d,(GLdouble u, GLdouble v))
SDL_PROC_UNUSED(void,glEvalCoord2dv,(const GLdouble *u))
SDL_PROC_UNUSED(void,glEvalCoord2f,(GLfloat u, GLfloat v))
SDL_PROC_UNUSED(void,glEvalCoord2fv,(const GLfloat *u))
SDL_PROC_UNUSED(void,glEvalMesh1,(GLenum mode, GLint i1, GLint i2))
SDL_PROC_UNUSED(void,glEvalMesh2,(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2))
SDL_PROC_UNUSED(void,glEvalPoint1,(GLint i))
SDL_PROC_UNUSED(void,glEvalPoint2,(GLint i, GLint j))
SDL_PROC_UNUSED(void,glFeedbackBuffer,(GLsizei size, GLenum type, GLfloat *buffer))
SDL_PROC_UNUSED(void,glFinish,(void))
SDL_PROC(void,glFlush,(void))
SDL_PROC_UNUSED(void,glFogf,(GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glFogfv,(GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glFogi,(GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glFogiv,(GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glFrontFace,(GLenum mode))
SDL_PROC_UNUSED(void,glFrustum,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar))
SDL_PROC_UNUSED(GLuint,glGenLists,(GLsizei range))
SDL_PROC(void,glGenTextures,(GLsizei n, GLuint *textures))
SDL_PROC_UNUSED(void,glGetBooleanv,(GLenum pname, GLboolean *params))
SDL_PROC_UNUSED(void,glGetClipPlane,(GLenum plane, GLdouble *equation))
SDL_PROC_UNUSED(void,glGetDoublev,(GLenum pname, GLdouble *params))
SDL_PROC_UNUSED(GLenum,glGetError,(void))
SDL_PROC_UNUSED(void,glGetFloatv,(GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetIntegerv,(GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetLightfv,(GLenum light, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetLightiv,(GLenum light, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetMapdv,(GLenum target, GLenum query, GLdouble *v))
SDL_PROC_UNUSED(void,glGetMapfv,(GLenum target, GLenum query, GLfloat *v))
SDL_PROC_UNUSED(void,glGetMapiv,(GLenum target, GLenum query, GLint *v))
SDL_PROC_UNUSED(void,glGetMaterialfv,(GLenum face, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetMaterialiv,(GLenum face, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetPixelMapfv,(GLenum map, GLfloat *values))
SDL_PROC_UNUSED(void,glGetPixelMapuiv,(GLenum map, GLuint *values))
SDL_PROC_UNUSED(void,glGetPixelMapusv,(GLenum map, GLushort *values))
SDL_PROC_UNUSED(void,glGetPointerv,(GLenum pname, GLvoid* *params))
SDL_PROC_UNUSED(void,glGetPolygonStipple,(GLubyte *mask))
SDL_PROC(const GLubyte *,glGetString,(GLenum name))
SDL_PROC_UNUSED(void,glGetTexEnvfv,(GLenum target, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetTexEnviv,(GLenum target, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetTexGendv,(GLenum coord, GLenum pname, GLdouble *params))
SDL_PROC_UNUSED(void,glGetTexGenfv,(GLenum coord, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetTexGeniv,(GLenum coord, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetTexImage,(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels))
SDL_PROC_UNUSED(void,glGetTexLevelParameterfv,(GLenum target, GLint level, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetTexLevelParameteriv,(GLenum target, GLint level, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glGetTexParameterfv,(GLenum target, GLenum pname, GLfloat *params))
SDL_PROC_UNUSED(void,glGetTexParameteriv,(GLenum target, GLenum pname, GLint *params))
SDL_PROC_UNUSED(void,glHint,(GLenum target, GLenum mode))
SDL_PROC_UNUSED(void,glIndexMask,(GLuint mask))
SDL_PROC_UNUSED(void,glIndexPointer,(GLenum type, GLsizei stride, const GLvoid *pointer))
SDL_PROC_UNUSED(void,glIndexd,(GLdouble c))
SDL_PROC_UNUSED(void,glIndexdv,(const GLdouble *c))
SDL_PROC_UNUSED(void,glIndexf,(GLfloat c))
SDL_PROC_UNUSED(void,glIndexfv,(const GLfloat *c))
SDL_PROC_UNUSED(void,glIndexi,(GLint c))
SDL_PROC_UNUSED(void,glIndexiv,(const GLint *c))
SDL_PROC_UNUSED(void,glIndexs,(GLshort c))
SDL_PROC_UNUSED(void,glIndexsv,(const GLshort *c))
SDL_PROC_UNUSED(void,glIndexub,(GLubyte c))
SDL_PROC_UNUSED(void,glIndexubv,(const GLubyte *c))
SDL_PROC_UNUSED(void,glInitNames,(void))
SDL_PROC_UNUSED(void,glInterleavedArrays,(GLenum format, GLsizei stride, const GLvoid *pointer))
SDL_PROC_UNUSED(GLboolean,glIsEnabled,(GLenum cap))
SDL_PROC_UNUSED(GLboolean,glIsList,(GLuint list))
SDL_PROC_UNUSED(GLboolean,glIsTexture,(GLuint texture))
SDL_PROC_UNUSED(void,glLightModelf,(GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glLightModelfv,(GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glLightModeli,(GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glLightModeliv,(GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glLightf,(GLenum light, GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glLightfv,(GLenum light, GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glLighti,(GLenum light, GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glLightiv,(GLenum light, GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glLineStipple,(GLint factor, GLushort pattern))
SDL_PROC_UNUSED(void,glLineWidth,(GLfloat width))
SDL_PROC_UNUSED(void,glListBase,(GLuint base))
SDL_PROC(void,glLoadIdentity,(void))
SDL_PROC_UNUSED(void,glLoadMatrixd,(const GLdouble *m))
SDL_PROC_UNUSED(void,glLoadMatrixf,(const GLfloat *m))
SDL_PROC_UNUSED(void,glLoadName,(GLuint name))
SDL_PROC_UNUSED(void,glLogicOp,(GLenum opcode))
SDL_PROC_UNUSED(void,glMap1d,(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points))
SDL_PROC_UNUSED(void,glMap1f,(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points))
SDL_PROC_UNUSED(void,glMap2d,(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points))
SDL_PROC_UNUSED(void,glMap2f,(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points))
SDL_PROC_UNUSED(void,glMapGrid1d,(GLint un, GLdouble u1, GLdouble u2))
SDL_PROC_UNUSED(void,glMapGrid1f,(GLint un, GLfloat u1, GLfloat u2))
SDL_PROC_UNUSED(void,glMapGrid2d,(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2))
SDL_PROC_UNUSED(void,glMapGrid2f,(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2))
SDL_PROC_UNUSED(void,glMaterialf,(GLenum face, GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glMaterialfv,(GLenum face, GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glMateriali,(GLenum face, GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glMaterialiv,(GLenum face, GLenum pname, const GLint *params))
SDL_PROC(void,glMatrixMode,(GLenum mode))
SDL_PROC_UNUSED(void,glMultMatrixd,(const GLdouble *m))
SDL_PROC_UNUSED(void,glMultMatrixf,(const GLfloat *m))
SDL_PROC_UNUSED(void,glNewList,(GLuint list, GLenum mode))
SDL_PROC_UNUSED(void,glNormal3b,(GLbyte nx, GLbyte ny, GLbyte nz))
SDL_PROC_UNUSED(void,glNormal3bv,(const GLbyte *v))
SDL_PROC_UNUSED(void,glNormal3d,(GLdouble nx, GLdouble ny, GLdouble nz))
SDL_PROC_UNUSED(void,glNormal3dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glNormal3f,(GLfloat nx, GLfloat ny, GLfloat nz))
SDL_PROC_UNUSED(void,glNormal3fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glNormal3i,(GLint nx, GLint ny, GLint nz))
SDL_PROC_UNUSED(void,glNormal3iv,(const GLint *v))
SDL_PROC_UNUSED(void,glNormal3s,(GLshort nx, GLshort ny, GLshort nz))
SDL_PROC_UNUSED(void,glNormal3sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glNormalPointer,(GLenum type, GLsizei stride, const GLvoid *pointer))
SDL_PROC(void,glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar))
SDL_PROC_UNUSED(void,glPassThrough,(GLfloat token))
SDL_PROC_UNUSED(void,glPixelMapfv,(GLenum map, GLsizei mapsize, const GLfloat *values))
SDL_PROC_UNUSED(void,glPixelMapuiv,(GLenum map, GLsizei mapsize, const GLuint *values))
SDL_PROC_UNUSED(void,glPixelMapusv,(GLenum map, GLsizei mapsize, const GLushort *values))
SDL_PROC_UNUSED(void,glPixelStoref,(GLenum pname, GLfloat param))
SDL_PROC(void,glPixelStorei,(GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glPixelTransferf,(GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glPixelTransferi,(GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glPixelZoom,(GLfloat xfactor, GLfloat yfactor))
SDL_PROC_UNUSED(void,glPointSize,(GLfloat size))
SDL_PROC_UNUSED(void,glPolygonMode,(GLenum face, GLenum mode))
SDL_PROC_UNUSED(void,glPolygonOffset,(GLfloat factor, GLfloat units))
SDL_PROC_UNUSED(void,glPolygonStipple,(const GLubyte *mask))
SDL_PROC(void,glPopAttrib,(void))
SDL_PROC(void,glPopClientAttrib,(void))
SDL_PROC(void,glPopMatrix,(void))
SDL_PROC_UNUSED(void,glPopName,(void))
SDL_PROC_UNUSED(void,glPrioritizeTextures,(GLsizei n, const GLuint *textures, const GLclampf *priorities))
SDL_PROC(void,glPushAttrib,(GLbitfield mask))
SDL_PROC(void,glPushClientAttrib,(GLbitfield mask))
SDL_PROC(void,glPushMatrix,(void))
SDL_PROC_UNUSED(void,glPushName,(GLuint name))
SDL_PROC_UNUSED(void,glRasterPos2d,(GLdouble x, GLdouble y))
SDL_PROC_UNUSED(void,glRasterPos2dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glRasterPos2f,(GLfloat x, GLfloat y))
SDL_PROC_UNUSED(void,glRasterPos2fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glRasterPos2i,(GLint x, GLint y))
SDL_PROC_UNUSED(void,glRasterPos2iv,(const GLint *v))
SDL_PROC_UNUSED(void,glRasterPos2s,(GLshort x, GLshort y))
SDL_PROC_UNUSED(void,glRasterPos2sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glRasterPos3d,(GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void,glRasterPos3dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glRasterPos3f,(GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void,glRasterPos3fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glRasterPos3i,(GLint x, GLint y, GLint z))
SDL_PROC_UNUSED(void,glRasterPos3iv,(const GLint *v))
SDL_PROC_UNUSED(void,glRasterPos3s,(GLshort x, GLshort y, GLshort z))
SDL_PROC_UNUSED(void,glRasterPos3sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glRasterPos4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w))
SDL_PROC_UNUSED(void,glRasterPos4dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glRasterPos4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w))
SDL_PROC_UNUSED(void,glRasterPos4fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glRasterPos4i,(GLint x, GLint y, GLint z, GLint w))
SDL_PROC_UNUSED(void,glRasterPos4iv,(const GLint *v))
SDL_PROC_UNUSED(void,glRasterPos4s,(GLshort x, GLshort y, GLshort z, GLshort w))
SDL_PROC_UNUSED(void,glRasterPos4sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glReadBuffer,(GLenum mode))
SDL_PROC_UNUSED(void,glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels))
SDL_PROC_UNUSED(void,glRectd,(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2))
SDL_PROC_UNUSED(void,glRectdv,(const GLdouble *v1, const GLdouble *v2))
SDL_PROC_UNUSED(void,glRectf,(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2))
SDL_PROC_UNUSED(void,glRectfv,(const GLfloat *v1, const GLfloat *v2))
SDL_PROC_UNUSED(void,glRecti,(GLint x1, GLint y1, GLint x2, GLint y2))
SDL_PROC_UNUSED(void,glRectiv,(const GLint *v1, const GLint *v2))
SDL_PROC_UNUSED(void,glRects,(GLshort x1, GLshort y1, GLshort x2, GLshort y2))
SDL_PROC_UNUSED(void,glRectsv,(const GLshort *v1, const GLshort *v2))
SDL_PROC_UNUSED(GLint,glRenderMode,(GLenum mode))
SDL_PROC_UNUSED(void,glRotated,(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void,glRotatef,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void,glScaled,(GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void,glScalef,(GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void,glScissor,(GLint x, GLint y, GLsizei width, GLsizei height))
SDL_PROC_UNUSED(void,glSelectBuffer,(GLsizei size, GLuint *buffer))
SDL_PROC_UNUSED(void,glShadeModel,(GLenum mode))
SDL_PROC_UNUSED(void,glStencilFunc,(GLenum func, GLint ref, GLuint mask))
SDL_PROC_UNUSED(void,glStencilMask,(GLuint mask))
SDL_PROC_UNUSED(void,glStencilOp,(GLenum fail, GLenum zfail, GLenum zpass))
SDL_PROC_UNUSED(void,glTexCoord1d,(GLdouble s))
SDL_PROC_UNUSED(void,glTexCoord1dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glTexCoord1f,(GLfloat s))
SDL_PROC_UNUSED(void,glTexCoord1fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glTexCoord1i,(GLint s))
SDL_PROC_UNUSED(void,glTexCoord1iv,(const GLint *v))
SDL_PROC_UNUSED(void,glTexCoord1s,(GLshort s))
SDL_PROC_UNUSED(void,glTexCoord1sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glTexCoord2d,(GLdouble s, GLdouble t))
SDL_PROC_UNUSED(void,glTexCoord2dv,(const GLdouble *v))
SDL_PROC(void,glTexCoord2f,(GLfloat s, GLfloat t))
SDL_PROC_UNUSED(void,glTexCoord2fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glTexCoord2i,(GLint s, GLint t))
SDL_PROC_UNUSED(void,glTexCoord2iv,(const GLint *v))
SDL_PROC_UNUSED(void,glTexCoord2s,(GLshort s, GLshort t))
SDL_PROC_UNUSED(void,glTexCoord2sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glTexCoord3d,(GLdouble s, GLdouble t, GLdouble r))
SDL_PROC_UNUSED(void,glTexCoord3dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glTexCoord3f,(GLfloat s, GLfloat t, GLfloat r))
SDL_PROC_UNUSED(void,glTexCoord3fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glTexCoord3i,(GLint s, GLint t, GLint r))
SDL_PROC_UNUSED(void,glTexCoord3iv,(const GLint *v))
SDL_PROC_UNUSED(void,glTexCoord3s,(GLshort s, GLshort t, GLshort r))
SDL_PROC_UNUSED(void,glTexCoord3sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glTexCoord4d,(GLdouble s, GLdouble t, GLdouble r, GLdouble q))
SDL_PROC_UNUSED(void,glTexCoord4dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glTexCoord4f,(GLfloat s, GLfloat t, GLfloat r, GLfloat q))
SDL_PROC_UNUSED(void,glTexCoord4fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glTexCoord4i,(GLint s, GLint t, GLint r, GLint q))
SDL_PROC_UNUSED(void,glTexCoord4iv,(const GLint *v))
SDL_PROC_UNUSED(void,glTexCoord4s,(GLshort s, GLshort t, GLshort r, GLshort q))
SDL_PROC_UNUSED(void,glTexCoord4sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glTexCoordPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer))
SDL_PROC(void,glTexEnvf,(GLenum target, GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glTexEnvfv,(GLenum target, GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glTexEnvi,(GLenum target, GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glTexEnviv,(GLenum target, GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glTexGend,(GLenum coord, GLenum pname, GLdouble param))
SDL_PROC_UNUSED(void,glTexGendv,(GLenum coord, GLenum pname, const GLdouble *params))
SDL_PROC_UNUSED(void,glTexGenf,(GLenum coord, GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glTexGenfv,(GLenum coord, GLenum pname, const GLfloat *params))
SDL_PROC_UNUSED(void,glTexGeni,(GLenum coord, GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glTexGeniv,(GLenum coord, GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glTexImage1D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels))
SDL_PROC(void,glTexImage2D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels))
SDL_PROC_UNUSED(void,glTexParameterf,(GLenum target, GLenum pname, GLfloat param))
SDL_PROC_UNUSED(void,glTexParameterfv,(GLenum target, GLenum pname, const GLfloat *params))
SDL_PROC(void,glTexParameteri,(GLenum target, GLenum pname, GLint param))
SDL_PROC_UNUSED(void,glTexParameteriv,(GLenum target, GLenum pname, const GLint *params))
SDL_PROC_UNUSED(void,glTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels))
SDL_PROC(void,glTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels))
SDL_PROC_UNUSED(void,glTranslated,(GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void,glTranslatef,(GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void,glVertex2d,(GLdouble x, GLdouble y))
SDL_PROC_UNUSED(void,glVertex2dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glVertex2f,(GLfloat x, GLfloat y))
SDL_PROC_UNUSED(void,glVertex2fv,(const GLfloat *v))
SDL_PROC(void,glVertex2i,(GLint x, GLint y))
SDL_PROC_UNUSED(void,glVertex2iv,(const GLint *v))
SDL_PROC_UNUSED(void,glVertex2s,(GLshort x, GLshort y))
SDL_PROC_UNUSED(void,glVertex2sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glVertex3d,(GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void,glVertex3dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glVertex3f,(GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void,glVertex3fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glVertex3i,(GLint x, GLint y, GLint z))
SDL_PROC_UNUSED(void,glVertex3iv,(const GLint *v))
SDL_PROC_UNUSED(void,glVertex3s,(GLshort x, GLshort y, GLshort z))
SDL_PROC_UNUSED(void,glVertex3sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glVertex4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w))
SDL_PROC_UNUSED(void,glVertex4dv,(const GLdouble *v))
SDL_PROC_UNUSED(void,glVertex4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w))
SDL_PROC_UNUSED(void,glVertex4fv,(const GLfloat *v))
SDL_PROC_UNUSED(void,glVertex4i,(GLint x, GLint y, GLint z, GLint w))
SDL_PROC_UNUSED(void,glVertex4iv,(const GLint *v))
SDL_PROC_UNUSED(void,glVertex4s,(GLshort x, GLshort y, GLshort z, GLshort w))
SDL_PROC_UNUSED(void,glVertex4sv,(const GLshort *v))
SDL_PROC_UNUSED(void,glVertexPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer))
SDL_PROC(void,glViewport,(GLint x, GLint y, GLsizei width, GLsizei height))

View File

@ -0,0 +1,35 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_leaks.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Define this if you want surface leak detection code enabled */
/*#define CHECK_LEAKS*/
/* Global variables used to check leaks in code using SDL */
#ifdef CHECK_LEAKS
extern int surfaces_allocated;
#endif

View File

@ -0,0 +1,144 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_memops.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
#ifndef _SDL_memops_h
#define _SDL_memops_h
/* System dependent optimized memory manipulation routines:
*/
#include <string.h>
#if defined(__GNUC__) && defined(i386)
/* Thanks to Brennan "Bas" Underwood, for the inspiration. :)
*/
#define SDL_memcpy(dst, src, len) \
do { \
int u0, u1, u2; \
__asm__ __volatile__ ( \
"cld\n\t" \
"rep ; movsl\n\t" \
"testb $2,%b4\n\t" \
"je 1f\n\t" \
"movsw\n" \
"1:\ttestb $1,%b4\n\t" \
"je 2f\n\t" \
"movsb\n" \
"2:" \
: "=&c" (u0), "=&D" (u1), "=&S" (u2) \
: "0" ((unsigned)(len)/4), "q" (len), "1" (dst),"2" (src) \
: "memory" ); \
} while(0)
#define SDL_memcpy4(dst, src, len) \
do { \
int ecx, edi, esi; \
__asm__ __volatile__ ( \
"cld\n\t" \
"rep ; movsl" \
: "=&c" (ecx), "=&D" (edi), "=&S" (esi) \
: "0" ((unsigned)(len)), "1" (dst), "2" (src) \
: "memory" ); \
} while(0)
#define SDL_revcpy(dst, src, len) \
do { \
int u0, u1, u2; \
char *dstp = (char *)(dst); \
char *srcp = (char *)(src); \
int n = (len); \
if ( n >= 4 ) { \
__asm__ __volatile__ ( \
"std\n\t" \
"rep ; movsl\n\t" \
: "=&c" (u0), "=&D" (u1), "=&S" (u2) \
: "0" (n >> 2), \
"1" (dstp+(n-4)), "2" (srcp+(n-4)) \
: "memory" ); \
} \
switch (n & 3) { \
case 3: dstp[2] = srcp[2]; \
case 2: dstp[1] = srcp[1]; \
case 1: dstp[0] = srcp[0]; \
break; \
default: \
break; \
} \
} while(0)
#define SDL_memmove(dst, src, len) \
do { \
if ( (dst) < (src) ) { \
SDL_memcpy((dst), (src), (len)); \
} else { \
SDL_revcpy((dst), (src), (len)); \
} \
} while(0)
#define SDL_memset4(dst, val, len) \
do { \
int u0, u1, u2; \
__asm__ __volatile__ ( \
"cld\n\t" \
"rep ; stosl\n\t" \
: "=&D" (u0), "=&a" (u1), "=&c" (u2) \
: "0" (dst), "1" (val), "2" ((Uint32)(len)) \
: "memory" ); \
} while(0)
#endif /* GNU C and x86 */
/* If there are no optimized versions, define the normal versions */
#ifndef SDL_memcpy
#define SDL_memcpy(dst, src, len) memcpy(dst, src, len)
#endif
#ifndef SDL_memcpy4
#define SDL_memcpy4(dst, src, len) memcpy(dst, src, (len) << 2)
#endif
#ifndef SDL_revcpy
#define SDL_revcpy(dst, src, len) memmove(dst, src, len)
#endif
#ifndef SDL_memset4
#define SDL_memset4(dst, val, len) \
do { \
unsigned _count = (len); \
unsigned _n = (_count + 3) / 4; \
Uint32 *_p = (Uint32 *)(dst); \
Uint32 _val = (val); \
switch (_count % 4) { \
case 0: do { *_p++ = _val; \
case 3: *_p++ = _val; \
case 2: *_p++ = _val; \
case 1: *_p++ = _val; \
} while ( --_n ); \
} \
} while(0)
#endif
#endif /* _SDL_memops_h */

View File

@ -0,0 +1,615 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* General (mostly internal) pixel/color manipulation routines for SDL */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_endian.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_blit.h"
#include "SDL_pixels_c.h"
#include "SDL_RLEaccel_c.h"
/* Helper functions */
/*
* Allocate a pixel format structure and fill it according to the given info.
*/
SDL_PixelFormat *SDL_AllocFormat(int bpp,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
SDL_PixelFormat *format;
Uint32 mask;
/* Allocate an empty pixel format structure */
format = malloc(sizeof(*format));
if ( format == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
memset(format, 0, sizeof(*format));
format->alpha = SDL_ALPHA_OPAQUE;
/* Set up the format */
format->BitsPerPixel = bpp;
format->BytesPerPixel = (bpp+7)/8;
switch (bpp) {
case 1:
/* Create the 2 color black-white palette */
format->palette = (SDL_Palette *)malloc(
sizeof(SDL_Palette));
if ( format->palette == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
(format->palette)->ncolors = 2;
(format->palette)->colors = (SDL_Color *)malloc(
(format->palette)->ncolors*sizeof(SDL_Color));
if ( (format->palette)->colors == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
format->palette->colors[0].r = 0xFF;
format->palette->colors[0].g = 0xFF;
format->palette->colors[0].b = 0xFF;
format->palette->colors[1].r = 0x00;
format->palette->colors[1].g = 0x00;
format->palette->colors[1].b = 0x00;
format->Rloss = 8;
format->Gloss = 8;
format->Bloss = 8;
format->Aloss = 8;
format->Rshift = 0;
format->Gshift = 0;
format->Bshift = 0;
format->Ashift = 0;
format->Rmask = 0;
format->Gmask = 0;
format->Bmask = 0;
format->Amask = 0;
break;
case 4:
/* Create the 16 color VGA palette */
format->palette = (SDL_Palette *)malloc(
sizeof(SDL_Palette));
if ( format->palette == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
(format->palette)->ncolors = 16;
(format->palette)->colors = (SDL_Color *)malloc(
(format->palette)->ncolors*sizeof(SDL_Color));
if ( (format->palette)->colors == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
/* Punt for now, will this ever be used? */
memset((format->palette)->colors, 0,
(format->palette)->ncolors*sizeof(SDL_Color));
/* Palettized formats have no mask info */
format->Rloss = 8;
format->Gloss = 8;
format->Bloss = 8;
format->Aloss = 8;
format->Rshift = 0;
format->Gshift = 0;
format->Bshift = 0;
format->Ashift = 0;
format->Rmask = 0;
format->Gmask = 0;
format->Bmask = 0;
format->Amask = 0;
break;
case 8:
/* Create an empty 256 color palette */
format->palette = (SDL_Palette *)malloc(
sizeof(SDL_Palette));
if ( format->palette == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
(format->palette)->ncolors = 256;
(format->palette)->colors = (SDL_Color *)malloc(
(format->palette)->ncolors*sizeof(SDL_Color));
if ( (format->palette)->colors == NULL ) {
SDL_FreeFormat(format);
SDL_OutOfMemory();
return(NULL);
}
memset((format->palette)->colors, 0,
(format->palette)->ncolors*sizeof(SDL_Color));
/* Palettized formats have no mask info */
format->Rloss = 8;
format->Gloss = 8;
format->Bloss = 8;
format->Aloss = 8;
format->Rshift = 0;
format->Gshift = 0;
format->Bshift = 0;
format->Ashift = 0;
format->Rmask = 0;
format->Gmask = 0;
format->Bmask = 0;
format->Amask = 0;
break;
default:
/* No palette, just packed pixel info */
format->palette = NULL;
format->Rshift = 0;
format->Rloss = 8;
if ( Rmask ) {
for ( mask = Rmask; !(mask&0x01); mask >>= 1 )
++format->Rshift;
for ( ; (mask&0x01); mask >>= 1 )
--format->Rloss;
}
format->Gshift = 0;
format->Gloss = 8;
if ( Gmask ) {
for ( mask = Gmask; !(mask&0x01); mask >>= 1 )
++format->Gshift;
for ( ; (mask&0x01); mask >>= 1 )
--format->Gloss;
}
format->Bshift = 0;
format->Bloss = 8;
if ( Bmask ) {
for ( mask = Bmask; !(mask&0x01); mask >>= 1 )
++format->Bshift;
for ( ; (mask&0x01); mask >>= 1 )
--format->Bloss;
}
format->Ashift = 0;
format->Aloss = 8;
if ( Amask ) {
for ( mask = Amask; !(mask&0x01); mask >>= 1 )
++format->Ashift;
for ( ; (mask&0x01); mask >>= 1 )
--format->Aloss;
}
format->Rmask = Rmask;
format->Gmask = Gmask;
format->Bmask = Bmask;
format->Amask = Amask;
break;
}
/* Calculate some standard bitmasks, if necessary
* Note: This could conflict with an alpha mask, if given.
*/
if ( (bpp > 8) && !format->Rmask && !format->Gmask && !format->Bmask ) {
/* R-G-B */
if ( bpp > 24 )
bpp = 24;
format->Rloss = 8-(bpp/3);
format->Gloss = 8-(bpp/3)-(bpp%3);
format->Bloss = 8-(bpp/3);
format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3);
format->Gshift = (bpp/3);
format->Bshift = 0;
format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift);
format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift);
format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift);
}
return(format);
}
SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
if ( surface->format ) {
SDL_FreeFormat(surface->format);
SDL_FormatChanged(surface);
}
surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
return surface->format;
}
/*
* Change any previous mappings from/to the new surface format
*/
void SDL_FormatChanged(SDL_Surface *surface)
{
surface->format_version++;
SDL_InvalidateMap(surface->map);
}
/*
* Free a previously allocated format structure
*/
void SDL_FreeFormat(SDL_PixelFormat *format)
{
if ( format ) {
if ( format->palette ) {
if ( format->palette->colors ) {
free(format->palette->colors);
}
free(format->palette);
}
free(format);
}
}
/*
* Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
*/
void SDL_DitherColors(SDL_Color *colors, int bpp)
{
int i;
if(bpp != 8)
return; /* only 8bpp supported right now */
for(i = 0; i < 256; i++) {
int r, g, b;
/* map each bit field to the full [0, 255] interval,
so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
r = i & 0xe0;
r |= r >> 3 | r >> 6;
colors[i].r = r;
g = (i << 3) & 0xe0;
g |= g >> 3 | g >> 6;
colors[i].g = g;
b = i & 0x3;
b |= b << 2;
b |= b << 4;
colors[i].b = b;
}
}
/*
* Calculate the pad-aligned scanline width of a surface
*/
Uint16 SDL_CalculatePitch(SDL_Surface *surface)
{
Uint16 pitch;
/* Surface should be 4-byte aligned for speed */
pitch = surface->w*surface->format->BytesPerPixel;
switch (surface->format->BitsPerPixel) {
case 1:
pitch = (pitch+7)/8;
break;
case 4:
pitch = (pitch+1)/2;
break;
default:
break;
}
pitch = (pitch + 3) & ~3; /* 4-byte aligning */
return(pitch);
}
/*
* Match an RGB value to a particular palette index
*/
Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b)
{
/* Do colorspace distance matching */
unsigned int smallest;
unsigned int distance;
int rd, gd, bd;
int i;
Uint8 pixel=0;
smallest = ~0;
for ( i=0; i<pal->ncolors; ++i ) {
rd = pal->colors[i].r - r;
gd = pal->colors[i].g - g;
bd = pal->colors[i].b - b;
distance = (rd*rd)+(gd*gd)+(bd*bd);
if ( distance < smallest ) {
pixel = i;
if ( distance == 0 ) { /* Perfect match! */
break;
}
smallest = distance;
}
}
return(pixel);
}
/* Find the opaque pixel value corresponding to an RGB triple */
Uint32 SDL_MapRGB(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b)
{
if ( format->palette == NULL ) {
return (r >> format->Rloss) << format->Rshift
| (g >> format->Gloss) << format->Gshift
| (b >> format->Bloss) << format->Bshift
| format->Amask;
} else {
return SDL_FindColor(format->palette, r, g, b);
}
}
/* Find the pixel value corresponding to an RGBA quadruple */
Uint32 SDL_MapRGBA(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
if ( format->palette == NULL ) {
return (r >> format->Rloss) << format->Rshift
| (g >> format->Gloss) << format->Gshift
| (b >> format->Bloss) << format->Bshift
| ((a >> format->Aloss) << format->Ashift & format->Amask);
} else {
return SDL_FindColor(format->palette, r, g, b);
}
}
void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt,
Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
if ( fmt->palette == NULL ) {
/*
* This makes sure that the result is mapped to the
* interval [0..255], and the maximum value for each
* component is 255. This is important to make sure
* that white is indeed reported as (255, 255, 255),
* and that opaque alpha is 255.
* This only works for RGB bit fields at least 4 bit
* wide, which is almost always the case.
*/
unsigned rv, gv, bv, av;
rv = (pixel & fmt->Rmask) >> fmt->Rshift;
*r = (rv << fmt->Rloss) + (rv >> (8 - fmt->Rloss));
gv = (pixel & fmt->Gmask) >> fmt->Gshift;
*g = (gv << fmt->Gloss) + (gv >> (8 - fmt->Gloss));
bv = (pixel & fmt->Bmask) >> fmt->Bshift;
*b = (bv << fmt->Bloss) + (bv >> (8 - fmt->Bloss));
if(fmt->Amask) {
av = (pixel & fmt->Amask) >> fmt->Ashift;
*a = (av << fmt->Aloss) + (av >> (8 - fmt->Aloss));
} else
*a = SDL_ALPHA_OPAQUE;
} else {
*r = fmt->palette->colors[pixel].r;
*g = fmt->palette->colors[pixel].g;
*b = fmt->palette->colors[pixel].b;
*a = SDL_ALPHA_OPAQUE;
}
}
void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r,Uint8 *g,Uint8 *b)
{
if ( fmt->palette == NULL ) {
/* the note for SDL_GetRGBA above applies here too */
unsigned rv, gv, bv;
rv = (pixel & fmt->Rmask) >> fmt->Rshift;
*r = (rv << fmt->Rloss) + (rv >> (8 - fmt->Rloss));
gv = (pixel & fmt->Gmask) >> fmt->Gshift;
*g = (gv << fmt->Gloss) + (gv >> (8 - fmt->Gloss));
bv = (pixel & fmt->Bmask) >> fmt->Bshift;
*b = (bv << fmt->Bloss) + (bv >> (8 - fmt->Bloss));
} else {
*r = fmt->palette->colors[pixel].r;
*g = fmt->palette->colors[pixel].g;
*b = fmt->palette->colors[pixel].b;
}
}
/* Apply gamma to a set of colors - this is easy. :) */
void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output,
int ncolors)
{
int i;
for ( i=0; i<ncolors; ++i ) {
output[i].r = gamma[0*256 + colors[i].r] >> 8;
output[i].g = gamma[1*256 + colors[i].g] >> 8;
output[i].b = gamma[2*256 + colors[i].b] >> 8;
}
}
/* Map from Palette to Palette */
static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical)
{
Uint8 *map;
int i;
if ( identical ) {
if ( src->ncolors <= dst->ncolors ) {
/* If an identical palette, no need to map */
if ( memcmp(src->colors, dst->colors, src->ncolors*
sizeof(SDL_Color)) == 0 ) {
*identical = 1;
return(NULL);
}
}
*identical = 0;
}
map = (Uint8 *)malloc(src->ncolors);
if ( map == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
for ( i=0; i<src->ncolors; ++i ) {
map[i] = SDL_FindColor(dst,
src->colors[i].r, src->colors[i].g, src->colors[i].b);
}
return(map);
}
/* Map from Palette to BitField */
static Uint8 *Map1toN(SDL_Palette *src, SDL_PixelFormat *dst)
{
Uint8 *map;
int i;
int bpp;
unsigned alpha;
bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
map = (Uint8 *)malloc(src->ncolors*bpp);
if ( map == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
alpha = dst->Amask ? SDL_ALPHA_OPAQUE : 0;
/* We memory copy to the pixel map so the endianness is preserved */
for ( i=0; i<src->ncolors; ++i ) {
ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst,
src->colors[i].r, src->colors[i].g,
src->colors[i].b, alpha);
}
return(map);
}
/* Map from BitField to Dithered-Palette to Palette */
static Uint8 *MapNto1(SDL_PixelFormat *src, SDL_Palette *dst, int *identical)
{
/* Generate a 256 color dither palette */
SDL_Palette dithered;
SDL_Color colors[256];
dithered.ncolors = 256;
SDL_DitherColors(colors, 8);
dithered.colors = colors;
return(Map1to1(&dithered, dst, identical));
}
SDL_BlitMap *SDL_AllocBlitMap(void)
{
SDL_BlitMap *map;
/* Allocate the empty map */
map = (SDL_BlitMap *)malloc(sizeof(*map));
if ( map == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
memset(map, 0, sizeof(*map));
/* Allocate the software blit data */
map->sw_data = (struct private_swaccel *)malloc(sizeof(*map->sw_data));
if ( map->sw_data == NULL ) {
SDL_FreeBlitMap(map);
SDL_OutOfMemory();
return(NULL);
}
memset(map->sw_data, 0, sizeof(*map->sw_data));
/* It's ready to go */
return(map);
}
void SDL_InvalidateMap(SDL_BlitMap *map)
{
if ( ! map ) {
return;
}
map->dst = NULL;
map->format_version = (unsigned int)-1;
if ( map->table ) {
free(map->table);
map->table = NULL;
}
}
int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst)
{
SDL_PixelFormat *srcfmt;
SDL_PixelFormat *dstfmt;
SDL_BlitMap *map;
/* Clear out any previous mapping */
map = src->map;
if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
SDL_UnRLESurface(src, 1);
}
SDL_InvalidateMap(map);
/* Figure out what kind of mapping we're doing */
map->identity = 0;
srcfmt = src->format;
dstfmt = dst->format;
switch (srcfmt->BytesPerPixel) {
case 1:
switch (dstfmt->BytesPerPixel) {
case 1:
/* Palette --> Palette */
/* If both SDL_HWSURFACE, assume have same palette */
if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) {
map->identity = 1;
} else {
map->table = Map1to1(srcfmt->palette,
dstfmt->palette, &map->identity);
}
if ( ! map->identity ) {
if ( map->table == NULL ) {
return(-1);
}
}
if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel)
map->identity = 0;
break;
default:
/* Palette --> BitField */
map->table = Map1toN(srcfmt->palette, dstfmt);
if ( map->table == NULL ) {
return(-1);
}
break;
}
break;
default:
switch (dstfmt->BytesPerPixel) {
case 1:
/* BitField --> Palette */
map->table = MapNto1(srcfmt,
dstfmt->palette, &map->identity);
if ( ! map->identity ) {
if ( map->table == NULL ) {
return(-1);
}
}
map->identity = 0; /* Don't optimize to copy */
break;
default:
/* BitField --> BitField */
if ( FORMAT_EQUAL(srcfmt, dstfmt) )
map->identity = 1;
break;
}
break;
}
map->dst = dst;
map->format_version = dst->format_version;
/* Choose your blitters wisely */
return(SDL_CalculateBlit(src));
}
void SDL_FreeBlitMap(SDL_BlitMap *map)
{
if ( map ) {
SDL_InvalidateMap(map);
if ( map->sw_data != NULL ) {
free(map->sw_data);
}
free(map);
}
}

View File

@ -0,0 +1,50 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_pixels_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Useful functions and variables from SDL_pixel.c */
#include "SDL_blit.h"
/* Pixel format functions */
extern SDL_PixelFormat *SDL_AllocFormat(int bpp,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
extern SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
extern void SDL_FormatChanged(SDL_Surface *surface);
extern void SDL_FreeFormat(SDL_PixelFormat *format);
/* Blit mapping functions */
extern SDL_BlitMap *SDL_AllocBlitMap(void);
extern void SDL_InvalidateMap(SDL_BlitMap *map);
extern int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst);
extern void SDL_FreeBlitMap(SDL_BlitMap *map);
/* Miscellaneous functions */
extern Uint16 SDL_CalculatePitch(SDL_Surface *surface);
extern void SDL_DitherColors(SDL_Color *colors, int bpp);
extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b);
extern void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, int ncolors);

View File

@ -0,0 +1,305 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* This a stretch blit implementation based on ideas given to me by
Tomasz Cejner - thanks! :)
April 27, 2000 - Sam Lantinga
*/
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_blit.h"
/* This isn't ready for general consumption yet - it should be folded
into the general blitting mechanism.
*/
#if (defined(WIN32UNDEFINED) && !defined(_M_ALPHA) && !defined(_WIN32_WCE)) || \
defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT)
#define USE_ASM_STRETCH
#endif
#ifdef USE_ASM_STRETCH
#if defined(WIN32UNDEFINED) || defined(i386)
#define PREFIX16 0x66
#define STORE_BYTE 0xAA
#define STORE_WORD 0xAB
#define LOAD_BYTE 0xAC
#define LOAD_WORD 0xAD
#define RETURN 0xC3
#else
#error Need assembly opcodes for this architecture
#endif
#if defined(__ELF__) && defined(__GNUC__)
extern unsigned char _copy_row[4096] __attribute__ ((alias ("copy_row")));
#endif
static unsigned char copy_row[4096];
static int generate_rowbytes(int src_w, int dst_w, int bpp)
{
static struct {
int bpp;
int src_w;
int dst_w;
} last;
int i;
int pos, inc;
unsigned char *eip;
unsigned char load, store;
/* See if we need to regenerate the copy buffer */
if ( (src_w == last.src_w) &&
(dst_w == last.src_w) && (bpp == last.bpp) ) {
return(0);
}
last.bpp = bpp;
last.src_w = src_w;
last.dst_w = dst_w;
switch (bpp) {
case 1:
load = LOAD_BYTE;
store = STORE_BYTE;
break;
case 2:
case 4:
load = LOAD_WORD;
store = STORE_WORD;
break;
default:
SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp);
return(-1);
}
pos = 0x10000;
inc = (src_w << 16) / dst_w;
eip = copy_row;
for ( i=0; i<dst_w; ++i ) {
while ( pos >= 0x10000L ) {
if ( bpp == 2 ) {
*eip++ = PREFIX16;
}
*eip++ = load;
pos -= 0x10000L;
}
if ( bpp == 2 ) {
*eip++ = PREFIX16;
}
*eip++ = store;
pos += inc;
}
*eip++ = RETURN;
/* Verify that we didn't overflow (too late) */
if ( eip > (copy_row+sizeof(copy_row)) ) {
SDL_SetError("Copy buffer overflow");
return(-1);
}
return(0);
}
#else
#define DEFINE_COPY_ROW(name, type) \
void name(type *src, int src_w, type *dst, int dst_w) \
{ \
int i; \
int pos, inc; \
type pixel = 0; \
\
pos = 0x10000; \
inc = (src_w << 16) / dst_w; \
for ( i=dst_w; i>0; --i ) { \
while ( pos >= 0x10000L ) { \
pixel = *src++; \
pos -= 0x10000L; \
} \
*dst++ = pixel; \
pos += inc; \
} \
}
DEFINE_COPY_ROW(copy_row1, Uint8)
DEFINE_COPY_ROW(copy_row2, Uint16)
DEFINE_COPY_ROW(copy_row4, Uint32)
#endif /* USE_ASM_STRETCH */
/* The ASM code doesn't handle 24-bpp stretch blits */
void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w)
{
int i;
int pos, inc;
Uint8 pixel[3];
pos = 0x10000;
inc = (src_w << 16) / dst_w;
for ( i=dst_w; i>0; --i ) {
while ( pos >= 0x10000L ) {
pixel[0] = *src++;
pixel[1] = *src++;
pixel[2] = *src++;
pos -= 0x10000L;
}
*dst++ = pixel[0];
*dst++ = pixel[1];
*dst++ = pixel[2];
pos += inc;
}
}
/* Perform a stretch blit between two surfaces of the same format.
NOTE: This function is not safe to call from multiple threads!
*/
int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
int pos, inc;
int dst_width;
int dst_maxrow;
int src_row, dst_row;
Uint8 *srcp = NULL;
Uint8 *dstp;
SDL_Rect full_src;
SDL_Rect full_dst;
#if defined(USE_ASM_STRETCH) && defined(__GNUC__)
int u1, u2;
#endif
const int bpp = dst->format->BytesPerPixel;
if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
SDL_SetError("Only works with same format surfaces");
return(-1);
}
/* Verify the blit rectangles */
if ( srcrect ) {
if ( (srcrect->x < 0) || (srcrect->y < 0) ||
((srcrect->x+srcrect->w) > src->w) ||
((srcrect->y+srcrect->h) > src->h) ) {
SDL_SetError("Invalid source blit rectangle");
return(-1);
}
} else {
full_src.x = 0;
full_src.y = 0;
full_src.w = src->w;
full_src.h = src->h;
srcrect = &full_src;
}
if ( dstrect ) {
if ( (dstrect->x < 0) || (dstrect->y < 0) ||
((dstrect->x+dstrect->w) > dst->w) ||
((dstrect->y+dstrect->h) > dst->h) ) {
SDL_SetError("Invalid destination blit rectangle");
return(-1);
}
} else {
full_dst.x = 0;
full_dst.y = 0;
full_dst.w = dst->w;
full_dst.h = dst->h;
dstrect = &full_dst;
}
/* Set up the data... */
pos = 0x10000;
inc = (srcrect->h << 16) / dstrect->h;
src_row = srcrect->y;
dst_row = dstrect->y;
dst_width = dstrect->w*bpp;
#ifdef USE_ASM_STRETCH
/* Write the opcodes for this stretch */
if ( (bpp != 3) &&
(generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) {
return(-1);
}
#endif
/* Perform the stretch blit */
for ( dst_maxrow = dst_row+dstrect->h; dst_row<dst_maxrow; ++dst_row ) {
dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch)
+ (dstrect->x*bpp);
while ( pos >= 0x10000L ) {
srcp = (Uint8 *)src->pixels + (src_row*src->pitch)
+ (srcrect->x*bpp);
++src_row;
pos -= 0x10000L;
}
#ifdef USE_ASM_STRETCH
switch (bpp) {
case 3:
copy_row3(srcp, srcrect->w, dstp, dstrect->w);
break;
default:
#ifdef __GNUC__
__asm__ __volatile__ ("call _copy_row"
: "=&D" (u1), "=&S" (u2)
: "0" (dstp), "1" (srcp)
: "memory" );
#else
#ifdef WIN32UNDEFINED
{ void *code = &copy_row;
__asm {
push edi
push esi
mov edi, dstp
mov esi, srcp
call dword ptr code
pop esi
pop edi
}
}
#else
#error Need inline assembly for this compiler
#endif
#endif /* __GNUC__ */
break;
}
#else
switch (bpp) {
case 1:
copy_row1(srcp, srcrect->w, dstp, dstrect->w);
break;
case 2:
copy_row2((Uint16 *)srcp, srcrect->w,
(Uint16 *)dstp, dstrect->w);
break;
case 3:
copy_row3(srcp, srcrect->w, dstp, dstrect->w);
break;
case 4:
copy_row4((Uint32 *)srcp, srcrect->w,
(Uint32 *)dstp, dstrect->w);
break;
}
#endif
pos += inc;
}
return(0);
}

View File

@ -0,0 +1,33 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_stretch_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* Perform a stretch blit between two surfaces of the same format.
NOTE: This function is not safe to call from multiple threads!
*/
extern int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);

View File

@ -0,0 +1,816 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_cursor_c.h"
#include "SDL_blit.h"
#include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h"
#include "SDL_memops.h"
#include "SDL_leaks.h"
/* Public routines */
/*
* Create an empty RGB surface of the appropriate depth
*/
SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,
int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
SDL_Surface *screen;
SDL_Surface *surface;
/* Check to see if we desire the surface in video memory */
if ( video ) {
screen = SDL_PublicSurface;
} else {
screen = NULL;
}
if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {
if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {
flags |= SDL_HWSURFACE;
}
if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
if ( ! current_video->info.blit_hw_CC ) {
flags &= ~SDL_HWSURFACE;
}
}
if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
if ( ! current_video->info.blit_hw_A ) {
flags &= ~SDL_HWSURFACE;
}
}
} else {
flags &= ~SDL_HWSURFACE;
}
/* Allocate the surface */
surface = (SDL_Surface *)malloc(sizeof(*surface));
if ( surface == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
surface->flags = SDL_SWSURFACE;
if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
depth = screen->format->BitsPerPixel;
Rmask = screen->format->Rmask;
Gmask = screen->format->Gmask;
Bmask = screen->format->Bmask;
Amask = screen->format->Amask;
}
surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
if ( surface->format == NULL ) {
free(surface);
return(NULL);
}
if ( Amask ) {
surface->flags |= SDL_SRCALPHA;
}
surface->w = width;
surface->h = height;
surface->pitch = SDL_CalculatePitch(surface);
surface->pixels = NULL;
surface->offset = 0;
surface->hwdata = NULL;
surface->locked = 0;
surface->map = NULL;
surface->format_version = 0;
SDL_SetClipRect(surface, NULL);
/* Get the pixels */
if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) ||
(video->AllocHWSurface(this, surface) < 0) ) {
if ( surface->w && surface->h ) {
surface->pixels = malloc(surface->h*surface->pitch);
if ( surface->pixels == NULL ) {
SDL_FreeSurface(surface);
SDL_OutOfMemory();
return(NULL);
}
/* This is important for bitmaps */
memset(surface->pixels, 0, surface->h*surface->pitch);
}
}
/* Allocate an empty mapping */
surface->map = SDL_AllocBlitMap();
if ( surface->map == NULL ) {
SDL_FreeSurface(surface);
return(NULL);
}
/* The surface is ready to go */
surface->refcount = 1;
#ifdef CHECK_LEAKS
++surfaces_allocated;
#endif
return(surface);
}
/*
* Create an RGB surface from an existing memory buffer
*/
SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,
int width, int height, int depth, int pitch,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
SDL_Surface *surface;
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,
Rmask, Gmask, Bmask, Amask);
if ( surface != NULL ) {
surface->flags |= SDL_PREALLOC;
surface->pixels = pixels;
surface->w = width;
surface->h = height;
surface->pitch = pitch;
SDL_SetClipRect(surface, NULL);
}
return(surface);
}
/*
* Set the color key in a blittable surface
*/
int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key)
{
/* Sanity check the flag as it gets passed in */
if ( flag & SDL_SRCCOLORKEY ) {
if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
} else {
flag = SDL_SRCCOLORKEY;
}
} else {
flag = 0;
}
/* Optimize away operations that don't change anything */
if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&
(key == surface->format->colorkey) ) {
return(0);
}
/* UnRLE surfaces before we change the colorkey */
if ( surface->flags & SDL_RLEACCEL ) {
SDL_UnRLESurface(surface, 1);
}
if ( flag ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
surface->flags |= SDL_SRCCOLORKEY;
surface->format->colorkey = key;
if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
if ( (video->SetHWColorKey == NULL) ||
(video->SetHWColorKey(this, surface, key) < 0) ) {
surface->flags &= ~SDL_HWACCEL;
}
}
if ( flag & SDL_RLEACCELOK ) {
surface->flags |= SDL_RLEACCELOK;
} else {
surface->flags &= ~SDL_RLEACCELOK;
}
} else {
surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
surface->format->colorkey = 0;
}
SDL_InvalidateMap(surface->map);
return(0);
}
int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value)
{
Uint32 oldflags = surface->flags;
Uint32 oldalpha = surface->format->alpha;
/* Sanity check the flag as it gets passed in */
if ( flag & SDL_SRCALPHA ) {
if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
} else {
flag = SDL_SRCALPHA;
}
} else {
flag = 0;
}
/* Optimize away operations that don't change anything */
if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&
(!flag || value == oldalpha) ) {
return(0);
}
if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
SDL_UnRLESurface(surface, 1);
if ( flag ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
surface->flags |= SDL_SRCALPHA;
surface->format->alpha = value;
if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
if ( (video->SetHWAlpha == NULL) ||
(video->SetHWAlpha(this, surface, value) < 0) ) {
surface->flags &= ~SDL_HWACCEL;
}
}
if ( flag & SDL_RLEACCELOK ) {
surface->flags |= SDL_RLEACCELOK;
} else {
surface->flags &= ~SDL_RLEACCELOK;
}
} else {
surface->flags &= ~SDL_SRCALPHA;
surface->format->alpha = SDL_ALPHA_OPAQUE;
}
/*
* The representation for software surfaces is independent of
* per-surface alpha, so no need to invalidate the blit mapping
* if just the alpha value was changed. (If either is 255, we still
* need to invalidate.)
*/
if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
|| oldflags != surface->flags
|| (((oldalpha + 1) ^ (value + 1)) & 0x100))
SDL_InvalidateMap(surface->map);
return(0);
}
/*
* A function to calculate the intersection of two rectangles:
* return true if the rectangles intersect, false otherwise
*/
static __inline__
SDL_bool SDL_IntersectRect(SDL_Rect *A, SDL_Rect *B, SDL_Rect *intersection)
{
int Amin, Amax, Bmin, Bmax;
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if(Bmin > Amin)
Amin = Bmin;
intersection->x = Amin;
if(Bmax < Amax)
Amax = Bmax;
intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if(Bmin > Amin)
Amin = Bmin;
intersection->y = Amin;
if(Bmax < Amax)
Amax = Bmax;
intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
return (intersection->w && intersection->h);
}
/*
* Set the clipping rectangle for a blittable surface
*/
SDL_bool SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect)
{
SDL_Rect full_rect;
/* Don't do anything if there's no surface to act on */
if ( ! surface ) {
return SDL_FALSE;
}
/* Set up the full surface rectangle */
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = surface->w;
full_rect.h = surface->h;
/* Set the clipping rectangle */
if ( ! rect ) {
surface->clip_rect = full_rect;
return 1;
}
return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
}
void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
{
if ( surface && rect ) {
*rect = surface->clip_rect;
}
}
/*
* Set up a blit between two surfaces -- split into three parts:
* The upper part, SDL_UpperBlit(), performs clipping and rectangle
* verification. The lower part is a pointer to a low level
* accelerated blitting function.
*
* These parts are separated out and each used internally by this
* library in the optimimum places. They are exported so that if
* you know exactly what you are doing, you can optimize your code
* by calling the one(s) you need.
*/
int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
SDL_blit do_blit;
/* Check to make sure the blit mapping is valid */
if ( (src->map->dst != dst) ||
(src->map->dst->format_version != src->map->format_version) ) {
if ( SDL_MapSurface(src, dst) < 0 ) {
return(-1);
}
}
/* Figure out which blitter to use */
if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
do_blit = src->map->hw_blit;
} else {
do_blit = src->map->sw_blit;
}
return(do_blit(src, srcrect, dst, dstrect));
}
int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
SDL_Rect fulldst;
int srcx, srcy, w, h;
/* Make sure the surfaces aren't locked */
if ( ! src || ! dst ) {
SDL_SetError("SDL_UpperBlit: passed a NULL surface");
return(-1);
}
if ( src->locked || dst->locked ) {
SDL_SetError("Surfaces must not be locked during blit");
return(-1);
}
/* If the destination rectangle is NULL, use the entire dest surface */
if ( dstrect == NULL ) {
fulldst.x = fulldst.y = 0;
dstrect = &fulldst;
}
/* clip the source rectangle to the source surface */
if(srcrect) {
int maxw, maxh;
srcx = srcrect->x;
w = srcrect->w;
if(srcx < 0) {
w += srcx;
dstrect->x -= srcx;
srcx = 0;
}
maxw = src->w - srcx;
if(maxw < w)
w = maxw;
srcy = srcrect->y;
h = srcrect->h;
if(srcy < 0) {
h += srcy;
dstrect->y -= srcy;
srcy = 0;
}
maxh = src->h - srcy;
if(maxh < h)
h = maxh;
} else {
srcx = srcy = 0;
w = src->w;
h = src->h;
}
/* clip the destination rectangle against the clip rectangle */
{
SDL_Rect *clip = &dst->clip_rect;
int dx, dy;
dx = clip->x - dstrect->x;
if(dx > 0) {
w -= dx;
dstrect->x += dx;
srcx += dx;
}
dx = dstrect->x + w - clip->x - clip->w;
if(dx > 0)
w -= dx;
dy = clip->y - dstrect->y;
if(dy > 0) {
h -= dy;
dstrect->y += dy;
srcy += dy;
}
dy = dstrect->y + h - clip->y - clip->h;
if(dy > 0)
h -= dy;
}
if(w > 0 && h > 0) {
SDL_Rect sr;
sr.x = srcx;
sr.y = srcy;
sr.w = dstrect->w = w;
sr.h = dstrect->h = h;
return SDL_LowerBlit(src, &sr, dst, dstrect);
}
dstrect->w = dstrect->h = 0;
return 0;
}
/*
* This function performs a fast fill of the given rectangle with 'color'
*/
int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
int x, y;
Uint8 *row;
/* If 'dstrect' == NULL, then fill the whole surface */
if ( dstrect ) {
/* Perform clipping */
if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) {
return(0);
}
} else {
dstrect = &dst->clip_rect;
}
/* Check for hardware acceleration */
if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
video->info.blit_fill ) {
return(video->FillHWRect(this, dst, dstrect, color));
}
/* Perform software fill */
if ( SDL_LockSurface(dst) != 0 ) {
return(-1);
}
row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+
dstrect->x*dst->format->BytesPerPixel;
if ( dst->format->palette || (color == 0) ) {
x = dstrect->w*dst->format->BytesPerPixel;
if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) {
int n = x >> 2;
for ( y=dstrect->h; y; --y ) {
SDL_memset4(row, 0, n);
row += dst->pitch;
}
} else {
#ifdef __powerpc__
/*
* memset() on PPC (both glibc and codewarrior) uses
* the dcbz (Data Cache Block Zero) instruction, which
* causes an alignment exception if the destination is
* uncachable, so only use it on software surfaces
*/
if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
if(dstrect->w >= 8) {
/*
* 64-bit stores are probably most
* efficient to uncached video memory
*/
double fill;
memset(&fill, color, (sizeof fill));
for(y = dstrect->h; y; y--) {
Uint8 *d = row;
unsigned n = x;
unsigned nn;
Uint8 c = color;
double f = fill;
while((unsigned long)d
& (sizeof(double) - 1)) {
*d++ = c;
n--;
}
nn = n / (sizeof(double) * 4);
while(nn) {
((double *)d)[0] = f;
((double *)d)[1] = f;
((double *)d)[2] = f;
((double *)d)[3] = f;
d += 4*sizeof(double);
nn--;
}
n &= ~(sizeof(double) * 4 - 1);
nn = n / sizeof(double);
while(nn) {
*(double *)d = f;
d += sizeof(double);
nn--;
}
n &= ~(sizeof(double) - 1);
while(n) {
*d++ = c;
n--;
}
row += dst->pitch;
}
} else {
/* narrow boxes */
for(y = dstrect->h; y; y--) {
Uint8 *d = row;
Uint8 c = color;
int n = x;
while(n) {
*d++ = c;
n--;
}
row += dst->pitch;
}
}
} else
#endif /* __powerpc__ */
{
for(y = dstrect->h; y; y--) {
memset(row, color, x);
row += dst->pitch;
}
}
}
} else {
switch (dst->format->BytesPerPixel) {
case 2:
for ( y=dstrect->h; y; --y ) {
Uint16 *pixels = (Uint16 *)row;
Uint16 c = color;
Uint32 cc = (Uint32)c << 16 | c;
int n = dstrect->w;
if((unsigned long)pixels & 3) {
*pixels++ = c;
n--;
}
if(n >> 1)
SDL_memset4(pixels, cc, n >> 1);
if(n & 1)
pixels[n - 1] = c;
row += dst->pitch;
}
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
color <<= 8;
for ( y=dstrect->h; y; --y ) {
Uint8 *pixels = row;
for ( x=dstrect->w; x; --x ) {
memcpy(pixels, &color, 3);
pixels += 3;
}
row += dst->pitch;
}
break;
case 4:
for(y = dstrect->h; y; --y) {
SDL_memset4(row, color, dstrect->w);
row += dst->pitch;
}
break;
}
}
SDL_UnlockSurface(dst);
/* We're done! */
return(0);
}
/*
* Lock a surface to directly access the pixels
* -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
* Instead, use:
* if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
* video->LockHWSurface(video, surface);
*/
int SDL_LockSurface (SDL_Surface *surface)
{
if ( ! surface->locked ) {
/* Perform the lock */
if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
if ( video->LockHWSurface(this, surface) < 0 ) {
return(-1);
}
}
if ( surface->flags & SDL_RLEACCEL ) {
SDL_UnRLESurface(surface, 1);
surface->flags |= SDL_RLEACCEL; /* save accel'd state */
}
/* This needs to be done here in case pixels changes value */
surface->pixels = (Uint8 *)surface->pixels + surface->offset;
}
/* Increment the surface lock count, for recursive locks */
++surface->locked;
/* Ready to go.. */
return(0);
}
/*
* Unlock a previously locked surface
* -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
* Instead, use:
* if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
* video->UnlockHWSurface(video, surface);
*/
void SDL_UnlockSurface (SDL_Surface *surface)
{
/* Only perform an unlock if we are locked */
if ( ! surface->locked || (--surface->locked > 0) ) {
return;
}
/* Perform the unlock */
surface->pixels = (Uint8 *)surface->pixels - surface->offset;
/* Unlock hardware or accelerated surfaces */
if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
video->UnlockHWSurface(this, surface);
} else {
/* Update RLE encoded surface with new data */
if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
surface->flags &= ~SDL_RLEACCEL; /* stop lying */
SDL_RLESurface(surface);
}
}
}
/*
* Convert a surface into the specified pixel format.
*/
SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface,
SDL_PixelFormat *format, Uint32 flags)
{
SDL_Surface *convert;
Uint32 colorkey = 0;
Uint8 alpha = 0;
Uint32 surface_flags;
SDL_Rect bounds;
/* Check for empty destination palette! (results in empty image) */
if ( format->palette != NULL ) {
int i;
for ( i=0; i<format->palette->ncolors; ++i ) {
if ( (format->palette->colors[i].r != 0) ||
(format->palette->colors[i].g != 0) ||
(format->palette->colors[i].b != 0) )
break;
}
if ( i == format->palette->ncolors ) {
SDL_SetError("Empty destination palette");
return(NULL);
}
}
/* Create a new surface with the desired format */
convert = SDL_CreateRGBSurface(flags,
surface->w, surface->h, format->BitsPerPixel,
format->Rmask, format->Gmask, format->Bmask, format->Amask);
if ( convert == NULL ) {
return(NULL);
}
/* Copy the palette if any */
if ( format->palette && convert->format->palette ) {
memcpy(convert->format->palette->colors,
format->palette->colors,
format->palette->ncolors*sizeof(SDL_Color));
convert->format->palette->ncolors = format->palette->ncolors;
}
/* Save the original surface color key and alpha */
surface_flags = surface->flags;
if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
/* Convert colourkeyed surfaces to RGBA if requested */
if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
&& format->Amask) {
surface_flags &= ~SDL_SRCCOLORKEY;
} else {
colorkey = surface->format->colorkey;
SDL_SetColorKey(surface, 0, 0);
}
}
if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
alpha = surface->format->alpha;
SDL_SetAlpha(surface, 0, 0);
}
/* Copy over the image data */
bounds.x = 0;
bounds.y = 0;
bounds.w = surface->w;
bounds.h = surface->h;
SDL_LowerBlit(surface, &bounds, convert, &bounds);
/* Clean up the original surface, and update converted surface */
if ( convert != NULL ) {
SDL_SetClipRect(convert, &surface->clip_rect);
}
if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
if ( convert != NULL ) {
Uint8 keyR, keyG, keyB;
SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
SDL_MapRGB(convert->format, keyR, keyG, keyB));
}
SDL_SetColorKey(surface, cflags, colorkey);
}
if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
if ( convert != NULL ) {
SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
alpha);
}
SDL_SetAlpha(surface, aflags, alpha);
}
/* We're ready to go! */
return(convert);
}
/*
* Free a surface created by the above function.
*/
void SDL_FreeSurface (SDL_Surface *surface)
{
/* Free anything that's not NULL, and not the screen surface */
if ((surface == NULL) ||
(current_video &&
((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
return;
}
if ( --surface->refcount > 0 ) {
return;
}
if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
SDL_UnRLESurface(surface, 0);
}
if ( surface->format ) {
SDL_FreeFormat(surface->format);
surface->format = NULL;
}
if ( surface->map != NULL ) {
SDL_FreeBlitMap(surface->map);
surface->map = NULL;
}
if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
video->FreeHWSurface(this, surface);
}
if ( surface->pixels &&
((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) {
free(surface->pixels);
}
free(surface);
#ifdef CHECK_LEAKS
--surfaces_allocated;
#endif
}

View File

@ -0,0 +1,399 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_sysvideo.h,v 1.6 2001/06/19 13:33:53 hercules Exp $";
#endif
#ifndef _SDL_sysvideo_h
#define _SDL_sysvideo_h
#include "SDL_mouse.h"
#define SDL_PROTOTYPES_ONLY
#include "SDL_syswm.h"
#undef SDL_PROTOTYPES_ONLY
/* This file prototypes the video driver implementation.
This is designed to be easily converted to C++ in the future.
*/
/* OpenGL is pretty much available on all Windows systems */
#ifdef WIN32UNDEFINED
#ifndef _WIN32_WCE
#define HAVE_OPENGL
#endif
#include <windows.h>
#endif
#ifdef HAVE_OPENGL
#ifdef MACOSX
#include <OpenGL/gl.h> /* OpenGL.framework */
#else
#include <GL/gl.h>
#endif /* MACOSX */
#endif /* HAVE_OPENGL */
/* The SDL video driver */
typedef struct SDL_VideoDevice SDL_VideoDevice;
/* Define the SDL video driver structure */
#define _THIS SDL_VideoDevice *_this
#ifndef _STATUS
#define _STATUS SDL_status *status
#endif
struct SDL_VideoDevice {
/* * * */
/* The name of this video driver */
const char *name;
/* * * */
/* Initialization/Query functions */
/* Initialize the native video subsystem, filling 'vformat' with the
"best" display pixel format, returning 0 or -1 if there's an error.
*/
int (*VideoInit)(_THIS, SDL_PixelFormat *vformat);
/* List the available video modes for the given pixel format, sorted
from largest to smallest.
*/
SDL_Rect **(*ListModes)(_THIS, SDL_PixelFormat *format, Uint32 flags);
/* 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 *(*SetVideoMode)(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags);
/* Toggle the fullscreen mode */
int (*ToggleFullScreen)(_THIS, int on);
/* This is called after the video mode has been set, to get the
initial mouse state. It should queue events as necessary to
properly represent the current mouse focus and position.
*/
void (*UpdateMouse)(_THIS);
/* Create a YUV video surface (possibly overlay) of the given
format. The hardware should be able to perform at least 2x
scaling on display.
*/
SDL_Overlay *(*CreateYUVOverlay)(_THIS, int width, int height,
Uint32 format, SDL_Surface *display);
/* 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 (*SetColors)(_THIS, int firstcolor, int ncolors,
SDL_Color *colors);
/* This pointer should exist in the native video subsystem and should
point to an appropriate update function for the current video mode
*/
void (*UpdateRects)(_THIS, int numrects, SDL_Rect *rects);
/* Reverse the effects VideoInit() -- called if VideoInit() fails
or if the application is shutting down the video subsystem.
*/
void (*VideoQuit)(_THIS);
/* * * */
/* Hardware acceleration functions */
/* Information about the video hardware */
SDL_VideoInfo info;
/* Allocates a surface in video memory */
int (*AllocHWSurface)(_THIS, SDL_Surface *surface);
/* Sets the hardware accelerated blit function, if any, based
on the current flags of the surface (colorkey, alpha, etc.)
*/
int (*CheckHWBlit)(_THIS, SDL_Surface *src, SDL_Surface *dst);
/* Fills a surface rectangle with the given color */
int (*FillHWRect)(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
/* Sets video mem colorkey and accelerated blit function */
int (*SetHWColorKey)(_THIS, SDL_Surface *surface, Uint32 key);
/* Sets per surface hardware alpha value */
int (*SetHWAlpha)(_THIS, SDL_Surface *surface, Uint8 value);
/* Returns a readable/writable surface */
int (*LockHWSurface)(_THIS, SDL_Surface *surface);
void (*UnlockHWSurface)(_THIS, SDL_Surface *surface);
/* Performs hardware flipping */
int (*FlipHWSurface)(_THIS, SDL_Surface *surface);
/* Frees a previously allocated video surface */
void (*FreeHWSurface)(_THIS, SDL_Surface *surface);
/* * * */
/* Gamma support */
Uint16 *gamma;
/* Set the gamma correction directly (emulated with gamma ramps) */
int (*SetGamma)(_THIS, float red, float green, float blue);
/* Get the gamma correction directly (emulated with gamma ramps) */
int (*GetGamma)(_THIS, float *red, float *green, float *blue);
/* Set the gamma ramp */
int (*SetGammaRamp)(_THIS, Uint16 *ramp);
/* Get the gamma ramp */
int (*GetGammaRamp)(_THIS, Uint16 *ramp);
/* * * */
/* OpenGL support */
/* Sets the dll to use for OpenGL and loads it */
int (*GL_LoadLibrary)(_THIS, const char *path);
/* Retrieves the address of a function in the gl library */
void* (*GL_GetProcAddress)(_THIS, const char *proc);
/* Get attribute information from the windowing system. */
int (*GL_GetAttribute)(_THIS, SDL_GLattr attrib, int* value);
/* Make the context associated with this driver current */
int (*GL_MakeCurrent)(_THIS);
/* Swap the current buffers in double buffer mode. */
void (*GL_SwapBuffers)(_THIS);
/* OpenGL functions for SDL_OPENGLBLIT */
#ifdef HAVE_OPENGL
#ifndef WIN32UNDEFINED
#define WINAPI
#endif
#define SDL_PROC(ret,func,params) ret (WINAPI *func) params;
#include "SDL_glfuncs.h"
#undef SDL_PROC
/* Texture id */
GLuint texture;
#endif
int is_32bit;
/* * * */
/* Window manager functions */
/* Set the title and icon text */
void (*SetCaption)(_THIS, const char *title, const char *icon);
/* Set the window icon image */
void (*SetIcon)(_THIS, SDL_Surface *icon, Uint8 *mask);
/* Iconify the window.
This function returns 1 if there is a window manager and the
window was actually iconified, it returns 0 otherwise.
*/
int (*IconifyWindow)(_THIS);
/* Grab or ungrab keyboard and mouse input */
SDL_GrabMode (*GrabInput)(_THIS, SDL_GrabMode mode);
/* Get some platform dependent window information */
int (*GetWMInfo)(_THIS, SDL_SysWMinfo *info);
/* * * */
/* Cursor manager functions */
/* Free a window manager cursor
This function can be NULL if CreateWMCursor is also NULL.
*/
void (*FreeWMCursor)(_THIS, WMcursor *cursor);
/* If not NULL, create a black/white window manager cursor */
WMcursor *(*CreateWMCursor)(_THIS,
Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
/* Show the specified cursor, or hide if cursor is NULL */
int (*ShowWMCursor)(_THIS, WMcursor *cursor);
/* Warp the window manager cursor to (x,y)
If NULL, a mouse motion event is posted internally.
*/
void (*WarpWMCursor)(_THIS, Uint16 x, Uint16 y);
/* If not NULL, this is called when a mouse motion event occurs */
void (*MoveWMCursor)(_THIS, int x, int y);
/* Determine whether the mouse should be in relative mode or not.
This function is called when the input grab state or cursor
visibility state changes.
If the cursor is not visible, and the input is grabbed, the
driver can place the mouse in relative mode, which may result
in higher accuracy sampling of the pointer motion.
*/
void (*CheckMouseMode)(_THIS);
/* * * */
/* Event manager functions */
/* Initialize keyboard mapping for this driver */
void (*InitOSKeymap)(_THIS);
/* Handle any queued OS events */
void (*PumpEvents)(_THIS);
/* * * */
/* Data common to all drivers */
SDL_Surface *screen;
SDL_Surface *shadow;
SDL_Surface *visible;
SDL_Palette *physpal; /* physical palette, if != logical palette */
SDL_Color *gammacols; /* gamma-corrected colours, or NULL */
char *wm_title;
char *wm_icon;
int offset_x;
int offset_y;
SDL_GrabMode input_grab;
/* Driver information flags */
int handles_any_size; /* Driver handles any size video mode */
/* * * */
/* Data used by the GL drivers */
struct {
int red_size;
int green_size;
int blue_size;
int alpha_size;
int depth_size;
int buffer_size;
int stencil_size;
int double_buffer;
int accum_red_size;
int accum_green_size;
int accum_blue_size;
int accum_alpha_size;
int driver_loaded;
char driver_path[256];
void* dll_handle;
} gl_config;
/* * * */
/* Data private to this driver */
struct SDL_PrivateVideoData *hidden;
struct SDL_PrivateGLData *gl_data;
/* * * */
/* The function used to dispose of this structure */
void (*free)(_THIS);
};
#undef _THIS
typedef struct VideoBootStrap {
const char *name;
const char *desc;
int (*available)(void);
SDL_VideoDevice *(*create)(int devindex);
} VideoBootStrap;
#ifdef ENABLE_X11
extern VideoBootStrap X11_bootstrap;
#endif
#ifdef ENABLE_DGA
extern VideoBootStrap DGA_bootstrap;
#endif
#ifdef ENABLE_NANOX
extern VideoBootStrap NX_bootstrap;
#endif
#ifdef ENABLE_FBCON
extern VideoBootStrap FBCON_bootstrap;
#endif
#ifdef ENABLE_PS2GS
extern VideoBootStrap PS2GS_bootstrap;
#endif
#ifdef ENABLE_GGI
extern VideoBootStrap GGI_bootstrap;
#endif
#ifdef ENABLE_VGL
extern VideoBootStrap VGL_bootstrap;
#endif
#ifdef ENABLE_SVGALIB
extern VideoBootStrap SVGALIB_bootstrap;
#endif
#ifdef ENABLE_AALIB
extern VideoBootStrap AALIB_bootstrap;
#endif
#ifdef ENABLE_WINDIB
extern VideoBootStrap WINDIB_bootstrap;
#endif
#ifdef ENABLE_DIRECTX
extern VideoBootStrap DIRECTX_bootstrap;
#endif
#ifdef ENABLE_BWINDOW
extern VideoBootStrap BWINDOW_bootstrap;
#endif
#ifdef ENABLE_DUMMYVIDEO
extern VideoBootStrap DUMMY_bootstrap;
#endif
#ifdef ENABLE_PHOTON
extern VideoBootStrap ph_bootstrap;
#endif
/* MacOS X gets the proper defines from configure */
#if defined(macintosh) && !defined(MACOSX)
#define ENABLE_TOOLBOX
#if !TARGET_API_MAC_CARBON
#define ENABLE_DRAWSPROCKET
#endif
#endif
#ifdef ENABLE_TOOLBOX
extern VideoBootStrap TOOLBOX_bootstrap;
#endif
#ifdef ENABLE_DRAWSPROCKET
extern VideoBootStrap DSp_bootstrap;
#endif
#ifdef ENABLE_QUARTZ
extern VideoBootStrap QZ_bootstrap;
#endif
#ifdef ENABLE_CYBERGRAPHICS
extern VideoBootStrap CGX_bootstrap;
#endif
#ifdef ENABLE_MENUETOS
extern VideoBootStrap mosvideo_bootstrab;
#endif
/* This is the current video device */
extern SDL_VideoDevice *current_video;
#define SDL_VideoSurface (current_video->screen)
#define SDL_ShadowSurface (current_video->shadow)
#define SDL_PublicSurface (current_video->visible)
#endif /* _SDL_sysvideo_h */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
/* This is the implementation of the YUV video surface support */
#include <stdlib.h>
#include <string.h>
#include "SDL_getenv.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_yuvfuncs.h"
#include "SDL_yuv_sw_c.h"
SDL_Overlay *SDL_CreateYUVOverlay(int w, int h, Uint32 format,
SDL_Surface *display)
{
SDL_VideoDevice *video = current_video;
SDL_VideoDevice *this = current_video;
const char *yuv_hwaccel;
SDL_Overlay *overlay;
overlay = NULL;
/* Display directly on video surface, if possible */
if ( getenv("SDL_VIDEO_YUV_DIRECT") ) {
if ( (display == SDL_PublicSurface) &&
((SDL_VideoSurface->format->BytesPerPixel == 2) ||
(SDL_VideoSurface->format->BytesPerPixel == 4)) ) {
display = SDL_VideoSurface;
}
}
yuv_hwaccel = getenv("SDL_VIDEO_YUV_HWACCEL");
if ( ((display == SDL_VideoSurface) && video->CreateYUVOverlay) &&
(!yuv_hwaccel || (atoi(yuv_hwaccel) > 0)) ) {
overlay = video->CreateYUVOverlay(this, w, h, format, display);
}
/* If hardware YUV overlay failed ... */
if ( overlay == NULL ) {
overlay = SDL_CreateYUV_SW(this, w, h, format, display);
}
return overlay;
}
int SDL_LockYUVOverlay(SDL_Overlay *overlay)
{
return overlay->hwfuncs->Lock(current_video, overlay);
}
void SDL_UnlockYUVOverlay(SDL_Overlay *overlay)
{
overlay->hwfuncs->Unlock(current_video, overlay);
}
int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect)
{
return overlay->hwfuncs->Display(current_video, overlay, dstrect);
}
void SDL_FreeYUVOverlay(SDL_Overlay *overlay)
{
if ( overlay ) {
if ( overlay->hwfuncs ) {
overlay->hwfuncs->FreeHW(current_video, overlay);
}
free(overlay);
}
}

View File

@ -0,0 +1,418 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT)
#include "SDL_types.h"
#ifdef __ELF__
#define ASM_VAR(X) _##X
#else
#define ASM_VAR(X) X
#endif
#define static
static unsigned int ASM_VAR(MMX_0080w)[] = {0x00800080, 0x00800080};
static unsigned int ASM_VAR(MMX_00FFw)[] = {0x00ff00ff, 0x00ff00ff};
static unsigned int ASM_VAR(MMX_FF00w)[] = {0xff00ff00, 0xff00ff00};
static unsigned short ASM_VAR(MMX_Ycoeff)[] = {0x004a, 0x004a, 0x004a, 0x004a};
static unsigned short ASM_VAR(MMX_UbluRGB)[] = {0x0072, 0x0072, 0x0072, 0x0072};
static unsigned short ASM_VAR(MMX_VredRGB)[] = {0x0059, 0x0059, 0x0059, 0x0059};
static unsigned short ASM_VAR(MMX_UgrnRGB)[] = {0xffea, 0xffea, 0xffea, 0xffea};
static unsigned short ASM_VAR(MMX_VgrnRGB)[] = {0xffd2, 0xffd2, 0xffd2, 0xffd2};
static unsigned short ASM_VAR(MMX_Ublu5x5)[] = {0x0081, 0x0081, 0x0081, 0x0081};
static unsigned short ASM_VAR(MMX_Vred5x5)[] = {0x0066, 0x0066, 0x0066, 0x0066};
static unsigned short ASM_VAR(MMX_Ugrn555)[] = {0xffe7, 0xffe7, 0xffe7, 0xffe7};
static unsigned short ASM_VAR(MMX_Vgrn555)[] = {0xffcc, 0xffcc, 0xffcc, 0xffcc};
static unsigned short ASM_VAR(MMX_Ugrn565)[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8};
static unsigned short ASM_VAR(MMX_Vgrn565)[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd};
static unsigned short ASM_VAR(MMX_red555)[] = {0x7c00, 0x7c00, 0x7c00, 0x7c00};
static unsigned short ASM_VAR(MMX_red565)[] = {0xf800, 0xf800, 0xf800, 0xf800};
static unsigned short ASM_VAR(MMX_grn555)[] = {0x03e0, 0x03e0, 0x03e0, 0x03e0};
static unsigned short ASM_VAR(MMX_grn565)[] = {0x07e0, 0x07e0, 0x07e0, 0x07e0};
static unsigned short ASM_VAR(MMX_blu5x5)[] = {0x001f, 0x001f, 0x001f, 0x001f};
/**
This MMX assembler is my first assembler/MMX program ever.
Thus it maybe buggy.
Send patches to:
mvogt@rhrk.uni-kl.de
After it worked fine I have "obfuscated" the code a bit to have
more parallism in the MMX units. This means I moved
initilisation around and delayed other instruction.
Performance measurement did not show that this brought any advantage
but in theory it _should_ be faster this way.
The overall performanve gain to the C based dither was 30%-40%.
The MMX routine calculates 256bit=8RGB values in each cycle
(4 for row1 & 4 for row2)
The red/green/blue.. coefficents are taken from the mpeg_play
player. They look nice, but I dont know if you can have
better values, to avoid integer rounding errors.
IMPORTANT:
==========
It is a requirement that the cr/cb/lum are 8 byte aligned and
the out are 16byte aligned or you will/may get segfaults
*/
void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod )
{
Uint32 *row1;
Uint32 *row2;
unsigned char* y = lum +cols*rows; // Pointer to the end
int x=0;
row1 = (Uint32 *)out; // 32 bit target
row2 = (Uint32 *)out+cols+mod; // start of second row
mod = (mod+cols+mod)*4; // increment for row1 in byte
__asm__ __volatile__ (
/* We don't really care about PIC - the code should be rewritten to use
relative addressing for the static tables, so right now we take the
COW hit on the pages this code resides. Big deal.
This spill is just to reduce register pressure in the PIC case. */
"pushl %%ebx\n"
"movl %0, %%ebx\n"
".align 8\n"
"1:\n"
// create Cr (result in mm1)
"movd (%%ebx), %%mm1\n" // 0 0 0 0 v3 v2 v1 v0
"pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00
"movd (%2), %%mm2\n" // 0 0 0 0 l3 l2 l1 l0
"punpcklbw %%mm7,%%mm1\n" // 0 v3 0 v2 00 v1 00 v0
"punpckldq %%mm1,%%mm1\n" // 00 v1 00 v0 00 v1 00 v0
"psubw _MMX_0080w,%%mm1\n" // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0
// create Cr_g (result in mm0)
"movq %%mm1,%%mm0\n" // r1 r1 r0 r0 r1 r1 r0 r0
"pmullw _MMX_VgrnRGB,%%mm0\n"// red*-46dec=0.7136*64
"pmullw _MMX_VredRGB,%%mm1\n"// red*89dec=1.4013*64
"psraw $6, %%mm0\n" // red=red/64
"psraw $6, %%mm1\n" // red=red/64
// create L1 L2 (result in mm2,mm4)
// L2=lum+cols
"movq (%2,%4),%%mm3\n" // 0 0 0 0 L3 L2 L1 L0
"punpckldq %%mm3,%%mm2\n" // L3 L2 L1 L0 l3 l2 l1 l0
"movq %%mm2,%%mm4\n" // L3 L2 L1 L0 l3 l2 l1 l0
"pand _MMX_FF00w,%%mm2\n" // L3 0 L1 0 l3 0 l1 0
"pand _MMX_00FFw,%%mm4\n" // 0 L2 0 L0 0 l2 0 l0
"psrlw $8,%%mm2\n" // 0 L3 0 L1 0 l3 0 l1
// create R (result in mm6)
"movq %%mm2,%%mm5\n" // 0 L3 0 L1 0 l3 0 l1
"movq %%mm4,%%mm6\n" // 0 L2 0 L0 0 l2 0 l0
"paddsw %%mm1, %%mm5\n" // lum1+red:x R3 x R1 x r3 x r1
"paddsw %%mm1, %%mm6\n" // lum1+red:x R2 x R0 x r2 x r0
"packuswb %%mm5,%%mm5\n" // R3 R1 r3 r1 R3 R1 r3 r1
"packuswb %%mm6,%%mm6\n" // R2 R0 r2 r0 R2 R0 r2 r0
"pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00
"punpcklbw %%mm5,%%mm6\n" // R3 R2 R1 R0 r3 r2 r1 r0
// create Cb (result in mm1)
"movd (%1), %%mm1\n" // 0 0 0 0 u3 u2 u1 u0
"punpcklbw %%mm7,%%mm1\n" // 0 u3 0 u2 00 u1 00 u0
"punpckldq %%mm1,%%mm1\n" // 00 u1 00 u0 00 u1 00 u0
"psubw _MMX_0080w,%%mm1\n" // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0
// create Cb_g (result in mm5)
"movq %%mm1,%%mm5\n" // u1 u1 u0 u0 u1 u1 u0 u0
"pmullw _MMX_UgrnRGB,%%mm5\n" // blue*-109dec=1.7129*64
"pmullw _MMX_UbluRGB,%%mm1\n" // blue*114dec=1.78125*64
"psraw $6, %%mm5\n" // blue=red/64
"psraw $6, %%mm1\n" // blue=blue/64
// create G (result in mm7)
"movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1
"movq %%mm4,%%mm7\n" // 0 L2 0 L0 0 l2 0 l1
"paddsw %%mm5, %%mm3\n" // lum1+Cb_g:x G3t x G1t x g3t x g1t
"paddsw %%mm5, %%mm7\n" // lum1+Cb_g:x G2t x G0t x g2t x g0t
"paddsw %%mm0, %%mm3\n" // lum1+Cr_g:x G3 x G1 x g3 x g1
"paddsw %%mm0, %%mm7\n" // lum1+blue:x G2 x G0 x g2 x g0
"packuswb %%mm3,%%mm3\n" // G3 G1 g3 g1 G3 G1 g3 g1
"packuswb %%mm7,%%mm7\n" // G2 G0 g2 g0 G2 G0 g2 g0
"punpcklbw %%mm3,%%mm7\n" // G3 G2 G1 G0 g3 g2 g1 g0
// create B (result in mm5)
"movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1
"movq %%mm4,%%mm5\n" // 0 L2 0 L0 0 l2 0 l1
"paddsw %%mm1, %%mm3\n" // lum1+blue:x B3 x B1 x b3 x b1
"paddsw %%mm1, %%mm5\n" // lum1+blue:x B2 x B0 x b2 x b0
"packuswb %%mm3,%%mm3\n" // B3 B1 b3 b1 B3 B1 b3 b1
"packuswb %%mm5,%%mm5\n" // B2 B0 b2 b0 B2 B0 b2 b0
"punpcklbw %%mm3,%%mm5\n" // B3 B2 B1 B0 b3 b2 b1 b0
// fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
"pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
"pxor %%mm4,%%mm4\n" // 0 0 0 0 0 0 0 0
"movq %%mm6,%%mm1\n" // R3 R2 R1 R0 r3 r2 r1 r0
"movq %%mm5,%%mm3\n" // B3 B2 B1 B0 b3 b2 b1 b0
// process lower lum
"punpcklbw %%mm4,%%mm1\n" // 0 r3 0 r2 0 r1 0 r0
"punpcklbw %%mm4,%%mm3\n" // 0 b3 0 b2 0 b1 0 b0
"movq %%mm1,%%mm2\n" // 0 r3 0 r2 0 r1 0 r0
"movq %%mm3,%%mm0\n" // 0 b3 0 b2 0 b1 0 b0
"punpcklwd %%mm1,%%mm3\n" // 0 r1 0 b1 0 r0 0 b0
"punpckhwd %%mm2,%%mm0\n" // 0 r3 0 b3 0 r2 0 b2
"pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
"movq %%mm7,%%mm1\n" // G3 G2 G1 G0 g3 g2 g1 g0
"punpcklbw %%mm1,%%mm2\n" // g3 0 g2 0 g1 0 g0 0
"punpcklwd %%mm4,%%mm2\n" // 0 0 g1 0 0 0 g0 0
"por %%mm3, %%mm2\n" // 0 r1 g1 b1 0 r0 g0 b0
"movq %%mm2,(%3)\n" // wrote out ! row1
"pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
"punpcklbw %%mm1,%%mm4\n" // g3 0 g2 0 g1 0 g0 0
"punpckhwd %%mm2,%%mm4\n" // 0 0 g3 0 0 0 g2 0
"por %%mm0, %%mm4\n" // 0 r3 g3 b3 0 r2 g2 b2
"movq %%mm4,8(%3)\n" // wrote out ! row1
// fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
// this can be done "destructive"
"pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0
"punpckhbw %%mm2,%%mm6\n" // 0 R3 0 R2 0 R1 0 R0
"punpckhbw %%mm1,%%mm5\n" // G3 B3 G2 B2 G1 B1 G0 B0
"movq %%mm5,%%mm1\n" // G3 B3 G2 B2 G1 B1 G0 B0
"punpcklwd %%mm6,%%mm1\n" // 0 R1 G1 B1 0 R0 G0 B0
"movq %%mm1,(%5)\n" // wrote out ! row2
"punpckhwd %%mm6,%%mm5\n" // 0 R3 G3 B3 0 R2 G2 B2
"movq %%mm5,8(%5)\n" // wrote out ! row2
"addl $4,%2\n" // lum+4
"leal 16(%3),%3\n" // row1+16
"leal 16(%5),%5\n" // row2+16
"addl $2, %%ebx\n" // cr+2
"addl $2, %1\n" // cb+2
"addl $4,%6\n" // x+4
"cmpl %4,%6\n"
"jl 1b\n"
"addl %4, %2\n" // lum += cols
"addl %8, %3\n" // row1+= mod
"addl %8, %5\n" // row2+= mod
"movl $0, %6\n" // x=0
"cmpl %7, %2\n"
"jl 1b\n"
"emms\n"
"popl %%ebx\n"
:
: "m" (cr), "r"(cb),"r"(lum),
"r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod)
: "%ebx"
);
}
void Color565DitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod )
{
Uint16 *row1;
Uint16 *row2;
unsigned char* y = lum +cols*rows; /* Pointer to the end */
int x=0;
row1 = (Uint16 *)out; /* 16 bit target */
row2 = (Uint16 *)out+cols+mod; /* start of second row */
mod = (mod+cols+mod)*2; /* increment for row1 in byte */
__asm__ __volatile__(
"pushl %%ebx\n"
"movl %0, %%ebx\n"
".align 8\n"
"1:\n"
"movd (%1), %%mm0\n" // 4 Cb 0 0 0 0 u3 u2 u1 u0
"pxor %%mm7, %%mm7\n"
"movd (%%ebx), %%mm1\n" // 4 Cr 0 0 0 0 v3 v2 v1 v0
"punpcklbw %%mm7, %%mm0\n" // 4 W cb 0 u3 0 u2 0 u1 0 u0
"punpcklbw %%mm7, %%mm1\n" // 4 W cr 0 v3 0 v2 0 v1 0 v0
"psubw _MMX_0080w, %%mm0\n"
"psubw _MMX_0080w, %%mm1\n"
"movq %%mm0, %%mm2\n" // Cb 0 u3 0 u2 0 u1 0 u0
"movq %%mm1, %%mm3\n" // Cr
"pmullw _MMX_Ugrn565, %%mm2\n" // Cb2green 0 R3 0 R2 0 R1 0 R0
"movq (%2), %%mm6\n" // L1 l7 L6 L5 L4 L3 L2 L1 L0
"pmullw _MMX_Ublu5x5, %%mm0\n" // Cb2blue
"pand _MMX_00FFw, %%mm6\n" // L1 00 L6 00 L4 00 L2 00 L0
"pmullw _MMX_Vgrn565, %%mm3\n" // Cr2green
"movq (%2), %%mm7\n" // L2
"pmullw _MMX_Vred5x5, %%mm1\n" // Cr2red
"psrlw $8, %%mm7\n" // L2 00 L7 00 L5 00 L3 00 L1
"pmullw _MMX_Ycoeff, %%mm6\n" // lum1
"paddw %%mm3, %%mm2\n" // Cb2green + Cr2green == green
"pmullw _MMX_Ycoeff, %%mm7\n" // lum2
"movq %%mm6, %%mm4\n" // lum1
"paddw %%mm0, %%mm6\n" // lum1 +blue 00 B6 00 B4 00 B2 00 B0
"movq %%mm4, %%mm5\n" // lum1
"paddw %%mm1, %%mm4\n" // lum1 +red 00 R6 00 R4 00 R2 00 R0
"paddw %%mm2, %%mm5\n" // lum1 +green 00 G6 00 G4 00 G2 00 G0
"psraw $6, %%mm4\n" // R1 0 .. 64
"movq %%mm7, %%mm3\n" // lum2 00 L7 00 L5 00 L3 00 L1
"psraw $6, %%mm5\n" // G1 - .. +
"paddw %%mm0, %%mm7\n" // Lum2 +blue 00 B7 00 B5 00 B3 00 B1
"psraw $6, %%mm6\n" // B1 0 .. 64
"packuswb %%mm4, %%mm4\n" // R1 R1
"packuswb %%mm5, %%mm5\n" // G1 G1
"packuswb %%mm6, %%mm6\n" // B1 B1
"punpcklbw %%mm4, %%mm4\n"
"punpcklbw %%mm5, %%mm5\n"
"pand _MMX_red565, %%mm4\n"
"psllw $3, %%mm5\n" // GREEN 1
"punpcklbw %%mm6, %%mm6\n"
"pand _MMX_grn565, %%mm5\n"
"pand _MMX_red565, %%mm6\n"
"por %%mm5, %%mm4\n" //
"psrlw $11, %%mm6\n" // BLUE 1
"movq %%mm3, %%mm5\n" // lum2
"paddw %%mm1, %%mm3\n" // lum2 +red 00 R7 00 R5 00 R3 00 R1
"paddw %%mm2, %%mm5\n" // lum2 +green 00 G7 00 G5 00 G3 00 G1
"psraw $6, %%mm3\n" // R2
"por %%mm6, %%mm4\n" // MM4
"psraw $6, %%mm5\n" // G2
"movq (%2, %4), %%mm6\n" // L3 load lum2
"psraw $6, %%mm7\n"
"packuswb %%mm3, %%mm3\n"
"packuswb %%mm5, %%mm5\n"
"packuswb %%mm7, %%mm7\n"
"pand _MMX_00FFw, %%mm6\n" // L3
"punpcklbw %%mm3, %%mm3\n"
"punpcklbw %%mm5, %%mm5\n"
"pmullw _MMX_Ycoeff, %%mm6\n" // lum3
"punpcklbw %%mm7, %%mm7\n"
"psllw $3, %%mm5\n" // GREEN 2
"pand _MMX_red565, %%mm7\n"
"pand _MMX_red565, %%mm3\n"
"psrlw $11, %%mm7\n" // BLUE 2
"pand _MMX_grn565, %%mm5\n"
"por %%mm7, %%mm3\n"
"movq (%2,%4), %%mm7\n" // L4 load lum2
"por %%mm5, %%mm3\n" //
"psrlw $8, %%mm7\n" // L4
"movq %%mm4, %%mm5\n"
"punpcklwd %%mm3, %%mm4\n"
"pmullw _MMX_Ycoeff, %%mm7\n" // lum4
"punpckhwd %%mm3, %%mm5\n"
"movq %%mm4, (%3)\n" // write row1
"movq %%mm5, 8(%3)\n" // write row1
"movq %%mm6, %%mm4\n" // Lum3
"paddw %%mm0, %%mm6\n" // Lum3 +blue
"movq %%mm4, %%mm5\n" // Lum3
"paddw %%mm1, %%mm4\n" // Lum3 +red
"paddw %%mm2, %%mm5\n" // Lum3 +green
"psraw $6, %%mm4\n"
"movq %%mm7, %%mm3\n" // Lum4
"psraw $6, %%mm5\n"
"paddw %%mm0, %%mm7\n" // Lum4 +blue
"psraw $6, %%mm6\n" // Lum3 +blue
"movq %%mm3, %%mm0\n" // Lum4
"packuswb %%mm4, %%mm4\n"
"paddw %%mm1, %%mm3\n" // Lum4 +red
"packuswb %%mm5, %%mm5\n"
"paddw %%mm2, %%mm0\n" // Lum4 +green
"packuswb %%mm6, %%mm6\n"
"punpcklbw %%mm4, %%mm4\n"
"punpcklbw %%mm5, %%mm5\n"
"punpcklbw %%mm6, %%mm6\n"
"psllw $3, %%mm5\n" // GREEN 3
"pand _MMX_red565, %%mm4\n"
"psraw $6, %%mm3\n" // psr 6
"psraw $6, %%mm0\n"
"pand _MMX_red565, %%mm6\n" // BLUE
"pand _MMX_grn565, %%mm5\n"
"psrlw $11, %%mm6\n" // BLUE 3
"por %%mm5, %%mm4\n"
"psraw $6, %%mm7\n"
"por %%mm6, %%mm4\n"
"packuswb %%mm3, %%mm3\n"
"packuswb %%mm0, %%mm0\n"
"packuswb %%mm7, %%mm7\n"
"punpcklbw %%mm3, %%mm3\n"
"punpcklbw %%mm0, %%mm0\n"
"punpcklbw %%mm7, %%mm7\n"
"pand _MMX_red565, %%mm3\n"
"pand _MMX_red565, %%mm7\n" // BLUE
"psllw $3, %%mm0\n" // GREEN 4
"psrlw $11, %%mm7\n"
"pand _MMX_grn565, %%mm0\n"
"por %%mm7, %%mm3\n"
"por %%mm0, %%mm3\n"
"movq %%mm4, %%mm5\n"
"punpcklwd %%mm3, %%mm4\n"
"punpckhwd %%mm3, %%mm5\n"
"movq %%mm4, (%5)\n"
"movq %%mm5, 8(%5)\n"
"addl $8, %6\n"
"addl $8, %2\n"
"addl $4, %%ebx\n"
"addl $4, %1\n"
"cmpl %4, %6\n"
"leal 16(%3), %3\n"
"leal 16(%5),%5\n" // row2+16
"jl 1b\n"
"addl %4, %2\n" // lum += cols
"addl %8, %3\n" // row1+= mod
"addl %8, %5\n" // row2+= mod
"movl $0, %6\n" // x=0
"cmpl %7, %2\n"
"jl 1b\n"
"emms\n"
"popl %%ebx\n"
:
:"m" (cr), "r"(cb),"r"(lum),
"r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod)
: "%ebx"
);
}
#endif /* GCC i386 inline assembly */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_yuv_sw_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
#include "SDL_video.h"
#include "SDL_sysvideo.h"
/* This is the software implementation of the YUV video overlay support */
extern SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
extern int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay);
extern void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay);
extern int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
extern void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay);

View File

@ -0,0 +1,41 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_yuvfuncs.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* This is the definition of the YUV video surface function structure */
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#ifndef _THIS
#define _THIS SDL_VideoDevice *_this
#endif
struct private_yuvhwfuncs {
int (*Lock)(_THIS, SDL_Overlay *overlay);
void (*Unlock)(_THIS, SDL_Overlay *overlay);
int (*Display)(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
void (*FreeHW)(_THIS, SDL_Overlay *overlay);
};

View File

@ -0,0 +1,38 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: blank_cursor.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
#endif
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* A default blank 8x8 cursor */
#define BLANK_CWIDTH 8
#define BLANK_CHEIGHT 8
#define BLANK_CHOTX 0
#define BLANK_CHOTY 0
static unsigned char blank_cdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char blank_cmask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

View File

@ -0,0 +1,121 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: default_cursor.h,v 1.3 2001/05/10 20:13:28 hercules Exp $";
#endif
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Default cursor - it happens to be the Mac cursor, but could be anything */
#define DEFAULT_CWIDTH 16
#define DEFAULT_CHEIGHT 16
#define DEFAULT_CHOTX 0
#define DEFAULT_CHOTY 0
/* Added a real MacOS cursor, at the request of Luc-Olivier de Charrière */
#define USE_MACOS_CURSOR
#ifdef USE_MACOS_CURSOR
static unsigned char default_cdata[] =
{
0x00,0x00,
0x40,0x00,
0x60,0x00,
0x70,0x00,
0x78,0x00,
0x7C,0x00,
0x7E,0x00,
0x7F,0x00,
0x7F,0x80,
0x7C,0x00,
0x6C,0x00,
0x46,0x00,
0x06,0x00,
0x03,0x00,
0x03,0x00,
0x00,0x00
};
static unsigned char default_cmask[] =
{
0xC0,0x00,
0xE0,0x00,
0xF0,0x00,
0xF8,0x00,
0xFC,0x00,
0xFE,0x00,
0xFF,0x00,
0xFF,0x80,
0xFF,0xC0,
0xFF,0xE0,
0xFE,0x00,
0xEF,0x00,
0xCF,0x00,
0x87,0x80,
0x07,0x80,
0x03,0x00
};
#else
static unsigned char default_cdata[] =
{
0x00,0x00,
0x40,0x00,
0x60,0x00,
0x70,0x00,
0x78,0x00,
0x7C,0x00,
0x7E,0x00,
0x7F,0x00,
0x7F,0x80,
0x7C,0x00,
0x6C,0x00,
0x46,0x00,
0x06,0x00,
0x03,0x00,
0x03,0x00,
0x00,0x00
};
static unsigned char default_cmask[] =
{
0x40,0x00,
0xE0,0x00,
0xF0,0x00,
0xF8,0x00,
0xFC,0x00,
0xFE,0x00,
0xFF,0x00,
0xFF,0x80,
0xFF,0xC0,
0xFF,0x80,
0xFE,0x00,
0xEF,0x00,
0x4F,0x00,
0x07,0x80,
0x07,0x80,
0x03,0x00
};
#endif /* TRUE_MACINTOSH_CURSOR */