Commit df7866c4 authored by Sam Lantinga's avatar Sam Lantinga

Updated the Amiga OS port of SDL (thanks Gabriele)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%4022
parent ac645d34
......@@ -169,9 +169,6 @@ QNX: -= NOT YET SUPPORTED =-
The software surfaces could use some speed up.
Many of the test apps segment violate on exit, and I'm not sure
they're all working either
It doesn't look like the OpenGL stuff is there. (did a grep for
PdCreateOpenGLContext, nothing found).
......@@ -187,13 +184,4 @@ AmigaOS: -= NOT YET SUPPORTED =-
Continuous relative mouse motion is not implemented.
Audio can work, but isn't completely integrated in the CVS
version of SDL.
The joystick subsystem isn't implemented yet.
There's some confusion about the multi-threaded synchronization
primitives on AmigaOS, so mutexes and semaphores aren't correctly
implemented yet.
The AmigaOS port was done by Gabriele.Greco@galactica.it
This is the porting of 1.2.0 version of SDL (the latest stable one)
to AmigaOS/68k.
All the bugs known of the past version have been corrected. And I've
added all the new SDL features.
This version of SDL needs Cybergraphx V3 (r69+) or CyberGraphX V4
and AHI v3+. Probably it works also with P96 or CGXAga, but it's
untested.
This version is available as linked library for SAS/C and GCC, only 68k this
time, a powerup (ppcemu compatible) and a morphos version will be ready quite
soon (i hope).
Implemented:
- 8/16/24/32bit video modes, both fullscreen and windowed.
- Hardware surfaces.
- CGX blitting acceleration.
- CGX colorkey blitting acceleration.
- AHI audio (8/16 bit, with any audio format), always uses unit 0 for now.
- Thread support (maybe not 100% compatible with other implementations)
- Semaphores
- Window resizing and backdrop windows (NEW)
- Joystick/Joypad support.
To do:
- CDRom audio playing support
- OpenGL (A guy was working on it but I've lost his tracks :( )
The SAS/C library is distributed with debug info attached, to strip debug info
simply add STRIPDEBUG argument to the linker.
NOTE: SDL includes debug output using kprintf, to disable it add to your
project a function like this:
void kprintf(char *a,...)
{
}
Otherwise you can redirect the debug to a console window with sushi, sashimi or
similar tools (the default output is the internal serial port).
For info, support, bugfix and other feel free to mail me:
Gabriele Greco (gabriele.greco@aruba.it)
You can find also a small SDL Amiga page at:
http://ggreco.interfree.it/sdl.html
......@@ -1936,6 +1936,7 @@ src/video/photon/Makefile
src/video/dummy/Makefile
src/events/Makefile
src/joystick/Makefile
src/joystick/amigaos/Makefile
src/joystick/beos/Makefile
src/joystick/dummy/Makefile
src/joystick/linux/Makefile
......
......@@ -76,6 +76,10 @@ static AudioBootStrap *bootstrap[] = {
#ifdef _AIX
&Paud_bootstrap,
#endif
#ifdef ENABLE_AHI
&AHI_bootstrap,
#endif
NULL
};
SDL_AudioDevice *current_audio = NULL;
......@@ -84,6 +88,9 @@ SDL_AudioDevice *current_audio = NULL;
int SDL_AudioInit(const char *driver_name);
void SDL_AudioQuit(void);
#ifdef ENABLE_AHI
static int audio_configured = 0;
#endif
/* The general mixing thread function */
int SDL_RunAudio(void *audiop)
......@@ -94,6 +101,21 @@ int SDL_RunAudio(void *audiop)
void *udata;
void (*fill)(void *userdata,Uint8 *stream, int len);
int silence;
#ifdef ENABLE_AHI
int started = 0;
/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
D(bug("Task audio started audio struct:<%lx>...\n",audiop));
D(bug("Before Openaudio..."));
if(audio->OpenAudio(audio, &audio->spec)==-1)
{
D(bug("Open audio failed...\n"));
return(-1);
}
D(bug("OpenAudio...OK\n"));
#endif
/* Perform any thread setup */
if ( audio->ThreadInit ) {
......@@ -104,6 +126,15 @@ int SDL_RunAudio(void *audiop)
/* Set up the mixing function */
fill = audio->spec.callback;
udata = audio->spec.userdata;
#ifdef ENABLE_AHI
audio_configured = 1;
D(bug("Audio configured... Checking for conversion\n"));
SDL_mutexP(audio->mixer_lock);
D(bug("Semaphore obtained...\n"));
#endif
if ( audio->convert.needed ) {
if ( audio->convert.src_format == AUDIO_U8 ) {
silence = 0x80;
......@@ -117,6 +148,12 @@ int SDL_RunAudio(void *audiop)
}
stream = audio->fake_stream;
#ifdef ENABLE_AHI
SDL_mutexV(audio->mixer_lock);
D(bug("Entering audio loop...\n"));
#endif
/* Loop, filling the audio buffers */
while ( audio->enabled ) {
......@@ -124,12 +161,14 @@ int SDL_RunAudio(void *audiop)
if ( stream == audio->fake_stream ) {
SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
} else {
#ifdef ENABLE_AHI
if ( started > 1 )
#endif
audio->WaitAudio(audio);
}
/* Fill the current buffer with sound */
if ( audio->convert.needed ) {
/* The buffer may not be allocated yet */
if ( audio->convert.buf ) {
stream = audio->convert.buf;
} else {
......@@ -163,12 +202,25 @@ int SDL_RunAudio(void *audiop)
/* Ready current buffer for play and change current buffer */
if ( stream != audio->fake_stream ) {
audio->PlayAudio(audio);
#ifdef ENABLE_AHI
/* AmigaOS don't have to wait the first time audio is played! */
started++;
#endif
}
}
/* Wait for the audio to drain.. */
if ( audio->WaitDone ) {
audio->WaitDone(audio);
}
#ifdef ENABLE_AHI
D(bug("WaitAudio...Done\n"));
audio->CloseAudio(audio);
D(bug("CloseAudio..Done, subtask exiting...\n"));
audio_configured = 0;
#endif
return(0);
}
......@@ -312,11 +364,33 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
audio->convert.needed = 0;
audio->enabled = 1;
audio->paused = 1;
#ifndef ENABLE_AHI
/* AmigaOS opens audio inside the main loop */
audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
if ( ! audio->opened ) {
SDL_CloseAudio();
return(-1);
}
#else
D(bug("Locking semaphore..."));
SDL_mutexP(audio->mixer_lock);
audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
D(bug("Created thread...\n"));
if ( audio->thread == NULL ) {
SDL_mutexV(audio->mixer_lock);
SDL_CloseAudio();
SDL_SetError("Couldn't create audio thread");
return(-1);
}
while(!audio_configured)
SDL_Delay(100);
#endif
/* If the audio driver changes the buffer size, accept it */
if ( audio->spec.samples != desired->samples ) {
......@@ -365,6 +439,7 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
}
}
#ifndef ENABLE_AHI
/* Start the audio thread if necessary */
switch (audio->opened) {
case 1:
......@@ -381,6 +456,12 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
/* The audio is now playing */
break;
}
#else
SDL_mutexV(audio->mixer_lock);
D(bug("SDL_OpenAudio USCITA...\n"));
#endif
return(0);
}
......@@ -457,12 +538,14 @@ void SDL_AudioQuit(void)
}
if ( audio->convert.needed ) {
SDL_FreeAudioMem(audio->convert.buf);
}
#ifndef ENABLE_AHI
if ( audio->opened ) {
audio->CloseAudio(audio);
audio->opened = 0;
}
#endif
/* Free the driver data */
audio->free(audio);
current_audio = NULL;
......
......@@ -126,14 +126,17 @@ extern AudioBootStrap DSOUND_bootstrap;
#ifdef ENABLE_WINDIB
extern AudioBootStrap WAVEOUT_bootstrap;
#endif
#ifdef _AIX
extern AudioBootStrap Paud_bootstrap;
#endif
#ifdef __BEOS__
extern AudioBootStrap BAUDIO_bootstrap;
#endif
#if defined(macintosh) || TARGET_API_MAC_CARBON
extern AudioBootStrap SNDMGR_bootstrap;
#endif
#ifdef _AIX
extern AudioBootStrap Paud_bootstrap;
#ifdef ENABLE_AHI
extern AudioBootStrap AHI_bootstrap;
#endif
/* This is the current audio device */
......
......@@ -3,6 +3,6 @@
noinst_LTLIBRARIES = libaudio_arch.la
ARCH_SRCS = SDL_ahiaudio.c SDL_audio.c SDL_lowaudio.h SDL_sysaudio.h
ARCH_SRCS = SDL_ahiaudio.c SDL_ahiaudio.h
libaudio_arch_la_SOURCES = $(ARCH_SRCS)
......@@ -27,13 +27,17 @@ static char rcsid =
"@(#) $Id$";
#endif
/* Allow access to a raw mixing buffer (For IRIX 6.5 and higher) */
/* Allow access to a raw mixing buffer (for AmigaOS) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audiomem.h"
#include "SDL_audio_c.h"
#include "SDL_lowaudio.h"
#include "SDL_ahiaudio.h"
/* Audio driver functions */
static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec);
......@@ -54,11 +58,29 @@ static void AHI_CloseAudio(_THIS);
static int Audio_Available(void)
{
#ifndef NO_AMIGADEBUG
D(bug("AHI available.\n"));
#endif
int ok=0;
struct MsgPort *p;
struct AHIRequest *req;
if(p=CreateMsgPort())
{
if(req=(struct AHIRequest *)CreateIORequest(p,sizeof(struct AHIRequest)))
{
req->ahir_Version=4;
return 1;
if(!OpenDevice(AHINAME,0,(struct IORequest *)req,NULL))
{
D(bug("AHI available.\n"));
ok=1;
CloseDevice((struct IORequest *)req);
}
DeleteIORequest((struct IORequest *)req);
}
DeleteMsgPort(p);
}
D(if(!ok) bug("AHI not available\n"));
return ok;
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
......@@ -125,7 +147,7 @@ static void AHI_PlayAudio(_THIS)
/* Write the audio data out */
audio_req[current_buffer] -> ahir_Std. io_Message.mn_Node.ln_Pri = 60;
audio_req[current_buffer] -> ahir_Std. io_Data = mixbuf[current_buffer];
audio_req[current_buffer] -> ahir_Std. io_Length = this->spec.samples*this->hidden->bytespersample;
audio_req[current_buffer] -> ahir_Std. io_Length = this->hidden->size;
audio_req[current_buffer] -> ahir_Std. io_Offset = 0;
audio_req[current_buffer] -> ahir_Std . io_Command = CMD_WRITE;
audio_req[current_buffer] -> ahir_Frequency = this->hidden->freq;
......@@ -149,43 +171,58 @@ static void AHI_CloseAudio(_THIS)
{
D(bug("Closing audio...\n"));
if ( mixbuf[0] != NULL ) {
myfree(mixbuf[0]);
// SDL_FreeAudioMem(mixbuf[0]);
mixbuf[0] = NULL;
}
if ( mixbuf[1] != NULL ) {
myfree(mixbuf[1]);
// SDL_FreeAudioMem(mixbuf[1]);
mixbuf[1] = NULL;
}
playing=0;
if(audio_req[0])
{
if(audio_req[1])
{
if(!CheckIO((struct IORequest *)audio_req[1]))
{
AbortIO((struct IORequest *)audio_req[1]);
WaitIO((struct IORequest *)audio_req[1]);
}
myfree(audio_req[1]);
D(bug("Break req[1]...\n"));
AbortIO((struct IORequest *)audio_req[1]);
WaitIO((struct IORequest *)audio_req[1]);
}
if(!CheckIO((struct IORequest *)audio_req[0]))
D(bug("Break req[0]...\n"));
AbortIO((struct IORequest *)audio_req[0]);
WaitIO((struct IORequest *)audio_req[0]);
if(audio_req[1])
{
AbortIO((struct IORequest *)audio_req[0]);
WaitIO((struct IORequest *)audio_req[0]);
D(bug("Break AGAIN req[1]...\n"));
AbortIO((struct IORequest *)audio_req[1]);
WaitIO((struct IORequest *)audio_req[1]);
}
// Double abort to be sure to break the dbuffering process.
SDL_Delay(200);
D(bug("Reqs breaked, closing device...\n"));
CloseDevice((struct IORequest *)audio_req[0]);
D(bug("Device closed, freeing memory...\n"));
myfree(audio_req[1]);
D(bug("Memory freed, deleting IOReq...\n"));
DeleteIORequest((struct IORequest *)audio_req[0]);
audio_req[0]=audio_req[1]=NULL;
}
D(bug("Freeing mixbuf[0]...\n"));
if ( mixbuf[0] != NULL ) {
myfree(mixbuf[0]);
// SDL_FreeAudioMem(mixbuf[0]);
mixbuf[0] = NULL;
}
D(bug("Freeing mixbuf[1]...\n"));
if ( mixbuf[1] != NULL ) {
myfree(mixbuf[1]);
// SDL_FreeAudioMem(mixbuf[1]);
mixbuf[1] = NULL;
}
D(bug("Freeing audio_port...\n"));
if ( audio_port != NULL ) {
DeleteMsgPort(audio_port);
audio_port = NULL;
......@@ -206,8 +243,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("Samples a 8 bit...\n"));
spec->format = AUDIO_S8;
this->hidden->bytespersample=1;
this->hidden->type = AHIST_M8S;
if(spec->channels<2)
this->hidden->type = AHIST_M8S;
else
this->hidden->type = AHIST_S8S;
}
break;
......@@ -215,7 +254,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("Samples a 16 bit...\n"));
spec->format = AUDIO_S16MSB;
this->hidden->bytespersample=2;
this->hidden->type = AHIST_M16S;
if(spec->channels<2)
this->hidden->type = AHIST_M16S;
else
this->hidden->type = AHIST_S16S;
}
break;
......@@ -225,6 +267,13 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
}
}
if(spec->channels!=1 && spec->channels!=2)
{
D(bug("Wrong channel number!\n"));
SDL_SetError("Channel number non supported");
return -1;
}
D(bug("Before CalculateAudioSpec\n"));
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec);
......@@ -258,8 +307,9 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("AFTER opendevice\n"));
/* Set output frequency */
/* Set output frequency and size */
this->hidden->freq = spec->freq;
this->hidden->size = spec->size;
D(bug("Before buffer allocation\n"));
......@@ -292,7 +342,7 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
current_buffer=0;
playing=0;
D(bug("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld\n",spec->freq,mixbuf[0],mixbuf[1],spec->size,this->hidden->bytespersample*8));
D(bug("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld channels:%ld\n",spec->freq,mixbuf[0],mixbuf[1],spec->size,this->hidden->bytespersample*8,spec->channels));
/* We're ready to rock and roll. :-) */
return(0);
......
......@@ -25,15 +25,20 @@ static char rcsid =
"@(#) $Id$";
#endif
#ifndef _SDL_lowaudio_h
#define _SDL_lowaudio_h
// #include <libraries/ahi_sub.h>
#ifndef _SDL_ahiaudio_h
#define _SDL_ahiaudio_h
#include <exec/exec.h>
#include <dos/dos.h>
#ifdef __SASC
#include <proto/exec.h>
#else
#include <inline/exec.h>
#endif
#include <devices/ahi.h>
#include "mydebug.h"
#include "SDL_sysaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
......@@ -55,4 +60,4 @@ struct SDL_PrivateAudioData {
#define current_buffer (this->hidden->current_buffer)
#define playing (this->hidden->playing)
#endif /* _SDL_lowaudio_h */
#endif /* _SDL_ahiaudio_h */
This diff is collapsed.
/*
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$";
#endif
#ifndef _SDL_sysaudio_h
#define _SDL_sysaudio_h
#include "SDL_mutex.h"
#include "SDL_thread.h"
#include <exec/exec.h>
#include <dos/dos.h>
#ifdef __SASC
#include <proto/exec.h>
#else
#include <inline/exec.h>
#endif
#include <devices/ahi.h>
#include "mydebug.h"
/* The SDL audio driver */
typedef struct SDL_AudioDevice SDL_AudioDevice;
/* Define the SDL audio driver structure */
#define _THIS SDL_AudioDevice *_this
#ifndef _STATUS
#define _STATUS SDL_status *status
#endif
struct SDL_AudioDevice {
/* * * */
/* The name of this audio driver */
const char *name;
/* * * */
/* Public driver functions */
int (*OpenAudio)(_THIS, SDL_AudioSpec *spec);
void (*ThreadInit)(_THIS); /* Called by audio thread at start */
void (*WaitAudio)(_THIS);
void (*PlayAudio)(_THIS);
Uint8 *(*GetAudioBuf)(_THIS);
void (*WaitDone)(_THIS);
void (*CloseAudio)(_THIS);
/* * * */
/* Data common to all devices */
/* The current audio specification (shared with audio thread) */
SDL_AudioSpec spec;
/* An audio conversion block for audio format emulation */
SDL_AudioCVT convert;
/* Current state flags */
int enabled;
int paused;
/* Fake audio buffer for when the audio hardware is busy */
Uint8 *fake_stream;
/* A semaphore for locking the mixing buffers */
struct SignalSemaphore mixer_lock;
/* A thread to feed the audio device */
SDL_Thread *thread;
Uint32 threadid;
/* * * */
/* Data private to this driver */
struct SDL_PrivateAudioData *hidden;
/* * * */
/* The function used to dispose of this structure */
void (*free)(_THIS);
};
#undef _THIS
typedef struct AudioBootStrap {
const char *name;
int (*available)(void);
SDL_AudioDevice *(*create)(int devindex);
} AudioBootStrap;
#ifdef ESD_SUPPORT
extern AudioBootStrap ESD_bootstrap;
#endif
#ifdef linux
extern AudioBootStrap DMA_bootstrap;
#endif
#ifdef unix
extern AudioBootStrap AUDIO_bootstrap;
#endif
#ifdef ENABLE_WINDIB
extern AudioBootStrap WAVEOUT_bootstrap;
#endif
#ifdef ENABLE_DIRECTX
extern AudioBootStrap DSOUND_bootstrap;
#endif
#ifdef __BEOS__
extern AudioBootStrap BAUDIO_bootstrap;
#endif
#ifdef macintosh
extern AudioBootStrap AUDIO_bootstrap;
#endif
#ifdef _AIX
extern AudioBootStrap Paud_bootstrap;
#endif
#ifdef ENABLE_CYBERGRAPHICS
extern AudioBootStrap AHI_bootstrap;
#endif
/* This is the current audio device */
extern SDL_AudioDevice *current_audio;
#ifndef __SASC
extern struct ExecBase *SysBase;
#endif
#endif /* _SDL_sysaudio_h */
## Makefile.am for the AmigaOS joystick driver for SDL
noinst_LTLIBRARIES = libjoystick_amiga.la
libjoystick_amiga_la_SOURCES = $(SRCS)
# The SDL joystick driver sources
SRCS = SDL_sysjoystick.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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* This is the system specific header for the SDL joystick API */
#include <stdio.h> /* For the definition of NULL */
#include <libraries/lowlevel.h>
#ifdef __SASC
#include <proto/exec.h>
#include <proto/lowlevel.h>
#include <proto/graphics.h>
#else
#include <inline/exec.h>
#include <inline/lowlevel.h>
#include <inline/graphics.h>
#endif
#include "mydebug.h"
extern struct ExecBase *SysBase;
extern struct GfxBase *GfxBase;
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_joystick.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
/* Function to scan the system for joysticks.
* This function should set SDL_numjoysticks to the number of available
* joysticks. Joystick 0 should be the system default joystick.
* It should return 0, or -1 on an unrecoverable fatal error.
*/
/* Amiga specific datas */
struct Library *LowLevelBase=NULL;
ULONG joybut[]=
{
JPF_BUTTON_RED,
JPF_BUTTON_BLUE,
JPF_BUTTON_PLAY,
JPF_BUTTON_YELLOW,
JPF_BUTTON_GREEN,
JPF_BUTTON_FORWARD,
JPF_BUTTON_REVERSE,
};
struct joystick_hwdata
{
ULONG joystate;
};
int SDL_SYS_JoystickInit(void)
{
if(!LowLevelBase)
{
if(LowLevelBase=OpenLibrary("lowlevel.library",37))
return 2;
}
else
return 2;
D(bug("%ld joysticks available.\n",SDL_numjoysticks));
return 0;
}
/* Function to get the device-dependent name of a joystick */
const char *SDL_SYS_JoystickName(int index)
{
if(index<2&&LowLevelBase)
{
switch(index)
{
case 0:
return "Port 1 Amiga Joystick/Joypad";
case 1:
return "Port 2 Amiga Joystick/Joypad";
}
}
SDL_SetError("No joystick available with that index");
return(NULL);
}
/* 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.
*/
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
{
ULONG temp,i;
D(bug("Opening joystick %ld\n",joystick->index));
if(!(joystick->hwdata=malloc(sizeof(struct joystick_hwdata))))
return -1;
/* This loop is to check if the controller is a joypad */
for(i=0;i<20;i++)
{
temp=ReadJoyPort(joystick->index);
WaitTOF();
}
if((temp&JP_TYPE_MASK)==JP_TYPE_GAMECTLR)
joystick->nbuttons=7;
else
joystick->nbuttons=3;
joystick->nhats=0;
joystick->nballs=0;
joystick->naxes=2;
joystick->hwdata->joystate=0L;
return 0;
}
/* 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.
*/
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
{
ULONG data;
int i;
if(joystick->index<2)
{
data=ReadJoyPort(joystick->index);
if(data&JP_DIRECTION_MASK)
{
if(data&JPF_JOY_DOWN)
{
if(!(joystick->hwdata->joystate&JPF_JOY_DOWN))
SDL_PrivateJoystickAxis(joystick,0,127);
}
else if(data&JPF_JOY_UP)
{
if(!(joystick->hwdata->joystate&JPF_JOY_UP))
SDL_PrivateJoystickAxis(joystick,0,-127);
}
else if(joystick->hwdata->joystate&(JPF_JOY_UP|JPF_JOY_DOWN))
SDL_PrivateJoystickAxis(joystick,0,0);
if(data&JPF_JOY_LEFT)
{
if(!(joystick->hwdata->joystate&JPF_JOY_LEFT))
SDL_PrivateJoystickAxis(joystick,1,-127);
}
else if(data&JPF_JOY_RIGHT)
{
if(!(joystick->hwdata->joystate&JPF_JOY_RIGHT))
SDL_PrivateJoystickAxis(joystick,1,127);
}
else if(joystick->hwdata->joystate&(JPF_JOY_LEFT|JPF_JOY_RIGHT))
SDL_PrivateJoystickAxis(joystick,1,0);
}
else if(joystick->hwdata->joystate&(JPF_JOY_LEFT|JPF_JOY_RIGHT))
{
SDL_PrivateJoystickAxis(joystick,1,0);
}
else if(joystick->hwdata->joystate&(JPF_JOY_UP|JPF_JOY_DOWN))
{
SDL_PrivateJoystickAxis(joystick,0,0);
}
for(i=0;i<joystick->nbuttons;i++)
{
if( (data&joybut[i]) )
{
if(i==1)
data&=(~(joybut[2]));
if(!(joystick->hwdata->joystate&joybut[i]))
SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED);
}
else if(joystick->hwdata->joystate&joybut[i])
SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED);
}
joystick->hwdata->joystate=data;
}
return;
}
/* Function to close a joystick after use */
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
{
if(joystick->hwdata)
free(joystick->hwdata);
return;
}
/* Function to perform any system-specific joystick related cleanup */
void SDL_SYS_JoystickQuit(void)
{
if(LowLevelBase)
{
CloseLibrary(LowLevelBase);
LowLevelBase=NULL;
SDL_numjoysticks=0;
}
return;
}
......@@ -25,7 +25,7 @@ static char rcsid =
"@(#) $Id$";
#endif
/* An native implementation of semaphores on AmigaOS */
/* An implementation of semaphores using mutexes and condition variables */
#include "SDL_error.h"
#include "SDL_thread.h"
......@@ -35,9 +35,13 @@ static char rcsid =
struct SDL_semaphore
{
struct SignalSemaphore Sem;
Uint32 count;
Uint32 waiters_count;
SDL_mutex *count_lock;
SDL_cond *count_nonzero;
};
#undef D(x)
#undef D
#define D(x)
......@@ -46,20 +50,18 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
SDL_sem *sem;
sem = (SDL_sem *)malloc(sizeof(*sem));
if ( ! sem ) {
SDL_OutOfMemory();
return(0);
}
memset(sem, 0, sizeof(*sem));
D(bug("Creating semaphore %lx...\n",sem));
memset(sem,0,sizeof(*sem));
InitSemaphore(&sem->Sem);
#if 1 // Allow multiple obtainings of the semaphore
while ( initial_value-- ) {
ReleaseSemaphore(&sem->Sem);
}
#endif
return(sem);
}
......@@ -75,8 +77,6 @@ void SDL_DestroySemaphore(SDL_sem *sem)
int SDL_SemTryWait(SDL_sem *sem)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
......@@ -84,17 +84,17 @@ int SDL_SemTryWait(SDL_sem *sem)
D(bug("TryWait semaphore...%lx\n",sem));
retval = SDL_MUTEX_TIMEDOUT;
if ( AttemptSemaphore(&sem->Sem) ) {
retval = 0;
}
return retval;
ObtainSemaphore(&sem->Sem);
// ReleaseSemaphore(&sem->Sem);
return 1;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
......@@ -102,16 +102,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
D(bug("WaitTimeout (%ld) semaphore...%lx\n",timeout,sem));
#if 1 // We need to keep trying the semaphore until the timeout expires
retval = SDL_MUTEX_TIMEDOUT;
then = SDL_GetTicks();
do {
if ( AttemptSemaphore(&sem->Sem) ) {
retval = 0;
}
now = SDL_GetTicks();
} while ( (retval == SDL_MUTEX_TIMEDOUT) && ((now-then) < timeout) );
#else
/* 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);
*/
if(!(retval=AttemptSemaphore(&sem->Sem)))
{
SDL_Delay(timeout);
......@@ -123,22 +129,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
// ReleaseSemaphore(&sem->Sem);
retval=1;
}
#endif
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
#if 1 // This should be an infinite wait - FIXME, what is the return value?
ObtainSemaphore(&sem->Sem);
return 0;
#else
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
#endif
return 0;
// return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32 SDL_SemValue(SDL_sem *sem)
......@@ -148,6 +147,7 @@ Uint32 SDL_SemValue(SDL_sem *sem)
value = 0;
if ( sem ) {
value = sem->Sem.ss_NestCount;
// SDL_UnlockMutex(sem->count_lock);
}
return value;
}
......@@ -161,6 +161,14 @@ int SDL_SemPost(SDL_sem *sem)
D(bug("SemPost semaphore...%lx\n",sem));
ReleaseSemaphore(&sem->Sem);
#if 0
SDL_LockMutex(sem->count_lock);
if ( sem->waiters_count > 0 ) {
SDL_CondSignal(sem->count_nonzero);
}
++sem->count;
SDL_UnlockMutex(sem->count_lock);
#endif
return 0;
}
......@@ -25,7 +25,7 @@ static char rcsid =
"@(#) $Id$";
#endif
/* AmigaOS thread management routines for SDL */
/* BeOS thread management routines for SDL */
#include "SDL_error.h"
#include "SDL_mutex.h"
......@@ -40,6 +40,8 @@ typedef struct {
struct Task *wait;
} thread_args;
#ifndef MORPHOS
#if defined(__SASC) && !defined(__PPC__)
__saveds __asm Uint32 RunThread(register __a0 char *args )
#elif defined(__PPC__)
......@@ -60,6 +62,34 @@ Uint32 RunThread(char *args __asm("a0") )
return(0);
}
#else
#include <emul/emulinterface.h>
Uint32 RunTheThread(void)
{
thread_args *data=(thread_args *)atol(REG_A0);
struct Task *Father;
D(bug("Received data: %lx\n",data));
Father=data->wait;
SDL_RunThread(data);
Signal(Father,SIGBREAKF_CTRL_F);
return(0);
}
struct EmulLibEntry RunThread=
{
TRAP_LIB,
0,
RunTheThread
};
#endif
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
/* Create the thread and go! */
......@@ -98,6 +128,7 @@ Uint32 SDL_ThreadID(void)
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
SetSignal(0L,SIGBREAKF_CTRL_F|SIGBREAKF_CTRL_C);
Wait(SIGBREAKF_CTRL_F|SIGBREAKF_CTRL_C);
}
......
......@@ -265,6 +265,18 @@ void SDL_WaitThread(SDL_Thread *thread, int *status)
}
}
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 ) {
......
......@@ -26,98 +26,221 @@ static char rcsid =
#endif
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <exec/types.h>
#ifdef __SASC
#include <proto/dos.h>
#include <clib/graphics_protos.h>
#include <pragmas/graphics.h>
#include <clib/exec_protos.h>
#include <pragmas/exec.h>
#else
#include <inline/dos.h>
#include <inline/exec.h>
#include <inline/graphics.h>
#endif
#include "mydebug.h"
extern struct DosLibrary *DOSBase;
extern struct ExecBase *SysBase;
static struct GfxBase *GfxBase;
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_timer_c.h"
#if defined(DISABLE_THREADS) || defined(FORK_HACK)
#define USE_ITIMER
#endif
/* The first ticks value of the application */
static struct timeval start;
#ifndef __PPC__
static clock_t start;
void SDL_StartTicks(void)
{
/* Set first ticks value */
gettimeofday(&start, NULL);
start=clock();
}
Uint32 SDL_GetTicks (void)
{
struct timeval now;
Uint32 ticks;
clock_t ticks;
ticks=clock()-start;
#ifdef __SASC
// CLOCKS_PER_SEC == 1000 !
gettimeofday(&now, NULL);
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
return(ticks);
#else
// CLOCKS_PER_SEC != 1000 !
return ticks*(1000/CLOCKS_PER_SEC);
#endif
}
void SDL_Delay (Uint32 ms)
{
int was_error;
#ifndef linux /* Non-Linux implementations need to calculate time left */
Uint32 then, now, elapsed;
// Do a busy wait if time is less than 50ms
if(ms<50)
{
clock_t to_wait=clock();
#ifndef __SASC
ms*=(CLOCKS_PER_SEC/1000);
#endif
struct timeval tv;
to_wait+=ms;
while(clock()<to_wait);
}
else
{
Delay(ms/20);
}
}
/* Set the timeout interval - Linux only needs to do this once */
#ifdef linux
tv.tv_sec = ms/1000;
tv.tv_usec = (ms%1000)*1000;
#else
then = SDL_GetTicks();
#endif
do {
errno = 0;
#ifndef linux
/* Calculate the time interval left (in case of interrupt) */
now = SDL_GetTicks();
elapsed = (now-then);
then = now;
if ( elapsed >= ms ) {
break;
ULONG MY_CLOCKS_PER_SEC;
void PPC_TimerInit(void);
APTR MyTimer;
ULONG start[2];
void SDL_StartTicks(void)
{
/* Set first ticks value */
if(!MyTimer)
PPC_TimerInit();
PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,start);
start[1]>>=10;
start[1]|=((result[0]&0x3ff)<<22);
start[0]>>=10;
}
Uint32 SDL_GetTicks (void)
{
ULONG result[2];
PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result);
// PPCAsr64p(result,10);
// Non va, la emulo:
result[1]>>=10;
result[1]|=((result[0]&0x3ff)<<22);
// Non mi interessa piu' result[0]
return result[1]*1000/MY_CLOCKS_PER_SEC;
}
void SDL_Delay (Uint32 ms)
{
// Do a busy wait if time is less than 50ms
if(ms<50)
{
ULONG to_wait[2],actual[2];
PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result);
actual[1]=0;
to_wait[1]+=ms*1000/MY_CLOCKS_PER_SEC;
while(actual[1]<to_wait[1])
{
PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,actual);
}
ms -= elapsed;
tv.tv_sec = ms/1000;
tv.tv_usec = (ms%1000)*1000;
#endif
was_error = select(0, NULL, NULL, NULL, &tv);
} while ( was_error && (errno == EINTR) );
}
else
{
Delay(ms/50);
}
}
void PPC_TimerInit(void)
{
struct TagItem tags[]=
{
PPCTIMERTAG_CPU,TRUE,
TAG_DONE,0
};
if(MyTimer=PPCCreateTimerObject(tags))
{
ULONG result[2];
PPCGetTimerObject(MyTimer,PPCTIMERTAG_TICKSPERSEC,result);
D(bug("Timer inizializzato, TPS: %lu - %lu\n",result[0],result[1]));
// PPCAsr64p(result,10);
result[1]>>=10;
result[1]|=((result[0]&0x3ff)<<22);
result[0]>>=10;
D(bug("Shiftato TPS: %lu - %lu\n",result[0],result[1]));
MY_CLOCKS_PER_SEC=result[1];
PPCGetTimerObject(MyTimer,PPCTIMERTAG_CURRENTTICKS,result);
D(bug("Current ticks: %lu - %lu\n",result[0],result[1]));
result[1]>>=10;
result[1]|=((result[0]&0x3ff)<<22);
result[0]>>=10;
// PPCAsr64p(result,10);
D(bug("Shiftato: %lu - %lu\n",result[0],result[1]));
}
else
{
D(bug("Errore nell'inizializzazione del timer!\n"));
}
}
#endif
#include "SDL_thread.h"
/* Data to handle a single periodic alarm */
static int timer_alive = 0;
static SDL_Thread *timer = NULL;
static SDL_Thread *timer_thread = NULL;
static int RunTimer(void *unused)
{
D(bug("SYSTimer: Entering RunTimer loop..."));
if(GfxBase==NULL)
GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37);
while ( timer_alive ) {
if ( SDL_timer_running ) {
SDL_ThreadedTimerCheck();
}
SDL_Delay(1);
if(GfxBase)
WaitTOF(); // Check the timer every fifth of seconds. Was SDL_Delay(1)->BusyWait!
else
Delay(1);
}
D(bug("SYSTimer: EXITING RunTimer loop..."));
return(0);
}
/* This is only called if the event thread is not running */
int SDL_SYS_TimerInit(void)
{
#ifdef NO_AMIGADEBUG
fprintf(stderr,"Creo il thread per il timer (NOITMER)...\n");
#endif
D(bug("Creo il thread per il timer (NOITMER)...\n"));
timer_alive = 1;
timer = SDL_CreateThread(RunTimer, NULL);
if ( timer == NULL )
timer_thread = SDL_CreateThread(RunTimer, NULL);
if ( timer_thread == NULL )
{
#ifdef NO_AMIGADEBUG
fprintf(stderr,"Creazione del thread fallita...\n");
#endif
D(bug("Creazione del thread fallita...\n"));
return(-1);
}
......@@ -127,15 +250,15 @@ int SDL_SYS_TimerInit(void)
void SDL_SYS_TimerQuit(void)
{
timer_alive = 0;
if ( timer ) {
SDL_WaitThread(timer, NULL);
timer = NULL;
if ( timer_thread ) {
SDL_WaitThread(timer_thread, NULL);
timer_thread = NULL;
}
}
int SDL_SYS_StartTimer(void)
{
SDL_SetError("Internal logic error: Linux uses threaded timer");
SDL_SetError("Internal logic error: AmigaOS uses threaded timer");
return(-1);
}
......
......@@ -255,8 +255,8 @@ printf("MapNotify!\n");
/* Have we been resized? */
case IDCMP_NEWSIZE:
SDL_PrivateResize(SDL_Window->Width,
SDL_Window->Height);
SDL_PrivateResize(SDL_Window->Width-SDL_Window->BorderLeft-SDL_Window->BorderRight,
SDL_Window->Height-SDL_Window->BorderTop-SDL_Window->BorderBottom);
break;
/* Have we been requested to quit? */
......
......@@ -214,6 +214,8 @@ static int CGX_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
}
else if(dst->hwdata)
BBB(src->hwdata->bmap,srcrect->x,srcrect->y,dst->hwdata->bmap,dstrect->x,dstrect->y,srcrect->w,srcrect->h,0xc0,0xff,NULL);
return 0;
}
int CGX_FillHWRect(_THIS,SDL_Surface *dst,SDL_Rect *dstrect,Uint32 color)
......@@ -234,4 +236,5 @@ int CGX_FillHWRect(_THIS,SDL_Surface *dst,SDL_Rect *dstrect,Uint32 color)
FillPixelArray(&temprp,dstrect->x,dstrect->y,dstrect->w,dstrect->h,color);
}
return 0;
}
......@@ -57,6 +57,7 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
{
if(screen->flags&SDL_HWSURFACE)
{
Uint32 pitch;
SDL_Ximage=NULL;
if(!screen->hwdata)
......@@ -66,14 +67,30 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
return -1;
}
D(bug("Creating system accel struct\n"));
screen->hwdata->lock=0;
screen->hwdata->bmap=SDL_RastPort->BitMap;
screen->hwdata->videodata=this;
}
screen->hwdata->lock=0;
screen->hwdata->bmap=SDL_RastPort->BitMap;
screen->hwdata->videodata=this;
if(!(screen->hwdata->lock=LockBitMapTags(screen->hwdata->bmap,
LBMI_BASEADDRESS,(ULONG)&screen->pixels,
LBMI_BYTESPERROW,(ULONG)&pitch,TAG_DONE)))
{
free(screen->hwdata);
screen->hwdata=NULL;
return -1;
}
else
{
UnLockBitMap(screen->hwdata->lock);
screen->hwdata->lock=NULL;
}
screen->pitch=pitch;
this->UpdateRects = CGX_FakeUpdate;
D(bug("Accel video image configured.\n"));
D(bug("Accel video image configured (%lx, pitch %ld).\n",screen->pixels,screen->pitch));
return 0;
}
......@@ -83,6 +100,18 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
SDL_OutOfMemory();
return(-1);
}
/*
{
int bpp = screen->format->BytesPerPixel;
SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual,
this->hidden->depth, ZPixmap, 0,
(char *)screen->pixels,
screen->w, screen->h,
(bpp == 3) ? 32 : bpp * 8,
0);
}
*/
SDL_Ximage=screen->pixels;
if ( SDL_Ximage == NULL ) {
......@@ -106,16 +135,35 @@ void CGX_DestroyImage(_THIS, SDL_Surface *screen)
}
}
/* This is a hack to see whether this system has more than 1 CPU */
static int num_CPU(void)
{
return 1;
}
int CGX_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags)
{
int retval;
D(bug("Chiamata ResizeImage!\n"));
CGX_DestroyImage(this, screen);
if ( flags & SDL_OPENGL ) { /* No image when using GL */
if ( flags & SDL_OPENGL ) { /* No image when using GL */
retval = 0;
} else {
} else {
retval = CGX_SetupImage(this, screen);
/* We support asynchronous blitting on the display */
if ( flags & SDL_ASYNCBLIT ) {
/* This is actually slower on single-CPU systems,
probably because of CPU contention between the
X server and the application.
Note: Is this still true with XFree86 4.0?
*/
if ( num_CPU() > 1 ) {
screen->flags |= SDL_ASYNCBLIT;
}
}
}
return(retval);
}
......@@ -135,11 +183,11 @@ int CGX_AllocHWSurface(_THIS, SDL_Surface *surface)
{
if(!(surface->hwdata=malloc(sizeof(struct private_hwdata))))
return -1;
surface->hwdata->lock=NULL;
surface->hwdata->videodata=this;
}
surface->hwdata->lock=NULL;
surface->hwdata->videodata=this;
if(surface->hwdata->bmap=AllocBitMap(surface->w,surface->h,this->hidden->depth,BMF_MINPLANES,SDL_Display->RastPort.BitMap))
{
surface->flags|=SDL_HWSURFACE;
......@@ -205,7 +253,7 @@ void CGX_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
UnLockBitMap(surface->hwdata->lock);
surface->hwdata->lock=NULL;
surface->pixels=NULL;
// surface->pixels=NULL;
}
}
......
......@@ -76,6 +76,13 @@ static void get_real_resolution(_THIS, int* w, int* h)
*h = SDL_Display->Height;
}
static void move_cursor_to(_THIS, int x, int y)
{
/* XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y); */
/* DA FARE! */
}
static void add_visual(_THIS, int depth, int class)
{
Uint32 tID;
......
......@@ -40,5 +40,10 @@ extern int CGX_GetVideoModes(_THIS);
extern SDL_Rect **CGX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
extern void CGX_FreeVideoModes(_THIS);
extern int CGX_ResizeFullScreen(_THIS);
/*
extern void CGX_WaitMapped(_THIS, Window win);
extern void CGX_WaitUnmapped(_THIS, Window win);
extern void CGX_QueueEnterFullScreen(_THIS);
*/
extern int CGX_EnterFullScreen(_THIS);
extern int CGX_LeaveFullScreen(_THIS);
This diff is collapsed.
......@@ -69,6 +69,8 @@ struct SDL_PrivateVideoData {
struct Window *SDL_Window; /* Shared by both displays (no X security?) */
unsigned char *BlankCursor; /* The invisible cursor */
char *SDL_windowid; /* Flag: true if we have been passed a window */
/* The variables used for displaying graphics */
Uint8 *Ximage; /* The X image for our window */
int swap_pixels; /* Flag: true if display is swapped endian */
......@@ -134,6 +136,7 @@ struct SDL_PrivateVideoData {
#define SDL_Window (this->hidden->SDL_Window)
#define WM_DELETE_WINDOW (this->hidden->WM_DELETE_WINDOW)
#define SDL_BlankCursor (this->hidden->BlankCursor)
#define SDL_windowid (this->hidden->SDL_windowid)
#define SDL_Ximage (this->hidden->Ximage)
#define SDL_GC (this->hidden->gc)
#define swap_pixels (this->hidden->swap_pixels)
......@@ -152,6 +155,9 @@ struct SDL_PrivateVideoData {
#define SDL_XPixels (this->hidden->XPixels)
#define SDL_iconcolors (this->hidden->iconcolors)
/* Used to get the X cursor from a window-manager specific cursor */
// extern Cursor SDL_GetWMXCursor(WMcursor *cursor);
extern int CGX_CreateWindow(_THIS, SDL_Surface *screen,
int w, int h, int bpp, Uint32 flags);
extern int CGX_ResizeWindow(_THIS,
......
/*
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$";
#endif
/* This is the XFree86 Xv extension implementation of YUV video overlays */
#ifdef XFREE86_XV
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h>
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_x11yuv_c.h"
#include "SDL_yuvfuncs.h"
/* The functions used to manipulate software video overlays */
static struct private_yuvhwfuncs x11_yuvfuncs = {
X11_LockYUVOverlay,
X11_UnlockYUVOverlay,
X11_DisplayYUVOverlay,
X11_FreeYUVOverlay
};
struct private_yuvhwdata {
int port;
XShmSegmentInfo yuvshm;
XvImage *image;
};
SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
{
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
int xv_port;
int i, j;
int adaptors;
XvAdaptorInfo *ainfo;
XShmSegmentInfo *yuvshm;
xv_port = -1;
if ( (Success == XvQueryExtension(GFX_Display, &j, &j, &j, &j, &j)) &&
(Success == XvQueryAdaptors(GFX_Display,
RootWindow(GFX_Display, SDL_Screen),
&adaptors, &ainfo)) ) {
for ( i=0; (i<adaptors) && (xv_port == -1); ++i ) {
if ( (ainfo[i].type & XvInputMask) &&
(ainfo[i].type & XvImageMask) ) {
int num_formats;
XvImageFormatValues *formats;
formats = XvListImageFormats(GFX_Display,
ainfo[i].base_id, &num_formats);
for ( j=0; j<num_formats; ++j ) {
if ( (Uint32)formats[j].id == format ) {
xv_port = ainfo[i].base_id;
break;
}
}
}
}
}
if ( xv_port == -1 ) {
SDL_SetError("No available video ports for requested format");
return(NULL);
}
/* Create the overlay structure */
overlay = (SDL_Overlay *)malloc(sizeof *overlay);
if ( overlay == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
memset(overlay, 0, (sizeof *overlay));
/* Fill in the basic members */
overlay->format = format;
overlay->w = width;
overlay->h = height;
/* Set up the YUV surface function structure */
overlay->hwfuncs = &x11_yuvfuncs;
/* Create the pixel data and lookup tables */
hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata);
overlay->hwdata = hwdata;
if ( hwdata == NULL ) {
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
return(NULL);
}
yuvshm = &hwdata->yuvshm;
memset(yuvshm, 0, sizeof(*yuvshm));
hwdata->port = xv_port;
hwdata->image = XvShmCreateImage(GFX_Display, xv_port, format,
0, width, height, yuvshm);
if ( hwdata->image == NULL ) {
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
return(NULL);
}
yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size,
IPC_CREAT | 0777);
if ( yuvshm->shmid < 0 ) {
SDL_SetError("Unable to get %d bytes shared memory",
hwdata->image->data_size);
SDL_FreeYUVOverlay(overlay);
return(NULL);
}
yuvshm->shmaddr = (caddr_t) shmat(yuvshm->shmid, 0, 0);
yuvshm->readOnly = False;
hwdata->image->data = yuvshm->shmaddr;
XShmAttach(GFX_Display, yuvshm);
XSync(GFX_Display, False);
shmctl(yuvshm->shmid, IPC_RMID, 0);
/* We're all done.. */
return(overlay);
}
int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
{
overlay->pixels = overlay->hwdata->image->data;
/* What should the pitch be set to? */
return(0);
}
void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
{
overlay->pixels = NULL;
}
int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
{
struct private_yuvhwdata *hwdata;
hwdata = overlay->hwdata;
XvShmPutImage(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
hwdata->image, 0, 0, overlay->w, overlay->h,
dstrect->x, dstrect->y, dstrect->w, dstrect->h, False);
XSync(GFX_Display, False);
return(0);
}
void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
{
struct private_yuvhwdata *hwdata;
hwdata = overlay->hwdata;
if ( hwdata ) {
if ( hwdata->yuvshm.shmaddr ) {
XShmDetach(GFX_Display, &hwdata->yuvshm);
shmdt(hwdata->yuvshm.shmaddr);
}
if ( hwdata->image ) {
XFree(hwdata->image);
}
free(hwdata);
}
}
#endif /* XFREE86_XV */
/*
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$";
#endif
/* This is the XFree86 Xv extension implementation of YUV video overlays */
#include "SDL_video.h"
#include "SDL_cgxvideo.h"
#ifdef XFREE86_XV
extern SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
extern int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay);
extern void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay);
extern int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
extern void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay);
#endif /* XFREE86_XV */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment