Merged 'default' into branch 'iOS-improvements'

This commit is contained in:
Alex Szpakowski
2014-07-31 03:14:10 -03:00
54 changed files with 876 additions and 357 deletions

View File

@@ -178,6 +178,12 @@ SDL_AudioPlayDevice_Default(_THIS)
{ /* no-op. */
}
static int
SDL_AudioGetPendingBytes_Default(_THIS)
{
return 0;
}
static Uint8 *
SDL_AudioGetDeviceBuf_Default(_THIS)
{
@@ -205,22 +211,34 @@ SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
return -1;
}
static SDL_INLINE SDL_bool
is_in_audio_device_thread(SDL_AudioDevice * device)
{
/* The device thread locks the same mutex, but not through the public API.
This check is in case the application, in the audio callback,
tries to lock the thread that we've already locked from the
device thread...just in case we only have non-recursive mutexes. */
if (device->thread && (SDL_ThreadID() == device->threadid)) {
return SDL_TRUE;
}
return SDL_FALSE;
}
static void
SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
{
if (device->thread && (SDL_ThreadID() == device->threadid)) {
return;
if (!is_in_audio_device_thread(device)) {
SDL_LockMutex(device->mixer_lock);
}
SDL_LockMutex(device->mixer_lock);
}
static void
SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
{
if (device->thread && (SDL_ThreadID() == device->threadid)) {
return;
if (!is_in_audio_device_thread(device)) {
SDL_UnlockMutex(device->mixer_lock);
}
SDL_UnlockMutex(device->mixer_lock);
}
@@ -241,6 +259,7 @@ finalize_audio_entry_points(void)
FILL_STUB(ThreadInit);
FILL_STUB(WaitDevice);
FILL_STUB(PlayDevice);
FILL_STUB(GetPendingBytes);
FILL_STUB(GetDeviceBuf);
FILL_STUB(WaitDone);
FILL_STUB(CloseDevice);
@@ -312,6 +331,181 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream)
}
#endif
/* buffer queueing support... */
/* this expects that you managed thread safety elsewhere. */
static void
free_audio_queue(SDL_AudioBufferQueue *buffer)
{
while (buffer) {
SDL_AudioBufferQueue *next = buffer->next;
SDL_free(buffer);
buffer = next;
}
}
static void SDLCALL
SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
{
/* this function always holds the mixer lock before being called. */
Uint32 len = (Uint32) _len;
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
SDL_AudioBufferQueue *buffer;
SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */
while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
const Uint32 avail = buffer->datalen - buffer->startpos;
const Uint32 cpy = SDL_min(len, avail);
SDL_assert(device->queued_bytes >= avail);
SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
buffer->startpos += cpy;
stream += cpy;
device->queued_bytes -= cpy;
len -= cpy;
if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */
device->buffer_queue_head = buffer->next;
SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
buffer->next = device->buffer_queue_pool;
device->buffer_queue_pool = buffer;
}
}
SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
if (len > 0) { /* fill any remaining space in the stream with silence. */
SDL_assert(device->buffer_queue_head == NULL);
SDL_memset(stream, device->spec.silence, len);
}
if (device->buffer_queue_head == NULL) {
device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
}
}
int
SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
{
SDL_AudioDevice *device = get_audio_device(devid);
const Uint8 *data = (const Uint8 *) _data;
SDL_AudioBufferQueue *orighead;
SDL_AudioBufferQueue *origtail;
Uint32 origlen;
Uint32 datalen;
if (!device) {
return -1; /* get_audio_device() will have set the error state */
}
if (device->spec.callback != SDL_BufferQueueDrainCallback) {
return SDL_SetError("Audio device has a callback, queueing not allowed");
}
current_audio.impl.LockDevice(device);
orighead = device->buffer_queue_head;
origtail = device->buffer_queue_tail;
origlen = origtail ? origtail->datalen : 0;
while (len > 0) {
SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
/* tail packet missing or completely full; we need a new packet. */
packet = device->buffer_queue_pool;
if (packet != NULL) {
/* we have one available in the pool. */
device->buffer_queue_pool = packet->next;
} else {
/* Have to allocate a new one! */
packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
if (packet == NULL) {
/* uhoh, reset so we've queued nothing new, free what we can. */
if (!origtail) {
packet = device->buffer_queue_head; /* whole queue. */
} else {
packet = origtail->next; /* what we added to existing queue. */
origtail->next = NULL;
origtail->datalen = origlen;
}
device->buffer_queue_head = orighead;
device->buffer_queue_tail = origtail;
device->buffer_queue_pool = NULL;
current_audio.impl.UnlockDevice(device);
free_audio_queue(packet); /* give back what we can. */
return SDL_OutOfMemory();
}
}
packet->datalen = 0;
packet->startpos = 0;
packet->next = NULL;
SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
if (device->buffer_queue_tail == NULL) {
device->buffer_queue_head = packet;
} else {
device->buffer_queue_tail->next = packet;
}
device->buffer_queue_tail = packet;
}
datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
SDL_memcpy(packet->data + packet->datalen, data, datalen);
data += datalen;
len -= datalen;
packet->datalen += datalen;
device->queued_bytes += datalen;
}
current_audio.impl.UnlockDevice(device);
return 0;
}
Uint32
SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
{
Uint32 retval = 0;
SDL_AudioDevice *device = get_audio_device(devid);
/* Nothing to do unless we're set up for queueing. */
if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
current_audio.impl.LockDevice(device);
retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
current_audio.impl.UnlockDevice(device);
}
return retval;
}
void
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
SDL_AudioBufferQueue *buffer = NULL;
if (!device) {
return; /* nothing to do. */
}
/* Blank out the device and release the mutex. Free it afterwards. */
current_audio.impl.LockDevice(device);
buffer = device->buffer_queue_head;
device->buffer_queue_tail = NULL;
device->buffer_queue_head = NULL;
device->queued_bytes = 0;
current_audio.impl.UnlockDevice(device);
free_audio_queue(buffer);
}
#if defined(__ANDROID__)
#include <android/log.h>
#endif
@@ -788,6 +982,10 @@ close_audio_device(SDL_AudioDevice * device)
current_audio.impl.CloseDevice(device);
device->opened = 0;
}
free_audio_queue(device->buffer_queue_head);
free_audio_queue(device->buffer_queue_pool);
SDL_FreeAudioMem(device);
}
@@ -802,11 +1000,6 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
{
SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
if (orig->callback == NULL) {
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
return 0;
}
if (orig->freq == 0) {
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
@@ -859,7 +1052,6 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
return 1;
}
static SDL_AudioDeviceID
open_audio_device(const char *devname, int iscapture,
const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
@@ -938,7 +1130,7 @@ open_audio_device(const char *devname, int iscapture,
SDL_OutOfMemory();
return 0;
}
SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
SDL_zerop(device);
device->spec = *obtained;
device->enabled = 1;
device->paused = 1;
@@ -956,8 +1148,9 @@ open_audio_device(const char *devname, int iscapture,
/* force a device detection if we haven't done one yet. */
if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
((!iscapture) && (current_audio.outputDevices == NULL)) )
((!iscapture) && (current_audio.outputDevices == NULL)) ) {
SDL_GetNumAudioDevices(iscapture);
}
if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
close_audio_device(device);
@@ -1031,6 +1224,25 @@ open_audio_device(const char *devname, int iscapture,
}
}
if (device->spec.callback == NULL) { /* use buffer queueing? */
/* pool a few packets to start. Enough for two callbacks. */
const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
for (i = 0; i < wantpackets; i++) {
SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
if (packet) { /* don't care if this fails, we'll deal later. */
packet->datalen = 0;
packet->startpos = 0;
packet->next = device->buffer_queue_pool;
device->buffer_queue_pool = packet;
}
}
device->spec.callback = SDL_BufferQueueDrainCallback;
device->spec.userdata = device;
}
/* Find an available device ID and store the structure... */
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
if (open_devices[id] == NULL) {

View File

@@ -33,6 +33,26 @@ typedef struct SDL_AudioDevice SDL_AudioDevice;
/* Used by audio targets during DetectDevices() */
typedef void (*SDL_AddAudioDevice)(const char *name);
/* This is the size of a packet when using SDL_QueueAudio(). We allocate
these as necessary and pool them, under the assumption that we'll
eventually end up with a handful that keep recycling, meeting whatever
the app needs. We keep packing data tightly as more arrives to avoid
wasting space, and if we get a giant block of data, we'll split them
into multiple packets behind the scenes. My expectation is that most
apps will have 2-3 of these in the pool. 8k should cover most needs, but
if this is crippling for some embedded system, we can #ifdef this.
The system preallocates enough packets for 2 callbacks' worth of data. */
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN (8 * 1024)
/* Used by apps that queue audio instead of using the callback. */
typedef struct SDL_AudioBufferQueue
{
Uint8 data[SDL_AUDIOBUFFERQUEUE_PACKETLEN]; /* packet data. */
Uint32 datalen; /* bytes currently in use in this packet. */
Uint32 startpos; /* bytes currently consumed in this packet. */
struct SDL_AudioBufferQueue *next; /* next item in linked list. */
} SDL_AudioBufferQueue;
typedef struct SDL_AudioDriverImpl
{
void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
@@ -40,6 +60,7 @@ typedef struct SDL_AudioDriverImpl
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
void (*WaitDevice) (_THIS);
void (*PlayDevice) (_THIS);
int (*GetPendingBytes) (_THIS);
Uint8 *(*GetDeviceBuf) (_THIS);
void (*WaitDone) (_THIS);
void (*CloseDevice) (_THIS);
@@ -119,6 +140,12 @@ struct SDL_AudioDevice
SDL_Thread *thread;
SDL_threadID threadid;
/* Queued buffers (if app not using callback). */
SDL_AudioBufferQueue *buffer_queue_head; /* device fed from here. */
SDL_AudioBufferQueue *buffer_queue_tail; /* queue fills to here. */
SDL_AudioBufferQueue *buffer_queue_pool; /* these are unused packets. */
Uint32 queued_bytes; /* number of bytes of audio data in the queue. */
/* * * */
/* Data private to this driver */
struct SDL_PrivateAudioData *hidden;

View File

@@ -58,7 +58,7 @@
/* The configure script already did any necessary checking */
# define SDL_XAUDIO2_HAS_SDK 1
#elif defined(__WINRT__)
/* WinRT always has access to the .the XAudio 2 SDK */
/* WinRT always has access to the the XAudio 2 SDK */
# define SDL_XAUDIO2_HAS_SDK
#else
/* XAudio2 exists as of the March 2008 DirectX SDK
@@ -241,14 +241,14 @@ XAUDIO2_WaitDone(_THIS)
SDL_assert(!this->enabled); /* flag that stops playing. */
IXAudio2SourceVoice_Discontinuity(source);
#if SDL_XAUDIO2_WIN8
IXAudio2SourceVoice_GetState(source, &state, 0);
IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
#else
IXAudio2SourceVoice_GetState(source, &state);
#endif
while (state.BuffersQueued > 0) {
SDL_SemWait(this->hidden->semaphore);
#if SDL_XAUDIO2_WIN8
IXAudio2SourceVoice_GetState(source, &state, 0);
IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
#else
IXAudio2SourceVoice_GetState(source, &state);
#endif

View File

@@ -331,10 +331,10 @@ IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
}
if(result){
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCapabilities");
msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCapabilities");
if(msg){
Uint32 caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
dbus->message_append_args(msg,

View File

@@ -588,3 +588,6 @@
#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
#define SDL_GetGlobalMouseState SDL_GetGlobalMouseState_REAL
#define SDL_HasAVX2 SDL_HasAVX2_REAL
#define SDL_QueueAudio SDL_QueueAudio_REAL
#define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL
#define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL

View File

@@ -620,3 +620,6 @@ SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetGlobalMouseState,(int *a, int *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),)

View File

@@ -10,9 +10,6 @@
/* Include this so we define UNICODE properly */
#include "../../core/windows/SDL_windows.h"
#include <stdio.h>
#include <stdlib.h>
/* Include the SDL main definition header */
#include "SDL.h"
#include "SDL_main.h"
@@ -103,23 +100,11 @@ ParseCommandLine(char *cmdline, char **argv)
return (argc);
}
/* Show an error message */
static void
ShowError(const char *title, const char *message)
{
/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
#ifdef USE_MESSAGEBOX
MessageBox(NULL, message, title, MB_ICONEXCLAMATION | MB_OK);
#else
fprintf(stderr, "%s: %s\n", title, message);
#endif
}
/* Pop up an out of memory message, returns to Windows */
static BOOL
OutOfMemory(void)
{
ShowError("Fatal Error", "Out of memory - aborting");
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
return FALSE;
}
@@ -132,18 +117,10 @@ OutOfMemory(void)
int
console_main(int argc, char *argv[])
{
int status;
SDL_SetMainReady();
/* Run the application main() code */
status = SDL_main(argc, argv);
/* Exit cleanly, calling atexit() functions */
exit(status);
/* Hush little compiler, don't you cry... */
return 0;
return SDL_main(argc, argv);
}
/* This is where execution begins [windowed apps] */

View File

@@ -688,6 +688,9 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
GL_CheckError("", renderer);
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
if (data->pixels) {
SDL_free(data->pixels);
}
SDL_free(data);
return -1;
}

View File

@@ -51,7 +51,7 @@ do { \
#define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
do { \
unsigned sr, sg, sb, sa; \
unsigned sr, sg, sb, sa = 0xFF; \
getpixel; \
sr = DRAW_MUL(inva, sr) + r; \
sg = DRAW_MUL(inva, sg) + g; \

View File

@@ -370,44 +370,35 @@ _ftol2_sse()
_ftol();
}
/* 64-bit math operators for 32-bit systems */
void
__declspec(naked)
_allmul()
{
/* *INDENT-OFF* */
__asm {
push ebp
mov ebp,esp
push edi
push esi
push ebx
sub esp,0Ch
mov eax,dword ptr [ebp+10h]
mov edi,dword ptr [ebp+8]
mov ebx,eax
mov esi,eax
sar esi,1Fh
mov eax,dword ptr [ebp+8]
mul ebx
imul edi,esi
mov ecx,edx
mov dword ptr [ebp-18h],eax
mov edx,dword ptr [ebp+0Ch]
add ecx,edi
imul ebx,edx
mov eax,dword ptr [ebp-18h]
lea ebx,[ebx+ecx]
mov dword ptr [ebp-14h],ebx
mov edx,dword ptr [ebp-14h]
add esp,0Ch
pop ebx
pop esi
pop edi
pop ebp
ret 10h
}
/* *INDENT-ON* */
/* 64-bit math operators for 32-bit systems */
void
__declspec(naked)
_allmul()
{
/* *INDENT-OFF* */
__asm {
mov eax, dword ptr[esp+8]
mov ecx, dword ptr[esp+10h]
or ecx, eax
mov ecx, dword ptr[esp+0Ch]
jne hard
mov eax, dword ptr[esp+4]
mul ecx
ret 10h
hard:
push ebx
mul ecx
mov ebx, eax
mov eax, dword ptr[esp+8]
mul dword ptr[esp+14h]
add ebx, eax
mov eax, dword ptr[esp+8]
mul ecx
add edx, ebx
pop ebx
ret 10h
}
/* *INDENT-ON* */
}
void

View File

@@ -93,6 +93,7 @@ struct SDL_Window
SDL_Surface *surface;
SDL_bool surface_valid;
SDL_bool is_hiding;
SDL_bool is_destroying;
SDL_WindowShaper *shaper;

View File

@@ -1105,6 +1105,10 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
CHECK_WINDOW_MAGIC(window,);
/* if we are in the process of hiding don't go back to fullscreen */
if ( window->is_hiding && fullscreen )
return;
#ifdef __MACOSX__
if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
window->last_fullscreen_flags = window->flags;
@@ -1833,11 +1837,13 @@ SDL_HideWindow(SDL_Window * window)
return;
}
window->is_hiding = SDL_TRUE;
SDL_UpdateFullscreenMode(window, SDL_FALSE);
if (_this->HideWindow) {
_this->HideWindow(_this, window);
}
window->is_hiding = SDL_FALSE;
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
}