From 576d9af505bd19ccaac04a68c8744f36f887bd5c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 10 Mar 2010 17:22:56 +0800 Subject: st/glx: Use st_api.h instead of st_public.h. --- src/gallium/state_trackers/glx/xlib/Makefile | 3 +- src/gallium/state_trackers/glx/xlib/glx_api.c | 5 +- src/gallium/state_trackers/glx/xlib/xm_api.c | 265 +++++++++++++------------ src/gallium/state_trackers/glx/xlib/xm_api.h | 39 ++-- src/gallium/state_trackers/glx/xlib/xm_st.c | 269 ++++++++++++++++++++++++++ src/gallium/state_trackers/glx/xlib/xm_st.h | 54 ++++++ 6 files changed, 470 insertions(+), 165 deletions(-) create mode 100644 src/gallium/state_trackers/glx/xlib/xm_st.c create mode 100644 src/gallium/state_trackers/glx/xlib/xm_st.h (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 7b2adc62c3..ddffdb162c 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -11,6 +11,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/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 2454585850..4930cd6cd5 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 f4d7133d2f..6a0f3146db 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" @@ -84,6 +82,8 @@ void xmesa_set_driver( const struct xm_driver *templ ) pipe_mutex _xmesa_lock; static struct pipe_screen *screen = NULL; +static struct st_api *stapi = NULL; +static struct st_manager *smapi = NULL; /**********************************************************************/ @@ -273,49 +273,49 @@ 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 for 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(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); - *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + count = 0; + switch (depth) { + case 16: + if (!stencil) + formats[count++] = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + break; + case 32: + if (!stencil) + formats[count++] = PIPE_FORMAT_Z32_UNORM; + break; + default: + break; + } - /* search for supported format */ - for (i = 0; i < Elements(formats); i++) { + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { if (screen->is_format_supported(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; } @@ -343,12 +343,14 @@ create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { XMesaBuffer b; - GLframebuffer *fb; - enum pipe_format colorFormat, depthFormat, stencilFormat; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + xmesa_init(vis->display); + if (!screen) + return NULL; + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); if (!b) return NULL; @@ -361,24 +363,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(screen, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -422,24 +412,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); @@ -681,6 +668,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(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; @@ -705,6 +712,26 @@ xmesa_init( Display *display ) if (firstTime) { pipe_mutex_init(_xmesa_lock); screen = driver.create_pipe_screen( display ); + stapi = xmesa_create_st_api(); + smapi = CALLOC_STRUCT(st_manager); + if (smapi) + smapi->screen = screen; + + if (!screen || !stapi || !smapi) { + if (screen) { + screen->destroy(screen); + screen = NULL; + } + if (stapi) { + stapi->destroy(stapi); + stapi = NULL; + } + if (smapi) { + FREE(smapi); + smapi = NULL; + } + } + firstTime = GL_FALSE; } } @@ -720,10 +747,7 @@ xmesa_init( Display *display ) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - struct pipe_context *pipe = NULL; XMesaContext c; - GLcontext *mesaCtx; - uint pf; xmesa_init( v->display ); @@ -732,9 +756,6 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 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; @@ -742,29 +763,18 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 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, 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 +785,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 +891,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; - GLuint width, height; assert(v); @@ -889,19 +898,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 +982,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 +1022,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 +1055,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 +1068,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 +1088,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 +1098,13 @@ 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); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + if (fence) { + screen->fence_finish(screen, fence, 0); + screen->fence_reference(screen, &fence, NULL); + } XSync( c->xm_visual->display, False ); } } @@ -1186,3 +1178,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 de47064b41..258abf9255 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" @@ -258,6 +257,8 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, int format, int target, int mipmap); +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); /*********************************************************************** @@ -280,6 +281,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 +291,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 +314,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 +338,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 +355,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 +363,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_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c new file mode 100644 index 0000000000..c5ea5c1549 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -0,0 +1,269 @@ +/* + * 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 + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "xm_api.h" +#include "xm_st.h" + +/* support OpenGL by default */ +#ifndef XMESA_ST_MODULE +#define XMESA_ST_MODULE st_module_OpenGL +#endif + +struct xmesa_st_framebuffer { + struct pipe_screen *screen; + XMesaBuffer buffer; + + struct st_visual stvis; + + unsigned texture_width, texture_height; + 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; +} + +/** + * Remove outdated textures and create the requested ones. + */ +static void +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture templ; + unsigned request_mask, i; + + request_mask = 0; + for (i = 0; i < count; i++) + request_mask |= 1 << statts[i]; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = xstfb->texture_width; + templ.height0 = xstfb->texture_height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + struct pipe_texture *ptex = xstfb->textures[i]; + enum pipe_format format; + unsigned tex_usage; + + /* remove outdated textures */ + if (ptex && (ptex->width0 != xstfb->texture_width || + ptex->height0 != xstfb->texture_height)) { + pipe_texture_reference(&xstfb->textures[i], NULL); + ptex = NULL; + } + + /* the texture already exists or not requested */ + if (ptex || !(request_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); + } + } +} + +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 i; + + /* revalidate textures */ + if (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height) { + xstfb->texture_width = xstfb->buffer->width; + xstfb->texture_height = xstfb->buffer->height; + + xmesa_st_framebuffer_validate_textures(stfbi, statts, count); + } + + 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_flush_front(stfbi, statt); + if (ret) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + 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->screen = screen; + xstfb->buffer = b; + 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); + + 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) +{ + /* TODO */ +} + +struct st_api * +xmesa_create_st_api(void) +{ + return XMESA_ST_MODULE.create_api(); +} 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 0000000000..7ca7afe253 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -0,0 +1,54 @@ +/* + * 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 + */ + +#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_api * +xmesa_create_st_api(void); + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(struct pipe_screen *screen, 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_ */ -- cgit v1.2.3 From 72ed7eb15a12ad88647dddefde5999ddd308b9e4 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 12 Mar 2010 10:04:47 +0800 Subject: st/glx: Fix an infinite recursion in flush_front. It was a stupid typo by me when I refactored the code. --- src/gallium/state_trackers/glx/xlib/xm_st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index c5ea5c1549..3b5f78e98a 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -186,7 +186,7 @@ xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); boolean ret; - ret = xmesa_st_framebuffer_flush_front(stfbi, statt); + ret = xmesa_st_framebuffer_display(stfbi, statt); if (ret) xmesa_check_buffer_size(xstfb->buffer); -- cgit v1.2.3 From 3475e88442c16fb2b50b903fe246b3ebe49da226 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 12 Mar 2010 11:20:27 +0800 Subject: st/glx: Return a better format in choose_depth_stencil_format. Return a better format instead of an exact format in choose_depth_stencil_format. Also, prefer formats with stencil bits. --- src/gallium/state_trackers/glx/xlib/xm_api.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 6a0f3146db..3ea4d77805 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -274,7 +274,8 @@ choose_pixel_format(XMesaVisual v) } /** - * Choose a depth/stencil format for the given depth and stencil sizes. + * Choose a depth/stencil format that is "better" than the given depth and + * stencil sizes. */ static enum pipe_format choose_depth_stencil_format(int depth, int stencil) @@ -289,21 +290,16 @@ choose_depth_stencil_format(int depth, int stencil) assert(screen); count = 0; - switch (depth) { - case 16: - if (!stencil) - formats[count++] = PIPE_FORMAT_Z16_UNORM; - break; - case 24: + if (depth <= 24 && stencil <= 8) { formats[count++] = PIPE_FORMAT_S8Z24_UNORM; formats[count++] = PIPE_FORMAT_Z24S8_UNORM; - break; - case 32: - if (!stencil) + } + + if (!stencil) { + if (depth <= 16) + formats[count++] = PIPE_FORMAT_Z16_UNORM; + if (depth <= 32) formats[count++] = PIPE_FORMAT_Z32_UNORM; - break; - default: - break; } fmt = PIPE_FORMAT_NONE; -- cgit v1.2.3 From 9dae0e0ff88957d16db47130a2646179fb5fc267 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 12 Mar 2010 13:26:18 +0800 Subject: st/glx: Add xm_st.c to SConscript. --- src/gallium/state_trackers/glx/xlib/SConscript | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index bb20235150..d6c16ad2f5 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') -- cgit v1.2.3 From 495bfb0ad2e60638e7b2e94f36f0079e3f450091 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 13 Mar 2010 00:52:47 +0800 Subject: st/glx: Fix leaks in xmesa_st_framebuffer. The textures and surface of a framebuffer should be unreferenced when the framebuffer is destroyed. --- src/gallium/state_trackers/glx/xlib/xm_st.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index 3b5f78e98a..d462776363 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -225,6 +225,12 @@ 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); -- cgit v1.2.3 From 813c58d77e21cb59adb914b4b4ee26be758ff0ea Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 13 Mar 2010 15:57:15 +0800 Subject: st/glx: Make xmesa_create_st_api a callback of xm_driver. Instead of guessing the API in st/glx, let the target decide how to create st_api. --- src/gallium/state_trackers/glx/xlib/xm_api.c | 2 +- src/gallium/state_trackers/glx/xlib/xm_public.h | 12 ++++++++---- src/gallium/state_trackers/glx/xlib/xm_st.c | 11 ----------- src/gallium/state_trackers/glx/xlib/xm_st.h | 3 --- src/gallium/targets/libgl-xlib/xlib.c | 3 ++- 5 files changed, 11 insertions(+), 20 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 3ea4d77805..82384a4d28 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -708,7 +708,7 @@ xmesa_init( Display *display ) if (firstTime) { pipe_mutex_init(_xmesa_lock); screen = driver.create_pipe_screen( display ); - stapi = xmesa_create_st_api(); + stapi = driver.create_st_api(); smapi = CALLOC_STRUCT(st_manager); if (smapi) smapi->screen = screen; diff --git a/src/gallium/state_trackers/glx/xlib/xm_public.h b/src/gallium/state_trackers/glx/xlib/xm_public.h index ac6a8ffb27..950eb21521 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 + +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 index d462776363..abe3b5429b 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -31,11 +31,6 @@ #include "xm_api.h" #include "xm_st.h" -/* support OpenGL by default */ -#ifndef XMESA_ST_MODULE -#define XMESA_ST_MODULE st_module_OpenGL -#endif - struct xmesa_st_framebuffer { struct pipe_screen *screen; XMesaBuffer buffer; @@ -267,9 +262,3 @@ xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, { /* TODO */ } - -struct st_api * -xmesa_create_st_api(void) -{ - return XMESA_ST_MODULE.create_api(); -} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h index 7ca7afe253..b22a837380 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.h +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -33,9 +33,6 @@ #include "xm_api.h" -struct st_api * -xmesa_create_st_api(void); - struct st_framebuffer_iface * xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b); diff --git a/src/gallium/targets/libgl-xlib/xlib.c b/src/gallium/targets/libgl-xlib/xlib.c index 50dd99ffce..1e6769367f 100644 --- a/src/gallium/targets/libgl-xlib/xlib.c +++ b/src/gallium/targets/libgl-xlib/xlib.c @@ -104,9 +104,10 @@ fail: return NULL; } -struct xm_driver xlib_driver = +static struct xm_driver xlib_driver = { .create_pipe_screen = swrast_xlib_create_screen, + .create_st_api = st_manager_create_api, }; -- cgit v1.2.3 From 418b9ac2990fc6809de359a862ee809d3b86343c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 13 Mar 2010 17:39:14 +0800 Subject: st/glx: Correctly set buffer_mask of a visual. Stupid typos again.. --- src/gallium/state_trackers/glx/xlib/xm_api.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 82384a4d28..94c0ad496d 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -666,11 +666,11 @@ XMesaVisual XMesaCreateVisual( Display *display, v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; if (db_flag) - v->stvis.buffer_mask = ST_ATTACHMENT_BACK_LEFT_MASK; + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; if (stereo_flag) { - v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_RIGHT_MASK; + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; if (db_flag) - v->stvis.buffer_mask = ST_ATTACHMENT_BACK_RIGHT_MASK; + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; } v->stvis.color_format = choose_pixel_format(v); -- cgit v1.2.3 From 66cd38f465499863de106e1ae83b5de85072c29b Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 13 Mar 2010 17:40:24 +0800 Subject: st/glx: Fix framebuffer validation. When xmesa_st_framebuffer_validate was called twice with different sets of attachments, the second call was ignored. Add a texture_mask to remember which textures have been requested to make sure the missing ones get created. --- src/gallium/state_trackers/glx/xlib/xm_st.c | 53 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index abe3b5429b..8714da8b34 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -37,7 +37,7 @@ struct xmesa_st_framebuffer { struct st_visual stvis; - unsigned texture_width, texture_height; + unsigned texture_width, texture_height, texture_mask; struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; struct pipe_surface *display_surface; @@ -86,39 +86,37 @@ xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, */ static void xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count) + unsigned width, unsigned height, + unsigned mask) { struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); struct pipe_texture templ; - unsigned request_mask, i; + unsigned i; - request_mask = 0; - for (i = 0; i < count; i++) - request_mask |= 1 << statts[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 = xstfb->texture_width; - templ.height0 = xstfb->texture_height; + templ.width0 = width; + templ.height0 = height; templ.depth0 = 1; templ.last_level = 0; for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - struct pipe_texture *ptex = xstfb->textures[i]; enum pipe_format format; unsigned tex_usage; - /* remove outdated textures */ - if (ptex && (ptex->width0 != xstfb->texture_width || - ptex->height0 != xstfb->texture_height)) { - pipe_texture_reference(&xstfb->textures[i], NULL); - ptex = NULL; - } - /* the texture already exists or not requested */ - if (ptex || !(request_mask & (1 << i))) + 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: @@ -146,6 +144,10 @@ xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, xstfb->screen->texture_create(xstfb->screen, &templ); } } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; } static boolean @@ -155,15 +157,18 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, struct pipe_texture **out) { struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - unsigned i; + unsigned statt_mask, i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; /* revalidate textures */ if (xstfb->buffer->width != xstfb->texture_width || - xstfb->buffer->height != xstfb->texture_height) { - xstfb->texture_width = xstfb->buffer->width; - xstfb->texture_height = xstfb->buffer->height; - - xmesa_st_framebuffer_validate_textures(stfbi, statts, count); + xstfb->buffer->height != xstfb->texture_height || + (xstfb->texture_mask & statt_mask) != statt_mask) { + xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); } for (i = 0; i < count; i++) { -- cgit v1.2.3 From 6632915e957149c153a3f793c400a532b4995b18 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 14 Mar 2010 11:20:58 +0800 Subject: st/glx: Add xmesa_display to hold per-display variables. This basically adds a static xmesa_display to collect per-display static variables in xm_api.c. Multiple display support is still missing, but this is a step forward. --- src/gallium/state_trackers/glx/xlib/xm_api.c | 117 +++++++++++++++------------ src/gallium/state_trackers/glx/xlib/xm_api.h | 14 ++-- 2 files changed, 73 insertions(+), 58 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 94c0ad496d..e7c1979b42 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -70,21 +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; -static struct st_api *stapi = NULL; -static struct st_manager *smapi = 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 */ @@ -278,7 +314,7 @@ choose_pixel_format(XMesaVisual v) * stencil sizes. */ static enum pipe_format -choose_depth_stencil_format(int depth, int stencil) +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; @@ -287,8 +323,6 @@ choose_depth_stencil_format(int depth, int stencil) enum pipe_format formats[8], fmt; int count, i; - assert(screen); - count = 0; if (depth <= 24 && stencil <= 8) { formats[count++] = PIPE_FORMAT_S8Z24_UNORM; @@ -304,7 +338,7 @@ choose_depth_stencil_format(int depth, int stencil) fmt = PIPE_FORMAT_NONE; for (i = 0; i < count; i++) { - if (screen->is_format_supported(screen, formats[i], + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], target, tex_usage, geom_flags)) { fmt = formats[i]; break; @@ -320,7 +354,7 @@ choose_depth_stencil_format(int depth, int stencil) /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -XMesaBuffer XMesaBufferList = NULL; +static XMesaBuffer XMesaBufferList = NULL; /** @@ -338,13 +372,13 @@ static XMesaBuffer create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { + XMesaDisplay xmdpy = xmesa_init_display(vis->display); XMesaBuffer b; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); - xmesa_init(vis->display); - if (!screen) + if (!xmdpy) return NULL; b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); @@ -364,7 +398,7 @@ create_xmesa_buffer(Drawable d, BufferType type, /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = xmesa_create_st_framebuffer(screen, b); + b->stfb = xmesa_create_st_framebuffer(xmdpy->screen, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -579,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")) { @@ -675,7 +711,7 @@ XMesaVisual XMesaCreateVisual( Display *display, v->stvis.color_format = choose_pixel_format(v); v->stvis.depth_stencil_format = - choose_depth_stencil_format(depth_size, stencil_size); + 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) ? @@ -699,37 +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 ); - stapi = driver.create_st_api(); - smapi = CALLOC_STRUCT(st_manager); - if (smapi) - smapi->screen = screen; - - if (!screen || !stapi || !smapi) { - if (screen) { - screen->destroy(screen); - screen = NULL; - } - if (stapi) { - stapi->destroy(stapi); - stapi = NULL; - } - if (smapi) { - FREE(smapi); - smapi = NULL; - } - } - - firstTime = GL_FALSE; - } + xmesa_init_display(display); } @@ -743,9 +754,11 @@ xmesa_init( Display *display ) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { + XMesaDisplay xmdpy = xmesa_init_display(v->display); XMesaContext c; - xmesa_init( v->display ); + if (!xmdpy) + return NULL; /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); @@ -756,10 +769,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; - if (screen == NULL) - goto fail; - - c->st = stapi->create_context(stapi, smapi, + c->st = stapi->create_context(stapi, xmdpy->smapi, &v->stvis, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; @@ -1094,12 +1104,13 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) void XMesaFlush( XMesaContext c ) { if (c && c->xm_visual->display) { + 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) { - screen->fence_finish(screen, fence, 0); - screen->fence_reference(screen, &fence, NULL); + xmdpy->screen->fence_finish(xmdpy->screen, fence, 0); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); } XSync( c->xm_visual->display, False ); } diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index 258abf9255..11a08962b7 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -67,11 +67,20 @@ and create a window, you must do the following to use the X/Mesa interface: # include # include +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; +}; + /* * Create a new X/Mesa visual. @@ -264,11 +273,6 @@ 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. -- cgit v1.2.3 From 48bc3cca89f7aecc40d1661e695796113df6e583 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 14 Mar 2010 11:34:16 +0800 Subject: st/glx: Add support for GLX_MESA_copy_sub_buffer. Create a per-display pipe_context as needed to copy the contents between framebuffer attachments. This allows us to support GLX_MESA_copy_sub_buffer. --- src/gallium/state_trackers/glx/xlib/xm_api.c | 2 +- src/gallium/state_trackers/glx/xlib/xm_api.h | 2 ++ src/gallium/state_trackers/glx/xlib/xm_st.c | 53 +++++++++++++++++++++++++--- src/gallium/state_trackers/glx/xlib/xm_st.h | 2 +- 4 files changed, 53 insertions(+), 6 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index e7c1979b42..62a2bfcfa0 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -398,7 +398,7 @@ create_xmesa_buffer(Drawable d, BufferType type, /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = xmesa_create_st_framebuffer(xmdpy->screen, b); + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index 11a08962b7..4f2c8a6e6a 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -79,6 +79,8 @@ struct xmesa_display { Display *display; struct pipe_screen *screen; struct st_manager *smapi; + + struct pipe_context *pipe; }; diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index 8714da8b34..de5a35edca 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -32,8 +32,9 @@ #include "xm_st.h" struct xmesa_st_framebuffer { - struct pipe_screen *screen; + XMesaDisplay display; XMesaBuffer buffer; + struct pipe_screen *screen; struct st_visual stvis; @@ -81,6 +82,45 @@ xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, 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, 0, 0, src, 0, 0, src->width, src->height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + /** * Remove outdated textures and create the requested ones. */ @@ -194,11 +234,13 @@ xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, } struct st_framebuffer_iface * -xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b) +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) { @@ -209,8 +251,9 @@ xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b) return NULL; } - xstfb->screen = screen; + xstfb->display = xmdpy; xstfb->buffer = b; + xstfb->screen = xmdpy->screen; xstfb->stvis = b->xm_visual->stvis; stfbi->visual = &xstfb->stvis; @@ -265,5 +308,7 @@ xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, enum st_attachment_type dst, int x, int y, int w, int h) { - /* TODO */ + 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 index b22a837380..396495c189 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.h +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -34,7 +34,7 @@ #include "xm_api.h" struct st_framebuffer_iface * -xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b); +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); void xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); -- cgit v1.2.3 From d6262bdcfb64e1f88f6a890829f5c30c26bc372b Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 14 Mar 2010 12:01:27 +0800 Subject: st/glx: Sync the back buffer to the front buffer. Consider this rendering sequence * render to the back buffer * swap buffers * read from the front buffer The front buffer is expected to have the contents of the back buffer. --- src/gallium/state_trackers/glx/xlib/xm_st.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index de5a35edca..bcb8285d9f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -197,18 +197,36 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, struct pipe_texture **out) { struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - unsigned statt_mask, i; + 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 (xstfb->buffer->width != xstfb->texture_width || - xstfb->buffer->height != xstfb->texture_height || - (xstfb->texture_mask & statt_mask) != statt_mask) { + 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++) { -- cgit v1.2.3 From 23e9a25e1ff01d9f3ef5cc99f59e0fda0ac2d421 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 14 Mar 2010 14:58:27 +0800 Subject: st/glx: Fix glXCopySubBufferMESA. Honor the (x, y) and (width, height) pairs. --- src/gallium/state_trackers/glx/xlib/xm_st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/glx') diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index bcb8285d9f..b6ed7e8e1e 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -115,7 +115,7 @@ xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); if (src && dst) - pipe->surface_copy(pipe, dst, 0, 0, src, 0, 0, src->width, src->height); + pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height); pipe_surface_reference(&src, NULL); pipe_surface_reference(&dst, NULL); -- cgit v1.2.3