summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--progs/xdemos/glxgears.c35
-rw-r--r--src/gallium/auxiliary/util/u_tile.c28
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_context.c56
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_device.c15
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_device.h4
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_framebuffer.c199
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_framebuffer.h83
-rw-r--r--src/glx/x11/dri_glx.c23
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c21
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c12
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c35
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c3
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c9
-rw-r--r--src/mesa/state_tracker/st_program.c34
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: