src/thread/windows/SDL_systhread.c
author Sam Lantinga
Fri, 27 Jan 2017 21:23:27 -0800
changeset 10861 71d8f9afb690
parent 10857 d2843a5e3d3a
child 10886 b2d018b8d9ba
permissions -rw-r--r--
Fixed bug 3569 - GL_UpdateViewport leaves PROJECTION matrix selected

Tom Seddon

GL_ActivateRenderer may call GL_UpdateViewport, which leaves the GL_PROJECTION matrix selected. But after GL_ResetState, the GL_MODELVIEW matrix is selected, suggesting that's the intended default state.

It seems at least like these should be consistent. Presumably GL_UpdateViewport should be doing a glMatrixMode(GL_MODELVIEW) before it finishes.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@0
    22
slouken@6044
    23
#if SDL_THREAD_WINDOWS
slouken@6044
    24
slouken@0
    25
/* Win32 thread management routines for SDL */
slouken@0
    26
flibitijibibo@10498
    27
#include "SDL_hints.h"
slouken@0
    28
#include "SDL_thread.h"
slouken@1361
    29
#include "../SDL_thread_c.h"
slouken@1361
    30
#include "../SDL_systhread.h"
slouken@5086
    31
#include "SDL_systhread_c.h"
slouken@0
    32
slouken@1471
    33
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@1471
    34
/* We'll use the C library from this DLL */
slouken@1471
    35
#include <process.h>
slouken@1471
    36
slouken@10392
    37
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
slouken@10392
    38
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
slouken@10392
    39
#endif
slouken@10392
    40
icculus@5904
    41
/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
icculus@5904
    42
#if (defined(__MINGW32__) && (__GNUC__ < 4))
icculus@5904
    43
typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@7191
    44
        unsigned (__stdcall *func)(void *), void *arg,
icculus@5904
    45
        unsigned, unsigned *threadID);
icculus@5904
    46
typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
icculus@5904
    47
slouken@1769
    48
#elif defined(__WATCOMC__)
slouken@1769
    49
/* This is for Watcom targets except OS2 */
slouken@1769
    50
#if __WATCOMC__ < 1240
slouken@1769
    51
#define __watcall
slouken@1769
    52
#endif
slouken@1895
    53
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
slouken@1895
    54
                                                               unsigned,
slouken@1895
    55
                                                               unsigned
slouken@1895
    56
                                                               (__stdcall *
slouken@1895
    57
                                                                func) (void
slouken@1895
    58
                                                                       *),
slouken@1895
    59
                                                               void *arg,
slouken@1895
    60
                                                               unsigned,
slouken@1895
    61
                                                               unsigned
slouken@1895
    62
                                                               *threadID);
slouken@1895
    63
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
icculus@5904
    64
slouken@1471
    65
#else
slouken@1895
    66
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@1895
    67
                                                        unsigned (__stdcall *
slouken@1895
    68
                                                                  func) (void
slouken@1895
    69
                                                                         *),
slouken@1895
    70
                                                        void *arg, unsigned,
slouken@1895
    71
                                                        unsigned *threadID);
slouken@1895
    72
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
slouken@1471
    73
#endif
slouken@1471
    74
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1471
    75
slouken@1471
    76
slouken@1330
    77
typedef struct ThreadStartParms
slouken@1330
    78
{
slouken@1895
    79
    void *args;
slouken@1895
    80
    pfnSDL_CurrentEndThread pfnCurrentEndThread;
slouken@1330
    81
} tThreadStartParms, *pThreadStartParms;
slouken@0
    82
icculus@5904
    83
static DWORD
slouken@1895
    84
RunThread(void *data)
slouken@0
    85
{
slouken@1895
    86
    pThreadStartParms pThreadParms = (pThreadStartParms) data;
icculus@5962
    87
    pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
icculus@5962
    88
    void *args = pThreadParms->args;
icculus@5962
    89
    SDL_free(pThreadParms);
icculus@5962
    90
    SDL_RunThread(args);
icculus@5962
    91
    if (pfnEndThread != NULL)
icculus@5962
    92
        pfnEndThread(0);
slouken@1895
    93
    return (0);
slouken@0
    94
}
slouken@0
    95
icculus@5904
    96
static DWORD WINAPI
icculus@5904
    97
RunThreadViaCreateThread(LPVOID data)
icculus@5904
    98
{
icculus@5904
    99
  return RunThread(data);
icculus@5904
   100
}
icculus@5904
   101
icculus@5904
   102
static unsigned __stdcall
icculus@5904
   103
RunThreadViaBeginThreadEx(void *data)
icculus@5904
   104
{
icculus@5904
   105
  return (unsigned) RunThread(data);
icculus@5904
   106
}
icculus@5904
   107
slouken@1471
   108
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@1895
   109
int
slouken@1895
   110
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
slouken@1895
   111
                     pfnSDL_CurrentBeginThread pfnBeginThread,
slouken@1895
   112
                     pfnSDL_CurrentEndThread pfnEndThread)
slouken@0
   113
{
dludwig@9930
   114
#elif defined(__CYGWIN__) || defined(__WINRT__)
slouken@7498
   115
int
slouken@7498
   116
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@7498
   117
{
slouken@7498
   118
    pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
slouken@7498
   119
    pfnSDL_CurrentEndThread pfnEndThread = NULL;
slouken@1471
   120
#else
slouken@1895
   121
int
slouken@1895
   122
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@1471
   123
{
slouken@7828
   124
    pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
slouken@7828
   125
    pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
slouken@1471
   126
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1895
   127
    pThreadStartParms pThreadParms =
slouken@1895
   128
        (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
icculus@10148
   129
    const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
slouken@1895
   130
    if (!pThreadParms) {
icculus@7037
   131
        return SDL_OutOfMemory();
slouken@1895
   132
    }
slouken@7191
   133
    /* Save the function which we will have to call to clear the RTL of calling app! */
slouken@1895
   134
    pThreadParms->pfnCurrentEndThread = pfnEndThread;
slouken@7191
   135
    /* Also save the real parameters we have to pass to thread function */
slouken@1895
   136
    pThreadParms->args = args;
slouken@1330
   137
icculus@10145
   138
    /* thread->stacksize == 0 means "system default", same as win32 expects */
slouken@1895
   139
    if (pfnBeginThread) {
icculus@5904
   140
        unsigned threadid = 0;
icculus@5904
   141
        thread->handle = (SYS_ThreadHandle)
icculus@10145
   142
            ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize,
icculus@10145
   143
                                     RunThreadViaBeginThreadEx,
icculus@10148
   144
                                     pThreadParms, flags, &threadid));
slouken@1895
   145
    } else {
icculus@5904
   146
        DWORD threadid = 0;
icculus@10145
   147
        thread->handle = CreateThread(NULL, thread->stacksize,
icculus@10145
   148
                                      RunThreadViaCreateThread,
icculus@10148
   149
                                      pThreadParms, flags, &threadid);
slouken@1895
   150
    }
slouken@1895
   151
    if (thread->handle == NULL) {
icculus@7037
   152
        return SDL_SetError("Not enough resources to create thread");
slouken@1895
   153
    }
icculus@7037
   154
    return 0;
slouken@0
   155
}
slouken@0
   156
icculus@5969
   157
#pragma pack(push,8)
icculus@5969
   158
typedef struct tagTHREADNAME_INFO
icculus@5969
   159
{
icculus@5969
   160
    DWORD dwType; /* must be 0x1000 */
icculus@5969
   161
    LPCSTR szName; /* pointer to name (in user addr space) */
icculus@5969
   162
    DWORD dwThreadID; /* thread ID (-1=caller thread) */
icculus@5969
   163
    DWORD dwFlags; /* reserved for future use, must be zero */
icculus@5969
   164
} THREADNAME_INFO;
icculus@5969
   165
#pragma pack(pop)
icculus@7724
   166
icculus@10857
   167
icculus@10857
   168
typedef HRESULT (WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
icculus@10857
   169
slouken@1895
   170
void
icculus@5969
   171
SDL_SYS_SetupThread(const char *name)
slouken@0
   172
{
icculus@10857
   173
    if (name != NULL) {
icculus@10857
   174
        static HMODULE kernel32 = 0;
icculus@10857
   175
        static pfnSetThreadDescription pSetThreadDescription = NULL;
flibitijibibo@10498
   176
icculus@10857
   177
        if (!kernel32) {
icculus@10857
   178
            kernel32 = LoadLibrary(L"kernel32.dll");
icculus@10857
   179
            if (kernel32) {
icculus@10857
   180
                pSetThreadDescription = (pfnSetThreadDescription) GetProcAddress(kernel32, "SetThreadDescription");
icculus@10857
   181
            }
icculus@10857
   182
        }
icculus@10857
   183
icculus@10857
   184
        if (pSetThreadDescription != NULL) {
icculus@10857
   185
            WCHAR *strw = WIN_UTF8ToString(name);
icculus@10857
   186
            if (strw) {
icculus@10857
   187
                pSetThreadDescription(GetCurrentThread(), strw);
icculus@10857
   188
                SDL_free(strw);
icculus@10857
   189
            }
flibitijibibo@10498
   190
        }
flibitijibibo@10498
   191
icculus@10857
   192
        /* Presumably some version of Visual Studio will understand SetThreadDescription(),
icculus@10857
   193
           but we still need to deal with older OSes and debuggers. Set it with the arcane
icculus@10857
   194
           exception magic, too. */
icculus@10857
   195
icculus@10857
   196
        if (IsDebuggerPresent()) {
icculus@10857
   197
            THREADNAME_INFO inf;
icculus@5969
   198
icculus@10857
   199
            /* C# and friends will try to catch this Exception, let's avoid it. */
icculus@10857
   200
            if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) {
icculus@10857
   201
                return;
icculus@10857
   202
            }
icculus@10857
   203
icculus@10857
   204
            /* This magic tells the debugger to name a thread if it's listening. */
icculus@10857
   205
            SDL_zero(inf);
icculus@10857
   206
            inf.dwType = 0x1000;
icculus@10857
   207
            inf.szName = name;
icculus@10857
   208
            inf.dwThreadID = (DWORD) -1;
icculus@10857
   209
            inf.dwFlags = 0;
icculus@10857
   210
icculus@10857
   211
            /* The debugger catches this, renames the thread, continues on. */
icculus@10857
   212
            RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
icculus@10857
   213
        }
icculus@5969
   214
    }
slouken@0
   215
}
slouken@0
   216
slouken@3578
   217
SDL_threadID
slouken@1895
   218
SDL_ThreadID(void)
slouken@0
   219
{
slouken@3578
   220
    return ((SDL_threadID) GetCurrentThreadId());
slouken@0
   221
}
slouken@0
   222
slouken@5506
   223
int
slouken@5509
   224
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
slouken@5506
   225
{
slouken@5509
   226
    int value;
slouken@5506
   227
slouken@5506
   228
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5509
   229
        value = THREAD_PRIORITY_LOWEST;
slouken@5506
   230
    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@5509
   231
        value = THREAD_PRIORITY_HIGHEST;
slouken@5506
   232
    } else {
slouken@5509
   233
        value = THREAD_PRIORITY_NORMAL;
slouken@5506
   234
    }
slouken@5509
   235
    if (!SetThreadPriority(GetCurrentThread(), value)) {
icculus@7037
   236
        return WIN_SetError("SetThreadPriority()");
slouken@5506
   237
    }
slouken@5506
   238
    return 0;
slouken@5506
   239
}
slouken@5506
   240
slouken@1895
   241
void
slouken@1895
   242
SDL_SYS_WaitThread(SDL_Thread * thread)
slouken@0
   243
{
dludwig@9930
   244
    WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
slouken@1895
   245
    CloseHandle(thread->handle);
slouken@0
   246
}
slouken@0
   247
icculus@7978
   248
void
icculus@7978
   249
SDL_SYS_DetachThread(SDL_Thread * thread)
icculus@7978
   250
{
icculus@7978
   251
    CloseHandle(thread->handle);
icculus@7978
   252
}
icculus@7978
   253
slouken@6044
   254
#endif /* SDL_THREAD_WINDOWS */
slouken@6044
   255
slouken@1895
   256
/* vi: set ts=4 sw=4 expandtab: */