From: Jacek Caban jacek@codeweavers.com
--- dlls/opengl32/make_opengl | 1 + dlls/opengl32/tests/opengl.c | 50 ++++++++++++++++++++++++++++++++++++ dlls/opengl32/unix_thunks.c | 3 +-- dlls/opengl32/unix_thunks.h | 1 + dlls/opengl32/unix_wgl.c | 43 ++++++++++++++++++++++++++----- 5 files changed, 90 insertions(+), 8 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index cf38747eae5..25862cd7ee9 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -283,6 +283,7 @@ my %manual_wow64_wrappers = "glFenceSync" => 0, "glGetBufferPointerv" => 0, "glGetBufferPointervARB" => 0, + "glGetError" => 0, "glGetNamedBufferPointerv" => 0, "glGetNamedBufferPointervEXT" => 0, "glGetSynciv" => 0, diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 55125722297..656872ec800 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -107,9 +107,11 @@ static PFN_glCopyBufferSubData pglCopyBufferSubData; static PFN_glCopyNamedBufferSubData pglCopyNamedBufferSubData; static PFN_glCreateBuffers pglCreateBuffers; static PFN_glDeleteBuffers pglDeleteBuffers; +static PFN_glDeleteSync pglDeleteSync; static PFN_glFlushMappedBufferRange pglFlushMappedBufferRange; static PFN_glFlushMappedNamedBufferRange pglFlushMappedNamedBufferRange; static PFN_glGenBuffers pglGenBuffers; +static PFN_glIsSync pglIsSync; static PFN_glMapBuffer pglMapBuffer; static PFN_glMapBufferRange pglMapBufferRange; static PFN_glMapNamedBuffer pglMapNamedBuffer; @@ -191,9 +193,11 @@ static void init_functions(void) GET_PROC(glCopyNamedBufferSubData) GET_PROC(glCreateBuffers) GET_PROC(glDeleteBuffers) + GET_PROC(glDeleteSync) GET_PROC(glFlushMappedBufferRange) GET_PROC(glFlushMappedNamedBufferRange) GET_PROC(glGenBuffers) + GET_PROC(glIsSync) GET_PROC(glMapBuffer) GET_PROC(glMapBufferRange) GET_PROC(glMapNamedBuffer) @@ -3491,6 +3495,50 @@ static void check_gl_error_( unsigned int line, GLenum exp ) ok_(__FILE__,line)( err == exp, "glGetError returned %x, expected %x\n", err, exp ); }
+static void test_gl_error( HDC hdc ) +{ + HGLRC rc, old_rc; + int i; + BOOL ret; + + if (!pglDeleteSync) + { + skip( "glDeleteSync not available\n" ); + return; + } + + old_rc = wglGetCurrentContext(); + rc = wglCreateContext( hdc ); + ok( !!rc, "got %p\n", rc ); + ret = wglMakeCurrent( hdc, rc ); + ok( ret, "got %u\n", ret ); + + check_gl_error( GL_NO_ERROR ); + glGetIntegerv( 0xdeadbeef, &i ); + check_gl_error( GL_INVALID_ENUM ); + check_gl_error( GL_NO_ERROR ); + + pglDeleteSync( (GLsync)0xdeadbeef ); + check_gl_error( GL_INVALID_VALUE ); + check_gl_error( GL_NO_ERROR ); + + glGetIntegerv( 0xdeadbeef, &i ); + pglDeleteSync( (GLsync)0xdeadbeef ); + check_gl_error( GL_INVALID_ENUM ); + check_gl_error( GL_NO_ERROR ); + + pglDeleteSync( (GLsync)0xdeadbeef ); + glGetIntegerv( 0xdeadbeef, &i ); + check_gl_error( GL_INVALID_VALUE ); + check_gl_error( GL_NO_ERROR ); + + ret = pglIsSync( (GLsync)0xdeadbeef ); + ok( !ret, "glIsSync returned %x\n", ret ); + check_gl_error( GL_NO_ERROR ); + + wglMakeCurrent( hdc, old_rc ); +} + static void test_memory_map( HDC hdc) { unsigned int i, major = 0, minor = 0; @@ -3745,6 +3793,7 @@ START_TEST(opengl) pD3DKMTCreateDCFromMemory = (void *)GetProcAddress( gdi32, "D3DKMTCreateDCFromMemory" ); pD3DKMTDestroyDCFromMemory = (void *)GetProcAddress( gdi32, "D3DKMTDestroyDCFromMemory" );
+ check_gl_error( GL_INVALID_OPERATION ); ShowWindow(hwnd, SW_SHOW);
hdc = GetDC(hwnd); @@ -3824,6 +3873,7 @@ START_TEST(opengl) test_acceleration(hdc); test_framebuffer(); test_memory_map(hdc); + test_gl_error(hdc);
wgl_extensions = pwglGetExtensionsStringARB(hdc); if(wgl_extensions == NULL) skip("Skipping opengl32 tests because this OpenGL implementation doesn't support WGL extensions!\n"); diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 727df735759..7ecf7514afa 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -31659,8 +31659,7 @@ static NTSTATUS wow64_gl_glGetError( void *args ) GLenum ret; } *params = args; TEB *teb = get_teb64( params->teb ); - const struct opengl_funcs *funcs = teb->glTable; - params->ret = funcs->p_glGetError(); + params->ret = wow64_glGetError( teb ); return STATUS_SUCCESS; }
diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index f3084ed237d..83a53da6e87 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -47,6 +47,7 @@ extern BOOL wrap_wglReleaseTexImageARB( TEB *teb, HPBUFFERARB hPbuffer, int iBuf extern BOOL wrap_wglSetPbufferAttribARB( TEB *teb, HPBUFFERARB hPbuffer, const int *piAttribList );
#ifdef _WIN64 +extern GLenum wow64_glGetError( TEB *teb ); extern GLenum wow64_glClientWaitSync( TEB *teb, GLsync sync, GLbitfield flags, GLuint64 timeout ); extern void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers ); extern void wow64_glDeleteSync( TEB *teb, GLsync sync ); diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index bd37d661ce6..a68773f3604 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -139,6 +139,7 @@ struct context GLuint *disabled_exts; /* indices of disabled extensions */ GLubyte *wow64_version; /* wow64 GL version override */ struct buffers *buffers; /* wow64 buffers map */ + GLenum gl_error; /* wrapped GL error */
/* semi-stub state tracker for wglCopyContext */ GLbitfield used; /* context state used bits */ @@ -2023,12 +2024,41 @@ NTSTATUS return_wow64_string( const void *str, PTR32 *wow64_str ) return STATUS_BUFFER_TOO_SMALL; }
+GLenum wow64_glGetError( TEB *teb ) +{ + const struct opengl_funcs *funcs = teb->glTable; + GLenum gl_err, prev_err; + struct context *ctx; + + if (!(ctx = get_current_context( teb, NULL, NULL ))) return GL_INVALID_OPERATION; + gl_err = funcs->p_glGetError(); + prev_err = ctx->gl_error; + ctx->gl_error = GL_NO_ERROR; + return prev_err ? prev_err : gl_err; +} + +static void set_gl_error( TEB *teb, GLenum gl_error ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct context *ctx; + + if (!(ctx = get_current_context( teb, NULL, NULL )) || ctx->gl_error) return; + if (!(ctx->gl_error = funcs->p_glGetError())) ctx->gl_error = gl_error; +} + +static struct wgl_handle *get_sync_ptr( TEB *teb, GLsync sync ) +{ + struct wgl_handle *handle = get_handle_ptr( sync ); + if (!handle) set_gl_error( teb, GL_INVALID_VALUE ); + return handle; +} + GLenum wow64_glClientWaitSync( TEB *teb, GLsync sync, GLbitfield flags, GLuint64 timeout ) { const struct opengl_funcs *funcs = teb->glTable; struct wgl_handle *handle;
- if (!(handle = get_handle_ptr( sync ))) return GL_INVALID_VALUE; + if (!(handle = get_sync_ptr( teb, sync ))) return GL_INVALID_VALUE; return funcs->p_glClientWaitSync( handle->u.sync, flags, timeout ); }
@@ -2037,7 +2067,7 @@ void wow64_glDeleteSync( TEB *teb, GLsync sync ) const struct opengl_funcs *funcs = teb->glTable; struct wgl_handle *handle;
- if ((handle = get_handle_ptr( sync ))) + if ((handle = get_sync_ptr( teb, sync ))) { funcs->p_glDeleteSync( handle->u.sync ); free_handle_ptr( handle ); @@ -2062,7 +2092,7 @@ void wow64_glGetSynciv( TEB *teb, GLsync sync, GLenum pname, GLsizei count, GLsi const struct opengl_funcs *funcs = teb->glTable; struct wgl_handle *handle;
- if ((handle = get_handle_ptr( sync ))) funcs->p_glGetSynciv( handle->u.sync, pname, count, length, values ); + if ((handle = get_sync_ptr( teb, sync ))) funcs->p_glGetSynciv( handle->u.sync, pname, count, length, values ); }
GLboolean wow64_glIsSync( TEB *teb, GLsync sync ) @@ -2079,7 +2109,7 @@ void wow64_glWaitSync( TEB *teb, GLsync sync, GLbitfield flags, GLuint64 timeout const struct opengl_funcs *funcs = teb->glTable; struct wgl_handle *handle;
- if ((handle = get_handle_ptr( sync ))) funcs->p_glWaitSync( handle->u.sync, flags, timeout ); + if ((handle = get_sync_ptr( teb, sync ))) funcs->p_glWaitSync( handle->u.sync, flags, timeout ); }
static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param ) @@ -2181,7 +2211,7 @@ static struct buffer *get_target_buffer( TEB *teb, GLenum target ) return name ? get_named_buffer( teb, name ) : NULL; }
-static BOOL buffer_vm_alloc( struct buffer *buffer, SIZE_T size ) +static BOOL buffer_vm_alloc( TEB *teb, struct buffer *buffer, SIZE_T size ) { if (buffer->vm_size >= size) return TRUE; if (buffer->vm_ptr) @@ -2194,6 +2224,7 @@ static BOOL buffer_vm_alloc( struct buffer *buffer, SIZE_T size ) MEM_COMMIT, PAGE_READWRITE )) { ERR("NtAllocateVirtualMemory failed\n"); + set_gl_error( teb, GL_OUT_OF_MEMORY ); return FALSE; } buffer->vm_size = size; @@ -2233,7 +2264,7 @@ static PTR32 wow64_map_buffer( TEB *teb, GLenum target, GLuint name, GLintptr of goto unmap; }
- if (!buffer_vm_alloc( buffer, length + (offset & 0xf) )) return 0; + if (!buffer_vm_alloc( teb, buffer, length + (offset & 0xf) )) goto unmap; buffer->map_ptr = (char *)buffer->vm_ptr + (offset & 0xf); buffer->copy_length = (access & GL_MAP_WRITE_BIT) ? length : 0; if (!(access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)))