Module: wine Branch: master Commit: 676194383c0e37644e98586ca0a1a201d3dd2e6a URL: http://source.winehq.org/git/wine.git/?a=commit;h=676194383c0e37644e98586ca0...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Jun 29 15:15:57 2012 +0200
opengl32: Don't allow making a thread current in multiple threads.
---
dlls/opengl32/tests/opengl.c | 27 ++++++++++++++++++--------- dlls/opengl32/wgl.c | 36 ++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 03e8ed2..77b4cf5 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -694,24 +694,30 @@ static void test_bitmap_rendering( BOOL use_dib ) struct wgl_thread_param { HANDLE test_finished; + HWND hwnd; HGLRC hglrc; - BOOL hglrc_deleted; - DWORD last_error; + BOOL make_current; + BOOL make_current_error; + BOOL deleted; + DWORD deleted_error; };
static DWORD WINAPI wgl_thread(void *param) { struct wgl_thread_param *p = param; + HDC hdc = GetDC( p->hwnd );
SetLastError(0xdeadbeef); - p->hglrc_deleted = wglDeleteContext(p->hglrc); - p->last_error = GetLastError(); + p->make_current = wglMakeCurrent(hdc, p->hglrc); + p->make_current_error = GetLastError(); + p->deleted = wglDeleteContext(p->hglrc); + p->deleted_error = GetLastError(); + ReleaseDC( p->hwnd, hdc ); SetEvent(p->test_finished); - return 0; }
-static void test_deletecontext(HDC hdc) +static void test_deletecontext(HWND hwnd, HDC hdc) { struct wgl_thread_param thread_params; HGLRC hglrc = wglCreateContext(hdc); @@ -740,14 +746,17 @@ static void test_deletecontext(HDC hdc) * This differs from GLX which does allow it but it delays actual deletion until the context becomes not current. */ thread_params.hglrc = hglrc; + thread_params.hwnd = hwnd; thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL); thread_handle = CreateThread(NULL, 0, wgl_thread, &thread_params, 0, &tid); ok(!!thread_handle, "Failed to create thread, last error %#x.\n", GetLastError()); if(thread_handle) { WaitForSingleObject(thread_handle, INFINITE); - ok(thread_params.hglrc_deleted == FALSE, "Attempt to delete WGL context from another thread passed but should fail!\n"); - ok(thread_params.last_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.last_error); + ok(!thread_params.make_current, "Attempt to make WGL context from another thread passed\n"); + ok(thread_params.make_current_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.make_current_error); + ok(!thread_params.deleted, "Attempt to delete WGL context from another thread passed\n"); + ok(thread_params.deleted_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.deleted_error); } CloseHandle(thread_params.test_finished);
@@ -1469,6 +1478,7 @@ START_TEST(opengl) * any WGL call :( On Wine this would work but not on real Windows because there can be different implementations (software, ICD, MCD). */ init_functions(); + test_deletecontext(hwnd, hdc); /* The lack of wglGetExtensionsStringARB in general means broken software rendering or the lack of decent OpenGL support, skip tests in such cases */ if (!pwglGetExtensionsStringARB) { @@ -1477,7 +1487,6 @@ START_TEST(opengl) }
test_getprocaddress(hdc); - test_deletecontext(hdc); test_makecurrent(hdc); test_setpixelformat(hdc); test_destroy(hdc); diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 6906b56..d0d9d83 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -223,12 +223,20 @@ BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc) if (hglrc) { if (!(ptr = get_handle_ptr( hglrc ))) return FALSE; - ret = wgl_driver->p_wglMakeCurrent( hdc, ptr->context ); - if (ret) + if (!ptr->tid || ptr->tid == GetCurrentThreadId()) { - if (prev) prev->tid = 0; - ptr->tid = GetCurrentThreadId(); - NtCurrentTeb()->glCurrentRC = hglrc; + ret = wgl_driver->p_wglMakeCurrent( hdc, ptr->context ); + if (ret) + { + if (prev) prev->tid = 0; + ptr->tid = GetCurrentThreadId(); + NtCurrentTeb()->glCurrentRC = hglrc; + } + } + else + { + SetLastError( ERROR_BUSY ); + ret = FALSE; } release_handle_ptr( ptr ); } @@ -278,12 +286,20 @@ static BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC h if (hglrc) { if (!(ptr = get_handle_ptr( hglrc ))) return FALSE; - ret = wgl_driver->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->context ); - if (ret) + if (!ptr->tid || ptr->tid == GetCurrentThreadId()) + { + ret = wgl_driver->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->context ); + if (ret) + { + if (prev) prev->tid = 0; + ptr->tid = GetCurrentThreadId(); + NtCurrentTeb()->glCurrentRC = hglrc; + } + } + else { - if (prev) prev->tid = 0; - ptr->tid = GetCurrentThreadId(); - NtCurrentTeb()->glCurrentRC = hglrc; + SetLastError( ERROR_BUSY ); + ret = FALSE; } release_handle_ptr( ptr ); }