summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-09-11 18:32:05 +0100
committerKeith Whitwell <keith@tungstengraphics.com>2008-09-11 18:32:05 +0100
commitcc7dd4fc1b3c765ca1ecd943d189bb156dae529d (patch)
tree1a3560eb6df8a443c4f0e5af0a916f190b1542f6 /src/gallium/auxiliary
parent685248bea1fef5fd6335982570e34d0f6672030d (diff)
parentd50d68a1c940ed9c8d8c65e8e33667fa90d5baa1 (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')
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c149
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos.h10
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos_io.c4
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c24
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c38
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c77
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c20
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c24
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c124
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_execmem.c11
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c124
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h52
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c2
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.c160
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c2
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c87
-rw-r--r--src/gallium/auxiliary/translate/translate_generic.c6
-rw-r--r--src/gallium/auxiliary/util/Makefile5
-rw-r--r--src/gallium/auxiliary/util/SConscript2
-rw-r--r--src/gallium/auxiliary/util/p_debug.c111
-rw-r--r--src/gallium/auxiliary/util/u_blit.c22
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c12
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c42
-rw-r--r--src/gallium/auxiliary/util/u_memory.h13
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h155
-rw-r--r--src/gallium/auxiliary/util/u_rect.c178
-rw-r--r--src/gallium/auxiliary/util/u_rect.h18
-rw-r--r--src/gallium/auxiliary/util/u_stream.h61
-rw-r--r--src/gallium/auxiliary/util/u_stream_stdc.c106
-rw-r--r--src/gallium/auxiliary/util/u_stream_wd.c224
-rw-r--r--src/gallium/auxiliary/util/u_time.c20
-rw-r--r--src/gallium/auxiliary/util/u_time.h3
-rw-r--r--src/gallium/auxiliary/util/u_timed_winsys.c346
-rw-r--r--src/gallium/auxiliary/util/u_timed_winsys.h41
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