xm_winsys_aub.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00017  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
00018  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
00019  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
00020  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * The above copyright notice and this permission notice (including the
00023  * next paragraph) shall be included in all copies or substantial portions
00024  * of the Software.
00025  * 
00026  * 
00027  **************************************************************************/
00028 
00029 /*
00030  * Authors:
00031  *   Keith Whitwell
00032  *   Brian Paul
00033  */
00034 
00035 
00036 #include "glxheader.h"
00037 #include "xmesaP.h"
00038 
00039 #include "pipe/p_winsys.h"
00040 #include "pipe/p_inlines.h"
00041 #include "util/u_math.h"
00042 #include "util/u_memory.h"
00043 #include "i965simple/brw_winsys.h"
00044 #include "i965simple/brw_screen.h"
00045 #include "brw_aub.h"
00046 #include "xm_winsys_aub.h"
00047 
00048 
00049 
00050 struct aub_buffer {
00051    char *data;
00052    unsigned offset;
00053    unsigned size;
00054    unsigned refcount;
00055    unsigned map_count;
00056    boolean dump_on_unmap;
00057 };
00058 
00059 
00060 
00061 struct aub_pipe_winsys {
00062    struct pipe_winsys winsys;
00063 
00064    struct brw_aubfile *aubfile;
00065 
00066    /* This is simple, isn't it:
00067     */
00068    char *pool;
00069    unsigned size;
00070    unsigned used;
00071 };
00072 
00073 
00074 /* Turn a pipe winsys into an aub/pipe winsys:
00075  */
00076 static inline struct aub_pipe_winsys *
00077 aub_pipe_winsys( struct pipe_winsys *winsys )
00078 {
00079    return (struct aub_pipe_winsys *)winsys;
00080 }
00081 
00082 
00083 
00084 static INLINE struct aub_buffer *
00085 aub_bo( struct pipe_buffer *bo )
00086 {
00087    return (struct aub_buffer *)bo;
00088 }
00089 
00090 static INLINE struct pipe_buffer *
00091 pipe_bo( struct aub_buffer *bo )
00092 {
00093    return (struct pipe_buffer *)bo;
00094 }
00095 
00096 
00097 
00098 
00099 static void *aub_buffer_map(struct pipe_winsys *winsys, 
00100                               struct pipe_buffer *buf,
00101                               unsigned flags )
00102 {
00103    struct aub_buffer *sbo = aub_bo(buf);
00104 
00105    assert(sbo->data);
00106 
00107    if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
00108       sbo->dump_on_unmap = 1;
00109 
00110    sbo->map_count++;
00111    return sbo->data;
00112 }
00113 
00114 static void aub_buffer_unmap(struct pipe_winsys *winsys, 
00115                                struct pipe_buffer *buf)
00116 {
00117    struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00118    struct aub_buffer *sbo = aub_bo(buf);
00119 
00120    sbo->map_count--;
00121 
00122    if (sbo->map_count == 0 &&
00123        sbo->dump_on_unmap) {
00124 
00125       sbo->dump_on_unmap = 0;
00126 
00127       brw_aub_gtt_data( iws->aubfile, 
00128                         sbo->offset,
00129                         sbo->data,
00130                         sbo->size,
00131                         0,
00132                         0);
00133    }
00134 }
00135 
00136 
00137 static void
00138 aub_buffer_destroy(struct pipe_winsys *winsys,
00139                    struct pipe_buffer *buf)
00140 {
00141    free(buf);
00142 }
00143 
00144 
00145 void xmesa_buffer_subdata_aub(struct pipe_winsys *winsys, 
00146                               struct pipe_buffer *buf,
00147                               unsigned long offset, 
00148                               unsigned long size, 
00149                               const void *data,
00150                               unsigned aub_type,
00151                               unsigned aub_sub_type)
00152 {
00153    struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00154    struct aub_buffer *sbo = aub_bo(buf);
00155 
00156    assert(sbo->size > offset + size);
00157    memcpy(sbo->data + offset, data, size);
00158 
00159    brw_aub_gtt_data( iws->aubfile, 
00160                      sbo->offset + offset,
00161                      sbo->data + offset,
00162                      size,
00163                      aub_type,
00164                      aub_sub_type );
00165 }
00166 
00167 void xmesa_commands_aub(struct pipe_winsys *winsys,
00168                         unsigned *cmds,
00169                         unsigned nr_dwords)
00170 {
00171    struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00172    unsigned size = nr_dwords * 4;
00173 
00174    assert(iws->used + size < iws->size);
00175 
00176    brw_aub_gtt_cmds( iws->aubfile, 
00177                      AUB_BUF_START + iws->used,
00178                      cmds,
00179                      nr_dwords * sizeof(int) );
00180 
00181    iws->used += align(size, 4096);
00182 }
00183 
00184 
00185 static struct aub_pipe_winsys *global_winsys = NULL;
00186 
00187 void xmesa_display_aub( /* struct pipe_winsys *winsys, */
00188                        struct pipe_surface *surface )
00189 {
00190 //   struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00191    brw_aub_dump_bmp( global_winsys->aubfile, 
00192                      surface,
00193                      aub_bo(surface->buffer)->offset );
00194 }
00195 
00196 
00197 
00198 /* Pipe has no concept of pools.  We choose the tex/region pool
00199  * for all buffers.
00200  */
00201 static struct pipe_buffer *
00202 aub_buffer_create(struct pipe_winsys *winsys,
00203                   unsigned alignment,
00204                   unsigned usage,
00205                   unsigned size)
00206 {
00207    struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00208    struct aub_buffer *sbo = CALLOC_STRUCT(aub_buffer);
00209 
00210    sbo->refcount = 1;
00211 
00212    /* Could reuse buffers that are not referenced in current
00213     * batchbuffer.  Can't do that atm, so always reallocate:
00214     */
00215    assert(iws->used + size < iws->size);
00216    sbo->data = iws->pool + iws->used;
00217    sbo->offset = AUB_BUF_START + iws->used;
00218    iws->used += align(size, 4096);
00219 
00220    sbo->size = size;
00221 
00222    return pipe_bo(sbo);
00223 }
00224 
00225 
00226 static struct pipe_buffer *
00227 aub_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
00228 {
00229    struct aub_buffer *sbo;
00230 
00231    /* Lets hope this is meant for upload, not as a result!  
00232     */
00233    sbo = aub_bo(aub_buffer_create( winsys, 0, 0, 0 ));
00234 
00235    sbo->data = ptr;
00236    sbo->size = bytes;
00237 
00238    return pipe_bo(sbo);
00239 }
00240 
00241 
00242 /* The state tracker (should!) keep track of whether the fake
00243  * frontbuffer has been touched by any rendering since the last time
00244  * we copied its contents to the real frontbuffer.  Our task is easy:
00245  */
00246 static void
00247 aub_flush_frontbuffer( struct pipe_winsys *winsys,
00248                          struct pipe_surface *surf,
00249                          void *context_private)
00250 {
00251    xmesa_display_aub( surf );
00252 }
00253 
00254 static struct pipe_surface *
00255 aub_i915_surface_alloc(struct pipe_winsys *winsys)
00256 {
00257    struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
00258    if (surf) {
00259       surf->refcount = 1;
00260       surf->winsys = winsys;
00261    }
00262    return surf;
00263 }
00264 
00265 
00269 static INLINE unsigned
00270 round_up(unsigned n, unsigned multiple)
00271 {
00272    return (n + multiple - 1) & ~(multiple - 1);
00273 }
00274 
00275 static int
00276 aub_i915_surface_alloc_storage(struct pipe_winsys *winsys,
00277                                struct pipe_surface *surf,
00278                                unsigned width, unsigned height,
00279                                enum pipe_format format,
00280                                unsigned flags,
00281                                unsigned tex_usage)
00282 {
00283    const unsigned alignment = 64;
00284 
00285    surf->width = width;
00286    surf->height = height;
00287    surf->format = format;
00288    pf_get_block(format, &surf->block);
00289    surf->nblocksx = pf_get_nblocksx(&surf->block, width);
00290    surf->nblocksy = pf_get_nblocksy(&surf->block, height);
00291    surf->stride = round_up(surf->nblocksx * surf->block.size, alignment);
00292    surf->usage = flags;
00293 
00294    assert(!surf->buffer);
00295    surf->buffer = winsys->buffer_create(winsys, alignment,
00296                                         PIPE_BUFFER_USAGE_PIXEL,
00297                                         surf->stride * surf->nblocksy);
00298     if(!surf->buffer)
00299        return -1;
00300 
00301    return 0;
00302 }
00303 
00304 static void
00305 aub_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
00306 {
00307    struct pipe_surface *surf = *s;
00308    surf->refcount--;
00309    if (surf->refcount == 0) {
00310       if (surf->buffer)
00311          winsys_buffer_reference(winsys, &surf->buffer, NULL);
00312       free(surf);
00313    }
00314    *s = NULL;
00315 }
00316 
00317 
00318 
00319 static const char *
00320 aub_get_name( struct pipe_winsys *winsys )
00321 {
00322    return "Aub/xlib";
00323 }
00324 
00325 struct pipe_winsys *
00326 xmesa_create_pipe_winsys_aub( void )
00327 {
00328    struct aub_pipe_winsys *iws = CALLOC_STRUCT( aub_pipe_winsys );
00329    
00330    /* Fill in this struct with callbacks that pipe will need to
00331     * communicate with the window system, buffer manager, etc. 
00332     *
00333     * Pipe would be happy with a malloc based memory manager, but
00334     * the SwapBuffers implementation in this winsys driver requires
00335     * that rendering be done to an appropriate _DriBufferObject.  
00336     */
00337    iws->winsys.buffer_create = aub_buffer_create;
00338    iws->winsys.user_buffer_create = aub_user_buffer_create;
00339    iws->winsys.buffer_map = aub_buffer_map;
00340    iws->winsys.buffer_unmap = aub_buffer_unmap;
00341    iws->winsys.buffer_destroy = aub_buffer_destroy;
00342    iws->winsys.flush_frontbuffer = aub_flush_frontbuffer;
00343    iws->winsys.get_name = aub_get_name;
00344 
00345    iws->winsys.surface_alloc = aub_i915_surface_alloc;
00346    iws->winsys.surface_alloc_storage = aub_i915_surface_alloc_storage;
00347    iws->winsys.surface_release = aub_i915_surface_release;
00348 
00349    iws->aubfile = brw_aubfile_create();
00350    iws->size = AUB_BUF_SIZE;
00351    iws->pool = malloc(AUB_BUF_SIZE);
00352 
00353    /* HACK: static copy of this pointer:
00354     */
00355    assert(global_winsys == NULL);
00356    global_winsys = iws;
00357 
00358    return &iws->winsys;
00359 }
00360 
00361 
00362 void
00363 xmesa_destroy_pipe_winsys_aub( struct pipe_winsys *winsys )
00364 
00365 {
00366    struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
00367    brw_aub_destroy(iws->aubfile);
00368    free(iws->pool);
00369    free(iws);
00370 }
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 #define IWS_BATCHBUFFER_SIZE 1024
00379 
00380 struct aub_brw_winsys {
00381    struct brw_winsys winsys;   
00382    struct aub_context *aub;
00383                          
00384    struct pipe_winsys *pipe_winsys;
00385 
00386    unsigned batch_data[IWS_BATCHBUFFER_SIZE];
00387    unsigned batch_nr;
00388    unsigned batch_size;
00389    unsigned batch_alloc;
00390 };
00391 
00392 
00393 /* Turn a i965simple winsys into an aub/i965simple winsys:
00394  */
00395 static inline struct aub_brw_winsys *
00396 aub_brw_winsys( struct brw_winsys *sws )
00397 {
00398    return (struct aub_brw_winsys *)sws;
00399 }
00400 
00401 
00402 /* Simple batchbuffer interface:
00403  */
00404 
00405 static unsigned *aub_i965_batch_start( struct brw_winsys *sws,
00406                                          unsigned dwords,
00407                                          unsigned relocs )
00408 {
00409    struct aub_brw_winsys *iws = aub_brw_winsys(sws);
00410 
00411    if (iws->batch_size < iws->batch_nr + dwords)
00412       return NULL;
00413 
00414    iws->batch_alloc = iws->batch_nr + dwords;
00415    return (void *)1;                    /* not a valid pointer! */
00416 }
00417 
00418 static void aub_i965_batch_dword( struct brw_winsys *sws,
00419                                     unsigned dword )
00420 {
00421    struct aub_brw_winsys *iws = aub_brw_winsys(sws);
00422 
00423    assert(iws->batch_nr < iws->batch_alloc);
00424    iws->batch_data[iws->batch_nr++] = dword;
00425 }
00426 
00427 static void aub_i965_batch_reloc( struct brw_winsys *sws,
00428                              struct pipe_buffer *buf,
00429                              unsigned access_flags,
00430                              unsigned delta )
00431 {
00432    struct aub_brw_winsys *iws = aub_brw_winsys(sws);
00433 
00434    assert(iws->batch_nr < iws->batch_alloc);
00435    iws->batch_data[iws->batch_nr++] = aub_bo(buf)->offset + delta;
00436 }
00437 
00438 static unsigned aub_i965_get_buffer_offset( struct brw_winsys *sws,
00439                                             struct pipe_buffer *buf,
00440                                             unsigned access_flags )
00441 {
00442    return aub_bo(buf)->offset;
00443 }
00444 
00445 static void aub_i965_batch_end( struct brw_winsys *sws )
00446 {
00447    struct aub_brw_winsys *iws = aub_brw_winsys(sws);
00448 
00449    assert(iws->batch_nr <= iws->batch_alloc);
00450    iws->batch_alloc = 0;
00451 }
00452 
00453 static void aub_i965_batch_flush( struct brw_winsys *sws,
00454                                     struct pipe_fence_handle **fence )
00455 {
00456    struct aub_brw_winsys *iws = aub_brw_winsys(sws);
00457    assert(iws->batch_nr <= iws->batch_size);
00458 
00459    if (iws->batch_nr) {
00460       xmesa_commands_aub( iws->pipe_winsys,
00461                           iws->batch_data,
00462                           iws->batch_nr );
00463    }
00464 
00465    iws->batch_nr = 0;
00466 }
00467 
00468 
00469 
00470 static void aub_i965_buffer_subdata_typed(struct brw_winsys *winsys, 
00471                                             struct pipe_buffer *buf,
00472                                             unsigned long offset, 
00473                                             unsigned long size, 
00474                                             const void *data,
00475                                             unsigned data_type)
00476 {
00477    struct aub_brw_winsys *iws = aub_brw_winsys(winsys);
00478    unsigned aub_type = DW_GENERAL_STATE;
00479    unsigned aub_sub_type;
00480 
00481    switch (data_type) {
00482    case BRW_CC_VP:
00483       aub_sub_type = DWGS_COLOR_CALC_VIEWPORT_STATE;
00484       break;
00485    case BRW_CC_UNIT:
00486       aub_sub_type = DWGS_COLOR_CALC_STATE;
00487       break;
00488    case BRW_WM_PROG:
00489       aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
00490       break;
00491    case BRW_SAMPLER_DEFAULT_COLOR:
00492       aub_sub_type = DWGS_SAMPLER_DEFAULT_COLOR;
00493       break;
00494    case BRW_SAMPLER:
00495       aub_sub_type = DWGS_SAMPLER_STATE;
00496       break;
00497    case BRW_WM_UNIT:
00498       aub_sub_type = DWGS_WINDOWER_IZ_STATE;
00499       break;
00500    case BRW_SF_PROG:
00501       aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
00502       break;
00503    case BRW_SF_VP:
00504       aub_sub_type = DWGS_STRIPS_FANS_VIEWPORT_STATE;
00505       break;
00506    case BRW_SF_UNIT:
00507       aub_sub_type = DWGS_STRIPS_FANS_STATE;
00508       break;
00509    case BRW_VS_UNIT:
00510       aub_sub_type = DWGS_VERTEX_SHADER_STATE;
00511       break;
00512    case BRW_VS_PROG:
00513       aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
00514       break;
00515    case BRW_GS_UNIT:
00516       aub_sub_type = DWGS_GEOMETRY_SHADER_STATE;
00517       break;
00518    case BRW_GS_PROG:
00519       aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
00520       break;
00521    case BRW_CLIP_VP:
00522       aub_sub_type = DWGS_CLIPPER_VIEWPORT_STATE;
00523       break;
00524    case BRW_CLIP_UNIT:
00525       aub_sub_type = DWGS_CLIPPER_STATE;
00526       break;
00527    case BRW_CLIP_PROG:
00528       aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
00529       break;
00530    case BRW_SS_SURFACE:
00531       aub_type = DW_SURFACE_STATE;
00532       aub_sub_type = DWSS_SURFACE_STATE; 
00533       break;
00534    case BRW_SS_SURF_BIND:
00535       aub_type = DW_SURFACE_STATE;
00536       aub_sub_type = DWSS_BINDING_TABLE_STATE; 
00537       break;
00538    case BRW_CONSTANT_BUFFER:
00539       aub_type = DW_CONSTANT_URB_ENTRY;
00540       aub_sub_type = 0; 
00541       break;
00542 
00543    default:
00544       assert(0);
00545       break;
00546    }
00547 
00548    xmesa_buffer_subdata_aub( iws->pipe_winsys,
00549                              buf,
00550                              offset,
00551                              size,
00552                              data,
00553                              aub_type,
00554                              aub_sub_type );
00555 }
00556    
00560 struct pipe_context *
00561 xmesa_create_i965simple( struct pipe_winsys *winsys )
00562 {
00563    struct aub_brw_winsys *iws = CALLOC_STRUCT( aub_brw_winsys );
00564    struct pipe_screen *screen = brw_create_screen(winsys, 0/* XXX pci_id */);
00565    
00566    /* Fill in this struct with callbacks that i965simple will need to
00567     * communicate with the window system, buffer manager, etc. 
00568     */
00569    iws->winsys.batch_start = aub_i965_batch_start;
00570    iws->winsys.batch_dword = aub_i965_batch_dword;
00571    iws->winsys.batch_reloc = aub_i965_batch_reloc;
00572    iws->winsys.batch_end = aub_i965_batch_end;
00573    iws->winsys.batch_flush = aub_i965_batch_flush;
00574    iws->winsys.buffer_subdata_typed = aub_i965_buffer_subdata_typed;
00575    iws->winsys.get_buffer_offset = aub_i965_get_buffer_offset;
00576 
00577    iws->pipe_winsys = winsys;
00578 
00579    iws->batch_size = IWS_BATCHBUFFER_SIZE;
00580 
00581    /* Create the i965simple context:
00582     */
00583    return brw_create( screen,
00584                       &iws->winsys,
00585                       0 );
00586 }

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4