diff options
Diffstat (limited to 'src/mesa/pipe')
44 files changed, 2666 insertions, 147 deletions
diff --git a/src/mesa/pipe/Makefile b/src/mesa/pipe/Makefile index 5099b65885..e4b72e4940 100644 --- a/src/mesa/pipe/Makefile +++ b/src/mesa/pipe/Makefile @@ -1,4 +1,3 @@ - TOP = ../../.. include $(TOP)/configs/current @@ -7,7 +6,7 @@ ifeq ($(CONFIG_NAME), linux-cell) CELL_DIR = cell endif -SUBDIRS = softpipe i915simple nv40 nv50 failover $(CELL_DIR) +SUBDIRS = softpipe i915simple nv40 nv50 failover pipebuffer $(CELL_DIR) default: subdirs diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c index e4c257a0ee..c50376f11f 100644 --- a/src/mesa/pipe/draw/draw_clip.c +++ b/src/mesa/pipe/draw/draw_clip.c @@ -415,6 +415,13 @@ static void clip_reset_stipple_counter( struct draw_stage *stage ) } +static void clip_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Allocate a new clipper stage. * \return pointer to new stage object @@ -432,6 +439,7 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw ) clipper->stage.tri = clip_tri; clipper->stage.end = clip_end; clipper->stage.reset_stipple_counter = clip_reset_stipple_counter; + clipper->stage.destroy = clip_destroy; clipper->plane = draw->plane; diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c index e7997180b5..6792a06a4e 100644 --- a/src/mesa/pipe/draw/draw_context.c +++ b/src/mesa/pipe/draw/draw_context.c @@ -42,7 +42,7 @@ struct draw_context *draw_create( void ) struct draw_context *draw = CALLOC_STRUCT( draw_context ); #if defined(__i386__) || defined(__386__) - draw->use_sse = GETENV( "GALLIUM_SSE" ) != NULL; + draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; #else draw->use_sse = FALSE; #endif @@ -85,6 +85,7 @@ struct draw_context *draw_create( void ) draw->prim = ~0; /* != any of PIPE_PRIM_x */ draw_vertex_cache_invalidate( draw ); + draw_set_mapped_element_buffer( draw, 0, NULL ); return draw; } @@ -92,6 +93,16 @@ struct draw_context *draw_create( void ) void draw_destroy( struct draw_context *draw ) { + draw->pipeline.wide->destroy( draw->pipeline.wide ); + draw->pipeline.unfilled->destroy( draw->pipeline.unfilled ); + draw->pipeline.twoside->destroy( draw->pipeline.twoside ); + draw->pipeline.offset->destroy( draw->pipeline.offset ); + draw->pipeline.clip->destroy( draw->pipeline.clip ); + draw->pipeline.flatshade->destroy( draw->pipeline.flatshade ); + draw->pipeline.cull->destroy( draw->pipeline.cull ); + draw->pipeline.feedback->destroy( draw->pipeline.feedback ); + draw->pipeline.validate->destroy( draw->pipeline.validate ); + draw->pipeline.rasterize->destroy( draw->pipeline.rasterize ); FREE( draw->vcache.vertex[0] ); /* Frees all the vertices. */ FREE( draw ); } diff --git a/src/mesa/pipe/draw/draw_cull.c b/src/mesa/pipe/draw/draw_cull.c index f898834ba5..9bd53f45f2 100644 --- a/src/mesa/pipe/draw/draw_cull.c +++ b/src/mesa/pipe/draw/draw_cull.c @@ -116,6 +116,14 @@ static void cull_reset_stipple_counter( struct draw_stage *stage ) stage->next->reset_stipple_counter( stage->next ); } + +static void cull_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Create a new polygon culling stage. */ @@ -133,6 +141,7 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw ) cull->stage.tri = cull_tri; cull->stage.end = cull_end; cull->stage.reset_stipple_counter = cull_reset_stipple_counter; + cull->stage.destroy = cull_destroy; return &cull->stage; } diff --git a/src/mesa/pipe/draw/draw_feedback.c b/src/mesa/pipe/draw/draw_feedback.c index b9906e5b4b..aea6a8184c 100644 --- a/src/mesa/pipe/draw/draw_feedback.c +++ b/src/mesa/pipe/draw/draw_feedback.c @@ -224,6 +224,12 @@ static void feedback_reset_stipple_counter( struct draw_stage *stage ) } +static void feedback_destroy( struct draw_stage *stage ) +{ + FREE( stage ); +} + + /** * Create feedback drawing stage. */ @@ -239,6 +245,7 @@ struct draw_stage *draw_feedback_stage( struct draw_context *draw ) feedback->stage.tri = feedback_tri; feedback->stage.end = feedback_end; feedback->stage.reset_stipple_counter = feedback_reset_stipple_counter; + feedback->stage.destroy = feedback_destroy; return &feedback->stage; } diff --git a/src/mesa/pipe/draw/draw_flatshade.c b/src/mesa/pipe/draw/draw_flatshade.c index d46e53f2be..d7551e7948 100644 --- a/src/mesa/pipe/draw/draw_flatshade.c +++ b/src/mesa/pipe/draw/draw_flatshade.c @@ -127,6 +127,13 @@ static void flatshade_reset_stipple_counter( struct draw_stage *stage ) } +static void flatshade_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Create flatshading drawing stage. */ @@ -144,6 +151,7 @@ struct draw_stage *draw_flatshade_stage( struct draw_context *draw ) flatshade->tri = flatshade_tri; flatshade->end = flatshade_end; flatshade->reset_stipple_counter = flatshade_reset_stipple_counter; + flatshade->destroy = flatshade_destroy; return flatshade; } diff --git a/src/mesa/pipe/draw/draw_linestipple.c b/src/mesa/pipe/draw/draw_linestipple.c index 1fac1ebe66..5f0db99b23 100644 --- a/src/mesa/pipe/draw/draw_linestipple.c +++ b/src/mesa/pipe/draw/draw_linestipple.c @@ -241,12 +241,18 @@ static void stipple_begin( struct clip_pipe_stage *stage ) } - static void stipple_end( struct clip_pipe_stage *stage ) { stage->next->end( stage->next ); } + +static void stipple_destroy( struct clip_pipe_stage *stage ) +{ + FREE( stage ); +} + + struct clip_pipe_stage *clip_pipe_stipple( struct clip_pipeline *pipe ) { struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage); @@ -261,6 +267,7 @@ struct clip_pipe_stage *clip_pipe_stipple( struct clip_pipeline *pipe ) stipple->stage.tri = clip_passthrough_tri; stipple->stage.reset_tmps = clip_pipe_reset_tmps; stipple->stage.end = stipple_end; + stipple->stage.destroy = stipple_destroy; return &stipple->stage; } diff --git a/src/mesa/pipe/draw/draw_offset.c b/src/mesa/pipe/draw/draw_offset.c index 6acc7cbcd2..f8a01db3dd 100644 --- a/src/mesa/pipe/draw/draw_offset.c +++ b/src/mesa/pipe/draw/draw_offset.c @@ -151,6 +151,13 @@ static void offset_reset_stipple_counter( struct draw_stage *stage ) } +static void offset_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Create polygon offset drawing stage. */ @@ -168,6 +175,7 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw ) offset->stage.tri = offset_tri; offset->stage.end = offset_end; offset->stage.reset_stipple_counter = offset_reset_stipple_counter; + offset->stage.destroy = offset_destroy; return &offset->stage; } diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h index 53d7451113..ca5ca7b3c9 100644 --- a/src/mesa/pipe/draw/draw_private.h +++ b/src/mesa/pipe/draw/draw_private.h @@ -124,6 +124,8 @@ struct draw_stage void (*reset_tmps)( struct draw_stage * ); void (*reset_stipple_counter)( struct draw_stage * ); + + void (*destroy)( struct draw_stage * ); }; diff --git a/src/mesa/pipe/draw/draw_twoside.c b/src/mesa/pipe/draw/draw_twoside.c index d987b00598..00b4ee45cd 100644 --- a/src/mesa/pipe/draw/draw_twoside.c +++ b/src/mesa/pipe/draw/draw_twoside.c @@ -146,6 +146,13 @@ static void twoside_reset_stipple_counter( struct draw_stage *stage ) } +static void twoside_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Create twoside pipeline stage. */ @@ -163,6 +170,7 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw ) twoside->stage.tri = twoside_tri; twoside->stage.end = twoside_end; twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter; + twoside->stage.destroy = twoside_destroy; return &twoside->stage; } diff --git a/src/mesa/pipe/draw/draw_unfilled.c b/src/mesa/pipe/draw/draw_unfilled.c index 6cab086a45..786826b33c 100644 --- a/src/mesa/pipe/draw/draw_unfilled.c +++ b/src/mesa/pipe/draw/draw_unfilled.c @@ -168,6 +168,13 @@ static void unfilled_reset_stipple_counter( struct draw_stage *stage ) } +static void unfilled_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + /** * Create unfilled triangle stage. */ @@ -186,6 +193,7 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw ) unfilled->stage.tri = unfilled_tri; unfilled->stage.end = unfilled_end; unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter; + unfilled->stage.destroy = unfilled_destroy; return &unfilled->stage; } diff --git a/src/mesa/pipe/draw/draw_validate.c b/src/mesa/pipe/draw/draw_validate.c index 4e8f986b27..8ce4a926e2 100644 --- a/src/mesa/pipe/draw/draw_validate.c +++ b/src/mesa/pipe/draw/draw_validate.c @@ -110,6 +110,10 @@ static void validate_begin( struct draw_stage *stage ) } +static void validate_destroy( struct draw_stage *stage ) +{ + FREE( stage ); +} /** @@ -127,6 +131,7 @@ struct draw_stage *draw_validate_stage( struct draw_context *draw ) stage->tri = NULL; stage->end = NULL; stage->reset_stipple_counter = NULL; + stage->destroy = validate_destroy; return stage; } diff --git a/src/mesa/pipe/draw/draw_vbuf.c b/src/mesa/pipe/draw/draw_vbuf.c index d00cdec56c..d010aaba07 100644 --- a/src/mesa/pipe/draw/draw_vbuf.c +++ b/src/mesa/pipe/draw/draw_vbuf.c @@ -369,6 +369,15 @@ vbuf_reset_stipple_counter( struct draw_stage *stage ) } +static void vbuf_destroy( struct draw_stage *stage ) +{ + struct vbuf_stage *vbuf = vbuf_stage( stage ); + + FREE( vbuf->indices ); + FREE( stage ); +} + + /** * Create a new primitive vbuf/render stage. */ @@ -384,12 +393,12 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw, vbuf->stage.tri = vbuf_first_tri; vbuf->stage.end = vbuf_end; vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter; + vbuf->stage.destroy = vbuf_destroy; vbuf->render = render; assert(render->max_indices < UNDEFINED_VERTEX_ID); vbuf->max_indices = render->max_indices; - /* FIXME: free this memory on takedown */ vbuf->indices = MALLOC( vbuf->max_indices ); vbuf->vertices = NULL; diff --git a/src/mesa/pipe/draw/draw_vertex_fetch.c b/src/mesa/pipe/draw/draw_vertex_fetch.c index e0759c2e9a..7d983ebd29 100644 --- a/src/mesa/pipe/draw/draw_vertex_fetch.c +++ b/src/mesa/pipe/draw/draw_vertex_fetch.c @@ -80,6 +80,7 @@ fetch_attrib4(const void *ptr, enum pipe_format format, float attrib[4]) break; case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: attrib[0] = (float) ((unsigned char *) ptr)[2] / 255.0f; attrib[1] = (float) ((unsigned char *) ptr)[1] / 255.0f; attrib[2] = (float) ((unsigned char *) ptr)[0] / 255.0f; diff --git a/src/mesa/pipe/draw/draw_wide_prims.c b/src/mesa/pipe/draw/draw_wide_prims.c index 494a2bc619..a56c9b8893 100644 --- a/src/mesa/pipe/draw/draw_wide_prims.c +++ b/src/mesa/pipe/draw/draw_wide_prims.c @@ -315,7 +315,6 @@ static void wide_begin( struct draw_stage *stage ) } - static void wide_end( struct draw_stage *stage ) { stage->next->end( stage->next ); @@ -327,6 +326,14 @@ static void draw_reset_stipple_counter( struct draw_stage *stage ) stage->next->reset_stipple_counter( stage->next ); } + +static void wide_destroy( struct draw_stage *stage ) +{ + draw_free_tmps( stage ); + FREE( stage ); +} + + struct draw_stage *draw_wide_stage( struct draw_context *draw ) { struct wide_stage *wide = CALLOC_STRUCT(wide_stage); @@ -341,6 +348,7 @@ struct draw_stage *draw_wide_stage( struct draw_context *draw ) wide->stage.tri = passthrough_tri; wide->stage.end = wide_end; wide->stage.reset_stipple_counter = draw_reset_stipple_counter; + wide->stage.destroy = wide_destroy; return &wide->stage; } diff --git a/src/mesa/pipe/i915simple/i915_prim_emit.c b/src/mesa/pipe/i915simple/i915_prim_emit.c index 0a8be79ae4..c50a591589 100644 --- a/src/mesa/pipe/i915simple/i915_prim_emit.c +++ b/src/mesa/pipe/i915simple/i915_prim_emit.c @@ -194,6 +194,11 @@ static void reset_stipple_counter( struct draw_stage *stage ) { } +static void render_destroy( struct draw_stage *stage ) +{ + FREE( stage ); +} + /** * Create a new primitive setup/render stage. This gets plugged into @@ -211,6 +216,7 @@ struct draw_stage *i915_draw_render_stage( struct i915_context *i915 ) setup->stage.tri = setup_tri; setup->stage.end = setup_end; setup->stage.reset_stipple_counter = reset_stipple_counter; + setup->stage.destroy = render_destroy; return &setup->stage; } diff --git a/src/mesa/pipe/i915simple/i915_prim_vbuf.c b/src/mesa/pipe/i915simple/i915_prim_vbuf.c index 08ac5b672c..571ad40595 100644 --- a/src/mesa/pipe/i915simple/i915_prim_vbuf.c +++ b/src/mesa/pipe/i915simple/i915_prim_vbuf.c @@ -99,7 +99,7 @@ i915_vbuf_render_allocate_vertices( struct vbuf_render *render, /* FIXME: handle failure */ assert(!i915->vbo); - i915->vbo = winsys->buffer_create(winsys, 64); + i915->vbo = winsys->buffer_create(winsys, 64, 0, 0); winsys->buffer_data( winsys, i915->vbo, size, NULL, I915_BUFFER_USAGE_LIT_VERTEX ); diff --git a/src/mesa/pipe/i915simple/i915_texture.c b/src/mesa/pipe/i915simple/i915_texture.c index 1ca2815dfb..59e8db8a95 100644 --- a/src/mesa/pipe/i915simple/i915_texture.c +++ b/src/mesa/pipe/i915simple/i915_texture.c @@ -496,7 +496,8 @@ i915_texture_create(struct pipe_context *pipe, struct pipe_texture **pt) if (i915->flags.is_i945 ? i945_miptree_layout(pipe, tex) : i915_miptree_layout(pipe, tex)) { tex->buffer = pipe->winsys->buffer_create(pipe->winsys, - PIPE_SURFACE_FLAG_TEXTURE); + PIPE_SURFACE_FLAG_TEXTURE, + 0, 0); if (tex->buffer) pipe->winsys->buffer_data(pipe->winsys, tex->buffer, diff --git a/src/mesa/pipe/p_defines.h b/src/mesa/pipe/p_defines.h index a853605486..8dce3aba90 100644 --- a/src/mesa/pipe/p_defines.h +++ b/src/mesa/pipe/p_defines.h @@ -170,8 +170,12 @@ /** * Buffer access flags */ -#define PIPE_BUFFER_FLAG_READ 0x1 -#define PIPE_BUFFER_FLAG_WRITE 0x2 +#define PIPE_BUFFER_FLAG_READ 0x1 +#define PIPE_BUFFER_FLAG_WRITE 0x2 +#define PIPE_BUFFER_FLAG_MEM_LOCAL 0x4 +#define PIPE_BUFFER_FLAG_CACHED 0x8 +#define PIPE_BUFFER_FLAG_CUSTOM (1<<16) + /** diff --git a/src/mesa/pipe/p_util.h b/src/mesa/pipe/p_util.h index 7897bc90e4..3c5e98453c 100644 --- a/src/mesa/pipe/p_util.h +++ b/src/mesa/pipe/p_util.h @@ -114,6 +114,7 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) #define Elements(x) sizeof(x)/sizeof(*(x)) +#define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER)) /** * Return a pointer aligned to next multiple of 16 bytes. @@ -204,8 +205,8 @@ static INLINE unsigned char float_to_ubyte( float f ) static INLINE unsigned pack_ui32_float4( float a, float b, - float d, - float c ) + float c, + float d ) { return pack_ub4( float_to_ubyte(a), float_to_ubyte(b), @@ -300,4 +301,8 @@ static INLINE float LOG2(float val) #define CEILF(x) ((float) ceil(x)) #endif +/* Convenient... + */ +extern void _mesa_printf(const char *str, ...); + #endif diff --git a/src/mesa/pipe/p_winsys.h b/src/mesa/pipe/p_winsys.h index 438e8bdb63..f2be7655f4 100644 --- a/src/mesa/pipe/p_winsys.h +++ b/src/mesa/pipe/p_winsys.h @@ -42,6 +42,13 @@ /** Opaque type for a buffer */ struct pipe_buffer_handle; +/** Opaque type */ +struct pipe_fence_handle; + +struct pipe_region; +struct pipe_surface; + + /** * Gallium3D drivers are (meant to be!) independent of both GL and the * window system. The window system provides a buffer manager and a @@ -52,14 +59,6 @@ struct pipe_buffer_handle; * driver and the hardware driver about the format of command buffers, * etc. */ - - -struct pipe_region; -struct pipe_surface; - -/** Opaque type */ -struct pipe_buffer_handle; - struct pipe_winsys { /** Returns name of this winsys interface */ @@ -96,6 +95,7 @@ struct pipe_winsys void (*surface_release)(struct pipe_winsys *ws, struct pipe_surface **s); + /** * The buffer manager is modeled after the dri_bufmgr interface, which * in turn is modeled after the ARB_vertex_buffer_object extension, @@ -104,15 +104,16 @@ struct pipe_winsys * systems must then implement that interface (rather than the * other way around...). */ - struct pipe_buffer_handle *(*buffer_create)(struct pipe_winsys *sws, - unsigned alignment ); + struct pipe_buffer_handle *(*buffer_create)( struct pipe_winsys *sws, + unsigned alignment, + unsigned flags, + unsigned hint ); /** Create a buffer that wraps user-space data */ struct pipe_buffer_handle *(*user_buffer_create)(struct pipe_winsys *sws, void *ptr, unsigned bytes); - /** * Map the entire data store of a buffer object into the client's address. * flags is bitmask of PIPE_BUFFER_FLAG_READ/WRITE. @@ -135,25 +136,64 @@ struct pipe_winsys * usage is a bitmask of PIPE_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This * usage argument is only an optimization hint, not a guarantee, therefore * proper behavior must be observed in all circumstances. + * + * Returns zero on success. */ - void (*buffer_data)(struct pipe_winsys *sws, + int (*buffer_data)(struct pipe_winsys *sws, struct pipe_buffer_handle *buf, unsigned size, const void *data, unsigned usage); - /** Modify some or all of the data contained in a buffer's data store */ - void (*buffer_subdata)(struct pipe_winsys *sws, - struct pipe_buffer_handle *buf, - unsigned long offset, - unsigned long size, - const void *data); - - /** Query some or all of the data contained in a buffer's data store */ - void (*buffer_get_subdata)(struct pipe_winsys *sws, - struct pipe_buffer_handle *buf, - unsigned long offset, - unsigned long size, - void *data); + /** + * Modify some or all of the data contained in a buffer's data store. + * + * Returns zero on success. + */ + int (*buffer_subdata)(struct pipe_winsys *sws, + struct pipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + const void *data); + + /** + * Query some or all of the data contained in a buffer's data store. + * + * Returns zero on success. + */ + int (*buffer_get_subdata)(struct pipe_winsys *sws, + struct pipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + void *data); + + + /** Set ptr = buf, with reference counting */ + void (*fence_reference)( struct pipe_winsys *sws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence ); + + /** + * Checks whether the fence has been signalled. + * + * The meaning of flag is pipe-driver specific. + * + * Returns zero if it has. + */ + int (*fence_signalled)( struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag ); + + /** + * Wait for the fence to finish. + * + * The meaning of flag is pipe-driver specific. + * + * Returns zero on success. + */ + int (*fence_finish)( struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag ); + }; diff --git a/src/mesa/pipe/pipebuffer/Makefile b/src/mesa/pipe/pipebuffer/Makefile new file mode 100644 index 0000000000..061d8a060f --- /dev/null +++ b/src/mesa/pipe/pipebuffer/Makefile @@ -0,0 +1,27 @@ + +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = pipebuffer + + +DRIVER_SOURCES = \ + pb_buffer.c \ + pb_buffer_client.c \ + pb_buffer_handle.c \ + pb_buffer_fenced.c \ + pb_buffer_malloc.c \ + pb_buffer_null.c \ + pb_bufmgr_fenced.c \ + pb_bufmgr_mm.c \ + pb_bufmgr_pool.c + +C_SOURCES = \ + $(DRIVER_SOURCES) + +ASM_SOURCES = + +include ../Makefile.template + +symlinks: + diff --git a/src/mesa/pipe/pipebuffer/linked_list.h b/src/mesa/pipe/pipebuffer/linked_list.h new file mode 100644 index 0000000000..e99817fb13 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/linked_list.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * Copyright 2006 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. + * + **************************************************************************/ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ + +#ifndef LINKED_LIST_H_ +#define LINKED_LIST_H_ + + +#include <stddef.h> + + +struct list_head +{ + struct list_head *prev; + struct list_head *next; +}; + + +#define LIST_INITHEAD(__item) \ + do { \ + (__item)->prev = (__item); \ + (__item)->next = (__item); \ + } while (0) + +#define LIST_ADD(__item, __list) \ + do { \ + (__item)->prev = (__list); \ + (__item)->next = (__list)->next; \ + (__list)->next->prev = (__item); \ + (__list)->next = (__item); \ + } while (0) + +#define LIST_ADDTAIL(__item, __list) \ + do { \ + (__item)->next = (__list); \ + (__item)->prev = (__list)->prev; \ + (__list)->prev->next = (__item); \ + (__list)->prev = (__item); \ + } while(0) + +#define LIST_DEL(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + } while(0) + +#define LIST_DELINIT(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + (__item)->next = (__item); \ + (__item)->prev = (__item); \ + } while(0) + +#define LIST_ENTRY(__type, __item, __field) \ + ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + + +#endif /*LINKED_LIST_H_*/ diff --git a/src/mesa/pipe/pipebuffer/pb_buffer.c b/src/mesa/pipe/pipebuffer/pb_buffer.c new file mode 100644 index 0000000000..99c960b697 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer.c @@ -0,0 +1,52 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Buffer implementation. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include "pb_buffer.h" + + +void +buffer_reference(struct pipe_buffer **dst, + struct pipe_buffer *src) +{ + if(*dst != src) { + if (src) + src->vtbl->reference(src); + + if (*dst) + (*dst)->vtbl->release(*dst); + + *dst = src; + } +} diff --git a/src/mesa/pipe/pipebuffer/pb_buffer.h b/src/mesa/pipe/pipebuffer/pb_buffer.h new file mode 100644 index 0000000000..0523531395 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer.h @@ -0,0 +1,175 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Generic code for buffers. + * + * Behind a pipe buffle handle there can be DMA buffers, client (or user) + * buffers, regular malloced buffers, etc. This file provides an abstract base + * buffer handle that allows the driver to cope with all those kinds of buffers + * in a more flexible way. + * + * There is no obligation of a winsys driver to use this library. And a pipe + * driver should be completly agnostic about it. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + +#ifndef PB_BUFFER_H_ +#define PB_BUFFER_H_ + + +#include <assert.h> +#include <stdlib.h> + + +struct pipe_buffer_vtbl; + + +/** + * Base class for all pipe buffers. + */ +struct pipe_buffer +{ + /** + * Pointer to the virtual function table. + * + * Avoid accessing this table directly. Use the inline functions below + * instead to avoid mistakes. + */ + const struct pipe_buffer_vtbl *vtbl; +}; + + +/** + * Virtual function table for the buffer storage operations. + * + * Note that creation is not done through this table. + */ +struct pipe_buffer_vtbl +{ + /** + * Add a reference to the buffer. + * + * This method can be a no-op for buffers that don't need reference + * counting. + */ + void (*reference)( struct pipe_buffer *buf ); + + /** + * Release a reference to this buffer and destroy it. + */ + void (*release)( struct pipe_buffer *buf ); + + /** + * Map the entire data store of a buffer object into the client's address. + * flags is bitmask of PIPE_BUFFER_FLAG_READ/WRITE. + */ + void *(*map)( struct pipe_buffer *buf, + unsigned flags ); + + void (*unmap)( struct pipe_buffer *buf ); + + /** + * Get the base buffer and the offset. + * + * A buffer can be subdivided in smaller buffers. This method should return + * the underlaying buffer, and the relative offset. + * + * Buffers without an underlaying base buffer should return themselves, with + * a zero offset. + * + * Note that this will increase the reference count of the base buffer. + */ + void (*get_base_buffer)( struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset ); +}; + + +/** *dst = src with reference counting */ +void +buffer_reference(struct pipe_buffer **dst, + struct pipe_buffer *src); + + +static inline void +buffer_release(struct pipe_buffer *buf) +{ + assert(buf); + buf->vtbl->release(buf); +} + + +static inline void * +buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + assert(buf); + return buf->vtbl->map(buf, flags); +} + + +static inline void +buffer_unmap(struct pipe_buffer *buf) +{ + assert(buf); + buf->vtbl->unmap(buf); +} + + +static inline void +buffer_get_base_buffer( struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset ) +{ + buf->vtbl->get_base_buffer(buf, base_buf, offset); +} + + +/** Placeholder for empty buffers. */ +extern struct pipe_buffer null_buffer; + + +/** + * Client buffers (also designated as user buffers) are just for convenience + * of the state tracker, so that it can masquerade its own data as a buffer. + */ +struct pipe_buffer * +client_buffer_create(void *data); + + +/** + * Malloc-based buffer to store data that can't be used by the graphics + * hardware. + */ +struct pipe_buffer * +malloc_buffer_create(unsigned size); + + +#endif /*PB_BUFFER_H_*/ diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_client.c b/src/mesa/pipe/pipebuffer/pb_buffer_client.c new file mode 100644 index 0000000000..bb7f5a9a94 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_client.c @@ -0,0 +1,123 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Implementation of client buffer (also designated as "user buffers"), which + * are just state-tracker owned data masqueraded as buffers. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include "pb_buffer.h" + + +struct client_buffer +{ + struct pipe_buffer base; + void *data; +}; + + +extern const struct pipe_buffer_vtbl client_buffer_vtbl; + + +static inline struct client_buffer * +client_buffer(struct pipe_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &client_buffer_vtbl); + return (struct client_buffer *)buf; +} + + +static void +client_buffer_reference(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +client_buffer_release(struct pipe_buffer *buf) +{ + assert(buf); + free(buf); +} + + +static void * +client_buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + return client_buffer(buf)->data; +} + + +static void +client_buffer_unmap(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +client_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +const struct pipe_buffer_vtbl +client_buffer_vtbl = { + client_buffer_reference, + client_buffer_release, + client_buffer_map, + client_buffer_unmap, + client_buffer_get_base_buffer +}; + + +struct pipe_buffer * +client_buffer_create(void *data) +{ + struct client_buffer *buf; + + buf = (struct client_buffer *)malloc(sizeof(struct client_buffer)); + if(!buf) + return NULL; + + buf->base.vtbl = &client_buffer_vtbl; + + buf->data = data; + + return &buf->base; +} diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_fenced.c b/src/mesa/pipe/pipebuffer/pb_buffer_fenced.c new file mode 100644 index 0000000000..e69f88a323 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_fenced.c @@ -0,0 +1,316 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Implementation of fenced buffers. + * + * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com> + * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + + +#include <assert.h> +#include <stdlib.h> +#include <unistd.h> + +#include "main/imports.h" +#include "glapi/glthread.h" +#include "linked_list.h" + +#include "p_winsys.h" + +#include "pb_buffer.h" +#include "pb_buffer_fenced.h" + + +/** + * Convenience macro (type safe). + */ +#define SUPER(__derived) (&(__derived)->base) + + +struct fenced_buffer_list +{ + _glthread_Mutex mutex; + + struct pipe_winsys *winsys; + + size_t numDelayed; + size_t checkDelayed; + + struct list_head delayed; +}; + + +/** + * Wrapper around a pipe buffer which adds fencing and reference counting. + */ +struct fenced_buffer +{ + struct pipe_buffer base; + + struct pipe_buffer *buffer; + + unsigned refcount; + struct pipe_fence_handle *fence; + + struct list_head head; + struct fenced_buffer_list *list; +}; + + +static inline struct fenced_buffer * +fenced_buffer(struct pipe_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &fenced_buffer_vtbl); + return (struct fenced_buffer *)buf; +} + + +static void +_fenced_buffer_destroy(struct fenced_buffer *fenced_buf) +{ + buffer_release(fenced_buf->buffer); + free(fenced_buf); +} + + +static void +_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, + int wait) +{ + struct pipe_winsys *winsys = fenced_list->winsys; + struct fenced_buffer *fenced_buf; + struct list_head *list, *prev; + int signaled = -1; + int i; + + list = fenced_list->delayed.next; + + if (fenced_list->numDelayed > 3) { + for (i = 0; i < fenced_list->numDelayed; i += 3) { + list = list->next; + } + } + + prev = list->prev; + for (; list != &fenced_list->delayed; list = prev, prev = list->prev) { + + fenced_buf = LIST_ENTRY(struct fenced_buffer, list, head); + + if (signaled != 0) { + if (wait) { + signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0); + } + else { + signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0); + } + } + + if (signaled != 0) + /* XXX: we are assuming that buffers are freed in the same order they + * are fenced which may not always be true... + */ + break; + + winsys->fence_reference(winsys, &fenced_buf->fence, NULL); + + LIST_DEL(list); + fenced_list->numDelayed--; + + _fenced_buffer_destroy(fenced_buf); + } +} + + +static void +fenced_buffer_reference(struct pipe_buffer *buf) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_buffer_list *fenced_list = fenced_buf->list; + + _glthread_LOCK_MUTEX(fenced_list->mutex); + fenced_buf->refcount++; + _glthread_UNLOCK_MUTEX(fenced_list->mutex); +} + + +static void +fenced_buffer_release(struct pipe_buffer *buf) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_buffer_list *fenced_list = fenced_buf->list; + + _glthread_LOCK_MUTEX(fenced_list->mutex); + + fenced_buf->refcount--; + if(!fenced_buf->refcount) { + if (fenced_buf->fence) { + LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed); + fenced_list->numDelayed++; + } + else { + _fenced_buffer_destroy(fenced_buf); + } + + if ((fenced_list->numDelayed % fenced_list->checkDelayed) == 0) + _fenced_buffer_list_check_free(fenced_list, 0); + } + + _glthread_UNLOCK_MUTEX(fenced_list->mutex); +} + + +static void * +fenced_buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + return buffer_map(fenced_buf->buffer, flags); +} + + +static void +fenced_buffer_unmap(struct pipe_buffer *buf) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + buffer_unmap(fenced_buf->buffer); +} + + +static void +fenced_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + buffer_get_base_buffer(fenced_buf->buffer, base_buf, offset); +} + + +const struct pipe_buffer_vtbl +fenced_buffer_vtbl = { + fenced_buffer_reference, + fenced_buffer_release, + fenced_buffer_map, + fenced_buffer_unmap, + fenced_buffer_get_base_buffer +}; + + +struct pipe_buffer * +fenced_buffer_create(struct fenced_buffer_list *fenced_list, + struct pipe_buffer *buffer) +{ + struct fenced_buffer *buf; + + buf = (struct fenced_buffer *)calloc(1, sizeof(struct fenced_buffer)); + if(!buf) + return NULL; + + buf->base.vtbl = &fenced_buffer_vtbl; + buf->buffer = buffer; + buf->refcount = 1; + buf->list = fenced_list; + + return &buf->base; +} + + +void +buffer_fence(struct pipe_buffer *buf, + struct pipe_fence_handle *fence) +{ + if(buf->vtbl == &fenced_buffer_vtbl) { + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_buffer_list *fenced_list = fenced_buf->list; + struct pipe_winsys *winsys = fenced_list->winsys; + + _glthread_LOCK_MUTEX(fenced_list->mutex); + winsys->fence_reference(winsys, &fenced_buf->fence, fence); + _glthread_UNLOCK_MUTEX(fenced_list->mutex); + } + else + assert(0); +} + + +struct fenced_buffer_list * +fenced_buffer_list_create(struct pipe_winsys *winsys) +{ + struct fenced_buffer_list *fenced_list; + + fenced_list = (struct fenced_buffer_list *)calloc(1, sizeof(*fenced_list)); + if (!fenced_list) + return NULL; + + fenced_list->winsys = winsys; + + LIST_INITHEAD(&fenced_list->delayed); + + fenced_list->numDelayed = 0; + + /* TODO: don't hard code this */ + fenced_list->checkDelayed = 5; + + _glthread_INIT_MUTEX(fenced_list->mutex); + + return fenced_list; +} + + +void +fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, + int wait) +{ + _glthread_LOCK_MUTEX(fenced_list->mutex); + _fenced_buffer_list_check_free(fenced_list, wait); + _glthread_UNLOCK_MUTEX(fenced_list->mutex); +} + + +void +fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) +{ + _glthread_LOCK_MUTEX(fenced_list->mutex); + + /* Wait on outstanding fences */ + while (fenced_list->numDelayed) { + _glthread_UNLOCK_MUTEX(fenced_list->mutex); + sched_yield(); + _fenced_buffer_list_check_free(fenced_list, GL_TRUE); + _glthread_LOCK_MUTEX(fenced_list->mutex); + } + + _glthread_UNLOCK_MUTEX(fenced_list->mutex); + + free(fenced_list); +} + + diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_fenced.h b/src/mesa/pipe/pipebuffer/pb_buffer_fenced.h new file mode 100644 index 0000000000..07e42a67f8 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_fenced.h @@ -0,0 +1,117 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Buffer fencing. + * + * "Fenced buffers" is actually a misnomer. They should be referred as + * "fenceable buffers", i.e, buffers that can be fenced, but I couldn't find + * the word "fenceable" in the dictionary. + * + * A "fenced buffer" is a decorator around a normal buffer, which adds two + * special properties: + * - the ability for the destruction to be delayed by a fence; + * - reference counting. + * + * Usually DMA buffers have a life-time that will extend the life-time of its + * handle. The end-of-life is dictated by the fence signalling. + * + * Between the handle's destruction, and the fence signalling, the buffer is + * stored in a fenced buffer list. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + +#ifndef PB_BUFFER_FENCED_H_ +#define PB_BUFFER_FENCED_H_ + + +#include <assert.h> + + +struct pipe_winsys; +struct pipe_buffer; +struct pipe_fence_handle; + + +/** + * List of buffers which are awaiting fence signalling. + */ +struct fenced_buffer_list; + + +/** + * The fenced buffer's virtual function table. + * + * NOTE: Made public for debugging purposes. + */ +extern const struct pipe_buffer_vtbl fenced_buffer_vtbl; + + +/** + * Create a fenced buffer list. + * + * See also fenced_bufmgr_create for a more convenient way to use this. + */ +struct fenced_buffer_list * +fenced_buffer_list_create(struct pipe_winsys *winsys); + + +/** + * Walk the fenced buffer list to check and free signalled buffers. + */ +void +fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, + int wait); + +void +fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list); + + +/** + * Wrap a buffer in a fenced buffer. + * + * NOTE: this will not increase the buffer reference count. + */ +struct pipe_buffer * +fenced_buffer_create(struct fenced_buffer_list *fenced, + struct pipe_buffer *buffer); + + +/** + * Set a buffer's fence. + * + * NOTE: Although it takes a generic pipe buffer argument, it will fail + * on everything but buffers returned by fenced_buffer_create. + */ +void +buffer_fence(struct pipe_buffer *buf, + struct pipe_fence_handle *fence); + + +#endif /*PB_BUFFER_FENCED_H_*/ diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_handle.c b/src/mesa/pipe/pipebuffer/pb_buffer_handle.c new file mode 100644 index 0000000000..5a5eaee7ac --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_handle.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Drop-in implementation of the winsys driver functions for buffer handles. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include <assert.h> +#include <stdlib.h> + +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" + +#include "pb_buffer.h" +#include "pb_buffer_handle.h" + + +static struct pipe_buffer_handle * +buffer_handle_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned flags, + unsigned hint) +{ + struct pipe_buffer_handle *handle; + + handle = (struct pipe_buffer_handle *)malloc(sizeof(struct pipe_buffer_handle)); + if(!handle) + return NULL; + + handle->refcount = 1; + handle->alignment = alignment; + handle->flags = flags; + handle->hint = hint; + + handle->buf = &null_buffer; + + return handle; +} + + +static struct pipe_buffer_handle * +buffer_handle_create_user(struct pipe_winsys *winsys, + void *data, unsigned size) +{ + struct pipe_buffer_handle *handle; + struct pipe_buffer *buf; + + handle = buffer_handle_create(winsys, 1, 0, 0); + if(!handle) + return NULL; + + buf = client_buffer_create(data); + if(!buf) { + free(handle); + return NULL; + } + + buffer_handle_data(handle, buf); + + return handle; +} + + +static void * +buffer_handle_map(struct pipe_winsys *winsys, + struct pipe_buffer_handle *handle, + unsigned flags) +{ + return buffer_map(handle->buf, flags); +} + + +static void +buffer_handle_unmap(struct pipe_winsys *winsys, + struct pipe_buffer_handle *handle) +{ + buffer_unmap(handle->buf); +} + + +static void +buffer_handle_reference(struct pipe_winsys *winsys, + struct pipe_buffer_handle **dst, + struct pipe_buffer_handle *src) +{ + /* XXX: should this be thread safe? */ + + if (src) { + src->refcount++; + } + + if (*dst) { + (*dst)->refcount--; + if ((*dst)->refcount == 0) { + buffer_release((*dst)->buf); + free(*dst); + } + } + + *dst = src; +} + + +static int +buffer_handle_subdata(struct pipe_winsys *winsys, + struct pipe_buffer_handle *handle, + unsigned long offset, + unsigned long size, + const void *data) +{ + void *map; + assert(handle); + assert(data); + map = buffer_handle_map(winsys, handle, PIPE_BUFFER_FLAG_WRITE); + if(map) { + memcpy((char *)map + offset, data, size); + buffer_handle_unmap(winsys, handle); + return 0; + } + return -1; +} + + +static int +buffer_handle_get_subdata(struct pipe_winsys *winsys, + struct pipe_buffer_handle *handle, + unsigned long offset, + unsigned long size, + void *data) +{ + void *map; + assert(handle); + assert(data); + map = buffer_handle_map(winsys, handle, PIPE_BUFFER_FLAG_READ); + if(map) { + memcpy(data, (char *)map + offset, size); + buffer_handle_unmap(winsys, handle); + return 0; + } + return -1; +} + + +void +buffer_handle_init_winsys(struct pipe_winsys *winsys) +{ + winsys->buffer_create = buffer_handle_create; + winsys->user_buffer_create = buffer_handle_create_user; + winsys->buffer_map = buffer_handle_map; + winsys->buffer_unmap = buffer_handle_unmap; + winsys->buffer_reference = buffer_handle_reference; + winsys->buffer_subdata = buffer_handle_subdata; + winsys->buffer_get_subdata = buffer_handle_get_subdata; +} diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_handle.h b/src/mesa/pipe/pipebuffer/pb_buffer_handle.h new file mode 100644 index 0000000000..076eec2fdc --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_handle.h @@ -0,0 +1,120 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Buffer handle interface. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + +#ifndef PB_BUFFER_HANDLE_H_ +#define PB_BUFFER_HANDLE_H_ + + +#include <assert.h> + +#include "pb_buffer.h" + + +/** + * Buffer handle. + * + * The buffer handle and the buffer data storage are separate entities. This + * is modelled after ARB_vertex_buffer_object, which is the interface that + * Gallium requires. See p_winsys.h for more information. + */ +struct pipe_buffer_handle +{ + /** Reference count */ + unsigned refcount; + + /** Allocation characteristics */ + unsigned alignment; + unsigned flags; + unsigned hint; + + /** + * The actual buffer. + * + * It should never be NULL. Use null_buffer instead. + */ + struct pipe_buffer *buf; +}; + + +/** + * Set buffer storage. + * + * NOTE: this will not increase the buffer reference count. + */ +static inline void +buffer_handle_data(struct pipe_buffer_handle *handle, + struct pipe_buffer *buf) +{ + assert(handle); + assert(handle->buf); + buffer_release(handle->buf); + assert(buf); + handle->buf = buf; +} + + +static inline void +buffer_handle_clear(struct pipe_buffer_handle *handle) +{ + buffer_handle_data(handle, &null_buffer); +} + + +static inline int +buffer_handle_has_data(struct pipe_buffer_handle *handle) { + assert(handle); + assert(handle->buf); + return handle->buf != &null_buffer; +} + + +/** + * Fill in the pipe_winsys' buffer-related callbacks. + * + * Specifically, the fullfilled functions are: + * - buffer_create + * - user_buffer_create + * - buffer_map + * - buffer_unmap + * - buffer_reference + * - buffer_subdata + * - buffer_get_subdata + * + * NOTE: buffer_data is left untouched. + */ +void +buffer_handle_init_winsys(struct pipe_winsys *winsys); + + +#endif /*PB_BUFFER_HANDLE_H_*/ diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_malloc.c b/src/mesa/pipe/pipebuffer/pb_buffer_malloc.c new file mode 100644 index 0000000000..65ad51e1e7 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_malloc.c @@ -0,0 +1,132 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Implementation of malloc-based buffers to store data that can't be processed + * by the hardware. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include <assert.h> +#include <stdlib.h> + +#include "pb_buffer.h" + + +struct malloc_buffer +{ + struct pipe_buffer base; + void *data; +}; + + +extern const struct pipe_buffer_vtbl malloc_buffer_vtbl; + +static inline struct malloc_buffer * +malloc_buffer(struct pipe_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &malloc_buffer_vtbl); + return (struct malloc_buffer *)buf; +} + + +static void +malloc_buffer_reference(struct pipe_buffer *buf) +{ + /* no-op */ +} + + +static void +malloc_buffer_release(struct pipe_buffer *buf) +{ + free(malloc_buffer(buf)->data); + free(buf); +} + + +static void * +malloc_buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + return malloc_buffer(buf)->data; +} + + +static void +malloc_buffer_unmap(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +malloc_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +const struct pipe_buffer_vtbl +malloc_buffer_vtbl = { + malloc_buffer_reference, + malloc_buffer_release, + malloc_buffer_map, + malloc_buffer_unmap, + malloc_buffer_get_base_buffer +}; + + +struct pipe_buffer * +malloc_buffer_create(unsigned size) +{ + struct malloc_buffer *buf; + + /* TODO: accept an alignment parameter */ + /* TODO: do a single allocation */ + + buf = (struct malloc_buffer *)malloc(sizeof(struct malloc_buffer)); + if(!buf) + return NULL; + + buf->base.vtbl = &malloc_buffer_vtbl; + + buf->data = malloc(size); + if(!buf->data) { + free(buf); + return NULL; + } + + return &buf->base; +} diff --git a/src/mesa/pipe/pipebuffer/pb_buffer_null.c b/src/mesa/pipe/pipebuffer/pb_buffer_null.c new file mode 100644 index 0000000000..a356c6b2d5 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_buffer_null.c @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Null buffer implementation. + * + * We have a special null buffer object so that we can safely call buffer + * operations without having to check whether the buffer pointer is null or not. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" + +#include "pb_buffer.h" + + +static void +null_buffer_reference(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +null_buffer_release(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void * +null_buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + assert(0); + return NULL; +} + + +static void +null_buffer_unmap(struct pipe_buffer *buf) +{ + assert(0); +} + + +static void +null_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +const struct pipe_buffer_vtbl +pipe_buffer_vtbl = { + null_buffer_reference, + null_buffer_release, + null_buffer_map, + null_buffer_unmap, + null_buffer_get_base_buffer +}; + + +struct pipe_buffer +null_buffer = { + &pipe_buffer_vtbl +}; diff --git a/src/mesa/pipe/pipebuffer/pb_bufmgr.h b/src/mesa/pipe/pipebuffer/pb_bufmgr.h new file mode 100644 index 0000000000..0e6c3a8d37 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_bufmgr.h @@ -0,0 +1,114 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \file + * Buffer management. + * + * A buffer manager does only one basic thing: it creates buffers. Actually, + * "buffer factory" would probably a more accurate description. + * + * You can chain buffer managers so that you can have a finer grained memory + * management and pooling. + * + * For example, for a simple batch buffer manager you would chain: + * - the native buffer manager, which provides DMA memory from the graphics + * memory space; + * - the pool buffer manager, which keep around a pool of equally sized buffers + * to avoid latency associated with the native buffer manager; + * - the fenced buffer manager, which will delay buffer destruction until the + * the moment the card finishing processing it. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + +#ifndef PB_BUFMGR_H_ +#define PB_BUFMGR_H_ + + +#include <stddef.h> + + +struct pipe_buffer; +struct pipe_winsys; + + +/** + * Abstract base class for all buffer managers. + */ +struct buffer_manager +{ + /* XXX: we will likely need more allocation flags */ + struct pipe_buffer * + (*create_buffer)( struct buffer_manager *mgr, + size_t size); + + void + (*destroy)( struct buffer_manager *mgr ); +}; + + +/** + * Static buffer pool manager. + * + * Manages the allocation of equally sized buffers. It does so by allocating + * a single big buffer and divide it equally sized buffers. + * + * It is meant to manage the allocation of batch buffer pools. + */ +struct buffer_manager * +pool_bufmgr_create(struct buffer_manager *provider, + size_t n, size_t size); + + +/** + * Wraper around the old memory manager. + * + * It managers buffers of different sizes. It does so by allocating a buffer + * with the size of the heap, and then using the old mm memory manager to manage + * that heap. + */ +struct buffer_manager * +mm_bufmgr_create(struct buffer_manager *provider, + size_t size, size_t align2); + + +/** + * Fenced buffer manager. + * + * This manager is just meant for convenience. It wraps the buffers returned + * by another manager in fenced buffers, so that + * + * NOTE: the buffer manager that provides the buffers will be destroyed + * at the same time. + */ +struct buffer_manager * +fenced_bufmgr_create(struct buffer_manager *provider, + struct pipe_winsys *winsys); + + +#endif /*PB_BUFMGR_H_*/ diff --git a/src/mesa/pipe/pipebuffer/pb_bufmgr_fenced.c b/src/mesa/pipe/pipebuffer/pb_bufmgr_fenced.c new file mode 100644 index 0000000000..defd8e4df7 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_bufmgr_fenced.c @@ -0,0 +1,128 @@ +/************************************************************************** + * + * Copyright 2006 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. + * + * + **************************************************************************/ + +/** + * \file + * A buffer manager that wraps buffers in fenced buffers. + * + * \author José Fonseca <jrfonseca@tungstengraphics.dot.com> + */ + + +#include <assert.h> +#include <stdlib.h> + +#include "pb_buffer.h" +#include "pb_buffer_fenced.h" +#include "pb_bufmgr.h" + + +struct fenced_buffer_manager +{ + struct buffer_manager base; + + struct buffer_manager *provider; + + struct fenced_buffer_list *fenced_list; +}; + + +static inline struct fenced_buffer_manager * +fenced_buffer_manager(struct buffer_manager *mgr) +{ + assert(mgr); + return (struct fenced_buffer_manager *)mgr; +} + + +static struct pipe_buffer * +fenced_bufmgr_create_buffer(struct buffer_manager *mgr, size_t size) +{ + struct fenced_buffer_manager *fenced_mgr = fenced_buffer_manager(mgr); + struct pipe_buffer *buf; + struct pipe_buffer *fenced_buf; + + /* check for free buffers before allocating new ones */ + fenced_buffer_list_check_free(fenced_mgr->fenced_list, 0); + + buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size); + if(!buf) { + /* try harder to get a buffer */ + fenced_buffer_list_check_free(fenced_mgr->fenced_list, 1); + + buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size); + if(!buf) { + /* give up */ + return NULL; + } + } + + fenced_buf = fenced_buffer_create(fenced_mgr->fenced_list, buf); + if(!fenced_buf) { + buffer_release(buf); + } + + return fenced_buf; +} + + +static void +fenced_bufmgr_destroy(struct buffer_manager *mgr) +{ + struct fenced_buffer_manager *fenced_mgr = fenced_buffer_manager(mgr); + + fenced_buffer_list_destroy(fenced_mgr->fenced_list); + + fenced_mgr->provider->destroy(fenced_mgr->provider); + + free(fenced_mgr); +} + + +struct buffer_manager * +fenced_bufmgr_create(struct buffer_manager *provider, + struct pipe_winsys *winsys) +{ + struct fenced_buffer_manager *fenced_mgr; + + fenced_mgr = (struct fenced_buffer_manager *)calloc(1, sizeof(*fenced_mgr)); + if (!fenced_mgr) + return NULL; + + fenced_mgr->base.destroy = fenced_bufmgr_destroy; + fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer; + + fenced_mgr->provider = provider; + fenced_mgr->fenced_list = fenced_buffer_list_create(winsys); + if(!fenced_mgr->fenced_list) { + free(fenced_mgr); + return NULL; + } + + return &fenced_mgr->base; +} diff --git a/src/mesa/pipe/pipebuffer/pb_bufmgr_mm.c b/src/mesa/pipe/pipebuffer/pb_bufmgr_mm.c new file mode 100644 index 0000000000..8e6dcf1116 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_bufmgr_mm.c @@ -0,0 +1,265 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * \file + * Buffer manager using the old texture memory manager. + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include <assert.h> +#include <stdlib.h> +#include <unistd.h> + +#include "main/imports.h" +#include "glapi/glthread.h" +#include "main/mm.h" +#include "linked_list.h" + +#include "p_defines.h" +#include "pb_buffer.h" +#include "pb_bufmgr.h" + + +/** + * Convenience macro (type safe). + */ +#define SUPER(__derived) (&(__derived)->base) + + +struct mm_buffer_manager +{ + struct buffer_manager base; + + _glthread_Mutex mutex; + + size_t size; + struct mem_block *heap; + + size_t align2; + + struct pipe_buffer *buffer; + void *map; +}; + + +static inline struct mm_buffer_manager * +mm_buffer_manager(struct buffer_manager *mgr) +{ + assert(mgr); + return (struct mm_buffer_manager *)mgr; +} + + +struct mm_buffer +{ + struct pipe_buffer base; + + struct mm_buffer_manager *mgr; + + struct mem_block *block; +}; + + +static inline struct mm_buffer * +mm_buffer(struct pipe_buffer *buf) +{ + assert(buf); + return (struct mm_buffer *)buf; +} + + +static void +mm_buffer_reference(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +mm_buffer_release(struct pipe_buffer *buf) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_buffer_manager *mm = mm_buf->mgr; + + _glthread_LOCK_MUTEX(mm->mutex); + mmFreeMem(mm_buf->block); + free(buf); + _glthread_UNLOCK_MUTEX(mm->mutex); +} + + +static void * +mm_buffer_map(struct pipe_buffer *buf, + unsigned flags) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_buffer_manager *mm = mm_buf->mgr; + + return (unsigned char *) mm->map + mm_buf->block->ofs; +} + + +static void +mm_buffer_unmap(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +mm_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_buffer_manager *mm = mm_buf->mgr; + buffer_get_base_buffer(mm->buffer, base_buf, offset); + *offset += mm_buf->block->ofs; +} + + +static const struct pipe_buffer_vtbl +mm_buffer_vtbl = { + mm_buffer_reference, + mm_buffer_release, + mm_buffer_map, + mm_buffer_unmap, + mm_buffer_get_base_buffer +}; + + +static struct pipe_buffer * +mm_bufmgr_create_buffer(struct buffer_manager *mgr, + size_t size) +{ + struct mm_buffer_manager *mm = mm_buffer_manager(mgr); + struct mm_buffer *mm_buf; + + _glthread_LOCK_MUTEX(mm->mutex); + + mm_buf = (struct mm_buffer *)malloc(sizeof(*mm_buf)); + if (!mm_buf) { + _glthread_UNLOCK_MUTEX(mm->mutex); + return NULL; + } + + mm_buf->base.vtbl = &mm_buffer_vtbl; + + mm_buf->mgr = mm; + + mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); + if(!mm_buf->block) { + fprintf(stderr, "warning: heap full\n"); +#if 0 + mmDumpMemInfo(mm->heap); +#endif + + mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); + if(!mm_buf->block) { + assert(0); + free(mm_buf); + _glthread_UNLOCK_MUTEX(mm->mutex); + return NULL; + } + } + + /* Some sanity checks */ + assert(0 <= mm_buf->block->ofs && mm_buf->block->ofs < mm->size); + assert(size <= mm_buf->block->size && mm_buf->block->ofs + mm_buf->block->size <= mm->size); + + _glthread_UNLOCK_MUTEX(mm->mutex); + return SUPER(mm_buf); +} + + +static void +mm_bufmgr_destroy(struct buffer_manager *mgr) +{ + struct mm_buffer_manager *mm = mm_buffer_manager(mgr); + + _glthread_LOCK_MUTEX(mm->mutex); + + mmDestroy(mm->heap); + + buffer_unmap(mm->buffer); + buffer_release(mm->buffer); + + _glthread_UNLOCK_MUTEX(mm->mutex); + + free(mgr); +} + + +struct buffer_manager * +mm_bufmgr_create(struct buffer_manager *provider, + size_t size, size_t align2) +{ + struct mm_buffer_manager *mm; + + mm = (struct mm_buffer_manager *)calloc(1, sizeof(*mm)); + if (!mm) + return NULL; + + assert(provider); + assert(provider->create_buffer); + mm->base.create_buffer = mm_bufmgr_create_buffer; + mm->base.destroy = mm_bufmgr_destroy; + + mm->size = size; + mm->align2 = align2; /* 64-byte alignment */ + + _glthread_INIT_MUTEX(mm->mutex); + + mm->buffer = provider->create_buffer(provider, size); + if (!mm->buffer) + goto failure; + + mm->map = buffer_map(mm->buffer, + PIPE_BUFFER_FLAG_READ | PIPE_BUFFER_FLAG_WRITE ); + if(!mm->map) + goto failure; + + mm->heap = mmInit(0, size); + if (!mm->heap) + goto failure; + + return SUPER(mm); + +failure: +if(mm->heap) + mmDestroy(mm->heap); + if(mm->map) + buffer_unmap(mm->buffer); + if(mm->buffer) + buffer_release(mm->buffer); + if(mm) + free(mm); + return NULL; +} diff --git a/src/mesa/pipe/pipebuffer/pb_bufmgr_pool.c b/src/mesa/pipe/pipebuffer/pb_bufmgr_pool.c new file mode 100644 index 0000000000..ee6fa62500 --- /dev/null +++ b/src/mesa/pipe/pipebuffer/pb_bufmgr_pool.c @@ -0,0 +1,279 @@ +/************************************************************************** + * + * Copyright 2006 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. + * + * + **************************************************************************/ + +/** + * \file + * Batch buffer pool management. + * + * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com> + * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + + +#include <assert.h> +#include <stdlib.h> +#include <unistd.h> + +#include "main/imports.h" +#include "glapi/glthread.h" +#include "linked_list.h" + +#include "p_defines.h" + +#include "pb_buffer.h" +#include "pb_bufmgr.h" + + +/** + * Convenience macro (type safe). + */ +#define SUPER(__derived) (&(__derived)->base) + + +struct pool_buffer_manager +{ + struct buffer_manager base; + + _glthread_Mutex mutex; + + size_t bufSize; + + size_t numFree; + size_t numTot; + + struct list_head free; + + struct pipe_buffer *buffer; + void *map; + + struct pool_buffer *bufs; +}; + + +static inline struct pool_buffer_manager * +pool_buffer_manager(struct buffer_manager *mgr) +{ + assert(mgr); + return (struct pool_buffer_manager *)mgr; +} + + +struct pool_buffer +{ + struct pipe_buffer base; + + struct pool_buffer_manager *mgr; + + struct list_head head; + + size_t start; +}; + + +static inline struct pool_buffer * +pool_buffer(struct pipe_buffer *buf) +{ + assert(buf); + return (struct pool_buffer *)buf; +} + + +static void +pool_buffer_reference(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +pool_buffer_release(struct pipe_buffer *buf) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_buffer_manager *pool = pool_buf->mgr; + + _glthread_LOCK_MUTEX(pool->mutex); + LIST_ADD(&pool_buf->head, &pool->free); + pool->numFree++; + _glthread_UNLOCK_MUTEX(pool->mutex); +} + + +static void * +pool_buffer_map(struct pipe_buffer *buf, unsigned flags) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_buffer_manager *pool = pool_buf->mgr; + void *map; + + _glthread_LOCK_MUTEX(pool->mutex); + map = (unsigned char *) pool->map + pool_buf->start; + _glthread_UNLOCK_MUTEX(pool->mutex); + return map; +} + + +static void +pool_buffer_unmap(struct pipe_buffer *buf) +{ + /* No-op */ +} + + +static void +pool_buffer_get_base_buffer(struct pipe_buffer *buf, + struct pipe_buffer **base_buf, + unsigned *offset) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_buffer_manager *pool = pool_buf->mgr; + buffer_get_base_buffer(pool->buffer, base_buf, offset); + *offset += pool_buf->start; +} + + +static const struct pipe_buffer_vtbl +pool_buffer_vtbl = { + pool_buffer_reference, + pool_buffer_release, + pool_buffer_map, + pool_buffer_unmap, + pool_buffer_get_base_buffer +}; + + +static struct pipe_buffer * +pool_bufmgr_create_buffer(struct buffer_manager *mgr, size_t size) +{ + struct pool_buffer_manager *pool = pool_buffer_manager(mgr); + struct pool_buffer *pool_buf; + struct list_head *item; + + assert(size == pool->bufSize); + + _glthread_LOCK_MUTEX(pool->mutex); + + if (pool->numFree == 0) { + _glthread_UNLOCK_MUTEX(pool->mutex); + fprintf(stderr, "warning: out of fixed size buffer objects\n"); + return NULL; + } + + item = pool->free.next; + + if (item == &pool->free) { + _glthread_UNLOCK_MUTEX(pool->mutex); + fprintf(stderr, "error: fixed size buffer pool corruption\n"); + return NULL; + } + + LIST_DEL(item); + --pool->numFree; + + _glthread_UNLOCK_MUTEX(pool->mutex); + pool_buf = LIST_ENTRY(struct pool_buffer, item, head); + return SUPER(pool_buf); +} + + +static void +pool_bufmgr_destroy(struct buffer_manager *mgr) +{ + struct pool_buffer_manager *pool = pool_buffer_manager(mgr); + _glthread_LOCK_MUTEX(pool->mutex); + + free(pool->bufs); + + buffer_unmap(pool->buffer); + buffer_release(pool->buffer); + + _glthread_UNLOCK_MUTEX(pool->mutex); + + free(mgr); +} + + +struct buffer_manager * +pool_bufmgr_create(struct buffer_manager *provider, + size_t numBufs, + size_t bufSize) +{ + struct pool_buffer_manager *pool; + struct pool_buffer *pool_buf; + int i; + + pool = (struct pool_buffer_manager *)calloc(1, sizeof(*pool)); + if (!pool) + return NULL; + + pool->base.destroy = pool_bufmgr_destroy; + pool->base.create_buffer = pool_bufmgr_create_buffer; + + LIST_INITHEAD(&pool->free); + + pool->numTot = numBufs; + pool->numFree = numBufs; + pool->bufSize = bufSize; + + _glthread_INIT_MUTEX(pool->mutex); + + pool->buffer = provider->create_buffer(provider, numBufs*bufSize); + if (!pool->buffer) + goto failure; + + pool->map = buffer_map(pool->buffer, + PIPE_BUFFER_FLAG_READ | + PIPE_BUFFER_FLAG_WRITE ); + if(!pool->map) + goto failure; + + pool->bufs = (struct pool_buffer *) malloc(numBufs * sizeof(*pool->bufs)); + if (!pool->bufs) + goto failure; + + pool_buf = pool->bufs; + for (i = 0; i < numBufs; ++i) { + pool_buf->base.vtbl = &pool_buffer_vtbl; + pool_buf->mgr = pool; + pool_buf->start = i * bufSize; + LIST_ADDTAIL(&pool_buf->head, &pool->free); + pool_buf++; + } + + return SUPER(pool); + +failure: + if(pool->bufs) + free(pool->bufs); + if(pool->map) + buffer_unmap(pool->buffer); + if(pool->buffer) + buffer_release(pool->buffer); + if(pool) + free(pool); + return NULL; +} diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index df4e0cbd5a..809b165f45 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -244,7 +244,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, uint i; #if defined(__i386__) || defined(__386__) - softpipe->use_sse = GETENV( "GALLIUM_SSE" ) != NULL; + softpipe->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; #else softpipe->use_sse = FALSE; #endif diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c index 9f5a43a827..6980564bdc 100644 --- a/src/mesa/pipe/softpipe/sp_prim_setup.c +++ b/src/mesa/pipe/softpipe/sp_prim_setup.c @@ -1124,6 +1124,12 @@ static void reset_stipple_counter( struct draw_stage *stage ) } +static void render_destroy( struct draw_stage *stage ) +{ + FREE( stage ); +} + + /** * Create a new primitive setup/render stage. */ @@ -1139,6 +1145,7 @@ struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe ) setup->stage.tri = setup_tri; setup->stage.end = setup_end; setup->stage.reset_stipple_counter = reset_stipple_counter; + setup->stage.destroy = render_destroy; setup->quad.coef = setup->coef; diff --git a/src/mesa/pipe/softpipe/sp_prim_vbuf.c b/src/mesa/pipe/softpipe/sp_prim_vbuf.c index 59cf1c4eb7..2cfdeb5809 100644 --- a/src/mesa/pipe/softpipe/sp_prim_vbuf.c +++ b/src/mesa/pipe/softpipe/sp_prim_vbuf.c @@ -275,6 +275,16 @@ static void reset_stipple_counter( struct draw_stage *stage ) } +static void vbuf_destroy( struct draw_stage *stage ) +{ + struct vbuf_stage *vbuf = vbuf_stage( stage ); + + FREE( vbuf->element_map ); + FREE( vbuf->vertex_map ); + FREE( stage ); +} + + /** * Create a new primitive vbuf/render stage. */ @@ -290,6 +300,7 @@ struct draw_stage *sp_draw_vbuf_stage( struct draw_context *draw_context, vbuf->stage.tri = vbuf_first_tri; vbuf->stage.end = vbuf_end; vbuf->stage.reset_stipple_counter = reset_stipple_counter; + vbuf->stage.destroy = vbuf_destroy; vbuf->pipe = pipe; vbuf->draw = draw; diff --git a/src/mesa/pipe/softpipe/sp_texture.c b/src/mesa/pipe/softpipe/sp_texture.c index 2288c343bf..cfe9628184 100644 --- a/src/mesa/pipe/softpipe/sp_texture.c +++ b/src/mesa/pipe/softpipe/sp_texture.c @@ -382,7 +382,9 @@ softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt) if (softpipe_mipmap_tree_layout(pipe, spt)) { spt->buffer = pipe->winsys->buffer_create(pipe->winsys, - PIPE_SURFACE_FLAG_TEXTURE); + 32, + PIPE_SURFACE_FLAG_TEXTURE, + 0); if (spt->buffer) { pipe->winsys->buffer_data(pipe->winsys, spt->buffer, diff --git a/src/mesa/pipe/tgsi/exec/tgsi_exec.c b/src/mesa/pipe/tgsi/exec/tgsi_exec.c index dd11dd58b7..ab83f27c1b 100644 --- a/src/mesa/pipe/tgsi/exec/tgsi_exec.c +++ b/src/mesa/pipe/tgsi/exec/tgsi_exec.c @@ -1066,6 +1066,10 @@ fetch_source( case TGSI_UTIL_SIGN_KEEP: break; } + + if (reg->SrcRegisterExtMod.Complement) { + micro_sub( chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], chan ); + } } static void @@ -1808,7 +1812,7 @@ exec_instruction( micro_sub( &r[2], &r[2], &r[5] ); if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) { - STORE( &r[2], 0, CHAN_X ); + STORE( &r[2], 0, CHAN_X ); } FETCH(&r[2], 1, CHAN_X); @@ -1821,7 +1825,7 @@ exec_instruction( micro_sub( &r[3], &r[3], &r[1] ); if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) { - STORE( &r[3], 0, CHAN_Y ); + STORE( &r[3], 0, CHAN_Y ); } micro_mul( &r[5], &r[5], &r[4] ); @@ -1829,11 +1833,11 @@ exec_instruction( micro_sub( &r[5], &r[5], &r[0] ); if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { - STORE( &r[5], 0, CHAN_Z ); + STORE( &r[5], 0, CHAN_Z ); } if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) { - STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); } break; diff --git a/src/mesa/pipe/tgsi/util/tgsi_dump.c b/src/mesa/pipe/tgsi/util/tgsi_dump.c index 982d5ce796..3f4d930dec 100644 --- a/src/mesa/pipe/tgsi/util/tgsi_dump.c +++ b/src/mesa/pipe/tgsi/util/tgsi_dump.c @@ -31,129 +31,196 @@ #include "tgsi_parse.h" #include "tgsi_build.h" -struct text_dump +struct gen_dump { - FILE *file; unsigned tabs; + void (* write)( + struct gen_dump *dump, + const void *data, + unsigned size ); +}; + +struct text_dump +{ + struct gen_dump base; + char *text; + unsigned length; + unsigned capacity; }; static void -text_dump_str( - struct text_dump *dump, - const char *str ) +_text_dump_write( + struct gen_dump *dump, + const void *data, + unsigned size ) { - unsigned i; - size_t len = strlen( str ); + struct text_dump *td = (struct text_dump *) dump; + unsigned new_length = td->length + size; + + if( new_length >= td->capacity ) { + unsigned new_capacity = td->capacity; + + do { + if( new_capacity == 0 ) { + new_capacity = 256; + } + else { + new_capacity *= 2; + } + } while( new_length >= new_capacity ); + td->text = (char *) REALLOC( + td->text, + td->capacity, + new_capacity ); + td->capacity = new_capacity; + } + memcpy( + &td->text[td->length], + data, + size ); + td->length = new_length; + td->text[td->length] = '\0'; +} + +struct file_dump +{ + struct gen_dump base; + FILE *file; +}; + +static void +_file_dump_write( + struct gen_dump *dump, + const void *data, + unsigned size ) +{ + struct file_dump *fd = (struct file_dump *) dump; + +#if 0 + fwrite( data, 1, size, fd->file ); +#else + { + unsigned i; - for( i = 0; i < len; i++ ) { - fprintf( dump->file, "%c", str[i] ); + for (i = 0; i < size; i++ ) { + fprintf( fd->file, "%c", ((const char *) data)[i] ); + } + } +#endif +} - if( str[i] == '\n' ) { +static void +gen_dump_str( + struct gen_dump *dump, + const char *str ) +{ + unsigned i; + size_t len = strlen( str ); + + for (i = 0; i < len; i++) { + dump->write( dump, &str[i], 1 ); + if (str[i] == '\n') { unsigned i; - for( i = 0; i < dump->tabs; i++ ) { - fprintf( dump->file, " " ); + for (i = 0; i < dump->tabs; i++) { + dump->write( dump, " ", 4 ); } } } } static void -text_dump_chr( - struct text_dump *dump, - const char chr ) +gen_dump_chr( + struct gen_dump *dump, + const char chr ) { - char str[2]; - - str[0] = chr; - str[1] = '\0'; - text_dump_str( dump, str ); + dump->write( dump, &chr, 1 ); } static void -text_dump_uix( - struct text_dump *dump, - const unsigned ui ) +gen_dump_uix( + struct gen_dump *dump, + const unsigned ui ) { - char str[36]; + char str[36]; sprintf( str, "0x%x", ui ); - text_dump_str( dump, str ); + gen_dump_str( dump, str ); } static void -text_dump_uid( - struct text_dump *dump, - const unsigned ui ) +gen_dump_uid( + struct gen_dump *dump, + const unsigned ui ) { - char str[16]; + char str[16]; sprintf( str, "%u", ui ); - text_dump_str( dump, str ); + gen_dump_str( dump, str ); } static void -text_dump_sid( - struct text_dump *dump, - const int si ) +gen_dump_sid( + struct gen_dump *dump, + const int si ) { - char str[16]; + char str[16]; sprintf( str, "%d", si ); - text_dump_str( dump, str ); + gen_dump_str( dump, str ); } static void -text_dump_flt( - struct text_dump *dump, - const float f ) +gen_dump_flt( + struct gen_dump *dump, + const float flt ) { - char str[48]; + char str[48]; - sprintf( str, "%10.4f", f ); - text_dump_str( dump, str ); + sprintf( str, "%10.4f", flt ); + gen_dump_str( dump, str ); } static void -text_dump_enum( - struct text_dump *dump, - const unsigned e, - const char **enums, - const unsigned enums_count ) +gen_dump_enum( + struct gen_dump *dump, + const unsigned e, + const char **enums, + const unsigned enums_count ) { - if( e >= enums_count ) { - text_dump_uid( dump, e ); + if (e >= enums_count) { + gen_dump_uid( dump, e ); } else { - text_dump_str( dump, enums[e] ); + gen_dump_str( dump, enums[e] ); } } static void -text_dump_tab( - struct text_dump *dump ) +gen_dump_tab( + struct gen_dump *dump ) { - dump->tabs++; + ++dump->tabs; } static void -text_dump_untab( - struct text_dump *dump ) +gen_dump_untab( + struct gen_dump *dump ) { assert( dump->tabs > 0 ); --dump->tabs; } -#define TXT(S) text_dump_str( dump, S ) -#define CHR(C) text_dump_chr( dump, C ) -#define UIX(I) text_dump_uix( dump, I ) -#define UID(I) text_dump_uid( dump, I ) -#define SID(I) text_dump_sid( dump, I ) -#define FLT(F) text_dump_flt( dump, F ) -#define TAB() text_dump_tab( dump ) -#define UNT() text_dump_untab( dump ) -#define ENM(E,ENUMS) text_dump_enum( dump, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) +#define TXT(S) gen_dump_str( dump, S ) +#define CHR(C) gen_dump_chr( dump, C ) +#define UIX(I) gen_dump_uix( dump, I ) +#define UID(I) gen_dump_uid( dump, I ) +#define SID(I) gen_dump_sid( dump, I ) +#define FLT(F) gen_dump_flt( dump, F ) +#define TAB() gen_dump_tab( dump ) +#define UNT() gen_dump_untab( dump ) +#define ENM(E,ENUMS) gen_dump_enum( dump, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) static const char *TGSI_PROCESSOR_TYPES[] = { @@ -659,8 +726,8 @@ static const char *TGSI_MODULATES[] = static void dump_declaration_short( - struct text_dump *dump, - struct tgsi_full_declaration *decl ) + struct gen_dump *dump, + struct tgsi_full_declaration *decl ) { TXT( "\nDCL " ); ENM( decl->Declaration.File, TGSI_FILES_SHORT ); @@ -711,11 +778,11 @@ dump_declaration_short( static void dump_declaration_verbose( - struct text_dump *dump, - struct tgsi_full_declaration *decl, - unsigned ignored, - unsigned deflt, - struct tgsi_full_declaration *fd ) + struct gen_dump *dump, + struct tgsi_full_declaration *decl, + unsigned ignored, + unsigned deflt, + struct tgsi_full_declaration *fd ) { TXT( "\nFile : " ); ENM( decl->Declaration.File, TGSI_FILES ); @@ -792,7 +859,7 @@ dump_declaration_verbose( static void dump_immediate_short( - struct text_dump *dump, + struct gen_dump *dump, struct tgsi_full_immediate *imm ) { unsigned i; @@ -820,9 +887,9 @@ dump_immediate_short( static void dump_immediate_verbose( - struct text_dump *dump, + struct gen_dump *dump, struct tgsi_full_immediate *imm, - unsigned ignored ) + unsigned ignored ) { unsigned i; @@ -849,12 +916,12 @@ dump_immediate_verbose( static void dump_instruction_short( - struct text_dump *dump, - struct tgsi_full_instruction *inst, - unsigned instno ) + struct gen_dump *dump, + struct tgsi_full_instruction *inst, + unsigned instno ) { unsigned i; - boolean first_reg = TRUE; + boolean first_reg = TRUE; CHR( '\n' ); UID( instno ); @@ -915,6 +982,9 @@ dump_instruction_short( } CHR( ' ' ); + if( src->SrcRegisterExtMod.Complement ) { + TXT( "(1 - " ); + } if( src->SrcRegisterExtMod.Negate ) { CHR( '-' ); } @@ -957,6 +1027,9 @@ dump_instruction_short( if( src->SrcRegisterExtMod.Absolute ) { CHR( '|' ); } + if( src->SrcRegisterExtMod.Complement ) { + CHR( ')' ); + } first_reg = FALSE; } @@ -975,11 +1048,11 @@ dump_instruction_short( static void dump_instruction_verbose( - struct text_dump *dump, - struct tgsi_full_instruction *inst, - unsigned ignored, - unsigned deflt, - struct tgsi_full_instruction *fi ) + struct gen_dump *dump, + struct tgsi_full_instruction *inst, + unsigned ignored, + unsigned deflt, + struct tgsi_full_instruction *fi ) { unsigned i; @@ -1317,13 +1390,12 @@ dump_instruction_verbose( } } -void -tgsi_dump( +static void +dump_gen( + struct gen_dump *dump, const struct tgsi_token *tokens, - unsigned flags ) + unsigned flags ) { - struct text_dump _dump; - struct text_dump *dump = &_dump; struct tgsi_parse_context parse; struct tgsi_full_instruction fi; struct tgsi_full_declaration fd; @@ -1332,18 +1404,7 @@ tgsi_dump( unsigned deflt = !(flags & TGSI_DUMP_NO_DEFAULT); unsigned instno = 0; - { -#if 0 - static unsigned counter = 0; - char buffer[64]; - - sprintf( buffer, "tgsi-dump-%.4u.txt", counter++ ); - dump->file = fopen( buffer, "wt" ); -#else - dump->file = stderr; -#endif - dump->tabs = 0; - } + dump->tabs = 0; /* sanity check */ assert(strcmp(TGSI_OPCODES[TGSI_OPCODE_CONT], "OPCODE_CONT") == 0); @@ -1457,3 +1518,52 @@ tgsi_dump( tgsi_parse_free( &parse ); } +void +tgsi_dump( + const struct tgsi_token *tokens, + unsigned flags ) +{ + struct file_dump dump; + + dump.base.write = _file_dump_write; +#if 0 + { + static unsigned counter = 0; + char buffer[64]; + sprintf( buffer, "tgsi-dump-%.4u.txt", counter++ ); + dump.file = fopen( buffer, "wt" ); + } +#else + dump.file = stderr; +#endif + + dump_gen( + &dump.base, + tokens, + flags ); + +#if 0 + fclose( dump.file ); +#endif +} + +void +tgsi_dump_str( + char **str, + const struct tgsi_token *tokens, + unsigned flags ) +{ + struct text_dump dump; + + dump.base.write = _text_dump_write; + dump.text = NULL; + dump.length = 0; + dump.capacity = 0; + + dump_gen( + &dump.base, + tokens, + flags ); + + *str = dump.text; +} diff --git a/src/mesa/pipe/tgsi/util/tgsi_dump.h b/src/mesa/pipe/tgsi/util/tgsi_dump.h index 70860c0885..1adc9db251 100644 --- a/src/mesa/pipe/tgsi/util/tgsi_dump.h +++ b/src/mesa/pipe/tgsi/util/tgsi_dump.h @@ -12,7 +12,13 @@ extern "C" { void tgsi_dump( const struct tgsi_token *tokens, - unsigned flags ); + unsigned flags ); + +void +tgsi_dump_str( + char **str, + const struct tgsi_token *tokens, + unsigned flags ); #if defined __cplusplus } // extern "C" diff --git a/src/mesa/pipe/xlib/xm_winsys.c b/src/mesa/pipe/xlib/xm_winsys.c index 976884ad52..c347d1c2a3 100644 --- a/src/mesa/pipe/xlib/xm_winsys.c +++ b/src/mesa/pipe/xlib/xm_winsys.c @@ -155,7 +155,7 @@ xm_buffer_reference(struct pipe_winsys *pws, } } -static void +static int xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, unsigned size, const void *data, unsigned usage ) { @@ -169,9 +169,10 @@ xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, } if (data) memcpy(xm_buf->data, data, size); + return 0; } -static void +static int xm_buffer_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, unsigned long offset, unsigned long size, const void *data) { @@ -180,9 +181,10 @@ xm_buffer_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, assert(!xm_buf->userBuffer); assert(b); memcpy(b + offset, data, size); + return 0; } -static void +static int xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, unsigned long offset, unsigned long size, void *data) { @@ -191,6 +193,7 @@ xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, assert(!xm_buf->userBuffer); assert(b); memcpy(data, b + offset, size); + return 0; } @@ -255,7 +258,10 @@ xm_get_name(struct pipe_winsys *pws) static struct pipe_buffer_handle * -xm_buffer_create(struct pipe_winsys *pws, unsigned flags) +xm_buffer_create(struct pipe_winsys *pws, + unsigned alignment, + unsigned flags, + unsigned hints) { struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); buffer->refcount = 1; |