diff options
Diffstat (limited to 'src/gallium/auxiliary/util')
-rw-r--r-- | src/gallium/auxiliary/util/u_blit.c | 82 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_debug.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_math.h | 75 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_simple_screen.c | 3 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_surface.h | 17 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_timed_winsys.c | 3 |
6 files changed, 141 insertions, 41 deletions
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 414cf91025..cda6dbd46d 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" @@ -155,7 +156,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 +178,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,9 +264,38 @@ 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 @@ -285,10 +318,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 +367,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)); diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c index a5ca0b72bd..96d400c839 100644 --- a/src/gallium/auxiliary/util/u_debug.c +++ b/src/gallium/auxiliary/util/u_debug.c @@ -143,11 +143,9 @@ void _debug_vprintf(const char *format, va_list ap) #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) /* TODO */ #else /* !PIPE_SUBSYSTEM_WINDOWS */ -#ifdef DEBUG fflush(stdout); vfprintf(stderr, format, ap); #endif -#endif } diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index e5003af01d..57410e78b0 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) { @@ -274,7 +284,6 @@ util_fast_pow(float x, float y) } - /** * Floor(x), returned as int. */ @@ -284,8 +293,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; @@ -305,9 +314,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,7 +349,7 @@ 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; @@ -351,7 +360,7 @@ unsigned ffs( unsigned u ) { unsigned i; - if( u == 0 ) { + if (u == 0) { return 0; } @@ -378,7 +387,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) { @@ -409,7 +421,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) ) @@ -422,6 +450,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_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c index 8114b53cd0..f01296b40f 100644 --- a/src/gallium/auxiliary/util/u_simple_screen.c +++ b/src/gallium/auxiliary/util/u_simple_screen.c @@ -65,12 +65,13 @@ 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); + format, usage, tex_usage, stride); buffer->screen = screen; 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_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__); |