diff options
-rw-r--r-- | progs/xdemos/glxgears.c | 35 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_tile.c | 28 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_context.c | 56 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_device.c | 15 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_device.h | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_framebuffer.c | 199 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/shared/stw_framebuffer.h | 83 | ||||
-rw-r--r-- | src/glx/x11/dri_glx.c | 23 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 21 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 12 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 35 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_framebuffer.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_mesa_to_tgsi.c | 9 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.c | 34 |
14 files changed, 378 insertions, 179 deletions
diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c index 2dc157a890..bc84ee3dbd 100644 --- a/progs/xdemos/glxgears.c +++ b/progs/xdemos/glxgears.c @@ -39,6 +39,12 @@ #include <GL/gl.h> #include <GL/glx.h> +#ifndef GLX_MESA_swap_control +#define GLX_MESA_swap_control 1 +typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void); +#endif + + static int is_glx_extension_supported(Display *dpy, const char *query); static void query_vsync(Display *dpy); @@ -592,31 +598,22 @@ query_vsync(Display *dpy) int interval = 0; -#ifdef GLX_MESA_swap_control - if ((interval <= 0) - && is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { + if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA"); interval = (*pglXGetSwapIntervalMESA)(); + } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) { + /* The default swap interval with this extension is 1. Assume that it + * is set to the default. + * + * Many Mesa-based drivers default to 0, but all of these drivers also + * export GLX_MESA_swap_control. In that case, this branch will never + * be taken, and the correct result should be reported. + */ + interval = 1; } -#endif - - -#ifdef GLX_SGI_video_sync - if ((interval <= 0) - && is_glx_extension_supported(dpy, "GLX_SGI_video_sync")) { - PFNGLXGETVIDEOSYNCSGIPROC pglXGetVideoSyncSGI = - (PFNGLXGETVIDEOSYNCSGIPROC) - glXGetProcAddressARB((const GLubyte *) "glXGetVideoSyncSGI"); - unsigned count; - - if ((*pglXGetVideoSyncSGI)(& count) == 0) { - interval = (int) count; - } - } -#endif if (interval > 0) { diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 9747a55cbf..a0c8ed88f7 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -1202,6 +1202,19 @@ pipe_put_tile_z(struct pipe_transfer *pt, } break; case PIPE_FORMAT_S8Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + assert(pt->usage == PIPE_TRANSFER_READ_WRITE); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; case PIPE_FORMAT_X8Z24_UNORM: { uint *pDest = (uint *) (map + y * pt->stride + x*4); @@ -1216,13 +1229,26 @@ pipe_put_tile_z(struct pipe_transfer *pt, } break; case PIPE_FORMAT_Z24S8_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + assert(pt->usage == PIPE_TRANSFER_READ_WRITE); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00); + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; case PIPE_FORMAT_Z24X8_UNORM: { uint *pDest = (uint *) (map + y * pt->stride + x*4); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 32-bit Z to 24-bit Z (0 stencil) */ - pDest[j] = ptrc[j] << 8; + pDest[j] = ptrc[j] & 0xffffff00; } pDest += pt->stride/4; ptrc += srcStride; diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c index 9df1ab7652..4968ecc692 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_context.c +++ b/src/gallium/state_trackers/wgl/shared/stw_context.c @@ -60,8 +60,14 @@ stw_context(GLcontext *glctx) static INLINE struct stw_context * stw_current_context(void) { - GET_CURRENT_CONTEXT( glctx ); - return stw_context(glctx); + /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT + * might return the current context of the thread first seen. */ + _glapi_check_multithread(); + + { + GET_CURRENT_CONTEXT( glctx ); + return stw_context(glctx); + } } BOOL @@ -74,7 +80,7 @@ stw_copy_context( struct stw_context *dst; BOOL ret = FALSE; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); src = stw_lookup_context_locked( hglrcSrc ); dst = stw_lookup_context_locked( hglrcDst ); @@ -87,7 +93,7 @@ stw_copy_context( (void) mask; } - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); return ret; } @@ -101,7 +107,7 @@ stw_share_lists( struct stw_context *ctx2; BOOL ret = FALSE; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); ctx1 = stw_lookup_context_locked( hglrc1 ); ctx2 = stw_lookup_context_locked( hglrc2 ); @@ -111,7 +117,7 @@ stw_share_lists( ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx); } - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); return ret; } @@ -124,8 +130,10 @@ stw_viewport(GLcontext * glctx, GLint x, GLint y, struct stw_framebuffer *fb; fb = stw_framebuffer_from_hdc( ctx->hdc ); - if(fb) + if(fb) { stw_framebuffer_update(fb); + stw_framebuffer_release(fb); + } } UINT_PTR @@ -189,9 +197,9 @@ stw_create_layer_context( ctx->st->ctx->DriverCtx = ctx; ctx->st->ctx->Driver.Viewport = stw_viewport; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); ctx->hglrc = handle_table_add(stw_dev->ctx_table, ctx); - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); if (!ctx->hglrc) goto no_hglrc; @@ -218,10 +226,10 @@ stw_delete_context( if (!stw_dev) return FALSE; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); ctx = stw_lookup_context_locked(hglrc); handle_table_remove(stw_dev->ctx_table, hglrc); - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); if (ctx) { struct stw_context *curctx = stw_current_context(); @@ -248,9 +256,9 @@ stw_release_context( if (!stw_dev) return FALSE; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); ctx = stw_lookup_context_locked( hglrc ); - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); if (!ctx) return FALSE; @@ -298,9 +306,9 @@ stw_make_current( HDC hdc, UINT_PTR hglrc ) { - struct stw_context *curctx; - struct stw_context *ctx; - struct stw_framebuffer *fb; + struct stw_context *curctx = NULL; + struct stw_context *ctx = NULL; + struct stw_framebuffer *fb = NULL; if (!stw_dev) goto fail; @@ -322,13 +330,13 @@ stw_make_current( return st_make_current( NULL, NULL, NULL ); } - pipe_mutex_lock( stw_dev->mutex ); - + pipe_mutex_lock( stw_dev->ctx_mutex ); ctx = stw_lookup_context_locked( hglrc ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); if(!ctx) goto fail; - fb = stw_framebuffer_from_hdc_locked( hdc ); + fb = stw_framebuffer_from_hdc( hdc ); if(!fb) { /* Applications should call SetPixelFormat before creating a context, * but not all do, and the opengl32 runtime seems to use a default pixel @@ -336,13 +344,11 @@ stw_make_current( */ int iPixelFormat = GetPixelFormat(hdc); if(iPixelFormat) - fb = stw_framebuffer_create_locked( hdc, iPixelFormat ); + fb = stw_framebuffer_create( hdc, iPixelFormat ); if(!fb) goto fail; } - pipe_mutex_unlock( stw_dev->mutex ); - if(fb->iPixelFormat != ctx->iPixelFormat) goto fail; @@ -361,12 +367,16 @@ stw_make_current( success: assert(fb); - if(fb) + if(fb) { stw_framebuffer_update(fb); + stw_framebuffer_release(fb); + } return TRUE; fail: + if(fb) + stw_framebuffer_release(fb); st_make_current( NULL, NULL, NULL ); return FALSE; } diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/shared/stw_device.c index ce46624146..0b6954915a 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_device.c +++ b/src/gallium/state_trackers/wgl/shared/stw_device.c @@ -69,8 +69,6 @@ stw_flush_frontbuffer(struct pipe_screen *screen, 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; @@ -94,8 +92,7 @@ stw_flush_frontbuffer(struct pipe_screen *screen, if(fb) { stw_framebuffer_update(fb); - - pipe_mutex_unlock( fb->mutex ); + stw_framebuffer_release(fb); } } @@ -138,7 +135,8 @@ stw_init(const struct stw_winsys *stw_winsys) stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer; - pipe_mutex_init( stw_dev->mutex ); + pipe_mutex_init( stw_dev->ctx_mutex ); + pipe_mutex_init( stw_dev->fb_mutex ); stw_dev->ctx_table = handle_table_create(); if (!stw_dev->ctx_table) { @@ -179,7 +177,7 @@ stw_cleanup(void) if (!stw_dev) return; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->ctx_mutex ); { /* Ensure all contexts are destroyed */ i = handle_table_get_first_handle(stw_dev->ctx_table); @@ -189,11 +187,12 @@ stw_cleanup(void) } handle_table_destroy(stw_dev->ctx_table); } - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); stw_framebuffer_cleanup(); - pipe_mutex_destroy( stw_dev->mutex ); + pipe_mutex_destroy( stw_dev->fb_mutex ); + pipe_mutex_destroy( stw_dev->ctx_mutex ); stw_dev->screen->destroy(stw_dev->screen); diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.h b/src/gallium/state_trackers/wgl/shared/stw_device.h index e097f1f71e..e1bb9518dd 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_device.h +++ b/src/gallium/state_trackers/wgl/shared/stw_device.h @@ -57,10 +57,10 @@ struct stw_device unsigned pixelformat_count; unsigned pixelformat_extended_count; - pipe_mutex mutex; - + pipe_mutex ctx_mutex; struct handle_table *ctx_table; + pipe_mutex fb_mutex; struct stw_framebuffer *fb_head; #ifdef DEBUG diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c index 78a2dbc4d7..b8956bb550 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c @@ -45,6 +45,10 @@ #include "stw_tls.h" +/** + * Search the framebuffer with the matching HWND while holding the + * stw_dev::fb_mutex global lock. + */ static INLINE struct stw_framebuffer * stw_framebuffer_from_hwnd_locked( HWND hwnd ) @@ -52,13 +56,20 @@ stw_framebuffer_from_hwnd_locked( struct stw_framebuffer *fb; for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) - if (fb->hWnd == hwnd) + if (fb->hWnd == hwnd) { + pipe_mutex_lock(fb->mutex); break; + } return fb; } +/** + * Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex + * must be held, by this order. Obviously no further access to fb can be done + * after this. + */ static INLINE void stw_framebuffer_destroy_locked( struct stw_framebuffer *fb ) @@ -74,12 +85,48 @@ stw_framebuffer_destroy_locked( st_unreference_framebuffer(fb->stfb); + pipe_mutex_unlock( fb->mutex ); + pipe_mutex_destroy( fb->mutex ); FREE( fb ); } +void +stw_framebuffer_release( + struct stw_framebuffer *fb) +{ + assert(fb); + pipe_mutex_unlock( fb->mutex ); +} + + +static INLINE 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; + } +} + + /** * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx @@ -92,6 +139,7 @@ stw_call_window_proc( { struct stw_tls_data *tls_data; PCWPSTRUCT pParams = (PCWPSTRUCT)lParam; + struct stw_framebuffer *fb; tls_data = stw_tls_get_data(); if(!tls_data) @@ -100,71 +148,37 @@ stw_call_window_proc( if (nCode < 0) return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); - if (pParams->message == WM_SIZE && pParams->wParam != SIZE_MINIMIZED) { - struct stw_framebuffer *fb; - - pipe_mutex_lock( stw_dev->mutex ); - fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); - pipe_mutex_unlock( stw_dev->mutex ); - - if(fb) { - unsigned width = LOWORD( pParams->lParam ); - unsigned height = HIWORD( pParams->lParam ); - - pipe_mutex_lock( fb->mutex ); - fb->must_resize = TRUE; - fb->width = width; - fb->height = height; - pipe_mutex_unlock( fb->mutex ); + if (pParams->message == WM_WINDOWPOSCHANGED) { + /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according to + * http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx + * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it + * can be masked out by the application. */ + LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam; + if((lpWindowPos->flags & SWP_SHOWWINDOW) || + !(lpWindowPos->flags & SWP_NOSIZE)) { + fb = stw_framebuffer_from_hwnd( pParams->hwnd ); + if(fb) { + /* Size in WINDOWPOS includes the window frame, so get the size + * of the client area via GetClientRect. */ + stw_framebuffer_get_size(fb); + stw_framebuffer_release(fb); + } } } - - if (pParams->message == WM_DESTROY) { - struct stw_framebuffer *fb; - - pipe_mutex_lock( stw_dev->mutex ); - + else if (pParams->message == WM_DESTROY) { + pipe_mutex_lock( stw_dev->fb_mutex ); fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); if(fb) stw_framebuffer_destroy_locked(fb); - - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->fb_mutex ); } return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); } -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. - */ struct stw_framebuffer * -stw_framebuffer_create_locked( +stw_framebuffer_create( HDC hdc, int iPixelFormat ) { @@ -193,8 +207,16 @@ stw_framebuffer_create_locked( pipe_mutex_init( fb->mutex ); + /* This is the only case where we lock the stw_framebuffer::mutex before + * stw_dev::fb_mutex, since no other thread can know about this framebuffer + * and we must prevent any other thread from destroying it before we return. + */ + pipe_mutex_lock( fb->mutex ); + + pipe_mutex_lock( stw_dev->fb_mutex ); fb->next = stw_dev->fb_head; stw_dev->fb_head = fb; + pipe_mutex_unlock( stw_dev->fb_mutex ); return fb; } @@ -204,8 +226,8 @@ BOOL stw_framebuffer_allocate( struct stw_framebuffer *fb) { - pipe_mutex_lock( fb->mutex ); - + assert(fb); + if(!fb->stfb) { const struct stw_pixelformat_info *pfi = fb->pfi; enum pipe_format colorFormat, depthFormat, stencilFormat; @@ -241,8 +263,6 @@ stw_framebuffer_allocate( fb->must_resize = TRUE; } - pipe_mutex_unlock( fb->mutex ); - return fb->stfb ? TRUE : FALSE; } @@ -279,24 +299,27 @@ stw_framebuffer_cleanup( void ) struct stw_framebuffer *fb; struct stw_framebuffer *next; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->fb_mutex ); fb = stw_dev->fb_head; while (fb) { next = fb->next; + + pipe_mutex_lock(fb->mutex); stw_framebuffer_destroy_locked(fb); + fb = next; } stw_dev->fb_head = NULL; - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->fb_mutex ); } /** * Given an hdc, return the corresponding stw_framebuffer. */ -struct stw_framebuffer * +static INLINE struct stw_framebuffer * stw_framebuffer_from_hdc_locked( HDC hdc ) { @@ -313,8 +336,10 @@ stw_framebuffer_from_hdc_locked( return stw_framebuffer_from_hwnd_locked(hwnd); for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) - if (fb->hDC == hdc) + if (fb->hDC == hdc) { + pipe_mutex_lock(fb->mutex); break; + } return fb; } @@ -329,9 +354,26 @@ stw_framebuffer_from_hdc( { struct stw_framebuffer *fb; - pipe_mutex_lock( stw_dev->mutex ); + pipe_mutex_lock( stw_dev->fb_mutex ); fb = stw_framebuffer_from_hdc_locked(hdc); - pipe_mutex_unlock( stw_dev->mutex ); + pipe_mutex_unlock( stw_dev->fb_mutex ); + + return fb; +} + + +/** + * Given an hdc, return the corresponding stw_framebuffer. + */ +struct stw_framebuffer * +stw_framebuffer_from_hwnd( + HWND hwnd ) +{ + struct stw_framebuffer *fb; + + pipe_mutex_lock( stw_dev->fb_mutex ); + fb = stw_framebuffer_from_hwnd_locked(hwnd); + pipe_mutex_unlock( stw_dev->fb_mutex ); return fb; } @@ -351,22 +393,19 @@ stw_pixelformat_set( if (index >= count) return FALSE; - pipe_mutex_lock( stw_dev->mutex ); - fb = stw_framebuffer_from_hdc_locked(hdc); if(fb) { /* SetPixelFormat must be called only once */ - pipe_mutex_unlock( stw_dev->mutex ); + stw_framebuffer_release( fb ); return FALSE; } - fb = stw_framebuffer_create_locked(hdc, iPixelFormat); + fb = stw_framebuffer_create(hdc, iPixelFormat); if(!fb) { - pipe_mutex_unlock( stw_dev->mutex ); return FALSE; } - pipe_mutex_unlock( stw_dev->mutex ); + stw_framebuffer_release( fb ); /* Some applications mistakenly use the undocumented wglSetPixelFormat * function instead of SetPixelFormat, so we call SetPixelFormat here to @@ -383,13 +422,16 @@ int stw_pixelformat_get( HDC hdc ) { + int iPixelFormat = 0; struct stw_framebuffer *fb; fb = stw_framebuffer_from_hdc(hdc); - if(!fb) - return 0; + if(fb) { + iPixelFormat = fb->iPixelFormat; + stw_framebuffer_release(fb); + } - return fb->iPixelFormat; + return iPixelFormat; } @@ -405,10 +447,10 @@ stw_swap_buffers( if (fb == NULL) return FALSE; - if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) + if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) { + stw_framebuffer_release(fb); return TRUE; - - pipe_mutex_lock( fb->mutex ); + } /* If we're swapping the buffer associated with the current context * we have to flush any pending rendering commands first. @@ -419,7 +461,7 @@ stw_swap_buffers( if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface )) { /* FIXME: this shouldn't happen, but does on glean */ - pipe_mutex_unlock( fb->mutex ); + stw_framebuffer_release(fb); return FALSE; } @@ -433,8 +475,7 @@ stw_swap_buffers( stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc ); stw_framebuffer_update(fb); - - pipe_mutex_unlock( fb->mutex ); + stw_framebuffer_release(fb); return TRUE; } diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h index 759e06b891..13d29f37e4 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h @@ -41,6 +41,23 @@ struct stw_pixelformat_info; */ struct stw_framebuffer { + /** + * This mutex has two purposes: + * - protect the access to the mutable data members below + * - prevent the the framebuffer from being deleted while being accessed. + * + * It is OK to lock this mutex while holding the stw_device::fb_mutex lock, + * but the opposite must never happen. + */ + pipe_mutex mutex; + + /* + * Immutable members. + * + * Note that even access to immutable members implies acquiring the mutex + * above, to prevent the framebuffer from being destroyed. + */ + HDC hDC; HWND hWnd; @@ -48,7 +65,10 @@ struct stw_framebuffer const struct stw_pixelformat_info *pfi; GLvisual visual; - pipe_mutex mutex; + /* + * Mutable members. + */ + struct st_framebuffer *stfb; /* FIXME: Make this work for multiple contexts bound to the same framebuffer */ @@ -56,15 +76,52 @@ struct stw_framebuffer unsigned width; unsigned height; - /** This is protected by stw_device::mutex, not the mutex above */ + /** + * This is protected by stw_device::fb_mutex, not the mutex above. + * + * Deletions must be done by first acquiring stw_device::fb_mutex, and then + * acquiring the stw_framebuffer::mutex of the framebuffer to be deleted. + * This ensures that nobody else is reading/writing to the. + * + * It is not necessary to aquire the mutex above to navigate the linked list + * given that deletions are done with stw_device::fb_mutex held, so no other + * thread can delete. + */ struct stw_framebuffer *next; }; + +/** + * Create a new framebuffer object which will correspond to the given HDC. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release + * must be called when done + */ struct stw_framebuffer * -stw_framebuffer_create_locked( +stw_framebuffer_create( HDC hdc, int iPixelFormat ); +/** + * Search a framebuffer with a matching HWND. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release + * must be called when done + */ +struct stw_framebuffer * +stw_framebuffer_from_hwnd( + HWND hwnd ); + +/** + * Search a framebuffer with a matching HDC. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release + * must be called when done + */ +struct stw_framebuffer * +stw_framebuffer_from_hdc( + HDC hdc ); + BOOL stw_framebuffer_allocate( struct stw_framebuffer *fb ); @@ -73,15 +130,19 @@ void stw_framebuffer_update( struct stw_framebuffer *fb); +/** + * Release stw_framebuffer::mutex lock. This framebuffer must not be accessed + * after calling this function, as it may have been deleted by another thread + * in the meanwhile. + */ void -stw_framebuffer_cleanup(void); - -struct stw_framebuffer * -stw_framebuffer_from_hdc_locked( - HDC hdc ); +stw_framebuffer_release( + struct stw_framebuffer *fb); -struct stw_framebuffer * -stw_framebuffer_from_hdc( - HDC hdc ); +/** + * Cleanup any existing framebuffers when exiting application. + */ +void +stw_framebuffer_cleanup(void); #endif /* STW_FRAMEBUFFER_H */ diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 3ce410d9be..ac2eb05341 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -305,6 +305,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, drm_handle_t hFB; int junk; const __DRIconfig **driver_configs; + __GLcontextModes *visual; /* DRI protocol version. */ dri_version.major = driDpy->driMajor; @@ -417,6 +418,28 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + /* Visuals with depth != screen depth are subject to automatic compositing + * in the X server, so DRI1 can't render to them properly. Mark them as + * non-conformant to prevent apps from picking them up accidentally. + */ + for (visual = psc->visuals; visual; visual = visual->next) { + XVisualInfo template; + XVisualInfo *visuals; + int num_visuals; + long mask; + + template.visualid = visual->visualID; + mask = VisualIDMask; + visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals); + + if (visuals) { + if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn)) + visual->visualRating = GLX_NON_CONFORMANT_CONFIG; + + XFree(visuals); + } + } + return psp; handle_error: diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index c02ccc3528..299aa762c2 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -137,22 +137,15 @@ find_translated_vp(struct st_context *st, for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) { if (fragInputsRead & (1 << inAttr)) { + stfp->input_to_slot[inAttr] = numIn; + numIn++; if ((fragInputsRead & FRAG_BIT_FOGC)) { - if (stfp->Base.UsesPointCoord) { - stfp->input_to_slot[inAttr] = numIn; - numIn++; + /* leave placeholders for the + * extra registers we extract from fog */ + if (stfp->Base.UsesFrontFacing || + stfp->Base.UsesPointCoord) { + numIn += 2; } - if (stfp->Base.UsesFrontFacing) { - stfp->input_to_slot[inAttr] = numIn; - numIn++; - } - if (stfp->Base.UsesFogFragCoord) { - stfp->input_to_slot[inAttr] = numIn; - numIn++; - } - } else { - stfp->input_to_slot[inAttr] = numIn; - numIn++; } } else { diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 2027b713ce..8b5094a04f 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -1037,10 +1037,16 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, PIPE_TRANSFER_READ, srcx, srcy, width, height); + struct pipe_transfer *ptTex; + enum pipe_transfer_usage transfer_usage; - struct pipe_transfer *ptTex = - st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, width, height); + if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format)) + transfer_usage = PIPE_TRANSFER_READ_WRITE; + else + transfer_usage = PIPE_TRANSFER_WRITE; + + ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, + 0, 0, width, height); if (type == GL_COLOR) { /* alternate path using get/put_tile() */ diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 0a72784ce0..909189f9d3 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -529,6 +529,7 @@ st_TexImage(GLcontext * ctx, GLint texelBytes, sizeInBytes; GLuint dstRowStride; struct gl_pixelstore_attrib unpackNB; + enum pipe_transfer_usage transfer_usage; DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); @@ -680,8 +681,14 @@ st_TexImage(GLcontext * ctx, } if (stImage->pt) { + if (format == GL_DEPTH_COMPONENT && + pf_is_depth_and_stencil(stImage->pt->format)) + transfer_usage = PIPE_TRANSFER_READ_WRITE; + else + transfer_usage = PIPE_TRANSFER_WRITE; + texImage->Data = st_texture_image_map(ctx->st, stImage, 0, - PIPE_TRANSFER_WRITE, 0, 0, + transfer_usage, 0, 0, stImage->base.Width, stImage->base.Height); if(stImage->transfer) @@ -742,7 +749,7 @@ st_TexImage(GLcontext * ctx, st_texture_image_unmap(ctx->st, stImage); /* map next slice of 3D texture */ texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1, - PIPE_TRANSFER_WRITE, 0, 0, + transfer_usage, 0, 0, stImage->base.Width, stImage->base.Height); src += srcImageStride; @@ -1041,6 +1048,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, _mesa_image_image_stride(packing, width, height, format, type); GLint i; const GLubyte *src; + enum pipe_transfer_usage transfer_usage; DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), @@ -1072,10 +1080,16 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, * from uploading the buffer under us. */ if (stImage->pt) { + if (format == GL_DEPTH_COMPONENT && + pf_is_depth_and_stencil(stImage->pt->format)) + transfer_usage = PIPE_TRANSFER_READ_WRITE; + else + transfer_usage = PIPE_TRANSFER_WRITE; + st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level, - PIPE_TRANSFER_WRITE); + transfer_usage); texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, - PIPE_TRANSFER_WRITE, + transfer_usage, xoffset, yoffset, width, height); } @@ -1106,7 +1120,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, /* map next slice of 3D texture */ texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i + 1, - PIPE_TRANSFER_WRITE, + transfer_usage, xoffset, yoffset, width, height); src += srcImageStride; @@ -1274,6 +1288,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, struct pipe_screen *screen = pipe->screen; struct pipe_transfer *src_trans; GLvoid *texDest; + enum pipe_transfer_usage transfer_usage; assert(width <= MAX_WIDTH); @@ -1288,10 +1303,16 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, srcX, srcY, width, height); + if (baseFormat == GL_DEPTH_COMPONENT && + pf_is_depth_and_stencil(stImage->pt->format)) + transfer_usage = PIPE_TRANSFER_READ_WRITE; + else + transfer_usage = PIPE_TRANSFER_WRITE; + st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0, - PIPE_TRANSFER_WRITE); + transfer_usage); - texDest = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE, + texDest = st_texture_image_map(ctx->st, stImage, 0, transfer_usage, destX, destY, width, height); if (baseFormat == GL_DEPTH_COMPONENT || diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index 13589151ba..ca32b2e573 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -280,7 +280,8 @@ st_notify_swapbuffers(struct st_framebuffer *stfb) PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME, NULL ); - ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK; + if (st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer)) + ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK; } } diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 3140ebe04a..8aef3fc6dc 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -122,8 +122,15 @@ map_register_file_index( SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); + /* register after fog */ + return inputMapping[index] + 1; } else { - /* fixme: point coord */ + *swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, + SWIZZLE_W, + SWIZZLE_Z, + SWIZZLE_W); + /* register after frontface */ + return inputMapping[index] + 2; } } /* inputs are mapped according to the user-defined map */ diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 3365bc0b8b..e4d3bb33c7 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -453,20 +453,34 @@ st_translate_fragment_program(struct st_context *st, stfp->input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; - case FRAG_ATTRIB_FOGC: - if (stfp->Base.UsesPointCoord) { - stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - stfp->input_semantic_index[slot] = num_generic++; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - } else if (stfp->Base.UsesFrontFacing) { - stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - stfp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; - } else { + case FRAG_ATTRIB_FOGC: { + int extra_decls = 0; + if (stfp->Base.UsesFogFragCoord) { stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stfp->input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + input_flags[slot] = stfp->Base.Base.InputFlags[attr]; + ++extra_decls; } + if (stfp->Base.UsesFrontFacing) { + GLint idx = slot + extra_decls; + stfp->input_semantic_name[idx] = TGSI_SEMANTIC_FACE; + stfp->input_semantic_index[idx] = 0; + interpMode[idx] = TGSI_INTERPOLATE_CONSTANT; + input_flags[idx] = stfp->Base.Base.InputFlags[attr]; + ++extra_decls; + } + if (stfp->Base.UsesPointCoord) { + GLint idx = slot + extra_decls; + stfp->input_semantic_name[idx] = TGSI_SEMANTIC_GENERIC; + stfp->input_semantic_index[idx] = num_generic++; + interpMode[idx] = TGSI_INTERPOLATE_PERSPECTIVE; + input_flags[idx] = stfp->Base.Base.InputFlags[attr]; + ++extra_decls; + } + fs_num_inputs += extra_decls - 1; + continue; + } break; case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX1: |