diff --git a/README.QNX b/README.QNX index 8412a295a..a116c42dd 100644 --- a/README.QNX +++ b/README.QNX @@ -1,7 +1,38 @@ README.QNX by Mike Gorchak , -Last changed at 10 Mar 2009. +Last changed at 22 Mar 2009. -QNX Photon and GF drivers are under construction. Please be patient. +QNX Photon and GF drivers are being constructed. +QNX QSA (QNX Sound Architecture) driver is ready. +QNX CDROM driver is ready. +QNX HID input driver is being constructed. + +---------------------- + -- SDL QSA driver -- +---------------------- + + Due to QNX Sound Architecture limitations software could not determine +what playback channels are designed for, so some casus can be. For example, +output after testmultiaudio test utility execution: + +Using audio driver: qsa +playing on device #0: ('Vortex 8820 @ fb000000 d0')...done. +playing on device #1: ('Vortex 8820 @ fb000000 d1')...done. +playing on device #2: ('i8x0 @ d800 d0')...done. +playing on device #3: ('i8x0 @ d800 d1')...done. +playing on all devices... +Open device 3 failed: QSA: snd_pcm_channel_params failed: Invalid argument + +If speakers are connected to both audio cards: Vortex 8820 and Intel +Integrated Audio we can hear sound playback on device #0 and devices #2, #3 +only. Device #1 is an unknown PCM channel which does not produce any sound. + +As for error during device #3 opening, it's caused by QSA software mixer +channel, because it can't open real hardware device #2, since it's already +opened by SDL. + +After simultaneous sound playback on all devices utility testmultiaudio +stays running waiting for sound playback finish on device #1, which is +locked up due to some Aureal Vortex 8820 driver limitations. --------------------- -- SDL GF driver -- @@ -15,43 +46,61 @@ Here is an additional information about SDL GF driver: 0. Introduction. - SDL GF driver is a layer between SDL and QNX Graphics Framework (GF). Hardware -accelerated features which SDL could support depends on real hardware capabilities. + SDL GF driver is a layer between SDL and QNX Graphics Framework (GF). +SDL GF driver also supports OpenGL ES through the QNX Graphics Framework. +Hardware accelerated features which SDL can support depend on real hardware +capabilities. 1. Environment variables which GF driver supports. - GF driver supports the following environment variables for QNX GF specific -customization options: - a) SDL_VIDEO_GF_REFRESH_RATE - refresh rate of video output in Hz. Without - this environment variable declaration SDL controls refresh rate of your - display. If this enironment variable is set to 0, SDL will control refresh - rate of display, otherwise value of SDL_VIDEO_GF_REFRESH_RATE is used for - all screen resolutions as refresh rate. This example will set 60Hz refresh - rate as refresh rate for all graphics modes: + GF driver supports the following environment variables for QNX GF +specific customization options: + a) SDL_VIDEO_GF_REFRESH_RATE - refresh rate of video output in Hz. + Without this environment variable declaration SDL controls refresh + rate of your display. If this enironment variable is set to 0, SDL + will control refresh rate of display, otherwise value of flag + SDL_VIDEO_GF_REFRESH_RATE is used for all screen resolutions as + refresh rate. This example will set 60Hz refresh rate as refresh rate + for all graphics modes: export SDL_VIDEO_GF_REFRESH_RATE=60 2. Custom video modes. - Since most QNX graphics drivers supports GENERIC video modes, i.e. you could -specify any horizontal and vertical resolution and any refresh rate, SDL GF -driver uses its own fullscreen modes list, which could be incomplete. You could -add any custom video mode, which your QNX graphics driver supports by editing -file ./src/video/qnxgf/SDL_qnxgf.c. Custom graphics mode definition looks like + Since most QNX graphics drivers support GENERIC video modes, i.e. you +can specify any horizontal and vertical resolution and any refresh rate, +SDL GF driver uses its own fullscreen modes list, which can be incomplete. +You can add any custom video mode, which your QNX graphics driver supports +by editing file ./src/video/qnxgf/SDL_qnxgf.c. Custom graphics mode +definition looks like this: - {0, 1024, 640, 60, NULL}, /* 1024x640 mode is 60Hz only */ + {0, 1024, 640, 60, NULL}, /* 1024x640 mode is 60Hz only */ -You must specify horizontal resolution as second parameter, vertical resolution -as third parameter and refresh rate as fourth parameter. Please leave first and -last parameters as 0 and NULL. Then please send me your changes to e-mail address -which is specified in the header of this document. +You must specify horizontal resolution as the second parameter, vertical +resolution as the third one and refresh rate as the fourth parameter. +Please leave the first and the last parameters as 0 and NULL. Then send me +your changes to e-mail address which is specified in the header of this +document. 3. Limitations. There are few limitations while using SDL GF driver: - a) Since GF driver supports fullscreen modes only, when you are not specifing -SDL_WINDOW_FULLSCREEN flag, an SDL GF driver will try to find the fullscreen -graphics mode which corresponds to SDL window size. Refresh rate will be the -lowest available, if SDL_VIDEO_GF_REFRESH_RATE environment variable is not set. + a) Since GF driver supports fullscreen modes only, when flag +SDL_WINDOW_FULLSCREEN is not specified, SDL GF driver will try to find the +fullscreen graphics mode which corresponds to SDL window size. Refresh rate +will be the lowest available, if SDL_VIDEO_GF_REFRESH_RATE environment +variable is not set. + b) As confirmed by QSSL none of existing video drivers has support of +doublescan low-resolution video modes. So modes below 640x480 are not +supported. If your video driver supports low-resolution video modes, please +add SDL_GF_LOWRESOLUTION flag to the gf_devicename array in the SDL_qnxgf.c +source file. +------------------------- + -- SDL Photon driver -- +------------------------- + +---------------------------- + -- SDL HID input driver -- +---------------------------- diff --git a/configure.in b/configure.in index c928f8640..4cafd8d74 100644 --- a/configure.in +++ b/configure.in @@ -1705,6 +1705,7 @@ CheckOpenGLESQNX() AC_MSG_RESULT($video_opengl) if test x$video_opengl = xyes; then AC_DEFINE(SDL_VIDEO_OPENGL_ES) + AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES) EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lGLES_CM" else AC_MSG_CHECKING(for QNX OpenGL ES (CL) support) @@ -1719,7 +1720,8 @@ CheckOpenGLESQNX() AC_MSG_RESULT($video_opengl) if test x$video_opengl = xyes; then AC_DEFINE(SDL_VIDEO_OPENGL_ES) - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lGLES_CL" + AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES) + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lGLES_CLS" fi fi fi @@ -2501,8 +2503,8 @@ case "$host" in # Set up files for the audio library if test x$enable_audio = xyes; then - AC_DEFINE(SDL_AUDIO_DRIVER_QNXNTO) - SOURCES="$SOURCES $srcdir/src/audio/nto/*.c" + AC_DEFINE(SDL_AUDIO_DRIVER_QSA) + SOURCES="$SOURCES $srcdir/src/audio/qsa/*.c" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lasound" have_audio=yes fi diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 25ef1bc52..c02193596 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -193,7 +193,7 @@ #undef SDL_AUDIO_DRIVER_OSS #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H #undef SDL_AUDIO_DRIVER_PAUDIO -#undef SDL_AUDIO_DRIVER_QNXNTO +#undef SDL_AUDIO_DRIVER_QSA #undef SDL_AUDIO_DRIVER_SNDMGR #undef SDL_AUDIO_DRIVER_SUNAUDIO #undef SDL_AUDIO_DRIVER_WINWAVEOUT diff --git a/include/SDL_opengles.h b/include/SDL_opengles.h index b15a56b0f..5297e4a47 100644 --- a/include/SDL_opengles.h +++ b/include/SDL_opengles.h @@ -962,6 +962,12 @@ extern "C" const GLvoid * pointer); #endif +/* GL_OES_query_matrix */ +#ifndef GL_OES_query_matrix +#define GL_OES_query_matrix 1 + GL_API GLbitfield GL_APIENTRY glQueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]); +#endif /* GL_OES_query_matrix */ + /* GL_OES_point_sprite */ #ifndef GL_OES_point_sprite #define GL_OES_point_sprite 1 diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 35326669c..6ed8bc5de 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -49,7 +49,7 @@ extern AudioBootStrap DSP_bootstrap; extern AudioBootStrap DMA_bootstrap; extern AudioBootStrap ALSA_bootstrap; extern AudioBootStrap PULSEAUDIO_bootstrap; -extern AudioBootStrap QNXNTOAUDIO_bootstrap; +extern AudioBootStrap QSAAUDIO_bootstrap; extern AudioBootStrap SUNAUDIO_bootstrap; extern AudioBootStrap DMEDIA_bootstrap; extern AudioBootStrap ARTS_bootstrap; @@ -91,8 +91,8 @@ static AudioBootStrap *bootstrap[] = { &DSP_bootstrap, &DMA_bootstrap, #endif -#if SDL_AUDIO_DRIVER_QNXNTO - &QNXNTOAUDIO_bootstrap, +#if SDL_AUDIO_DRIVER_QSA + &QSAAUDIO_bootstrap, #endif #if SDL_AUDIO_DRIVER_SUNAUDIO &SUNAUDIO_bootstrap, diff --git a/src/audio/nto/SDL_nto_audio.c b/src/audio/nto/SDL_nto_audio.c deleted file mode 100644 index 2622b4331..000000000 --- a/src/audio/nto/SDL_nto_audio.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org -*/ -#include "SDL_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SDL_timer.h" -#include "SDL_audio.h" -#include "../SDL_audiomem.h" -#include "../SDL_audio_c.h" -#include "SDL_nto_audio.h" - -/* The tag name used by NTO audio */ -#define DRIVER_NAME "qsa-nto" - -/* default channel communication parameters */ -#define DEFAULT_CPARAMS_RATE 22050 -#define DEFAULT_CPARAMS_VOICES 1 -/* FIXME: need to add in the near future flexible logic with frag_size and frags count */ -#define DEFAULT_CPARAMS_FRAG_SIZE 4096 -#define DEFAULT_CPARAMS_FRAGS_MIN 1 -#define DEFAULT_CPARAMS_FRAGS_MAX 1 - -/* Open the audio device for playback, and don't block if busy */ -#define OPEN_FLAGS SND_PCM_OPEN_PLAYBACK - -#define QSA_NO_WORKAROUNDS 0x00000000 -#define QSA_MMAP_WORKAROUND 0x00000001 - -struct BuggyCards -{ - char *cardname; - unsigned long bugtype; -}; - -#define QSA_WA_CARDS 3 - -struct BuggyCards buggycards[QSA_WA_CARDS] = { - {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, - {"Vortex 8820", QSA_MMAP_WORKAROUND}, - {"Vortex 8830", QSA_MMAP_WORKAROUND}, -}; - - -static inline void -NTO_SetError(const char *fn, int rval) -{ - SDL_SetError("NTO: %s failed: %s", fn, snd_strerror(rval)); -} - - -/* card names check to apply the workarounds */ -static int -NTO_CheckBuggyCards(_THIS, unsigned long checkfor) -{ - char scardname[33]; - int it; - - if (snd_card_get_name(this->hidden->cardno, scardname, 32) < 0) { - return 0; - } - - for (it = 0; it < QSA_WA_CARDS; it++) { - if (SDL_strcmp(buggycards[it].cardname, scardname) == 0) { - if (buggycards[it].bugtype == checkfor) { - return 1; - } - } - } - - return 0; -} - -static void -NTO_ThreadInit(_THIS) -{ - struct sched_param param; - int status = SchedGet(0, 0, ¶m); - - /* increasing default 10 priority to 25 to avoid jerky sound */ - param.sched_priority = param.sched_curpriority + 15; - status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); -} - -/* PCM transfer channel parameters initialize function */ -static void -NTO_InitAudioParams(snd_pcm_channel_params_t * cpars) -{ - SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t)); - - cpars->channel = SND_PCM_CHANNEL_PLAYBACK; - cpars->mode = SND_PCM_MODE_BLOCK; - cpars->start_mode = SND_PCM_START_DATA; - cpars->stop_mode = SND_PCM_STOP_STOP; - cpars->format.format = SND_PCM_SFMT_S16_LE; - cpars->format.interleave = 1; - cpars->format.rate = DEFAULT_CPARAMS_RATE; - cpars->format.voices = DEFAULT_CPARAMS_VOICES; - cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; - cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; - cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; -} - - -/* This function waits until it is possible to write a full sound buffer */ -static void -NTO_WaitDevice(_THIS) -{ - fd_set wfds; - int selectret; - - FD_ZERO(&wfds); - FD_SET(this->hidden->audio_fd, &wfds); - - do { - selectret = - select(this->hidden->audio_fd + 1, NULL, &wfds, NULL, NULL); - switch (selectret) { - case -1: - case 0: - SDL_SetError("NTO: select() failed: %s\n", strerror(errno)); - return; - default: - if (FD_ISSET(this->hidden->audio_fd, &wfds)) { - return; - } - break; - } - } while (1); -} - -static void -NTO_PlayDevice(_THIS) -{ - snd_pcm_channel_status_t cstatus; - int written, rval; - int towrite; - void *pcmbuffer; - - if ((!this->enabled) || (!this->hidden)) { - return; - } - - towrite = this->spec.size; - pcmbuffer = this->hidden->pcm_buf; - - /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ - do { - written = snd_pcm_plugin_write(this->hidden->audio_handle, - pcmbuffer, towrite); - if (written != towrite) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - /* Let a little CPU time go by and try to write again */ - SDL_Delay(1); - /* if we wrote some data */ - towrite -= written; - pcmbuffer += written * this->spec.channels; - continue; - } else if ((errno == EINVAL) || (errno == EIO)) { - SDL_memset(&cstatus, 0, sizeof(cstatus)); - cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; - rval = snd_pcm_plugin_status(this->hidden->audio_handle, - &cstatus); - if (rval < 0) { - NTO_SetError("snd_pcm_plugin_status", rval); - return; - } - - if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || - (cstatus.status == SND_PCM_STATUS_READY)) { - rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, - SND_PCM_CHANNEL_PLAYBACK); - if (rval < 0) { - NTO_SetError("snd_pcm_plugin_prepare", rval); - return; - } - } - continue; - } else { - return; - } - } else { - /* we wrote all remaining data */ - towrite -= written; - pcmbuffer += written * this->spec.channels; - } - } while ((towrite > 0) && (this->enabled)); - - /* If we couldn't write, assume fatal error for now */ - if (towrite != 0) { - this->enabled = 0; - } -} - -static Uint8 * -NTO_GetDeviceBuf(_THIS) -{ - return this->hidden->pcm_buf; -} - -static void -NTO_CloseDevice(_THIS) -{ - if (this->hidden != NULL) { - if (this->hidden->audio_handle != NULL) { - snd_pcm_plugin_flush(this->hidden->audio_handle, - SND_PCM_CHANNEL_PLAYBACK); - snd_pcm_close(this->hidden->audio_handle); - this->hidden->audio_handle = NULL; - } - if (this->hidden->pcm_buf != NULL) { - SDL_FreeAudioMem(this->hidden->pcm_buf); - this->hidden->pcm_buf = NULL; - } - SDL_free(this->hidden); - this->hidden = NULL; - } -} - -static int -NTO_OpenDevice(_THIS, const char *devname, int iscapture) -{ - int rval = 0; - int format = 0; - SDL_AudioFormat test_format = 0; - int found = 0; - snd_pcm_channel_setup_t csetup; - snd_pcm_channel_params_t cparams; - - /* Initialize all variables that we clean on shutdown */ - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - if (this->hidden == NULL) { - SDL_OutOfMemory(); - return 0; - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* initialize channel transfer parameters to default */ - NTO_InitAudioParams(&cparams); - - /* Open the audio device */ - rval = snd_pcm_open_preferred(&this->hidden->audio_handle, - &this->hidden->cardno, - &this->hidden->deviceno, OPEN_FLAGS); - - if (rval < 0) { - NTO_CloseDevice(this); - NTO_SetError("snd_pcm_open", rval); - return 0; - } - - if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { - /* enable count status parameter */ - rval = snd_pcm_plugin_set_disable(this->hidden->audio_handle, - PLUGIN_DISABLE_MMAP); - if (rval < 0) { - NTO_CloseDevice(this); - NTO_SetError("snd_pcm_plugin_set_disable", rval); - return 0; - } - } - - /* Try for a closest match on audio format */ - format = 0; - /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ - found = 0; - - for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) { - /* if match found set format to equivalent ALSA format */ - switch (test_format) { - case AUDIO_U8: - format = SND_PCM_SFMT_U8; - found = 1; - break; - case AUDIO_S8: - format = SND_PCM_SFMT_S8; - found = 1; - break; - case AUDIO_S16LSB: - format = SND_PCM_SFMT_S16_LE; - found = 1; - break; - case AUDIO_S16MSB: - format = SND_PCM_SFMT_S16_BE; - found = 1; - break; - case AUDIO_U16LSB: - format = SND_PCM_SFMT_U16_LE; - found = 1; - break; - case AUDIO_U16MSB: - format = SND_PCM_SFMT_U16_BE; - found = 1; - break; - case AUDIO_S32LSB: - format = SND_PCM_SFMT_S32_LE; - found = 1; - break; - case AUDIO_S32MSB: - format = SND_PCM_SFMT_S32_BE; - found = 1; - break; - case AUDIO_F32LSB: - format = SND_PCM_SFMT_FLOAT_LE; - found = 1; - break; - case AUDIO_F32MSB: - format = SND_PCM_SFMT_FLOAT_BE; - found = 1; - break; - default: - break; - } - - if (!found) { - test_format = SDL_NextAudioFormat(); - } - } - - /* assumes test_format not 0 on success */ - if (test_format == 0) { - NTO_CloseDevice(this); - SDL_SetError("NTO: Couldn't find any hardware audio formats"); - return 0; - } - - this->spec.format = test_format; - - /* Set the audio format */ - cparams.format.format = format; - - /* Set mono or stereo audio (currently only two channels supported) */ - cparams.format.voices = this->spec.channels; - - /* Set rate */ - cparams.format.rate = this->spec.freq; - - /* Setup the transfer parameters according to cparams */ - rval = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); - if (rval < 0) { - NTO_CloseDevice(this); - NTO_SetError("snd_pcm_channel_params", rval); - return 0; - } - - /* Make sure channel is setup right one last time */ - SDL_memset(&csetup, '\0', sizeof(csetup)); - csetup.channel = SND_PCM_CHANNEL_PLAYBACK; - if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) { - NTO_CloseDevice(this); - SDL_SetError("NTO: Unable to setup playback channel\n"); - return 0; - } - - /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(&this->spec); - - this->hidden->pcm_len = this->spec.size; - - if (this->hidden->pcm_len == 0) { - this->hidden->pcm_len = - csetup.buf.block.frag_size * this->spec.channels * - (snd_pcm_format_width(format) / 8); - } - - /* - * Allocate memory to the audio buffer and initialize with silence - * (Note that buffer size must be a multiple of fragment size, so find - * closest multiple) - */ - this->hidden->pcm_buf = - (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len); - if (this->hidden->pcm_buf == NULL) { - NTO_CloseDevice(this); - SDL_OutOfMemory(); - return 0; - } - SDL_memset(this->hidden->pcm_buf, this->spec.silence, - this->hidden->pcm_len); - - /* get the file descriptor */ - this->hidden->audio_fd = - snd_pcm_file_descriptor(this->hidden->audio_handle, - SND_PCM_CHANNEL_PLAYBACK); - if (this->hidden->audio_fd < 0) { - NTO_CloseDevice(this); - NTO_SetError("snd_pcm_file_descriptor", rval); - return 0; - } - - /* Trigger audio playback */ - rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, - SND_PCM_CHANNEL_PLAYBACK); - if (rval < 0) { - NTO_CloseDevice(this); - NTO_SetError("snd_pcm_plugin_prepare", rval); - return 0; - } - - /* We're really ready to rock and roll. :-) */ - return 1; -} - - -static int -NTO_Init(SDL_AudioDriverImpl * impl) -{ - /* !!! FIXME: not right for device enum? */ - /* See if we can open a nonblocking channel. */ - snd_pcm_t *handle = NULL; - int rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); - if (rval < 0) { - SDL_SetError("NTO: couldn't open preferred audio device"); - return 0; - } - if ((rval = snd_pcm_close(handle)) < 0) { - SDL_SetError("NTO: couldn't close test audio device"); - return 0; - } - - /* Set the function pointers */ - impl->OpenDevice = NTO_OpenDevice; - impl->ThreadInit = NTO_ThreadInit; - impl->WaitDevice = NTO_WaitDevice; - impl->PlayDevice = NTO_PlayDevice; - impl->GetDeviceBuf = NTO_GetDeviceBuf; - impl->CloseDevice = NTO_CloseDevice; - impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */ - - /* !!! FIXME: device enum might make this 1. */ - return 2; /* 2 == definitely has an audio device. */ -} - -AudioBootStrap QNXNTOAUDIO_bootstrap = { - DRIVER_NAME, "QNX6 QSA-NTO Audio", NTO_Init, 0 -}; - -/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/qsa/SDL_qsa_audio.c b/src/audio/qsa/SDL_qsa_audio.c new file mode 100644 index 000000000..5e3e7cf76 --- /dev/null +++ b/src/audio/qsa/SDL_qsa_audio.c @@ -0,0 +1,945 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Sound Architecture (QSA) SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#include "SDL_config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "SDL_qsa_audio.h" + +/* The tag name used by QSA audio framework */ +#define DRIVER_NAME "qsa" + +/* default channel communication parameters */ +#define DEFAULT_CPARAMS_RATE 44100 +#define DEFAULT_CPARAMS_VOICES 1 + +#define DEFAULT_CPARAMS_FRAG_SIZE 4096 +#define DEFAULT_CPARAMS_FRAGS_MIN 1 +#define DEFAULT_CPARAMS_FRAGS_MAX 1 + +#define QSA_NO_WORKAROUNDS 0x00000000 +#define QSA_MMAP_WORKAROUND 0x00000001 + +struct BuggyCards +{ + char* cardname; + unsigned long bugtype; +}; + +#define QSA_WA_CARDS 3 +#define QSA_MAX_CARD_NAME_LENGTH 33 + +struct BuggyCards buggycards[QSA_WA_CARDS]= +{ + {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, + {"Vortex 8820", QSA_MMAP_WORKAROUND}, + {"Vortex 8830", QSA_MMAP_WORKAROUND}, +}; + +/* List of found devices */ +#define QSA_MAX_DEVICES 32 +#define QSA_MAX_NAME_LENGTH 81+16 /* Hardcoded in QSA, can't be changed */ + +typedef struct _QSA_Device +{ + char name[QSA_MAX_NAME_LENGTH]; /* Long audio device name for SDL */ + int cardno; + int deviceno; +} QSA_Device; + +QSA_Device qsa_playback_device[QSA_MAX_DEVICES]; +uint32_t qsa_playback_devices; + +QSA_Device qsa_capture_device[QSA_MAX_DEVICES]; +uint32_t qsa_capture_devices; + +static inline void QSA_SetError(const char* fn, int status) +{ + SDL_SetError("QSA: %s failed: %s", fn, snd_strerror(status)); +} + +/* card names check to apply the workarounds */ +static int QSA_CheckBuggyCards(_THIS, unsigned long checkfor) +{ + char scardname[QSA_MAX_CARD_NAME_LENGTH]; + int it; + + if (snd_card_get_name(this->hidden->cardno, scardname, QSA_MAX_CARD_NAME_LENGTH-1)<0) + { + return 0; + } + + for (it=0; itchannel=SND_PCM_CHANNEL_PLAYBACK; + cpars->mode=SND_PCM_MODE_BLOCK; + cpars->start_mode=SND_PCM_START_DATA; + cpars->stop_mode=SND_PCM_STOP_STOP; + cpars->format.format=SND_PCM_SFMT_S16_LE; + cpars->format.interleave=1; + cpars->format.rate=DEFAULT_CPARAMS_RATE; + cpars->format.voices=DEFAULT_CPARAMS_VOICES; + cpars->buf.block.frag_size=DEFAULT_CPARAMS_FRAG_SIZE; + cpars->buf.block.frags_min=DEFAULT_CPARAMS_FRAGS_MIN; + cpars->buf.block.frags_max=DEFAULT_CPARAMS_FRAGS_MAX; +} + +/* This function waits until it is possible to write a full sound buffer */ +static void QSA_WaitDevice(_THIS) +{ + fd_set wfds; + fd_set rfds; + int selectret; + struct timeval timeout; + + if (!this->hidden->iscapture) + { + FD_ZERO(&wfds); + FD_SET(this->hidden->audio_fd, &wfds); + } + else + { + FD_ZERO(&rfds); + FD_SET(this->hidden->audio_fd, &rfds); + } + + do { + /* Setup timeout for playing one fragment equal to 2 seconds */ + /* If timeout occured than something wrong with hardware or driver */ + /* For example, Vortex 8820 audio driver stucks on second DAC because */ + /* it doesn't exist ! */ + timeout.tv_sec=2; + timeout.tv_usec=0; + this->hidden->timeout_on_wait=0; + + if (!this->hidden->iscapture) + { + selectret=select(this->hidden->audio_fd+1, NULL, &wfds, NULL, &timeout); + } + else + { + selectret=select(this->hidden->audio_fd+1, &rfds, NULL, NULL, &timeout); + } + + switch(selectret) + { + case -1: + { + SDL_SetError("QSA: select() failed: %s\n", strerror(errno)); + return; + } + break; + case 0: + { + SDL_SetError("QSA: timeout on buffer waiting occured\n"); + this->hidden->timeout_on_wait=1; + return; + } + break; + default: + { + if (!this->hidden->iscapture) + { + if (FD_ISSET(this->hidden->audio_fd, &wfds)) + { + return; + } + } + else + { + if (FD_ISSET(this->hidden->audio_fd, &rfds)) + { + return; + } + } + } + break; + } + } while (1); +} + +static void QSA_PlayDevice(_THIS) +{ + snd_pcm_channel_status_t cstatus; + int written; + int status; + int towrite; + void* pcmbuffer; + + if ((!this->enabled) || (!this->hidden)) + { + return; + } + + towrite = this->spec.size; + pcmbuffer = this->hidden->pcm_buf; + + /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ + do { + written=snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer, towrite); + if (written!=towrite) + { + /* Check if samples playback got stuck somewhere in hardware or in */ + /* the audio device driver */ + if ((errno==EAGAIN) && (written==0)) + { + if (this->hidden->timeout_on_wait!=0) + { + SDL_SetError("QSA: buffer playback timeout\n"); + return; + } + } + + /* Check for errors or conditions */ + if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) + { + /* Let a little CPU time go by and try to write again */ + SDL_Delay(1); + + /* if we wrote some data */ + towrite-=written; + pcmbuffer+=written*this->spec.channels; + continue; + } + else + { + if ((errno==EINVAL)||(errno==EIO)) + { + SDL_memset(&cstatus, 0, sizeof(cstatus)); + if (!this->hidden->iscapture) + { + cstatus.channel=SND_PCM_CHANNEL_PLAYBACK; + } + else + { + cstatus.channel=SND_PCM_CHANNEL_CAPTURE; + } + + status=snd_pcm_plugin_status(this->hidden->audio_handle, &cstatus); + if (status<0) + { + QSA_SetError("snd_pcm_plugin_status", status); + return; + } + + if ((cstatus.status==SND_PCM_STATUS_UNDERRUN) || + (cstatus.status==SND_PCM_STATUS_READY)) + { + if (!this->hidden->iscapture) + { + status=snd_pcm_plugin_prepare(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); + } + else + { + status=snd_pcm_plugin_prepare(this->hidden->audio_handle, + SND_PCM_CHANNEL_CAPTURE); + } + if (status<0) + { + QSA_SetError("snd_pcm_plugin_prepare", status); + return; + } + } + continue; + } + else + { + return; + } + } + } + else + { + /* we wrote all remaining data */ + towrite -= written; + pcmbuffer += written * this->spec.channels; + } + } while ((towrite>0) && (this->enabled)); + + /* If we couldn't write, assume fatal error for now */ + if (towrite!=0) + { + this->enabled=0; + } +} + +static Uint8* QSA_GetDeviceBuf(_THIS) +{ + return this->hidden->pcm_buf; +} + +static void QSA_CloseDevice(_THIS) +{ + if (this->hidden!=NULL) + { + if (this->hidden->audio_handle!=NULL) + { + if (!this->hidden->iscapture) + { + /* Finish playing available samples */ + snd_pcm_plugin_flush(this->hidden->audio_handle, SND_PCM_CHANNEL_PLAYBACK); + } + else + { + /* Cancel unread samples during capture */ + snd_pcm_plugin_flush(this->hidden->audio_handle, SND_PCM_CHANNEL_CAPTURE); + } + snd_pcm_close(this->hidden->audio_handle); + this->hidden->audio_handle=NULL; + } + + if (this->hidden->pcm_buf!=NULL) + { + SDL_FreeAudioMem(this->hidden->pcm_buf); + this->hidden->pcm_buf=NULL; + } + + SDL_free(this->hidden); + this->hidden=NULL; + } +} + +static int QSA_OpenDevice(_THIS, const char* devname, int iscapture) +{ + int status=0; + int format=0; + SDL_AudioFormat test_format=0; + int found=0; + snd_pcm_channel_setup_t csetup; + snd_pcm_channel_params_t cparams; + + /* Initialize all variables that we clean on shutdown */ + this->hidden=(struct SDL_PrivateAudioData*)SDL_calloc(1, (sizeof(struct SDL_PrivateAudioData))); + if (this->hidden==NULL) + { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); + + /* Initialize channel transfer parameters to default */ + QSA_InitAudioParams(&cparams); + + /* Initialize channel direction: capture or playback */ + this->hidden->iscapture=iscapture; + + /* Find deviceid and cardid by device name for playback */ + if ((!this->hidden->iscapture) && (devname!=NULL)) + { + uint32_t device; + int32_t status; + + /* Search in the playback devices */ + device=0; + do { + status=SDL_strcmp(qsa_playback_device[device].name, devname); + if (status==0) + { + /* Found requested device */ + this->hidden->deviceno=qsa_playback_device[device].deviceno; + this->hidden->cardno=qsa_playback_device[device].cardno; + break; + } + device++; + if (device>=qsa_playback_devices) + { + QSA_CloseDevice(this); + SDL_SetError("No such playback device"); + return 0; + } + } while(1); + } + + /* Find deviceid and cardid by device name for capture */ + if ((this->hidden->iscapture) && (devname!=NULL)) + { + /* Search in the capture devices */ + uint32_t device; + int32_t status; + + /* Searching in the playback devices */ + device=0; + do { + status=SDL_strcmp(qsa_capture_device[device].name, devname); + if (status==0) + { + /* Found requested device */ + this->hidden->deviceno=qsa_capture_device[device].deviceno; + this->hidden->cardno=qsa_capture_device[device].cardno; + break; + } + device++; + if (device>=qsa_capture_devices) + { + QSA_CloseDevice(this); + SDL_SetError("No such capture device"); + return 0; + } + } while(1); + } + + /* Check if SDL requested default audio device */ + if (devname==NULL) + { + /* Open system default audio device */ + if (!this->hidden->iscapture) + { + status=snd_pcm_open_preferred(&this->hidden->audio_handle, + &this->hidden->cardno, + &this->hidden->deviceno, SND_PCM_OPEN_PLAYBACK); + } + else + { + status=snd_pcm_open_preferred(&this->hidden->audio_handle, + &this->hidden->cardno, + &this->hidden->deviceno, SND_PCM_OPEN_CAPTURE); + } + } + else + { + /* Open requested audio device */ + if (!this->hidden->iscapture) + { + status=snd_pcm_open(&this->hidden->audio_handle, this->hidden->cardno, + this->hidden->deviceno, SND_PCM_OPEN_PLAYBACK); + } + else + { + status=snd_pcm_open(&this->hidden->audio_handle, this->hidden->cardno, + this->hidden->deviceno, SND_PCM_OPEN_CAPTURE); + } + } + + /* Check if requested device is opened */ + if (status<0) + { + QSA_CloseDevice(this); + QSA_SetError("snd_pcm_open", status); + return 0; + } + + if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) + { + /* Disable QSA MMAP plugin for buggy audio drivers */ + status=snd_pcm_plugin_set_disable(this->hidden->audio_handle, PLUGIN_DISABLE_MMAP); + if (status<0) + { + QSA_CloseDevice(this); + QSA_SetError("snd_pcm_plugin_set_disable", status); + return 0; + } + } + + /* Try for a closest match on audio format */ + format = 0; + /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */ + found = 0; + + for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) + { + /* if match found set format to equivalent QSA format */ + switch (test_format) + { + case AUDIO_U8: + { + format=SND_PCM_SFMT_U8; + found=1; + } + break; + case AUDIO_S8: + { + format=SND_PCM_SFMT_S8; + found=1; + } + break; + case AUDIO_S16LSB: + { + format=SND_PCM_SFMT_S16_LE; + found=1; + } + break; + case AUDIO_S16MSB: + { + format=SND_PCM_SFMT_S16_BE; + found=1; + } + break; + case AUDIO_U16LSB: + { + format=SND_PCM_SFMT_U16_LE; + found=1; + } + break; + case AUDIO_U16MSB: + { + format=SND_PCM_SFMT_U16_BE; + found=1; + } + break; + case AUDIO_S32LSB: + { + format=SND_PCM_SFMT_S32_LE; + found=1; + } + break; + case AUDIO_S32MSB: + { + format=SND_PCM_SFMT_S32_BE; + found=1; + } + break; + case AUDIO_F32LSB: + { + format=SND_PCM_SFMT_FLOAT_LE; + found=1; + } + break; + case AUDIO_F32MSB: + { + format=SND_PCM_SFMT_FLOAT_BE; + found=1; + } + break; + default: + { + break; + } + } + + if (!found) + { + test_format = SDL_NextAudioFormat(); + } + } + + /* assumes test_format not 0 on success */ + if (test_format==0) + { + QSA_CloseDevice(this); + SDL_SetError("QSA: Couldn't find any hardware audio formats"); + return 0; + } + + this->spec.format=test_format; + + /* Set the audio format */ + cparams.format.format=format; + + /* Set mono/stereo/4ch/6ch/8ch audio */ + cparams.format.voices=this->spec.channels; + + /* Set rate */ + cparams.format.rate=this->spec.freq; + + /* Setup the transfer parameters according to cparams */ + status=snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); + if (status<0) + { + QSA_CloseDevice(this); + QSA_SetError("snd_pcm_channel_params", status); + return 0; + } + + /* Make sure channel is setup right one last time */ + SDL_memset(&csetup, '\0', sizeof(csetup)); + if (!this->hidden->iscapture) + { + csetup.channel=SND_PCM_CHANNEL_PLAYBACK; + } + else + { + csetup.channel=SND_PCM_CHANNEL_CAPTURE; + } + + /* Setup an audio channel */ + if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) + { + QSA_CloseDevice(this); + SDL_SetError("QSA: Unable to setup channel\n"); + return 0; + } + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(&this->spec); + + this->hidden->pcm_len = this->spec.size; + + if (this->hidden->pcm_len==0) + { + this->hidden->pcm_len=csetup.buf.block.frag_size * this->spec.channels * + (snd_pcm_format_width(format) / 8); + } + + /* + * Allocate memory to the audio buffer and initialize with silence + * (Note that buffer size must be a multiple of fragment size, so find + * closest multiple) + */ + this->hidden->pcm_buf=(Uint8*)SDL_AllocAudioMem(this->hidden->pcm_len); + if (this->hidden->pcm_buf==NULL) + { + QSA_CloseDevice(this); + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden->pcm_buf, this->spec.silence, this->hidden->pcm_len); + + /* get the file descriptor */ + if (!this->hidden->iscapture) + { + this->hidden->audio_fd=snd_pcm_file_descriptor(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); + } + else + { + this->hidden->audio_fd=snd_pcm_file_descriptor(this->hidden->audio_handle, + SND_PCM_CHANNEL_CAPTURE); + } + + if (this->hidden->audio_fd<0) + { + QSA_CloseDevice(this); + QSA_SetError("snd_pcm_file_descriptor", status); + return 0; + } + + /* Prepare an audio channel */ + if (!this->hidden->iscapture) + { + /* Prepare audio playback */ + status=snd_pcm_plugin_prepare(this->hidden->audio_handle, SND_PCM_CHANNEL_PLAYBACK); + } + else + { + /* Prepare audio capture */ + status=snd_pcm_plugin_prepare(this->hidden->audio_handle, SND_PCM_CHANNEL_CAPTURE); + } + + if (status<0) + { + QSA_CloseDevice(this); + QSA_SetError("snd_pcm_plugin_prepare", status); + return 0; + } + + /* We're really ready to rock and roll. :-) */ + return 1; +} + +int QSA_DetectDevices(int iscapture) +{ + uint32_t it; + uint32_t cards; + uint32_t devices; + int32_t status; + + /* Detect amount of available devices */ + /* this value can be changed in the runtime */ + cards=snd_cards(); + + /* If io-audio manager is not running we will get 0 as number */ + /* of available audio devices */ + if (cards==0) + { + /* We have no any available audio devices */ + return 0; + } + + /* Find requested devices by type */ + if (!iscapture) + { + /* Playback devices enumeration requested */ + for(it=0; it=QSA_MAX_DEVICES) + { + break; + } + devices++; + } while(1); + + /* Check if we reached maximum devices count */ + if (qsa_playback_devices>=QSA_MAX_DEVICES) + { + break; + } + } + } + else + { + /* Capture devices enumeration requested */ + for(it=0; it=QSA_MAX_DEVICES) + { + break; + } + } + else + { + break; + } + devices++; + } while(1); + + /* Check if we reached maximum devices count */ + if (qsa_capture_devices>=QSA_MAX_DEVICES) + { + break; + } + } + } + + /* Return amount of available playback or capture devices */ + if (!iscapture) + { + return qsa_playback_devices; + } + else + { + return qsa_capture_devices; + } +} + +const char* QSA_GetDeviceName(int index, int iscapture) +{ + if (!iscapture) + { + if (index>=qsa_playback_devices) + { + return "No such playback device"; + } + + return qsa_playback_device[index].name; + } + else + { + if (index>=qsa_capture_devices) + { + return "No such capture device"; + } + + return qsa_capture_device[index].name; + } +} + +void QSA_WaitDone(_THIS) +{ + if (!this->hidden->iscapture) + { + if (this->hidden->audio_handle!=NULL) + { + /* Wait till last fragment is played and stop channel */ + snd_pcm_plugin_flush(this->hidden->audio_handle, SND_PCM_CHANNEL_PLAYBACK); + } + } + else + { + if (this->hidden->audio_handle!=NULL) + { + /* Discard all unread data and stop channel */ + snd_pcm_plugin_flush(this->hidden->audio_handle, SND_PCM_CHANNEL_CAPTURE); + } + } +} + +void QSA_Deinitialize(void) +{ + /* Clear devices array on shutdown */ + SDL_memset(qsa_playback_device, 0x00, sizeof(QSA_Device)*QSA_MAX_DEVICES); + SDL_memset(qsa_capture_device, 0x00, sizeof(QSA_Device)*QSA_MAX_DEVICES); + qsa_playback_devices=0; + qsa_capture_devices=0; +} + +static int QSA_Init(SDL_AudioDriverImpl* impl) +{ + snd_pcm_t* handle=NULL; + int32_t status=0; + + /* Clear devices array */ + SDL_memset(qsa_playback_device, 0x00, sizeof(QSA_Device)*QSA_MAX_DEVICES); + SDL_memset(qsa_capture_device, 0x00, sizeof(QSA_Device)*QSA_MAX_DEVICES); + qsa_playback_devices=0; + qsa_capture_devices=0; + + /* Set function pointers */ + /* DeviceLock and DeviceUnlock functions are used default, */ + /* provided by SDL, which uses pthread_mutex for lock/unlock */ + impl->DetectDevices=QSA_DetectDevices; + impl->GetDeviceName=QSA_GetDeviceName; + impl->OpenDevice=QSA_OpenDevice; + impl->ThreadInit=QSA_ThreadInit; + impl->WaitDevice=QSA_WaitDevice; + impl->PlayDevice=QSA_PlayDevice; + impl->GetDeviceBuf=QSA_GetDeviceBuf; + impl->CloseDevice=QSA_CloseDevice; + impl->WaitDone=QSA_WaitDone; + impl->Deinitialize=QSA_Deinitialize; + impl->LockDevice=NULL; + impl->UnlockDevice=NULL; + + impl->OnlyHasDefaultOutputDevice=0; + impl->ProvidesOwnCallbackThread=0; + impl->SkipMixerLock=0; + impl->HasCaptureSupport=1; + impl->OnlyHasDefaultOutputDevice=0; + impl->OnlyHasDefaultInputDevice=0; + + /* Check if io-audio manager is running or not */ + status=snd_cards(); + if (status==0) + { + /* if no, return immediately */ + return 1; + } + + /* At this point we are definitely has an audio device */ + return 2; +} + +AudioBootStrap QSAAUDIO_bootstrap= +{ + DRIVER_NAME, "QNX QSA Audio", QSA_Init, 0 +}; + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nto/SDL_nto_audio.h b/src/audio/qsa/SDL_qsa_audio.h similarity index 75% rename from src/audio/nto/SDL_nto_audio.h rename to src/audio/qsa/SDL_qsa_audio.h index e2a8531f1..00f3d772f 100644 --- a/src/audio/nto/SDL_nto_audio.h +++ b/src/audio/qsa/SDL_qsa_audio.h @@ -18,36 +18,45 @@ Sam Lantinga slouken@libsdl.org + + QNX Sound Architecture (QSA) SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) */ + #include "SDL_config.h" -#ifndef __SDL_NTO_AUDIO_H__ -#define __SDL_NTO_AUDIO_H__ +#ifndef __SDL_QSA_AUDIO_H__ +#define __SDL_QSA_AUDIO_H__ #include #include "../SDL_sysaudio.h" /* Hidden "this" pointer for the audio functions */ -#define _THIS SDL_AudioDevice *this +#define _THIS SDL_AudioDevice* this struct SDL_PrivateAudioData { + /* SDL capture state */ + int iscapture; + /* The audio device handle */ int cardno; int deviceno; - snd_pcm_t *audio_handle; + snd_pcm_t* audio_handle; /* The audio file descriptor */ int audio_fd; - /* The parent process id, to detect when application quits */ - pid_t parent; + /* Select timeout status */ + uint32_t timeout_on_wait; /* Raw mixing buffer */ - Uint8 *pcm_buf; + Uint8* pcm_buf; Uint32 pcm_len; }; -#endif /* __SDL_NTO_AUDIO_H__ */ +#endif /* __SDL_QSA_AUDIO_H__ */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_renderer_gles.c b/src/video/SDL_renderer_gles.c index fb4688e5f..4aec2ed11 100644 --- a/src/video/SDL_renderer_gles.c +++ b/src/video/SDL_renderer_gles.c @@ -30,6 +30,17 @@ #include "SDL_rect_c.h" #include "SDL_yuv_sw_c.h" +#ifdef __QNXNTO__ + +/* Empty function stub to get OpenGL ES 1.0 support without */ +/* OpenGL ES extension GL_OES_draw_texture_supported */ +GL_API void GL_APIENTRY glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) +{ + return; +} + +#endif /* __QNXNTO__ */ + /* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */ static const float inv255f = 1.0f / 255.0f; @@ -349,6 +360,7 @@ GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) GLenum format, type; int texture_w, texture_h; GLenum result; + switch (texture->format) { case SDL_PIXELFORMAT_INDEX1LSB: case SDL_PIXELFORMAT_INDEX1MSB: @@ -479,8 +491,6 @@ static void SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture, int pitch) { - - GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; renderdata->glBindTexture(data->type, data->texture); renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -888,6 +898,6 @@ GLES_DestroyRenderer(SDL_Renderer * renderer) SDL_free(renderer); } -#endif /* SDL_VIDEO_RENDER_OGL */ +#endif /* SDL_VIDEO_RENDER_OGL_ES */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 2b8b1d166..f2b259ac0 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2711,12 +2711,23 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) { #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params); + GLenum (APIENTRY * glGetErrorFunc) (void); GLenum attrib = 0; + GLenum error = 0; glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv"); if (!glGetIntegervFunc) { return -1; } + + glGetErrorFunc = SDL_GL_GetProcAddress("glGetError"); + if (!glGetErrorFunc) { + return -1; + } + + /* Clear value in any case */ + *value=0; + switch (attr) { case SDL_GL_RETAINED_BACKING: *value = _this->gl_config.retained_backing; @@ -2738,11 +2749,10 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) attrib = GL_DOUBLEBUFFER; break; #else - /* - * I believe double buffering is the only option in OpenGL ES - * -- in any case, GL_DOUBLEBUFFER doesn't exist - */ - *value = 1; + /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER */ + /* parameter which switches double buffer to single buffer. OpenGL ES */ + /* SDL driver must set proper value after initialization */ + *value = _this->gl_config.double_buffer; return 0; #endif case SDL_GL_DEPTH_SIZE: @@ -2824,6 +2834,29 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) } glGetIntegervFunc(attrib, (GLint *) value); + error=glGetErrorFunc(); + if (error!=GL_NO_ERROR) + { + switch (error) + { + case GL_INVALID_ENUM: + { + SDL_SetError("OpenGL error: GL_INVALID_ENUM"); + } + break; + case GL_INVALID_VALUE: + { + SDL_SetError("OpenGL error: GL_INVALID_VALUE"); + } + break; + default: + { + SDL_SetError("OpenGL error: %08X", error); + } + break; + } + return -1; + } return 0; #else SDL_Unsupported(); diff --git a/src/video/qnxgf/SDL_gf_opengles.c b/src/video/qnxgf/SDL_gf_opengles.c new file mode 100644 index 000000000..12b596275 --- /dev/null +++ b/src/video/qnxgf/SDL_gf_opengles.c @@ -0,0 +1,56 @@ +Date: Mon, 23 Mar 2009 09:17:24 +0200 +From: "Mike Gorchak" +To: "Sam Lantinga" +Subject: New QNX patches + +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#include +#include + +/* This is OpenGL ES 1.0 helper functions from OpenGL ES 1.1 specification, */ +/* which could be implemented independently from hardware, just wrappers */ + +GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) +{ + glTexParameterx(target, pname, (GLfixed)param); + return; +} + +GLAPI void APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + /* Retrieve one parameter only */ + glTexParameterx(target, pname, (GLfixed)*params); + return; +} + +GLAPI void APIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + glColor4f(((GLfloat)red)/255.f, ((GLfloat)green)/255.f, ((GLfloat)blue)/255.f, ((GLfloat)alpha)/255.f); + return; +} + diff --git a/src/video/qnxgf/SDL_gf_render.c b/src/video/qnxgf/SDL_gf_render.c index ac4307836..fbd32b76c 100644 --- a/src/video/qnxgf/SDL_gf_render.c +++ b/src/video/qnxgf/SDL_gf_render.c @@ -103,6 +103,13 @@ static SDL_Renderer* gf_createrenderer(SDL_Window* window, Uint32 flags) int32_t jt; int32_t status; + /* Check if it is OpenGL ES window */ + if ((window->flags & SDL_WINDOW_OPENGL)==SDL_WINDOW_OPENGL) + { + /* No error, just no need to create 2D renderer for OpenGL ES window */ + return NULL; + } + /* Allocate new renderer structure */ renderer=(SDL_Renderer*)SDL_calloc(1, sizeof(SDL_Renderer)); if (renderer==NULL) diff --git a/src/video/qnxgf/SDL_qnxgf.c b/src/video/qnxgf/SDL_qnxgf.c index 3745a0162..e94bd3735 100644 --- a/src/video/qnxgf/SDL_qnxgf.c +++ b/src/video/qnxgf/SDL_qnxgf.c @@ -29,6 +29,7 @@ #include "../SDL_sysvideo.h" #include "SDL_version.h" #include "SDL_syswm.h" +#include "SDL_loadso.h" /* Include QNX Graphics Framework declarations */ #include @@ -46,104 +47,132 @@ /******************************************************************************/ static SDL_DisplayMode generic_mode[]= { - {0, 320, 200, 70, NULL}, /* 320x200 modes are 70Hz and 85Hz */ - {0, 320, 200, 85, NULL}, - {0, 320, 240, 70, NULL}, /* 320x240 modes are 70Hz and 85Hz */ - {0, 320, 240, 85, NULL}, - {0, 512, 384, 60, NULL}, /* 512x384 modes are 60Hz and 70Hz */ - {0, 512, 384, 70, NULL}, - {0, 640, 480, 60, NULL}, /* 640x480 modes are 60Hz, 75Hz, 85Hz */ - {0, 640, 480, 75, NULL}, - {0, 640, 480, 85, NULL}, - {0, 800, 600, 60, NULL}, /* 800x600 modes are 60Hz, 75Hz, 85Hz */ - {0, 800, 600, 75, NULL}, - {0, 800, 600, 85, NULL}, - {0, 800, 480, 60, NULL}, /* 800x480 mode is 60Hz only */ - {0, 1024, 640, 60, NULL}, /* 1024x640 mode is 60Hz only */ - {0, 1024, 768, 60, NULL}, /* 1024x768 modes are 60Hz, 70Hz, 75Hz */ - {0, 1024, 768, 70, NULL}, - {0, 1024, 768, 75, NULL}, - {0, 1280, 720, 60, NULL}, /* 1280x720 mode is 60Hz only */ - {0, 1280, 768, 60, NULL}, /* 1280x768 mode is 60Hz only */ - {0, 1280, 800, 60, NULL}, /* 1280x800 mode is 60Hz only */ - {0, 1280, 960, 60, NULL}, /* 1280x960 mode is 60Hz only */ - {0, 1280, 1024, 60, NULL}, /* 1280x1024 modes are 60Hz, 75Hz, 85Hz and */ - {0, 1280, 1024, 75, NULL}, /* 100 Hz */ - {0, 1280, 1024, 85, NULL}, /* */ + {0, 320, 200, 70, NULL}, /* 320x200 modes are 70Hz and 85Hz */ + {0, 320, 200, 85, NULL}, + {0, 320, 240, 70, NULL}, /* 320x240 modes are 70Hz and 85Hz */ + {0, 320, 240, 85, NULL}, + {0, 512, 384, 60, NULL}, /* 512x384 modes are 60Hz and 70Hz */ + {0, 512, 384, 70, NULL}, + {0, 640, 480, 60, NULL}, /* 640x480 modes are 60Hz, 75Hz, 85Hz */ + {0, 640, 480, 75, NULL}, + {0, 640, 480, 85, NULL}, + {0, 800, 600, 60, NULL}, /* 800x600 modes are 60Hz, 75Hz, 85Hz */ + {0, 800, 600, 75, NULL}, + {0, 800, 600, 85, NULL}, + {0, 800, 480, 60, NULL}, /* 800x480 mode is 60Hz only */ + {0, 1024, 640, 60, NULL}, /* 1024x640 mode is 60Hz only */ + {0, 1024, 768, 60, NULL}, /* 1024x768 modes are 60Hz, 70Hz, 75Hz */ + {0, 1024, 768, 70, NULL}, + {0, 1024, 768, 75, NULL}, + {0, 1280, 720, 60, NULL}, /* 1280x720 mode is 60Hz only */ + {0, 1280, 768, 60, NULL}, /* 1280x768 mode is 60Hz only */ + {0, 1280, 800, 60, NULL}, /* 1280x800 mode is 60Hz only */ + {0, 1280, 960, 60, NULL}, /* 1280x960 mode is 60Hz only */ + {0, 1280, 1024, 60, NULL}, /* 1280x1024 modes are 60Hz, 75Hz, 85Hz and */ + {0, 1280, 1024, 75, NULL}, /* 100 Hz */ + {0, 1280, 1024, 85, NULL}, /* */ {0, 1280, 1024, 100, NULL}, /* */ - {0, 1400, 1050, 60, NULL}, /* 1400x1050 mode is 60Hz only */ - {0, 1440, 900, 60, NULL}, /* 1440x900 mode is 60Hz only */ - {0, 1440, 960, 60, NULL}, /* 1440x960 mode is 60Hz only */ - {0, 1600, 1200, 60, NULL}, /* 1600x1200 mode is 60Hz only */ - {0, 1680, 1050, 60, NULL}, /* 1680x1050 mode is 60Hz only */ - {0, 1920, 1080, 60, NULL}, /* 1920x1080 mode is 60Hz only */ - {0, 1920, 1200, 60, NULL}, /* 1920x1200 mode is 60Hz only */ - {0, 2048, 1536, 60, NULL}, /* 2048x1536 mode is 60Hz only */ - {0, 2048, 1080, 60, NULL}, /* 2048x1080 mode is 60Hz only */ - {0, 0, 0, 0, NULL} /* End of generic mode list */ + {0, 1400, 1050, 60, NULL}, /* 1400x1050 mode is 60Hz only */ + {0, 1440, 900, 60, NULL}, /* 1440x900 mode is 60Hz only */ + {0, 1440, 960, 60, NULL}, /* 1440x960 mode is 60Hz only */ + {0, 1600, 1200, 60, NULL}, /* 1600x1200 mode is 60Hz only */ + {0, 1680, 1050, 60, NULL}, /* 1680x1050 mode is 60Hz only */ + {0, 1920, 1080, 60, NULL}, /* 1920x1080 mode is 60Hz only */ + {0, 1920, 1200, 60, NULL}, /* 1920x1200 mode is 60Hz only */ + {0, 2048, 1536, 60, NULL}, /* 2048x1536 mode is 60Hz only */ + {0, 2048, 1080, 60, NULL}, /* 2048x1080 mode is 60Hz only */ + {0, 0, 0, 0, NULL} /* End of generic mode list */ }; /* Low level device graphics driver names, which they are reporting */ GF_DeviceCaps gf_devicename[]= { /* ATI Rage 128 graphics driver (devg-ati_rage128) */ - {"ati_rage128", SDL_GF_ACCELERATED}, + {"ati_rage128", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Fujitsu Carmine graphics driver (devg-carmine.so) */ - {"carmine", SDL_GF_ACCELERATED}, + {"carmine", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* C&T graphics driver (devg-chips.so) */ - {"chips", SDL_GF_ACCELERATED}, + {"chips", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Fujitsu Coral graphics driver (devg-coral.so) */ - {"coral", SDL_GF_ACCELERATED}, + {"coral", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* Intel integrated graphics driver (devg-extreme2.so) */ - {"extreme2", SDL_GF_ACCELERATED}, + {"extreme2", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* Unaccelerated FB driver (devg-flat.so) */ - {"flat", SDL_GF_UNACCELERATED}, + {"flat", SDL_GF_UNACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* NS Geode graphics driver (devg-geode.so) */ - {"geode", SDL_GF_ACCELERATED}, + {"geode", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Geode LX graphics driver (devg-geodelx.so) */ - {"geodelx", SDL_GF_ACCELERATED}, + {"geodelx", SDL_GF_ACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Intel integrated graphics driver (devg-gma9xx.so) */ - {"gma", SDL_GF_ACCELERATED}, + {"gma", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* Intel integrated graphics driver (devg-i810.so) */ - {"i810", SDL_GF_ACCELERATED}, + {"i810", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Intel integrated graphics driver (devg-i830.so) */ - {"i830", SDL_GF_ACCELERATED}, + {"i830", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Geode LX graphics driver (devg-lx800.so) */ - {"lx800", SDL_GF_ACCELERATED}, + {"lx800", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Matrox Gxx graphics driver (devg-matroxg.so) */ - {"matroxg", SDL_GF_ACCELERATED}, + {"matroxg", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Intel Poulsbo graphics driver (devg-poulsbo.so) */ - {"poulsbo", SDL_GF_ACCELERATED}, + {"poulsbo", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* ATI Radeon driver (devg-radeon.so) */ - {"radeon", SDL_GF_ACCELERATED}, + {"radeon", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* ATI Rage driver (devg-rage.so) */ - {"rage", SDL_GF_ACCELERATED}, + {"rage", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* S3 Savage graphics driver (devg-s3_savage.so) */ - {"s3_savage", SDL_GF_ACCELERATED}, + {"s3_savage", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* SiS630 integrated graphics driver (devg-sis630.so) */ - {"sis630", SDL_GF_ACCELERATED}, + {"sis630", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* PowerVR SGX 535 graphics driver (devg-poulsbo.so) */ - {"sgx", SDL_GF_ACCELERATED}, + {"sgx", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_ACCELERATED_3D}, /* SM Voyager GX graphics driver (devg-smi5xx.so) */ - {"smi5xx", SDL_GF_ACCELERATED}, + {"smi5xx", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* Silicon Motion graphics driver (devg-smi7xx.so) */ - {"smi7xx", SDL_GF_ACCELERATED}, + {"smi7xx", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* SVGA unaccelerated gfx driver (devg-svga.so) */ - {"svga", SDL_GF_UNACCELERATED}, + {"svga", SDL_GF_UNACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* nVidia TNT graphics driver (devg-tnt.so) */ - {"tnt", SDL_GF_ACCELERATED}, + {"tnt", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* VIA integrated graphics driver (devg-tvia.so) */ - {"tvia", SDL_GF_ACCELERATED}, + {"tvia", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* VIA UniChrome graphics driver (devg-unichrome.so) */ - {"unichrome", SDL_GF_ACCELERATED}, + {"unichrome", SDL_GF_ACCELERATED | SDL_GF_NOLOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* VESA unaccelerated gfx driver (devg-vesa.so) */ - {"vesa", SDL_GF_UNACCELERATED}, + {"vesa", SDL_GF_UNACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* VmWare graphics driver (devg-volari.so) */ - {"vmware", SDL_GF_ACCELERATED}, + {"vmware", SDL_GF_ACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* XGI XP10 graphics driver (devg-volari.so) */ - {"volari", SDL_GF_ACCELERATED}, + {"volari", SDL_GF_ACCELERATED | SDL_GF_LOWRESOLUTION | + SDL_GF_UNACCELERATED_3D}, /* End of list */ - {NULL, 0x00000000} + {NULL, 0x00000000} }; /*****************************************************************************/ @@ -314,7 +343,7 @@ int qnxgf_videoinit(_THIS) { /* video initialization problem */ SDL_free(didata); - SDL_SetError("display query failed"); + SDL_SetError("GF: Display query failed"); return -1; } @@ -324,7 +353,7 @@ int qnxgf_videoinit(_THIS) { /* video initialization problem */ SDL_free(didata); - SDL_SetError("couldn't attach to display"); + SDL_SetError("GF: Couldn't attach to display"); return -1; } @@ -335,7 +364,7 @@ int qnxgf_videoinit(_THIS) status=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); if (status!=GF_ERR_OK) { - SDL_SetError("couldn't attach to main layer, it could be busy"); + SDL_SetError("GF: Couldn't attach to main layer, it could be busy"); /* Failed to attach to main layer */ return -1; @@ -432,6 +461,16 @@ void qnxgf_getdisplaymodes(_THIS) break; } + /* Check if driver do not supports doublescan video modes */ + if ((didata->caps & SDL_GF_LOWRESOLUTION)!=SDL_GF_LOWRESOLUTION) + { + if (generic_mode[jt].w<640) + { + jt++; + continue; + } + } + mode.w=generic_mode[jt].w; mode.h=generic_mode[jt].h; mode.refresh_rate=generic_mode[jt].refresh_rate; @@ -597,7 +636,7 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) if (result!=GF_ERR_OK) { /* Display mode/resolution switch has been failed */ - SDL_SetError("mode is not supported by graphics driver"); + SDL_SetError("GF: Mode is not supported by graphics driver"); return -1; } else @@ -610,7 +649,7 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) result=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); if (result!=GF_ERR_OK) { - SDL_SetError("couldn't attach to main layer, it could be busy"); + SDL_SetError("GF: Couldn't attach to main layer, it could be busy"); /* Failed to attach to main displayable layer */ return -1; @@ -674,8 +713,10 @@ int qnxgf_getdisplaygammaramp(_THIS, Uint16* ramp) int qnxgf_createwindow(_THIS, SDL_Window* window) { + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata; SDL_WindowData* wdata; + int32_t status; /* QNX GF supports fullscreen window modes only */ if ((window->flags & SDL_WINDOW_FULLSCREEN)!=SDL_WINDOW_FULLSCREEN) @@ -705,7 +746,7 @@ int qnxgf_createwindow(_THIS, SDL_Window* window) /* Check if end of display list has been reached */ if (mode.refresh_rate==0x0000FFFF) { - SDL_SetError("desired video mode is not supported"); + SDL_SetError("GF: Desired video mode is not supported"); /* Failed to create new window */ return -1; @@ -716,7 +757,12 @@ int qnxgf_createwindow(_THIS, SDL_Window* window) window->flags|=SDL_WINDOW_FULLSCREEN; /* Setup fullscreen mode, bpp used from desktop mode in this case */ - qnxgf_setdisplaymode(_this, &mode); + status=qnxgf_setdisplaymode(_this, &mode); + if (status!=0) + { + /* Failed to swith fullscreen video mode */ + return -1; + } } } @@ -744,8 +790,37 @@ int qnxgf_createwindow(_THIS, SDL_Window* window) /* Check if window must support OpenGL ES rendering */ if ((window->flags & SDL_WINDOW_OPENGL)==SDL_WINDOW_OPENGL) { - /* Mark this window as OpenGL ES compatible */ - wdata->uses_gles=SDL_TRUE; + #if defined(SDL_VIDEO_OPENGL_ES) + EGLBoolean initstatus; + + /* Mark this window as OpenGL ES compatible */ + wdata->uses_gles=SDL_TRUE; + + /* Create connection to OpenGL ES */ + if (gfdata->egldisplay==EGL_NO_DISPLAY) + { + gfdata->egldisplay=eglGetDisplay(gfdata->gfdev); + if (gfdata->egldisplay==EGL_NO_DISPLAY) + { + SDL_SetError("GF: Can't get connection to OpenGL ES"); + return -1; + } + + /* Initialize OpenGL ES library, ignore EGL version */ + initstatus=eglInitialize(gfdata->egldisplay, NULL, NULL); + if (initstatus!=EGL_TRUE) + { + SDL_SetError("GF: Can't init OpenGL ES library"); + return -1; + } + } + + /* Increment GL ES reference count usage */ + gfdata->egl_refcount++; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return -1; + #endif /* SDL_VIDEO_OPENGL_ES */ } /* Window has been successfully created */ @@ -804,11 +879,37 @@ void qnxgf_setwindowgrab(_THIS, SDL_Window* window) void qnxgf_destroywindow(_THIS, SDL_Window* window) { + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata; SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata; if (wdata!=NULL) { + #if defined(SDL_VIDEO_OPENGL_ES) + /* Destroy OpenGL ES surface if it was created */ + if (wdata->gles_surface!=EGL_NO_SURFACE) + { + eglDestroySurface(gfdata->egldisplay, wdata->gles_surface); + } + + /* Free any 3D target if it was created before */ + if (wdata->target_created==SDL_TRUE) + { + gf_3d_target_free(wdata->target); + } + + + gfdata->egl_refcount--; + if (gfdata->egl_refcount==0) + { + /* Terminate connection to OpenGL ES */ + if (gfdata->egldisplay!=EGL_NO_DISPLAY) + { + eglTerminate(gfdata->egldisplay); + gfdata->egldisplay=EGL_NO_DISPLAY; + } + } + #endif /* SDL_VIDEO_OPENGL_ES */ } } @@ -826,7 +927,7 @@ SDL_bool qnxgf_getwindowwminfo(_THIS, SDL_Window* window, struct SDL_SysWMinfo* } else { - SDL_SetError("application not compiled with SDL %d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + SDL_SetError("Application not compiled with SDL %d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION); return SDL_FALSE; } @@ -839,50 +940,382 @@ SDL_bool qnxgf_getwindowwminfo(_THIS, SDL_Window* window, struct SDL_SysWMinfo* /*****************************************************************************/ int qnxgf_gl_loadlibrary(_THIS, const char* path) { - /* Failed to load new GL library */ - return -1; + #if defined(SDL_VIDEO_OPENGL_ES) + /* Check if OpenGL ES library is specified for GF driver */ + if (path==NULL) + { + path=SDL_getenv("SDL_OPENGL_LIBRARY"); + if (path==NULL) + { + path=SDL_getenv("SDL_OPENGLES_LIBRARY"); + } + } + + /* Check if default library loading requested */ + if (path==NULL) + { + /* Already linked with GF library which provides egl* subset of */ + /* functions, use Common profile of OpenGL ES library by default */ + path="/usr/lib/libGLES_CM.so.1"; + } + + /* Load dynamic library */ + _this->gl_config.dll_handle=SDL_LoadObject(path); + if (!_this->gl_config.dll_handle) + { + /* Failed to load new GL ES library */ + SDL_SetError("GF: Failed to locate OpenGL ES library"); + return -1; + } + + /* Store OpenGL ES library path and name */ + SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); + + /* New OpenGL ES library is loaded */ + return 0; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return -1; + #endif /* SDL_VIDEO_OPENGL_ES */ } void* qnxgf_gl_getprocaddres(_THIS, const char* proc) { - /* Failed to get GL function address pointer */ - return NULL; + #if defined(SDL_VIDEO_OPENGL_ES) + void* function_address; + + /* Try to get function address through the egl interface */ + function_address=eglGetProcAddress(proc); + if (function_address!=NULL) + { + return function_address; + } + + /* Then try to get function in the OpenGL ES library */ + if (_this->gl_config.dll_handle) + { + function_address=SDL_LoadFunction(_this->gl_config.dll_handle, proc); + if (function_address!=NULL) + { + return function_address; + } + } + + /* Failed to get GL ES function address pointer */ + SDL_SetError("GF: Cannot locate given function name"); + return NULL; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return NULL; + #endif /* SDL_VIDEO_OPENGL_ES */ } void qnxgf_gl_unloadlibrary(_THIS) { + #if defined(SDL_VIDEO_OPENGL_ES) + /* Unload OpenGL ES library */ + if (_this->gl_config.dll_handle) + { + SDL_UnloadObject(_this->gl_config.dll_handle); + _this->gl_config.dll_handle=NULL; + } + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return; + #endif /* SDL_VIDEO_OPENGL_ES */ } SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) { - /* Failed to create GL context */ - return NULL; + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata; + SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata; + EGLBoolean status; + int32_t gfstatus; + EGLint configs; + uint32_t surfaces; + uint32_t attr_pos; + + /* Prepare attributes list to pass them to OpenGL ES */ + attr_pos=0; + wdata->gles_attributes[attr_pos++]=EGL_NATIVE_VISUAL_ID; + wdata->gles_attributes[attr_pos++]=qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format); + wdata->gles_attributes[attr_pos++]=EGL_RED_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.red_size; + wdata->gles_attributes[attr_pos++]=EGL_GREEN_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.green_size; + wdata->gles_attributes[attr_pos++]=EGL_BLUE_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.blue_size; + wdata->gles_attributes[attr_pos++]=EGL_ALPHA_SIZE; + if (_this->gl_config.alpha_size) + { + wdata->gles_attributes[attr_pos++]=_this->gl_config.alpha_size; + } + else + { + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + } + wdata->gles_attributes[attr_pos++]=EGL_DEPTH_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.depth_size; + if (_this->gl_config.buffer_size) + { + wdata->gles_attributes[attr_pos++]=EGL_BUFFER_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.buffer_size; + } + if (_this->gl_config.stencil_size) + { + wdata->gles_attributes[attr_pos++]=EGL_STENCIL_SIZE; + wdata->gles_attributes[attr_pos++]=_this->gl_config.buffer_size; + } + + /* OpenGL ES 1.0 uses double buffer by default, so if application */ + /* do not requested double buffering, switch to single buffer */ + if (!_this->gl_config.double_buffer) + { + wdata->gles_attributes[attr_pos++]=EGL_SINGLE_BUFFER; + wdata->gles_attributes[attr_pos++]=EGL_TRUE; + surfaces=1; + } + else + { + surfaces=2; + } + + /* Set number of samples in multisampling */ + if (_this->gl_config.multisamplesamples) + { + wdata->gles_attributes[attr_pos++]=EGL_SAMPLES; + wdata->gles_attributes[attr_pos++]=_this->gl_config.multisamplesamples; + } + + /* Multisample buffers, OpenGL ES 1.0 spec defines 0 or 1 buffer */ + if (_this->gl_config.multisamplebuffers) + { + wdata->gles_attributes[attr_pos++]=EGL_SAMPLE_BUFFERS; + wdata->gles_attributes[attr_pos++]=_this->gl_config.multisamplebuffers; + } + + /* Finish attributes list */ + wdata->gles_attributes[attr_pos]=EGL_NONE; + + /* Request first suitable framebuffer configuration */ + status=eglChooseConfig(gfdata->egldisplay, wdata->gles_attributes, &wdata->gles_config, 1, &configs); + if (status!=EGL_TRUE) + { + SDL_SetError("GF: Can't find closest configuration for OpenGL ES"); + return NULL; + } + + /* Create OpenGL ES context */ + wdata->gles_context=eglCreateContext(gfdata->egldisplay, wdata->gles_config, EGL_NO_CONTEXT, NULL); + if (wdata->gles_context==EGL_NO_CONTEXT) + { + SDL_SetError("GF: OpenGL ES context creation has been failed"); + return NULL; + } + + /* Free any 3D target if it was created before */ + if (wdata->target_created==SDL_TRUE) + { + gf_3d_target_free(wdata->target); + } + + /* Create surface(s) target for OpenGL ES */ + gfstatus=gf_3d_target_create(&wdata->target, didata->layer, NULL, + surfaces, didata->current_mode.w, didata->current_mode.h, + qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format)); + + if (gfstatus!=GF_ERR_OK) + { + /* Destroy just created context */ + eglDestroyContext(gfdata->egldisplay, wdata->gles_context); + wdata->gles_context=EGL_NO_CONTEXT; + + /* Mark 3D target as unallocated */ + wdata->target_created=SDL_FALSE; + SDL_SetError("GF: OpenGL ES target could not be created"); + return NULL; + } + else + { + wdata->target_created=SDL_TRUE; + } + + /* Create target rendering surface on whole screen */ + wdata->gles_surface=eglCreateWindowSurface(gfdata->egldisplay, wdata->gles_config, wdata->target, NULL); + if (wdata->gles_surface==EGL_NO_SURFACE) + { + /* Destroy 3d target */ + gf_3d_target_free(wdata->target); + wdata->target_created=SDL_FALSE; + + /* Destroy OpenGL ES context */ + eglDestroyContext(gfdata->egldisplay, wdata->gles_context); + wdata->gles_context=EGL_NO_CONTEXT; + + SDL_SetError("GF: OpenGL ES surface could not be created"); + return NULL; + } + + /* Make just created context current */ + status=eglMakeCurrent(gfdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context); + if (status!=EGL_TRUE) + { + /* Destroy OpenGL ES surface */ + eglDestroySurface(gfdata->egldisplay, wdata->gles_surface); + + /* Destroy 3d target */ + gf_3d_target_free(wdata->target); + wdata->target_created=SDL_FALSE; + + /* Destroy OpenGL ES context */ + eglDestroyContext(gfdata->egldisplay, wdata->gles_context); + wdata->gles_context=EGL_NO_CONTEXT; + + /* Failed to set current GL ES context */ + SDL_SetError("GF: Can't set OpenGL ES context on creation"); + return NULL; + } + + /* Setup into SDL internals state of OpenGL ES: */ + /* it is accelerated or not */ + if ((didata->caps & SDL_GF_ACCELERATED_3D)==SDL_GF_ACCELERATED_3D) + { + _this->gl_config.accelerated=1; + } + else + { + _this->gl_config.accelerated=0; + } + + /* Always clear stereo enable, since OpenGL ES do not supports stereo */ + _this->gl_config.stereo=0; + + /* Failed to create GL ES context */ + return wdata->gles_context; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return NULL; + #endif /* SDL_VIDEO_OPENGL_ES */ } int qnxgf_gl_makecurrent(_THIS, SDL_Window* window, SDL_GLContext context) { - /* Failed to set current GL context */ - return -1; + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + SDL_WindowData* wdata; + EGLBoolean status; + + if ((window==NULL) && (context==NULL)) + { + status=eglMakeCurrent(gfdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (status!=EGL_TRUE) + { + /* Failed to set current GL ES context */ + SDL_SetError("GF: Can't set OpenGL ES context"); + return -1; + } + } + else + { + wdata=(SDL_WindowData*)window->driverdata; + status=eglMakeCurrent(gfdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context); + if (status!=EGL_TRUE) + { + /* Failed to set current GL ES context */ + SDL_SetError("GF: Can't set OpenGL ES context"); + return -1; + } + } + + return 0; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return -1; + #endif /* SDL_VIDEO_OPENGL_ES */ } int qnxgf_gl_setswapinterval(_THIS, int interval) { - /* Failed to set swap interval */ - return -1; + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + EGLBoolean status; + + /* Check if OpenGL ES connection has been initialized */ + if (gfdata->egldisplay!=EGL_NO_DISPLAY) + { + /* Set swap OpenGL ES interval */ + status=eglSwapInterval(gfdata->egldisplay, interval); + if (status==EGL_TRUE) + { + /* Return success to upper level */ + gfdata->swapinterval=interval; + return 0; + } + } + + /* Failed to set swap interval */ + SDL_SetError("GF: Cannot set swap interval"); + return -1; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return -1; + #endif /* SDL_VIDEO_OPENGL_ES */ } int qnxgf_gl_getswapinterval(_THIS) { - /* Failed to get default swap interval */ - return -1; + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + + /* Return default swap interval value */ + return gfdata->swapinterval; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return -1; + #endif /* SDL_VIDEO_OPENGL_ES */ } void qnxgf_gl_swapwindow(_THIS, SDL_Window* window) { + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata; + + eglSwapBuffers(gfdata->egldisplay, wdata->gles_surface); + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return; + #endif /* SDL_VIDEO_OPENGL_ES */ } void qnxgf_gl_deletecontext(_THIS, SDL_GLContext context) { + #if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + EGLBoolean status; + + /* Check if OpenGL ES connection has been initialized */ + if (gfdata->egldisplay!=EGL_NO_DISPLAY) + { + if (context!=EGL_NO_CONTEXT) + { + status=eglDestroyContext(gfdata->egldisplay, context); + if (status!=EGL_TRUE) + { + /* Error during OpenGL ES context destroying */ + SDL_SetError("GF: OpenGL ES context destroy error"); + return; + } + } + } + + return; + #else + SDL_SetError("GF: OpenGL ES support is not compiled in"); + return; + #endif /* SDL_VIDEO_OPENGL_ES */ } /*****************************************************************************/ diff --git a/src/video/qnxgf/SDL_qnxgf.h b/src/video/qnxgf/SDL_qnxgf.h index 08814bf4b..b080ac145 100644 --- a/src/video/qnxgf/SDL_qnxgf.h +++ b/src/video/qnxgf/SDL_qnxgf.h @@ -30,12 +30,22 @@ #include "../SDL_sysvideo.h" #include +#include + +#if defined(SDL_VIDEO_OPENGL_ES) + #include +#endif /* SDL_VIDEO_OPENGL_ES */ typedef struct SDL_VideoData { gf_dev_t gfdev; /* GF device handle */ gf_dev_info_t gfdev_info; /* GF device information */ SDL_bool gfinitialized; /* GF device initialization status */ + #if defined(SDL_VIDEO_OPENGL_ES) + EGLDisplay egldisplay; /* OpenGL ES display connection */ + uint32_t egl_refcount; /* OpenGL ES reference count */ + uint32_t swapinterval; /* OpenGL ES default swap interval */ + #endif /* SDL_VIDEO_OPENGL_ES */ } SDL_VideoData; #define SDL_VIDEO_GF_DEVICENAME_MAX 257 @@ -55,9 +65,23 @@ typedef struct SDL_DisplayData typedef struct SDL_WindowData { - SDL_bool uses_gles; /* if true window must support OpenGL ES*/ + SDL_bool uses_gles; /* true if window support OpenGL ES */ + #if defined(SDL_VIDEO_OPENGL_ES) + gf_3d_target_t target; /* OpenGL ES window target */ + SDL_bool target_created; /* GF 3D target is created if true */ + EGLConfig gles_config; /* OpenGL ES framebuffer configuration*/ + EGLContext gles_context; /* OpenGL ES context */ + EGLint gles_attributes[256]; /* OpenGL ES attributes for context */ + EGLSurface gles_surface; /* OpenGL ES target rendering surface */ + #endif /* SDL_VIDEO_OPENGL_ES */ } SDL_WindowData; +typedef struct SDL_GLDriverData +{ + #if defined(SDL_VIDEO_OPENGL_ES) + #endif /* SDL_VIDEO_OPENGL_ES */ +} SDL_GLDriverData; + /****************************************************************************/ /* Low level GF graphics driver capabilities */ /****************************************************************************/ @@ -69,6 +93,10 @@ typedef struct GF_DeviceCaps #define SDL_GF_UNACCELERATED 0x00000000 #define SDL_GF_ACCELERATED 0x00000001 +#define SDL_GF_NOLOWRESOLUTION 0x00000000 +#define SDL_GF_LOWRESOLUTION 0x00000002 +#define SDL_GF_UNACCELERATED_3D 0x00000000 +#define SDL_GF_ACCELERATED_3D 0x00000004 /****************************************************************************/ /* SDL_VideoDevice functions declaration */ diff --git a/test/testdyngles.c b/test/testdyngles.c index e63d32179..2539363fc 100644 --- a/test/testdyngles.c +++ b/test/testdyngles.c @@ -65,7 +65,7 @@ typedef struct void (APIENTRY * glClear) (GLbitfield); void (APIENTRY * glDisable) (GLenum); void (APIENTRY * glEnable) (GLenum); - void (APIENTRY * glColor4ub) (GLubyte, GLubyte, GLubyte, GLubyte); + void (APIENTRY * glColor4f) (GLfloat, GLfloat, GLfloat, GLfloat); void (APIENTRY * glPointSize) (GLfloat); void (APIENTRY * glHint) (GLenum, GLenum); void (APIENTRY * glBlendFunc) (GLenum, GLenum); @@ -89,7 +89,7 @@ init_glfuncs(glfuncs * f) f->glClear = get_funcaddr("glClear"); f->glDisable = get_funcaddr("glDisable"); f->glEnable = get_funcaddr("glEnable"); - f->glColor4ub = get_funcaddr("glColor4ub"); + f->glColor4f = get_funcaddr("glColor4f"); f->glPointSize = get_funcaddr("glPointSize"); f->glHint = get_funcaddr("glHint"); f->glBlendFunc = get_funcaddr("glBlendFunc"); @@ -118,6 +118,10 @@ main(int argc, char *argv[]) /* you may want to change these according to the platform */ video_w = 320; video_h = 480; + #ifdef __QNXNTO__ + video_h = 640; + video_w = 480; + #endif /* __QNXNTO__ */ if (argv[1]) { gl_library = argv[1]; @@ -149,7 +153,11 @@ main(int argc, char *argv[]) pixels[3 * i + 2] = rand() % 250 - 125; } - f.glViewport(0, 0, video_w, video_h); + #ifdef __QNXNTO__ + f.glViewport(0, 0, video_h, video_w); + #else + f.glViewport(0, 0, video_w, video_h); + #endif /* __QNXNTO__ */ f.glMatrixMode(GL_PROJECTION); f.glLoadIdentity(); @@ -180,7 +188,7 @@ main(int argc, char *argv[]) f.glRotatef(2.0, 1.0, 1.0, 1.0); f.glRotatef(1.0, 0.0, 1.0, 1.0); - f.glColor4ub(255, 255, 255, 255); + f.glColor4f(1.0, 1.0, 1.0, 1.0); f.glEnableClientState(GL_VERTEX_ARRAY); f.glVertexPointer(3, GL_FLOAT, 0, pixels); @@ -189,6 +197,8 @@ main(int argc, char *argv[]) SDL_GL_SwapBuffers(); while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) + done = 1; if (event.type == SDL_KEYDOWN) done = 1; } diff --git a/test/testgl2.c b/test/testgl2.c index 2369b5659..d6a36b149 100644 --- a/test/testgl2.c +++ b/test/testgl2.c @@ -168,6 +168,7 @@ main(int argc, char *argv[]) SDL_DisplayMode mode; SDL_Event event; Uint32 then, now, frames; + int status; /* Initialize parameters */ fsaa = 0; @@ -241,26 +242,52 @@ main(int argc, char *argv[]) printf("Extensions : %s\n", glGetString(GL_EXTENSIONS)); printf("\n"); - SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); - printf("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); - printf("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); - printf("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); - printf("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value); - SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &value); - printf("SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value); + status=SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); + if (!status) { + printf("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); + if (!status) { + printf("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); + if (!status) { + printf("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); + if (!status) { + printf("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value); + } else { + printf("Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError()); + } if (fsaa) { - SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); - printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); - SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); - printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, - value); + status=SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); + if (!status) { + printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); + } else { + printf("Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); + if (!status) { + printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value); + } else { + printf("Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n", SDL_GetError()); + } } if (accel) { - SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); - printf("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); + status=SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); + if (!status) + { + printf("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); + } else { + printf("Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n", SDL_GetError()); + } } /* Set rendering settings */ diff --git a/test/testgles.c b/test/testgles.c index 3b539ef85..fb33afcb2 100644 --- a/test/testgles.c +++ b/test/testgles.c @@ -88,6 +88,7 @@ main(int argc, char *argv[]) SDL_DisplayMode mode; SDL_Event event; Uint32 then, now, frames; + int status; /* Initialize parameters */ fsaa = 0; @@ -160,24 +161,52 @@ main(int argc, char *argv[]) printf("Extensions : %s\n", glGetString(GL_EXTENSIONS)); printf("\n"); - SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); - printf("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); - printf("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); - printf("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); - SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); - printf("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value); + status=SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); + if (!status) { + printf("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); + if (!status) { + printf("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); + if (!status) { + printf("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); + } else { + printf("Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); + if (!status) { + printf("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value); + } else { + printf("Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError()); + } if (fsaa) { - SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); - printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); - SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); - printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, - value); + status=SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); + if (!status) { + printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); + } else { + printf("Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n", SDL_GetError()); + } + status=SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); + if (!status) { + printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value); + } else { + printf("Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n", SDL_GetError()); + } } if (accel) { - SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); - printf("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); + status=SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); + if (!status) + { + printf("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); + } else { + printf("Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n", SDL_GetError()); + } } /* Set rendering settings */ diff --git a/test/testmultiaudio.c b/test/testmultiaudio.c index 3c86dc19f..5d6fc04bf 100644 --- a/test/testmultiaudio.c +++ b/test/testmultiaudio.c @@ -55,7 +55,7 @@ test_multi_audio(int devcount) spec.userdata = &cbd[0]; cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0); if (cbd[0].dev == 0) { - printf("Open device failed: %s\n", SDL_GetError()); + printf("\nOpen device failed: %s\n", SDL_GetError()); } else { SDL_PauseAudioDevice(cbd[0].dev, 0); while (!cbd[0].done)