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