diff options
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/fakeglx.c | 2 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_context.c | 82 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_device.c | 42 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_framebuffer.c | 140 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_framebuffer.h | 13 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_tls.c | 33 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_tls.h | 6 |
7 files changed, 179 insertions, 139 deletions
diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.c b/src/gallium/state_trackers/glx/xlib/fakeglx.c index 85e7ecfb9e8..23777c76f6c 100644 --- a/src/gallium/state_trackers/glx/xlib/fakeglx.c +++ b/src/gallium/state_trackers/glx/xlib/fakeglx.c @@ -1820,7 +1820,7 @@ Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, if (!dpy || !config || !pixmap) return 0; - for (attr = attribList; *attr; attr++) { + for (attr = attribList; attr && *attr; attr++) { switch (*attr) { case GLX_TEXTURE_FORMAT_EXT: attr++; diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c index 662b5fbcd2a..9df1ab76526 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_context.c +++ b/src/gallium/state_trackers/wgl/shared/stw_context.c @@ -47,6 +47,23 @@ #include "stw_context.h" #include "stw_tls.h" + +static INLINE struct stw_context * +stw_context(GLcontext *glctx) +{ + if(!glctx) + return NULL; + assert(glctx->DriverCtx); + return (struct stw_context *)glctx->DriverCtx; +} + +static INLINE struct stw_context * +stw_current_context(void) +{ + GET_CURRENT_CONTEXT( glctx ); + return stw_context(glctx); +} + BOOL stw_copy_context( UINT_PTR hglrcSrc, @@ -99,6 +116,18 @@ stw_share_lists( return ret; } +static void +stw_viewport(GLcontext * glctx, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx; + struct stw_framebuffer *fb; + + fb = stw_framebuffer_from_hdc( ctx->hdc ); + if(fb) + stw_framebuffer_update(fb); +} + UINT_PTR stw_create_layer_context( HDC hdc, @@ -158,6 +187,7 @@ stw_create_layer_context( goto no_st_ctx; ctx->st->ctx->DriverCtx = ctx; + ctx->st->ctx->Driver.Viewport = stw_viewport; pipe_mutex_lock( stw_dev->mutex ); ctx->hglrc = handle_table_add(stw_dev->ctx_table, ctx); @@ -194,11 +224,10 @@ stw_delete_context( pipe_mutex_unlock( stw_dev->mutex ); if (ctx) { - GLcontext *glctx = ctx->st->ctx; - GET_CURRENT_CONTEXT( glcurctx ); - + struct stw_context *curctx = stw_current_context(); + /* Unbind current if deleting current context. */ - if (glcurctx == glctx) + if (curctx == ctx) st_make_current( NULL, NULL, NULL ); st_destroy_context(ctx->st); @@ -230,13 +259,8 @@ stw_release_context( * current for this thread. We should check that and return False * if not the case. */ - { - GLcontext *glctx = ctx->st->ctx; - GET_CURRENT_CONTEXT( glcurctx ); - - if (glcurctx != glctx) - return FALSE; - } + if (ctx != stw_current_context()) + return FALSE; if (stw_make_current( NULL, 0 ) == FALSE) return FALSE; @@ -248,14 +272,9 @@ stw_release_context( UINT_PTR stw_get_current_context( void ) { - GET_CURRENT_CONTEXT( glcurctx ); struct stw_context *ctx; - if(!glcurctx) - return 0; - - ctx = (struct stw_context *)glcurctx->DriverCtx; - assert(ctx); + ctx = stw_current_context(); if(!ctx) return 0; @@ -265,14 +284,9 @@ stw_get_current_context( void ) HDC stw_get_current_dc( void ) { - GET_CURRENT_CONTEXT( glcurctx ); struct stw_context *ctx; - if(!glcurctx) - return NULL; - - ctx = (struct stw_context *)glcurctx->DriverCtx; - assert(ctx); + ctx = stw_current_context(); if(!ctx) return NULL; @@ -284,23 +298,24 @@ stw_make_current( HDC hdc, UINT_PTR hglrc ) { + struct stw_context *curctx; struct stw_context *ctx; - GET_CURRENT_CONTEXT( glcurctx ); struct stw_framebuffer *fb; if (!stw_dev) goto fail; - if (glcurctx != NULL) { - struct stw_context *curctx; - curctx = (struct stw_context *) glcurctx->DriverCtx; - + curctx = stw_current_context(); + if (curctx != NULL) { if (curctx->hglrc != hglrc) - st_flush(glcurctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); /* Return if already current. */ - if (curctx->hglrc == hglrc && curctx->hdc == hdc) - return TRUE; + if (curctx->hglrc == hglrc && curctx->hdc == hdc) { + ctx = curctx; + fb = stw_framebuffer_from_hdc( hdc ); + goto success; + } } if (hdc == NULL || hglrc == 0) { @@ -344,7 +359,10 @@ stw_make_current( if(!st_make_current( ctx->st, fb->stfb, fb->stfb )) goto fail; - stw_framebuffer_resize(fb); +success: + assert(fb); + if(fb) + stw_framebuffer_update(fb); return TRUE; diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/shared/stw_device.c index 1a6b29807d7..ce466241463 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_device.c +++ b/src/gallium/state_trackers/wgl/shared/stw_device.c @@ -30,6 +30,7 @@ #include "glapi/glthread.h" #include "util/u_debug.h" #include "pipe/p_screen.h" +#include "state_tracker/st_public.h" #ifdef DEBUG #include "trace/tr_screen.h" @@ -63,15 +64,39 @@ stw_flush_frontbuffer(struct pipe_screen *screen, { const struct stw_winsys *stw_winsys = stw_dev->stw_winsys; HDC hdc = (HDC)context_private; + struct stw_framebuffer *fb; + fb = stw_framebuffer_from_hdc( hdc ); + /* fb can be NULL if window was destroyed already */ + if (fb) { + pipe_mutex_lock( fb->mutex ); + +#if DEBUG + { + struct pipe_surface *surface2; + + if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_FRONT_LEFT, &surface2 )) + assert(0); + else + assert(surface2 == surface); + } +#endif + #ifdef DEBUG - if(stw_dev->trace_running) { - screen = trace_screen(screen)->screen; - surface = trace_surface(surface)->surface; - } + if(stw_dev->trace_running) { + screen = trace_screen(screen)->screen; + surface = trace_surface(surface)->surface; + } #endif + } stw_winsys->flush_frontbuffer(screen, surface, hdc); + + if(fb) { + stw_framebuffer_update(fb); + + pipe_mutex_unlock( fb->mutex ); + } } @@ -133,20 +158,13 @@ error1: boolean stw_init_thread(void) { - if (!stw_tls_init_thread()) - return FALSE; - - if (!stw_framebuffer_init_thread()) - return FALSE; - - return TRUE; + return stw_tls_init_thread(); } void stw_cleanup_thread(void) { - stw_framebuffer_cleanup_thread(); stw_tls_cleanup_thread(); } diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c index 58f18303191..7d0e8f46482 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c @@ -84,7 +84,7 @@ stw_framebuffer_destroy_locked( * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx */ -static LRESULT CALLBACK +LRESULT CALLBACK stw_call_window_proc( int nCode, WPARAM wParam, @@ -111,15 +111,10 @@ stw_call_window_proc( unsigned width = LOWORD( pParams->lParam ); unsigned height = HIWORD( pParams->lParam ); - /* FIXME: The mesa statetracker makes the assumptions that only - * one context is using the framebuffer, and that that context is the - * current one. However neither holds true, as WGL allows more than - * one context to be bound to the same drawable, and this function can - * be called from any thread. - */ pipe_mutex_lock( fb->mutex ); - if (fb->stfb) - st_resize_framebuffer( fb->stfb, width, height ); + fb->must_resize = TRUE; + fb->width = width; + fb->height = height; pipe_mutex_unlock( fb->mutex ); } } @@ -140,6 +135,31 @@ stw_call_window_proc( } +static void +stw_framebuffer_get_size( struct stw_framebuffer *fb ) +{ + unsigned width, height; + RECT rect; + + assert(fb->hWnd); + + GetClientRect( fb->hWnd, &rect ); + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + if(width < 1) + width = 1; + if(height < 1) + height = 1; + + if(width != fb->width || height != fb->height) { + fb->must_resize = TRUE; + fb->width = width; + fb->height = height; + } +} + + /** * Create a new framebuffer object which will correspond to the given HDC. */ @@ -169,6 +189,8 @@ stw_framebuffer_create_locked( stw_pixelformat_visual(&fb->visual, pfi); + stw_framebuffer_get_size(fb); + pipe_mutex_init( fb->mutex ); fb->next = stw_dev->fb_head; @@ -178,32 +200,6 @@ stw_framebuffer_create_locked( } -static void -stw_framebuffer_get_size( struct stw_framebuffer *fb, GLuint *pwidth, GLuint *pheight ) -{ - GLuint width, height; - - if (fb->hWnd) { - RECT rect; - GetClientRect( fb->hWnd, &rect ); - width = rect.right - rect.left; - height = rect.bottom - rect.top; - } - else { - width = GetDeviceCaps( fb->hDC, HORZRES ); - height = GetDeviceCaps( fb->hDC, VERTRES ); - } - - if(width < 1) - width = 1; - if(height < 1) - height = 1; - - *pwidth = width; - *pheight = height; -} - - BOOL stw_framebuffer_allocate( struct stw_framebuffer *fb) @@ -213,7 +209,6 @@ stw_framebuffer_allocate( if(!fb->stfb) { const struct stw_pixelformat_info *pfi = fb->pfi; enum pipe_format colorFormat, depthFormat, stencilFormat; - GLuint width, height; colorFormat = pfi->color_format; @@ -229,16 +224,21 @@ stw_framebuffer_allocate( else stencilFormat = PIPE_FORMAT_NONE; - stw_framebuffer_get_size(fb, &width, &height); - + assert(fb->must_resize); + assert(fb->width); + assert(fb->height); + fb->stfb = st_create_framebuffer( &fb->visual, colorFormat, depthFormat, stencilFormat, - width, - height, + fb->width, + fb->height, (void *) fb ); + + // to notify the context + fb->must_resize = TRUE; } pipe_mutex_unlock( fb->mutex ); @@ -247,14 +247,29 @@ stw_framebuffer_allocate( } +/** + * Update the framebuffer's size if necessary. + */ void -stw_framebuffer_resize( +stw_framebuffer_update( struct stw_framebuffer *fb) { - GLuint width, height; assert(fb->stfb); - stw_framebuffer_get_size(fb, &width, &height); - st_resize_framebuffer(fb->stfb, width, height); + assert(fb->height); + assert(fb->width); + + /* XXX: It would be nice to avoid checking the size again -- in theory + * stw_call_window_proc would have cought the resize and stored the right + * size already, but unfortunately threads created before the DllMain is + * called don't get a DLL_THREAD_ATTACH notification, and there is no way + * to know of their existing without using the not very portable PSAPI. + */ + stw_framebuffer_get_size(fb); + + if(fb->must_resize) { + st_resize_framebuffer(fb->stfb, fb->width, fb->height); + fb->must_resize = FALSE; + } } @@ -407,6 +422,8 @@ stw_swap_buffers( stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc ); + stw_framebuffer_update(fb); + pipe_mutex_unlock( fb->mutex ); return TRUE; @@ -423,38 +440,3 @@ stw_swap_layer_buffers( return FALSE; } - - -boolean -stw_framebuffer_init_thread(void) -{ - struct stw_tls_data *tls_data; - - tls_data = stw_tls_get_data(); - if(!tls_data) - return FALSE; - - tls_data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, - stw_call_window_proc, - NULL, - GetCurrentThreadId()); - if(tls_data->hCallWndProcHook == NULL) - return FALSE; - - return TRUE; -} - -void -stw_framebuffer_cleanup_thread(void) -{ - struct stw_tls_data *tls_data; - - tls_data = stw_tls_get_data(); - if(!tls_data) - return; - - if(tls_data->hCallWndProcHook) { - UnhookWindowsHookEx(tls_data->hCallWndProcHook); - tls_data->hCallWndProcHook = NULL; - } -} diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h index e7fa51c3a81..759e06b8914 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h @@ -51,6 +51,11 @@ struct stw_framebuffer pipe_mutex mutex; struct st_framebuffer *stfb; + /* FIXME: Make this work for multiple contexts bound to the same framebuffer */ + boolean must_resize; + unsigned width; + unsigned height; + /** This is protected by stw_device::mutex, not the mutex above */ struct stw_framebuffer *next; }; @@ -65,7 +70,7 @@ stw_framebuffer_allocate( struct stw_framebuffer *fb ); void -stw_framebuffer_resize( +stw_framebuffer_update( struct stw_framebuffer *fb); void @@ -79,10 +84,4 @@ struct stw_framebuffer * stw_framebuffer_from_hdc( HDC hdc ); -boolean -stw_framebuffer_init_thread(void); - -void -stw_framebuffer_cleanup_thread(void); - #endif /* STW_FRAMEBUFFER_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.c b/src/gallium/state_trackers/wgl/shared/stw_tls.c index 0c18a52352c..4bd6a9289c9 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_tls.c +++ b/src/gallium/state_trackers/wgl/shared/stw_tls.c @@ -51,9 +51,23 @@ stw_tls_data_create() data = CALLOC_STRUCT(stw_tls_data); if (!data) - return NULL; + goto no_data; + + data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, + stw_call_window_proc, + NULL, + GetCurrentThreadId()); + if(data->hCallWndProcHook == NULL) + goto no_hook; + + TlsSetValue(tlsIndex, data); return data; + +no_hook: + FREE(data); +no_data: + return NULL; } boolean @@ -69,8 +83,6 @@ stw_tls_init_thread(void) if(!data) return FALSE; - TlsSetValue(tlsIndex, data); - return TRUE; } @@ -84,8 +96,16 @@ stw_tls_cleanup_thread(void) } data = (struct stw_tls_data *) TlsGetValue(tlsIndex); - TlsSetValue(tlsIndex, NULL); - FREE(data); + if(data) { + TlsSetValue(tlsIndex, NULL); + + if(data->hCallWndProcHook) { + UnhookWindowsHookEx(data->hCallWndProcHook); + data->hCallWndProcHook = NULL; + } + + FREE(data); + } } void @@ -110,12 +130,9 @@ stw_tls_get_data(void) if(!data) { /* DllMain is called with DLL_THREAD_ATTACH only by threads created after * the DLL is loaded by the process */ - data = stw_tls_data_create(); if(!data) return NULL; - - TlsSetValue(tlsIndex, data); } return data; diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.h b/src/gallium/state_trackers/wgl/shared/stw_tls.h index 6af8be70c9f..fbf8b1cbee4 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_tls.h +++ b/src/gallium/state_trackers/wgl/shared/stw_tls.h @@ -50,4 +50,10 @@ stw_tls_cleanup(void); struct stw_tls_data * stw_tls_get_data(void); +LRESULT CALLBACK +stw_call_window_proc( + int nCode, + WPARAM wParam, + LPARAM lParam ); + #endif /* STW_TLS_H */ |