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 =- ...@@ -169,9 +169,6 @@ QNX: -= NOT YET SUPPORTED =-
The software surfaces could use some speed up. 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 It doesn't look like the OpenGL stuff is there. (did a grep for
PdCreateOpenGLContext, nothing found). PdCreateOpenGLContext, nothing found).
...@@ -187,13 +184,4 @@ AmigaOS: -= NOT YET SUPPORTED =- ...@@ -187,13 +184,4 @@ AmigaOS: -= NOT YET SUPPORTED =-
Continuous relative mouse motion is not implemented. 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 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 ...@@ -1936,6 +1936,7 @@ src/video/photon/Makefile
src/video/dummy/Makefile src/video/dummy/Makefile
src/events/Makefile src/events/Makefile
src/joystick/Makefile src/joystick/Makefile
src/joystick/amigaos/Makefile
src/joystick/beos/Makefile src/joystick/beos/Makefile
src/joystick/dummy/Makefile src/joystick/dummy/Makefile
src/joystick/linux/Makefile src/joystick/linux/Makefile
......
...@@ -76,6 +76,10 @@ static AudioBootStrap *bootstrap[] = { ...@@ -76,6 +76,10 @@ static AudioBootStrap *bootstrap[] = {
#ifdef _AIX #ifdef _AIX
&Paud_bootstrap, &Paud_bootstrap,
#endif #endif
#ifdef ENABLE_AHI
&AHI_bootstrap,
#endif
NULL NULL
}; };
SDL_AudioDevice *current_audio = NULL; SDL_AudioDevice *current_audio = NULL;
...@@ -84,6 +88,9 @@ SDL_AudioDevice *current_audio = NULL; ...@@ -84,6 +88,9 @@ SDL_AudioDevice *current_audio = NULL;
int SDL_AudioInit(const char *driver_name); int SDL_AudioInit(const char *driver_name);
void SDL_AudioQuit(void); void SDL_AudioQuit(void);
#ifdef ENABLE_AHI
static int audio_configured = 0;
#endif
/* The general mixing thread function */ /* The general mixing thread function */
int SDL_RunAudio(void *audiop) int SDL_RunAudio(void *audiop)
...@@ -94,6 +101,21 @@ int SDL_RunAudio(void *audiop) ...@@ -94,6 +101,21 @@ int SDL_RunAudio(void *audiop)
void *udata; void *udata;
void (*fill)(void *userdata,Uint8 *stream, int len); void (*fill)(void *userdata,Uint8 *stream, int len);
int silence; 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 */ /* Perform any thread setup */
if ( audio->ThreadInit ) { if ( audio->ThreadInit ) {
...@@ -104,6 +126,15 @@ int SDL_RunAudio(void *audiop) ...@@ -104,6 +126,15 @@ int SDL_RunAudio(void *audiop)
/* Set up the mixing function */ /* Set up the mixing function */
fill = audio->spec.callback; fill = audio->spec.callback;
udata = audio->spec.userdata; 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.needed ) {
if ( audio->convert.src_format == AUDIO_U8 ) { if ( audio->convert.src_format == AUDIO_U8 ) {
silence = 0x80; silence = 0x80;
...@@ -117,6 +148,12 @@ int SDL_RunAudio(void *audiop) ...@@ -117,6 +148,12 @@ int SDL_RunAudio(void *audiop)
} }
stream = audio->fake_stream; stream = audio->fake_stream;
#ifdef ENABLE_AHI
SDL_mutexV(audio->mixer_lock);
D(bug("Entering audio loop...\n"));
#endif
/* Loop, filling the audio buffers */ /* Loop, filling the audio buffers */
while ( audio->enabled ) { while ( audio->enabled ) {
...@@ -124,12 +161,14 @@ int SDL_RunAudio(void *audiop) ...@@ -124,12 +161,14 @@ int SDL_RunAudio(void *audiop)
if ( stream == audio->fake_stream ) { if ( stream == audio->fake_stream ) {
SDL_Delay((audio->spec.samples*1000)/audio->spec.freq); SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
} else { } else {
#ifdef ENABLE_AHI
if ( started > 1 )
#endif
audio->WaitAudio(audio); audio->WaitAudio(audio);
} }
/* Fill the current buffer with sound */ /* Fill the current buffer with sound */
if ( audio->convert.needed ) { if ( audio->convert.needed ) {
/* The buffer may not be allocated yet */
if ( audio->convert.buf ) { if ( audio->convert.buf ) {
stream = audio->convert.buf; stream = audio->convert.buf;
} else { } else {
...@@ -163,12 +202,25 @@ int SDL_RunAudio(void *audiop) ...@@ -163,12 +202,25 @@ int SDL_RunAudio(void *audiop)
/* Ready current buffer for play and change current buffer */ /* Ready current buffer for play and change current buffer */
if ( stream != audio->fake_stream ) { if ( stream != audio->fake_stream ) {
audio->PlayAudio(audio); 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.. */ /* Wait for the audio to drain.. */
if ( audio->WaitDone ) { if ( audio->WaitDone ) {
audio->WaitDone(audio); 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); return(0);
} }
...@@ -312,11 +364,33 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) ...@@ -312,11 +364,33 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
audio->convert.needed = 0; audio->convert.needed = 0;
audio->enabled = 1; audio->enabled = 1;
audio->paused = 1; audio->paused = 1;
#ifndef ENABLE_AHI
/* AmigaOS opens audio inside the main loop */
audio->opened = audio->OpenAudio(audio, &audio->spec)+1; audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
if ( ! audio->opened ) { if ( ! audio->opened ) {
SDL_CloseAudio(); SDL_CloseAudio();
return(-1); 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 the audio driver changes the buffer size, accept it */
if ( audio->spec.samples != desired->samples ) { if ( audio->spec.samples != desired->samples ) {
...@@ -365,6 +439,7 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) ...@@ -365,6 +439,7 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
} }
} }
#ifndef ENABLE_AHI
/* Start the audio thread if necessary */ /* Start the audio thread if necessary */
switch (audio->opened) { switch (audio->opened) {
case 1: case 1:
...@@ -381,6 +456,12 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) ...@@ -381,6 +456,12 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
/* The audio is now playing */ /* The audio is now playing */
break; break;
} }
#else
SDL_mutexV(audio->mixer_lock);
D(bug("SDL_OpenAudio USCITA...\n"));
#endif
return(0); return(0);
} }
...@@ -457,12 +538,14 @@ void SDL_AudioQuit(void) ...@@ -457,12 +538,14 @@ void SDL_AudioQuit(void)
} }
if ( audio->convert.needed ) { if ( audio->convert.needed ) {
SDL_FreeAudioMem(audio->convert.buf); SDL_FreeAudioMem(audio->convert.buf);
} }
#ifndef ENABLE_AHI
if ( audio->opened ) { if ( audio->opened ) {
audio->CloseAudio(audio); audio->CloseAudio(audio);
audio->opened = 0; audio->opened = 0;
} }
#endif
/* Free the driver data */ /* Free the driver data */
audio->free(audio); audio->free(audio);
current_audio = NULL; current_audio = NULL;
......
...@@ -126,14 +126,17 @@ extern AudioBootStrap DSOUND_bootstrap; ...@@ -126,14 +126,17 @@ extern AudioBootStrap DSOUND_bootstrap;
#ifdef ENABLE_WINDIB #ifdef ENABLE_WINDIB
extern AudioBootStrap WAVEOUT_bootstrap; extern AudioBootStrap WAVEOUT_bootstrap;
#endif #endif
#ifdef _AIX
extern AudioBootStrap Paud_bootstrap;
#endif
#ifdef __BEOS__ #ifdef __BEOS__
extern AudioBootStrap BAUDIO_bootstrap; extern AudioBootStrap BAUDIO_bootstrap;
#endif #endif
#if defined(macintosh) || TARGET_API_MAC_CARBON #if defined(macintosh) || TARGET_API_MAC_CARBON
extern AudioBootStrap SNDMGR_bootstrap; extern AudioBootStrap SNDMGR_bootstrap;
#endif #endif
#ifdef _AIX #ifdef ENABLE_AHI
extern AudioBootStrap Paud_bootstrap; extern AudioBootStrap AHI_bootstrap;
#endif #endif
/* This is the current audio device */ /* This is the current audio device */
......
...@@ -3,6 +3,6 @@ ...@@ -3,6 +3,6 @@
noinst_LTLIBRARIES = libaudio_arch.la 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) libaudio_arch_la_SOURCES = $(ARCH_SRCS)
...@@ -27,13 +27,17 @@ static char rcsid = ...@@ -27,13 +27,17 @@ static char rcsid =
"@(#) $Id$"; "@(#) $Id$";
#endif #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_endian.h"
#include "SDL_audio.h" #include "SDL_audio.h"
#include "SDL_audiomem.h" #include "SDL_audiomem.h"
#include "SDL_audio_c.h" #include "SDL_audio_c.h"
#include "SDL_lowaudio.h" #include "SDL_ahiaudio.h"
/* Audio driver functions */ /* Audio driver functions */
static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec); static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec);
...@@ -54,11 +58,29 @@ static void AHI_CloseAudio(_THIS); ...@@ -54,11 +58,29 @@ static void AHI_CloseAudio(_THIS);
static int Audio_Available(void) static int Audio_Available(void)
{ {
#ifndef NO_AMIGADEBUG int ok=0;
D(bug("AHI available.\n")); struct MsgPort *p;
#endif 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) static void Audio_DeleteDevice(SDL_AudioDevice *device)
...@@ -125,7 +147,7 @@ static void AHI_PlayAudio(_THIS) ...@@ -125,7 +147,7 @@ static void AHI_PlayAudio(_THIS)
/* Write the audio data out */ /* 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_Message.mn_Node.ln_Pri = 60;
audio_req[current_buffer] -> ahir_Std. io_Data = mixbuf[current_buffer]; 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_Offset = 0;
audio_req[current_buffer] -> ahir_Std . io_Command = CMD_WRITE; audio_req[current_buffer] -> ahir_Std . io_Command = CMD_WRITE;
audio_req[current_buffer] -> ahir_Frequency = this->hidden->freq; audio_req[current_buffer] -> ahir_Frequency = this->hidden->freq;
...@@ -149,43 +171,58 @@ static void AHI_CloseAudio(_THIS) ...@@ -149,43 +171,58 @@ static void AHI_CloseAudio(_THIS)
{ {
D(bug("Closing audio...\n")); 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; playing=0;
if(audio_req[0]) if(audio_req[0])
{ {
if(audio_req[1]) if(audio_req[1])
{ {
if(!CheckIO((struct IORequest *)audio_req[1])) D(bug("Break req[1]...\n"));
{
AbortIO((struct IORequest *)audio_req[1]); AbortIO((struct IORequest *)audio_req[1]);
WaitIO((struct IORequest *)audio_req[1]); WaitIO((struct IORequest *)audio_req[1]);
}
myfree(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]); D(bug("Break AGAIN req[1]...\n"));
WaitIO((struct IORequest *)audio_req[0]); 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]); 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]); DeleteIORequest((struct IORequest *)audio_req[0]);
audio_req[0]=audio_req[1]=NULL; 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 ) { if ( audio_port != NULL ) {
DeleteMsgPort(audio_port); DeleteMsgPort(audio_port);
audio_port = NULL; audio_port = NULL;
...@@ -206,8 +243,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -206,8 +243,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("Samples a 8 bit...\n")); D(bug("Samples a 8 bit...\n"));
spec->format = AUDIO_S8; spec->format = AUDIO_S8;
this->hidden->bytespersample=1; 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; break;
...@@ -215,7 +254,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -215,7 +254,10 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("Samples a 16 bit...\n")); D(bug("Samples a 16 bit...\n"));
spec->format = AUDIO_S16MSB; spec->format = AUDIO_S16MSB;
this->hidden->bytespersample=2; 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; break;
...@@ -225,6 +267,13 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -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")); D(bug("Before CalculateAudioSpec\n"));
/* Update the fragment size as size in bytes */ /* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec); SDL_CalculateAudioSpec(spec);
...@@ -258,8 +307,9 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -258,8 +307,9 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
D(bug("AFTER opendevice\n")); D(bug("AFTER opendevice\n"));
/* Set output frequency */ /* Set output frequency and size */
this->hidden->freq = spec->freq; this->hidden->freq = spec->freq;
this->hidden->size = spec->size;
D(bug("Before buffer allocation\n")); D(bug("Before buffer allocation\n"));
...@@ -292,7 +342,7 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -292,7 +342,7 @@ static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
current_buffer=0; current_buffer=0;
playing=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. :-) */ /* We're ready to rock and roll. :-) */
return(0); return(0);
......
...@@ -25,15 +25,20 @@ static char rcsid = ...@@ -25,15 +25,20 @@ static char rcsid =
"@(#) $Id$"; "@(#) $Id$";
#endif #endif
#ifndef _SDL_lowaudio_h #ifndef _SDL_ahiaudio_h
#define _SDL_lowaudio_h #define _SDL_ahiaudio_h
// #include <libraries/ahi_sub.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 "SDL_sysaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Hidden "this" pointer for the audio functions */ /* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this #define _THIS SDL_AudioDevice *this
...@@ -55,4 +60,4 @@ struct SDL_PrivateAudioData { ...@@ -55,4 +60,4 @@ struct SDL_PrivateAudioData {
#define current_buffer (this->hidden->current_buffer) #define current_buffer (this->hidden->current_buffer)
#define playing (this->hidden->playing) #define playing (this->hidden->playing)
#endif /* _SDL_lowaudio_h */ #endif /* _SDL_ahiaudio_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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Allow access to a raw mixing buffer */
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_timer.h"
#include "SDL_error.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
/* Available audio drivers */
static AudioBootStrap *bootstrap[] = {
#ifdef unix
&AUDIO_bootstrap,
#endif
#ifdef linux
&DMA_bootstrap,
#endif
#ifdef ESD_SUPPORT
&ESD_bootstrap,
#endif
#ifdef ENABLE_DIRECTX
&DSOUND_bootstrap,
#endif
#ifdef ENABLE_WINDIB
&WAVEOUT_bootstrap,
#endif
#ifdef __BEOS__
&BAUDIO_bootstrap,
#endif
#ifdef macintosh
&AUDIO_bootstrap,
#endif
#ifdef _AIX
&Paud_bootstrap,
#endif
#ifdef ENABLE_CYBERGRAPHICS
&AHI_bootstrap,
#endif
NULL
};
SDL_AudioDevice *current_audio = NULL;
/* Various local functions */
int SDL_AudioInit(const char *driver_name);
void SDL_AudioQuit(void);
struct SignalSemaphore AudioSem;
/* The general mixing thread function */
int RunAudio(void *audiop)
{
SDL_AudioDevice *audio = (SDL_AudioDevice *)audiop;
Uint8 *stream;
int stream_len;
void *udata;
void (*fill)(void *userdata,Uint8 *stream, int len);
int silence,started=0;
D(bug("Task audio started audio struct:<%lx>...\n",audiop));
D(bug("Before Openaudio..."));
if(audio->OpenAudio(audio, &audio->spec)==-1)
{
return(-1);
}
D(bug("OpenAudio...OK\n"));
/* Perform any thread setup */
if ( audio->ThreadInit ) {
audio->ThreadInit(audio);
}
audio->threadid = SDL_ThreadID();
/* Set up the mixing function */
fill = audio->spec.callback;
udata = audio->spec.userdata;
if ( audio->convert.needed ) {
if ( audio->convert.src_format == AUDIO_U8 ) {
silence = 0x80;
D(bug("*** Silence 0x80 ***\n"));
} else {
silence = 0;
}
stream_len = audio->convert.len;
} else {
silence = audio->spec.silence;
stream_len = audio->spec.size;
}
stream = audio->fake_stream;
ObtainSemaphore(&AudioSem);
ReleaseSemaphore(&AudioSem);
D(bug("Enering audio loop...\n"));
D(if(audio->convert.needed)bug("*** Conversion needed.\n"));
/* Loop, filling the audio buffers */
while ( audio->enabled )
{
/* Wait for new current buffer to finish playing */
if ( stream == audio->fake_stream )
SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
else
{
if(started>1)
{
// D(bug("Waiting audio...\n"));
audio->WaitAudio(audio);
}
}
ObtainSemaphore(&AudioSem);
/* Fill the current buffer with sound */
if ( audio->convert.needed ) {
stream = audio->convert.buf;
} else {
stream = audio->GetAudioBuf(audio);
}
if(stream!=audio->fake_stream)
memset(stream, silence, stream_len);
if ( ! audio->paused ) {
ObtainSemaphore(&audio->mixer_lock);
(*fill)(udata, stream, stream_len);
ReleaseSemaphore(&audio->mixer_lock);
}
/* Convert the audio if necessary */
if ( audio->convert.needed ) {
SDL_ConvertAudio(&audio->convert);
stream = audio->GetAudioBuf(audio);
memcpy(stream, audio->convert.buf,audio->convert.len_cvt);
}
if(stream!=audio->fake_stream)
{
// D(bug("Playing stream at %lx\n",stream));
audio->PlayAudio(audio);
started++;
}
ReleaseSemaphore(&AudioSem);
}
D(bug("Out of subtask loop...\n"));
/* Wait for the audio to drain.. */
if ( audio->WaitDone ) {
audio->WaitDone(audio);
}
D(bug("WaitAudio...Done\n"));
audio->CloseAudio(audio);
D(bug("CloseAudio..Done, subtask exiting...\n"));
return(0);
}
int SDL_AudioInit(const char *driver_name)
{
SDL_AudioDevice *audio;
int i = 0, idx;
/* Check to make sure we don't overwrite 'current_audio' */
if ( current_audio != NULL ) {
SDL_AudioQuit();
}
/* Select the proper audio driver */
audio = NULL;
idx = 0;
InitSemaphore(&AudioSem);
if ( audio == NULL ) {
if ( driver_name != NULL ) {
if ( strrchr(driver_name, ':') != NULL ) {
idx = atoi(strrchr(driver_name, ':')+1);
}
for ( i=0; bootstrap[i]; ++i ) {
if (strncmp(bootstrap[i]->name, driver_name,
strlen(bootstrap[i]->name)) == 0) {
if ( bootstrap[i]->available() ) {
audio=bootstrap[i]->create(idx);
break;
}
}
}
} else {
for ( i=0; bootstrap[i]; ++i ) {
if ( bootstrap[i]->available() ) {
audio = bootstrap[i]->create(idx);
if ( audio != NULL ) {
break;
}
}
}
}
if ( audio == NULL ) {
SDL_SetError("No available audio device");
#if 0 /* Don't fail SDL_Init() if audio isn't available.
SDL_OpenAudio() will handle it at that point. *sigh*
*/
return(-1);
#endif
}
}
current_audio = audio;
if ( current_audio ) {
current_audio->name = bootstrap[i]->name;
}
return(0);
}
char *SDL_AudioDriverName(char *namebuf, int maxlen)
{
if ( current_audio != NULL ) {
strncpy(namebuf, current_audio->name, maxlen-1);
namebuf[maxlen-1] = '\0';
return(namebuf);
}
return(NULL);
}
int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
{
SDL_AudioDevice *audio;
/* Start up the audio driver, if necessary */
if ( ! current_audio ) {
if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
(current_audio == NULL) ) {
return(-1);
}
}
audio = current_audio;
D(bug("Chiamata SDL_OpenAudio...\n"));
/* Verify some parameters */
if ( desired->callback == NULL ) {
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
return(-1);
}
switch ( desired->channels ) {
case 1: /* Mono */
case 2: /* Stereo */
break;
default:
SDL_SetError("1 (mono) and 2 (stereo) channels supported");
return(-1);
}
/* Create a semaphore for locking the sound buffers */
InitSemaphore(&audio->mixer_lock);
/* Calculate the silence and size of the audio specification */
SDL_CalculateAudioSpec(desired);
/* Open the audio subsystem */
memcpy(&audio->spec, desired, sizeof(audio->spec));
audio->convert.needed = 0;
audio->enabled = 1;
audio->paused = 1;
ObtainSemaphore(&AudioSem);
audio->thread = SDL_CreateThread(RunAudio, audio);
if ( audio->thread == NULL ) {
ReleaseSemaphore(&AudioSem);
SDL_CloseAudio();
SDL_SetError("Couldn't create audio thread");
return(-1);
}
/* If the audio driver changes the buffer size, accept it */
if ( audio->spec.samples != desired->samples ) {
desired->samples = audio->spec.samples;
SDL_CalculateAudioSpec(desired);
}
/* Allocate a fake audio memory buffer */
audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
if ( audio->fake_stream == NULL ) {
ReleaseSemaphore(&AudioSem);
SDL_CloseAudio();
SDL_OutOfMemory();
return(-1);
}
/* See if we need to do any conversion */
if ( memcmp(desired, &audio->spec, sizeof(audio->spec)) == 0 ) {
/* Just copy over the desired audio specification */
if ( obtained != NULL ) {
memcpy(obtained, &audio->spec, sizeof(audio->spec));
}
} else {
/* Copy over the audio specification if possible */
if ( obtained != NULL ) {
memcpy(obtained, &audio->spec, sizeof(audio->spec));
} else {
/* Build an audio conversion block */
D(bug("Need conversion:\n desired: C:%ld F:%ld T:%lx\navailable: C:%ld F:%ld T:%lx\n",
desired->channels, desired->freq, desired->format,
audio->spec.channels,audio->spec.freq,audio->spec.format));
Forbid();
// Magari poi lo sostiutisco con un semaforo.
if ( SDL_BuildAudioCVT(&audio->convert,
desired->format, desired->channels,
desired->freq,
audio->spec.format, audio->spec.channels,
audio->spec.freq) < 0 ) {
ReleaseSemaphore(&AudioSem);
SDL_CloseAudio();
return(-1);
}
if ( audio->convert.needed ) {
audio->convert.len = desired->size;
audio->convert.buf =(Uint8 *)SDL_AllocAudioMem(
audio->convert.len*audio->convert.len_mult);
if ( audio->convert.buf == NULL ) {
ReleaseSemaphore(&AudioSem);
SDL_CloseAudio();
SDL_OutOfMemory();
return(-1);
}
}
}
}
ReleaseSemaphore(&AudioSem);
D(bug("SDL_OpenAudio USCITA...\n"));
return(0);
}
SDL_audiostatus SDL_GetAudioStatus(void)
{
SDL_AudioDevice *audio = current_audio;
SDL_audiostatus status;
status = SDL_AUDIO_STOPPED;
if ( audio && audio->enabled ) {
if ( audio->paused ) {
status = SDL_AUDIO_PAUSED;
} else {
status = SDL_AUDIO_PLAYING;
}
}
return(status);
}
void SDL_PauseAudio (int pause_on)
{
SDL_AudioDevice *audio = current_audio;
if ( audio ) {
audio->paused = pause_on;
}
}
void SDL_LockAudio (void)
{
SDL_AudioDevice *audio = current_audio;
/* Obtain a lock on the mixing buffers */
if ( audio ) {
if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
return;
}
ObtainSemaphore(&audio->mixer_lock);
}
}
void SDL_UnlockAudio (void)
{
SDL_AudioDevice *audio = current_audio;
/* Release lock on the mixing buffers */
if ( audio ) {
if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
return;
}
ReleaseSemaphore(&audio->mixer_lock);
}
}
void SDL_CloseAudio (void)
{
SDL_AudioDevice *audio = current_audio;
if ( audio ) {
if(audio->enabled)
{
audio->enabled = 0;
if ( audio->thread != NULL ) {
D(bug("Waiting audio thread...\n"));
SDL_WaitThread(audio->thread, NULL);
D(bug("...audio replied\n"));
}
}
if ( audio->fake_stream != NULL ) {
SDL_FreeAudioMem(audio->fake_stream);
audio->fake_stream=NULL;
}
if ( audio->convert.needed && current_audio->convert.buf!=NULL) {
SDL_FreeAudioMem(audio->convert.buf);
current_audio->convert.buf=NULL;
}
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
void SDL_AudioQuit(void)
{
if ( current_audio ) {
if(current_audio->enabled)
{
D(bug("Closing audio in AudioQuit...\n"));
current_audio->enabled = 0;
if ( current_audio->thread != NULL ) {
D(bug("Waiting audio thread...\n"));
SDL_WaitThread(current_audio->thread, NULL);
D(bug("...audio replied\n"));
}
}
if ( current_audio->fake_stream != NULL ) {
SDL_FreeAudioMem(current_audio->fake_stream);
}
if ( current_audio->convert.needed &&
current_audio->convert.buf) {
SDL_FreeAudioMem(current_audio->convert.buf);
}
current_audio->free(current_audio);
current_audio = NULL;
}
}
#define NUM_FORMATS 6
static int format_idx;
static int format_idx_sub;
static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
{ AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
{ AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
{ AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
{ AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
{ AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
{ AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
};
Uint16 SDL_FirstAudioFormat(Uint16 format)
{
for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) {
if ( format_list[format_idx][0] == format ) {
break;
}
}
format_idx_sub = 0;
return(SDL_NextAudioFormat());
}
Uint16 SDL_NextAudioFormat(void)
{
if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) {
return(0);
}
return(format_list[format_idx][format_idx_sub++]);
}
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
{
switch (spec->format) {
case AUDIO_U8:
spec->silence = 0x80;
break;
default:
spec->silence = 0x00;
break;
}
spec->size = (spec->format&0xFF)/8;
spec->size *= spec->channels;
spec->size *= spec->samples;
}
/*
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 = ...@@ -25,7 +25,7 @@ static char rcsid =
"@(#) $Id$"; "@(#) $Id$";
#endif #endif
/* An native implementation of semaphores on AmigaOS */ /* An implementation of semaphores using mutexes and condition variables */
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_thread.h" #include "SDL_thread.h"
...@@ -35,9 +35,13 @@ static char rcsid = ...@@ -35,9 +35,13 @@ static char rcsid =
struct SDL_semaphore struct SDL_semaphore
{ {
struct SignalSemaphore Sem; struct SignalSemaphore Sem;
Uint32 count;
Uint32 waiters_count;
SDL_mutex *count_lock;
SDL_cond *count_nonzero;
}; };
#undef D(x) #undef D
#define D(x) #define D(x)
...@@ -46,20 +50,18 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) ...@@ -46,20 +50,18 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
SDL_sem *sem; SDL_sem *sem;
sem = (SDL_sem *)malloc(sizeof(*sem)); sem = (SDL_sem *)malloc(sizeof(*sem));
if ( ! sem ) { if ( ! sem ) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return(0); return(0);
} }
memset(sem, 0, sizeof(*sem));
D(bug("Creating semaphore %lx...\n",sem)); D(bug("Creating semaphore %lx...\n",sem));
memset(sem,0,sizeof(*sem));
InitSemaphore(&sem->Sem); InitSemaphore(&sem->Sem);
#if 1 // Allow multiple obtainings of the semaphore
while ( initial_value-- ) {
ReleaseSemaphore(&sem->Sem);
}
#endif
return(sem); return(sem);
} }
...@@ -75,8 +77,6 @@ void SDL_DestroySemaphore(SDL_sem *sem) ...@@ -75,8 +77,6 @@ void SDL_DestroySemaphore(SDL_sem *sem)
int SDL_SemTryWait(SDL_sem *sem) int SDL_SemTryWait(SDL_sem *sem)
{ {
int retval;
if ( ! sem ) { if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore"); SDL_SetError("Passed a NULL semaphore");
return -1; return -1;
...@@ -84,17 +84,17 @@ int SDL_SemTryWait(SDL_sem *sem) ...@@ -84,17 +84,17 @@ int SDL_SemTryWait(SDL_sem *sem)
D(bug("TryWait semaphore...%lx\n",sem)); D(bug("TryWait semaphore...%lx\n",sem));
retval = SDL_MUTEX_TIMEDOUT; ObtainSemaphore(&sem->Sem);
if ( AttemptSemaphore(&sem->Sem) ) { // ReleaseSemaphore(&sem->Sem);
retval = 0;
} return 1;
return retval;
} }
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{ {
int retval; int retval;
if ( ! sem ) { if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore"); SDL_SetError("Passed a NULL semaphore");
return -1; return -1;
...@@ -102,16 +102,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) ...@@ -102,16 +102,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
D(bug("WaitTimeout (%ld) semaphore...%lx\n",timeout,sem)); D(bug("WaitTimeout (%ld) semaphore...%lx\n",timeout,sem));
#if 1 // We need to keep trying the semaphore until the timeout expires /* A timeout of 0 is an easy case */
retval = SDL_MUTEX_TIMEDOUT; if ( timeout == 0 ) {
then = SDL_GetTicks(); return SDL_SemTryWait(sem);
do { }
if ( AttemptSemaphore(&sem->Sem) ) { /*
retval = 0; SDL_LockMutex(sem->count_lock);
} ++sem->waiters_count;
now = SDL_GetTicks(); retval = 0;
} while ( (retval == SDL_MUTEX_TIMEDOUT) && ((now-then) < timeout) ); while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
#else 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))) if(!(retval=AttemptSemaphore(&sem->Sem)))
{ {
SDL_Delay(timeout); SDL_Delay(timeout);
...@@ -123,22 +129,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) ...@@ -123,22 +129,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
// ReleaseSemaphore(&sem->Sem); // ReleaseSemaphore(&sem->Sem);
retval=1; retval=1;
} }
#endif
return retval; return retval;
} }
int SDL_SemWait(SDL_sem *sem) 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); ObtainSemaphore(&sem->Sem);
return 0; return 0;
#else // return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
#endif
} }
Uint32 SDL_SemValue(SDL_sem *sem) Uint32 SDL_SemValue(SDL_sem *sem)
...@@ -148,6 +147,7 @@ Uint32 SDL_SemValue(SDL_sem *sem) ...@@ -148,6 +147,7 @@ Uint32 SDL_SemValue(SDL_sem *sem)
value = 0; value = 0;
if ( sem ) { if ( sem ) {
value = sem->Sem.ss_NestCount; value = sem->Sem.ss_NestCount;
// SDL_UnlockMutex(sem->count_lock);
} }
return value; return value;
} }
...@@ -161,6 +161,14 @@ int SDL_SemPost(SDL_sem *sem) ...@@ -161,6 +161,14 @@ int SDL_SemPost(SDL_sem *sem)
D(bug("SemPost semaphore...%lx\n",sem)); D(bug("SemPost semaphore...%lx\n",sem));
ReleaseSemaphore(&sem->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; return 0;
} }
...@@ -25,7 +25,7 @@ static char rcsid = ...@@ -25,7 +25,7 @@ static char rcsid =
"@(#) $Id$"; "@(#) $Id$";
#endif #endif
/* AmigaOS thread management routines for SDL */ /* BeOS thread management routines for SDL */
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_mutex.h" #include "SDL_mutex.h"
...@@ -40,6 +40,8 @@ typedef struct { ...@@ -40,6 +40,8 @@ typedef struct {
struct Task *wait; struct Task *wait;
} thread_args; } thread_args;
#ifndef MORPHOS
#if defined(__SASC) && !defined(__PPC__) #if defined(__SASC) && !defined(__PPC__)
__saveds __asm Uint32 RunThread(register __a0 char *args ) __saveds __asm Uint32 RunThread(register __a0 char *args )
#elif defined(__PPC__) #elif defined(__PPC__)
...@@ -60,6 +62,34 @@ Uint32 RunThread(char *args __asm("a0") ) ...@@ -60,6 +62,34 @@ Uint32 RunThread(char *args __asm("a0") )
return(0); 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) int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{ {
/* Create the thread and go! */ /* Create the thread and go! */
...@@ -98,6 +128,7 @@ Uint32 SDL_ThreadID(void) ...@@ -98,6 +128,7 @@ Uint32 SDL_ThreadID(void)
void SDL_SYS_WaitThread(SDL_Thread *thread) void SDL_SYS_WaitThread(SDL_Thread *thread)
{ {
SetSignal(0L,SIGBREAKF_CTRL_F|SIGBREAKF_CTRL_C);
Wait(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) ...@@ -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) void SDL_KillThread(SDL_Thread *thread)
{ {
if ( thread ) { if ( thread ) {
......
...@@ -26,98 +26,221 @@ static char rcsid = ...@@ -26,98 +26,221 @@ static char rcsid =
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <time.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.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_error.h"
#include "SDL_timer.h" #include "SDL_timer.h"
#include "SDL_timer_c.h" #include "SDL_timer_c.h"
#if defined(DISABLE_THREADS) || defined(FORK_HACK)
#define USE_ITIMER
#endif
/* The first ticks value of the application */ /* The first ticks value of the application */
static struct timeval start;
#ifndef __PPC__
static clock_t start;
void SDL_StartTicks(void) void SDL_StartTicks(void)
{ {
/* Set first ticks value */ /* Set first ticks value */
gettimeofday(&start, NULL); start=clock();
} }
Uint32 SDL_GetTicks (void) Uint32 SDL_GetTicks (void)
{ {
struct timeval now; clock_t ticks;
Uint32 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); return(ticks);
#else
// CLOCKS_PER_SEC != 1000 !
return ticks*(1000/CLOCKS_PER_SEC);
#endif
} }
void SDL_Delay (Uint32 ms) void SDL_Delay (Uint32 ms)
{ {
int was_error; // Do a busy wait if time is less than 50ms
#ifndef linux /* Non-Linux implementations need to calculate time left */
Uint32 then, now, elapsed; if(ms<50)
{
clock_t to_wait=clock();
#ifndef __SASC
ms*=(CLOCKS_PER_SEC/1000);
#endif #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 #else
then = SDL_GetTicks();
#endif ULONG MY_CLOCKS_PER_SEC;
do {
errno = 0; void PPC_TimerInit(void);
#ifndef linux APTR MyTimer;
/* Calculate the time interval left (in case of interrupt) */
now = SDL_GetTicks(); ULONG start[2];
elapsed = (now-then);
then = now; void SDL_StartTicks(void)
if ( elapsed >= ms ) { {
break; /* 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; else
tv.tv_usec = (ms%1000)*1000; {
#endif Delay(ms/50);
was_error = select(0, NULL, NULL, NULL, &tv); }
} while ( was_error && (errno == EINTR) ); }
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" #include "SDL_thread.h"
/* Data to handle a single periodic alarm */ /* Data to handle a single periodic alarm */
static int timer_alive = 0; static int timer_alive = 0;
static SDL_Thread *timer = NULL; static SDL_Thread *timer_thread = NULL;
static int RunTimer(void *unused) static int RunTimer(void *unused)
{ {
D(bug("SYSTimer: Entering RunTimer loop..."));
if(GfxBase==NULL)
GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37);
while ( timer_alive ) { while ( timer_alive ) {
if ( SDL_timer_running ) { if ( SDL_timer_running ) {
SDL_ThreadedTimerCheck(); 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); return(0);
} }
/* This is only called if the event thread is not running */ /* This is only called if the event thread is not running */
int SDL_SYS_TimerInit(void) int SDL_SYS_TimerInit(void)
{ {
#ifdef NO_AMIGADEBUG D(bug("Creo il thread per il timer (NOITMER)...\n"));
fprintf(stderr,"Creo il thread per il timer (NOITMER)...\n");
#endif
timer_alive = 1; timer_alive = 1;
timer = SDL_CreateThread(RunTimer, NULL); timer_thread = SDL_CreateThread(RunTimer, NULL);
if ( timer == NULL ) if ( timer_thread == NULL )
{ {
#ifdef NO_AMIGADEBUG D(bug("Creazione del thread fallita...\n"));
fprintf(stderr,"Creazione del thread fallita...\n");
#endif
return(-1); return(-1);
} }
...@@ -127,15 +250,15 @@ int SDL_SYS_TimerInit(void) ...@@ -127,15 +250,15 @@ int SDL_SYS_TimerInit(void)
void SDL_SYS_TimerQuit(void) void SDL_SYS_TimerQuit(void)
{ {
timer_alive = 0; timer_alive = 0;
if ( timer ) { if ( timer_thread ) {
SDL_WaitThread(timer, NULL); SDL_WaitThread(timer_thread, NULL);
timer = NULL; timer_thread = NULL;
} }
} }
int SDL_SYS_StartTimer(void) 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); return(-1);
} }
......
...@@ -255,8 +255,8 @@ printf("MapNotify!\n"); ...@@ -255,8 +255,8 @@ printf("MapNotify!\n");
/* Have we been resized? */ /* Have we been resized? */
case IDCMP_NEWSIZE: case IDCMP_NEWSIZE:
SDL_PrivateResize(SDL_Window->Width, SDL_PrivateResize(SDL_Window->Width-SDL_Window->BorderLeft-SDL_Window->BorderRight,
SDL_Window->Height); SDL_Window->Height-SDL_Window->BorderTop-SDL_Window->BorderBottom);
break; break;
/* Have we been requested to quit? */ /* Have we been requested to quit? */
......
...@@ -214,6 +214,8 @@ static int CGX_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, ...@@ -214,6 +214,8 @@ static int CGX_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
} }
else if(dst->hwdata) 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); 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) 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) ...@@ -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); FillPixelArray(&temprp,dstrect->x,dstrect->y,dstrect->w,dstrect->h,color);
} }
return 0;
} }
...@@ -57,6 +57,7 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen) ...@@ -57,6 +57,7 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
{ {
if(screen->flags&SDL_HWSURFACE) if(screen->flags&SDL_HWSURFACE)
{ {
Uint32 pitch;
SDL_Ximage=NULL; SDL_Ximage=NULL;
if(!screen->hwdata) if(!screen->hwdata)
...@@ -66,14 +67,30 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen) ...@@ -66,14 +67,30 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
return -1; return -1;
} }
D(bug("Creating system accel struct\n")); 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; 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; return 0;
} }
...@@ -83,6 +100,18 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen) ...@@ -83,6 +100,18 @@ int CGX_SetupImage(_THIS, SDL_Surface *screen)
SDL_OutOfMemory(); SDL_OutOfMemory();
return(-1); 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; SDL_Ximage=screen->pixels;
if ( SDL_Ximage == NULL ) { if ( SDL_Ximage == NULL ) {
...@@ -106,16 +135,35 @@ void CGX_DestroyImage(_THIS, SDL_Surface *screen) ...@@ -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 CGX_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags)
{ {
int retval; int retval;
D(bug("Chiamata ResizeImage!\n"));
CGX_DestroyImage(this, screen); CGX_DestroyImage(this, screen);
if ( flags & SDL_OPENGL ) { /* No image when using GL */ if ( flags & SDL_OPENGL ) { /* No image when using GL */
retval = 0; retval = 0;
} else { } else {
retval = CGX_SetupImage(this, screen); 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); return(retval);
} }
...@@ -135,11 +183,11 @@ int CGX_AllocHWSurface(_THIS, SDL_Surface *surface) ...@@ -135,11 +183,11 @@ int CGX_AllocHWSurface(_THIS, SDL_Surface *surface)
{ {
if(!(surface->hwdata=malloc(sizeof(struct private_hwdata)))) if(!(surface->hwdata=malloc(sizeof(struct private_hwdata))))
return -1; 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)) if(surface->hwdata->bmap=AllocBitMap(surface->w,surface->h,this->hidden->depth,BMF_MINPLANES,SDL_Display->RastPort.BitMap))
{ {
surface->flags|=SDL_HWSURFACE; surface->flags|=SDL_HWSURFACE;
...@@ -205,7 +253,7 @@ void CGX_UnlockHWSurface(_THIS, SDL_Surface *surface) ...@@ -205,7 +253,7 @@ void CGX_UnlockHWSurface(_THIS, SDL_Surface *surface)
{ {
UnLockBitMap(surface->hwdata->lock); UnLockBitMap(surface->hwdata->lock);
surface->hwdata->lock=NULL; surface->hwdata->lock=NULL;
surface->pixels=NULL; // surface->pixels=NULL;
} }
} }
......
...@@ -76,6 +76,13 @@ static void get_real_resolution(_THIS, int* w, int* h) ...@@ -76,6 +76,13 @@ static void get_real_resolution(_THIS, int* w, int* h)
*h = SDL_Display->Height; *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) static void add_visual(_THIS, int depth, int class)
{ {
Uint32 tID; Uint32 tID;
......
...@@ -40,5 +40,10 @@ extern int CGX_GetVideoModes(_THIS); ...@@ -40,5 +40,10 @@ extern int CGX_GetVideoModes(_THIS);
extern SDL_Rect **CGX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); extern SDL_Rect **CGX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
extern void CGX_FreeVideoModes(_THIS); extern void CGX_FreeVideoModes(_THIS);
extern int CGX_ResizeFullScreen(_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_EnterFullScreen(_THIS);
extern int CGX_LeaveFullScreen(_THIS); extern int CGX_LeaveFullScreen(_THIS);
...@@ -64,8 +64,7 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat); ...@@ -64,8 +64,7 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int CGX_ToggleFullScreen(_THIS, int on); static int CGX_ToggleFullScreen(_THIS, int on);
static void CGX_UpdateMouse(_THIS); static void CGX_UpdateMouse(_THIS);
static int CGX_SetColors(_THIS, int firstcolor, int ncolors, static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
SDL_Color *colors);
static void CGX_VideoQuit(_THIS); static void CGX_VideoQuit(_THIS);
/* CGX driver bootstrap functions */ /* CGX driver bootstrap functions */
...@@ -110,6 +109,7 @@ static void DestroyScreen(_THIS) ...@@ -110,6 +109,7 @@ static void DestroyScreen(_THIS)
this->hidden->dbuffer=0; this->hidden->dbuffer=0;
} }
CloseScreen(GFX_Display); CloseScreen(GFX_Display);
currently_fullscreen=0;
} }
else else
UnlockPubScreen(NULL,GFX_Display); UnlockPubScreen(NULL,GFX_Display);
...@@ -173,6 +173,9 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex) ...@@ -173,6 +173,9 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex)
device->SetVideoMode = CGX_SetVideoMode; device->SetVideoMode = CGX_SetVideoMode;
device->ToggleFullScreen = CGX_ToggleFullScreen; device->ToggleFullScreen = CGX_ToggleFullScreen;
device->UpdateMouse = CGX_UpdateMouse; device->UpdateMouse = CGX_UpdateMouse;
#ifdef XFREE86_XV
device->CreateYUVOverlay = X11_CreateYUVOverlay;
#endif
device->SetColors = CGX_SetColors; device->SetColors = CGX_SetColors;
device->UpdateRects = NULL; device->UpdateRects = NULL;
device->VideoQuit = CGX_VideoQuit; device->VideoQuit = CGX_VideoQuit;
...@@ -192,8 +195,8 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex) ...@@ -192,8 +195,8 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex)
device->GL_MakeCurrent = X11_GL_MakeCurrent; device->GL_MakeCurrent = X11_GL_MakeCurrent;
device->GL_SwapBuffers = X11_GL_SwapBuffers; device->GL_SwapBuffers = X11_GL_SwapBuffers;
#endif #endif
device->SetCaption = CGX_SetCaption;
device->SetIcon = CGX_SetIcon; device->SetIcon = CGX_SetIcon;
device->SetCaption = CGX_SetCaption;
device->IconifyWindow = NULL; /* CGX_IconifyWindow; */ device->IconifyWindow = NULL; /* CGX_IconifyWindow; */
device->GrabInput = NULL /* CGX_GrabInput*/; device->GrabInput = NULL /* CGX_GrabInput*/;
device->GetWMInfo = CGX_GetWMInfo; device->GetWMInfo = CGX_GetWMInfo;
...@@ -211,10 +214,114 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex) ...@@ -211,10 +214,114 @@ static SDL_VideoDevice *CGX_CreateDevice(int devindex)
} }
VideoBootStrap CGX_bootstrap = { VideoBootStrap CGX_bootstrap = {
"CGX", "Amiga CyberGFX video", "CGX", "AmigaOS CyberGraphics", CGX_Available, CGX_CreateDevice
CGX_Available, CGX_CreateDevice
}; };
#if 0
/* Create auxiliary (toplevel) windows with the current visual */
static void create_aux_windows(_THIS)
{
XSetWindowAttributes xattr;
XWMHints *hints;
XTextProperty titleprop, iconprop;
int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen));
/* Don't create any extra windows if we are being managed */
if ( SDL_windowid ) {
FSwindow = 0;
WMwindow = strtol(SDL_windowid, NULL, 0);
return;
}
if(FSwindow)
XDestroyWindow(SDL_Display, FSwindow);
xattr.override_redirect = True;
xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0;
xattr.border_pixel = 0;
xattr.colormap = SDL_XColorMap;
FSwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0,
this->hidden->depth, InputOutput, SDL_Visual,
CWOverrideRedirect | CWBackPixel | CWBorderPixel
| CWColormap,
&xattr);
XSelectInput(SDL_Display, FSwindow, StructureNotifyMask);
/* Tell KDE to keep the fullscreen window on top */
{
XEvent ev;
long mask;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = SDL_Root;
ev.xclient.message_type = XInternAtom(SDL_Display,
"KWM_KEEP_ON_TOP", False);
ev.xclient.format = 32;
ev.xclient.data.l[0] = FSwindow;
ev.xclient.data.l[1] = CurrentTime;
mask = SubstructureRedirectMask;
XSendEvent(SDL_Display, SDL_Root, False, mask, &ev);
}
hints = NULL;
titleprop.value = iconprop.value = NULL;
if(WMwindow) {
/* All window attributes must survive the recreation */
hints = XGetWMHints(SDL_Display, WMwindow);
XGetWMName(SDL_Display, WMwindow, &titleprop);
XGetWMIconName(SDL_Display, WMwindow, &iconprop);
XDestroyWindow(SDL_Display, WMwindow);
}
/* Create the window for windowed management */
/* (reusing the xattr structure above) */
WMwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0,
this->hidden->depth, InputOutput, SDL_Visual,
CWBackPixel | CWBorderPixel | CWColormap,
&xattr);
/* Set the input hints so we get keyboard input */
if(!hints) {
hints = XAllocWMHints();
hints->input = True;
hints->flags = InputHint;
}
XSetWMHints(SDL_Display, WMwindow, hints);
XFree(hints);
if(titleprop.value) {
XSetWMName(SDL_Display, WMwindow, &titleprop);
XFree(titleprop.value);
}
if(iconprop.value) {
XSetWMIconName(SDL_Display, WMwindow, &iconprop);
XFree(iconprop.value);
}
XSelectInput(SDL_Display, WMwindow,
FocusChangeMask | KeyPressMask | KeyReleaseMask
| PropertyChangeMask | StructureNotifyMask);
/* Set the class hints so we can get an icon (AfterStep) */
{
XClassHint *classhints;
classhints = XAllocClassHint();
if(classhints != NULL) {
classhints->res_name = "SDL_App";
classhints->res_class = "SDL_App";
XSetClassHint(SDL_Display, WMwindow, classhints);
XFree(classhints);
}
}
/* Allow the window to be deleted by the window manager */
WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1);
}
#endif
Uint32 MakeBitMask(_THIS,int type,int format,int *bpp) Uint32 MakeBitMask(_THIS,int type,int format,int *bpp)
{ {
...@@ -468,6 +575,8 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat) ...@@ -468,6 +575,8 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat)
} }
SDL_Visual = this->hidden->visuals[i].visual; SDL_Visual = this->hidden->visuals[i].visual;
// SDL_XColorMap = SDL_DisplayColormap;
this->hidden->depth = this->hidden->visuals[i].depth; this->hidden->depth = this->hidden->visuals[i].depth;
D(bug("Setto la profiondita' dello schermo a: %ld\n",this->hidden->depth)); D(bug("Setto la profiondita' dello schermo a: %ld\n",this->hidden->depth));
vformat->BitsPerPixel = this->hidden->visuals[i].depth; /* this->hidden->visuals[i].bpp; */ vformat->BitsPerPixel = this->hidden->visuals[i].depth; /* this->hidden->visuals[i].bpp; */
...@@ -495,6 +604,10 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat) ...@@ -495,6 +604,10 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat)
} }
} }
/* See if we have been passed a window to use */
/* SDL_windowid = getenv("SDL_WINDOWID"); */
SDL_windowid=NULL;
/* Create the fullscreen and managed windows */ /* Create the fullscreen and managed windows */
// create_aux_windows(this); // create_aux_windows(this);
...@@ -517,45 +630,47 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat) ...@@ -517,45 +630,47 @@ static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat)
void CGX_DestroyWindow(_THIS, SDL_Surface *screen) void CGX_DestroyWindow(_THIS, SDL_Surface *screen)
{ {
/* Hide the managed window */ if ( ! SDL_windowid ) {
int was_fullscreen=0; /* Hide the managed window */
int was_fullscreen=0;
if ( screen && (screen->flags & SDL_FULLSCREEN) ) { if ( screen && (screen->flags & SDL_FULLSCREEN) ) {
was_fullscreen=1; was_fullscreen=1;
screen->flags &= ~SDL_FULLSCREEN; screen->flags &= ~SDL_FULLSCREEN;
CGX_LeaveFullScreen(this); // CGX_LeaveFullScreen(this); tolto x crash
} }
/* Destroy the output window */ /* Destroy the output window */
if ( SDL_Window ) { if ( SDL_Window ) {
CloseWindow(SDL_Window); CloseWindow(SDL_Window);
SDL_Window=NULL; SDL_Window=NULL;
} }
/* Free the colormap entries */ /* Free the colormap entries */
if ( SDL_XPixels ) { if ( SDL_XPixels ) {
int numcolors; int numcolors;
unsigned long pixel; unsigned long pixel;
if(this->screen->format&&this->hidden->depth==8&&!was_fullscreen) if(this->screen->format&&this->hidden->depth==8&&!was_fullscreen)
{ {
numcolors = 1<<this->screen->format->BitsPerPixel; numcolors = 1<<this->screen->format->BitsPerPixel;
if(numcolors>256) if(numcolors>256)
numcolors=256; numcolors=256;
if(!was_fullscreen&&this->hidden->depth==8) if(!was_fullscreen&&this->hidden->depth==8)
{
for ( pixel=0; pixel<numcolors; pixel++ )
{ {
if(SDL_XPixels[pixel]>=0) for ( pixel=0; pixel<numcolors; pixel++ )
ReleasePen(GFX_Display->ViewPort.ColorMap,SDL_XPixels[pixel]); {
if(SDL_XPixels[pixel]>=0)
ReleasePen(GFX_Display->ViewPort.ColorMap,SDL_XPixels[pixel]);
}
} }
} }
} free(SDL_XPixels);
free(SDL_XPixels); SDL_XPixels = NULL;
SDL_XPixels = NULL; }
} }
} }
static void CGX_SetSizeHints(_THIS, int w, int h, Uint32 flags) static void CGX_SetSizeHints(_THIS, int w, int h, Uint32 flags)
...@@ -590,7 +705,13 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, ...@@ -590,7 +705,13 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen,
if ( SDL_Window ) { if ( SDL_Window ) {
CGX_DestroyWindow(this, screen); CGX_DestroyWindow(this, screen);
} }
SDL_Window = 0;
/* See if we have been given a window id */
if ( SDL_windowid ) {
SDL_Window = (struct Window *)atol(SDL_windowid);
} else {
SDL_Window = 0;
}
/* find out which visual we are going to use */ /* find out which visual we are going to use */
#if 0 #if 0
...@@ -656,6 +777,11 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, ...@@ -656,6 +777,11 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen,
} }
/* Create the appropriate colormap */ /* Create the appropriate colormap */
/*
if ( SDL_XColorMap != SDL_DisplayColormap ) {
XFreeColormap(SDL_Display, SDL_XColorMap);
}
*/
if ( GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_PIXFMT)==PIXFMT_LUT8 || bpp==8 ) { if ( GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_PIXFMT)==PIXFMT_LUT8 || bpp==8 ) {
int ncolors; int ncolors;
D(bug("Alloco XPixels x la palette...\n")); D(bug("Alloco XPixels x la palette...\n"));
...@@ -681,32 +807,70 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, ...@@ -681,32 +807,70 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen,
flags |= SDL_HWPALETTE; flags |= SDL_HWPALETTE;
if ( flags & SDL_HWPALETTE ) { if ( flags & SDL_HWPALETTE ) {
screen->flags |= SDL_HWPALETTE; screen->flags |= SDL_HWPALETTE;
/*
SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
SDL_Visual, AllocAll);
*/
} else {
/*
SDL_XColorMap = SDL_DisplayColormap;
*/
} }
} else {
/*
SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
SDL_Visual, AllocNone);
*/
} }
/* Recreate the auxiliary windows, if needed (required for GL) */
/*
if ( vis_change )
create_aux_windows(this);
*/
/* resize the (possibly new) window manager window */ /* resize the (possibly new) window manager window */
/* Create (or use) the X11 display window */ /* Create (or use) the X11 display window */
if ( flags & SDL_OPENGL ) { if ( !SDL_windowid ) {
return(-1); if ( flags & SDL_OPENGL ) {
} else { return(-1);
if(flags & SDL_FULLSCREEN) }
SDL_Window = OpenWindowTags(NULL,WA_Width,w,WA_Height,h, else
{
if(flags & SDL_FULLSCREEN)
{
SDL_Window = OpenWindowTags(NULL,WA_Width,w,WA_Height,h,
WA_Flags,WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_BACKDROP|WFLG_REPORTMOUSE, WA_Flags,WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_BACKDROP|WFLG_REPORTMOUSE,
WA_IDCMP,IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE, WA_IDCMP,IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
WA_CustomScreen,(ULONG)SDL_Display, WA_CustomScreen,(ULONG)SDL_Display,
TAG_DONE); TAG_DONE);
else
SDL_Window = OpenWindowTags(NULL,WA_InnerWidth,w,WA_InnerHeight,h, D(bug("Apro finestra backdrop %ldx%ld su %lx!\n",w,h,SDL_Display));
WA_Flags,WFLG_REPORTMOUSE|WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR| ((screen->flags&SDL_RESIZABLE) ? WFLG_SIZEGADGET|WFLG_SIZEBBOTTOM : 0), }
else
{
SDL_Window = OpenWindowTags(NULL,WA_InnerWidth,w,WA_InnerHeight,h,
WA_Flags,WFLG_REPORTMOUSE|WFLG_ACTIVATE|WFLG_RMBTRAP | ((flags&SDL_NOFRAME) ? 0 : (WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR | ((flags&SDL_RESIZABLE) ? WFLG_SIZEGADGET|WFLG_SIZEBBOTTOM : 0))),
WA_IDCMP,IDCMP_RAWKEY|IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_NEWSIZE|IDCMP_MOUSEMOVE, WA_IDCMP,IDCMP_RAWKEY|IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_NEWSIZE|IDCMP_MOUSEMOVE,
WA_PubScreen,(ULONG)SDL_Display, WA_PubScreen,(ULONG)SDL_Display,
TAG_DONE); TAG_DONE);
D(bug("Apro finestra %ldx%ld sul wb!\n",w,h));
}
}
/* Only manage our input if we own the window */
/*
XSelectInput(SDL_Display, SDL_Window,
( EnterWindowMask | LeaveWindowMask
| ButtonPressMask | ButtonReleaseMask
| PointerMotionMask | ExposureMask ));
*/
if(!SDL_Window)
return -1;
} }
/* Only manage our input if we own the window */
if(!SDL_Window)
return -1;
this->hidden->BytesPerPixel=GetCyberMapAttr(SDL_Window->RPort->BitMap,CYBRMATTR_BPPIX); this->hidden->BytesPerPixel=GetCyberMapAttr(SDL_Window->RPort->BitMap,CYBRMATTR_BPPIX);
...@@ -736,45 +900,69 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, ...@@ -736,45 +900,69 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen,
if(flags&SDL_HWSURFACE) if(flags&SDL_HWSURFACE)
screen->flags|=SDL_HWSURFACE; screen->flags|=SDL_HWSURFACE;
CGX_SetSizeHints(this, w, h, flags); if( !SDL_windowid ) {
current_w = w; CGX_SetSizeHints(this, w, h, flags);
current_h = h; current_w = w;
current_h = h;
}
/* Set our colormaps when not setting a GL mode */
/*
if ( ! (flags & SDL_OPENGL) ) {
XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap);
}
*/
/* Map them both and go fullscreen, if requested */ /* Map them both and go fullscreen, if requested */
if ( flags & SDL_FULLSCREEN ) { if ( ! SDL_windowid ) {
screen->flags |= SDL_FULLSCREEN; if ( flags & SDL_FULLSCREEN ) {
currently_fullscreen=1; screen->flags |= SDL_FULLSCREEN;
// CGX_EnterFullScreen(this); Ci siamo gia'! currently_fullscreen=1;
} else { // CGX_EnterFullScreen(this); Ci siamo gia'!
screen->flags &= ~SDL_FULLSCREEN; } else {
screen->flags &= ~SDL_FULLSCREEN;
}
} }
screen->w = w;
screen->h = h;
screen->pitch = SDL_CalculatePitch(screen);
CGX_ResizeImage(this, screen, flags);
return(0); return(0);
} }
int CGX_ResizeWindow(_THIS, int CGX_ResizeWindow(_THIS,
SDL_Surface *screen, int w, int h, Uint32 flags) SDL_Surface *screen, int w, int h, Uint32 flags)
{ {
/* Resize the window manager window */ if ( ! SDL_windowid ) {
CGX_SetSizeHints(this, w, h, flags); /* Resize the window manager window */
current_w = w; CGX_SetSizeHints(this, w, h, flags);
current_h = h; current_w = w;
current_h = h;
ChangeWindowBox(SDL_Window,SDL_Window->LeftEdge,SDL_Window->TopEdge, w+SDL_Window->BorderLeft+SDL_Window->BorderRight, ChangeWindowBox(SDL_Window,SDL_Window->LeftEdge,SDL_Window->TopEdge, w+SDL_Window->BorderLeft+SDL_Window->BorderRight,
h+SDL_Window->BorderTop+SDL_Window->BorderBottom); h+SDL_Window->BorderTop+SDL_Window->BorderBottom);
/* Resize the fullscreen and display windows */ /* Resize the fullscreen and display windows */
if ( flags & SDL_FULLSCREEN ) { /*
if ( screen->flags & SDL_FULLSCREEN ) { if ( flags & SDL_FULLSCREEN ) {
CGX_ResizeFullScreen(this); if ( screen->flags & SDL_FULLSCREEN ) {
CGX_ResizeFullScreen(this);
} else {
screen->flags |= SDL_FULLSCREEN;
CGX_EnterFullScreen(this);
}
} else { } else {
screen->flags |= SDL_FULLSCREEN; if ( screen->flags & SDL_FULLSCREEN ) {
CGX_EnterFullScreen(this); screen->flags &= ~SDL_FULLSCREEN;
} CGX_LeaveFullScreen(this);
} else { }
if ( screen->flags & SDL_FULLSCREEN ) {
screen->flags &= ~SDL_FULLSCREEN;
CGX_LeaveFullScreen(this);
} }
*/
screen->w = w;
screen->h = h;
screen->pitch = SDL_CalculatePitch(screen);
CGX_ResizeImage(this, screen, flags);
} }
return(0); return(0);
} }
...@@ -783,24 +971,51 @@ static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, ...@@ -783,24 +971,51 @@ static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags) int width, int height, int bpp, Uint32 flags)
{ {
Uint32 saved_flags; Uint32 saved_flags;
int needcreate=0;
/* Lock the event thread, in multi-threading environments */ /* Lock the event thread, in multi-threading environments */
SDL_Lock_EventThread(); SDL_Lock_EventThread();
// Check if the window needs to be closed or can be resized
if( (flags&SDL_FULLSCREEN) || (current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN)))
needcreate=1;
// Check if we need to close an already existing videomode... // Check if we need to close an already existing videomode...
if(current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN)) if(current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN))
{ {
unsigned long i;
CGX_DestroyImage(this,current); CGX_DestroyImage(this,current);
CGX_DestroyWindow(this,current); CGX_DestroyWindow(this,current);
DestroyScreen(this); DestroyScreen(this);
D(bug("Distrutte immagine, finestra e schermo!\n"));
GFX_Display=SDL_Display=LockPubScreen(NULL);
bpp=this->hidden->depth=GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_DEPTH);
for ( i = 0; i < this->hidden->nvisuals; i++ ) {
if ( this->hidden->visuals[i].depth == bpp ) /* era .depth */
break;
}
if ( i == this->hidden->nvisuals ) {
SDL_SetError("No matching visual for requested depth");
return NULL; /* should never happen */
}
SDL_Visual = this->hidden->visuals[i].visual;
D(bug("Setto la profiondita' dello schermo a: %ld\n",this->hidden->depth));
} }
/* Check the combination of flags we were passed */ /* Check the combination of flags we were passed */
if ( flags & SDL_FULLSCREEN ) { if ( flags & SDL_FULLSCREEN ) {
int i; int i;
/* Clear fullscreen flag if not supported */ /* Clear fullscreen flag if not supported */
if(current->flags&SDL_FULLSCREEN ) if ( SDL_windowid ) {
flags &= ~SDL_FULLSCREEN;
}
else if(current->flags&SDL_FULLSCREEN )
{ {
if(current->w!=width || if(current->w!=width ||
current->h!=height || current->h!=height ||
...@@ -930,7 +1145,7 @@ buildnewscreen: ...@@ -930,7 +1145,7 @@ buildnewscreen:
saved_flags = current->flags; saved_flags = current->flags;
if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL) if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)
&& bpp == current->format->BitsPerPixel) { && bpp == current->format->BitsPerPixel && !needcreate) {
if (CGX_ResizeWindow(this, current, width, height, flags) < 0) { if (CGX_ResizeWindow(this, current, width, height, flags) < 0) {
current = NULL; current = NULL;
goto done; goto done;
...@@ -942,6 +1157,7 @@ buildnewscreen: ...@@ -942,6 +1157,7 @@ buildnewscreen:
} }
} }
#if 0
/* Set up the new mode framebuffer */ /* Set up the new mode framebuffer */
if ( ((current->w != width) || (current->h != height)) || if ( ((current->w != width) || (current->h != height)) ||
((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) {
...@@ -950,6 +1166,8 @@ buildnewscreen: ...@@ -950,6 +1166,8 @@ buildnewscreen:
current->pitch = SDL_CalculatePitch(current); current->pitch = SDL_CalculatePitch(current);
CGX_ResizeImage(this, current, flags); CGX_ResizeImage(this, current, flags);
} }
#endif
current->flags |= (flags&SDL_RESIZABLE); // Resizable only if the user asked it current->flags |= (flags&SDL_RESIZABLE); // Resizable only if the user asked it
done: done:
...@@ -964,6 +1182,11 @@ static int CGX_ToggleFullScreen(_THIS, int on) ...@@ -964,6 +1182,11 @@ static int CGX_ToggleFullScreen(_THIS, int on)
{ {
Uint32 event_thread; Uint32 event_thread;
/* Don't switch if we don't own the window */
if ( SDL_windowid ) {
return(0);
}
/* Don't lock if we are the event thread */ /* Don't lock if we are the event thread */
event_thread = SDL_EventThreadID(); event_thread = SDL_EventThreadID();
if ( event_thread && (SDL_ThreadID() == event_thread) ) { if ( event_thread && (SDL_ThreadID() == event_thread) ) {
...@@ -1090,9 +1313,6 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) ...@@ -1090,9 +1313,6 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
/* Check to make sure we have a colormap allocated */ /* Check to make sure we have a colormap allocated */
// It's not needed to reload the whole palette each time on Amiga!
// ncolors = this->screen->format->palette->ncolors;
/* It's easy if we have a hidden colormap */ /* It's easy if we have a hidden colormap */
if ( (this->screen->flags & SDL_HWPALETTE) && currently_fullscreen ) if ( (this->screen->flags & SDL_HWPALETTE) && currently_fullscreen )
{ {
...@@ -1104,9 +1324,9 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) ...@@ -1104,9 +1324,9 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
// D(bug("Setting %ld colors on an HWPALETTE screen\n",ncolors)); // D(bug("Setting %ld colors on an HWPALETTE screen\n",ncolors));
for ( i=0; i<ncolors; i++ ) { for ( i=0; i<ncolors; i++ ) {
xcmap[i*3+1] = colors[i].r<<24; xcmap[i*3+1] = colors[i+firstcolor].r<<24;
xcmap[i*3+2] = colors[i].g<<24; xcmap[i*3+2] = colors[i+firstcolor].g<<24;
xcmap[i*3+3] = colors[i].b<<24; xcmap[i*3+3] = colors[i+firstcolor].b<<24;
} }
xcmap[ncolors*3+1]=0; xcmap[ncolors*3+1]=0;
LoadRGB32(&GFX_Display->ViewPort,xcmap); LoadRGB32(&GFX_Display->ViewPort,xcmap);
...@@ -1119,7 +1339,6 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) ...@@ -1119,7 +1339,6 @@ static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
return(0); return(0);
} }
colors = this->screen->format->palette->colors;
if(this->hidden->depth==8) if(this->hidden->depth==8)
{ {
// In this case I have to unalloc and realloc the full palette // In this case I have to unalloc and realloc the full palette
...@@ -1178,6 +1397,22 @@ static void CGX_VideoQuit(_THIS) ...@@ -1178,6 +1397,22 @@ static void CGX_VideoQuit(_THIS)
SDL_VideoSurface=NULL; SDL_VideoSurface=NULL;
CGX_FreeVideoModes(this); CGX_FreeVideoModes(this);
/*
if ( SDL_iconcolors ) {
unsigned long pixel;
int numcolors =
((this->screen->format)->palette)->ncolors;
for ( pixel=0; pixel<numcolors; ++pixel ) {
while ( SDL_iconcolors[pixel] > 0 ) {
XFreeColors(SDL_Display,
SDL_DisplayColormap,&pixel,1,0);
--SDL_iconcolors[pixel];
}
}
free(SDL_iconcolors);
SDL_iconcolors = NULL;
}
*/
/* Free that blank cursor */ /* Free that blank cursor */
if ( SDL_BlankCursor != NULL ) { if ( SDL_BlankCursor != NULL ) {
FreeMem(SDL_BlankCursor,16); FreeMem(SDL_BlankCursor,16);
......
...@@ -69,6 +69,8 @@ struct SDL_PrivateVideoData { ...@@ -69,6 +69,8 @@ struct SDL_PrivateVideoData {
struct Window *SDL_Window; /* Shared by both displays (no X security?) */ struct Window *SDL_Window; /* Shared by both displays (no X security?) */
unsigned char *BlankCursor; /* The invisible cursor */ unsigned char *BlankCursor; /* The invisible cursor */
char *SDL_windowid; /* Flag: true if we have been passed a window */
/* The variables used for displaying graphics */ /* The variables used for displaying graphics */
Uint8 *Ximage; /* The X image for our window */ Uint8 *Ximage; /* The X image for our window */
int swap_pixels; /* Flag: true if display is swapped endian */ int swap_pixels; /* Flag: true if display is swapped endian */
...@@ -134,6 +136,7 @@ struct SDL_PrivateVideoData { ...@@ -134,6 +136,7 @@ struct SDL_PrivateVideoData {
#define SDL_Window (this->hidden->SDL_Window) #define SDL_Window (this->hidden->SDL_Window)
#define WM_DELETE_WINDOW (this->hidden->WM_DELETE_WINDOW) #define WM_DELETE_WINDOW (this->hidden->WM_DELETE_WINDOW)
#define SDL_BlankCursor (this->hidden->BlankCursor) #define SDL_BlankCursor (this->hidden->BlankCursor)
#define SDL_windowid (this->hidden->SDL_windowid)
#define SDL_Ximage (this->hidden->Ximage) #define SDL_Ximage (this->hidden->Ximage)
#define SDL_GC (this->hidden->gc) #define SDL_GC (this->hidden->gc)
#define swap_pixels (this->hidden->swap_pixels) #define swap_pixels (this->hidden->swap_pixels)
...@@ -152,6 +155,9 @@ struct SDL_PrivateVideoData { ...@@ -152,6 +155,9 @@ struct SDL_PrivateVideoData {
#define SDL_XPixels (this->hidden->XPixels) #define SDL_XPixels (this->hidden->XPixels)
#define SDL_iconcolors (this->hidden->iconcolors) #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, extern int CGX_CreateWindow(_THIS, SDL_Surface *screen,
int w, int h, int bpp, Uint32 flags); int w, int h, int bpp, Uint32 flags);
extern int CGX_ResizeWindow(_THIS, 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 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public 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