diff options
Diffstat (limited to 'src/gallium/auxiliary/util')
34 files changed, 2059 insertions, 371 deletions
diff --git a/src/gallium/auxiliary/util/.gitignore b/src/gallium/auxiliary/util/.gitignore new file mode 100644 index 0000000000..29c586c9b5 --- /dev/null +++ b/src/gallium/auxiliary/util/.gitignore @@ -0,0 +1,2 @@ +u_format_access.c +u_format_table.c diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile index 6a8eb73e84..ae8d330a78 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -5,11 +5,15 @@ LIBNAME = util C_SOURCES = \ u_debug.c \ + u_debug_dump.c \ u_debug_symbol.c \ u_debug_stack.c \ u_blit.c \ u_cache.c \ u_draw_quad.c \ + u_format.c \ + u_format_access.c \ + u_format_table.c \ u_gen_mipmap.c \ u_handle_table.c \ u_hash_table.c \ @@ -32,3 +36,9 @@ C_SOURCES = \ u_simple_screen.c include ../../Makefile.template + +u_format_table.c: u_format_table.py u_format_parse.py u_format.csv + python u_format_table.py u_format.csv > $@ + +u_format_access.c: u_format_access.py u_format_parse.py u_format.csv + python u_format_access.py u_format.csv > $@ diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index fb142eebca..28a5ab4256 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -1,5 +1,23 @@ Import('*') +env.Clone() + +env.Append(CPPPATH = ['.']) + +env.CodeGenerate( + target = 'u_format_table.c', + script = 'u_format_table.py', + source = ['u_format.csv'], + command = 'python $SCRIPT $SOURCE > $TARGET' +) + +env.CodeGenerate( + target = 'u_format_access.c', + script = 'u_format_access.py', + source = ['u_format.csv'], + command = 'python $SCRIPT $SOURCE > $TARGET' +) + util = env.ConvenienceLibrary( target = 'util', source = [ @@ -7,11 +25,15 @@ util = env.ConvenienceLibrary( 'u_blit.c', 'u_cache.c', 'u_debug.c', + 'u_debug_dump.c', 'u_debug_memory.c', 'u_debug_profile.c', 'u_debug_stack.c', 'u_debug_symbol.c', 'u_draw_quad.c', + 'u_format.c', + 'u_format_access.c', + 'u_format_table.c', 'u_gen_mipmap.c', 'u_handle_table.c', 'u_hash.c', diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 414cf91025..c516317d70 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -45,6 +45,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_simple_shaders.h" +#include "util/u_surface.h" #include "cso_cache/cso_context.h" @@ -61,7 +62,7 @@ struct blit_state struct pipe_viewport_state viewport; void *vs; - void *fs; + void *fs[TGSI_WRITEMASK_XYZW + 1]; struct pipe_buffer *vbuf; /**< quad vertices */ unsigned vbuf_slot; @@ -124,7 +125,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) } /* fragment shader */ - ctx->fs = util_make_fragment_tex_shader(pipe); + ctx->fs[TGSI_WRITEMASK_XYZW] = util_make_fragment_tex_shader(pipe); ctx->vbuf = NULL; /* init vertex data that doesn't change */ @@ -145,9 +146,13 @@ void util_destroy_blit(struct blit_state *ctx) { struct pipe_context *pipe = ctx->pipe; + unsigned i; pipe->delete_vs_state(pipe, ctx->vs); - pipe->delete_fs_state(pipe, ctx->fs); + + for (i = 0; i < Elements(ctx->fs); i++) + if (ctx->fs[i]) + pipe->delete_fs_state(pipe, ctx->fs[i]); pipe_buffer_reference(&ctx->vbuf, NULL); @@ -155,7 +160,11 @@ util_destroy_blit(struct blit_state *ctx) } -static unsigned get_next_slot( struct blit_state *ctx ) +/** + * Get offset of next free slot in vertex buffer for quad vertices. + */ +static unsigned +get_next_slot( struct blit_state *ctx ) { const unsigned max_slots = 4096 / sizeof ctx->vertices; @@ -173,7 +182,6 @@ static unsigned get_next_slot( struct blit_state *ctx ) } - /** * Setup vertex data for the textured quad we'll draw. * Note: y=0=top @@ -260,20 +268,50 @@ setup_vertex_data_tex(struct blit_state *ctx, return offset; } + + +/** + * \return TRUE if two regions overlap, FALSE otherwise + */ +static boolean +regions_overlap(int srcX0, int srcY0, + int srcX1, int srcY1, + int dstX0, int dstY0, + int dstX1, int dstY1) +{ + if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) + return FALSE; /* src completely left of dst */ + + if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) + return FALSE; /* dst completely left of src */ + + if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) + return FALSE; /* src completely above dst */ + + if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) + return FALSE; /* dst completely above src */ + + return TRUE; /* some overlap */ +} + + /** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. + * Flipping and stretching are supported. + * XXX what about clipping??? * XXX need some control over blitting Z and/or stencil. */ void -util_blit_pixels(struct blit_state *ctx, - struct pipe_surface *src, - int srcX0, int srcY0, - int srcX1, int srcY1, - struct pipe_surface *dst, - int dstX0, int dstY0, - int dstX1, int dstY1, - float z, uint filter) +util_blit_pixels_writemask(struct blit_state *ctx, + struct pipe_surface *src, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter, + uint writemask) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; @@ -285,10 +323,41 @@ util_blit_pixels(struct blit_state *ctx, const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); unsigned offset; + boolean overlap; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); + assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + + /* do the regions overlap? */ + overlap = util_same_surface(src, dst) && + regions_overlap(srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1); + + /* + * Check for simple case: no format conversion, no flipping, no stretching, + * no overlapping. + * Filter mode should not matter since there's no stretching. + */ + if (dst->format == src->format && + srcX0 < srcX1 && + dstX0 < dstX1 && + srcY0 < srcY1 && + dstY0 < dstY1 && + (dstX1 - dstX0) == (srcX1 - srcX0) && + (dstY1 - dstY0) == (srcY1 - srcY0) && + !overlap) { + pipe->surface_copy(pipe, + dst, dstX0, dstY0, /* dest */ + src, srcX0, srcY0, /* src */ + srcW, srcH); /* size */ + return; + } + if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; @@ -303,20 +372,6 @@ util_blit_pixels(struct blit_state *ctx, dstY1 = tmp; } - assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - - if(dst->format == src->format && (dstX1 - dstX0) == srcW && (dstY1 - dstY0) == srcH) { - /* FIXME: this will most surely fail for overlapping rectangles */ - pipe->surface_copy(pipe, - dst, dstX0, dstY0, /* dest */ - src, srcX0, srcY0, /* src */ - srcW, srcH); /* size */ - return; - } - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); @@ -376,8 +431,11 @@ util_blit_pixels(struct blit_state *ctx, /* texture */ cso_set_sampler_textures(ctx->cso, 1, &tex); + if (ctx->fs[writemask] == NULL) + ctx->fs[writemask] = util_make_fragment_tex_shader_writemask(pipe, writemask); + /* shaders */ - cso_set_fragment_shader_handle(ctx->cso, ctx->fs); + cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]); cso_set_vertex_shader_handle(ctx->cso, ctx->vs); /* drawing dest */ @@ -412,6 +470,27 @@ util_blit_pixels(struct blit_state *ctx, } +void +util_blit_pixels(struct blit_state *ctx, + struct pipe_surface *src, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter ) +{ + util_blit_pixels_writemask( ctx, src, + srcX0, srcY0, + srcX1, srcY1, + dst, + dstX0, dstY0, + dstX1, dstY1, + z, filter, + TGSI_WRITEMASK_XYZW ); +} + + /* Release vertex buffer at end of frame to avoid synchronous * rendering. */ @@ -485,7 +564,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_set_sampler_textures(ctx->cso, 1, &tex); /* shaders */ - cso_set_fragment_shader_handle(ctx->cso, ctx->fs); + cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]); cso_set_vertex_shader_handle(ctx->cso, ctx->vs); /* drawing dest */ diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h index c35beceda8..a102021529 100644 --- a/src/gallium/auxiliary/util/u_blit.h +++ b/src/gallium/auxiliary/util/u_blit.h @@ -60,6 +60,17 @@ util_blit_pixels(struct blit_state *ctx, int dstX1, int dstY1, float z, uint filter); +void +util_blit_pixels_writemask(struct blit_state *ctx, + struct pipe_surface *src, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter, + uint writemask); + extern void util_blit_pixels_tex(struct blit_state *ctx, struct pipe_texture *tex, diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h index d42b65ce28..b82e7cb4d4 100644 --- a/src/gallium/auxiliary/util/u_debug.h +++ b/src/gallium/auxiliary/util/u_debug.h @@ -65,6 +65,11 @@ extern "C" { #define __FUNCTION__ "???" #endif +#if defined(__GNUC__) +#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list))) +#else +#define _util_printf_format(fmt, list) +#endif void _debug_vprintf(const char *format, va_list ap); @@ -82,12 +87,16 @@ _debug_printf(const char *format, ...) /** * Print debug messages. * - * The actual channel used to output debug message is platform specific. To - * avoid misformating or truncation, follow these rules of thumb: + * The actual channel used to output debug message is platform specific. To + * avoid misformating or truncation, follow these rules of thumb: * - output whole lines - * - avoid outputing large strings (512 bytes is the current maximum length + * - avoid outputing large strings (512 bytes is the current maximum length * that is guaranteed to be printed in all platforms) */ +#if !defined(PIPE_OS_HAIKU) +static INLINE void +debug_printf(const char *format, ...) _util_printf_format(1,2); + static INLINE void debug_printf(const char *format, ...) { @@ -101,6 +110,7 @@ debug_printf(const char *format, ...) #endif } +#endif /* !PIPE_OS_HAIKU */ /* * ... isn't portable so we need to pass arguments in parentheses. diff --git a/src/gallium/auxiliary/util/u_debug_dump.c b/src/gallium/auxiliary/util/u_debug_dump.c new file mode 100644 index 0000000000..6bdecde048 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_dump.c @@ -0,0 +1,189 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ + + +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/u_debug_dump.h" + + +#define DEBUG_DUMP_INVALID_NAME "<invalid>" + + +#if 0 +static const char * +debug_dump_strip_prefix(const char *name, + const char *prefix) +{ + const char *stripped; + assert(name); + assert(prefix); + stripped = name; + while(*prefix) { + if(*stripped != *prefix) + return name; + + ++stripped; + ++prefix; + } + return stripped; +} +#endif + +static const char * +debug_dump_enum_continuous(unsigned value, + unsigned num_names, + const char **names) +{ + if (value >= num_names) + return DEBUG_DUMP_INVALID_NAME; + return names[value]; +} + + +#define DEFINE_DEBUG_DUMP_CONTINUOUS(_name) \ + const char * \ + debug_dump_##_name(unsigned value, boolean shortened) \ + { \ + if(shortened) \ + return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_short_names), debug_dump_##_name##_short_names); \ + else \ + return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_names), debug_dump_##_name##_names); \ + } + + +static const char * +debug_dump_blend_factor_names[] = { + DEBUG_DUMP_INVALID_NAME, /* 0x0 */ + "PIPE_BLENDFACTOR_ONE", + "PIPE_BLENDFACTOR_SRC_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA", + "PIPE_BLENDFACTOR_DST_ALPHA", + "PIPE_BLENDFACTOR_DST_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE", + "PIPE_BLENDFACTOR_CONST_COLOR", + "PIPE_BLENDFACTOR_CONST_ALPHA", + "PIPE_BLENDFACTOR_SRC1_COLOR", + "PIPE_BLENDFACTOR_SRC1_ALPHA", + DEBUG_DUMP_INVALID_NAME, /* 0x0b */ + DEBUG_DUMP_INVALID_NAME, /* 0x0c */ + DEBUG_DUMP_INVALID_NAME, /* 0x0d */ + DEBUG_DUMP_INVALID_NAME, /* 0x0e */ + DEBUG_DUMP_INVALID_NAME, /* 0x0f */ + DEBUG_DUMP_INVALID_NAME, /* 0x10 */ + "PIPE_BLENDFACTOR_ZERO", + "PIPE_BLENDFACTOR_INV_SRC_COLOR", + "PIPE_BLENDFACTOR_INV_SRC_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_COLOR", + DEBUG_DUMP_INVALID_NAME, /* 0x16 */ + "PIPE_BLENDFACTOR_INV_CONST_COLOR", + "PIPE_BLENDFACTOR_INV_CONST_ALPHA", + "PIPE_BLENDFACTOR_INV_SRC1_COLOR", + "PIPE_BLENDFACTOR_INV_SRC1_ALPHA" +}; + +static const char * +debug_dump_blend_factor_short_names[] = { + DEBUG_DUMP_INVALID_NAME, /* 0x0 */ + "one", + "src_color", + "src_alpha", + "dst_alpha", + "dst_color", + "src_alpha_saturate", + "const_color", + "const_alpha", + "src1_color", + "src1_alpha", + DEBUG_DUMP_INVALID_NAME, /* 0x0b */ + DEBUG_DUMP_INVALID_NAME, /* 0x0c */ + DEBUG_DUMP_INVALID_NAME, /* 0x0d */ + DEBUG_DUMP_INVALID_NAME, /* 0x0e */ + DEBUG_DUMP_INVALID_NAME, /* 0x0f */ + DEBUG_DUMP_INVALID_NAME, /* 0x10 */ + "zero", + "inv_src_color", + "inv_src_alpha", + "inv_dst_alpha", + "inv_dst_color", + DEBUG_DUMP_INVALID_NAME, /* 0x16 */ + "inv_const_color", + "inv_const_alpha", + "inv_src1_color", + "inv_src1_alpha" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(blend_factor) + + +static const char * +debug_dump_blend_func_names[] = { + "PIPE_BLEND_ADD", + "PIPE_BLEND_SUBTRACT", + "PIPE_BLEND_REVERSE_SUBTRACT", + "PIPE_BLEND_MIN", + "PIPE_BLEND_MAX" +}; + +static const char * +debug_dump_blend_func_short_names[] = { + "add", + "sub", + "rev_sub", + "min", + "max" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(blend_func) + + +static const char * +debug_dump_func_names[] = { + "PIPE_FUNC_NEVER", + "PIPE_FUNC_LESS", + "PIPE_FUNC_EQUAL", + "PIPE_FUNC_LEQUAL", + "PIPE_FUNC_GREATER", + "PIPE_FUNC_NOTEQUAL", + "PIPE_FUNC_GEQUAL", + "PIPE_FUNC_ALWAYS" +}; + +static const char * +debug_dump_func_short_names[] = { + "never", + "less", + "equal", + "less_equal", + "greater", + "not_equal", + "greater_equal", + "always" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(func) diff --git a/src/gallium/auxiliary/util/u_debug_dump.h b/src/gallium/auxiliary/util/u_debug_dump.h new file mode 100644 index 0000000000..102935559c --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_dump.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 VMWARE 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 + * Dump data in human/machine readable format. + * + * @author Jose Fonseca <jfonseca@vmware.com> + */ + +#ifndef U_DEBUG_DUMP_H_ +#define U_DEBUG_DUMP_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +const char * +debug_dump_blend_factor(unsigned value, boolean shortened); + +const char * +debug_dump_blend_func(unsigned value, boolean shortened); + +const char * +debug_dump_func(unsigned value, boolean shortened); + + +/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_H_ */ diff --git a/src/gallium/auxiliary/util/u_fifo.h b/src/gallium/auxiliary/util/u_fifo.h new file mode 100644 index 0000000000..9e007de1ad --- /dev/null +++ b/src/gallium/auxiliary/util/u_fifo.h @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright © 2009 Jakob Bornecrantz + * + * 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, sublicense, + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + **************************************************************************/ + +#ifndef U_FIFO_H +#define U_FIFO_H + +#include "util/u_memory.h" + +struct util_fifo +{ + size_t head; + size_t tail; + size_t num; + size_t size; +}; + +static INLINE struct util_fifo * +u_fifo_create(size_t size) +{ + struct util_fifo *fifo; + fifo = MALLOC(sizeof(*fifo) + size * sizeof(void*)); + + fifo->head = 0; + fifo->tail = 0; + fifo->num = 0; + fifo->size = size; + + return fifo; +} + +static INLINE boolean +u_fifo_add(struct util_fifo *fifo, void *ptr) +{ + void **array = (void**)&fifo[1]; + if (fifo->num >= fifo->size) + return FALSE; + + if (++fifo->head >= fifo->size) + fifo->head = 0; + + array[fifo->head] = ptr; + + ++fifo->num; + + return TRUE; +} + +static INLINE boolean +u_fifo_pop(struct util_fifo *fifo, void **ptr) +{ + void **array = (void**)&fifo[1]; + + if (!fifo->num) + return FALSE; + + if (++fifo->tail >= fifo->size) + fifo->tail = 0; + + *ptr = array[fifo->tail]; + + ++fifo->num; + + return TRUE; +} + +static INLINE void +u_fifo_destroy(struct util_fifo *fifo) +{ + FREE(fifo); +} + +#endif diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c new file mode 100644 index 0000000000..98ea13b60b --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.c @@ -0,0 +1,46 @@ +/************************************************************************** + * + * Copyright 2009 Vmware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ + + +#include "u_format.h" + + +const struct util_format_description * +util_format_description(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description_table; + + while(TRUE) { + if(desc->format == format) + return desc; + + if(desc->format == PIPE_FORMAT_NONE) + return NULL; + + ++desc; + }; +} diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv new file mode 100644 index 0000000000..f1bf94f17d --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.csv @@ -0,0 +1,99 @@ +PIPE_FORMAT_A8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb +PIPE_FORMAT_X8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyx1, rgb +PIPE_FORMAT_B8G8R8A8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb +PIPE_FORMAT_B8G8R8X8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb +PIPE_FORMAT_A1R5G5B5_UNORM , arith , 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb +PIPE_FORMAT_A4R4G4B4_UNORM , arith , 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb +PIPE_FORMAT_R5G6B5_UNORM , arith , 1, 1, un5 , un6 , un5 , , zyx1, rgb +PIPE_FORMAT_A2B10G10R10_UNORM , arith , 1, 1, un10, un10, un10, un2 , xyzw, rgb +PIPE_FORMAT_L8_UNORM , arith , 1, 1, un8 , , , , xxx1, rgb +PIPE_FORMAT_A8_UNORM , arith , 1, 1, un8 , , , , 000x, rgb +PIPE_FORMAT_I8_UNORM , arith , 1, 1, un8 , , , , xxxx, rgb +PIPE_FORMAT_A8L8_UNORM , arith , 1, 1, un8 , un8 , , , xxxy, rgb +PIPE_FORMAT_L16_UNORM , arith , 1, 1, un16, , , , xxx1, rgb +PIPE_FORMAT_Z16_UNORM , array , 1, 1, un16, , , , x___, zs +PIPE_FORMAT_Z32_UNORM , array , 1, 1, un32, , , , x___, zs +PIPE_FORMAT_Z32_FLOAT , array , 1, 1, f32 , , , , x___, zs +PIPE_FORMAT_S8Z24_UNORM , arith , 1, 1, un24, un8 , , , xy__, zs +PIPE_FORMAT_Z24S8_UNORM , arith , 1, 1, un8 , un24, , , yx__, zs +PIPE_FORMAT_X8Z24_UNORM , arith , 1, 1, un24, un8 , , , x___, zs +PIPE_FORMAT_Z24X8_UNORM , arith , 1, 1, un8 , un24, , , y___, zs +PIPE_FORMAT_S8_UNORM , array , 1, 1, un8 , , , , _x__, zs +PIPE_FORMAT_R64_FLOAT , array , 1, 1, f64 , , , , x001, rgb +PIPE_FORMAT_R64G64_FLOAT , array , 1, 1, f64 , f64 , , , xy01, rgb +PIPE_FORMAT_R64G64B64_FLOAT , array , 1, 1, f64 , f64 , f64 , , xyz1, rgb +PIPE_FORMAT_R64G64B64A64_FLOAT , array , 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb +PIPE_FORMAT_R32_FLOAT , array , 1, 1, f32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FLOAT , array , 1, 1, f32 , f32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FLOAT , array , 1, 1, f32 , f32 , f32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FLOAT , array , 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb +PIPE_FORMAT_R32_UNORM , array , 1, 1, un32, , , , x001, rgb +PIPE_FORMAT_R32G32_UNORM , array , 1, 1, un32, un32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_UNORM , array , 1, 1, un32, un32, un32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_UNORM , array , 1, 1, un32, un32, un32, un32, xyzw, rgb +PIPE_FORMAT_R32_USCALED , array , 1, 1, u32 , , , , x001, rgb +PIPE_FORMAT_R32G32_USCALED , array , 1, 1, u32 , u32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_USCALED , array , 1, 1, u32 , u32 , u32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_USCALED , array , 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb +PIPE_FORMAT_R32_SNORM , array , 1, 1, sn32, , , , x001, rgb +PIPE_FORMAT_R32G32_SNORM , array , 1, 1, sn32, sn32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_SNORM , array , 1, 1, sn32, sn32, sn32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SNORM , array , 1, 1, sn32, sn32, sn32, sn32, xyzw, rgb +PIPE_FORMAT_R32_SSCALED , array , 1, 1, s32 , , , , x001, rgb +PIPE_FORMAT_R32G32_SSCALED , array , 1, 1, s32 , s32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_SSCALED , array , 1, 1, s32 , s32 , s32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SSCALED , array , 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb +PIPE_FORMAT_R16_UNORM , array , 1, 1, un16, , , , x001, rgb +PIPE_FORMAT_R16G16_UNORM , array , 1, 1, un16, un16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_UNORM , array , 1, 1, un16, un16, un16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_UNORM , array , 1, 1, un16, un16, un16, un16, xyzw, rgb +PIPE_FORMAT_R16_USCALED , array , 1, 1, u16 , , , , x001, rgb +PIPE_FORMAT_R16G16_USCALED , array , 1, 1, u16 , u16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_USCALED , array , 1, 1, u16 , u16 , u16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_USCALED , array , 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb +PIPE_FORMAT_R16_SNORM , array , 1, 1, sn16, , , , x001, rgb +PIPE_FORMAT_R16G16_SNORM , array , 1, 1, sn16, sn16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_SNORM , array , 1, 1, sn16, sn16, sn16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SNORM , array , 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb +PIPE_FORMAT_R16_SSCALED , array , 1, 1, s16 , , , , x001, rgb +PIPE_FORMAT_R16G16_SSCALED , array , 1, 1, s16 , s16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_SSCALED , array , 1, 1, s16 , s16 , s16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SSCALED , array , 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb +PIPE_FORMAT_R8_UNORM , array , 1, 1, un8 , , , , x001, rgb +PIPE_FORMAT_R8G8_UNORM , array , 1, 1, un8 , un8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_UNORM , array , 1, 1, un8 , un8 , un8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyz1, rgb +PIPE_FORMAT_R8_USCALED , array , 1, 1, u8 , , , , x001, rgb +PIPE_FORMAT_R8G8_USCALED , array , 1, 1, u8 , u8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_USCALED , array , 1, 1, u8 , u8 , u8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyz1, rgb +PIPE_FORMAT_R8_SNORM , array , 1, 1, sn8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SNORM , array , 1, 1, sn8 , sn8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyz1, rgb +PIPE_FORMAT_B6G5R5_SNORM , arith , 1, 1, sn5 , sn5 , sn6 , , zyx1, rgb +PIPE_FORMAT_A8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyxw, rgb +PIPE_FORMAT_X8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyx1, rgb +PIPE_FORMAT_R8_SSCALED , array , 1, 1, s8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SSCALED , array , 1, 1, s8 , s8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SSCALED , array , 1, 1, s8 , s8 , s8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyz1, rgb +PIPE_FORMAT_R32_FIXED , array , 1, 1, h32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FIXED , array , 1, 1, h32 , h32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FIXED , array , 1, 1, h32 , h32 , h32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FIXED , array , 1, 1, h32 , h32 , h32 , h32 , xyzw, rgb +PIPE_FORMAT_L8_SRGB , arith , 1, 1, u8 , , , , xxx1, srgb +PIPE_FORMAT_A8L8_SRGB , arith , 1, 1, u8 , u8 , , , xxxy, srgb +PIPE_FORMAT_R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , , xyz1, srgb +PIPE_FORMAT_R8G8B8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyzw, srgb +PIPE_FORMAT_R8G8B8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyz1, srgb +PIPE_FORMAT_A8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , wxyz, srgb +PIPE_FORMAT_X8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , 1xyz, srgb +PIPE_FORMAT_B8G8R8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyxw, srgb +PIPE_FORMAT_B8G8R8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyx1, srgb +PIPE_FORMAT_X8UB8UG8SR8S_NORM , arith , 1, 1, sn8 , sn8 , un8 , x8 , 1zyx, rgb +PIPE_FORMAT_B6UG5SR5S_NORM , arith , 1, 1, sn5 , sn5 , un6 , , xyz1, rgb diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h new file mode 100644 index 0000000000..7b5b7fcda5 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.h @@ -0,0 +1,138 @@ +/************************************************************************** + * + * Copyright 2009 Vmware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ + + +#ifndef U_FORMAT_H +#define U_FORMAT_H + + +#include "pipe/p_format.h" + + +enum util_format_layout { + UTIL_FORMAT_LAYOUT_SCALAR = 0, + UTIL_FORMAT_LAYOUT_ARITH = 1, + UTIL_FORMAT_LAYOUT_ARRAY = 2, + UTIL_FORMAT_LAYOUT_YUV = 3, + UTIL_FORMAT_LAYOUT_DXT = 4 +}; + + +struct util_format_block +{ + /** Block width in pixels */ + unsigned width; + + /** Block height in pixels */ + unsigned height; + + /** Block size in bytes */ + unsigned bits; +}; + + +enum util_format_type { + UTIL_FORMAT_TYPE_VOID = 0, + UTIL_FORMAT_TYPE_UNSIGNED = 1, + UTIL_FORMAT_TYPE_SIGNED = 2, + UTIL_FORMAT_TYPE_FIXED = 3, + UTIL_FORMAT_TYPE_FLOAT = 4 +}; + + +enum util_format_swizzle { + UTIL_FORMAT_SWIZZLE_X = 0, + UTIL_FORMAT_SWIZZLE_Y = 1, + UTIL_FORMAT_SWIZZLE_Z = 2, + UTIL_FORMAT_SWIZZLE_W = 3, + UTIL_FORMAT_SWIZZLE_0 = 4, + UTIL_FORMAT_SWIZZLE_1 = 5, + UTIL_FORMAT_SWIZZLE_NONE = 6 +}; + + +enum util_format_colorspace { + UTIL_FORMAT_COLORSPACE_RGB = 0, + UTIL_FORMAT_COLORSPACE_SRGB = 1, + UTIL_FORMAT_COLORSPACE_YUV = 2, + UTIL_FORMAT_COLORSPACE_ZS = 3, +}; + + +struct util_format_channel_description +{ + unsigned type:6; + unsigned normalized:1; + unsigned size:9; +}; + + +struct util_format_description +{ + enum pipe_format format; + const char *name; + struct util_format_block block; + enum util_format_layout layout; + struct util_format_channel_description channel[4]; + unsigned char swizzle[4]; + enum util_format_colorspace colorspace; +}; + + +extern const struct util_format_description +util_format_description_table[]; + + +const struct util_format_description * +util_format_description(enum pipe_format format); + + +void +util_format_read_4f(enum pipe_format format, + float *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4f(enum pipe_format format, + const float *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4ub(enum pipe_format format, + uint8_t *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ub(enum pipe_format format, + const uint8_t *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +#endif /* ! U_FORMAT_H */ diff --git a/src/gallium/auxiliary/util/u_format_access.py b/src/gallium/auxiliary/util/u_format_access.py new file mode 100644 index 0000000000..eeb1a9657f --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_access.py @@ -0,0 +1,498 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 VMWARE 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 + * Pixel format accessor functions. + * + * @author Jose Fonseca <jfonseca@vmware.com> + */ +''' + + +import sys + +from u_format_parse import * + + +def short_name(format): + '''Make up a short norm for a format, suitable to be used as suffix in + function names.''' + + name = format.name + if name.startswith('PIPE_FORMAT_'): + name = name[len('PIPE_FORMAT_'):] + name = name.lower() + return name + + +def is_format_supported(format): + '''Determines whether we actually have the plumbing necessary to generate the + to read/write to/from this format.''' + + # FIXME: Ideally we would support any format combination here. + + # XXX: It should be straightforward to support srgb + if format.colorspace not in ('rgb', 'zs'): + return False + + if format.layout not in (ARITH, ARRAY): + return False + + for i in range(4): + type = format.in_types[i] + if type.kind not in (VOID, UNSIGNED, FLOAT): + return False + + # We can only read a color from a depth/stencil format if the depth channel is present + if format.colorspace == 'zs' and format.out_swizzle[0] == SWIZZLE_NONE: + return False + + return True + + +def native_type(format): + '''Get the native appropriate for a format.''' + + if format.layout == ARITH: + # For arithmetic pixel formats return the integer type that matches the whole pixel + return 'uint%u_t' % format.block_size() + elif format.layout == ARRAY: + # For array pixel formats return the integer type that matches the color channel + type = format.in_types[0] + if type.kind == UNSIGNED: + return 'uint%u_t' % type.size + elif type.kind == SIGNED: + return 'int%u_t' % type.size + elif type.kind == FLOAT: + if type.size == 32: + return 'float' + elif type.size == 64: + return 'double' + else: + assert False + else: + assert False + else: + assert False + + +def intermediate_native_type(bits, sign): + '''Find a native type adequate to hold intermediate results of the request bit size.''' + + bytes = 4 # don't use anything smaller than 32bits + while bytes * 8 < bits: + bytes *= 2 + bits = bytes*8 + + if sign: + return 'int%u_t' % bits + else: + return 'uint%u_t' % bits + + +def get_one_shift(type): + '''Get the number of the bit that matches unity for this type.''' + if type.kind == 'FLOAT': + assert False + if not type.norm: + return 0 + if type.kind == UNSIGNED: + return type.size + if type.kind == SIGNED: + return type.size - 1 + if type.kind == FIXED: + return type.size / 2 + assert False + + +def get_one(type): + '''Get the value of unity for this type.''' + if type.kind == 'FLOAT' or not type.norm: + return 1 + else: + return (1 << get_one_shift(type)) - 1 + + +def generate_clamp(): + '''Code generate the clamping functions for each type. + + We don't use a macro so that arguments with side effects, + like *src_pixel++ are correctly handled. + ''' + + for suffix, native_type in [ + ('', 'double'), + ('f', 'float'), + ('ui', 'unsigned int'), + ('si', 'int'), + ]: + print 'static INLINE %s' % native_type + print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix, native_type, native_type, native_type) + print '{' + print ' if(value < lbound)' + print ' return lbound;' + print ' if(value > ubound)' + print ' return ubound;' + print ' return value;' + print '}' + print + + +def clamp_expr(src_type, dst_type, dst_native_type, value): + '''Generate the expression to clamp the value in the source type to the + destination type range.''' + + if src_type == dst_type: + return value + + # Pick the approriate clamp function + if src_type.kind == FLOAT: + if src_type.size == 32: + func = 'clampf' + elif src_type.size == 64: + func = 'clamp' + else: + assert False + elif src_type.kind == UNSIGNED: + func = 'clampui' + elif src_type.kind == SIGNED: + func = 'clampsi' + else: + assert False + + # Clamp floats to [-1, 1] or [0, 1] range + if src_type.kind == FLOAT and dst_type.norm: + max = 1 + if src_type.sign and dst_type.sign: + min = -1 + else: + min = 0 + return '%s(%s, %s, %s)' % (func, value, min, max) + + # FIXME: Also clamp scaled values + + return value + + +def conversion_expr(src_type, dst_type, dst_native_type, value): + '''Generate the expression to convert a value between two types.''' + + if src_type == dst_type: + return value + + if src_type.kind == FLOAT and dst_type.kind == FLOAT: + return '(%s)%s' % (dst_native_type, value) + + if not src_type.norm and not dst_type.norm: + return '(%s)%s' % (dst_native_type, value) + + value = clamp_expr(src_type, dst_type, dst_native_type, value) + + if dst_type.kind == FLOAT: + if src_type.norm: + one = get_one(src_type) + if src_type.size <= 23: + scale = '(1.0f/0x%x)' % one + else: + # bigger than single precision mantissa, use double + scale = '(1.0/0x%x)' % one + value = '(%s * %s)' % (value, scale) + return '(%s)%s' % (dst_native_type, value) + + if src_type.kind == FLOAT: + if dst_type.norm: + dst_one = get_one(dst_type) + if dst_type.size <= 23: + scale = '0x%x' % dst_one + else: + # bigger than single precision mantissa, use double + scale = '(double)0x%x' % dst_one + value = '(%s * %s)' % (value, scale) + return '(%s)%s' % (dst_native_type, value) + + if src_type.kind == dst_type.kind: + src_one = get_one(src_type) + dst_one = get_one(dst_type) + + if src_one > dst_one and src_type.norm and dst_type.norm: + # We can just bitshift + src_shift = get_one_shift(src_type) + dst_shift = get_one_shift(dst_type) + value = '(%s >> %s)' % (value, src_shift - dst_shift) + else: + # We need to rescale using an intermediate type big enough to hold the multiplication of both + tmp_native_type = intermediate_native_type(src_type.size + dst_type.size, src_type.sign and dst_type.sign) + value = '(%s)%s' % (tmp_native_type, value) + value = '%s * 0x%x / 0x%x' % (value, dst_one, src_one) + value = '(%s)%s' % (dst_native_type, value) + return value + + assert False + + +def generate_format_read(format, dst_type, dst_native_type, dst_suffix): + '''Generate the function to read pixels from a particular format''' + + name = short_name(format) + + src_native_type = native_type(format) + + print 'static void' + print 'util_format_%s_read_%s(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type) + print '{' + print ' unsigned x, y;' + print ' const uint8_t *src_row = src + y0*src_stride;' + print ' %s *dst_row = dst;' % dst_native_type + print ' for (y = 0; y < h; ++y) {' + print ' const %s *src_pixel = (const %s *)(src_row + x0*%u);' % (src_native_type, src_native_type, format.stride()) + print ' %s *dst_pixel = dst_row;' %dst_native_type + print ' for (x = 0; x < w; ++x) {' + + names = ['']*4 + if format.colorspace == 'rgb': + for i in range(4): + swizzle = format.out_swizzle[i] + if swizzle < 4: + names[swizzle] += 'rgba'[i] + elif format.colorspace == 'zs': + swizzle = format.out_swizzle[0] + if swizzle < 4: + names[swizzle] = 'z' + else: + assert False + else: + assert False + + if format.layout == ARITH: + print ' %s pixel = *src_pixel++;' % src_native_type + shift = 0; + for i in range(4): + src_type = format.in_types[i] + width = src_type.size + if names[i]: + value = 'pixel' + mask = (1 << width) - 1 + if shift: + value = '(%s >> %u)' % (value, shift) + if shift + width < format.block_size(): + value = '(%s & 0x%x)' % (value, mask) + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' %s %s = %s;' % (dst_native_type, names[i], value) + shift += width + elif format.layout == ARRAY: + for i in range(4): + src_type = format.in_types[i] + if names[i]: + value = '(*src_pixel++)' + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' %s %s = %s;' % (dst_native_type, names[i], value) + else: + assert False + + for i in range(4): + if format.colorspace == 'rgb': + swizzle = format.out_swizzle[i] + if swizzle < 4: + value = names[swizzle] + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: + value = '1' + else: + assert False + elif format.colorspace == 'zs': + if i < 3: + value = 'z' + else: + value = '1' + else: + assert False + print ' *dst_pixel++ = %s; /* %s */' % (value, 'rgba'[i]) + + print ' }' + print ' src_row += src_stride;' + print ' dst_row += dst_stride/sizeof(%s);' % dst_native_type + print ' }' + print '}' + print + + +def generate_format_write(format, src_type, src_native_type, src_suffix): + '''Generate the function to write pixels to a particular format''' + + name = short_name(format) + + dst_native_type = native_type(format) + + print 'static void' + print 'util_format_%s_write_%s(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type) + print '{' + print ' unsigned x, y;' + print ' uint8_t *dst_row = dst + y0*dst_stride;' + print ' const %s *src_row = src;' % src_native_type + print ' for (y = 0; y < h; ++y) {' + print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride()) + print ' const %s *src_pixel = src_row;' %src_native_type + print ' for (x = 0; x < w; ++x) {' + + inv_swizzle = [None]*4 + if format.colorspace == 'rgb': + for i in range(4): + swizzle = format.out_swizzle[i] + if swizzle < 4: + inv_swizzle[swizzle] = i + elif format.colorspace == 'zs': + swizzle = format.out_swizzle[0] + if swizzle < 4: + inv_swizzle[swizzle] = 0 + else: + assert False + + if format.layout == ARITH: + print ' %s pixel = 0;' % dst_native_type + shift = 0; + for i in range(4): + dst_type = format.in_types[i] + width = dst_type.size + if inv_swizzle[i] is not None: + value = 'src_pixel[%u]' % inv_swizzle[i] + value = conversion_expr(src_type, dst_type, dst_native_type, value) + if shift: + value = '(%s << %u)' % (value, shift) + print ' pixel |= %s;' % value + shift += width + print ' *dst_pixel++ = pixel;' + elif format.layout == ARRAY: + for i in range(4): + dst_type = format.in_types[i] + if inv_swizzle[i] is not None: + value = 'src_pixel[%u]' % inv_swizzle[i] + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' *dst_pixel++ = %s;' % value + else: + assert False + print ' src_pixel += 4;' + + print ' }' + print ' dst_row += dst_stride;' + print ' src_row += src_stride/sizeof(%s);' % src_native_type + print ' }' + print '}' + print + + +def generate_read(formats, dst_type, dst_native_type, dst_suffix): + '''Generate the dispatch function to read pixels from any format''' + + for format in formats: + if is_format_supported(format): + generate_format_read(format, dst_type, dst_native_type, dst_suffix) + + print 'void' + print 'util_format_read_%s(enum pipe_format format, %s *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type) + print '{' + print ' void (*func)(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type + print ' switch(format) {' + for format in formats: + if is_format_supported(format): + print ' case %s:' % format.name + print ' func = &util_format_%s_read_%s;' % (short_name(format), dst_suffix) + print ' break;' + print ' default:' + print ' debug_printf("unsupported format\\n");' + print ' return;' + print ' }' + print ' func(dst, dst_stride, (const uint8_t *)src, src_stride, x, y, w, h);' + print '}' + print + + +def generate_write(formats, src_type, src_native_type, src_suffix): + '''Generate the dispatch function to write pixels to any format''' + + for format in formats: + if is_format_supported(format): + generate_format_write(format, src_type, src_native_type, src_suffix) + + print 'void' + print 'util_format_write_%s(enum pipe_format format, const %s *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type) + + print '{' + print ' void (*func)(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type + print ' switch(format) {' + for format in formats: + if is_format_supported(format): + print ' case %s:' % format.name + print ' func = &util_format_%s_write_%s;' % (short_name(format), src_suffix) + print ' break;' + print ' default:' + print ' debug_printf("unsupported format\\n");' + print ' return;' + print ' }' + print ' func(src, src_stride, (uint8_t *)dst, dst_stride, x, y, w, h);' + print '}' + print + + +def main(): + formats = [] + for arg in sys.argv[1:]: + formats.extend(parse(arg)) + + print '/* This file is autogenerated by u_format_access.py from u_format.csv. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print __doc__.strip() + print + print '#include "pipe/p_compiler.h"' + print '#include "u_format.h"' + print '#include "u_math.h"' + print + + generate_clamp() + + type = Type(FLOAT, False, 32) + native_type = 'float' + suffix = '4f' + + generate_read(formats, type, native_type, suffix) + generate_write(formats, type, native_type, suffix) + + type = Type(UNSIGNED, True, 8) + native_type = 'uint8_t' + suffix = '4ub' + + generate_read(formats, type, native_type, suffix) + generate_write(formats, type, native_type, suffix) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py new file mode 100755 index 0000000000..493aff7112 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_parse.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ +''' + + +import sys + + +VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5) + +SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7) + +ARITH = 'arith' +ARRAY = 'array' + + +class Type: + '''Describe the type of a color channel.''' + + def __init__(self, kind, norm, size): + self.kind = kind + self.norm = norm + self.size = size + self.sign = kind in (SIGNED, FIXED, FLOAT) + + def __str__(self): + s = str(self.kind) + if self.norm: + s += 'n' + s += str(self.size) + return s + + def __eq__(self, other): + return self.kind == other.kind and self.norm == other.norm and self.size == other.size + + +class Format: + '''Describe a pixel format.''' + + def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace): + self.name = name + self.layout = layout + self.block_width = block_width + self.block_height = block_height + self.in_types = in_types + self.out_swizzle = out_swizzle + self.name = name + self.colorspace = colorspace + + def __str__(self): + return self.name + + def block_size(self): + size = 0 + for type in self.in_types: + size += type.size + return size + + def stride(self): + return self.block_size()/8 + + +_kind_parse_map = { + '': VOID, + 'x': VOID, + 'u': UNSIGNED, + 's': SIGNED, + 'h': FIXED, + 'f': FLOAT, +} + +_swizzle_parse_map = { + 'x': SWIZZLE_X, + 'y': SWIZZLE_Y, + 'z': SWIZZLE_Z, + 'w': SWIZZLE_W, + '0': SWIZZLE_0, + '1': SWIZZLE_1, + '_': SWIZZLE_NONE, +} + +def parse(filename): + '''Parse the format descrition in CSV format in terms of the + Type and Format classes above.''' + + stream = open(filename) + formats = [] + for line in stream: + line = line.rstrip() + fields = [field.strip() for field in line.split(',')] + name = fields[0] + layout = fields[1] + block_width, block_height = map(int, fields[2:4]) + in_types = [] + for field in fields[4:8]: + if field: + kind = _kind_parse_map[field[0]] + if field[1] == 'n': + norm = True + size = int(field[2:]) + else: + norm = False + size = int(field[1:]) + else: + kind = VOID + norm = False + size = 0 + in_type = Type(kind, norm, size) + in_types.append(in_type) + out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]] + colorspace = fields[9] + formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace)) + return formats + diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py new file mode 100755 index 0000000000..8834568e8e --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_table.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ +''' + + +import sys + +from u_format_parse import * + + +def layout_map(layout): + return 'UTIL_FORMAT_LAYOUT_' + str(layout).upper() + + +def colorspace_map(colorspace): + return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper() + + +colorspace_channels_map = { + 'rgb': 'rgba', + 'rgba': 'rgba', + 'zs': 'zs', + 'yuv': ['y1', 'y2', 'u', 'v'], + 'dxt': [] +} + + +kind_map = { + VOID: "UTIL_FORMAT_TYPE_VOID", + UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED", + SIGNED: "UTIL_FORMAT_TYPE_SIGNED", + FIXED: "UTIL_FORMAT_TYPE_FIXED", + FLOAT: "UTIL_FORMAT_TYPE_FLOAT", +} + + +def bool_map(value): + if value: + return "TRUE" + else: + return "FALSE" + + +swizzle_map = { + SWIZZLE_X: "UTIL_FORMAT_SWIZZLE_X", + SWIZZLE_Y: "UTIL_FORMAT_SWIZZLE_Y", + SWIZZLE_Z: "UTIL_FORMAT_SWIZZLE_Z", + SWIZZLE_W: "UTIL_FORMAT_SWIZZLE_W", + SWIZZLE_0: "UTIL_FORMAT_SWIZZLE_0", + SWIZZLE_1: "UTIL_FORMAT_SWIZZLE_1", + SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE", +} + + +def write_format_table(formats): + print '/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print __doc__.strip() + print + print '#include "u_format.h"' + print + print 'const struct util_format_description' + print 'util_format_description_table[] = ' + print "{" + for format in formats: + print " {" + print " %s," % (format.name,) + print " \"%s\"," % (format.name,) + print " {%u, %u, %u}, /* block */" % (format.block_width, format.block_height, format.block_size()) + print " %s," % (layout_map(format.layout),) + print " {" + for i in range(4): + type = format.in_types[i] + if i < 3: + sep = "," + else: + sep = "" + print " {%s, %s, %u}%s /* %s */" % (kind_map[type.kind], bool_map(type.norm), type.size, sep, "xyzw"[i]) + print " }," + print " {" + for i in range(4): + swizzle = format.out_swizzle[i] + if i < 3: + sep = "," + else: + sep = "" + try: + comment = layout_channels_map[format.layout][i] + except: + comment = 'ignored' + print " %s%s /* %s */" % (swizzle_map[swizzle], sep, comment) + print " }," + print " %s," % (colorspace_map(format.colorspace),) + print " }," + print " {" + print " PIPE_FORMAT_NONE," + print " \"PIPE_FORMAT_NONE\"," + print " {0, 0, 0}," + print " 0," + print " {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}," + print " {0, 0, 0, 0}," + print " 0" + print " }," + print "};" + + +def main(): + + formats = [] + for arg in sys.argv[1:]: + formats.extend(parse(arg)) + write_format_table(formats) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index ca797486a0..f06c0e463d 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -46,10 +46,6 @@ #include "util/u_gen_mipmap.h" #include "util/u_simple_shaders.h" -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" - #include "cso_cache/cso_context.h" @@ -921,11 +917,19 @@ static void format_to_type_comps(enum pipe_format pformat, enum dtype *datatype, uint *comps) { + /* XXX I think this could be implemented in terms of the pf_*() functions */ switch (pformat) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_X8R8G8B8_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_R8G8B8A8_SRGB: + case PIPE_FORMAT_R8G8B8X8_SRGB: + case PIPE_FORMAT_A8R8G8B8_SRGB: + case PIPE_FORMAT_X8R8G8B8_SRGB: + case PIPE_FORMAT_B8G8R8A8_SRGB: + case PIPE_FORMAT_B8G8R8X8_SRGB: + case PIPE_FORMAT_R8G8B8_SRGB: *datatype = DTYPE_UBYTE; *comps = 4; return; @@ -942,12 +946,14 @@ format_to_type_comps(enum pipe_format pformat, *comps = 3; return; case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: *datatype = DTYPE_UBYTE; *comps = 1; return; case PIPE_FORMAT_A8L8_UNORM: + case PIPE_FORMAT_A8L8_SRGB: *datatype = DTYPE_UBYTE; *comps = 2; return; diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 163522d3ef..cd6a9fcc09 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -53,11 +53,11 @@ __inline double ceil(double val) { double ceil_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { ceil_val = val; } else { - if(val > 0) { + if (val > 0) { ceil_val = (long) val + 1; } else { @@ -73,11 +73,11 @@ __inline double floor(double val) { double floor_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { floor_val = val; } else { - if(val > 0) { + if (val > 0) { floor_val = (long) val; } else { @@ -189,7 +189,10 @@ static INLINE double log2( double x ) extern float pow2_table[POW2_TABLE_SIZE]; - +/** + * Initialize math module. This should be called before using any + * other functions in this module. + */ extern void util_init_math(void); @@ -216,23 +219,24 @@ util_fast_exp2(float x) int32_t ipart; float fpart, mpart; union fi epart; - + if(x > 129.00000f) return 3.402823466e+38f; - - if(x < -126.99999f) + + if (x < -126.99999f) return 0.0f; ipart = (int32_t) x; fpart = x - (float) ipart; - + /* same as * epart.f = (float) (1 << ipart) - * but faster and without integer overflow for ipart > 31 */ + * but faster and without integer overflow for ipart > 31 + */ epart.i = (ipart + 127 ) << 23; - + mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; - + return epart.f * mpart; } @@ -254,6 +258,9 @@ util_fast_exp(float x) extern float log2_table[LOG2_TABLE_SIZE]; +/** + * Fast approximation to log2(x). + */ static INLINE float util_fast_log2(float x) { @@ -267,6 +274,9 @@ util_fast_log2(float x) } +/** + * Fast approximation to x^y. + */ static INLINE float util_fast_pow(float x, float y) { @@ -282,7 +292,6 @@ util_is_power_of_two( unsigned v ) } - /** * Floor(x), returned as int. */ @@ -292,8 +301,8 @@ util_ifloor(float f) int ai, bi; double af, bf; union fi u; - af = (3 << 22) + 0.5 + (double)f; - bf = (3 << 22) + 0.5 - (double)f; + af = (3 << 22) + 0.5 + (double) f; + bf = (3 << 22) + 0.5 - (double) f; u.f = (float) af; ai = u.i; u.f = (float) bf; bi = u.i; return (ai - bi) >> 1; @@ -313,9 +322,9 @@ util_iround(float f) #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) int r; _asm { - fld f - fistp r - } + fld f + fistp r + } return r; #else if (f >= 0.0f) @@ -340,15 +349,27 @@ util_is_inf_or_nan(float x) /** + * Test whether x is a power of two. + */ +static INLINE boolean +util_is_pot(unsigned x) +{ + return (x & (x - 1)) == 0; +} + + +/** * Find first bit set in word. Least significant bit is 1. * Return 0 if no bits set. */ -#if defined(_MSC_VER) && _MSC_VER >= 1300 +#if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) +unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); +#pragma intrinsic(_BitScanForward) static INLINE unsigned long ffs( unsigned long u ) { unsigned long i; - if(_BitScanForward(&i, u)) + if (_BitScanForward(&i, u)) return i + 1; else return 0; @@ -359,7 +380,7 @@ unsigned ffs( unsigned u ) { unsigned i; - if( u == 0 ) { + if (u == 0) { return 0; } @@ -373,6 +394,10 @@ unsigned ffs( unsigned u ) #define ffs __builtin_ffs #endif +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#endif + /* Could also binary search for the highest bit. */ @@ -398,7 +423,10 @@ fui( float f ) } - +/** + * Convert ubyte to float in [0, 1]. + * XXX a 256-entry lookup table would be slightly faster. + */ static INLINE float ubyte_to_float(ubyte ub) { @@ -429,7 +457,23 @@ float_to_ubyte(float f) } +/** + * Calc log base 2 + */ +static INLINE unsigned +util_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + +/** + * Clamp X to [MIN, MAX]. + * This is a macro to allow float, int, uint, etc. types. + */ #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) @@ -442,6 +486,11 @@ align(int value, int alignment) return (value + alignment - 1) & ~(alignment - 1); } +static INLINE unsigned +minify(unsigned value) +{ + return MAX2(1, value >> 1); +} #ifndef COPY_4V #define COPY_4V( DST, SRC ) \ diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h index 0b18d043ad..c3f8c91833 100644 --- a/src/gallium/auxiliary/util/u_memory.h +++ b/src/gallium/auxiliary/util/u_memory.h @@ -100,8 +100,14 @@ ExFreePool(void *P); #define MALLOC( SIZE ) malloc( SIZE ) #define CALLOC( COUNT, SIZE ) calloc( COUNT, SIZE ) #define FREE( PTR ) free( PTR ) -#define REALLOC( OLDPTR, OLDSIZE, NEWSIZE ) realloc( OLDPTR, NEWSIZE ) +static INLINE void * +_REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) +{ + (void) old_size; + return realloc(old_ptr, new_size); +} +#define REALLOC( a, b, c ) _REALLOC( a, b, c ) #endif diff --git a/src/gallium/auxiliary/util/u_mm.c b/src/gallium/auxiliary/util/u_mm.c index 151a480d34..4b75d4ba1d 100644 --- a/src/gallium/auxiliary/util/u_mm.c +++ b/src/gallium/auxiliary/util/u_mm.c @@ -33,30 +33,32 @@ void u_mmDumpMemInfo(const struct mem_block *heap) { - debug_printf("Memory heap %p:\n", (void *)heap); + debug_printf("Memory heap %p:\n", (void *) heap); if (heap == 0) { debug_printf(" heap == 0\n"); - } else { + } + else { const struct mem_block *p; - for(p = heap->next; p != heap; p = p->next) { - debug_printf(" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, - p->free ? 'F':'.', - p->reserved ? 'R':'.'); + for (p = heap->next; p != heap; p = p->next) { + debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); } debug_printf("\nFree list:\n"); - for(p = heap->next_free; p != heap; p = p->next_free) { - debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, - p->free ? 'F':'.', - p->reserved ? 'R':'.'); + for (p = heap->next_free; p != heap; p = p->next_free) { + debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); } } debug_printf("End of memory blocks\n"); } + struct mem_block * u_mmInit(int ofs, int size) { diff --git a/src/gallium/auxiliary/util/u_mm.h b/src/gallium/auxiliary/util/u_mm.h index ce20e48763..6b158aae6e 100644 --- a/src/gallium/auxiliary/util/u_mm.h +++ b/src/gallium/auxiliary/util/u_mm.h @@ -84,7 +84,7 @@ extern struct mem_block *u_mmFindBlock(struct mem_block *heap, int start); extern void u_mmDestroy(struct mem_block *mmInit); /** - * For debuging purpose. + * For debugging purposes. */ extern void u_mmDumpMemInfo(const struct mem_block *mmInit); diff --git a/src/gallium/auxiliary/util/u_network.c b/src/gallium/auxiliary/util/u_network.c index 07d804ecdb..bc4b758406 100644 --- a/src/gallium/auxiliary/util/u_network.c +++ b/src/gallium/auxiliary/util/u_network.c @@ -6,7 +6,7 @@ #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) # include <winsock2.h> # include <windows.h> -#elif defined(PIPE_OS_LINUX) +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) # include <sys/socket.h> # include <netinet/in.h> # include <unistd.h> @@ -54,7 +54,7 @@ u_socket_close(int s) if (s < 0) return; -#if defined(PIPE_OS_LINUX) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) shutdown(s, SHUT_RDWR); close(s); #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) @@ -169,7 +169,7 @@ u_socket_listen_on_port(uint16_t portnum) void u_socket_block(int s, boolean block) { -#if defined(PIPE_OS_LINUX) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) int old = fcntl(s, F_GETFL, 0); if (old == -1) return; diff --git a/src/gallium/auxiliary/util/u_network.h b/src/gallium/auxiliary/util/u_network.h index 14d3884427..8c778f492c 100644 --- a/src/gallium/auxiliary/util/u_network.h +++ b/src/gallium/auxiliary/util/u_network.h @@ -6,7 +6,7 @@ #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) # define PIPE_HAVE_SOCKETS -#elif defined(PIPE_OS_LINUX) +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) # define PIPE_HAVE_SOCKETS #endif diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c index 74259d453b..9866b6fc8a 100644 --- a/src/gallium/auxiliary/util/u_rect.c +++ b/src/gallium/auxiliary/util/u_rect.c @@ -43,7 +43,7 @@ * src_pitch may be negative to do vertical flip of pixels from source. */ void -pipe_copy_rect(ubyte * dst, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -91,7 +91,7 @@ pipe_copy_rect(ubyte * dst, } void -pipe_fill_rect(ubyte * dst, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -204,7 +204,7 @@ util_surface_copy(struct pipe_context *pipe, if (src_map && dst_map) { /* If do_flip, invert src_y position and pass negative src stride */ - pipe_copy_rect(dst_map, + util_copy_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, @@ -263,7 +263,7 @@ util_surface_fill(struct pipe_context *pipe, case 1: case 2: case 4: - pipe_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, + util_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, width, height, value); break; case 8: diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h index 59e842e16d..daa50834d3 100644 --- a/src/gallium/auxiliary/util/u_rect.h +++ b/src/gallium/auxiliary/util/u_rect.h @@ -42,13 +42,13 @@ struct pipe_surface; extern void -pipe_copy_rect(ubyte * dst, const struct pipe_format_block *block, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, const ubyte * src, int src_stride, unsigned src_x, int src_y); extern void -pipe_fill_rect(ubyte * dst, const struct pipe_format_block *block, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, uint32_t value); diff --git a/src/gallium/auxiliary/util/u_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c index 8114b53cd0..5238299015 100644 --- a/src/gallium/auxiliary/util/u_simple_screen.c +++ b/src/gallium/auxiliary/util/u_simple_screen.c @@ -52,8 +52,7 @@ pass_user_buffer_create(struct pipe_screen *screen, unsigned bytes) { struct pipe_buffer *buffer = - screen->winsys->user_buffer_create(screen->winsys, - ptr, bytes); + screen->winsys->user_buffer_create(screen->winsys, ptr, bytes); buffer->screen = screen; @@ -65,12 +64,12 @@ pass_surface_buffer_create(struct pipe_screen *screen, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_buffer *buffer = - screen->winsys->surface_buffer_create(screen->winsys, - width, height, - format, usage, stride); + screen->winsys->surface_buffer_create(screen->winsys, width, height, + format, usage, tex_usage, stride); buffer->screen = screen; @@ -82,8 +81,7 @@ pass_buffer_map(struct pipe_screen *screen, struct pipe_buffer *buf, unsigned usage) { - return screen->winsys->buffer_map(screen->winsys, - buf, usage); + return screen->winsys->buffer_map(screen->winsys, buf, usage); } static void @@ -105,8 +103,7 @@ pass_flush_frontbuffer(struct pipe_screen *screen, struct pipe_surface *surf, void *context_private) { - screen->winsys->flush_frontbuffer(screen->winsys, - surf, context_private); + screen->winsys->flush_frontbuffer(screen->winsys, surf, context_private); } static void @@ -114,8 +111,7 @@ pass_fence_reference(struct pipe_screen *screen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence) { - screen->winsys->fence_reference(screen->winsys, - ptr, fence); + screen->winsys->fence_reference(screen->winsys, ptr, fence); } static int @@ -123,8 +119,7 @@ pass_fence_signalled(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flag) { - return screen->winsys->fence_signalled(screen->winsys, - fence, flag); + return screen->winsys->fence_signalled(screen->winsys, fence, flag); } static int @@ -132,11 +127,11 @@ pass_fence_finish(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flag) { - return screen->winsys->fence_finish(screen->winsys, - fence, flag); + return screen->winsys->fence_finish(screen->winsys, fence, flag); } -void u_simple_screen_init(struct pipe_screen *screen) +void +u_simple_screen_init(struct pipe_screen *screen) { screen->buffer_create = pass_buffer_create; screen->user_buffer_create = pass_user_buffer_create; @@ -151,7 +146,8 @@ void u_simple_screen_init(struct pipe_screen *screen) screen->fence_finish = pass_fence_finish; } -const char* u_simple_screen_winsys_name(struct pipe_screen *screen) +const char * +u_simple_screen_winsys_name(struct pipe_screen *screen) { return screen->winsys->get_name(screen->winsys); } diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index e519c354d2..0d706f9449 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -34,17 +34,9 @@ #include "pipe/p_context.h" -#include "util/u_debug.h" -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" #include "pipe/p_shader_tokens.h" - -#include "util/u_memory.h" #include "util/u_simple_shaders.h" - -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_ureg.h" @@ -58,93 +50,29 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, const uint *semantic_indexes) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_VERTEX; - uint ti, i; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); + struct ureg_program *ureg; + uint i; - ti = 3; + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; - /* declare inputs */ for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); + struct ureg_src src; + struct ureg_dst dst; + + src = ureg_DECL_vs_input( ureg, i ); + + dst = ureg_DECL_output( ureg, + semantic_names[i], + semantic_indexes[i]); + + ureg_MOV( ureg, dst, src ); } - /* declare outputs */ - for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - } + ureg_END( ureg ); - /* emit MOV instructions */ - for (i = 0; i < num_attribs; i++) { - /* MOVE out[i], in[i]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = i; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = i; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - } - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_vs_state(pipe, &shader); + return ureg_create_shader_and_destroy( ureg, pipe ); } @@ -152,108 +80,46 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, /** * Make simple fragment texture shader: - * TEX OUT[0], IN[0], SAMP[0], 2D; + * IMM {0,0,0,1} // (if writemask != 0xf) + * MOV OUT[0], IMM[0] // (if writemask != 0xf) + * TEX OUT[0].writemask, IN[0], SAMP[0], 2D; * END; */ void * -util_make_fragment_tex_shader(struct pipe_context *pipe) +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned writemask ) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out; - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); - ti = 3; + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); - /* declare TEX[0] input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - /* XXX this could be linear... */ - decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); - /* declare color[0] output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); + ureg_TEX( ureg, out, TGSI_TEXTURE_2D, tex, sampler ); + ureg_END( ureg ); - /* declare sampler */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* TEX instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_TEX; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 2; - inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; - inst.FullSrcRegisters[1].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_fs_state(pipe, &shader); + return ureg_create_shader_and_destroy( ureg, pipe ); } - +void * +util_make_fragment_tex_shader(struct pipe_context *pipe ) +{ + return util_make_fragment_tex_shader_writemask( pipe, + TGSI_WRITEMASK_XYZW ); +} @@ -263,87 +129,23 @@ util_make_fragment_tex_shader(struct pipe_context *pipe) void * util_make_fragment_passthrough_shader(struct pipe_context *pipe) { - struct pipe_shader_state shader; - struct tgsi_token tokens[40]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - - /* MOVE out[0], in[0]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst; - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; - assert(ti < Elements(tokens)); + src = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_COLOR, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif + dst = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ); - shader.tokens = tokens; + ureg_MOV( ureg, dst, src ); + ureg_END( ureg ); - return pipe->create_fs_state(pipe, &shader); + return ureg_create_shader_and_destroy( ureg, pipe ); } diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h index 6f8d96af9b..d2e80d6eb4 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/src/gallium/auxiliary/util/u_simple_shaders.h @@ -50,6 +50,10 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, extern void * +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned writemask ); + +extern void * util_make_fragment_tex_shader(struct pipe_context *pipe); diff --git a/src/gallium/auxiliary/util/u_stream_stdc.c b/src/gallium/auxiliary/util/u_stream_stdc.c index d8f648e5dd..5cd05b2904 100644 --- a/src/gallium/auxiliary/util/u_stream_stdc.c +++ b/src/gallium/auxiliary/util/u_stream_stdc.c @@ -32,7 +32,7 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU) #include <stdio.h> diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h index a5b73cfc20..ce84ed7ad0 100644 --- a/src/gallium/auxiliary/util/u_surface.h +++ b/src/gallium/auxiliary/util/u_surface.h @@ -37,6 +37,23 @@ struct pipe_texture; struct pipe_surface; +/** + * Are s1 and s2 the same surface? + * Surfaces are basically views into textures so check if the two surfaces + * name the same part of the same texture. + */ +static INLINE boolean +util_same_surface(const struct pipe_surface *s1, const struct pipe_surface *s2) +{ + return (s1->texture == s2->texture && + s1->face == s2->face && + s1->level == s2->level && + s1->zslice == s2->zslice); +} + + + + extern boolean util_create_rgba_surface(struct pipe_screen *screen, uint width, uint height, diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index a0c8ed88f7..0d6489c26e 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -62,7 +62,7 @@ pipe_get_tile_raw(struct pipe_transfer *pt, if(!src) return; - pipe_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + util_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); screen->transfer_unmap(screen, pt); } @@ -90,7 +90,7 @@ pipe_put_tile_raw(struct pipe_transfer *pt, if(!dst) return; - pipe_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); + util_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); screen->transfer_unmap(screen, pt); } @@ -153,7 +153,7 @@ a8r8g8b8_put_tile_rgba(unsigned *dst, } -/*** PIPE_FORMAT_A8R8G8B8_UNORM ***/ +/*** PIPE_FORMAT_X8R8G8B8_UNORM ***/ static void x8r8g8b8_get_tile_rgba(const unsigned *src, @@ -170,7 +170,7 @@ x8r8g8b8_get_tile_rgba(const unsigned *src, pRow[0] = ubyte_to_float((pixel >> 16) & 0xff); pRow[1] = ubyte_to_float((pixel >> 8) & 0xff); pRow[2] = ubyte_to_float((pixel >> 0) & 0xff); - pRow[3] = ubyte_to_float(0xff); + pRow[3] = 1.0F; } p += dst_stride; } @@ -394,6 +394,52 @@ r5g6b5_put_tile_rgba(ushort *dst, +/*** PIPE_FORMAT_R8G8B8_UNORM ***/ + +static void +r8g8b8_get_tile_rgba(const ubyte *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = ubyte_to_float(src[0]); + pRow[1] = ubyte_to_float(src[1]); + pRow[2] = ubyte_to_float(src[2]); + pRow[3] = 1.0f; + src += 3; + } + p += dst_stride; + } +} + + +static void +r8g8b8_put_tile_rgba(ubyte *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + dst[0] = float_to_ubyte(pRow[0]); + dst[1] = float_to_ubyte(pRow[1]); + dst[2] = float_to_ubyte(pRow[2]); + dst += 3; + } + p += src_stride; + } +} + + + /*** PIPE_FORMAT_Z16_UNORM ***/ /** @@ -596,6 +642,184 @@ r16g16b16a16_put_tile_rgba(short *dst, } +/*** PIPE_FORMAT_R8G8B8A8_SRGB ***/ + +/** + * Convert an 8-bit sRGB value from non-linear space to a + * linear RGB value in [0, 1]. + * Implemented with a 256-entry lookup table. + */ +static INLINE float +srgb_to_linear(ubyte cs8) +{ + static float table[256]; + static boolean tableReady = FALSE; + if (!tableReady) { + /* compute lookup table now */ + uint i; + for (i = 0; i < 256; i++) { + const float cs = ubyte_to_float(i); + if (cs <= 0.04045) { + table[i] = cs / 12.92f; + } + else { + table[i] = (float) powf((cs + 0.055) / 1.055, 2.4); + } + } + tableReady = TRUE; + } + return table[cs8]; +} + + +/** + * Convert linear float in [0,1] to an srgb ubyte value in [0,255]. + * XXX this hasn't been tested (render to srgb surface). + * XXX this needs optimization. + */ +static INLINE ubyte +linear_to_srgb(float cl) +{ + if (cl >= 1.0F) + return 255; + else if (cl >= 0.0031308F) + return float_to_ubyte(1.055F * powf(cl, 0.41666F) - 0.055F); + else if (cl > 0.0F) + return float_to_ubyte(12.92F * cl); + else + return 0.0; +} + + +static void +a8r8g8b8_srgb_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + const unsigned pixel = *src++; + pRow[0] = srgb_to_linear((pixel >> 16) & 0xff); + pRow[1] = srgb_to_linear((pixel >> 8) & 0xff); + pRow[2] = srgb_to_linear((pixel >> 0) & 0xff); + pRow[3] = ubyte_to_float((pixel >> 24) & 0xff); + } + p += dst_stride; + } +} + +static void +a8r8g8b8_srgb_put_tile_rgba(unsigned *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + unsigned r, g, b, a; + r = linear_to_srgb(pRow[0]); + g = linear_to_srgb(pRow[1]); + b = linear_to_srgb(pRow[2]); + a = float_to_ubyte(pRow[3]); + *dst++ = (a << 24) | (r << 16) | (g << 8) | b; + } + p += src_stride; + } +} + + +/*** PIPE_FORMAT_A8L8_SRGB ***/ + +static void +a8l8_srgb_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + ushort p = *src++; + pRow[0] = + pRow[1] = + pRow[2] = srgb_to_linear(p & 0xff); + pRow[3] = ubyte_to_float(p >> 8); + } + p += dst_stride; + } +} + +static void +a8l8_srgb_put_tile_rgba(ushort *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + unsigned r, a; + r = linear_to_srgb(pRow[0]); + a = float_to_ubyte(pRow[3]); + *dst++ = (a << 8) | r; + } + p += src_stride; + } +} + + +/*** PIPE_FORMAT_L8_SRGB ***/ + +static void +l8_srgb_get_tile_rgba(const ubyte *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, src++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = srgb_to_linear(*src); + pRow[3] = 1.0; + } + p += dst_stride; + } +} + +static void +l8_srgb_put_tile_rgba(ubyte *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + unsigned r; + r = linear_to_srgb(pRow[0]); + *dst++ = (ubyte) r; + } + p += src_stride; + } +} + /*** PIPE_FORMAT_I8_UNORM ***/ @@ -928,6 +1152,9 @@ pipe_tile_raw_to_rgba(enum pipe_format format, case PIPE_FORMAT_R5G6B5_UNORM: r5g6b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); break; + case PIPE_FORMAT_R8G8B8_UNORM: + r8g8b8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride); + break; case PIPE_FORMAT_L8_UNORM: l8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride); break; @@ -946,6 +1173,15 @@ pipe_tile_raw_to_rgba(enum pipe_format format, case PIPE_FORMAT_R16G16B16A16_SNORM: r16g16b16a16_get_tile_rgba((short *) src, w, h, dst, dst_stride); break; + case PIPE_FORMAT_A8R8G8B8_SRGB: + a8r8g8b8_srgb_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_A8L8_SRGB: + a8l8_srgb_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_L8_SRGB: + l8_srgb_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride); + break; case PIPE_FORMAT_Z16_UNORM: z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); break; @@ -1035,6 +1271,9 @@ pipe_put_tile_rgba(struct pipe_transfer *pt, case PIPE_FORMAT_R5G6B5_UNORM: r5g6b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride); break; + case PIPE_FORMAT_R8G8B8_UNORM: + r8g8b8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride); + break; case PIPE_FORMAT_R8G8B8A8_UNORM: assert(0); break; @@ -1059,6 +1298,15 @@ pipe_put_tile_rgba(struct pipe_transfer *pt, case PIPE_FORMAT_R16G16B16A16_SNORM: r16g16b16a16_put_tile_rgba((short *) packed, w, h, p, src_stride); break; + case PIPE_FORMAT_A8R8G8B8_SRGB: + a8r8g8b8_srgb_put_tile_rgba((unsigned *) packed, w, h, p, src_stride); + break; + case PIPE_FORMAT_A8L8_SRGB: + a8l8_srgb_put_tile_rgba((ushort *) packed, w, h, p, src_stride); + break; + case PIPE_FORMAT_L8_SRGB: + l8_srgb_put_tile_rgba((ubyte *) packed, w, h, p, src_stride); + break; case PIPE_FORMAT_Z16_UNORM: /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/ break; diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c index 5268cbf79c..b958a98635 100644 --- a/src/gallium/auxiliary/util/u_time.c +++ b/src/gallium/auxiliary/util/u_time.c @@ -35,7 +35,7 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) #include <sys/time.h> #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) #include <windows.h> @@ -77,7 +77,7 @@ util_time_get_frequency(void) void util_time_get(struct util_time *t) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) gettimeofday(&t->tv, NULL); #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) LONGLONG temp; @@ -102,7 +102,7 @@ util_time_add(const struct util_time *t1, int64_t usecs, struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) t2->tv.tv_sec = t1->tv.tv_sec + usecs / 1000000; t2->tv.tv_usec = t1->tv.tv_usec + usecs % 1000000; #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) @@ -124,7 +124,7 @@ int64_t util_time_diff(const struct util_time *t1, const struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) return (t2->tv.tv_usec - t1->tv.tv_usec) + (t2->tv.tv_sec - t1->tv.tv_sec)*1000000; #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) @@ -144,7 +144,7 @@ util_time_micros( void ) util_time_get(&t1); -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 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(); @@ -166,7 +166,7 @@ static INLINE int util_time_compare(const struct util_time *t1, const struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) if (t1->tv.tv_sec < t2->tv.tv_sec) return -1; else if(t1->tv.tv_sec > t2->tv.tv_sec) diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h index 6bca6077a2..a6189a247b 100644 --- a/src/gallium/auxiliary/util/u_time.h +++ b/src/gallium/auxiliary/util/u_time.h @@ -38,11 +38,16 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) #include <time.h> /* timeval */ #include <unistd.h> /* usleep */ #endif +#if defined(PIPE_OS_HAIKU) +#include <sys/time.h> /* timeval */ +#include <unistd.h> +#endif + #include "pipe/p_compiler.h" @@ -58,7 +63,7 @@ extern "C" { */ struct util_time { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) struct timeval tv; #else int64_t counter; @@ -89,7 +94,7 @@ util_time_timeout(const struct util_time *start, const struct util_time *end, const struct util_time *curr); -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) #define util_time_sleep usleep #else void diff --git a/src/gallium/auxiliary/util/u_timed_winsys.c b/src/gallium/auxiliary/util/u_timed_winsys.c index 77b2a3a1c8..178acdca4d 100644 --- a/src/gallium/auxiliary/util/u_timed_winsys.c +++ b/src/gallium/auxiliary/util/u_timed_winsys.c @@ -212,13 +212,14 @@ timed_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_winsys *backend = timed_winsys(winsys)->backend; uint64_t start = time_start(); struct pipe_buffer *ret = backend->surface_buffer_create( backend, width, height, - format, usage, stride ); + format, usage, tex_usage, stride ); time_finish(winsys, start, 7, __FUNCTION__); diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c index c90425f3e5..eb635c9f14 100644 --- a/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/src/gallium/auxiliary/util/u_upload_mgr.c @@ -123,21 +123,25 @@ static enum pipe_error u_upload_alloc_buffer( struct u_upload_mgr *upload, unsigned min_size ) { + unsigned size; + /* Release old buffer, if present: */ u_upload_flush( upload ); /* Allocate a new one: */ - upload->size = align(MAX2(upload->default_size, min_size), 4096); + size = align(MAX2(upload->default_size, min_size), 4096); upload->buffer = pipe_buffer_create( upload->screen, upload->alignment, upload->usage | PIPE_BUFFER_USAGE_CPU_WRITE, - upload->size ); + size ); if (upload->buffer == NULL) goto fail; + upload->size = size; + upload->offset = 0; return 0; |