diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2008-09-11 18:32:05 +0100 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2008-09-11 18:32:05 +0100 |
commit | cc7dd4fc1b3c765ca1ecd943d189bb156dae529d (patch) | |
tree | 1a3560eb6df8a443c4f0e5af0a916f190b1542f6 /src/gallium/auxiliary | |
parent | 685248bea1fef5fd6335982570e34d0f6672030d (diff) | |
parent | d50d68a1c940ed9c8d8c65e8e33667fa90d5baa1 (diff) |
Merge commit 'origin/gallium-0.1' into gallium-0.2
Conflicts:
Makefile
progs/demos/Makefile
progs/glsl/Makefile
progs/redbook/Makefile
progs/samples/Makefile
progs/tests/Makefile
progs/trivial/Makefile
progs/xdemos/Makefile
src/gallium/Makefile
src/mesa/main/attrib.c
src/mesa/main/bufferobj.c
src/mesa/vbo/vbo_exec_draw.c
Diffstat (limited to 'src/gallium/auxiliary')
36 files changed, 1903 insertions, 382 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index e8467b2ae3..80d7200ca6 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -63,7 +63,8 @@ struct vcache_frontend { unsigned opt; }; -static void vcache_flush( struct vcache_frontend *vcache ) +static INLINE void +vcache_flush( struct vcache_frontend *vcache ) { if (vcache->middle_prim != vcache->output_prim) { vcache->middle_prim = vcache->output_prim; @@ -86,7 +87,8 @@ static void vcache_flush( struct vcache_frontend *vcache ) vcache->draw_count = 0; } -static void vcache_check_flush( struct vcache_frontend *vcache ) +static INLINE void +vcache_check_flush( struct vcache_frontend *vcache ) { if ( vcache->draw_count + 6 >= DRAW_MAX || vcache->fetch_count + 4 >= FETCH_MAX ) @@ -96,9 +98,10 @@ static void vcache_check_flush( struct vcache_frontend *vcache ) } -static INLINE void vcache_elt( struct vcache_frontend *vcache, - unsigned felt, - ushort flags ) +static INLINE void +vcache_elt( struct vcache_frontend *vcache, + unsigned felt, + ushort flags ) { unsigned idx = felt % CACHE_MAX; @@ -115,10 +118,11 @@ static INLINE void vcache_elt( struct vcache_frontend *vcache, -static void vcache_triangle( struct vcache_frontend *vcache, - unsigned i0, - unsigned i1, - unsigned i2 ) +static INLINE void +vcache_triangle( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2 ) { vcache_elt(vcache, i0, 0); vcache_elt(vcache, i1, 0); @@ -127,11 +131,12 @@ static void vcache_triangle( struct vcache_frontend *vcache, } -static void vcache_triangle_flags( struct vcache_frontend *vcache, - ushort flags, - unsigned i0, - unsigned i1, - unsigned i2 ) +static INLINE void +vcache_triangle_flags( struct vcache_frontend *vcache, + ushort flags, + unsigned i0, + unsigned i1, + unsigned i2 ) { vcache_elt(vcache, i0, flags); vcache_elt(vcache, i1, 0); @@ -139,9 +144,10 @@ static void vcache_triangle_flags( struct vcache_frontend *vcache, vcache_check_flush(vcache); } -static void vcache_line( struct vcache_frontend *vcache, - unsigned i0, - unsigned i1 ) +static INLINE void +vcache_line( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1 ) { vcache_elt(vcache, i0, 0); vcache_elt(vcache, i1, 0); @@ -149,10 +155,11 @@ static void vcache_line( struct vcache_frontend *vcache, } -static void vcache_line_flags( struct vcache_frontend *vcache, - ushort flags, - unsigned i0, - unsigned i1 ) +static INLINE void +vcache_line_flags( struct vcache_frontend *vcache, + ushort flags, + unsigned i0, + unsigned i1 ) { vcache_elt(vcache, i0, flags); vcache_elt(vcache, i1, 0); @@ -160,28 +167,31 @@ static void vcache_line_flags( struct vcache_frontend *vcache, } -static void vcache_point( struct vcache_frontend *vcache, - unsigned i0 ) +static INLINE void +vcache_point( struct vcache_frontend *vcache, + unsigned i0 ) { vcache_elt(vcache, i0, 0); vcache_check_flush(vcache); } -static void vcache_quad( struct vcache_frontend *vcache, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) +static INLINE void +vcache_quad( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2, + unsigned i3 ) { vcache_triangle( vcache, i0, i1, i3 ); vcache_triangle( vcache, i1, i2, i3 ); } -static void vcache_ef_quad( struct vcache_frontend *vcache, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) +static INLINE void +vcache_ef_quad( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2, + unsigned i3 ) { vcache_triangle_flags( vcache, ( DRAW_PIPE_RESET_STIPPLE | @@ -213,10 +223,11 @@ static void vcache_ef_quad( struct vcache_frontend *vcache, #define FUNC vcache_run #include "draw_pt_vcache_tmp.h" -static void rebase_uint_elts( const unsigned *src, - unsigned count, - int delta, - ushort *dest ) +static INLINE void +rebase_uint_elts( const unsigned *src, + unsigned count, + int delta, + ushort *dest ) { unsigned i; @@ -224,9 +235,10 @@ static void rebase_uint_elts( const unsigned *src, dest[i] = (ushort)(src[i] + delta); } -static void rebase_ushort_elts( const ushort *src, - unsigned count, - int delta, +static INLINE void +rebase_ushort_elts( const ushort *src, + unsigned count, + int delta, ushort *dest ) { unsigned i; @@ -235,10 +247,11 @@ static void rebase_ushort_elts( const ushort *src, dest[i] = (ushort)(src[i] + delta); } -static void rebase_ubyte_elts( const ubyte *src, - unsigned count, - int delta, - ushort *dest ) +static INLINE void +rebase_ubyte_elts( const ubyte *src, + unsigned count, + int delta, + ushort *dest ) { unsigned i; @@ -248,9 +261,10 @@ static void rebase_ubyte_elts( const ubyte *src, -static void translate_uint_elts( const unsigned *src, - unsigned count, - ushort *dest ) +static INLINE void +translate_uint_elts( const unsigned *src, + unsigned count, + ushort *dest ) { unsigned i; @@ -258,9 +272,10 @@ static void translate_uint_elts( const unsigned *src, dest[i] = (ushort)(src[i]); } -static void translate_ushort_elts( const ushort *src, - unsigned count, - ushort *dest ) +static INLINE void +translate_ushort_elts( const ushort *src, + unsigned count, + ushort *dest ) { unsigned i; @@ -268,9 +283,10 @@ static void translate_ushort_elts( const ushort *src, dest[i] = (ushort)(src[i]); } -static void translate_ubyte_elts( const ubyte *src, - unsigned count, - ushort *dest ) +static INLINE void +translate_ubyte_elts( const ubyte *src, + unsigned count, + ushort *dest ) { unsigned i; @@ -282,7 +298,8 @@ static void translate_ubyte_elts( const ubyte *src, #if 0 -static enum pipe_format format_from_get_elt( pt_elt_func get_elt ) +static INLINE enum pipe_format +format_from_get_elt( pt_elt_func get_elt ) { switch (draw->pt.user.eltSize) { case 1: return PIPE_FORMAT_R8_UNORM; @@ -293,10 +310,11 @@ static enum pipe_format format_from_get_elt( pt_elt_func get_elt ) } #endif -static void vcache_check_run( struct draw_pt_front_end *frontend, - pt_elt_func get_elt, - const void *elts, - unsigned draw_count ) +static INLINE void +vcache_check_run( struct draw_pt_front_end *frontend, + pt_elt_func get_elt, + const void *elts, + unsigned draw_count ) { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; struct draw_context *draw = vcache->draw; @@ -416,10 +434,11 @@ static void vcache_check_run( struct draw_pt_front_end *frontend, -static void vcache_prepare( struct draw_pt_front_end *frontend, - unsigned prim, - struct draw_pt_middle_end *middle, - unsigned opt ) +static void +vcache_prepare( struct draw_pt_front_end *frontend, + unsigned prim, + struct draw_pt_middle_end *middle, + unsigned opt ) { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; @@ -448,14 +467,16 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, -static void vcache_finish( struct draw_pt_front_end *frontend ) +static void +vcache_finish( struct draw_pt_front_end *frontend ) { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; vcache->middle->finish( vcache->middle ); vcache->middle = NULL; } -static void vcache_destroy( struct draw_pt_front_end *frontend ) +static void +vcache_destroy( struct draw_pt_front_end *frontend ) { FREE(frontend); } diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c index 760fcb389f..a556477a76 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -32,6 +32,7 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "pipe/p_shader_tokens.h" +#include "pipe/p_debug.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi/tgsi_exec.h" @@ -119,21 +120,26 @@ static struct x86_reg get_reg_ptr(struct aos_compilation *cp, switch (file) { case TGSI_FILE_INPUT: + assert(idx < MAX_INPUTS); return x86_make_disp(ptr, Offset(struct aos_machine, input[idx])); case TGSI_FILE_OUTPUT: return x86_make_disp(ptr, Offset(struct aos_machine, output[idx])); case TGSI_FILE_TEMPORARY: + assert(idx < MAX_TEMPS); return x86_make_disp(ptr, Offset(struct aos_machine, temp[idx])); case AOS_FILE_INTERNAL: + assert(idx < MAX_INTERNALS); return x86_make_disp(ptr, Offset(struct aos_machine, internal[idx])); case TGSI_FILE_IMMEDIATE: + assert(idx < MAX_IMMEDIATES); /* just a sanity check */ return x86_make_disp(aos_get_x86(cp, 0, X86_IMMEDIATES), idx * 4 * sizeof(float)); case TGSI_FILE_CONSTANT: + assert(idx < MAX_CONSTANTS); /* just a sanity check */ return x86_make_disp(aos_get_x86(cp, 1, X86_CONSTANTS), idx * 4 * sizeof(float)); default: @@ -2108,6 +2114,11 @@ static void PIPE_CDECL vaos_run_linear( struct draw_vs_varient *varient, start, count, output_buffer ); + + /* Sanity spot checks to make sure we didn't trash our constants */ + assert(machine->internal[IMM_ONES][0] == 1.0f); + assert(machine->internal[IMM_IDENTITY][0] == 0.0f); + assert(machine->internal[IMM_NEGS][0] == -1.0f); } diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.h b/src/gallium/auxiliary/draw/draw_vs_aos.h index 64e021ff6b..7fe6f79db0 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.h +++ b/src/gallium/auxiliary/draw/draw_vs_aos.h @@ -51,11 +51,11 @@ struct x86_function; #define W 3 #define MAX_INPUTS PIPE_MAX_ATTRIBS -#define MAX_OUTPUTS PIPE_MAX_ATTRIBS -#define MAX_TEMPS PIPE_MAX_ATTRIBS /* say */ -#define MAX_CONSTANTS PIPE_MAX_ATTRIBS /* say */ -#define MAX_IMMEDIATES PIPE_MAX_ATTRIBS /* say */ -#define MAX_INTERNALS 8 +#define MAX_OUTPUTS PIPE_MAX_SHADER_OUTPUTS +#define MAX_TEMPS TGSI_EXEC_NUM_TEMPS +#define MAX_CONSTANTS 1024 /** only used for sanity checking */ +#define MAX_IMMEDIATES 1024 /** only used for sanity checking */ +#define MAX_INTERNALS 8 /** see IMM_x values below */ #define AOS_FILE_INTERNAL TGSI_FILE_COUNT diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_io.c b/src/gallium/auxiliary/draw/draw_vs_aos_io.c index ab3c5b94a5..26297c74f8 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos_io.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos_io.c @@ -55,9 +55,13 @@ static void emit_load_R32G32B32( struct aos_compilation *cp, struct x86_reg src_ptr ) { sse_movss(cp->func, data, x86_make_disp(src_ptr, 8)); + /* data = z ? ? ? */ sse_shufps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ), SHUF(X,Y,Z,W) ); + /* data = z ? 0 1 */ sse_shufps(cp->func, data, data, SHUF(Y,Z,X,W) ); + /* data = ? 0 z 1 */ sse_movlps(cp->func, data, src_ptr); + /* data = x y z 1 */ } static void emit_load_R32G32( struct aos_compilation *cp, diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 410d336fef..17b2781052 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -69,7 +69,7 @@ struct fenced_buffer_list { - _glthread_Mutex mutex; + pipe_mutex mutex; struct pipe_winsys *winsys; @@ -240,7 +240,7 @@ fenced_buffer_destroy(struct pb_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); + pipe_mutex_lock(fenced_list->mutex); assert(fenced_buf->base.base.refcount == 0); if (fenced_buf->fence) { struct pipe_winsys *winsys = fenced_list->winsys; @@ -263,7 +263,7 @@ fenced_buffer_destroy(struct pb_buffer *buf) else { _fenced_buffer_destroy(fenced_buf); } - _glthread_UNLOCK_MUTEX(fenced_list->mutex); + pipe_mutex_unlock(fenced_list->mutex); } @@ -396,7 +396,7 @@ buffer_fence(struct pb_buffer *buf, return; } - _glthread_LOCK_MUTEX(fenced_list->mutex); + pipe_mutex_lock(fenced_list->mutex); if (fenced_buf->fence) _fenced_buffer_remove(fenced_list, fenced_buf); if (fence) { @@ -404,7 +404,7 @@ buffer_fence(struct pb_buffer *buf, fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE; _fenced_buffer_add(fenced_buf); } - _glthread_UNLOCK_MUTEX(fenced_list->mutex); + pipe_mutex_unlock(fenced_list->mutex); } @@ -423,7 +423,7 @@ fenced_buffer_list_create(struct pipe_winsys *winsys) fenced_list->numDelayed = 0; - _glthread_INIT_MUTEX(fenced_list->mutex); + pipe_mutex_init(fenced_list->mutex); return fenced_list; } @@ -433,28 +433,28 @@ void fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, int wait) { - _glthread_LOCK_MUTEX(fenced_list->mutex); + pipe_mutex_lock(fenced_list->mutex); _fenced_buffer_list_check_free(fenced_list, wait); - _glthread_UNLOCK_MUTEX(fenced_list->mutex); + pipe_mutex_unlock(fenced_list->mutex); } void fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) { - _glthread_LOCK_MUTEX(fenced_list->mutex); + pipe_mutex_lock(fenced_list->mutex); /* Wait on outstanding fences */ while (fenced_list->numDelayed) { - _glthread_UNLOCK_MUTEX(fenced_list->mutex); + pipe_mutex_unlock(fenced_list->mutex); #if defined(PIPE_OS_LINUX) sched_yield(); #endif _fenced_buffer_list_check_free(fenced_list, 1); - _glthread_LOCK_MUTEX(fenced_list->mutex); + pipe_mutex_lock(fenced_list->mutex); } - _glthread_UNLOCK_MUTEX(fenced_list->mutex); + pipe_mutex_unlock(fenced_list->mutex); FREE(fenced_list); } diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index b914c2d0fe..1ec422fb19 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -79,7 +79,7 @@ struct pb_cache_manager struct pb_manager *provider; unsigned usecs; - _glthread_Mutex mutex; + pipe_mutex mutex; struct list_head delayed; size_t numDelayed; @@ -153,7 +153,7 @@ pb_cache_buffer_destroy(struct pb_buffer *_buf) struct pb_cache_buffer *buf = pb_cache_buffer(_buf); struct pb_cache_manager *mgr = buf->mgr; - _glthread_LOCK_MUTEX(mgr->mutex); + pipe_mutex_lock(mgr->mutex); assert(buf->base.base.refcount == 0); _pb_cache_buffer_list_check_free(mgr); @@ -162,7 +162,7 @@ pb_cache_buffer_destroy(struct pb_buffer *_buf) util_time_add(&buf->start, mgr->usecs, &buf->end); LIST_ADDTAIL(&buf->head, &mgr->delayed); ++mgr->numDelayed; - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); } @@ -235,7 +235,7 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr, struct list_head *curr, *next; struct util_time now; - _glthread_LOCK_MUTEX(mgr->mutex); + pipe_mutex_lock(mgr->mutex); buf = NULL; curr = mgr->delayed.next; @@ -249,27 +249,35 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr, buf = curr_buf; else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now)) _pb_cache_buffer_destroy(curr_buf); + else + /* This buffer (and all hereafter) are still hot in cache */ + break; curr = next; next = curr->next; } /* keep searching in the hot buffers */ - while(!buf && curr != &mgr->delayed) { - curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); - if(pb_cache_is_buffer_compat(curr_buf, size, desc)) - buf = curr_buf; - curr = next; - next = curr->next; + if(!buf) { + while(curr != &mgr->delayed) { + curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); + if(pb_cache_is_buffer_compat(curr_buf, size, desc)) { + buf = curr_buf; + break; + } + /* no need to check the timeout here */ + curr = next; + next = curr->next; + } } if(buf) { LIST_DEL(&buf->head); - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); ++buf->base.base.refcount; return &buf->base; } - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); buf = CALLOC_STRUCT(pb_cache_buffer); if(!buf) @@ -305,7 +313,7 @@ pb_cache_flush(struct pb_manager *_mgr) struct list_head *curr, *next; struct pb_cache_buffer *buf; - _glthread_LOCK_MUTEX(mgr->mutex); + pipe_mutex_lock(mgr->mutex); curr = mgr->delayed.next; next = curr->next; while(curr != &mgr->delayed) { @@ -314,7 +322,7 @@ pb_cache_flush(struct pb_manager *_mgr) curr = next; next = curr->next; } - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); } @@ -345,7 +353,7 @@ pb_cache_manager_create(struct pb_manager *provider, mgr->usecs = usecs; LIST_INITHEAD(&mgr->delayed); mgr->numDelayed = 0; - _glthread_INIT_MUTEX(mgr->mutex); + pipe_mutex_init(mgr->mutex); return &mgr->base; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 4cb8c3bb55..5f1ed3e5a8 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -129,7 +129,7 @@ check_random_pattern(const uint8_t *dst, size_t size, for(i = 0; i < size; ++i) { if(*dst++ != random_pattern[i % sizeof(random_pattern)]) { *min_ofs = MIN2(*min_ofs, i); - *max_ofs = MIN2(*max_ofs, i); + *max_ofs = MAX2(*max_ofs, i); result = FALSE; } } @@ -138,12 +138,30 @@ check_random_pattern(const uint8_t *dst, size_t size, static void -pb_debug_buffer_destroy(struct pb_buffer *_buf) +pb_debug_buffer_fill(struct pb_debug_buffer *buf) { - struct pb_debug_buffer *buf = pb_debug_buffer(_buf); uint8_t *map; - assert(!buf->base.base.refcount); + map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + assert(map); + if(map) { + fill_random_pattern(map, buf->underflow_size); + fill_random_pattern(map + buf->underflow_size + buf->base.base.size, + buf->overflow_size); + pb_unmap(buf->buffer); + } +} + + +/** + * Check for under/over flows. + * + * Should be called with the buffer unmaped. + */ +static void +pb_debug_buffer_check(struct pb_debug_buffer *buf) +{ + uint8_t *map; map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ); assert(map); @@ -154,24 +172,45 @@ pb_debug_buffer_destroy(struct pb_buffer *_buf) underflow = !check_random_pattern(map, buf->underflow_size, &min_ofs, &max_ofs); if(underflow) { - debug_printf("buffer underflow (%u of %u bytes) detected\n", - buf->underflow_size - min_ofs, - buf->underflow_size); + debug_printf("buffer underflow (offset -%u%s to -%u bytes) detected\n", + buf->underflow_size - min_ofs, + min_ofs == 0 ? "+" : "", + buf->underflow_size - max_ofs); } overflow = !check_random_pattern(map + buf->underflow_size + buf->base.base.size, buf->overflow_size, &min_ofs, &max_ofs); if(overflow) { - debug_printf("buffer overflow (%u of %u bytes) detected\n", + debug_printf("buffer overflow (size %u plus offset %u to %u%s bytes) detected\n", + buf->base.base.size, + min_ofs, max_ofs, - buf->overflow_size); + max_ofs == buf->overflow_size - 1 ? "+" : ""); } debug_assert(!underflow && !overflow); - + + /* re-fill if not aborted */ + if(underflow) + fill_random_pattern(map, buf->underflow_size); + if(overflow) + fill_random_pattern(map + buf->underflow_size + buf->base.base.size, + buf->overflow_size); + pb_unmap(buf->buffer); } +} + + +static void +pb_debug_buffer_destroy(struct pb_buffer *_buf) +{ + struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + + assert(!buf->base.base.refcount); + + pb_debug_buffer_check(buf); pb_reference(&buf->buffer, NULL); FREE(buf); @@ -183,9 +222,14 @@ pb_debug_buffer_map(struct pb_buffer *_buf, unsigned flags) { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); - void *map = pb_map(buf->buffer, flags); + void *map; + + pb_debug_buffer_check(buf); + + map = pb_map(buf->buffer, flags); if(!map) return NULL; + return (uint8_t *)map + buf->underflow_size; } @@ -195,6 +239,8 @@ pb_debug_buffer_unmap(struct pb_buffer *_buf) { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); pb_unmap(buf->buffer); + + pb_debug_buffer_check(buf); } @@ -227,7 +273,6 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, struct pb_debug_buffer *buf; struct pb_desc real_desc; size_t real_size; - uint8_t *map; buf = CALLOC_STRUCT(pb_debug_buffer); if(!buf) @@ -262,13 +307,7 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, buf->underflow_size = mgr->band_size; buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size; - map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); - assert(map); - if(map) { - fill_random_pattern(map, buf->underflow_size); - fill_random_pattern(map + buf->underflow_size + size, buf->overflow_size); - pb_unmap(buf->buffer); - } + pb_debug_buffer_fill(buf); return &buf->base; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index b40eb6cc90..e8c7f8e1f8 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -53,7 +53,7 @@ struct mm_pb_manager { struct pb_manager base; - _glthread_Mutex mutex; + pipe_mutex mutex; size_t size; struct mem_block *heap; @@ -99,10 +99,10 @@ mm_buffer_destroy(struct pb_buffer *buf) assert(buf->base.refcount == 0); - _glthread_LOCK_MUTEX(mm->mutex); + pipe_mutex_lock(mm->mutex); mmFreeMem(mm_buf->block); FREE(buf); - _glthread_UNLOCK_MUTEX(mm->mutex); + pipe_mutex_unlock(mm->mutex); } @@ -158,11 +158,11 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr, if(desc->alignment % (1 << mm->align2)) return NULL; - _glthread_LOCK_MUTEX(mm->mutex); + pipe_mutex_lock(mm->mutex); mm_buf = CALLOC_STRUCT(mm_buffer); if (!mm_buf) { - _glthread_UNLOCK_MUTEX(mm->mutex); + pipe_mutex_unlock(mm->mutex); return NULL; } @@ -185,7 +185,7 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr, mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); if(!mm_buf->block) { FREE(mm_buf); - _glthread_UNLOCK_MUTEX(mm->mutex); + pipe_mutex_unlock(mm->mutex); return NULL; } } @@ -194,7 +194,7 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr, assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size); assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size); - _glthread_UNLOCK_MUTEX(mm->mutex); + pipe_mutex_unlock(mm->mutex); return SUPER(mm_buf); } @@ -204,14 +204,14 @@ mm_bufmgr_destroy(struct pb_manager *mgr) { struct mm_pb_manager *mm = mm_pb_manager(mgr); - _glthread_LOCK_MUTEX(mm->mutex); + pipe_mutex_lock(mm->mutex); mmDestroy(mm->heap); pb_unmap(mm->buffer); pb_reference(&mm->buffer, NULL); - _glthread_UNLOCK_MUTEX(mm->mutex); + pipe_mutex_unlock(mm->mutex); FREE(mgr); } @@ -236,7 +236,7 @@ mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, mm->size = size; mm->align2 = align2; /* 64-byte alignment */ - _glthread_INIT_MUTEX(mm->mutex); + pipe_mutex_init(mm->mutex); mm->buffer = buffer; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index 93d2cc9635..3ef72c5bbb 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -56,7 +56,7 @@ struct pool_pb_manager { struct pb_manager base; - _glthread_Mutex mutex; + pipe_mutex mutex; size_t bufSize; size_t bufAlign; @@ -110,10 +110,10 @@ pool_buffer_destroy(struct pb_buffer *buf) assert(pool_buf->base.base.refcount == 0); - _glthread_LOCK_MUTEX(pool->mutex); + pipe_mutex_lock(pool->mutex); LIST_ADD(&pool_buf->head, &pool->free); pool->numFree++; - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); } @@ -124,9 +124,9 @@ pool_buffer_map(struct pb_buffer *buf, unsigned flags) struct pool_pb_manager *pool = pool_buf->mgr; void *map; - _glthread_LOCK_MUTEX(pool->mutex); + pipe_mutex_lock(pool->mutex); map = (unsigned char *) pool->map + pool_buf->start; - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); return map; } @@ -171,10 +171,10 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr, assert(size == pool->bufSize); assert(pool->bufAlign % desc->alignment == 0); - _glthread_LOCK_MUTEX(pool->mutex); + pipe_mutex_lock(pool->mutex); if (pool->numFree == 0) { - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); debug_printf("warning: out of fixed size buffer objects\n"); return NULL; } @@ -182,7 +182,7 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr, item = pool->free.next; if (item == &pool->free) { - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); debug_printf("error: fixed size buffer pool corruption\n"); return NULL; } @@ -190,7 +190,7 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr, LIST_DEL(item); --pool->numFree; - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); pool_buf = LIST_ENTRY(struct pool_buffer, item, head); assert(pool_buf->base.base.refcount == 0); @@ -206,14 +206,14 @@ static void pool_bufmgr_destroy(struct pb_manager *mgr) { struct pool_pb_manager *pool = pool_pb_manager(mgr); - _glthread_LOCK_MUTEX(pool->mutex); + pipe_mutex_lock(pool->mutex); FREE(pool->bufs); pb_unmap(pool->buffer); pb_reference(&pool->buffer, NULL); - _glthread_UNLOCK_MUTEX(pool->mutex); + pipe_mutex_unlock(pool->mutex); FREE(mgr); } @@ -246,7 +246,7 @@ pool_bufmgr_create(struct pb_manager *provider, pool->bufSize = bufSize; pool->bufAlign = desc->alignment; - _glthread_INIT_MUTEX(pool->mutex); + pipe_mutex_init(pool->mutex); pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc); if (!pool->buffer) diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index af307e265a..8698c4cff6 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -30,6 +30,8 @@ * @file * S-lab pool implementation. * + * @sa http://en.wikipedia.org/wiki/Slab_allocation + * * @author Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> * @author Jose Fonseca <jrfonseca@tungstengraphics.com> */ @@ -49,46 +51,96 @@ struct pb_slab; + +/** + * Buffer in a slab. + * + * Sub-allocation of a contiguous buffer. + */ struct pb_slab_buffer { struct pb_buffer base; struct pb_slab *slab; + struct list_head head; + unsigned mapCount; + + /** Offset relative to the start of the slab buffer. */ size_t start; - _glthread_Cond event; + + /** Use when validating, to signal that all mappings are finished */ + /* TODO: Actually validation does not reach this stage yet */ + pipe_condvar event; }; + +/** + * Slab -- a contiguous piece of memory. + */ struct pb_slab { struct list_head head; struct list_head freeBuffers; size_t numBuffers; size_t numFree; + struct pb_slab_buffer *buffers; struct pb_slab_manager *mgr; + /** Buffer from the provider */ struct pb_buffer *bo; + void *virtual; }; + +/** + * It adds/removes slabs as needed in order to meet the allocation/destruction + * of individual buffers. + */ struct pb_slab_manager { struct pb_manager base; + /** From where we get our buffers */ struct pb_manager *provider; + + /** Size of the buffers we hand on downstream */ size_t bufSize; + + /** Size of the buffers we request upstream */ size_t slabSize; + + /** + * Alignment, usage to be used to allocate the slab buffers. + * + * We can only provide buffers which are consistent (in alignment, usage) + * with this description. + */ struct pb_desc desc; + /** + * Partial slabs + * + * Full slabs are not stored in any list. Empty slabs are destroyed + * immediatly. + */ struct list_head slabs; - struct list_head freeSlabs; - _glthread_Mutex mutex; + pipe_mutex mutex; }; + /** + * Wrapper around several slabs, therefore capable of handling buffers of + * multiple sizes. + * + * This buffer manager just dispatches buffer allocations to the appropriate slab + * manager, according to the requested buffer size, or by passes the slab + * managers altogether for even greater sizes. + * * The data of this structure remains constant after * initialization and thus needs no mutex protection. */ @@ -97,12 +149,17 @@ struct pb_slab_range_manager struct pb_manager base; struct pb_manager *provider; + size_t minBufSize; size_t maxBufSize; + + /** @sa pb_slab_manager::desc */ struct pb_desc desc; unsigned numBuckets; size_t *bucketSizes; + + /** Array of pb_slab_manager, one for each bucket size */ struct pb_manager **buckets; }; @@ -143,7 +200,7 @@ pb_slab_buffer_destroy(struct pb_buffer *_buf) struct pb_slab_manager *mgr = slab->mgr; struct list_head *list = &buf->head; - _glthread_LOCK_MUTEX(mgr->mutex); + pipe_mutex_lock(mgr->mutex); assert(buf->base.base.refcount == 0); @@ -156,30 +213,16 @@ pb_slab_buffer_destroy(struct pb_buffer *_buf) if (slab->head.next == &slab->head) LIST_ADDTAIL(&slab->head, &mgr->slabs); + /* If the slab becomes totally empty, free it */ if (slab->numFree == slab->numBuffers) { list = &slab->head; - LIST_DEL(list); - LIST_ADDTAIL(list, &mgr->freeSlabs); + LIST_DELINIT(list); + pb_reference(&slab->bo, NULL); + FREE(slab->buffers); + FREE(slab); } - if (mgr->slabs.next == &mgr->slabs || slab->numFree - != slab->numBuffers) { - - struct list_head *next; - - for (list = mgr->freeSlabs.next, next = list->next; list - != &mgr->freeSlabs; list = next, next = list->next) { - - slab = LIST_ENTRY(struct pb_slab, list, head); - - LIST_DELINIT(list); - pb_reference(&slab->bo, NULL); - FREE(slab->buffers); - FREE(slab); - } - } - - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); } @@ -201,7 +244,7 @@ pb_slab_buffer_unmap(struct pb_buffer *_buf) --buf->mapCount; if (buf->mapCount == 0) - _glthread_COND_BROADCAST(buf->event); + pipe_condvar_broadcast(buf->event); } @@ -225,6 +268,11 @@ pb_slab_buffer_vtbl = { }; +/** + * Create a new slab. + * + * Called when we ran out of free slabs. + */ static enum pipe_error pb_slab_create(struct pb_slab_manager *mgr) { @@ -238,17 +286,14 @@ pb_slab_create(struct pb_slab_manager *mgr) if (!slab) return PIPE_ERROR_OUT_OF_MEMORY; - /* - * FIXME: We should perhaps allow some variation in slabsize in order - * to efficiently reuse slabs. - */ - slab->bo = mgr->provider->create_buffer(mgr->provider, mgr->slabSize, &mgr->desc); if(!slab->bo) { ret = PIPE_ERROR_OUT_OF_MEMORY; goto out_err0; } + /* Note down the slab virtual address. All mappings are accessed directly + * through this address so it is required that the buffer is pinned. */ slab->virtual = pb_map(slab->bo, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE); @@ -256,7 +301,6 @@ pb_slab_create(struct pb_slab_manager *mgr) ret = PIPE_ERROR_OUT_OF_MEMORY; goto out_err1; } - pb_unmap(slab->bo); numBuffers = slab->bo->base.size / mgr->bufSize; @@ -283,12 +327,13 @@ pb_slab_create(struct pb_slab_manager *mgr) buf->slab = slab; buf->start = i* mgr->bufSize; buf->mapCount = 0; - _glthread_INIT_COND(buf->event); + pipe_condvar_init(buf->event); LIST_ADDTAIL(&buf->head, &slab->freeBuffers); slab->numFree++; buf++; } + /* Add this slab to the list of partial slabs */ LIST_ADDTAIL(&slab->head, &mgr->slabs); return PIPE_OK; @@ -328,23 +373,29 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, if(!pb_check_usage(desc->usage, mgr->desc.usage)) return NULL; - _glthread_LOCK_MUTEX(mgr->mutex); + pipe_mutex_lock(mgr->mutex); + + /* Create a new slab, if we run out of partial slabs */ if (mgr->slabs.next == &mgr->slabs) { (void) pb_slab_create(mgr); if (mgr->slabs.next == &mgr->slabs) { - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); return NULL; } } + + /* Allocate the buffer from a partial (or just created) slab */ list = mgr->slabs.next; slab = LIST_ENTRY(struct pb_slab, list, head); + + /* If totally full remove from the partial slab list */ if (--slab->numFree == 0) LIST_DELINIT(list); list = slab->freeBuffers.next; LIST_DELINIT(list); - _glthread_UNLOCK_MUTEX(mgr->mutex); + pipe_mutex_unlock(mgr->mutex); buf = LIST_ENTRY(struct pb_slab_buffer, list, head); ++buf->base.base.refcount; @@ -386,9 +437,8 @@ pb_slab_manager_create(struct pb_manager *provider, mgr->desc = *desc; LIST_INITHEAD(&mgr->slabs); - LIST_INITHEAD(&mgr->freeSlabs); - _glthread_INIT_MUTEX(mgr->mutex); + pipe_mutex_init(mgr->mutex); return &mgr->base; } diff --git a/src/gallium/auxiliary/rtasm/rtasm_execmem.c b/src/gallium/auxiliary/rtasm/rtasm_execmem.c index dfa5c35ab6..19087589a8 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_execmem.c +++ b/src/gallium/auxiliary/rtasm/rtasm_execmem.c @@ -47,11 +47,12 @@ #include <unistd.h> #include <sys/mman.h> +#include "pipe/p_thread.h" #include "util/u_mm.h" #define EXEC_HEAP_SIZE (10*1024*1024) -_glthread_DECLARE_STATIC_MUTEX(exec_mutex); +pipe_static_mutex(exec_mutex); static struct mem_block *exec_heap = NULL; static unsigned char *exec_mem = NULL; @@ -76,7 +77,7 @@ rtasm_exec_malloc(size_t size) struct mem_block *block = NULL; void *addr = NULL; - _glthread_LOCK_MUTEX(exec_mutex); + pipe_mutex_lock(exec_mutex); init_heap(); @@ -90,7 +91,7 @@ rtasm_exec_malloc(size_t size) else debug_printf("rtasm_exec_malloc failed\n"); - _glthread_UNLOCK_MUTEX(exec_mutex); + pipe_mutex_unlock(exec_mutex); return addr; } @@ -99,7 +100,7 @@ rtasm_exec_malloc(size_t size) void rtasm_exec_free(void *addr) { - _glthread_LOCK_MUTEX(exec_mutex); + pipe_mutex_lock(exec_mutex); if (exec_heap) { struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); @@ -108,7 +109,7 @@ rtasm_exec_free(void *addr) mmFreeMem(block); } - _glthread_UNLOCK_MUTEX(exec_mutex); + pipe_mutex_unlock(exec_mutex); } diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 285ddc0e3f..61010e4333 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -151,8 +151,8 @@ static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rB = rB; inst.inst.rA = rA; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -165,8 +165,8 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rB = rB; inst.inst.rA = rA; inst.inst.rC = rC; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -178,8 +178,8 @@ static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, inst.inst.i7 = imm; inst.inst.rA = rA; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -192,8 +192,8 @@ static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, inst.inst.i8 = imm; inst.inst.rA = rA; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -206,8 +206,8 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, inst.inst.i10 = imm; inst.inst.rA = rA; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -218,8 +218,8 @@ static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, inst.inst.op = op; inst.inst.i16 = imm; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -230,8 +230,8 @@ static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, inst.inst.op = op; inst.inst.i18 = imm; inst.inst.rT = rT; - *p->csr = inst.bits; - p->csr++; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); } @@ -300,13 +300,16 @@ void _name (struct spe_function *p, int imm) \ #include "rtasm_ppc_spe.h" -/* +/** + * Initialize an spe_function. + * \param code_size size of instruction buffer to allocate, in bytes. */ void spe_init_func(struct spe_function *p, unsigned code_size) { p->store = align_malloc(code_size, 16); - p->csr = p->store; - + p->num_inst = 0; + p->max_inst = code_size / SPE_INST_SIZE; + /* Conservatively treat R0 - R2 and R80 - R127 as non-volatile. */ p->regs[0] = ~7; @@ -316,21 +319,26 @@ void spe_init_func(struct spe_function *p, unsigned code_size) void spe_release_func(struct spe_function *p) { + assert(p->num_inst <= p->max_inst); if (p->store != NULL) { align_free(p->store); } p->store = NULL; - p->csr = NULL; } +/** + * Alloate a SPE register. + * \return register index or -1 if none left. + */ int spe_allocate_available_register(struct spe_function *p) { unsigned i; - for (i = 0; i < 128; i++) { + for (i = 0; i < SPE_NUM_REGS; i++) { const uint64_t mask = (1ULL << (i % 64)); const unsigned idx = i / 64; + assert(idx < 2); if ((p->regs[idx] & mask) != 0) { p->regs[idx] &= ~mask; return i; @@ -341,11 +349,15 @@ int spe_allocate_available_register(struct spe_function *p) } +/** + * Mark the given SPE register as "allocated". + */ int spe_allocate_register(struct spe_function *p, int reg) { const unsigned idx = reg / 64; const unsigned bit = reg % 64; + assert(reg < SPE_NUM_REGS); assert((p->regs[idx] & (1ULL << bit)) != 0); p->regs[idx] &= ~(1ULL << bit); @@ -353,57 +365,75 @@ int spe_allocate_register(struct spe_function *p, int reg) } +/** + * Mark the given SPE register as "unallocated". + */ void spe_release_register(struct spe_function *p, int reg) { const unsigned idx = reg / 64; const unsigned bit = reg % 64; + assert(idx < 2); + + assert(reg < SPE_NUM_REGS); assert((p->regs[idx] & (1ULL << bit)) == 0); p->regs[idx] |= (1ULL << bit); } +/** + * For branch instructions: + * \param d if 1, disable interupts if branch is taken + * \param e if 1, enable interupts if branch is taken + * If d and e are both zero, don't change interupt status (right?) + */ - +/** Branch Indirect to address in rA */ void spe_bi(struct spe_function *p, unsigned rA, int d, int e) { emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4)); } +/** Interupt Return */ void spe_iret(struct spe_function *p, unsigned rA, int d, int e) { emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4)); } +/** Branch indirect and set link on external data */ void spe_bisled(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4)); } +/** Branch indirect and set link. Save PC in rT, jump to rA. */ void spe_bisl(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4)); } -void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d, - int e) +/** Branch indirect if zero word. If rT.word[0]==0, jump to rA. */ +void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4)); } +/** Branch indirect if non-zero word. If rT.word[0]!=0, jump to rA. */ void spe_binz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4)); } +/** Branch indirect if zero halfword. If rT.halfword[1]==0, jump to rA. */ void spe_bihz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4)); } +/** Branch indirect if non-zero halfword. If rT.halfword[1]!=0, jump to rA. */ void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4)); @@ -432,4 +462,54 @@ EMIT_R (spe_mfspr, 0x00c); EMIT_R (spe_mtspr, 0x10c); #endif + +/** + ** Helper / "macro" instructions. + ** Use somewhat verbose names as a reminder that these aren't native + ** SPE instructions. + **/ + + +void +spe_load_float(struct spe_function *p, unsigned rT, float x) +{ + union { + float f; + unsigned u; + } bits; + bits.f = x; + spe_ilhu(p, rT, bits.u >> 16); + spe_iohl(p, rT, bits.u & 0xffff); +} + + +void +spe_load_int(struct spe_function *p, unsigned rT, int i) +{ + spe_ilhu(p, rT, i >> 16); + spe_iohl(p, rT, i & 0xffff); +} + + +void +spe_complement(struct spe_function *p, unsigned rT) +{ + spe_nor(p, rT, rT, rT); +} + + +void +spe_move(struct spe_function *p, unsigned rT, unsigned rA) +{ + spe_ori(p, rT, rA, 0); +} + + +void +spe_zero(struct spe_function *p, unsigned rT) +{ + spe_xor(p, rT, rT, rT); +} + + #endif /* GALLIUM_CELL */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 1cacc717b1..dee8c55c4a 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -25,6 +25,7 @@ /** * \file * Real-time assembly generation interface for Cell B.E. SPEs. + * For details, see /opt/cell/sdk/docs/arch/SPU_ISA_v1.2_27Jan2007_pub.pdf * * \author Ian Romanick <idr@us.ibm.com> */ @@ -32,13 +33,24 @@ #ifndef RTASM_PPC_SPE_H #define RTASM_PPC_SPE_H -struct spe_function { - /** - * - */ - uint32_t *store; - uint32_t *csr; - const char *fn; +/** 4 bytes per instruction */ +#define SPE_INST_SIZE 4 + +/** number of general-purpose SIMD registers */ +#define SPE_NUM_REGS 128 + +/** Return Address register */ +#define SPE_REG_RA 0 + +/** Stack Pointer register */ +#define SPE_REG_SP 1 + + +struct spe_function +{ + uint32_t *store; /**< instruction buffer */ + uint num_inst; + uint max_inst; /** * Mask of used / unused registers @@ -50,7 +62,7 @@ struct spe_function { * spe_allocate_register, spe_allocate_available_register, * spe_release_register */ - uint64_t regs[2]; + uint64_t regs[SPE_NUM_REGS / 64]; }; extern void spe_init_func(struct spe_function *p, unsigned code_size); @@ -119,7 +131,8 @@ EMIT_RI16(spe_ilhu, 0x082); EMIT_RI16(spe_il, 0x081); EMIT_RI18(spe_ila, 0x021); EMIT_RI16(spe_iohl, 0x0c1); -EMIT_RI16(spe_fsmbi, 0x0c5); +EMIT_RI16(spe_fsmbi, 0x065); + /* Integer and logical instructions @@ -271,6 +284,27 @@ extern void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e); +/** Load/splat immediate float into rT. */ +extern void +spe_load_float(struct spe_function *p, unsigned rT, float x); + +/** Load/splat immediate int into rT. */ +extern void +spe_load_int(struct spe_function *p, unsigned rT, int i); + +/** Complement/invert all bits in rT. */ +extern void +spe_complement(struct spe_function *p, unsigned rT); + +/** rT = rA. */ +extern void +spe_move(struct spe_function *p, unsigned rT, unsigned rA); + +/** rT = {0,0,0,0}. */ +extern void +spe_zero(struct spe_function *p, unsigned rT); + + /* Floating-point instructions */ EMIT_RR (spe_fa, 0x2c4); diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index f4ca282dd9..6d4c081e04 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -27,7 +27,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_debug.h" -#include "pipe/p_pointer.h" +#include "util/u_pointer.h" #include "rtasm_execmem.h" #include "rtasm_x86sse.h" diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index a168c94928..afc8ffa553 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -37,30 +37,40 @@ struct dump_ctx uint instno; - struct util_strbuf *sbuf; + void (*printf)(struct dump_ctx *ctx, const char *format, ...); }; +static void +dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) +{ + va_list ap; + (void)ctx; + va_start(ap, format); + debug_vprintf(format, ap); + va_end(ap); +} + static void dump_enum( - struct util_strbuf *sbuf, + struct dump_ctx *ctx, uint e, const char **enums, uint enum_count ) { if (e >= enum_count) - util_strbuf_printf( sbuf, "%u", e ); + ctx->printf( ctx, "%u", e ); else - util_strbuf_printf( sbuf, "%s", enums[e] ); + ctx->printf( ctx, "%s", enums[e] ); } -#define EOL() util_strbuf_printf( sbuf, "\n" ) -#define TXT(S) util_strbuf_printf( sbuf, "%s", S ) -#define CHR(C) util_strbuf_printf( sbuf, "%c", C ) -#define UIX(I) util_strbuf_printf( sbuf, "0x%x", I ) -#define UID(I) util_strbuf_printf( sbuf, "%u", I ) -#define SID(I) util_strbuf_printf( sbuf, "%d", I ) -#define FLT(F) util_strbuf_printf( sbuf, "%10.4f", F ) -#define ENM(E,ENUMS) dump_enum( sbuf, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) +#define EOL() ctx->printf( ctx, "\n" ) +#define TXT(S) ctx->printf( ctx, "%s", S ) +#define CHR(C) ctx->printf( ctx, "%c", C ) +#define UIX(I) ctx->printf( ctx, "0x%x", I ) +#define UID(I) ctx->printf( ctx, "%u", I ) +#define SID(I) ctx->printf( ctx, "%d", I ) +#define FLT(F) ctx->printf( ctx, "%10.4f", F ) +#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) static const char *processor_type_names[] = { @@ -148,7 +158,7 @@ static const char *modulate_names[TGSI_MODULATE_COUNT] = static void _dump_register( - struct util_strbuf *sbuf, + struct dump_ctx *ctx, uint file, int first, int last ) @@ -165,7 +175,7 @@ _dump_register( static void _dump_register_ind( - struct util_strbuf *sbuf, + struct dump_ctx *ctx, uint file, int index, uint ind_file, @@ -187,7 +197,7 @@ _dump_register_ind( static void _dump_writemask( - struct util_strbuf *sbuf, + struct dump_ctx *ctx, uint writemask ) { if (writemask != TGSI_WRITEMASK_XYZW) { @@ -208,18 +218,17 @@ iter_declaration( struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl ) { - struct dump_ctx *ctx = (struct dump_ctx *) iter; - struct util_strbuf *sbuf = ctx->sbuf; + struct dump_ctx *ctx = (struct dump_ctx *)iter; TXT( "DCL " ); _dump_register( - sbuf, + ctx, decl->Declaration.File, decl->DeclarationRange.First, decl->DeclarationRange.Last ); _dump_writemask( - sbuf, + ctx, decl->Declaration.UsageMask ); if (decl->Declaration.Semantic) { @@ -245,17 +254,11 @@ void tgsi_dump_declaration( const struct tgsi_full_declaration *decl ) { - static char str[1024]; - struct util_strbuf sbuf; struct dump_ctx ctx; - util_strbuf_init(&sbuf, str, sizeof(str)); - - ctx.sbuf = &sbuf; + ctx.printf = dump_ctx_printf; iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl ); - - debug_printf("%s", str); } static boolean @@ -264,7 +267,6 @@ iter_immediate( struct tgsi_full_immediate *imm ) { struct dump_ctx *ctx = (struct dump_ctx *) iter; - struct util_strbuf *sbuf = ctx->sbuf; uint i; @@ -295,17 +297,11 @@ void tgsi_dump_immediate( const struct tgsi_full_immediate *imm ) { - static char str[1024]; - struct util_strbuf sbuf; struct dump_ctx ctx; - util_strbuf_init(&sbuf, str, sizeof(str)); - - ctx.sbuf = &sbuf; + ctx.printf = dump_ctx_printf; iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm ); - - debug_printf("%s", str); } static boolean @@ -314,7 +310,6 @@ iter_instruction( struct tgsi_full_instruction *inst ) { struct dump_ctx *ctx = (struct dump_ctx *) iter; - struct util_strbuf *sbuf = ctx->sbuf; uint instno = ctx->instno++; uint i; @@ -345,12 +340,12 @@ iter_instruction( CHR( ' ' ); _dump_register( - sbuf, + ctx, dst->DstRegister.File, dst->DstRegister.Index, dst->DstRegister.Index ); ENM( dst->DstRegisterExtModulate.Modulate, modulate_names ); - _dump_writemask( sbuf, dst->DstRegister.WriteMask ); + _dump_writemask( ctx, dst->DstRegister.WriteMask ); first_reg = FALSE; } @@ -377,7 +372,7 @@ iter_instruction( if (src->SrcRegister.Indirect) { _dump_register_ind( - sbuf, + ctx, src->SrcRegister.File, src->SrcRegister.Index, src->SrcRegisterInd.File, @@ -385,7 +380,7 @@ iter_instruction( } else { _dump_register( - sbuf, + ctx, src->SrcRegister.File, src->SrcRegister.Index, src->SrcRegister.Index ); @@ -460,18 +455,12 @@ tgsi_dump_instruction( const struct tgsi_full_instruction *inst, uint instno ) { - static char str[1024]; - struct util_strbuf sbuf; struct dump_ctx ctx; - util_strbuf_init(&sbuf, str, sizeof(str)); - ctx.instno = instno; - ctx.sbuf = &sbuf; + ctx.printf = dump_ctx_printf; iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); - - debug_printf("%s", str); } static boolean @@ -479,7 +468,6 @@ prolog( struct tgsi_iterate_context *iter ) { struct dump_ctx *ctx = (struct dump_ctx *) iter; - struct util_strbuf *sbuf = ctx->sbuf; ENM( iter->processor.Processor, processor_type_names ); UID( iter->version.MajorVersion ); CHR( '.' ); @@ -489,17 +477,12 @@ prolog( } void -tgsi_dump_str( +tgsi_dump( const struct tgsi_token *tokens, - uint flags, - char *str, - size_t size) + uint flags ) { - struct util_strbuf sbuf; struct dump_ctx ctx; - util_strbuf_init(&sbuf, str, size); - ctx.iter.prolog = prolog; ctx.iter.iterate_instruction = iter_instruction; ctx.iter.iterate_declaration = iter_declaration; @@ -507,34 +490,57 @@ tgsi_dump_str( ctx.iter.epilog = NULL; ctx.instno = 0; - ctx.sbuf = &sbuf; + ctx.printf = dump_ctx_printf; tgsi_iterate_shader( tokens, &ctx.iter ); } +struct str_dump_ctx +{ + struct dump_ctx base; + char *str; + char *ptr; + size_t left; +}; + +static void +str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) +{ + struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx; + + if(sctx->left > 1) { + size_t written; + va_list ap; + va_start(ap, format); + written = util_vsnprintf(sctx->ptr, sctx->left, format, ap); + va_end(ap); + sctx->ptr += written; + sctx->left -= written; + } +} + void -tgsi_dump( +tgsi_dump_str( const struct tgsi_token *tokens, - uint flags ) + uint flags, + char *str, + size_t size) { - static char str[4096]; - uint len; - char *p = str; - - tgsi_dump_str(tokens, flags, str, sizeof(str)); - - /* Workaround output buffer size limitations. - */ - len = strlen( str ); - while (len > 256) { - char piggy_bank; - - piggy_bank = p[256]; - p[256] = '\0'; - debug_printf( "%s", p ); - p[256] = piggy_bank; - p += 256; - len -= 256; - } - debug_printf( "%s", p ); + struct str_dump_ctx ctx; + + ctx.base.iter.prolog = prolog; + ctx.base.iter.iterate_instruction = iter_instruction; + ctx.base.iter.iterate_declaration = iter_declaration; + ctx.base.iter.iterate_immediate = iter_immediate; + ctx.base.iter.epilog = NULL; + + ctx.base.instno = 0; + ctx.base.printf = &str_dump_ctx_printf; + + ctx.str = str; + ctx.str[0] = 0; + ctx.ptr = str; + ctx.left = size; + + tgsi_iterate_shader( tokens, &ctx.base.iter ); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index fb573fe1f0..df002939c6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -957,6 +957,7 @@ fetch_src_file_channel( case TGSI_EXTSWIZZLE_W: switch( file ) { case TGSI_FILE_CONSTANT: + assert(mach->Consts); chan->f[0] = mach->Consts[index->i[0]][swizzle]; chan->f[1] = mach->Consts[index->i[1]][swizzle]; chan->f[2] = mach->Consts[index->i[2]][swizzle]; diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index 0b5bdd6ba1..c659027296 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -322,7 +322,7 @@ epilog( /* Print totals, if any. */ if (ctx->errors || ctx->warnings) - debug_printf( "\n%u errors, %u warnings", ctx->errors, ctx->warnings ); + debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings ); return TRUE; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 626724ad4e..4681b29f52 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -601,12 +601,10 @@ static void PIPE_CDECL cos4f( float *store ) { - const unsigned X = 0; - - store[X + 0] = cosf( store[X + 0] ); - store[X + 1] = cosf( store[X + 1] ); - store[X + 2] = cosf( store[X + 2] ); - store[X + 3] = cosf( store[X + 3] ); + store[0] = cosf( store[0] ); + store[1] = cosf( store[1] ); + store[2] = cosf( store[2] ); + store[3] = cosf( store[3] ); } static void @@ -624,18 +622,16 @@ static void PIPE_CDECL ex24f( float *store ) { - const unsigned X = 0; - #if FAST_MATH - store[X + 0] = util_fast_exp2( store[X + 0] ); - store[X + 1] = util_fast_exp2( store[X + 1] ); - store[X + 2] = util_fast_exp2( store[X + 2] ); - store[X + 3] = util_fast_exp2( store[X + 3] ); + store[0] = util_fast_exp2( store[0] ); + store[1] = util_fast_exp2( store[1] ); + store[2] = util_fast_exp2( store[2] ); + store[3] = util_fast_exp2( store[3] ); #else - store[X + 0] = powf( 2.0f, store[X + 0] ); - store[X + 1] = powf( 2.0f, store[X + 1] ); - store[X + 2] = powf( 2.0f, store[X + 2] ); - store[X + 3] = powf( 2.0f, store[X + 3] ); + store[0] = powf( 2.0f, store[0] ); + store[1] = powf( 2.0f, store[1] ); + store[2] = powf( 2.0f, store[2] ); + store[3] = powf( 2.0f, store[3] ); #endif } @@ -665,12 +661,10 @@ static void PIPE_CDECL flr4f( float *store ) { - const unsigned X = 0; - - store[X + 0] = floorf( store[X + 0] ); - store[X + 1] = floorf( store[X + 1] ); - store[X + 2] = floorf( store[X + 2] ); - store[X + 3] = floorf( store[X + 3] ); + store[0] = floorf( store[0] ); + store[1] = floorf( store[1] ); + store[2] = floorf( store[2] ); + store[3] = floorf( store[3] ); } static void @@ -688,12 +682,10 @@ static void PIPE_CDECL frc4f( float *store ) { - const unsigned X = 0; - - store[X + 0] -= floorf( store[X + 0] ); - store[X + 1] -= floorf( store[X + 1] ); - store[X + 2] -= floorf( store[X + 2] ); - store[X + 3] -= floorf( store[X + 3] ); + store[0] -= floorf( store[0] ); + store[1] -= floorf( store[1] ); + store[2] -= floorf( store[2] ); + store[3] -= floorf( store[3] ); } static void @@ -711,12 +703,10 @@ static void PIPE_CDECL lg24f( float *store ) { - const unsigned X = 0; - - store[X + 0] = util_fast_log2( store[X + 0] ); - store[X + 1] = util_fast_log2( store[X + 1] ); - store[X + 2] = util_fast_log2( store[X + 2] ); - store[X + 3] = util_fast_log2( store[X + 3] ); + store[0] = util_fast_log2( store[0] ); + store[1] = util_fast_log2( store[1] ); + store[2] = util_fast_log2( store[2] ); + store[3] = util_fast_log2( store[3] ); } static void @@ -770,18 +760,16 @@ static void PIPE_CDECL pow4f( float *store ) { - const unsigned X = 0; - #if FAST_MATH - store[X + 0] = util_fast_pow( store[X + 0], store[X + 4] ); - store[X + 1] = util_fast_pow( store[X + 1], store[X + 5] ); - store[X + 2] = util_fast_pow( store[X + 2], store[X + 6] ); - store[X + 3] = util_fast_pow( store[X + 3], store[X + 7] ); + store[0] = util_fast_pow( store[0], store[4] ); + store[1] = util_fast_pow( store[1], store[5] ); + store[2] = util_fast_pow( store[2], store[6] ); + store[3] = util_fast_pow( store[3], store[7] ); #else - store[X + 0] = powf( store[X + 0], store[X + 4] ); - store[X + 1] = powf( store[X + 1], store[X + 5] ); - store[X + 2] = powf( store[X + 2], store[X + 6] ); - store[X + 3] = powf( store[X + 3], store[X + 7] ); + store[0] = powf( store[0], store[4] ); + store[1] = powf( store[1], store[5] ); + store[2] = powf( store[2], store[6] ); + store[3] = powf( store[3], store[7] ); #endif } @@ -877,12 +865,10 @@ static void PIPE_CDECL sin4f( float *store ) { - const unsigned X = 0; - - store[X + 0] = sinf( store[X + 0] ); - store[X + 1] = sinf( store[X + 1] ); - store[X + 2] = sinf( store[X + 2] ); - store[X + 3] = sinf( store[X + 3] ); + store[0] = sinf( store[0] ); + store[1] = sinf( store[1] ); + store[2] = sinf( store[2] ); + store[3] = sinf( store[3] ); } static void @@ -2416,3 +2402,4 @@ tgsi_emit_sse2( } #endif /* PIPE_ARCH_X86 */ + diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c index 4d336f47ea..8d39b64c6c 100644 --- a/src/gallium/auxiliary/translate/translate_generic.c +++ b/src/gallium/auxiliary/translate/translate_generic.c @@ -415,6 +415,12 @@ static fetch_func get_fetch_func( enum pipe_format format ) static emit_func get_emit_func( enum pipe_format format ) { + /* silence warnings */ + (void) emit_R32G32B32A32_FIXED; + (void) emit_R32G32B32_FIXED; + (void) emit_R32G32_FIXED; + (void) emit_R32_FIXED; + switch (format) { case PIPE_FORMAT_R64_FLOAT: return &emit_R64_FLOAT; diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile index 6e5fd26c05..d3951e4e7d 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -15,8 +15,11 @@ C_SOURCES = \ u_rect.c \ u_simple_shaders.c \ u_snprintf.c \ + u_stream_stdc.c \ + u_stream_wd.c \ u_tile.c \ - u_time.c + u_time.c \ + u_timed_winsys.c include ../../Makefile.template diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index ce3fad7068..e65c17b1cc 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -16,6 +16,8 @@ util = env.ConvenienceLibrary( 'u_rect.c', 'u_simple_shaders.c', 'u_snprintf.c', + 'u_stream_stdc.c', + 'u_stream_wd.c', 'u_tile.c', 'u_time.c', ]) diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index 7d1dba5a24..b6cff281e6 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -55,7 +55,11 @@ #include "pipe/p_format.h" #include "pipe/p_state.h" #include "pipe/p_inlines.h" +#include "util/u_memory.h" #include "util/u_string.h" +#include "util/u_stream.h" +#include "util/u_math.h" +#include "util/u_tile.h" #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY @@ -76,7 +80,7 @@ void _debug_vprintf(const char *format, va_list ap) /* EngDebugPrint does not handle float point arguments, so we need to use * our own vsnprintf implementation. It is also very slow, so buffer until * we find a newline. */ - static char buf[512 + 1] = {'\0'}; + static char buf[512] = {'\0'}; size_t len = strlen(buf); int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap); if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) { @@ -584,4 +588,109 @@ error2: error1: ; } + + +#pragma pack(push,2) +struct bmp_file_header { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; +#pragma pack(pop) + +struct bmp_info_header { + uint32_t biSize; + int32_t biWidth; + int32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter; + int32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +}; + +struct bmp_rgb_quad { + uint8_t rgbBlue; + uint8_t rgbGreen; + uint8_t rgbRed; + uint8_t rgbAlpha; +}; + +void +debug_dump_surface_bmp(const char *filename, + struct pipe_surface *surface) +{ + struct util_stream *stream; + unsigned surface_usage; + struct bmp_file_header bmfh; + struct bmp_info_header bmih; + float *rgba; + unsigned x, y; + + if (!surface) + goto error1; + + rgba = MALLOC(surface->width*4*sizeof(float)); + if(!rgba) + goto error1; + + bmfh.bfType = 0x4d42; + bmfh.bfSize = 14 + 40 + surface->height*surface->width*4; + bmfh.bfReserved1 = 0; + bmfh.bfReserved2 = 0; + bmfh.bfOffBits = 14 + 40; + + bmih.biSize = 40; + bmih.biWidth = surface->width; + bmih.biHeight = surface->height; + bmih.biPlanes = 1; + bmih.biBitCount = 32; + bmih.biCompression = 0; + bmih.biSizeImage = surface->height*surface->width*4; + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + bmih.biClrUsed = 0; + bmih.biClrImportant = 0; + + stream = util_stream_create(filename, bmfh.bfSize); + if(!stream) + goto error2; + + util_stream_write(stream, &bmfh, 14); + util_stream_write(stream, &bmih, 40); + + /* XXX: force mappable surface */ + surface_usage = surface->usage; + surface->usage |= PIPE_BUFFER_USAGE_CPU_READ; + + y = surface->height; + while(y--) { + pipe_get_tile_rgba(surface, + 0, y, surface->width, 1, + rgba); + for(x = 0; x < surface->width; ++x) + { + struct bmp_rgb_quad pixel; + pixel.rgbRed = float_to_ubyte(rgba[x*4 + 0]); + pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]); + pixel.rgbBlue = float_to_ubyte(rgba[x*4 + 2]); + pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]); + util_stream_write(stream, &pixel, 4); + } + } + + surface->usage = surface_usage; + + util_stream_close(stream); +error2: + FREE(rgba); +error1: + ; +} + #endif diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 05399f9885..9adf72944e 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -138,10 +138,10 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) /* fragment shader */ ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader); - ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys, - 32, - PIPE_BUFFER_USAGE_VERTEX, - sizeof(ctx->vertices)); + ctx->vbuf = pipe_buffer_create(pipe->screen, + 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(ctx->vertices)); if (!ctx->vbuf) { FREE(ctx); ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs); @@ -174,7 +174,7 @@ util_destroy_blit(struct blit_state *ctx) FREE((void*) ctx->vert_shader.tokens); FREE((void*) ctx->frag_shader.tokens); - pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf); + pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL); FREE(ctx); } @@ -214,12 +214,12 @@ setup_vertex_data(struct blit_state *ctx, ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = 1.0f; - buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); + buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); - ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); + pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf); } @@ -259,12 +259,12 @@ setup_vertex_data_tex(struct blit_state *ctx, ctx->vertices[3][1][0] = s0; ctx->vertices[3][1][1] = t1; - buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); + buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); - ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); + pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf); } /** * Copy pixel block from src surface to dst surface. diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index bf143815d8..8ecae71b64 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -86,11 +86,11 @@ util_draw_texquad(struct pipe_context *pipe, vertexBytes = 4 * (4 * numAttribs * sizeof(float)); /* XXX create one-time */ - vbuf = pipe->winsys->buffer_create(pipe->winsys, 32, - PIPE_BUFFER_USAGE_VERTEX, vertexBytes); + vbuf = pipe_buffer_create(pipe->screen, 32, + PIPE_BUFFER_USAGE_VERTEX, vertexBytes); if (vbuf) { - float *v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); + float *v = (float *) pipe_buffer_map(pipe->screen, vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); if (v) { /* * Load vertex buffer @@ -123,10 +123,10 @@ util_draw_texquad(struct pipe_context *pipe, v[28] = 0.0; v[29] = 1.0; - pipe->winsys->buffer_unmap(pipe->winsys, vbuf); + pipe_buffer_unmap(pipe->screen, vbuf); util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2); } - pipe_buffer_reference(pipe->winsys, &vbuf, NULL); + pipe_buffer_reference(pipe->screen, &vbuf, NULL); } } diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index c1e2c19f87..b19a649bbc 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -580,7 +580,6 @@ make_1d_mipmap(struct gen_mipmap_state *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_winsys *winsys = pipe->winsys; const uint zslice = 0; uint dstLevel; @@ -595,19 +594,19 @@ make_1d_mipmap(struct gen_mipmap_state *ctx, dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, PIPE_BUFFER_USAGE_CPU_WRITE); - srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer, - PIPE_BUFFER_USAGE_CPU_READ) + srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer, + PIPE_BUFFER_USAGE_CPU_READ) + srcSurf->offset); - dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE) + dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer, + PIPE_BUFFER_USAGE_CPU_WRITE) + dstSurf->offset); reduce_1d(pt->format, srcSurf->width, srcMap, dstSurf->width, dstMap); - winsys->buffer_unmap(winsys, srcSurf->buffer); - winsys->buffer_unmap(winsys, dstSurf->buffer); + pipe_buffer_unmap(screen, srcSurf->buffer); + pipe_buffer_unmap(screen, dstSurf->buffer); pipe_surface_reference(&srcSurf, NULL); pipe_surface_reference(&dstSurf, NULL); @@ -622,7 +621,6 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_winsys *winsys = pipe->winsys; const uint zslice = 0; uint dstLevel; @@ -639,11 +637,11 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, PIPE_BUFFER_USAGE_CPU_WRITE); - srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer, - PIPE_BUFFER_USAGE_CPU_READ) + srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer, + PIPE_BUFFER_USAGE_CPU_READ) + srcSurf->offset); - dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE) + dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer, + PIPE_BUFFER_USAGE_CPU_WRITE) + dstSurf->offset); reduce_2d(pt->format, @@ -652,8 +650,8 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, dstSurf->width, dstSurf->height, dstSurf->stride, dstMap); - winsys->buffer_unmap(winsys, srcSurf->buffer); - winsys->buffer_unmap(winsys, dstSurf->buffer); + pipe_buffer_unmap(screen, srcSurf->buffer); + pipe_buffer_unmap(screen, dstSurf->buffer); pipe_surface_reference(&srcSurf, NULL); pipe_surface_reference(&dstSurf, NULL); @@ -759,10 +757,10 @@ util_create_gen_mipmap(struct pipe_context *pipe, /* fragment shader */ ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader); - ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys, - 32, - PIPE_BUFFER_USAGE_VERTEX, - sizeof(ctx->vertices)); + ctx->vbuf = pipe_buffer_create(pipe->screen, + 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(ctx->vertices)); if (!ctx->vbuf) { FREE(ctx); return NULL; @@ -805,12 +803,12 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height) ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = 1.0f; - buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); + buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); - ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); + pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf); } @@ -829,7 +827,7 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx) FREE((void*) ctx->vert_shader.tokens); FREE((void*) ctx->frag_shader.tokens); - pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf); + pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL); FREE(ctx); } diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h index 8fbbb4e55d..857102719d 100644 --- a/src/gallium/auxiliary/util/u_memory.h +++ b/src/gallium/auxiliary/util/u_memory.h @@ -39,7 +39,12 @@ #include "pipe/p_debug.h" - /* Define ENOMEM for WINCE */ +#ifdef __cplusplus +extern "C" { +#endif + + +/* Define ENOMEM for WINCE */ #if (_WIN32_WCE < 600) #ifndef ENOMEM #define ENOMEM 12 @@ -47,7 +52,6 @@ #endif - #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && defined(DEBUG) /* memory debugging */ @@ -220,4 +224,9 @@ mem_dup(const void *src, uint size) +#ifdef __cplusplus +} +#endif + + #endif /* U_MEMORY_H */ diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 39e4ae9d07..e0e8aa8e9f 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -142,6 +142,161 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, /** + * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. + */ +static INLINE void +util_unpack_color_ub(enum pipe_format format, const void *src, + ubyte *r, ubyte *g, ubyte *b, ubyte *a) +{ + switch (format) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_R8G8B8X8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) ((p >> 24) & 0xff); + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uint p = ((const uint *) src)[0]; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_R5G6B5_UNORM: + { + ushort p = ((const ushort *) src)[0]; + *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); + *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_A1R5G5B5_UNORM: + { + ushort p = ((const ushort *) src)[0]; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) (0xff * (p >> 15)); + } + return; + case PIPE_FORMAT_A4R4G4B4_UNORM: + { + ushort p = ((const ushort *) src)[0]; + *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); + *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); + *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); + *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte p = ((const ubyte *) src)[0]; + *r = *g = *b = (ubyte) 0xff; + *a = p; + } + return; + case PIPE_FORMAT_L8_UNORM: + { + ubyte p = ((const ubyte *) src)[0]; + *r = *g = *b = p; + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_I8_UNORM: + { + ubyte p = ((const ubyte *) src)[0]; + *r = *g = *b = *a = p; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + const float *p = (const float *) src; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = float_to_ubyte(p[3]); + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + const float *p = (const float *) src; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32G32_FLOAT: + { + const float *p = (const float *) src; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32_FLOAT: + { + const float *p = (const float *) src; + *r = float_to_ubyte(p[0]); + *g = *b = *a = (ubyte) 0xff; + } + return; + + /* XXX lots more cases to add */ + default: + debug_print_format("gallium: unhandled format in util_unpack_color_ub()", + format); + assert(0); + } +} + + + +/** * Note rgba outside [0,1] will be clamped for int pixel formats. */ static INLINE void diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c index b31ab5415f..f5619ef791 100644 --- a/src/gallium/auxiliary/util/u_rect.c +++ b/src/gallium/auxiliary/util/u_rect.c @@ -32,6 +32,8 @@ #include "pipe/p_defines.h" #include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" #include "util/u_rect.h" @@ -148,3 +150,179 @@ pipe_fill_rect(ubyte * dst, break; } } + + + +/** + * Fallback function for pipe->surface_copy(). + * Note: (X,Y)=(0,0) is always the upper-left corner. + * if do_flip, flip the image vertically on its way from src rect to dst rect. + * XXX should probably put this in new u_surface.c file... + */ +void +util_surface_copy(struct pipe_context *pipe, + boolean do_flip, + struct pipe_surface *dst, + unsigned dst_x, unsigned dst_y, + struct pipe_surface *src, + unsigned src_x, unsigned src_y, + unsigned w, unsigned h) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *new_src = NULL, *new_dst = NULL; + void *dst_map; + const void *src_map; + + assert(dst->block.size == src->block.size); + assert(dst->block.width == src->block.width); + assert(dst->block.height == src->block.height); + + if ((src->usage & PIPE_BUFFER_USAGE_CPU_READ) == 0) { + /* Need to create new src surface which is CPU readable */ + assert(src->texture); + if (!src->texture) + return; + new_src = screen->get_tex_surface(screen, + src->texture, + src->face, + src->level, + src->zslice, + PIPE_BUFFER_USAGE_CPU_READ); + src = new_src; + } + + if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) { + /* Need to create new dst surface which is CPU writable */ + assert(dst->texture); + if (!dst->texture) + return; + new_dst = screen->get_tex_surface(screen, + dst->texture, + dst->face, + dst->level, + dst->zslice, + PIPE_BUFFER_USAGE_CPU_WRITE); + dst = new_dst; + } + + src_map = pipe->screen->surface_map(screen, + src, PIPE_BUFFER_USAGE_CPU_READ); + dst_map = pipe->screen->surface_map(screen, + dst, PIPE_BUFFER_USAGE_CPU_WRITE); + + assert(src_map); + assert(dst_map); + + if (src_map && dst_map) { + /* If do_flip, invert src_y position and pass negative src stride */ + pipe_copy_rect(dst_map, + &dst->block, + dst->stride, + dst_x, dst_y, + w, h, + src_map, + do_flip ? -(int) src->stride : src->stride, + src_x, src_y); + } + + pipe->screen->surface_unmap(pipe->screen, src); + pipe->screen->surface_unmap(pipe->screen, dst); + + if (new_src) + screen->tex_surface_release(screen, &new_src); + if (new_dst) + screen->tex_surface_release(screen, &new_dst); +} + + + +static void * +get_pointer(struct pipe_surface *dst, void *dst_map, unsigned x, unsigned y) +{ + return (char *)dst_map + + y / dst->block.height * dst->stride + + x / dst->block.width * dst->block.size; +} + + +#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) + + +/** + * Fallback for pipe->surface_fill() function. + * XXX should probably put this in new u_surface.c file... + */ +void +util_surface_fill(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, unsigned value) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *new_dst = NULL; + void *dst_map; + + if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) { + /* Need to create new dst surface which is CPU writable */ + assert(dst->texture); + if (!dst->texture) + return; + new_dst = screen->get_tex_surface(screen, + dst->texture, + dst->face, + dst->level, + dst->zslice, + PIPE_BUFFER_USAGE_CPU_WRITE); + dst = new_dst; + } + + dst_map = pipe->screen->surface_map(screen, + dst, PIPE_BUFFER_USAGE_CPU_WRITE); + + assert(dst_map); + + if (dst_map) { + assert(dst->stride > 0); + + switch (dst->block.size) { + case 1: + case 2: + case 4: + pipe_fill_rect(dst_map, &dst->block, dst->stride, + dstx, dsty, width, height, value); + break; + case 8: + { + /* expand the 4-byte clear value to an 8-byte value */ + ushort *row = (ushort *) get_pointer(dst, dst_map, dstx, dsty); + ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff); + ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff); + ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff); + ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff); + unsigned i, j; + val0 = (val0 << 8) | val0; + val1 = (val1 << 8) | val1; + val2 = (val2 << 8) | val2; + val3 = (val3 << 8) | val3; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + row[j*4+0] = val0; + row[j*4+1] = val1; + row[j*4+2] = val2; + row[j*4+3] = val3; + } + row += dst->stride/2; + } + } + break; + default: + assert(0); + break; + } + } + + pipe->screen->surface_unmap(pipe->screen, dst); + + if (new_dst) + screen->tex_surface_release(screen, &new_dst); +} diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h index fba4808864..59e842e16d 100644 --- a/src/gallium/auxiliary/util/u_rect.h +++ b/src/gallium/auxiliary/util/u_rect.h @@ -37,6 +37,9 @@ #include "pipe/p_format.h" +struct pipe_context; +struct pipe_surface; + extern void pipe_copy_rect(ubyte * dst, const struct pipe_format_block *block, @@ -50,5 +53,20 @@ pipe_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned width, unsigned height, uint32_t value); +extern void +util_surface_copy(struct pipe_context *pipe, + boolean do_flip, + struct pipe_surface *dst, + unsigned dst_x, unsigned dst_y, + struct pipe_surface *src, + unsigned src_x, unsigned src_y, + unsigned w, unsigned h); + +extern void +util_surface_fill(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, unsigned value); + #endif /* U_RECT_H */ diff --git a/src/gallium/auxiliary/util/u_stream.h b/src/gallium/auxiliary/util/u_stream.h new file mode 100644 index 0000000000..a9d0f0121a --- /dev/null +++ b/src/gallium/auxiliary/util/u_stream.h @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2008 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 + * Cross-platform sequential access stream abstraction. + */ + +#ifndef U_STREAM_H +#define U_STREAM_H + + +#include "pipe/p_compiler.h" + + +struct util_stream; + + +/** + * Create a stream + * @param filename relative or absolute path (necessary for windows) + * @param optional maximum file size (0 for a growable size). + */ +struct util_stream * +util_stream_create(const char *filename, size_t max_size); + +boolean +util_stream_write(struct util_stream *stream, const void *data, size_t size); + +void +util_stream_flush(struct util_stream *stream); + +void +util_stream_close(struct util_stream *stream); + + +#endif /* U_STREAM_H */ diff --git a/src/gallium/auxiliary/util/u_stream_stdc.c b/src/gallium/auxiliary/util/u_stream_stdc.c new file mode 100644 index 0000000000..ca80bef0f3 --- /dev/null +++ b/src/gallium/auxiliary/util/u_stream_stdc.c @@ -0,0 +1,106 @@ +/************************************************************************** + * + * Copyright 2008 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 + * Stream implementation based on the Standard C Library. + */ + +#include "pipe/p_config.h" + +#if defined(PIPE_OS_LINUX) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) + +#include <stdio.h> + +#include "util/u_memory.h" + +#include "u_stream.h" + + +struct util_stream +{ + FILE *file; +}; + + +struct util_stream * +util_stream_create(const char *filename, size_t max_size) +{ + struct util_stream *stream; + + (void)max_size; + + stream = CALLOC_STRUCT(util_stream); + if(!stream) + goto error1; + + stream->file = fopen(filename, "w"); + if(!stream->file) + goto error2; + + return stream; + +error2: + FREE(stream); +error1: + return NULL; +} + + +boolean +util_stream_write(struct util_stream *stream, const void *data, size_t size) +{ + if(!stream) + return FALSE; + + return fwrite(data, size, 1, stream->file) == size ? TRUE : FALSE; +} + + +void +util_stream_flush(struct util_stream *stream) +{ + if(!stream) + return; + + fflush(stream->file); +} + + +void +util_stream_close(struct util_stream *stream) +{ + if(!stream) + return; + + fclose(stream->file); + + FREE(stream); +} + + +#endif diff --git a/src/gallium/auxiliary/util/u_stream_wd.c b/src/gallium/auxiliary/util/u_stream_wd.c new file mode 100644 index 0000000000..864489e775 --- /dev/null +++ b/src/gallium/auxiliary/util/u_stream_wd.c @@ -0,0 +1,224 @@ +/************************************************************************** + * + * Copyright 2008 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 + * Stream implementation for the Windows Display driver. + */ + +#include "pipe/p_config.h" + +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) + +#include <windows.h> +#include <winddi.h> + +#include "util/u_memory.h" +#include "util/u_string.h" + +#include "u_stream.h" + + +#define MAP_FILE_SIZE (4*1024*1024) + + +struct util_stream +{ + char filename[MAX_PATH + 1]; + WCHAR wFileName[MAX_PATH + 1]; + boolean growable; + size_t map_size; + ULONG_PTR iFile; + char *pMap; + size_t written; + unsigned suffix; +}; + + +static INLINE boolean +util_stream_map(struct util_stream *stream) +{ + ULONG BytesInUnicodeString; + static char filename[MAX_PATH + 1]; + unsigned filename_len; + + if(stream->growable) + filename_len = util_snprintf(filename, + sizeof(filename), + "%s.%04x", + stream->filename, + stream->suffix++); + else + filename_len = util_snprintf(filename, + sizeof(filename), + "%s", + stream->filename); + + EngMultiByteToUnicodeN( + stream->wFileName, + sizeof(stream->wFileName), + &BytesInUnicodeString, + filename, + filename_len); + + stream->pMap = EngMapFile(stream->wFileName, stream->map_size, &stream->iFile); + if(!stream->pMap) + return FALSE; + + memset(stream->pMap, 0, stream->map_size); + stream->written = 0; + + return TRUE; +} + + +static INLINE void +util_stream_unmap(struct util_stream *stream) +{ + EngUnmapFile(stream->iFile); + if(stream->written < stream->map_size) { + /* Truncate file size */ + stream->pMap = EngMapFile(stream->wFileName, stream->written, &stream->iFile); + if(stream->pMap) + EngUnmapFile(stream->iFile); + } + + stream->pMap = NULL; +} + + +static INLINE void +util_stream_full_qualified_filename(char *dst, size_t size, const char *src) +{ + boolean need_drive, need_root; + + if((('A' <= src[0] && src[0] <= 'Z') || ('a' <= src[0] && src[0] <= 'z')) && src[1] == ':') { + need_drive = FALSE; + need_root = src[2] == '\\' ? FALSE : TRUE; + } + else { + need_drive = TRUE; + need_root = src[0] == '\\' ? FALSE : TRUE; + } + + util_snprintf(dst, size, + "\\??\\%s%s%s", + need_drive ? "C:" : "", + need_root ? "\\" : "", + src); +} + + +struct util_stream * +util_stream_create(const char *filename, size_t max_size) +{ + struct util_stream *stream; + + stream = CALLOC_STRUCT(util_stream); + if(!stream) + goto error1; + + util_stream_full_qualified_filename(stream->filename, + sizeof(stream->filename), + filename); + + if(max_size) { + stream->growable = FALSE; + stream->map_size = max_size; + } + else { + stream->growable = TRUE; + stream->map_size = MAP_FILE_SIZE; + } + + if(!util_stream_map(stream)) + goto error2; + + return stream; + +error2: + FREE(stream); +error1: + return NULL; +} + + +static INLINE void +util_stream_copy(struct util_stream *stream, const char *data, size_t size) +{ + assert(stream->written + size <= stream->map_size); + memcpy(stream->pMap + stream->written, data, size); + stream->written += size; +} + + +boolean +util_stream_write(struct util_stream *stream, const void *data, size_t size) +{ + if(!stream) + return FALSE; + + if(!stream->pMap) + return FALSE; + + while(stream->written + size > stream->map_size) { + size_t step = stream->map_size - stream->written; + util_stream_copy(stream, data, step); + data = (const char *)data + step; + size -= step; + + util_stream_unmap(stream); + if(!stream->growable || !util_stream_map(stream)) + return FALSE; + } + + util_stream_copy(stream, data, size); + + return TRUE; +} + + +void +util_stream_flush(struct util_stream *stream) +{ + (void)stream; +} + + +void +util_stream_close(struct util_stream *stream) +{ + if(!stream) + return; + + util_stream_unmap(stream); + + FREE(stream); +} + + +#endif diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c index 49dce75289..bf7d1d1c8d 100644 --- a/src/gallium/auxiliary/util/u_time.c +++ b/src/gallium/auxiliary/util/u_time.c @@ -136,6 +136,26 @@ util_time_diff(const struct util_time *t1, } + +uint64_t +util_time_micros( void ) +{ + struct util_time t1; + + util_time_get(&t1); + +#if defined(PIPE_OS_LINUX) + return t1.tv.tv_usec + t1.tv.tv_sec*1000000LL; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + util_time_get_frequency(); + return t1.counter*INT64_C(1000000)/frequency; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + return t1.counter/10; +#endif +} + + + /** * Compare two time values. * diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h index f9963ce0e2..35d97d16c7 100644 --- a/src/gallium/auxiliary/util/u_time.h +++ b/src/gallium/auxiliary/util/u_time.h @@ -74,6 +74,9 @@ util_time_add(const struct util_time *t1, int64_t usecs, struct util_time *t2); +uint64_t +util_time_micros( void ); + int64_t util_time_diff(const struct util_time *t1, const struct util_time *t2); diff --git a/src/gallium/auxiliary/util/u_timed_winsys.c b/src/gallium/auxiliary/util/u_timed_winsys.c new file mode 100644 index 0000000000..8beb3b4c88 --- /dev/null +++ b/src/gallium/auxiliary/util/u_timed_winsys.c @@ -0,0 +1,346 @@ +/************************************************************************** + * + * 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. + * + * + **************************************************************************/ +/* + * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> + */ + +#include "pipe/p_winsys.h" +#include "u_timed_winsys.h" +#include "util/u_memory.h" +#include "util/u_time.h" + + +struct timed_winsys { + struct pipe_winsys base; + struct pipe_winsys *backend; + uint64_t last_dump; + struct { + const char *name_key; + double total; + unsigned calls; + } funcs[13]; +}; + + +static struct timed_winsys *timed_winsys( struct pipe_winsys *winsys ) +{ + return (struct timed_winsys *)winsys; +} + + +static uint64_t time_start( void ) +{ + return util_time_micros(); +} + + +static void time_display( struct pipe_winsys *winsys ) +{ + struct timed_winsys *tws = timed_winsys(winsys); + unsigned i; + double overall = 0; + + for (i = 0; i < Elements(tws->funcs); i++) { + if (tws->funcs[i].name_key) { + debug_printf("*** %-25s %5.3fms (%d calls, avg %.3fms)\n", + tws->funcs[i].name_key, + tws->funcs[i].total, + tws->funcs[i].calls, + tws->funcs[i].total / tws->funcs[i].calls); + overall += tws->funcs[i].total; + tws->funcs[i].calls = 0; + tws->funcs[i].total = 0; + } + } + + debug_printf("*** %-25s %5.3fms\n", + "OVERALL WINSYS", + overall); +} + +static void time_finish( struct pipe_winsys *winsys, + long long startval, + unsigned idx, + const char *name ) +{ + struct timed_winsys *tws = timed_winsys(winsys); + uint64_t endval = util_time_micros(); + double elapsed = (endval - startval)/1000.0; + + if (endval - startval > 1000LL) + debug_printf("*** %s %.3f\n", name, elapsed ); + + assert( tws->funcs[idx].name_key == name || + tws->funcs[idx].name_key == NULL); + + tws->funcs[idx].name_key = name; + tws->funcs[idx].total += elapsed; + tws->funcs[idx].calls++; + + if (endval - tws->last_dump > 10LL * 1000LL * 1000LL) { + time_display( winsys ); + tws->last_dump = endval; + } +} + + +/* Pipe has no concept of pools, but the psb driver passes a flag that + * can be mapped onto pools in the backend. + */ +static struct pipe_buffer * +timed_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size ) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + struct pipe_buffer *buf = backend->buffer_create( backend, alignment, usage, size ); + + time_finish(winsys, start, 0, __FUNCTION__); + + return buf; +} + + + + +static struct pipe_buffer * +timed_user_buffer_create(struct pipe_winsys *winsys, + void *data, + unsigned bytes) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + struct pipe_buffer *buf = backend->user_buffer_create( backend, data, bytes ); + + time_finish(winsys, start, 1, __FUNCTION__); + + return buf; +} + + +static void * +timed_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + void *map = backend->buffer_map( backend, buf, flags ); + + time_finish(winsys, start, 2, __FUNCTION__); + + return map; +} + + +static void +timed_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + backend->buffer_unmap( backend, buf ); + + time_finish(winsys, start, 3, __FUNCTION__); +} + + +static void +timed_buffer_destroy(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + backend->buffer_destroy( backend, buf ); + + time_finish(winsys, start, 4, __FUNCTION__); +} + + +static void +timed_flush_frontbuffer( struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + backend->flush_frontbuffer( backend, surf, context_private ); + + time_finish(winsys, start, 5, __FUNCTION__); +} + + + + +static struct pipe_surface * +timed_surface_alloc(struct pipe_winsys *winsys) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + struct pipe_surface *surf = backend->surface_alloc( backend ); + + time_finish(winsys, start, 6, __FUNCTION__); + + return surf; +} + + + +static int +timed_surface_alloc_storage(struct pipe_winsys *winsys, + struct pipe_surface *surf, + unsigned width, unsigned height, + enum pipe_format format, + unsigned flags, + unsigned tex_usage) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + int ret = backend->surface_alloc_storage( backend, surf, width, height, + format, flags, tex_usage ); + + time_finish(winsys, start, 7, __FUNCTION__); + + return ret; +} + + +static void +timed_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + backend->surface_release( backend, s ); + + time_finish(winsys, start, 8, __FUNCTION__); +} + + + +static const char * +timed_get_name( struct pipe_winsys *winsys ) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + const char *ret = backend->get_name( backend ); + + time_finish(winsys, start, 9, __FUNCTION__); + + return ret; +} + +static void +timed_fence_reference(struct pipe_winsys *winsys, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + backend->fence_reference( backend, ptr, fence ); + + time_finish(winsys, start, 10, __FUNCTION__); +} + + +static int +timed_fence_signalled( struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag ) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + int ret = backend->fence_signalled( backend, fence, flag ); + + time_finish(winsys, start, 11, __FUNCTION__); + + return ret; +} + +static int +timed_fence_finish( struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag ) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + uint64_t start = time_start(); + + int ret = backend->fence_finish( backend, fence, flag ); + + time_finish(winsys, start, 12, __FUNCTION__); + + return ret; +} + +static void +timed_winsys_destroy( struct pipe_winsys *winsys ) +{ + struct pipe_winsys *backend = timed_winsys(winsys)->backend; + backend->destroy( backend ); + FREE(winsys); +} + + + +struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend ) +{ + struct timed_winsys *ws = CALLOC_STRUCT(timed_winsys); + + ws->base.user_buffer_create = timed_user_buffer_create; + ws->base.buffer_map = timed_buffer_map; + ws->base.buffer_unmap = timed_buffer_unmap; + ws->base.buffer_destroy = timed_buffer_destroy; + ws->base.buffer_create = timed_buffer_create; + ws->base.flush_frontbuffer = timed_flush_frontbuffer; + ws->base.get_name = timed_get_name; + ws->base.surface_alloc = timed_surface_alloc; + ws->base.surface_alloc_storage = timed_surface_alloc_storage; + ws->base.surface_release = timed_surface_release; + ws->base.fence_reference = timed_fence_reference; + ws->base.fence_signalled = timed_fence_signalled; + ws->base.fence_finish = timed_fence_finish; + ws->base.destroy = timed_winsys_destroy; + + ws->backend = backend; + + return &ws->base; +} + diff --git a/src/gallium/auxiliary/util/u_timed_winsys.h b/src/gallium/auxiliary/util/u_timed_winsys.h new file mode 100644 index 0000000000..542365112d --- /dev/null +++ b/src/gallium/auxiliary/util/u_timed_winsys.h @@ -0,0 +1,41 @@ +/************************************************************************** + * + * 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. + * + * + **************************************************************************/ +/* + * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> + */ + + +#ifndef U_TIMED_WINSYS_H +#define U_TIMED_WINSYS_H + + +struct pipe_winsys; +struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend ); + + +#endif |