diff options
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/state_trackers/glx/xlib/Makefile | 3 | ||||
| -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 | 263 | ||||
| -rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_api.h | 39 | ||||
| -rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_st.c | 269 | ||||
| -rw-r--r-- | src/gallium/state_trackers/glx/xlib/xm_st.h | 54 | 
6 files changed, 469 insertions, 164 deletions
| 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; +   XMesaContext xmctx = XMesaGetCurrentContext(); -   st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - -   if (frontLeftSurf) { -      screen->flush_frontbuffer( screen, -                                 frontLeftSurf,  -                                 &b->ws ); +   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 <olv@lunarg.com> + */ + +#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 <olv@lunarg.com> + */ + +#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_ */ | 
