diff options
Diffstat (limited to 'src/gallium/state_trackers/glx')
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/Makefile | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/SConscript | 1 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/glx_api.c | 5 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_api.c | 316 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_api.h | 55 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_public.h | 12 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_st.c | 332 | ||||
-rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_st.h | 51 |
8 files changed, 579 insertions, 196 deletions
diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 8c7cc524dfc..582e72bb463 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -12,6 +12,7 @@ C_SOURCES = \ glx_api.c \ glx_getproc.c \ glx_usefont.c \ - xm_api.c + xm_api.c \ + xm_st.c include ../../../Makefile.template diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index bb202351509..d6c16ad2f52 100644 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -20,6 +20,7 @@ if env['platform'] == 'linux' \ 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', + 'xm_st.c', ] ) Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 24545858500..4930cd6cd50 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -35,12 +35,9 @@ #include "xm_api.h" #include "main/context.h" -#include "main/config.h" #include "main/macros.h" #include "main/imports.h" #include "main/version.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" /* This indicates the client-side GLX API and GLX encoder version. */ @@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, if (MakeCurrent_PrevContext == src) { _mesa_Flush(); } - st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask ); + XMesaCopyContext(xm_src, xm_dst, mask); } diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index f4d7133d2ff..62a2bfcfa07 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -54,11 +54,9 @@ #endif #include "xm_api.h" -#include "main/context.h" -#include "main/framebuffer.h" +#include "xm_st.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" +#include "main/context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -72,19 +70,56 @@ * global. */ static struct xm_driver driver; +static struct st_api *stapi; void xmesa_set_driver( const struct xm_driver *templ ) { driver = *templ; + stapi = driver.create_st_api(); } -/** - * Global X driver lock - */ -pipe_mutex _xmesa_lock; +static XMesaDisplay +xmesa_init_display( Display *display ) +{ + pipe_static_mutex(init_mutex); + static struct xmesa_display xm_display; + XMesaDisplay xmdpy; + + pipe_mutex_lock(init_mutex); + + /* TODO support for multiple displays */ + xmdpy = &xm_display; + + if (!xmdpy->display && display) { + xmdpy->display = display; + xmdpy->screen = driver.create_pipe_screen(display); + xmdpy->smapi = CALLOC_STRUCT(st_manager); + if (xmdpy->smapi) + xmdpy->smapi->screen = xmdpy->screen; + + if (xmdpy->screen && xmdpy->smapi) { + pipe_mutex_init(xmdpy->mutex); + } + else { + if (xmdpy->screen) { + xmdpy->screen->destroy(xmdpy->screen); + xmdpy->screen = NULL; + } + if (xmdpy->smapi) { + FREE(xmdpy->smapi); + xmdpy->smapi = NULL; + } -static struct pipe_screen *screen = NULL; + xmdpy->display = NULL; + } + } + if (!xmdpy->display || xmdpy->display != display) + xmdpy = NULL; + pipe_mutex_unlock(init_mutex); + + return xmdpy; +} /**********************************************************************/ /***** X Utility Functions *****/ @@ -194,12 +229,13 @@ void xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height) { + XMesaDisplay xmdpy = xmesa_init_display(dpy); Status stat; - pipe_mutex_lock(_xmesa_lock); + pipe_mutex_lock(xmdpy->mutex); XSync(b->xm_visual->display, 0); /* added for Chromium */ stat = get_drawable_size(dpy, b->ws.drawable, width, height); - pipe_mutex_unlock(_xmesa_lock); + pipe_mutex_unlock(xmdpy->mutex); if (!stat) { /* probably querying a window that's recently been destroyed */ @@ -273,49 +309,43 @@ choose_pixel_format(XMesaVisual v) return 0; } - - /** - * Query the default gallium screen for a Z/Stencil format that - * at least matches the given depthBits and stencilBits. + * Choose a depth/stencil format that is "better" than the given depth and + * stencil sizes. */ -static void -xmesa_choose_z_stencil_format(int depthBits, int stencilBits, - enum pipe_format *depthFormat, - enum pipe_format *stencilFormat) +static enum pipe_format +choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil) { const enum pipe_texture_target target = PIPE_TEXTURE_2D; const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE | PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO); - static enum pipe_format formats[] = { - PIPE_FORMAT_S8Z24_UNORM, - PIPE_FORMAT_Z24S8_UNORM, - PIPE_FORMAT_Z16_UNORM, - PIPE_FORMAT_Z32_UNORM - }; - int i; + enum pipe_format formats[8], fmt; + int count, i; - assert(screen); + count = 0; + if (depth <= 24 && stencil <= 8) { + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + } - *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + if (!stencil) { + if (depth <= 16) + formats[count++] = PIPE_FORMAT_Z16_UNORM; + if (depth <= 32) + formats[count++] = PIPE_FORMAT_Z32_UNORM; + } - /* search for supported format */ - for (i = 0; i < Elements(formats); i++) { - if (screen->is_format_supported(screen, formats[i], + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], target, tex_usage, geom_flags)) { - *depthFormat = formats[i]; + fmt = formats[i]; break; } } - if (stencilBits) { - *stencilFormat = *depthFormat; - } - - /* XXX we should check that he chosen format has at least as many bits - * as what was requested. - */ + return fmt; } @@ -324,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits, /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -XMesaBuffer XMesaBufferList = NULL; +static XMesaBuffer XMesaBufferList = NULL; /** @@ -342,13 +372,15 @@ static XMesaBuffer create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { + XMesaDisplay xmdpy = xmesa_init_display(vis->display); XMesaBuffer b; - GLframebuffer *fb; - enum pipe_format colorFormat, depthFormat, stencilFormat; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + if (!xmdpy) + return NULL; + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); if (!b) return NULL; @@ -361,24 +393,12 @@ create_xmesa_buffer(Drawable d, BufferType type, b->type = type; b->cmap = cmap; - /* determine PIPE_FORMATs for buffers */ - colorFormat = choose_pixel_format(vis); - - xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits, - vis->mesa_visual.stencilBits, - &depthFormat, &stencilFormat); - - get_drawable_size(vis->display, d, &width, &height); /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = st_create_framebuffer(&vis->mesa_visual, - colorFormat, depthFormat, stencilFormat, - width, height, - (void *) b); - fb = &b->stfb->Base; + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -422,24 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer) for (b = XMesaBufferList; b; b = b->Next) { if (b == buffer) { - struct gl_framebuffer *fb = &buffer->stfb->Base; - /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; - /* mark as delete pending */ - fb->DeletePending = GL_TRUE; - /* Since the X window for the XMesaBuffer is going away, we don't * want to dereference this pointer in the future. */ b->ws.drawable = 0; - /* Unreference. If count = zero we'll really delete the buffer */ - _mesa_reference_framebuffer(&fb, NULL); + /* XXX we should move the buffer to a delete-pending list and destroy + * the buffer until it is no longer current. + */ + xmesa_destroy_st_framebuffer(buffer->stfb); free(buffer); @@ -596,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display, GLint level, GLint visualCaveat ) { + XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; - xmesa_init( display ); + if (!xmdpy) + return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { @@ -681,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display, accum_blue_size, accum_alpha_size, 0 ); + v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (stereo_flag) { + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + v->stvis.color_format = choose_pixel_format(v); + v->stvis.depth_stencil_format = + choose_depth_stencil_format(xmdpy, depth_size, stencil_size); + + v->stvis.accum_format = (accum_red_size + + accum_green_size + accum_blue_size + accum_alpha_size) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + v->stvis.samples = num_samples; + v->stvis.render_buffer = ST_ATTACHMENT_INVALID; + /* XXX minor hack */ v->mesa_visual.level = level; return v; @@ -696,17 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v ) /** - * Do one-time initializations. + * Do per-display initializations. */ void xmesa_init( Display *display ) { - static GLboolean firstTime = GL_TRUE; - if (firstTime) { - pipe_mutex_init(_xmesa_lock); - screen = driver.create_pipe_screen( display ); - firstTime = GL_FALSE; - } + xmesa_init_display(display); } @@ -720,51 +754,33 @@ xmesa_init( Display *display ) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - struct pipe_context *pipe = NULL; + XMesaDisplay xmdpy = xmesa_init_display(v->display); XMesaContext c; - GLcontext *mesaCtx; - uint pf; - xmesa_init( v->display ); + if (!xmdpy) + return NULL; /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); if (!c) return NULL; - pf = choose_pixel_format(v); - assert(pf); - c->xm_visual = v; c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; - if (screen == NULL) - goto fail; - - /* Trace screen knows how to properly wrap context creation in the - * wrapped screen, so nothing special to do here: - */ - pipe = screen->context_create(screen, (void *) c); - if (pipe == NULL) - goto fail; - - c->st = st_create_context(pipe, - &v->mesa_visual, - share_list ? share_list->st : NULL); + c->st = stapi->create_context(stapi, xmdpy->smapi, + &v->stvis, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; - mesaCtx = c->st->ctx; - c->st->ctx->DriverCtx = c; + c->st->st_manager_private = (void *) c; return c; fail: if (c->st) - st_destroy_context(c->st); - else if (pipe) - pipe->destroy(pipe); + c->st->destroy(c->st); free(c); return NULL; @@ -775,7 +791,7 @@ fail: PUBLIC void XMesaDestroyContext( XMesaContext c ) { - st_destroy_context(c->st); + c->st->destroy(c->st); /* FIXME: We should destroy the screen here, but if we do so, surfaces may * outlive it, causing segfaults @@ -881,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; - GLuint width, height; assert(v); @@ -889,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, if (!b) return NULL; - /* get pixmap size, update framebuffer/renderbuffer dims */ - xmesa_get_window_size(v->display, b, &width, &height); - _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); + /* get pixmap size */ + xmesa_get_window_size(v->display, b, &b->width, &b->height); if (target == 0) { /* examine dims */ if (ctx->Extensions.ARB_texture_non_power_of_two) { target = GLX_TEXTURE_2D_EXT; } - else if ( _mesa_bitcount(width) == 1 - && _mesa_bitcount(height) == 1) { + else if ( _mesa_bitcount(b->width) == 1 + && _mesa_bitcount(b->height) == 1) { /* power of two size */ - if (height == 1) { + if (b->height == 1) { target = GLX_TEXTURE_1D_EXT; } else { @@ -974,23 +988,20 @@ XMesaDestroyBuffer(XMesaBuffer b) /** - * Query the current window size and update the corresponding GLframebuffer - * and all attached renderbuffers. - * Called when: - * 1. the first time a buffer is bound to a context. - * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... - * Note: it's possible (and legal) for xmctx to be NULL. That can happen - * when resizing a buffer when no rendering context is bound. + * Query the current drawable size and notify the binding context. */ void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +xmesa_check_buffer_size(XMesaBuffer b) { - GLuint width, height; - xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); - st_resize_framebuffer(drawBuffer->stfb, width, height); -} + XMesaContext xmctx = XMesaGetCurrentContext(); + if (b->type == PBUFFER) + return; + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); + if (xmctx && xmctx->xm_buffer == b) + xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb); +} /* @@ -1017,22 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, c->xm_read_buffer == readBuffer) return GL_TRUE; + xmesa_check_buffer_size(drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_buffer_size(readBuffer); + c->xm_buffer = drawBuffer; c->xm_read_buffer = readBuffer; - st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb, - &drawBuffer->ws); - - xmesa_check_and_update_buffer_size(c, drawBuffer); - if (readBuffer != drawBuffer) - xmesa_check_and_update_buffer_size(c, readBuffer); + stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb); /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ drawBuffer->wasCurrent = GL_TRUE; } else { /* Detach */ - st_make_current( NULL, NULL, NULL, NULL ); + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; @@ -1051,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c ) XMesaContext XMesaGetCurrentContext( void ) { - GET_CURRENT_CONTEXT(ctx); - if (ctx) { - XMesaContext xmesa = xmesa_context(ctx); - return xmesa; - } - else { - return 0; - } + struct st_context_iface *st = stapi->get_current(stapi); + return (XMesaContext) (st) ? st->st_manager_private : NULL; } @@ -1070,17 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void ) PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *frontLeftSurf; - - st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - - if (frontLeftSurf) { - screen->flush_frontbuffer( screen, - frontLeftSurf, - &b->ws ); + XMesaContext xmctx = XMesaGetCurrentContext(); + + if (xmctx && xmctx->xm_buffer == b) { + xmctx->st->flush( xmctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); } - xmesa_check_and_update_buffer_size(NULL, b); + xmesa_swap_st_framebuffer(b->stfb); } @@ -1090,21 +1094,9 @@ void XMesaSwapBuffers( XMesaBuffer b ) */ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) { - struct pipe_surface *surf_front; - struct pipe_surface *surf_back; - struct pipe_context *pipe = NULL; /* XXX fix */ - - st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); - - if (!surf_front || !surf_back) - return; - - assert(pipe); - pipe->surface_copy(pipe, - surf_front, x, y, /* dest */ - surf_back, x, y, /* src */ - width, height); + xmesa_copy_st_framebuffer(b->stfb, + ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, + x, y, width, height); } @@ -1112,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) void XMesaFlush( XMesaContext c ) { if (c && c->xm_visual->display) { - st_finish(c->st); + XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + if (fence) { + xmdpy->screen->fence_finish(xmdpy->screen, fence, 0); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); + } XSync( c->xm_visual->display, False ); } } @@ -1186,3 +1185,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) { } + +void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) +{ + if (dst->st->copy) + dst->st->copy(dst->st, src->st, mask); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index de47064b410..4f2c8a6e6a9 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface: #include "main/mtypes.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" +#include "state_tracker/st_api.h" #include "os/os_thread.h" #include "state_tracker/xlib_sw_winsys.h" @@ -68,11 +67,22 @@ and create a window, you must do the following to use the X/Mesa interface: # include <X11/Xlibint.h> # include <X11/Xutil.h> +typedef struct xmesa_display *XMesaDisplay; typedef struct xmesa_buffer *XMesaBuffer; typedef struct xmesa_context *XMesaContext; typedef struct xmesa_visual *XMesaVisual; +struct xmesa_display { + pipe_mutex mutex; + + Display *display; + struct pipe_screen *screen; + struct st_manager *smapi; + + struct pipe_context *pipe; +}; + /* * Create a new X/Mesa visual. @@ -258,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, int format, int target, int mipmap); +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); /*********************************************************************** */ -extern pipe_mutex _xmesa_lock; - -extern struct xmesa_buffer *XMesaBufferList; - - /** * Visual inforation, derived from GLvisual. * Basically corresponds to an XVisualInfo. @@ -280,6 +287,8 @@ struct xmesa_visual { GLint BitsPerPixel; /* True bits per pixel for XImages */ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + struct st_visual stvis; }; @@ -288,7 +297,7 @@ struct xmesa_visual { * Basically corresponds to a GLXContext. */ struct xmesa_context { - struct st_context *st; + struct st_context_iface *st; XMesaVisual xm_visual; /** pixel format info */ XMesaBuffer xm_buffer; /** current drawbuffer */ XMesaBuffer xm_read_buffer; /** current readbuffer */ @@ -311,7 +320,7 @@ typedef enum { * Basically corresponds to a GLXDrawable. */ struct xmesa_buffer { - struct st_framebuffer *stfb; + struct st_framebuffer_iface *stfb; struct xlib_drawable ws; GLboolean wasCurrent; /* was ever the current buffer? */ @@ -335,33 +344,15 @@ struct xmesa_buffer { GLint TextureMipmap; /** 0 or 1 */ struct xmesa_buffer *Next; /* Linked list pointer: */ -}; - - - -/** cast wrapper */ -static INLINE XMesaContext -xmesa_context(GLcontext *ctx) -{ - return (XMesaContext) ctx->DriverCtx; -} + unsigned width, height; +}; -/** cast wrapper */ -static INLINE XMesaBuffer -xmesa_buffer(GLframebuffer *fb) -{ - struct st_framebuffer *stfb = (struct st_framebuffer *) fb; - return (XMesaBuffer) st_framebuffer_private(stfb); -} extern void xmesa_init(Display *dpy); -extern void -xmesa_delete_framebuffer(struct gl_framebuffer *fb); - extern XMesaBuffer xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); @@ -370,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height); extern void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer); +xmesa_check_buffer_size(XMesaBuffer b); extern void xmesa_destroy_buffers_on_display(Display *dpy); @@ -378,13 +369,13 @@ xmesa_destroy_buffers_on_display(Display *dpy); static INLINE GLuint xmesa_buffer_width(XMesaBuffer b) { - return b->stfb->Base.Width; + return b->width; } static INLINE GLuint xmesa_buffer_height(XMesaBuffer b) { - return b->stfb->Base.Height; + return b->height; } diff --git a/src/gallium/state_trackers/glx/xlib/xm_public.h b/src/gallium/state_trackers/glx/xlib/xm_public.h index ac6a8ffb27a..950eb21521f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_public.h +++ b/src/gallium/state_trackers/glx/xlib/xm_public.h @@ -26,19 +26,23 @@ * **************************************************************************/ -#ifndef XM_WINSYS_H -#define XM_WINSYS_H +#ifndef XM_PUBLIC_H +#define XM_PUBLIC_H -struct xm_driver; +#include <X11/Xlib.h> + +struct pipe_screen; +struct st_api; /* This is the driver interface required by the glx/xlib state tracker. */ struct xm_driver { struct pipe_screen *(*create_pipe_screen)( Display *display ); + struct st_api *(*create_st_api)( void ); }; extern void xmesa_set_driver( const struct xm_driver *driver ); -#endif +#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c new file mode 100644 index 00000000000..b6ed7e8e1e8 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -0,0 +1,332 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "xm_api.h" +#include "xm_st.h" + +struct xmesa_st_framebuffer { + XMesaDisplay display; + XMesaBuffer buffer; + struct pipe_screen *screen; + + struct st_visual stvis; + + unsigned texture_width, texture_height, texture_mask; + struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + + struct pipe_surface *display_surface; +}; + +static INLINE struct xmesa_st_framebuffer * +xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; +} + +/** + * Display an attachment to the xlib_drawable of the framebuffer. + */ +static boolean +xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture *ptex = xstfb->textures[statt]; + struct pipe_surface *psurf; + + if (!ptex) + return TRUE; + + psurf = xstfb->display_surface; + /* (re)allocate the surface for the texture to be displayed */ + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&xstfb->display_surface, NULL); + + psurf = xstfb->screen->get_tex_surface(xstfb->screen, + ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); + if (!psurf) + return FALSE; + + xstfb->display_surface = psurf; + } + + xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); + + return TRUE; +} + +/** + * Copy the contents between the attachments. + */ +static void +xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src_statt, + enum st_attachment_type dst_statt, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture *src_ptex = xstfb->textures[src_statt]; + struct pipe_texture *dst_ptex = xstfb->textures[dst_statt]; + struct pipe_surface *src, *dst; + struct pipe_context *pipe; + + if (!src_ptex || !dst_ptex) + return; + + pipe = xstfb->display->pipe; + if (!pipe) { + pipe = xstfb->screen->context_create(xstfb->screen, NULL); + if (!pipe) + return; + xstfb->display->pipe = pipe; + } + + src = xstfb->screen->get_tex_surface(xstfb->screen, + src_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + dst = xstfb->screen->get_tex_surface(xstfb->screen, + dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); + + if (src && dst) + pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/** + * Remove outdated textures and create the requested ones. + */ +static void +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture templ; + unsigned i; + + /* remove outdated textures */ + if (xstfb->texture_width != width || xstfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&xstfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned tex_usage; + + /* the texture already exists or not requested */ + if (xstfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (xstfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = xstfb->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = xstfb->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + xstfb->textures[i] = + xstfb->screen->texture_create(xstfb->screen, &templ); + } + } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; +} + +static boolean +xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_texture **out) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + unsigned statt_mask, new_mask, i; + boolean resized; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + /* record newly allocated textures */ + new_mask = statt_mask & ~xstfb->texture_mask; + + resized = (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height); + + /* revalidate textures */ + if (resized || new_mask) { + xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); + + if (!resized) { + enum st_attachment_type back, front; + + back = ST_ATTACHMENT_BACK_LEFT; + front = ST_ATTACHMENT_FRONT_LEFT; + /* copy the contents if front is newly allocated and back is not */ + if ((statt_mask & (1 << back)) && + (new_mask & (1 << front)) && + !(new_mask & (1 << back))) { + xmesa_st_framebuffer_copy_textures(stfbi, back, front, + 0, 0, xstfb->texture_width, xstfb->texture_height); + } + } + } + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_texture_reference(&out[i], xstfb->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, statt); + if (ret) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + assert(xmdpy->display == b->xm_visual->display); + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); + if (!stfbi || !xstfb) { + if (stfbi) + FREE(stfbi); + if (xstfb) + FREE(xstfb); + return NULL; + } + + xstfb->display = xmdpy; + xstfb->buffer = b; + xstfb->screen = xmdpy->screen; + xstfb->stvis = b->xm_visual->stvis; + + stfbi->visual = &xstfb->stvis; + stfbi->flush_front = xmesa_st_framebuffer_flush_front; + stfbi->validate = xmesa_st_framebuffer_validate; + stfbi->st_manager_private = (void *) xstfb; + + return stfbi; +} + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + int i; + + pipe_surface_reference(&xstfb->display_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&xstfb->textures[i], NULL); + + FREE(xstfb); + FREE(stfbi); +} + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); + if (ret) { + struct pipe_texture **front, **back, *tmp; + + front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; + back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; + /* swap textures only if the front texture has been allocated */ + if (*front) { + tmp = *front; + *front = *back; + *back = tmp; + } + + xmesa_check_buffer_size(xstfb->buffer); + } +} + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h) +{ + xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); + if (dst == ST_ATTACHMENT_FRONT_LEFT) + xmesa_st_framebuffer_display(stfbi, dst); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h new file mode 100644 index 00000000000..396495c1893 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -0,0 +1,51 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef _XM_ST_H_ +#define _XM_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" + +#include "xm_api.h" + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h); + +#endif /* _XM_ST_H_ */ |