diff options
Diffstat (limited to 'src/gallium/auxiliary')
24 files changed, 1047 insertions, 255 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 7236bff592b..af4af8ac1d4 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -769,8 +769,7 @@ void cso_restore_vertex_shader(struct cso_context *ctx) enum pipe_error cso_set_framebuffer(struct cso_context *ctx, const struct pipe_framebuffer_state *fb) { - /* XXX this memcmp() fails to detect buffer size changes */ - if (1/*memcmp(&ctx->fb, fb, sizeof(*fb))*/) { + if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { ctx->fb = *fb; ctx->pipe->set_framebuffer_state(ctx->pipe, fb); } diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index d93708ad3cb..fd48b224b48 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -415,8 +415,11 @@ aaline_create_texture(struct aaline_stage *aaline) assert(aaline->texture->width[level] == aaline->texture->height[level]); - surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0); - data = pipe_surface_map(surface); + /* This texture is new, no need to flush. + */ + surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + data = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE); if (data == NULL) return FALSE; @@ -440,9 +443,8 @@ aaline_create_texture(struct aaline_stage *aaline) } /* unmap */ - pipe_surface_unmap(surface); - pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, aaline->texture, 0, (1 << level)); + screen->surface_unmap(screen, surface); + screen->tex_surface_release(screen, &surface); } return TRUE; } @@ -713,6 +715,11 @@ static void aaline_destroy(struct draw_stage *stage) { struct aaline_stage *aaline = aaline_stage(stage); + uint i; + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + pipe_texture_reference(&aaline->state.texture[i], NULL); + } if (aaline->sampler_cso) aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso); @@ -836,6 +843,9 @@ aaline_set_sampler_textures(struct pipe_context *pipe, for (i = 0; i < num; i++) { pipe_texture_reference(&aaline->state.texture[i], texture[i]); } + for ( ; i < PIPE_MAX_SAMPLERS; i++) { + pipe_texture_reference(&aaline->state.texture[i], NULL); + } aaline->num_textures = num; /* pass-through */ diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c index 73ee4198580..4c92416eb19 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c @@ -376,8 +376,14 @@ pstip_update_texture(struct pstip_stage *pstip) uint i, j; ubyte *data; - surface = screen->get_tex_surface(screen, pstip->texture, 0, 0, 0); - data = pipe_surface_map(surface); + /* XXX: want to avoid flushing just because we use stipple: + */ + pipe->flush( pipe, PIPE_FLUSH_TEXTURE_CACHE, NULL ); + + surface = screen->get_tex_surface(screen, pstip->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + data = screen->surface_map(screen, surface, + PIPE_BUFFER_USAGE_CPU_WRITE); /* * Load alpha texture. @@ -399,9 +405,8 @@ pstip_update_texture(struct pstip_stage *pstip) } /* unmap */ - pipe_surface_unmap(surface); - pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, pstip->texture, 0, 0x1); + screen->surface_unmap(screen, surface); + screen->tex_surface_release(screen, &surface); } @@ -559,6 +564,11 @@ static void pstip_destroy(struct draw_stage *stage) { struct pstip_stage *pstip = pstip_stage(stage); + uint i; + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + pipe_texture_reference(&pstip->state.textures[i], NULL); + } pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso); diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile index d654dbcc919..ff09011b660 100644 --- a/src/gallium/auxiliary/pipebuffer/Makefile +++ b/src/gallium/auxiliary/pipebuffer/Makefile @@ -11,6 +11,7 @@ C_SOURCES = \ pb_bufmgr_mm.c \ pb_bufmgr_pool.c \ pb_bufmgr_slab.c \ + pb_validate.c \ pb_winsys.c include ../../Makefile.template diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript index 604a217982e..9db0c0eae3b 100644 --- a/src/gallium/auxiliary/pipebuffer/SConscript +++ b/src/gallium/auxiliary/pipebuffer/SConscript @@ -10,6 +10,7 @@ pipebuffer = env.ConvenienceLibrary( 'pb_bufmgr_mm.c', 'pb_bufmgr_pool.c', 'pb_bufmgr_slab.c', + 'pb_validate.c', 'pb_winsys.c', ]) diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h index 49705cb8627..857ea53c786 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h @@ -146,6 +146,8 @@ pb_map(struct pb_buffer *buf, unsigned flags) { assert(buf); + if(!buf) + return NULL; return buf->vtbl->map(buf, flags); } @@ -154,6 +156,8 @@ static INLINE void pb_unmap(struct pb_buffer *buf) { assert(buf); + if(!buf) + return; buf->vtbl->unmap(buf); } @@ -163,6 +167,12 @@ pb_get_base_buffer( struct pb_buffer *buf, struct pb_buffer **base_buf, unsigned *offset ) { + assert(buf); + if(!buf) { + base_buf = NULL; + offset = 0; + return; + } buf->vtbl->get_base_buffer(buf, base_buf, offset); } @@ -171,7 +181,8 @@ static INLINE void pb_destroy(struct pb_buffer *buf) { assert(buf); - assert(buf->vtbl); + if(!buf) + return; buf->vtbl->destroy(buf); } diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 2fa08429715..7f236887a90 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -168,6 +168,28 @@ _fenced_buffer_remove(struct fenced_buffer *fenced_buf) } +static INLINE enum pipe_error +_fenced_buffer_finish(struct fenced_buffer *fenced_buf) +{ + struct fenced_buffer_list *fenced_list = fenced_buf->list; + struct pipe_winsys *winsys = fenced_list->winsys; + + debug_warning("waiting for GPU"); + + assert(fenced_buf->fence); + if(fenced_buf->fence) { + if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0) { + return PIPE_ERROR; + } + /* Remove from the fenced list */ + _fenced_buffer_remove(fenced_buf); /* TODO: remove consequents */ + } + + fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; + return PIPE_OK; +} + + /** * Free as many fenced buffers from the list head as possible. */ @@ -207,40 +229,6 @@ _fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, } -/** - * Serialize writes, but allow concurrent reads. - */ -static INLINE enum pipe_error -fenced_buffer_serialize(struct fenced_buffer *fenced_buf, unsigned flags) -{ - struct fenced_buffer_list *fenced_list = fenced_buf->list; - struct pipe_winsys *winsys = fenced_list->winsys; - - /* Allow concurrent reads */ - if(((fenced_buf->flags | flags) & PIPE_BUFFER_USAGE_WRITE) == 0) - return PIPE_OK; - - /* Wait for the CPU to finish */ - if(fenced_buf->mapcount) { - /* FIXME: Use thread conditions variables to signal when mapcount - * reaches zero */ - debug_warning("attemp to write concurrently to buffer"); - /* XXX: we must not fail here in order to support texture mipmap generation - return PIPE_ERROR_RETRY; - */ - } - - /* Wait for the GPU to finish */ - if(fenced_buf->fence) { - if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0) - return PIPE_ERROR_RETRY; - _fenced_buffer_remove(fenced_buf); - } - - return PIPE_OK; -} - - static void fenced_buffer_destroy(struct pb_buffer *buf) { @@ -280,15 +268,28 @@ fenced_buffer_map(struct pb_buffer *buf, { struct fenced_buffer *fenced_buf = fenced_buffer(buf); void *map; - assert((flags & ~PIPE_BUFFER_USAGE_CPU_READ_WRITE) == 0); + + assert(!(flags & ~PIPE_BUFFER_USAGE_CPU_READ_WRITE)); + flags &= PIPE_BUFFER_USAGE_CPU_READ_WRITE; - if(fenced_buffer_serialize(fenced_buf, flags) != PIPE_OK) - return NULL; + /* Check for GPU read/write access */ + if(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) { + /* Wait for the GPU to finish writing */ + _fenced_buffer_finish(fenced_buf); + } + + /* Check for CPU write access (read is OK) */ + if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { + /* this is legal -- just for debugging */ + debug_warning("concurrent CPU writes"); + } map = pb_map(fenced_buf->buffer, flags); - if(map) + if(map) { ++fenced_buf->mapcount; - fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE; + fenced_buf->flags |= flags; + } + return map; } @@ -298,10 +299,12 @@ fenced_buffer_unmap(struct pb_buffer *buf) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); assert(fenced_buf->mapcount); - pb_unmap(fenced_buf->buffer); - --fenced_buf->mapcount; - if(!fenced_buf->mapcount) - fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE; + if(fenced_buf->mapcount) { + pb_unmap(fenced_buf->buffer); + --fenced_buf->mapcount; + if(!fenced_buf->mapcount) + fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE; + } } @@ -334,8 +337,10 @@ fenced_buffer_create(struct fenced_buffer_list *fenced_list, return NULL; buf = CALLOC_STRUCT(fenced_buffer); - if(!buf) + if(!buf) { + pb_reference(&buffer, NULL); return NULL; + } buf->base.base.refcount = 1; buf->base.base.alignment = buffer->base.alignment; @@ -374,7 +379,7 @@ buffer_fence(struct pb_buffer *buf, fenced_list = fenced_buf->list; winsys = fenced_list->winsys; - if(fence == fenced_buf->fence) { + if(!fence || fence == fenced_buf->fence) { /* Handle the same fence case specially, not only because it is a fast * path, but mostly to avoid serializing two writes with the same fence, * as that would bring the hardware down to synchronous operation without @@ -384,11 +389,6 @@ buffer_fence(struct pb_buffer *buf, return; } - if(fenced_buffer_serialize(fenced_buf, flags) != PIPE_OK) { - /* FIXME: propagate error */ - (void)0; - } - _glthread_LOCK_MUTEX(fenced_list->mutex); if (fenced_buf->fence) _fenced_buffer_remove(fenced_buf); diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 9e8244f909b..6c3502eea7f 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -30,13 +30,14 @@ * Implementation of malloc-based buffers to store data that can't be processed * by the hardware. * - * \author Jos� Fonseca <[email protected]> + * \author Jose Fonseca <[email protected]> */ #include "pipe/p_debug.h" #include "pipe/p_util.h" #include "pb_buffer.h" +#include "pb_bufmgr.h" struct malloc_buffer @@ -125,3 +126,33 @@ pb_malloc_buffer_create(size_t size, return &buf->base; } + + +static struct pb_buffer * +pb_malloc_buffer_create_buffer(struct pb_manager *mgr, + size_t size, + const struct pb_desc *desc) +{ + return pb_malloc_buffer_create(size, desc); +} + + +static void +pb_malloc_bufmgr_destroy(struct pb_manager *mgr) +{ + /* No-op */ +} + + +static struct pb_manager +pb_malloc_bufmgr = { + pb_malloc_buffer_create_buffer, + pb_malloc_bufmgr_destroy +}; + + +struct pb_manager * +pb_malloc_bufmgr_create(void) +{ + return &pb_malloc_bufmgr; +} diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index 8de286e3f94..4a922d16c18 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -50,7 +50,8 @@ #define PB_BUFMGR_H_ -#include <stddef.h> +#include "pipe/p_compiler.h" +#include "pipe/p_error.h" #ifdef __cplusplus @@ -68,7 +69,6 @@ struct pipe_winsys; */ struct pb_manager { - /* XXX: we will likely need more allocation flags */ struct pb_buffer * (*create_buffer)( struct pb_manager *mgr, size_t size, @@ -79,6 +79,15 @@ struct pb_manager }; +/** + * Malloc buffer provider. + * + * Simple wrapper around pb_malloc_buffer_create for convenience. + */ +struct pb_manager * +pb_malloc_bufmgr_create(void); + + /** * Static buffer pool sub-allocator. * diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index b931455056e..b9dff09804c 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -47,9 +47,6 @@ #include "pb_bufmgr.h" -#define DRI_SLABPOOL_ALLOC_RETRIES 100 - - struct pb_slab; struct pb_slab_buffer @@ -313,11 +310,10 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, static struct pb_slab_buffer *buf; struct pb_slab *slab; struct list_head *list; - int count = DRI_SLABPOOL_ALLOC_RETRIES; /* check size */ - assert(size == mgr->bufSize); - if(size != mgr->bufSize) + assert(size <= mgr->bufSize); + if(size > mgr->bufSize) return NULL; /* check if we can provide the requested alignment */ @@ -331,23 +327,14 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, /* XXX: check for compatible buffer usage too? */ _glthread_LOCK_MUTEX(mgr->mutex); - while (mgr->slabs.next == &mgr->slabs && count > 0) { - if (mgr->slabs.next != &mgr->slabs) - break; - - _glthread_UNLOCK_MUTEX(mgr->mutex); - if (count != DRI_SLABPOOL_ALLOC_RETRIES) - util_time_sleep(1); - _glthread_LOCK_MUTEX(mgr->mutex); + if (mgr->slabs.next == &mgr->slabs) { (void) pb_slab_create(mgr); - count--; + if (mgr->slabs.next == &mgr->slabs) { + _glthread_UNLOCK_MUTEX(mgr->mutex); + return NULL; + } } - list = mgr->slabs.next; - if (list == &mgr->slabs) { - _glthread_UNLOCK_MUTEX(mgr->mutex); - return NULL; - } slab = LIST_ENTRY(struct pb_slab, list, head); if (--slab->numFree == 0) LIST_DELINIT(list); diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c new file mode 100644 index 00000000000..362fd896f31 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -0,0 +1,153 @@ +/************************************************************************** + * + * 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 + * Buffer validation. + * + * @author Jose Fonseca <[email protected]> + */ + + +#include "pipe/p_compiler.h" +#include "pipe/p_error.h" +#include "pipe/p_util.h" +#include "pipe/p_debug.h" + +#include "pb_buffer.h" +#include "pb_buffer_fenced.h" +#include "pb_validate.h" + + +#define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ + + +struct pb_validate +{ + struct pb_buffer **buffers; + unsigned used; + unsigned size; +}; + + +enum pipe_error +pb_validate_add_buffer(struct pb_validate *vl, + struct pb_buffer *buf) +{ + assert(buf); + if(!buf) + return PIPE_ERROR; + + /* We only need to store one reference for each buffer, so avoid storing + * consecutive references for the same buffer. It might not be the more + * common pasttern, but it is easy to implement. + */ + if(vl->used && vl->buffers[vl->used - 1] == buf) { + return PIPE_OK; + } + + /* Grow the table */ + if(vl->used == vl->size) { + unsigned new_size; + struct pb_buffer **new_buffers; + + new_size = vl->size * 2; + if(!new_size) + return PIPE_ERROR_OUT_OF_MEMORY; + + new_buffers = (struct pb_buffer **)REALLOC(vl->buffers, + vl->size*sizeof(struct pb_buffer *), + new_size*sizeof(struct pb_buffer *)); + if(!new_buffers) + return PIPE_ERROR_OUT_OF_MEMORY; + + memset(new_buffers + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_buffer *)); + + vl->size = new_size; + vl->buffers = new_buffers; + } + + assert(!vl->buffers[vl->used]); + pb_reference(&vl->buffers[vl->used], buf); + ++vl->used; + + return PIPE_OK; +} + + +enum pipe_error +pb_validate_validate(struct pb_validate *vl) +{ + /* FIXME: go through each buffer, ensure its not mapped, its address is + * available -- requires a new pb_buffer interface */ + return PIPE_OK; +} + + +void +pb_validate_fence(struct pb_validate *vl, + struct pipe_fence_handle *fence) +{ + unsigned i; + for(i = 0; i < vl->used; ++i) { + buffer_fence(vl->buffers[i], fence); + pb_reference(&vl->buffers[i], NULL); + } + vl->used = 0; +} + + +void +pb_validate_destroy(struct pb_validate *vl) +{ + unsigned i; + for(i = 0; i < vl->used; ++i) + pb_reference(&vl->buffers[i], NULL); + FREE(vl->buffers); + FREE(vl); +} + + +struct pb_validate * +pb_validate_create() +{ + struct pb_validate *vl; + + vl = CALLOC_STRUCT(pb_validate); + if(!vl) + return NULL; + + vl->size = PB_VALIDATE_INITIAL_SIZE; + vl->buffers = (struct pb_buffer **)CALLOC(vl->size, sizeof(struct pb_buffer *)); + if(!vl->buffers) { + FREE(vl); + return NULL; + } + + return vl; +} + diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h new file mode 100644 index 00000000000..3db1d5330b9 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * 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 + * Buffer validation. + * + * @author Jose Fonseca <[email protected]> + */ + +#ifndef PB_VALIDATE_H_ +#define PB_VALIDATE_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct pb_buffer; +struct pipe_fence_handle; + + +/** + * Buffer validation list. + * + * It holds a list of buffers to be validated and fenced when flushing. + */ +struct pb_validate; + + +enum pipe_error +pb_validate_add_buffer(struct pb_validate *vl, + struct pb_buffer *buf); + +/** + * Validate all buffers for hardware access. + * + * Should be called right before issuing commands to the hardware. + */ +enum pipe_error +pb_validate_validate(struct pb_validate *vl); + +/** + * Fence all buffers and clear the list. + * + * Should be called right before issuing commands to the hardware. + */ +void +pb_validate_fence(struct pb_validate *vl, + struct pipe_fence_handle *fence); + +struct pb_validate * +pb_validate_create(void); + +void +pb_validate_destroy(struct pb_validate *vl); + + +#ifdef __cplusplus +} +#endif + +#endif /*PB_VALIDATE_H_*/ diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index d55d2c70818..0309de1ac22 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -5,6 +5,7 @@ util = env.ConvenienceLibrary( source = [ 'p_debug.c', 'p_debug_mem.c', + 'p_debug_prof.c', 'p_tile.c', 'p_util.c', 'u_blit.c', diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index 4ec17466624..ce7fb589562 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -67,7 +67,7 @@ void _debug_vprintf(const char *format, va_list ap) static char buf[512 + 1] = {'\0'}; size_t len = strlen(buf); int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap); - if(ret > (int)(sizeof(buf) - len - 1) || strchr(buf + len, '\n')) { + if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) { _EngDebugPrint("%s", buf); buf[0] = '\0'; } @@ -154,6 +154,7 @@ debug_get_option(const char *name, const char *dfault) { const char *result; #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY +#ifdef DEBUG ULONG_PTR iFile = 0; const void *pMap = NULL; const char *sol, *eol, *sep; @@ -184,6 +185,9 @@ debug_get_option(const char *name, const char *dfault) EngUnmapFile(iFile); } #else + result = dfault; +#endif +#else result = getenv(name); if(!result) @@ -203,15 +207,15 @@ debug_get_bool_option(const char *name, boolean dfault) if(str == NULL) result = dfault; - else if(!strcmp(str, "n")) + else if(!util_strcmp(str, "n")) result = FALSE; - else if(!strcmp(str, "no")) + else if(!util_strcmp(str, "no")) result = FALSE; - else if(!strcmp(str, "0")) + else if(!util_strcmp(str, "0")) result = FALSE; - else if(!strcmp(str, "f")) + else if(!util_strcmp(str, "f")) result = FALSE; - else if(!strcmp(str, "false")) + else if(!util_strcmp(str, "false")) result = FALSE; else result = TRUE; @@ -244,7 +248,7 @@ debug_get_flags_option(const char *name, else { result = 0; while( flags->name ) { - if (!strcmp(str, "all") || strstr(str, flags->name )) + if (!util_strcmp(str, "all") || util_strstr(str, flags->name )) result |= flags->value; ++flags; } @@ -299,10 +303,10 @@ debug_dump_flags(const struct debug_named_value *names, while(names->name) { if((names->value & value) == names->value) { if (!first) - strncat(output, "|", sizeof(output)); + util_strncat(output, "|", sizeof(output)); else first = 0; - strncat(output, names->name, sizeof(output)); + util_strncat(output, names->name, sizeof(output)); value &= ~names->value; } ++names; @@ -310,12 +314,12 @@ debug_dump_flags(const struct debug_named_value *names, if (value) { if (!first) - strncat(output, "|", sizeof(output)); + util_strncat(output, "|", sizeof(output)); else first = 0; util_snprintf(rest, sizeof(rest), "0x%08lx", value); - strncat(output, rest, sizeof(output)); + util_strncat(output, rest, sizeof(output)); } if(first) @@ -325,101 +329,159 @@ debug_dump_flags(const struct debug_named_value *names, } +static const struct debug_named_value pipe_format_names[] = { +#ifdef DEBUG + DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR), + DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV), + DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED), + DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA), + DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA), + DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA), +#endif + DEBUG_NAMED_VALUE_END +}; - - +#ifdef DEBUG +void debug_print_format(const char *msg, unsigned fmt ) +{ + debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt)); +} +#endif char *pf_sprint_name( char *str, enum pipe_format format ) { - strcpy( str, "PIPE_FORMAT_" ); - switch (pf_layout( format )) { - case PIPE_FORMAT_LAYOUT_RGBAZS: - { - pipe_format_rgbazs_t rgbazs = (pipe_format_rgbazs_t) format; - uint i; - uint scale = 1 << (pf_exp8( rgbazs ) * 3); - - for (i = 0; i < 4; i++) { - uint size = pf_size_xyzw( rgbazs, i ); - - if (size == 0) { - break; - } - switch (pf_swizzle_xyzw( rgbazs, i )) { - case PIPE_FORMAT_COMP_R: - strcat( str, "R" ); - break; - case PIPE_FORMAT_COMP_G: - strcat( str, "G" ); - break; - case PIPE_FORMAT_COMP_B: - strcat( str, "B" ); - break; - case PIPE_FORMAT_COMP_A: - strcat( str, "A" ); - break; - case PIPE_FORMAT_COMP_0: - strcat( str, "0" ); - break; - case PIPE_FORMAT_COMP_1: - strcat( str, "1" ); - break; - case PIPE_FORMAT_COMP_Z: - strcat( str, "Z" ); - break; - case PIPE_FORMAT_COMP_S: - strcat( str, "S" ); - break; - } - util_snprintf( &str[strlen( str )], 32, "%u", size * scale ); - } - if (i != 0) { - strcat( str, "_" ); - } - switch (pf_type( rgbazs )) { - case PIPE_FORMAT_TYPE_UNKNOWN: - strcat( str, "NONE" ); - break; - case PIPE_FORMAT_TYPE_FLOAT: - strcat( str, "FLOAT" ); - break; - case PIPE_FORMAT_TYPE_UNORM: - strcat( str, "UNORM" ); - break; - case PIPE_FORMAT_TYPE_SNORM: - strcat( str, "SNORM" ); - break; - case PIPE_FORMAT_TYPE_USCALED: - strcat( str, "USCALED" ); - break; - case PIPE_FORMAT_TYPE_SSCALED: - strcat( str, "SSCALED" ); - break; - } - } - break; - case PIPE_FORMAT_LAYOUT_YCBCR: - { - pipe_format_ycbcr_t ycbcr = (pipe_format_ycbcr_t) format; - - strcat( str, "YCBCR" ); - if (pf_rev( ycbcr )) { - strcat( str, "_REV" ); - } - } - break; - } + strcpy( str, debug_dump_enum(pipe_format_names, format) ); return str; } #ifdef DEBUG -void debug_print_format(const char *msg, unsigned fmt ) +void debug_dump_image(const char *prefix, + unsigned format, unsigned cpp, + unsigned width, unsigned height, + unsigned pitch, + const void *data) { - char fmtstr[80]; - - pf_sprint_name(fmtstr, (enum pipe_format)fmt); +#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY + static unsigned no = 0; + char filename[256]; + WCHAR wfilename[sizeof(filename)]; + ULONG_PTR iFile = 0; + struct { + unsigned format; + unsigned cpp; + unsigned width; + unsigned height; + } header; + unsigned char *pMap = NULL; + unsigned i; - debug_printf("%s: %s\n", msg, fmtstr); + util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix); + for(i = 0; i < sizeof(filename); ++i) + wfilename[i] = (WCHAR)filename[i]; + + pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + cpp*width*height, &iFile); + if(!pMap) + return; + + header.format = format; + header.cpp = cpp; + header.width = width; + header.height = height; + memcpy(pMap, &header, sizeof(header)); + pMap += sizeof(header); + + for(i = 0; i < height; ++i) { + memcpy(pMap, (unsigned char *)data + cpp*pitch*i, cpp*width); + pMap += cpp*width; + } + + EngUnmapFile(iFile); +#endif } #endif diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c index 3b5e4fbaeea..78497c5f6af 100644 --- a/src/gallium/auxiliary/util/p_debug_mem.c +++ b/src/gallium/auxiliary/util/p_debug_mem.c @@ -211,6 +211,7 @@ debug_memory_begin(void) void debug_memory_end(unsigned long start_no) { + size_t total_size = 0; struct list_head *entry; entry = list.prev; @@ -220,9 +221,15 @@ debug_memory_end(unsigned long start_no) hdr = LIST_ENTRY(struct debug_memory_header, entry, head); ptr = data_from_header(hdr); if(start_no <= hdr->no && hdr->no < last_no || - last_no < start_no && (hdr->no < last_no || start_no <= hdr->no)) + last_no < start_no && (hdr->no < last_no || start_no <= hdr->no)) { debug_printf("%s:%u:%s: %u bytes at %p not freed\n", hdr->file, hdr->line, hdr->function, hdr->size, ptr); + total_size += hdr->size; + } + } + if(total_size) { + debug_printf("Total of %u KB of system memory apparently leaked\n", + (total_size + 1023)/1024); } } diff --git a/src/gallium/auxiliary/util/p_debug_prof.c b/src/gallium/auxiliary/util/p_debug_prof.c new file mode 100644 index 00000000000..958f99c327c --- /dev/null +++ b/src/gallium/auxiliary/util/p_debug_prof.c @@ -0,0 +1,175 @@ +/************************************************************************** + * + * 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 + * Poor-man profiling. + * + * @author José Fonseca <[email protected]> + * + * @sa http://blogs.msdn.com/joshpoley/archive/2008/03/12/poor-man-s-profiler.aspx + * @sa http://www.johnpanzer.com/aci_cuj/index.html + */ + +#include "pipe/p_config.h" + +#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) + +#include <windows.h> +#include <winddi.h> + +#include "pipe/p_debug.h" +#include "util/u_string.h" + + +#define PROFILE_FILE_SIZE 4*1024*1024 +#define FILE_NAME_SIZE 256 + +static WCHAR wFileName[FILE_NAME_SIZE]; +static ULONG_PTR iFile = 0; +static void *pMap = NULL; +static void *pMapEnd = NULL; + + +/** + * Called at the start of every method or function. + * + * @sa http://msdn.microsoft.com/en-us/library/c63a9b7h.aspx + */ +void __declspec(naked) __cdecl +_penter(void) { + _asm { + push ebx + mov ebx, [pMap] + test ebx, ebx + jz done + cmp ebx, [pMapEnd] + je done + push eax + push edx + mov eax, [esp+12] + and eax, 0xfffffffe + mov [ebx], eax + add ebx, 4 + rdtsc + mov [ebx], eax + add ebx, 4 + mov [pMap], ebx + pop edx + pop eax +done: + pop ebx + ret + } +} + + +/** + * Called at the end of Calls the end of every method or function. + * + * @sa http://msdn.microsoft.com/en-us/library/xc11y76y.aspx + */ +void __declspec(naked) __cdecl +_pexit(void) { + _asm { + push ebx + mov ebx, [pMap] + test ebx, ebx + jz done + cmp ebx, [pMapEnd] + je done + push eax + push edx + mov eax, [esp+12] + or eax, 0x00000001 + mov [ebx], eax + add ebx, 4 + rdtsc + mov [ebx], eax + add ebx, 4 + mov [pMap], ebx + pop edx + pop eax +done: + pop ebx + ret + } +} + + +void __declspec(naked) +__debug_profile_reference1(void) { + _asm { + call _penter + call _pexit + ret + } +} + + +void __declspec(naked) +__debug_profile_reference2(void) { + _asm { + call _penter + call __debug_profile_reference1 + call _pexit + ret + } +} + + +void +debug_profile_start(void) +{ + static unsigned no = 0; + char filename[FILE_NAME_SIZE]; + unsigned i; + + util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u.prof", ++no); + for(i = 0; i < FILE_NAME_SIZE; ++i) + wFileName[i] = (WCHAR)filename[i]; + + pMap = EngMapFile(wFileName, PROFILE_FILE_SIZE, &iFile); + if(pMap) { + pMapEnd = (unsigned char*)pMap + PROFILE_FILE_SIZE; + /* reference functions for calibration purposes */ + __debug_profile_reference2(); + } +} + +void +debug_profile_stop(void) +{ + if(iFile) { + EngUnmapFile(iFile); + /* TODO: truncate file */ + } + iFile = 0; + pMapEnd = pMap = NULL; +} + +#endif /* PROFILE */ diff --git a/src/gallium/auxiliary/util/p_tile.c b/src/gallium/auxiliary/util/p_tile.c index 63e1cc6013a..5728757d2fb 100644 --- a/src/gallium/auxiliary/util/p_tile.c +++ b/src/gallium/auxiliary/util/p_tile.c @@ -50,6 +50,7 @@ pipe_get_tile_raw(struct pipe_context *pipe, uint x, uint y, uint w, uint h, void *p, int dst_stride) { + struct pipe_screen *screen = pipe->screen; const uint cpp = ps->cpp; const ubyte *pSrc; const uint src_stride = ps->pitch * cpp; @@ -63,7 +64,11 @@ pipe_get_tile_raw(struct pipe_context *pipe, if (pipe_clip_tile(x, y, &w, &h, ps)) return; - pSrc = (const ubyte *) pipe_surface_map(ps) + (y * ps->pitch + x) * cpp; + pSrc = (const ubyte *) screen->surface_map(screen, ps, + PIPE_BUFFER_USAGE_CPU_READ); + assert(pSrc); /* XXX: proper error handling! */ + + pSrc += (y * ps->pitch + x) * cpp; pDest = (ubyte *) p; for (i = 0; i < h; i++) { @@ -72,7 +77,7 @@ pipe_get_tile_raw(struct pipe_context *pipe, pSrc += src_stride; } - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); } @@ -86,6 +91,7 @@ pipe_put_tile_raw(struct pipe_context *pipe, uint x, uint y, uint w, uint h, const void *p, int src_stride) { + struct pipe_screen *screen = pipe->screen; const uint cpp = ps->cpp; const ubyte *pSrc; const uint dst_stride = ps->pitch * cpp; @@ -100,7 +106,11 @@ pipe_put_tile_raw(struct pipe_context *pipe, return; pSrc = (const ubyte *) p; - pDest = (ubyte *) pipe_surface_map(ps) + (y * ps->pitch + x) * cpp; + + pDest = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_WRITE); + assert(pDest); /* XXX: proper error handling */ + + pDest += (y * ps->pitch + x) * cpp; for (i = 0; i < h; i++) { memcpy(pDest, pSrc, w * cpp); @@ -108,7 +118,7 @@ pipe_put_tile_raw(struct pipe_context *pipe, pSrc += src_stride; } - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); } @@ -834,18 +844,26 @@ pipe_get_tile_z(struct pipe_context *pipe, uint x, uint y, uint w, uint h, uint *z) { + struct pipe_screen *screen = pipe->screen; const uint dstStride = w; + void *map; uint *pDest = z; uint i, j; if (pipe_clip_tile(x, y, &w, &h, ps)) return; + map = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ); + if (!map) { + assert(0); + return; + } + switch (ps->format) { case PIPE_FORMAT_Z32_UNORM: { const uint *pSrc - = (const uint *) pipe_surface_map(ps) + (y * ps->pitch + x); + = (const uint *)map + (y * ps->pitch + x); for (i = 0; i < h; i++) { memcpy(pDest, pSrc, 4 * w); pDest += dstStride; @@ -857,7 +875,7 @@ pipe_get_tile_z(struct pipe_context *pipe, case PIPE_FORMAT_X8Z24_UNORM: { const uint *pSrc - = (const uint *) pipe_surface_map(ps) + (y * ps->pitch + x); + = (const uint *)map + (y * ps->pitch + x); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 24-bit Z to 32-bit Z */ @@ -871,7 +889,7 @@ pipe_get_tile_z(struct pipe_context *pipe, case PIPE_FORMAT_Z16_UNORM: { const ushort *pSrc - = (const ushort *) pipe_surface_map(ps) + (y * ps->pitch + x); + = (const ushort *)map + (y * ps->pitch + x); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 16-bit Z to 32-bit Z */ @@ -886,7 +904,7 @@ pipe_get_tile_z(struct pipe_context *pipe, assert(0); } - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); } @@ -896,17 +914,25 @@ pipe_put_tile_z(struct pipe_context *pipe, uint x, uint y, uint w, uint h, const uint *zSrc) { + struct pipe_screen *screen = pipe->screen; const uint srcStride = w; const uint *pSrc = zSrc; + void *map; uint i, j; if (pipe_clip_tile(x, y, &w, &h, ps)) return; + map = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_WRITE); + if (!map) { + assert(0); + return; + } + switch (ps->format) { case PIPE_FORMAT_Z32_UNORM: { - uint *pDest = (uint *) pipe_surface_map(ps) + (y * ps->pitch + x); + uint *pDest = (uint *) map + (y * ps->pitch + x); for (i = 0; i < h; i++) { memcpy(pDest, pSrc, 4 * w); pDest += ps->pitch; @@ -917,7 +943,7 @@ pipe_put_tile_z(struct pipe_context *pipe, case PIPE_FORMAT_S8Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: { - uint *pDest = (uint *) pipe_surface_map(ps) + (y * ps->pitch + x); + uint *pDest = (uint *) map + (y * ps->pitch + x); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 32-bit Z to 24-bit Z (0 stencil) */ @@ -930,7 +956,7 @@ pipe_put_tile_z(struct pipe_context *pipe, break; case PIPE_FORMAT_Z16_UNORM: { - ushort *pDest = (ushort *) pipe_surface_map(ps) + (y * ps->pitch + x); + ushort *pDest = (ushort *) map + (y * ps->pitch + x); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 32-bit Z to 16-bit Z */ @@ -945,7 +971,7 @@ pipe_put_tile_z(struct pipe_context *pipe, assert(0); } - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); } diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 568d62ced19..999a3e50995 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -287,7 +287,8 @@ util_blit_pixels(struct blit_state *ctx, if (!tex) return; - texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0); + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); /* load temp texture */ pipe->surface_copy(pipe, FALSE, @@ -295,7 +296,9 @@ util_blit_pixels(struct blit_state *ctx, src, srcLeft, srcTop, /* src */ srcW, srcH); /* size */ - pipe->texture_update(pipe, tex, 0, 1 << 0); + /* free the surface, update the texture if necessary. + */ + screen->tex_surface_release(screen, &texSurf); /* save state (restored below) */ cso_save_blend(ctx->cso); @@ -356,8 +359,6 @@ util_blit_pixels(struct blit_state *ctx, cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); - /* free the texture */ - pipe_surface_reference(&texSurf, NULL); screen->texture_release(screen, &tex); } diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index e659edb0881..bf143815d8b 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -82,52 +82,51 @@ util_draw_texquad(struct pipe_context *pipe, { struct pipe_buffer *vbuf; uint numAttribs = 2, vertexBytes, i, j; - float *v; vertexBytes = 4 * (4 * numAttribs * sizeof(float)); /* XXX create one-time */ vbuf = pipe->winsys->buffer_create(pipe->winsys, 32, PIPE_BUFFER_USAGE_VERTEX, vertexBytes); - assert(vbuf); - - v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); - - /* - * Load vertex buffer - */ - for (i = j = 0; i < 4; i++) { - v[j + 2] = z; /* z */ - v[j + 3] = 1.0; /* w */ - v[j + 6] = 0.0; /* r */ - v[j + 7] = 1.0; /* q */ - j += 8; + if (vbuf) { + float *v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + if (v) { + /* + * Load vertex buffer + */ + for (i = j = 0; i < 4; i++) { + v[j + 2] = z; /* z */ + v[j + 3] = 1.0; /* w */ + v[j + 6] = 0.0; /* r */ + v[j + 7] = 1.0; /* q */ + j += 8; + } + + v[0] = x0; + v[1] = y0; + v[4] = 0.0; /*s*/ + v[5] = 0.0; /*t*/ + + v[8] = x1; + v[9] = y0; + v[12] = 1.0; + v[13] = 0.0; + + v[16] = x1; + v[17] = y1; + v[20] = 1.0; + v[21] = 1.0; + + v[24] = x0; + v[25] = y1; + v[28] = 0.0; + v[29] = 1.0; + + pipe->winsys->buffer_unmap(pipe->winsys, vbuf); + util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2); + } + + pipe_buffer_reference(pipe->winsys, &vbuf, NULL); } - - v[0] = x0; - v[1] = y0; - v[4] = 0.0; /*s*/ - v[5] = 0.0; /*t*/ - - v[8] = x1; - v[9] = y0; - v[12] = 1.0; - v[13] = 0.0; - - v[16] = x1; - v[17] = y1; - v[20] = 1.0; - v[21] = 1.0; - - v[24] = x0; - v[25] = y1; - v[28] = 0.0; - v[29] = 1.0; - - pipe->winsys->buffer_unmap(pipe->winsys, vbuf); - - util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2); - - pipe_buffer_reference(pipe->winsys, &vbuf, NULL); } diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index c53c5122681..7d71aefda9d 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -589,8 +589,11 @@ make_1d_mipmap(struct gen_mipmap_state *ctx, struct pipe_surface *srcSurf, *dstSurf; void *srcMap, *dstMap; - srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice); - dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice); + srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice, + PIPE_BUFFER_USAGE_CPU_READ); + + 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) @@ -629,8 +632,10 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, struct pipe_surface *srcSurf, *dstSurf; ubyte *srcMap, *dstMap; - srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice); - dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice); + srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice, + PIPE_BUFFER_USAGE_CPU_READ); + 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) @@ -891,10 +896,14 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; + struct pipe_surface *surf = + screen->get_tex_surface(screen, pt, face, dstLevel, zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + /* * Setup framebuffer / dest surface */ - fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice); + fb.cbufs[0] = surf; fb.width = pt->width[dstLevel]; fb.height = pt->height[dstLevel]; cso_set_framebuffer(ctx->cso, &fb); @@ -925,7 +934,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); /* need to signal that the texture has changed _after_ rendering to it */ - pipe->texture_update(pipe, pt, face, (1 << dstLevel)); + pipe_surface_reference( &surf, NULL ); } /* restore state we changed */ diff --git a/src/gallium/auxiliary/util/u_hash_table.c b/src/gallium/auxiliary/util/u_hash_table.c index f3f16a8d94f..dd5eca7fca3 100644 --- a/src/gallium/auxiliary/util/u_hash_table.c +++ b/src/gallium/auxiliary/util/u_hash_table.c @@ -67,6 +67,13 @@ struct hash_table_item }; +static INLINE struct hash_table_item * +hash_table_item(struct cso_hash_iter iter) +{ + return (struct hash_table_item *)cso_hash_iter_data(iter); +} + + struct hash_table * hash_table_create(unsigned (*hash)(void *key), int (*compare)(void *key1, void *key2)) @@ -90,7 +97,27 @@ hash_table_create(unsigned (*hash)(void *key), } -static struct hash_table_item * +static INLINE struct cso_hash_iter +hash_table_find_iter(struct hash_table *ht, + void *key, + unsigned key_hash) +{ + struct cso_hash_iter iter; + struct hash_table_item *item; + + iter = cso_hash_find(ht->cso, key_hash); + while (!cso_hash_iter_is_null(iter)) { + item = (struct hash_table_item *)cso_hash_iter_data(iter); + if (!ht->compare(item->key, key)) + break; + iter = cso_hash_iter_next(iter); + } + + return iter; +} + + +static INLINE struct hash_table_item * hash_table_find_item(struct hash_table *ht, void *key, unsigned key_hash) @@ -117,6 +144,7 @@ hash_table_set(struct hash_table *ht, { unsigned key_hash; struct hash_table_item *item; + struct cso_hash_iter iter; assert(ht); @@ -136,9 +164,8 @@ hash_table_set(struct hash_table *ht, item->key = key; item->value = value; - cso_hash_insert(ht->cso, key_hash, item); - /* FIXME: there is no OOM propagation in cso_hash */ - if(0) { + iter = cso_hash_insert(ht->cso, key_hash, item); + if(cso_hash_iter_is_null(iter)) { FREE(item); return PIPE_ERROR_OUT_OF_MEMORY; } @@ -171,19 +198,39 @@ hash_table_remove(struct hash_table *ht, void *key) { unsigned key_hash; + struct cso_hash_iter iter; struct hash_table_item *item; assert(ht); key_hash = ht->hash(key); - item = hash_table_find_item(ht, key, key_hash); - if(!item) + iter = hash_table_find_iter(ht, key, key_hash); + if(cso_hash_iter_is_null(iter)) return; - /* FIXME: cso_hash_take takes the first element of the collision list - * indiscriminately, so we can not take the item down. */ - item->value = NULL; + item = hash_table_item(iter); + assert(item); + FREE(item); + + cso_hash_erase(ht->cso, iter); +} + + +void +hash_table_clear(struct hash_table *ht) +{ + struct cso_hash_iter iter; + struct hash_table_item *item; + + assert(ht); + + iter = cso_hash_first_node(ht->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter)); + FREE(item); + iter = cso_hash_first_node(ht->cso); + } } @@ -196,6 +243,8 @@ hash_table_foreach(struct hash_table *ht, struct hash_table_item *item; enum pipe_error result; + assert(ht); + iter = cso_hash_first_node(ht->cso); while (!cso_hash_iter_is_null(iter)) { item = (struct hash_table_item *)cso_hash_iter_data(iter); @@ -212,7 +261,17 @@ hash_table_foreach(struct hash_table *ht, void hash_table_destroy(struct hash_table *ht) { + struct cso_hash_iter iter; + struct hash_table_item *item; + assert(ht); + + iter = cso_hash_first_node(ht->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct hash_table_item *)cso_hash_iter_data(iter); + FREE(item); + iter = cso_hash_iter_next(iter); + } cso_hash_delete(ht->cso); diff --git a/src/gallium/auxiliary/util/u_hash_table.h b/src/gallium/auxiliary/util/u_hash_table.h index 1583bd7548c..feee881582e 100644 --- a/src/gallium/auxiliary/util/u_hash_table.h +++ b/src/gallium/auxiliary/util/u_hash_table.h @@ -75,6 +75,10 @@ hash_table_remove(struct hash_table *ht, void *key); +void +hash_table_clear(struct hash_table *ht); + + enum pipe_error hash_table_foreach(struct hash_table *ht, enum pipe_error (*callback)(void *key, void *value, void *data), diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 0b917c005f1..655e2c82592 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -101,6 +101,19 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, *d = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); } return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte *d = (ubyte *) dest; + *d = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + ubyte *d = (ubyte *) dest; + *d = r; + } + return; case PIPE_FORMAT_R32G32B32A32_FLOAT: { float *d = (float *) dest; @@ -198,6 +211,19 @@ util_pack_color(const float rgba[4], enum pipe_format format, void *dest) *d = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); } return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte *d = (ubyte *) dest; + *d = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + ubyte *d = (ubyte *) dest; + *d = r; + } + return; case PIPE_FORMAT_R32G32B32A32_FLOAT: { float *d = (float *) dest; diff --git a/src/gallium/auxiliary/util/u_string.h b/src/gallium/auxiliary/util/u_string.h index b99d4e8021c..73c88d87b4c 100644 --- a/src/gallium/auxiliary/util/u_string.h +++ b/src/gallium/auxiliary/util/u_string.h @@ -41,6 +41,8 @@ #include <stddef.h> #include <stdarg.h> +#include "pipe/p_compiler.h" + #ifdef __cplusplus extern "C" { @@ -48,11 +50,129 @@ extern "C" { #ifdef WIN32 + int util_vsnprintf(char *, size_t, const char *, va_list); int util_snprintf(char *str, size_t size, const char *format, ...); + +static INLINE void +util_vsprintf(char *str, const char *format, va_list ap) +{ + util_vsnprintf(str, (size_t)-1, format, ap); +} + +static INLINE void +util_sprintf(char *str, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + util_vsnprintf(str, (size_t)-1, format, ap); + va_end(ap); +} + +static INLINE char * +util_strchr(const char *s, char c) +{ + while(*s) { + if(*s == c) + return (char *)s; + ++s; + } + return NULL; +} + +static INLINE char* +util_strncat(char *dst, const char *src, size_t n) +{ + char *p = dst + strlen(dst); + const char *q = src; + size_t i; + + for (i = 0; i < n && *q != '\0'; ++i) + *p++ = *q++; + *p = '\0'; + + return dst; +} + +static INLINE int +util_strcmp(const char *s1, const char *s2) +{ + unsigned char u1, u2; + + while (1) { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + +static INLINE int +util_strncmp(const char *s1, const char *s2, size_t n) +{ + unsigned char u1, u2; + + while (n-- > 0) { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + +static INLINE char * +util_strstr(const char *haystack, const char *needle) +{ + const char *p = haystack; + int len = strlen(needle); + + for (; (p = util_strchr(p, *needle)) != 0; p++) { + if (util_strncmp(p, needle, len) == 0) { + return (char *)p; + } + } + return NULL; +} + +static INLINE void * +util_memmove(void *dest, const void *src, size_t n) +{ + char *p = (char *)dest; + const char *q = (const char *)src; + if (dest < src) { + while (n--) + *p++ = *q++; + } + else + { + p += n; + q += n; + while (n--) + *--p = *--q; + } + return dest; +} + + #else + #define util_vsnprintf vsnprintf #define util_snprintf snprintf +#define util_vsprintf vsprintf +#define util_sprintf sprintf +#define util_strchr strchr +#define util_strcmp strcmp +#define util_strncmp strncmp +#define util_strncat strncat +#define util_strstr strstr +#define util_memmove memmove + #endif |