diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/pipe/xlib/xm_winsys_aub.c | 618 | ||||
| -rw-r--r-- | src/mesa/pipe/xlib/xm_winsys_aub.h | 67 | 
2 files changed, 685 insertions, 0 deletions
diff --git a/src/mesa/pipe/xlib/xm_winsys_aub.c b/src/mesa/pipe/xlib/xm_winsys_aub.c new file mode 100644 index 0000000000..ee3c2d6181 --- /dev/null +++ b/src/mesa/pipe/xlib/xm_winsys_aub.c @@ -0,0 +1,618 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + *  + * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + *  + **************************************************************************/ + +/* + * Authors: + *   Keith Whitwell + *   Brian Paul + */ + + +#include "glxheader.h" +#include "xmesaP.h" +#include "main/macros.h" + +#include "pipe/p_winsys.h" +#include "pipe/i965simple/brw_winsys.h" +#include "brw_aub.h" +#include "xm_winsys_aub.h" + + + +struct aub_buffer { +   char *data; +   unsigned offset; +   unsigned size; +   unsigned refcount; +   unsigned map_count; +   boolean dump_on_unmap; +   boolean userbuffer; +}; + + + +struct aub_pipe_winsys { +   struct pipe_winsys winsys; + +   struct brw_aubfile *aubfile; + +   /* This is simple, isn't it: +    */ +   char *pool; +   unsigned size; +   unsigned used; +}; + + +/* Turn a pipe winsys into an aub/pipe winsys: + */ +static inline struct aub_pipe_winsys * +aub_pipe_winsys( struct pipe_winsys *winsys ) +{ +   return (struct aub_pipe_winsys *)winsys; +} + + + +static INLINE struct aub_buffer * +aub_bo( struct pipe_buffer_handle *bo ) +{ +   return (struct aub_buffer *)bo; +} + +static INLINE struct pipe_buffer_handle * +pipe_bo( struct aub_buffer *bo ) +{ +   return (struct pipe_buffer_handle *)bo; +} + + + + +static void *aub_buffer_map(struct pipe_winsys *winsys,  +			      struct pipe_buffer_handle *buf, +			      unsigned flags ) +{ +   struct aub_buffer *sbo = aub_bo(buf); + +   if (flags & PIPE_BUFFER_FLAG_WRITE) +      sbo->dump_on_unmap = 1; + +   sbo->map_count++; +   return sbo->data; +} + +static void aub_buffer_unmap(struct pipe_winsys *winsys,  +			       struct pipe_buffer_handle *buf) +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   struct aub_buffer *sbo = aub_bo(buf); + +   sbo->map_count--; + +   if (sbo->map_count == 0 && +       sbo->dump_on_unmap) { +      brw_aub_gtt_data( iws->aubfile,  +			sbo->offset, +			sbo->data, +			sbo->size, +			0, +			0); +   } +} + + +static void +aub_buffer_reference(struct pipe_winsys *winsys, +		       struct pipe_buffer_handle **ptr, +		       struct pipe_buffer_handle *buf) +{ +   if (*ptr) { +      if (--(aub_bo(*ptr)->refcount) == 0) +	 free(*ptr); +      *ptr = NULL; +   } + +   if (buf) { +      aub_bo(buf)->refcount++; +      *ptr = buf; +   } +} + + +static int aub_buffer_data(struct pipe_winsys *winsys,  +			      struct pipe_buffer_handle *buf, +			      unsigned size, const void *data, +			      unsigned usage ) +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   struct aub_buffer *sbo = aub_bo(buf); + +   /* Could reuse buffers that are not referenced in current +    * batchbuffer.  Can't do that atm, so always reallocate: +    */ +   if (1 || sbo->size < size) { +      assert(iws->used + size < iws->size); +      sbo->data = iws->pool + iws->used; +      sbo->offset = AUB_BUF_START + iws->used; +      iws->used += size; +   } + +   sbo->size = size; + +   if (data != NULL) { +      memcpy(iws->pool, data, size); + +      brw_aub_gtt_data( iws->aubfile,  +			sbo->offset, +			sbo->data, +			sbo->size, +			0, +			0 ); +   } +   return 0; +} + +static int aub_buffer_subdata(struct pipe_winsys *winsys,  +				 struct pipe_buffer_handle *buf, +				 unsigned long offset,  +				 unsigned long size,  +				 const void *data) +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   struct aub_buffer *sbo = aub_bo(buf); + +   assert(sbo->size > offset + size); +   memcpy(sbo->data + offset, data, size); + +   brw_aub_gtt_data( iws->aubfile,  +		     sbo->offset + offset, +		     sbo->data + offset, +		     size, +		     0, +		     0 ); +   return 0; +} + + +void xmesa_buffer_subdata_aub(struct pipe_winsys *winsys,  +			      struct pipe_buffer_handle *buf, +			      unsigned long offset,  +			      unsigned long size,  +			      const void *data, +			      unsigned aub_type, +			      unsigned aub_sub_type) +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   struct aub_buffer *sbo = aub_bo(buf); + +   assert(sbo->size > offset + size); +   memcpy(sbo->data + offset, data, size); + +   brw_aub_gtt_data( iws->aubfile,  +		     sbo->offset + offset, +		     sbo->data + offset, +		     size, +		     aub_type, +		     aub_sub_type ); +} + +void xmesa_commands_aub(struct pipe_winsys *winsys, +			unsigned *cmds, +			unsigned nr_dwords) +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   brw_aub_gtt_cmds( iws->aubfile,  +		     0,		/* ?? */ +		     cmds, +		     nr_dwords * sizeof(int) ); +} + + +static struct aub_pipe_winsys *global_winsys = NULL; + +void xmesa_display_aub( /* struct pipe_winsys *winsys, */ +		       struct pipe_surface *surface ) +{ +//   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   brw_aub_dump_bmp( global_winsys->aubfile,  +		     surface, +		     aub_bo(surface->buffer)->offset ); +} + + + +static int aub_buffer_get_subdata(struct pipe_winsys *winsys,  +				     struct pipe_buffer_handle *buf, +				     unsigned long offset,  +				     unsigned long size,  +				     void *data) +{ +   struct aub_buffer *sbo = aub_bo(buf); +   assert(sbo->size > offset + size); +   memcpy(data, sbo->data + offset, size); +   return 0; +} + +/* Pipe has no concept of pools.  We choose the tex/region pool + * for all buffers. + */ +static struct pipe_buffer_handle * +aub_buffer_create(struct pipe_winsys *winsys, +                     unsigned alignment, +                     unsigned flags, +                     unsigned hint) +{ +   return pipe_bo(CALLOC_STRUCT(aub_buffer)); +} + + +static struct pipe_buffer_handle * +aub_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) +{ +   struct aub_buffer *sbo = CALLOC_STRUCT(aub_buffer); +   sbo->size = bytes; +   sbo->userbuffer = 1; +   sbo->data = ptr; +   return pipe_bo(sbo); +} + + +/* The state tracker (should!) keep track of whether the fake + * frontbuffer has been touched by any rendering since the last time + * we copied its contents to the real frontbuffer.  Our task is easy: + */ +static void +aub_flush_frontbuffer( struct pipe_winsys *winsys, +                         struct pipe_surface *surf, +                         void *context_private) +{ +   xmesa_display_aub( surf ); +} + +static struct pipe_surface * +aub_i915_surface_alloc(struct pipe_winsys *winsys) +{ +   struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface); +   if (surf) { +      surf->refcount = 1; +      surf->winsys = winsys; +   } +   return surf; +} + + +/** + * Round n up to next multiple. + */ +static INLINE unsigned +round_up(unsigned n, unsigned multiple) +{ +   return (n + multiple - 1) & ~(multiple - 1); +} + +static int +aub_i915_surface_alloc_storage(struct pipe_winsys *winsys, +                               struct pipe_surface *surf, +                               unsigned width, unsigned height, +                               enum pipe_format format, +                               unsigned flags) +{ +    const unsigned alignment = 64; +    int ret; + +    surf->width = width; +    surf->height = height; +    surf->format = format; +    surf->cpp = pf_get_size(format); +    surf->pitch = round_up(width, alignment / surf->cpp); + +    assert(!surf->buffer); +    surf->buffer = winsys->buffer_create(winsys, alignment, 0, 0); +    if(!surf->buffer) +        return -1; + +    ret = winsys->buffer_data(winsys, +                              surf->buffer, +                              surf->pitch * surf->cpp * height, +                              NULL, +                              0); +    if(ret) { +        winsys->buffer_reference(winsys, &surf->buffer, NULL); +        return ret; +    } + +    return 0; +} + +static void +aub_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) +{ +   struct pipe_surface *surf = *s; +   surf->refcount--; +   if (surf->refcount == 0) { +      if (surf->buffer) +         winsys->buffer_reference(winsys, &surf->buffer, NULL); +      free(surf); +   } +   *s = NULL; +} + + + +static void +aub_printf( struct pipe_winsys *winsys, const char *fmtString, ... ) +{ +   va_list args; +   va_start( args, fmtString );   +   vfprintf(stderr, fmtString, args); +   va_end( args ); +} + +static const char * +aub_get_name( struct pipe_winsys *winsys ) +{ +   return "Aub/xlib"; +} + +struct pipe_winsys * +xmesa_create_pipe_winsys_aub( void ) +{ +   struct aub_pipe_winsys *iws = CALLOC_STRUCT( aub_pipe_winsys ); +    +   /* Fill in this struct with callbacks that pipe will need to +    * communicate with the window system, buffer manager, etc.  +    * +    * Pipe would be happy with a malloc based memory manager, but +    * the SwapBuffers implementation in this winsys driver requires +    * that rendering be done to an appropriate _DriBufferObject.   +    */ +   iws->winsys.buffer_create = aub_buffer_create; +   iws->winsys.user_buffer_create = aub_user_buffer_create; +   iws->winsys.buffer_map = aub_buffer_map; +   iws->winsys.buffer_unmap = aub_buffer_unmap; +   iws->winsys.buffer_reference = aub_buffer_reference; +   iws->winsys.buffer_data = aub_buffer_data; +   iws->winsys.buffer_subdata = aub_buffer_subdata; +   iws->winsys.buffer_get_subdata = aub_buffer_get_subdata; +   iws->winsys.flush_frontbuffer = aub_flush_frontbuffer; +   iws->winsys.printf = aub_printf; +   iws->winsys.get_name = aub_get_name; + +   iws->winsys.surface_alloc = aub_i915_surface_alloc; +   iws->winsys.surface_alloc_storage = aub_i915_surface_alloc_storage; +   iws->winsys.surface_release = aub_i915_surface_release; + +   iws->aubfile = brw_aubfile_create(); +   iws->size = AUB_BUF_SIZE; +   iws->pool = malloc(AUB_BUF_SIZE); + +   /* HACK: static copy of this pointer: +    */ +   assert(global_winsys == NULL); +   global_winsys = iws; + +   return &iws->winsys; +} + + +void +xmesa_destroy_pipe_winsys_aub( struct pipe_winsys *winsys ) + +{ +   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys); +   brw_aub_destroy(iws->aubfile); +   free(iws->pool); +   free(iws); +} + + + + + + + +#define IWS_BATCHBUFFER_SIZE 1024 + +struct aub_brw_winsys { +   struct brw_winsys winsys;   /**< batch buffer funcs */ +   struct aub_context *aub; +                          +   struct pipe_winsys *pipe_winsys; + +   unsigned data[IWS_BATCHBUFFER_SIZE]; +   unsigned nr; +   unsigned size; +}; + + +/* Turn a i965simple winsys into an aub/i965simple winsys: + */ +static inline struct aub_brw_winsys * +aub_brw_winsys( struct brw_winsys *sws ) +{ +   return (struct aub_brw_winsys *)sws; +} + + +/* Simple batchbuffer interface: + */ + +static unsigned *aub_i965_batch_start( struct brw_winsys *sws, +					 unsigned dwords, +					 unsigned relocs ) +{ +   struct aub_brw_winsys *iws = aub_brw_winsys(sws); + +   if (iws->size < iws->nr + dwords) +      return NULL; + +   return (void *)1;			/* not a valid pointer! */ +} + +static void aub_i965_batch_dword( struct brw_winsys *sws, +				    unsigned dword ) +{ +   struct aub_brw_winsys *iws = aub_brw_winsys(sws); + +   iws->data[iws->nr++] = dword; +} + +static void aub_i965_batch_reloc( struct brw_winsys *sws, +			     struct pipe_buffer_handle *buf, +			     unsigned access_flags, +			     unsigned delta ) +{ +   struct aub_brw_winsys *iws = aub_brw_winsys(sws); + +   iws->data[iws->nr++] = aub_bo(buf)->offset + delta; +} + + + +static void aub_i965_batch_flush( struct brw_winsys *sws, +				    struct pipe_fence_handle **fence ) +{ +   struct aub_brw_winsys *iws = aub_brw_winsys(sws); +   assert(iws->nr <= iws->size); + +   if (iws->nr) +      xmesa_commands_aub( iws->pipe_winsys, +			  iws->data, +			  iws->nr ); +   iws->nr = 0; +} + + + +static void aub_i965_buffer_subdata_typed(struct brw_winsys *winsys,  +					    struct pipe_buffer_handle *buf, +					    unsigned long offset,  +					    unsigned long size,  +					    const void *data, +					    unsigned data_type) +{ +   struct aub_brw_winsys *iws = aub_brw_winsys(winsys); +   unsigned aub_type = DW_GENERAL_STATE; +   unsigned aub_sub_type; + +   switch (data_type) { +   case BRW_CC_VP: +      aub_sub_type = DWGS_COLOR_CALC_VIEWPORT_STATE; +      break; +   case BRW_CC_UNIT: +      aub_sub_type = DWGS_COLOR_CALC_STATE; +      break; +   case BRW_WM_PROG: +      aub_sub_type = DWGS_KERNEL_INSTRUCTIONS; +      break; +   case BRW_SAMPLER_DEFAULT_COLOR: +      aub_sub_type = DWGS_SAMPLER_DEFAULT_COLOR; +      break; +   case BRW_SAMPLER: +      aub_sub_type = DWGS_SAMPLER_STATE; +      break; +   case BRW_WM_UNIT: +      aub_sub_type = DWGS_WINDOWER_IZ_STATE; +      break; +   case BRW_SF_PROG: +      aub_sub_type = DWGS_KERNEL_INSTRUCTIONS; +      break; +   case BRW_SF_VP: +      aub_sub_type = DWGS_STRIPS_FANS_VIEWPORT_STATE; +      break; +   case BRW_SF_UNIT: +      aub_sub_type = DWGS_STRIPS_FANS_STATE; +      break; +   case BRW_VS_UNIT: +      aub_sub_type = DWGS_VERTEX_SHADER_STATE; +      break; +   case BRW_VS_PROG: +      aub_sub_type = DWGS_KERNEL_INSTRUCTIONS; +      break; +   case BRW_GS_UNIT: +      aub_sub_type = DWGS_GEOMETRY_SHADER_STATE; +      break; +   case BRW_GS_PROG: +      aub_sub_type = DWGS_KERNEL_INSTRUCTIONS; +      break; +   case BRW_CLIP_VP: +      aub_sub_type = DWGS_CLIPPER_VIEWPORT_STATE; +      break; +   case BRW_CLIP_UNIT: +      aub_sub_type = DWGS_CLIPPER_STATE; +      break; +   case BRW_CLIP_PROG: +      aub_sub_type = DWGS_KERNEL_INSTRUCTIONS; +      break; +   case BRW_SS_SURFACE: +      aub_type = DW_SURFACE_STATE; +      aub_sub_type = DWSS_SURFACE_STATE;  +      break; +   case BRW_SS_SURF_BIND: +      aub_type = DW_SURFACE_STATE; +      aub_sub_type = DWSS_BINDING_TABLE_STATE;  +      break; +   } + +   xmesa_buffer_subdata_aub( iws->pipe_winsys, +			     buf, +			     offset, +			     size, +			     data, +			     aub_type, +			     aub_sub_type ); +} +    +/** + * Create i965 hardware rendering context. + */ +struct pipe_context * +xmesa_create_i965simple( struct pipe_winsys *winsys ) +{ +   struct aub_brw_winsys *iws = CALLOC_STRUCT( aub_brw_winsys ); +    +   /* Fill in this struct with callbacks that i965simple will need to +    * communicate with the window system, buffer manager, etc.  +    */ +   iws->winsys.batch_start = aub_i965_batch_start; +   iws->winsys.batch_dword = aub_i965_batch_dword; +   iws->winsys.batch_reloc = aub_i965_batch_reloc; +   iws->winsys.batch_flush = aub_i965_batch_flush; +   iws->winsys.buffer_subdata_typed = aub_i965_buffer_subdata_typed; + +   iws->pipe_winsys = winsys; + +   iws->size = IWS_BATCHBUFFER_SIZE; + +   /* Create the i965simple context: +    */ +   return brw_create( winsys, +		      &iws->winsys, +		      0 ); +} diff --git a/src/mesa/pipe/xlib/xm_winsys_aub.h b/src/mesa/pipe/xlib/xm_winsys_aub.h new file mode 100644 index 0000000000..c0fe449107 --- /dev/null +++ b/src/mesa/pipe/xlib/xm_winsys_aub.h @@ -0,0 +1,67 @@ +/************************************************************************** + *  + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + *  + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + *  + **************************************************************************/ + +#ifndef AUB_WINSYS_H +#define AUB_WINSYS_H + +struct pipe_context; +struct pipe_winsys; +struct pipe_buffer_handle; +struct pipe_surface; + +struct pipe_winsys * +xmesa_create_pipe_winsys_aub( void ); + +void +xmesa_destroy_pipe_winsys_aub( struct pipe_winsys *winsys ); + + + +struct pipe_context * +xmesa_create_i965simple( struct pipe_winsys *winsys ); + + + +void xmesa_buffer_subdata_aub(struct pipe_winsys *winsys,  +			      struct pipe_buffer_handle *buf, +			      unsigned long offset,  +			      unsigned long size,  +			      const void *data, +			      unsigned aub_type, +			      unsigned aub_sub_type); + +void xmesa_commands_aub(struct pipe_winsys *winsys, +			unsigned *cmds, +			unsigned nr_dwords); + + +void xmesa_display_aub( /* struct pipe_winsys *winsys, */ +   struct pipe_surface *surface ); + +struct pipe_winsys *xmesa_get_pipe_winsys_aub(void); + +#endif  | 
