parent
b6f2d8f531
commit
57646ceb4e
@ -0,0 +1,322 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2007 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/* Authors: Zack Rusin <zackr@vmware.com>
|
||||
*/ |
||||
|
||||
#include "util/u_debug.h" |
||||
|
||||
#include "util/u_memory.h" |
||||
|
||||
#include "cso_cache.h" |
||||
#include "cso_hash.h" |
||||
|
||||
|
||||
struct cso_cache { |
||||
struct cso_hash *hashes[CSO_CACHE_MAX]; |
||||
int max_size; |
||||
|
||||
cso_sanitize_callback sanitize_cb; |
||||
void *sanitize_data; |
||||
}; |
||||
|
||||
#if 1 |
||||
static unsigned hash_key(const void *key, unsigned key_size) |
||||
{ |
||||
unsigned *ikey = (unsigned *)key; |
||||
unsigned hash = 0, i; |
||||
|
||||
assert(key_size % 4 == 0); |
||||
|
||||
/* I'm sure this can be improved on:
|
||||
*/ |
||||
for (i = 0; i < key_size/4; i++) |
||||
hash ^= ikey[i]; |
||||
|
||||
return hash; |
||||
} |
||||
#else |
||||
static unsigned hash_key(const unsigned char *p, int n) |
||||
{ |
||||
unsigned h = 0; |
||||
unsigned g; |
||||
|
||||
while (n--) { |
||||
h = (h << 4) + *p++; |
||||
if ((g = (h & 0xf0000000)) != 0) |
||||
h ^= g >> 23; |
||||
h &= ~g; |
||||
} |
||||
return h; |
||||
} |
||||
#endif |
||||
|
||||
unsigned cso_construct_key(void *item, int item_size) |
||||
{ |
||||
return hash_key((item), item_size); |
||||
} |
||||
|
||||
static INLINE struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type) |
||||
{ |
||||
struct cso_hash *hash; |
||||
hash = sc->hashes[type]; |
||||
return hash; |
||||
} |
||||
|
||||
static void delete_blend_state(void *state, void *data) |
||||
{ |
||||
struct cso_blend *cso = (struct cso_blend *)state; |
||||
if (cso->delete_state) |
||||
cso->delete_state(cso->context, cso->data); |
||||
FREE(state); |
||||
} |
||||
|
||||
static void delete_depth_stencil_state(void *state, void *data) |
||||
{ |
||||
struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state; |
||||
if (cso->delete_state) |
||||
cso->delete_state(cso->context, cso->data); |
||||
FREE(state); |
||||
} |
||||
|
||||
static void delete_sampler_state(void *state, void *data) |
||||
{ |
||||
struct cso_sampler *cso = (struct cso_sampler *)state; |
||||
if (cso->delete_state) |
||||
cso->delete_state(cso->context, cso->data); |
||||
FREE(state); |
||||
} |
||||
|
||||
static void delete_rasterizer_state(void *state, void *data) |
||||
{ |
||||
struct cso_rasterizer *cso = (struct cso_rasterizer *)state; |
||||
if (cso->delete_state) |
||||
cso->delete_state(cso->context, cso->data); |
||||
FREE(state); |
||||
} |
||||
|
||||
static void delete_velements(void *state, void *data) |
||||
{ |
||||
struct cso_velements *cso = (struct cso_velements *)state; |
||||
if (cso->delete_state) |
||||
cso->delete_state(cso->context, cso->data); |
||||
FREE(state); |
||||
} |
||||
|
||||
static INLINE void delete_cso(void *state, enum cso_cache_type type) |
||||
{ |
||||
switch (type) { |
||||
case CSO_BLEND: |
||||
delete_blend_state(state, 0); |
||||
break; |
||||
case CSO_SAMPLER: |
||||
delete_sampler_state(state, 0); |
||||
break; |
||||
case CSO_DEPTH_STENCIL_ALPHA: |
||||
delete_depth_stencil_state(state, 0); |
||||
break; |
||||
case CSO_RASTERIZER: |
||||
delete_rasterizer_state(state, 0); |
||||
break; |
||||
case CSO_VELEMENTS: |
||||
delete_velements(state, 0); |
||||
break; |
||||
default: |
||||
assert(0); |
||||
FREE(state); |
||||
} |
||||
} |
||||
|
||||
|
||||
static INLINE void sanitize_hash(struct cso_cache *sc, |
||||
struct cso_hash *hash, |
||||
enum cso_cache_type type, |
||||
int max_size) |
||||
{ |
||||
if (sc->sanitize_cb) |
||||
sc->sanitize_cb(hash, type, max_size, sc->sanitize_data); |
||||
} |
||||
|
||||
|
||||
static INLINE void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type, |
||||
int max_size, void *user_data) |
||||
{ |
||||
/* if we're approach the maximum size, remove fourth of the entries
|
||||
* otherwise every subsequent call will go through the same */ |
||||
int hash_size = cso_hash_size(hash); |
||||
int max_entries = (max_size > hash_size) ? max_size : hash_size; |
||||
int to_remove = (max_size < max_entries) * max_entries/4; |
||||
if (hash_size > max_size) |
||||
to_remove += hash_size - max_size; |
||||
while (to_remove) { |
||||
/*remove elements until we're good */ |
||||
/*fixme: currently we pick the nodes to remove at random*/ |
||||
struct cso_hash_iter iter = cso_hash_first_node(hash); |
||||
void *cso = cso_hash_take(hash, cso_hash_iter_key(iter)); |
||||
delete_cso(cso, type); |
||||
--to_remove; |
||||
} |
||||
} |
||||
|
||||
struct cso_hash_iter |
||||
cso_insert_state(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type, |
||||
void *state) |
||||
{ |
||||
struct cso_hash *hash = _cso_hash_for_type(sc, type); |
||||
sanitize_hash(sc, hash, type, sc->max_size); |
||||
|
||||
return cso_hash_insert(hash, hash_key, state); |
||||
} |
||||
|
||||
struct cso_hash_iter |
||||
cso_find_state(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type) |
||||
{ |
||||
struct cso_hash *hash = _cso_hash_for_type(sc, type); |
||||
|
||||
return cso_hash_find(hash, hash_key); |
||||
} |
||||
|
||||
|
||||
void *cso_hash_find_data_from_template( struct cso_hash *hash, |
||||
unsigned hash_key,
|
||||
void *templ, |
||||
int size ) |
||||
{ |
||||
struct cso_hash_iter iter = cso_hash_find(hash, hash_key); |
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
void *iter_data = cso_hash_iter_data(iter); |
||||
if (!memcmp(iter_data, templ, size)) { |
||||
/* We found a match
|
||||
*/ |
||||
return iter_data; |
||||
} |
||||
iter = cso_hash_iter_next(iter); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
|
||||
struct cso_hash_iter cso_find_state_template(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type, |
||||
void *templ, unsigned size) |
||||
{ |
||||
struct cso_hash_iter iter = cso_find_state(sc, hash_key, type); |
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
void *iter_data = cso_hash_iter_data(iter); |
||||
if (!memcmp(iter_data, templ, size)) |
||||
return iter; |
||||
iter = cso_hash_iter_next(iter); |
||||
} |
||||
return iter; |
||||
} |
||||
|
||||
void * cso_take_state(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type) |
||||
{ |
||||
struct cso_hash *hash = _cso_hash_for_type(sc, type); |
||||
return cso_hash_take(hash, hash_key); |
||||
} |
||||
|
||||
struct cso_cache *cso_cache_create(void) |
||||
{ |
||||
struct cso_cache *sc = MALLOC_STRUCT(cso_cache); |
||||
int i; |
||||
if (sc == NULL) |
||||
return NULL; |
||||
|
||||
sc->max_size = 4096; |
||||
for (i = 0; i < CSO_CACHE_MAX; i++) |
||||
sc->hashes[i] = cso_hash_create(); |
||||
|
||||
sc->sanitize_cb = sanitize_cb; |
||||
sc->sanitize_data = 0; |
||||
|
||||
return sc; |
||||
} |
||||
|
||||
void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, |
||||
cso_state_callback func, void *user_data) |
||||
{ |
||||
struct cso_hash *hash = _cso_hash_for_type(sc, type); |
||||
struct cso_hash_iter iter; |
||||
|
||||
iter = cso_hash_first_node(hash); |
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
void *state = cso_hash_iter_data(iter); |
||||
iter = cso_hash_iter_next(iter); |
||||
if (state) { |
||||
func(state, user_data); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void cso_cache_delete(struct cso_cache *sc) |
||||
{ |
||||
int i; |
||||
assert(sc); |
||||
|
||||
if (!sc) |
||||
return; |
||||
|
||||
/* delete driver data */ |
||||
cso_for_each_state(sc, CSO_BLEND, delete_blend_state, 0); |
||||
cso_for_each_state(sc, CSO_DEPTH_STENCIL_ALPHA, delete_depth_stencil_state, 0); |
||||
cso_for_each_state(sc, CSO_RASTERIZER, delete_rasterizer_state, 0); |
||||
cso_for_each_state(sc, CSO_SAMPLER, delete_sampler_state, 0); |
||||
cso_for_each_state(sc, CSO_VELEMENTS, delete_velements, 0); |
||||
|
||||
for (i = 0; i < CSO_CACHE_MAX; i++) |
||||
cso_hash_delete(sc->hashes[i]); |
||||
|
||||
FREE(sc); |
||||
} |
||||
|
||||
void cso_set_maximum_cache_size(struct cso_cache *sc, int number) |
||||
{ |
||||
int i; |
||||
|
||||
sc->max_size = number; |
||||
|
||||
for (i = 0; i < CSO_CACHE_MAX; i++) |
||||
sanitize_hash(sc, sc->hashes[i], i, sc->max_size); |
||||
} |
||||
|
||||
int cso_maximum_cache_size(const struct cso_cache *sc) |
||||
{ |
||||
return sc->max_size; |
||||
} |
||||
|
||||
void cso_cache_set_sanitize_callback(struct cso_cache *sc, |
||||
cso_sanitize_callback cb, |
||||
void *user_data) |
||||
{ |
||||
sc->sanitize_cb = cb; |
||||
sc->sanitize_data = user_data; |
||||
} |
||||
|
@ -0,0 +1,175 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2007-2008 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 |
||||
* Constant State Object (CSO) cache. |
||||
* |
||||
* The basic idea is that the states are created via the |
||||
* create_state/bind_state/delete_state semantics. The driver is expected to |
||||
* perform as much of the Gallium state translation to whatever its internal |
||||
* representation is during the create call. Gallium then has a caching |
||||
* mechanism where it stores the created states. When the pipeline needs an |
||||
* actual state change, a bind call is issued. In the bind call the driver |
||||
* gets its already translated representation. |
||||
* |
||||
* Those semantics mean that the driver doesn't do the repeated translations |
||||
* of states on every frame, but only once, when a new state is actually |
||||
* created. |
||||
* |
||||
* Even on hardware that doesn't do any kind of state cache, it makes the |
||||
* driver look a lot neater, plus it avoids all the redundant state |
||||
* translations on every frame. |
||||
* |
||||
* Currently our constant state objects are: |
||||
* - alpha test |
||||
* - blend |
||||
* - depth stencil |
||||
* - fragment shader |
||||
* - rasterizer (old setup) |
||||
* - sampler |
||||
* - vertex shader |
||||
* - vertex elements |
||||
* |
||||
* Things that are not constant state objects include: |
||||
* - blend_color |
||||
* - clip_state |
||||
* - clear_color_state |
||||
* - constant_buffer |
||||
* - feedback_state |
||||
* - framebuffer_state |
||||
* - polygon_stipple |
||||
* - scissor_state |
||||
* - texture_state |
||||
* - viewport_state |
||||
* |
||||
* @author Zack Rusin <zackr@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef CSO_CACHE_H |
||||
#define CSO_CACHE_H |
||||
|
||||
#include "pipe/p_context.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
/* cso_hash.h is necessary for cso_hash_iter, as MSVC requires structures
|
||||
* returned by value to be fully defined */ |
||||
#include "cso_hash.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
enum cso_cache_type { |
||||
CSO_RASTERIZER, |
||||
CSO_BLEND, |
||||
CSO_DEPTH_STENCIL_ALPHA, |
||||
CSO_SAMPLER, |
||||
CSO_VELEMENTS, |
||||
CSO_CACHE_MAX, |
||||
}; |
||||
|
||||
typedef void (*cso_state_callback)(void *ctx, void *obj); |
||||
|
||||
typedef void (*cso_sanitize_callback)(struct cso_hash *hash, |
||||
enum cso_cache_type type, |
||||
int max_size, |
||||
void *user_data); |
||||
|
||||
struct cso_cache; |
||||
|
||||
struct cso_blend { |
||||
struct pipe_blend_state state; |
||||
void *data; |
||||
cso_state_callback delete_state; |
||||
struct pipe_context *context; |
||||
}; |
||||
|
||||
struct cso_depth_stencil_alpha { |
||||
struct pipe_depth_stencil_alpha_state state; |
||||
void *data; |
||||
cso_state_callback delete_state; |
||||
struct pipe_context *context; |
||||
}; |
||||
|
||||
struct cso_rasterizer { |
||||
struct pipe_rasterizer_state state; |
||||
void *data; |
||||
cso_state_callback delete_state; |
||||
struct pipe_context *context; |
||||
}; |
||||
|
||||
struct cso_sampler { |
||||
struct pipe_sampler_state state; |
||||
void *data; |
||||
cso_state_callback delete_state; |
||||
struct pipe_context *context; |
||||
}; |
||||
|
||||
struct cso_velems_state { |
||||
unsigned count; |
||||
struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS]; |
||||
}; |
||||
|
||||
struct cso_velements { |
||||
struct cso_velems_state state; |
||||
void *data; |
||||
cso_state_callback delete_state; |
||||
struct pipe_context *context; |
||||
}; |
||||
|
||||
unsigned cso_construct_key(void *item, int item_size); |
||||
|
||||
struct cso_cache *cso_cache_create(void); |
||||
void cso_cache_delete(struct cso_cache *sc); |
||||
|
||||
void cso_cache_set_sanitize_callback(struct cso_cache *sc, |
||||
cso_sanitize_callback cb, |
||||
void *user_data); |
||||
|
||||
struct cso_hash_iter cso_insert_state(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type, |
||||
void *state); |
||||
struct cso_hash_iter cso_find_state(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type); |
||||
struct cso_hash_iter cso_find_state_template(struct cso_cache *sc, |
||||
unsigned hash_key, enum cso_cache_type type, |
||||
void *templ, unsigned size); |
||||
void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, |
||||
cso_state_callback func, void *user_data); |
||||
void * cso_take_state(struct cso_cache *sc, unsigned hash_key, |
||||
enum cso_cache_type type); |
||||
|
||||
void cso_set_maximum_cache_size(struct cso_cache *sc, int number); |
||||
int cso_maximum_cache_size(const struct cso_cache *sc); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,562 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 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_debug.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_prim.h" |
||||
#include "cso_cache/cso_hash.h" |
||||
#include "tgsi_sanity.h" |
||||
#include "tgsi_info.h" |
||||
#include "tgsi_iterate.h" |
||||
|
||||
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(print_sanity, "TGSI_PRINT_SANITY", FALSE) |
||||
|
||||
|
||||
typedef struct { |
||||
uint file : 28; |
||||
/* max 2 dimensions */ |
||||
uint dimensions : 4; |
||||
uint indices[2]; |
||||
} scan_register; |
||||
|
||||
struct sanity_check_ctx |
||||
{ |
||||
struct tgsi_iterate_context iter; |
||||
struct cso_hash *regs_decl; |
||||
struct cso_hash *regs_used; |
||||
struct cso_hash *regs_ind_used; |
||||
|
||||
uint num_imms; |
||||
uint num_instructions; |
||||
uint index_of_END; |
||||
|
||||
uint errors; |
||||
uint warnings; |
||||
uint implied_array_size; |
||||
|
||||
boolean print; |
||||
}; |
||||
|
||||
static INLINE unsigned |
||||
scan_register_key(const scan_register *reg) |
||||
{ |
||||
unsigned key = reg->file; |
||||
key |= (reg->indices[0] << 4); |
||||
key |= (reg->indices[1] << 18); |
||||
|
||||
return key; |
||||
} |
||||
|
||||
static void |
||||
fill_scan_register1d(scan_register *reg, |
||||
uint file, uint index) |
||||
{ |
||||
reg->file = file; |
||||
reg->dimensions = 1; |
||||
reg->indices[0] = index; |
||||
reg->indices[1] = 0; |
||||
} |
||||
|
||||
static void |
||||
fill_scan_register2d(scan_register *reg, |
||||
uint file, uint index1, uint index2) |
||||
{ |
||||
reg->file = file; |
||||
reg->dimensions = 2; |
||||
reg->indices[0] = index1; |
||||
reg->indices[1] = index2; |
||||
} |
||||
|
||||
static void |
||||
scan_register_dst(scan_register *reg, |
||||
struct tgsi_full_dst_register *dst) |
||||
{ |
||||
if (dst->Register.Dimension) { |
||||
/*FIXME: right now we don't support indirect
|
||||
* multidimensional addressing */ |
||||
fill_scan_register2d(reg, |
||||
dst->Register.File, |
||||
dst->Register.Index, |
||||
dst->Dimension.Index); |
||||
} else { |
||||
fill_scan_register1d(reg, |
||||
dst->Register.File, |
||||
dst->Register.Index); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
scan_register_src(scan_register *reg, |
||||
struct tgsi_full_src_register *src) |
||||
{ |
||||
if (src->Register.Dimension) { |
||||
/*FIXME: right now we don't support indirect
|
||||
* multidimensional addressing */ |
||||
fill_scan_register2d(reg, |
||||
src->Register.File, |
||||
src->Register.Index, |
||||
src->Dimension.Index); |
||||
} else { |
||||
fill_scan_register1d(reg, |
||||
src->Register.File, |
||||
src->Register.Index); |
||||
} |
||||
} |
||||
|
||||
static scan_register * |
||||
create_scan_register_src(struct tgsi_full_src_register *src) |
||||
{ |
||||
scan_register *reg = MALLOC(sizeof(scan_register)); |
||||
scan_register_src(reg, src); |
||||
|
||||
return reg; |
||||
} |
||||
|
||||
static scan_register * |
||||
create_scan_register_dst(struct tgsi_full_dst_register *dst) |
||||
{ |
||||
scan_register *reg = MALLOC(sizeof(scan_register)); |
||||
scan_register_dst(reg, dst); |
||||
|
||||
return reg; |
||||
} |
||||
|
||||
static void |
||||
report_error( |
||||
struct sanity_check_ctx *ctx, |
||||
const char *format, |
||||
... ) |
||||
{ |
||||
va_list args; |
||||
|
||||
if (!ctx->print) |
||||
return; |
||||
|
||||
debug_printf( "Error : " ); |
||||
va_start( args, format ); |
||||
_debug_vprintf( format, args ); |
||||
va_end( args ); |
||||
debug_printf( "\n" ); |
||||
ctx->errors++; |
||||
} |
||||
|
||||
static void |
||||
report_warning( |
||||
struct sanity_check_ctx *ctx, |
||||
const char *format, |
||||
... ) |
||||
{ |
||||
va_list args; |
||||
|
||||
if (!ctx->print) |
||||
return; |
||||
|
||||
debug_printf( "Warning: " ); |
||||
va_start( args, format ); |
||||
_debug_vprintf( format, args ); |
||||
va_end( args ); |
||||
debug_printf( "\n" ); |
||||
ctx->warnings++; |
||||
} |
||||
|
||||
static boolean |
||||
check_file_name( |
||||
struct sanity_check_ctx *ctx, |
||||
uint file ) |
||||
{ |
||||
if (file <= TGSI_FILE_NULL || file >= TGSI_FILE_COUNT) { |
||||
report_error( ctx, "(%u): Invalid register file name", file ); |
||||
return FALSE; |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
static boolean |
||||
is_register_declared( |
||||
struct sanity_check_ctx *ctx, |
||||
const scan_register *reg) |
||||
{ |
||||
void *data = cso_hash_find_data_from_template( |
||||
ctx->regs_decl, scan_register_key(reg), |
||||
(void*)reg, sizeof(scan_register)); |
||||
return data ? TRUE : FALSE; |
||||
} |
||||
|
||||
static boolean |
||||
is_any_register_declared( |
||||
struct sanity_check_ctx *ctx, |
||||
uint file ) |
||||
{ |
||||
struct cso_hash_iter iter = |
||||
cso_hash_first_node(ctx->regs_decl); |
||||
|
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
scan_register *reg = (scan_register *)cso_hash_iter_data(iter); |
||||
if (reg->file == file) |
||||
return TRUE; |
||||
iter = cso_hash_iter_next(iter); |
||||
} |
||||
|
||||
return FALSE; |
||||
} |
||||
|
||||
static boolean |
||||
is_register_used( |
||||
struct sanity_check_ctx *ctx, |
||||
scan_register *reg) |
||||
{ |
||||
void *data = cso_hash_find_data_from_template( |
||||
ctx->regs_used, scan_register_key(reg), |
||||
reg, sizeof(scan_register)); |
||||
return data ? TRUE : FALSE; |
||||
} |
||||
|
||||
|
||||
static boolean |
||||
is_ind_register_used( |
||||
struct sanity_check_ctx *ctx, |
||||
scan_register *reg) |
||||
{ |
||||
return cso_hash_contains(ctx->regs_ind_used, reg->file); |
||||
} |
||||
|
||||
static const char *file_names[TGSI_FILE_COUNT] = |
||||
{ |
||||
"NULL", |
||||
"CONST", |
||||
"IN", |
||||
"OUT", |
||||
"TEMP", |
||||
"SAMP", |
||||
"ADDR", |
||||
"IMM", |
||||
"PRED", |
||||
"SV", |
||||
"RES" |
||||
}; |
||||
|
||||
static boolean |
||||
check_register_usage( |
||||
struct sanity_check_ctx *ctx, |
||||
scan_register *reg, |
||||
const char *name, |
||||
boolean indirect_access ) |
||||
{ |
||||
if (!check_file_name( ctx, reg->file )) { |
||||
FREE(reg); |
||||
return FALSE; |
||||
} |
||||
|
||||
if (indirect_access) { |
||||
/* Note that 'index' is an offset relative to the value of the
|
||||
* address register. No range checking done here.*/ |
||||
reg->indices[0] = 0; |
||||
reg->indices[1] = 0; |
||||
if (!is_any_register_declared( ctx, reg->file )) |
||||
report_error( ctx, "%s: Undeclared %s register", file_names[reg->file], name ); |
||||
if (!is_ind_register_used(ctx, reg)) |
||||
cso_hash_insert(ctx->regs_ind_used, reg->file, reg); |
||||
else |
||||
FREE(reg); |
||||
} |
||||
else { |
||||
if (!is_register_declared( ctx, reg )) { |
||||
if (reg->dimensions == 2) { |
||||
report_error( ctx, "%s[%d][%d]: Undeclared %s register", file_names[reg->file], |
||||
reg->indices[0], reg->indices[1], name ); |
||||
} |
||||
else { |
||||
report_error( ctx, "%s[%d]: Undeclared %s register", file_names[reg->file], |
||||
reg->indices[0], name ); |
||||
} |
||||
} |
||||
if (!is_register_used( ctx, reg )) |
||||
cso_hash_insert(ctx->regs_used, scan_register_key(reg), reg); |
||||
else |
||||
FREE(reg); |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
static boolean |
||||
iter_instruction( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_instruction *inst ) |
||||
{ |
||||
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; |
||||
const struct tgsi_opcode_info *info; |
||||
uint i; |
||||
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_END) { |
||||
if (ctx->index_of_END != ~0) { |
||||
report_error( ctx, "Too many END instructions" ); |
||||
} |
||||
ctx->index_of_END = ctx->num_instructions; |
||||
} |
||||
|
||||
info = tgsi_get_opcode_info( inst->Instruction.Opcode ); |
||||
if (info == NULL) { |
||||
report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode ); |
||||
return TRUE; |
||||
} |
||||
|
||||
if (info->num_dst != inst->Instruction.NumDstRegs) { |
||||
report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst ); |
||||
} |
||||
if (info->num_src != inst->Instruction.NumSrcRegs) { |
||||
report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src ); |
||||
} |
||||
|
||||
/* Check destination and source registers' validity.
|
||||
* Mark the registers as used. |
||||
*/ |
||||
for (i = 0; i < inst->Instruction.NumDstRegs; i++) { |
||||
scan_register *reg = create_scan_register_dst(&inst->Dst[i]); |
||||
check_register_usage( |
||||
ctx, |
||||
reg, |
||||
"destination", |
||||
FALSE ); |
||||
if (!inst->Dst[i].Register.WriteMask) { |
||||
report_error(ctx, "Destination register has empty writemask"); |
||||
} |
||||
} |
||||
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { |
||||
scan_register *reg = create_scan_register_src(&inst->Src[i]); |
||||
check_register_usage( |
||||
ctx, |
||||
reg, |
||||
"source", |
||||
(boolean)inst->Src[i].Register.Indirect ); |
||||
if (inst->Src[i].Register.Indirect) { |
||||
scan_register *ind_reg = MALLOC(sizeof(scan_register)); |
||||
|
||||
fill_scan_register1d(ind_reg, |
||||
inst->Src[i].Indirect.File, |
||||
inst->Src[i].Indirect.Index); |
||||
check_register_usage( |
||||
ctx, |
||||
ind_reg, |
||||
"indirect", |
||||
FALSE ); |
||||
} |
||||
} |
||||
|
||||
ctx->num_instructions++; |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
static void |
||||
check_and_declare(struct sanity_check_ctx *ctx, |
||||
scan_register *reg) |
||||
{ |
||||
if (is_register_declared( ctx, reg)) |
||||
report_error( ctx, "%s[%u]: The same register declared more than once", |
||||
file_names[reg->file], reg->indices[0] ); |
||||
cso_hash_insert(ctx->regs_decl, |
||||
scan_register_key(reg), |
||||
reg); |
||||
} |
||||
|
||||
|
||||
static boolean |
||||
iter_declaration( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_declaration *decl ) |
||||
{ |
||||
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; |
||||
uint file; |
||||
uint i; |
||||
|
||||
/* No declarations allowed after the first instruction.
|
||||
*/ |
||||
if (ctx->num_instructions > 0) |
||||
report_error( ctx, "Instruction expected but declaration found" ); |
||||
|
||||
/* Check registers' validity.
|
||||
* Mark the registers as declared. |
||||
*/ |
||||
file = decl->Declaration.File; |
||||
if (!check_file_name( ctx, file )) |
||||
return TRUE; |
||||
for (i = decl->Range.First; i <= decl->Range.Last; i++) { |
||||
/* declared TGSI_FILE_INPUT's for geometry processor
|
||||
* have an implied second dimension */ |
||||
if (file == TGSI_FILE_INPUT && |
||||
ctx->iter.processor.Processor == TGSI_PROCESSOR_GEOMETRY) { |
||||
uint vert; |
||||
for (vert = 0; vert < ctx->implied_array_size; ++vert) { |
||||
scan_register *reg = MALLOC(sizeof(scan_register)); |
||||
fill_scan_register2d(reg, file, i, vert); |
||||
check_and_declare(ctx, reg); |
||||
} |
||||
} else { |
||||
scan_register *reg = MALLOC(sizeof(scan_register)); |
||||
if (decl->Declaration.Dimension) { |
||||
fill_scan_register2d(reg, file, i, decl->Dim.Index2D); |
||||
} else { |
||||
fill_scan_register1d(reg, file, i); |
||||
} |
||||
check_and_declare(ctx, reg); |
||||
} |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
static boolean |
||||
iter_immediate( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_immediate *imm ) |
||||
{ |
||||
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; |
||||
scan_register *reg; |
||||
|
||||
/* No immediates allowed after the first instruction.
|
||||
*/ |
||||
if (ctx->num_instructions > 0) |
||||
report_error( ctx, "Instruction expected but immediate found" ); |
||||
|
||||
/* Mark the register as declared.
|
||||
*/ |
||||
reg = MALLOC(sizeof(scan_register)); |
||||
fill_scan_register1d(reg, TGSI_FILE_IMMEDIATE, ctx->num_imms); |
||||
cso_hash_insert(ctx->regs_decl, scan_register_key(reg), reg); |
||||
ctx->num_imms++; |
||||
|
||||
/* Check data type validity.
|
||||
*/ |
||||
if (imm->Immediate.DataType != TGSI_IMM_FLOAT32 && |
||||
imm->Immediate.DataType != TGSI_IMM_UINT32 && |
||||
imm->Immediate.DataType != TGSI_IMM_INT32) { |
||||
report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType ); |
||||
return TRUE; |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
|
||||
static boolean |
||||
iter_property( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_property *prop ) |
||||
{ |
||||
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; |
||||
|
||||
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY && |
||||
prop->Property.PropertyName == TGSI_PROPERTY_GS_INPUT_PRIM) { |
||||
ctx->implied_array_size = u_vertices_per_prim(prop->u[0].Data); |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
static boolean |
||||
epilog( |
||||
struct tgsi_iterate_context *iter ) |
||||
{ |
||||
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; |
||||
|
||||
/* There must be an END instruction somewhere.
|
||||
*/ |
||||
if (ctx->index_of_END == ~0) { |
||||
report_error( ctx, "Missing END instruction" ); |
||||
} |
||||
|
||||
/* Check if all declared registers were used.
|
||||
*/ |
||||
{ |
||||
struct cso_hash_iter iter = |
||||
cso_hash_first_node(ctx->regs_decl); |
||||
|
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
scan_register *reg = (scan_register *)cso_hash_iter_data(iter); |
||||
if (!is_register_used(ctx, reg) && !is_ind_register_used(ctx, reg)) { |
||||
report_warning( ctx, "%s[%u]: Register never used", |
||||
file_names[reg->file], reg->indices[0] ); |
||||
} |
||||
iter = cso_hash_iter_next(iter); |
||||
} |
||||
} |
||||
|
||||
/* Print totals, if any.
|
||||
*/ |
||||
if (ctx->errors || ctx->warnings) |
||||
debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings ); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
static void |
||||
regs_hash_destroy(struct cso_hash *hash) |
||||
{ |
||||
struct cso_hash_iter iter = cso_hash_first_node(hash); |
||||
while (!cso_hash_iter_is_null(iter)) { |
||||
scan_register *reg = (scan_register *)cso_hash_iter_data(iter); |
||||
iter = cso_hash_erase(hash, iter); |
||||
assert(reg->file < TGSI_FILE_COUNT); |
||||
FREE(reg); |
||||
} |
||||
cso_hash_delete(hash); |
||||
} |
||||
|
||||
boolean |
||||
tgsi_sanity_check( |
||||
const struct tgsi_token *tokens ) |
||||
{ |
||||
struct sanity_check_ctx ctx; |
||||
|
||||
ctx.iter.prolog = NULL; |
||||
ctx.iter.iterate_instruction = iter_instruction; |
||||
ctx.iter.iterate_declaration = iter_declaration; |
||||
ctx.iter.iterate_immediate = iter_immediate; |
||||
ctx.iter.iterate_property = iter_property; |
||||
ctx.iter.epilog = epilog; |
||||
|
||||
ctx.regs_decl = cso_hash_create(); |
||||
ctx.regs_used = cso_hash_create(); |
||||
ctx.regs_ind_used = cso_hash_create(); |
||||
|
||||
ctx.num_imms = 0; |
||||
ctx.num_instructions = 0; |
||||
ctx.index_of_END = ~0; |
||||
|
||||
ctx.errors = 0; |
||||
ctx.warnings = 0; |
||||
ctx.implied_array_size = 0; |
||||
ctx.print = debug_get_option_print_sanity(); |
||||
|
||||
if (!tgsi_iterate_shader( tokens, &ctx.iter )) |
||||
return FALSE; |
||||
|
||||
regs_hash_destroy(ctx.regs_decl); |
||||
regs_hash_destroy(ctx.regs_used); |
||||
regs_hash_destroy(ctx.regs_ind_used); |
||||
return ctx.errors == 0; |
||||
} |
@ -0,0 +1,61 @@ |
||||
/*
|
||||
* Copyright (C) 2011 Red Hat Inc. |
||||
*
|
||||
* block compression parts are: |
||||
* Copyright (C) 2004 Roland Scheidegger 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, 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. |
||||
* |
||||
* Author: |
||||
* Dave Airlie |
||||
*/ |
||||
|
||||
#include <inttypes.h> |
||||
#include "macros.h" |
||||
|
||||
#include "rgtc.h" |
||||
|
||||
#define RGTC_DEBUG 0 |
||||
|
||||
#define TAG(x) util_format_unsigned_##x |
||||
|
||||
#define TYPE unsigned char |
||||
#define T_MIN 0 |
||||
#define T_MAX 0xff |
||||
|
||||
#include "texcompress_rgtc_tmp.h" |
||||
|
||||
#undef TAG |
||||
#undef TYPE |
||||
#undef T_MIN |
||||
#undef T_MAX |
||||
|
||||
#define TAG(x) util_format_signed_##x |
||||
#define TYPE signed char |
||||
#define T_MIN (signed char)-128 |
||||
#define T_MAX (signed char)127 |
||||
|
||||
#include "texcompress_rgtc_tmp.h" |
||||
|
||||
#undef TAG |
||||
#undef TYPE |
||||
#undef T_MIN |
||||
#undef T_MAX |
||||
|
@ -0,0 +1,39 @@ |
||||
/*
|
||||
* Copyright © 2014 Red Hat |
||||
* |
||||
* 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 _RGTC_H |
||||
#define _RGTC_H |
||||
|
||||
void util_format_unsigned_fetch_texel_rgtc(unsigned srcRowStride, const unsigned char *pixdata, |
||||
unsigned i, unsigned j, unsigned char *value, unsigned comps); |
||||
|
||||
void util_format_signed_fetch_texel_rgtc(unsigned srcRowStride, const signed char *pixdata, |
||||
unsigned i, unsigned j, signed char *value, unsigned comps); |
||||
|
||||
void util_format_unsigned_encode_rgtc_ubyte(unsigned char *blkaddr, unsigned char srccolors[4][4], |
||||
int numxpixels, int numypixels); |
||||
|
||||
void util_format_signed_encode_rgtc_ubyte(signed char *blkaddr, signed char srccolors[4][4], |
||||
int numxpixels, int numypixels); |
||||
#endif /* _RGTC_H */ |
@ -0,0 +1,458 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Dennis Smit |
||||
* 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 |
||||
* on 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 |
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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 |
||||
* CPU feature detection. |
||||
* |
||||
* @author Dennis Smit |
||||
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org> |
||||
*/ |
||||
|
||||
#include "pipe/p_config.h" |
||||
|
||||
#include "u_debug.h" |
||||
#include "u_cpu_detect.h" |
||||
|
||||
#if defined(PIPE_ARCH_PPC) |
||||
#if defined(PIPE_OS_APPLE) |
||||
#include <sys/sysctl.h> |
||||
#else |
||||
#include <signal.h> |
||||
#include <setjmp.h> |
||||
#endif |
||||
#endif |
||||
|
||||
#if defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD) |
||||
#include <sys/param.h> |
||||
#include <sys/sysctl.h> |
||||
#include <machine/cpu.h> |
||||
#endif |
||||
|
||||
#if defined(PIPE_OS_FREEBSD) |
||||
#include <sys/types.h> |
||||
#include <sys/sysctl.h> |
||||
#endif |
||||
|
||||
#if defined(PIPE_OS_LINUX) |
||||
#include <signal.h> |
||||
#endif |
||||
|
||||
#ifdef PIPE_OS_UNIX |
||||
#include <unistd.h> |
||||
#endif |
||||
|
||||
#if defined(PIPE_OS_WINDOWS) |
||||
#include <windows.h> |
||||
#if defined(PIPE_CC_MSVC) |
||||
#include <intrin.h> |
||||
#endif |
||||
#endif |
||||
|
||||
|
||||
#ifdef DEBUG |
||||
DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE) |
||||
#endif |
||||
|
||||
|
||||
struct util_cpu_caps util_cpu_caps; |
||||
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) |
||||
static int has_cpuid(void); |
||||
#endif |
||||
|
||||
|
||||
#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE) |
||||
static jmp_buf __lv_powerpc_jmpbuf; |
||||
static volatile sig_atomic_t __lv_powerpc_canjump = 0; |
||||
|
||||
static void |
||||
sigill_handler(int sig) |
||||
{ |
||||
if (!__lv_powerpc_canjump) { |
||||
signal (sig, SIG_DFL); |
||||
raise (sig); |
||||
} |
||||
|
||||
__lv_powerpc_canjump = 0; |
||||
longjmp(__lv_powerpc_jmpbuf, 1); |
||||
} |
||||
#endif |
||||
|
||||
#if defined(PIPE_ARCH_PPC) |
||||
static void |
||||
check_os_altivec_support(void) |
||||
{ |
||||
#if defined(PIPE_OS_APPLE) |
||||
int sels[2] = {CTL_HW, HW_VECTORUNIT}; |
||||
int has_vu = 0; |
||||
int len = sizeof (has_vu); |
||||
int err; |
||||
|
||||
err = sysctl(sels, 2, &has_vu, &len, NULL, 0); |
||||
|
||||
if (err == 0) { |
||||
if (has_vu != 0) { |
||||
util_cpu_caps.has_altivec = 1; |
||||
} |
||||
} |
||||
#else /* !PIPE_OS_APPLE */ |
||||
/* not on Apple/Darwin, do it the brute-force way */ |
||||
/* this is borrowed from the libmpeg2 library */ |
||||
signal(SIGILL, sigill_handler); |
||||
if (setjmp(__lv_powerpc_jmpbuf)) { |
||||
signal(SIGILL, SIG_DFL); |
||||
} else { |
||||
__lv_powerpc_canjump = 1; |
||||
|
||||
__asm __volatile |
||||
("mtspr 256, %0\n\t" |
||||
"vand %%v0, %%v0, %%v0" |
||||
: |
||||
: "r" (-1)); |
||||
|
||||
signal(SIGILL, SIG_DFL); |
||||
util_cpu_caps.has_altivec = 1; |
||||
} |
||||
#endif /* !PIPE_OS_APPLE */ |
||||
} |
||||
#endif /* PIPE_ARCH_PPC */ |
||||
|
||||
|
||||
#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64) |
||||
static int has_cpuid(void) |
||||
{ |
||||
#if defined(PIPE_ARCH_X86) |
||||
#if defined(PIPE_OS_GCC) |
||||
int a, c; |
||||
|
||||
__asm __volatile |
||||
("pushf\n" |
||||
"popl %0\n" |
||||
"movl %0, %1\n" |
||||
"xorl $0x200000, %0\n" |
||||
"push %0\n" |
||||
"popf\n" |
||||
"pushf\n" |
||||
"popl %0\n" |
||||
: "=a" (a), "=c" (c) |
||||
: |
||||
: "cc"); |
||||
|
||||
return a != c; |
||||
#else |
||||
/* FIXME */ |
||||
return 1; |
||||
#endif |
||||
#elif defined(PIPE_ARCH_X86_64) |
||||
return 1; |
||||
#else |
||||
return 0; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* @sa cpuid.h included in gcc-4.3 onwards. |
||||
* @sa http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
|
||||
*/ |
||||
static INLINE void |
||||
cpuid(uint32_t ax, uint32_t *p) |
||||
{ |
||||
#if (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86) |
||||
__asm __volatile ( |
||||
"xchgl %%ebx, %1\n\t" |
||||
"cpuid\n\t" |
||||
"xchgl %%ebx, %1" |
||||
: "=a" (p[0]), |
||||
"=S" (p[1]), |
||||
"=c" (p[2]), |
||||
"=d" (p[3]) |
||||
: "0" (ax) |
||||
); |
||||
#elif (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86_64) |
||||
__asm __volatile ( |
||||
"cpuid\n\t" |
||||
: "=a" (p[0]), |
||||
"=b" (p[1]), |
||||
"=c" (p[2]), |
||||
"=d" (p[3]) |
||||
: "0" (ax) |
||||
); |
||||
#elif defined(PIPE_CC_MSVC) |
||||
__cpuid(p, ax); |
||||
#else |
||||
p[0] = 0; |
||||
p[1] = 0; |
||||
p[2] = 0; |
||||
p[3] = 0; |
||||
#endif |
||||
} |
||||
|
||||
/**
|
||||
* @sa cpuid.h included in gcc-4.4 onwards. |
||||
* @sa http://msdn.microsoft.com/en-us/library/hskdteyh%28v=vs.90%29.aspx
|
||||
*/ |
||||
static INLINE void |
||||
cpuid_count(uint32_t ax, uint32_t cx, uint32_t *p) |
||||
{ |
||||
#if (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86) |
||||
__asm __volatile ( |
||||
"xchgl %%ebx, %1\n\t" |
||||
"cpuid\n\t" |
||||
"xchgl %%ebx, %1" |
||||
: "=a" (p[0]), |
||||
"=S" (p[1]), |
||||
"=c" (p[2]), |
||||
"=d" (p[3]) |
||||
: "0" (ax), "2" (cx) |
||||
); |
||||
#elif (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86_64) |
||||
__asm __volatile ( |
||||
"cpuid\n\t" |
||||
: "=a" (p[0]), |
||||
"=b" (p[1]), |
||||
"=c" (p[2]), |
||||
"=d" (p[3]) |
||||
: "0" (ax), "2" (cx) |
||||
); |
||||
#elif defined(PIPE_CC_MSVC) |
||||
__cpuidex(p, ax, cx); |
||||
#else |
||||
p[0] = 0; |
||||
p[1] = 0; |
||||
p[2] = 0; |
||||
p[3] = 0; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
static INLINE uint64_t xgetbv(void) |
||||
{ |
||||
#if defined(PIPE_CC_GCC) |
||||
uint32_t eax, edx; |
||||
|
||||
__asm __volatile ( |
||||
".byte 0x0f, 0x01, 0xd0" // xgetbv isn't supported on gcc < 4.4
|
||||
: "=a"(eax), |
||||
"=d"(edx) |
||||
: "c"(0) |
||||
); |
||||
|
||||
return ((uint64_t)edx << 32) | eax; |
||||
#elif defined(PIPE_CC_MSVC) && defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) |
||||
return _xgetbv(_XCR_XFEATURE_ENABLED_MASK); |
||||
#else |
||||
return 0; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
#if defined(PIPE_ARCH_X86) |
||||
static INLINE boolean sse2_has_daz(void) |
||||
{ |
||||
struct { |
||||
uint32_t pad1[7]; |
||||
uint32_t mxcsr_mask; |
||||
uint32_t pad2[128-8]; |
||||
} PIPE_ALIGN_VAR(16) fxarea; |
||||
|
||||
fxarea.mxcsr_mask = 0; |
||||
#if (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) |
||||
__asm __volatile ("fxsave %0" : "+m" (fxarea)); |
||||
#elif (defined(PIPE_CC_MSVC) && _MSC_VER >= 1700) || defined(PIPE_CC_ICL) |
||||
/* 1700 = Visual Studio 2012 */ |
||||
_fxsave(&fxarea); |
||||
#else |
||||
fxarea.mxcsr_mask = 0; |
||||
#endif |
||||
return !!(fxarea.mxcsr_mask & (1 << 6)); |
||||
} |
||||
#endif |
||||
|
||||
#endif /* X86 or X86_64 */ |
||||
|
||||
void |
||||
util_cpu_detect(void) |
||||
{ |
||||
static boolean util_cpu_detect_initialized = FALSE; |
||||
|
||||
if(util_cpu_detect_initialized) |
||||
return; |
||||
|
||||
memset(&util_cpu_caps, 0, sizeof util_cpu_caps); |
||||
|
||||
/* Count the number of CPUs in system */ |
||||
#if defined(PIPE_OS_WINDOWS) |
||||
{ |
||||
SYSTEM_INFO system_info; |
||||
GetSystemInfo(&system_info); |
||||
util_cpu_caps.nr_cpus = system_info.dwNumberOfProcessors; |
||||
} |
||||
#elif defined(PIPE_OS_UNIX) && defined(_SC_NPROCESSORS_ONLN) |
||||
util_cpu_caps.nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
||||
if (util_cpu_caps.nr_cpus == -1) |
||||
util_cpu_caps.nr_cpus = 1; |
||||
#elif defined(PIPE_OS_BSD) |
||||
{ |
||||
int mib[2], ncpu; |
||||
int len; |
||||
|
||||
mib[0] = CTL_HW; |
||||
mib[1] = HW_NCPU; |
||||
|
||||
len = sizeof (ncpu); |
||||
sysctl(mib, 2, &ncpu, &len, NULL, 0); |
||||
util_cpu_caps.nr_cpus = ncpu; |
||||
} |
||||
#else |
||||
util_cpu_caps.nr_cpus = 1; |
||||
#endif |
||||
|
||||
/* Make the fallback cacheline size nonzero so that it can be
|
||||
* safely passed to align(). |
||||
*/ |
||||
util_cpu_caps.cacheline = sizeof(void *); |
||||
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) |
||||
if (has_cpuid()) { |
||||
uint32_t regs[4]; |
||||
uint32_t regs2[4]; |
||||
|
||||
util_cpu_caps.cacheline = 32; |
||||
|
||||
/* Get max cpuid level */ |
||||
cpuid(0x00000000, regs); |
||||
|
||||
if (regs[0] >= 0x00000001) { |
||||
unsigned int cacheline; |
||||
|
||||
cpuid (0x00000001, regs2); |
||||
|
||||
util_cpu_caps.x86_cpu_type = (regs2[0] >> 8) & 0xf; |
||||
if (util_cpu_caps.x86_cpu_type == 0xf) |
||||
util_cpu_caps.x86_cpu_type = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */ |
||||
|
||||
/* general feature flags */ |
||||
util_cpu_caps.has_tsc = (regs2[3] >> 4) & 1; /* 0x0000010 */ |
||||
util_cpu_caps.has_mmx = (regs2[3] >> 23) & 1; /* 0x0800000 */ |
||||
util_cpu_caps.has_sse = (regs2[3] >> 25) & 1; /* 0x2000000 */ |
||||
util_cpu_caps.has_sse2 = (regs2[3] >> 26) & 1; /* 0x4000000 */ |
||||
util_cpu_caps.has_sse3 = (regs2[2] >> 0) & 1; /* 0x0000001 */ |
||||
util_cpu_caps.has_ssse3 = (regs2[2] >> 9) & 1; /* 0x0000020 */ |
||||
util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1; |
||||
util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1; |
||||
util_cpu_caps.has_popcnt = (regs2[2] >> 23) & 1; |
||||
util_cpu_caps.has_avx = ((regs2[2] >> 28) & 1) && // AVX
|
||||
((regs2[2] >> 27) & 1) && // OSXSAVE
|
||||
((xgetbv() & 6) == 6); // XMM & YMM
|
||||
util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1; |
||||
util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ |
||||
#if defined(PIPE_ARCH_X86_64) |
||||
util_cpu_caps.has_daz = 1; |
||||
#else |
||||
util_cpu_caps.has_daz = util_cpu_caps.has_sse3 || |
||||
(util_cpu_caps.has_sse2 && sse2_has_daz()); |
||||
#endif |
||||
|
||||
cacheline = ((regs2[1] >> 8) & 0xFF) * 8; |
||||
if (cacheline > 0) |
||||
util_cpu_caps.cacheline = cacheline; |
||||
} |
||||
if (util_cpu_caps.has_avx && regs[0] >= 0x00000007) { |
||||
uint32_t regs7[4]; |
||||
cpuid_count(0x00000007, 0x00000000, regs7); |
||||
util_cpu_caps.has_avx2 = (regs7[1] >> 5) & 1; |
||||
} |
||||
|
||||
if (regs[1] == 0x756e6547 && regs[2] == 0x6c65746e && regs[3] == 0x49656e69) { |
||||
/* GenuineIntel */ |
||||
util_cpu_caps.has_intel = 1; |
||||
} |
||||
|
||||
cpuid(0x80000000, regs); |
||||
|
||||
if (regs[0] >= 0x80000001) { |
||||
|
||||
cpuid(0x80000001, regs2); |
||||
|
||||
util_cpu_caps.has_mmx |= (regs2[3] >> 23) & 1; |
||||
util_cpu_caps.has_mmx2 |= (regs2[3] >> 22) & 1; |
||||
util_cpu_caps.has_3dnow = (regs2[3] >> 31) & 1; |
||||
util_cpu_caps.has_3dnow_ext = (regs2[3] >> 30) & 1; |
||||
|
||||
util_cpu_caps.has_xop = util_cpu_caps.has_avx && |
||||
((regs2[2] >> 11) & 1); |
||||
} |
||||
|
||||
if (regs[0] >= 0x80000006) { |
||||
cpuid(0x80000006, regs2); |
||||
util_cpu_caps.cacheline = regs2[2] & 0xFF; |
||||
} |
||||
|
||||
if (!util_cpu_caps.has_sse) { |
||||
util_cpu_caps.has_sse2 = 0; |
||||
util_cpu_caps.has_sse3 = 0; |
||||
util_cpu_caps.has_ssse3 = 0; |
||||
util_cpu_caps.has_sse4_1 = 0; |
||||
} |
||||
} |
||||
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */ |
||||
|
||||
#if defined(PIPE_ARCH_PPC) |
||||
check_os_altivec_support(); |
||||
#endif /* PIPE_ARCH_PPC */ |
||||
|
||||
#ifdef DEBUG |
||||
if (debug_get_option_dump_cpu()) { |
||||
debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus); |
||||
|
||||
debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type); |
||||
debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline); |
||||
|
||||
debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc); |
||||
debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx); |
||||
debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2); |
||||
debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse); |
||||
debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2); |
||||
debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3); |
||||
debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3); |
||||
debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1); |
||||
debug_printf("util_cpu_caps.has_sse4_2 = %u\n", util_cpu_caps.has_sse4_2); |
||||
debug_printf("util_cpu_caps.has_avx = %u\n", util_cpu_caps.has_avx); |
||||
debug_printf("util_cpu_caps.has_avx2 = %u\n", util_cpu_caps.has_avx2); |
||||
debug_printf("util_cpu_caps.has_f16c = %u\n", util_cpu_caps.has_f16c); |
||||
debug_printf("util_cpu_caps.has_popcnt = %u\n", util_cpu_caps.has_popcnt); |
||||
debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow); |
||||
debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext); |
||||
debug_printf("util_cpu_caps.has_xop = %u\n", util_cpu_caps.has_xop); |
||||
debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec); |
||||
debug_printf("util_cpu_caps.has_daz = %u\n", util_cpu_caps.has_daz); |
||||
} |
||||
#endif |
||||
|
||||
util_cpu_detect_initialized = TRUE; |
||||
} |
@ -0,0 +1,87 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Dennis Smit |
||||
* 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 |
||||
* on 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 |
||||
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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 |
||||
* CPU feature detection. |
||||
* |
||||
* @author Dennis Smit |
||||
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org> |
||||
*/ |
||||
|
||||
#ifndef _UTIL_CPU_DETECT_H |
||||
#define _UTIL_CPU_DETECT_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_config.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
struct util_cpu_caps { |
||||
unsigned nr_cpus; |
||||
|
||||
/* Feature flags */ |
||||
int x86_cpu_type; |
||||
unsigned cacheline; |
||||
|
||||
unsigned has_intel:1; |
||||
unsigned has_tsc:1; |
||||
unsigned has_mmx:1; |
||||
unsigned has_mmx2:1; |
||||
unsigned has_sse:1; |
||||
unsigned has_sse2:1; |
||||
unsigned has_sse3:1; |
||||
unsigned has_ssse3:1; |
||||
unsigned has_sse4_1:1; |
||||
unsigned has_sse4_2:1; |
||||
unsigned has_popcnt:1; |
||||
unsigned has_avx:1; |
||||
unsigned has_avx2:1; |
||||
unsigned has_f16c:1; |
||||
unsigned has_3dnow:1; |
||||
unsigned has_3dnow_ext:1; |
||||
unsigned has_xop:1; |
||||
unsigned has_altivec:1; |
||||
unsigned has_daz:1; |
||||
}; |
||||
|
||||
extern struct util_cpu_caps |
||||
util_cpu_caps; |
||||
|
||||
void util_cpu_detect(void); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* _UTIL_CPU_DETECT_H */ |
@ -0,0 +1,805 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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> |
||||
*/ |
||||
|
||||
#include "u_math.h" |
||||
#include "u_memory.h" |
||||
#include "u_format.h" |
||||
#include "u_format_s3tc.h" |
||||
#include "u_surface.h" |
||||
|
||||
#include "pipe/p_defines.h" |
||||
|
||||
|
||||
boolean |
||||
util_format_is_float(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
unsigned i; |
||||
|
||||
assert(desc); |
||||
if (!desc) { |
||||
return FALSE; |
||||
} |
||||
|
||||
i = util_format_get_first_non_void_channel(format); |
||||
if (i == -1) { |
||||
return FALSE; |
||||
} |
||||
|
||||
return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; |
||||
} |
||||
|
||||
|
||||
/** Test if the format contains RGB, but not alpha */ |
||||
boolean |
||||
util_format_has_alpha(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && |
||||
desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1; |
||||
} |
||||
|
||||
|
||||
boolean |
||||
util_format_is_luminance(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && |
||||
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) { |
||||
return TRUE; |
||||
} |
||||
return FALSE; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_alpha(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && |
||||
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_0 && |
||||
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0 && |
||||
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0 && |
||||
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) { |
||||
return TRUE; |
||||
} |
||||
return FALSE; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_pure_integer(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
int i; |
||||
|
||||
/* Find the first non-void channel. */ |
||||
i = util_format_get_first_non_void_channel(format); |
||||
if (i == -1) |
||||
return FALSE; |
||||
|
||||
return desc->channel[i].pure_integer ? TRUE : FALSE; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_pure_sint(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
int i; |
||||
|
||||
i = util_format_get_first_non_void_channel(format); |
||||
if (i == -1) |
||||
return FALSE; |
||||
|
||||
return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_pure_uint(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
int i; |
||||
|
||||
i = util_format_get_first_non_void_channel(format); |
||||
if (i == -1) |
||||
return FALSE; |
||||
|
||||
return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; |
||||
} |
||||
|
||||
/**
|
||||
* Returns true if all non-void channels are normalized signed. |
||||
*/ |
||||
boolean |
||||
util_format_is_snorm(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
int i; |
||||
|
||||
if (desc->is_mixed) |
||||
return FALSE; |
||||
|
||||
i = util_format_get_first_non_void_channel(format); |
||||
if (i == -1) |
||||
return FALSE; |
||||
|
||||
return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && |
||||
!desc->channel[i].pure_integer && |
||||
desc->channel[i].normalized; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_luminance_alpha(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && |
||||
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) { |
||||
return TRUE; |
||||
} |
||||
return FALSE; |
||||
} |
||||
|
||||
|
||||
boolean |
||||
util_format_is_intensity(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && |
||||
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && |
||||
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) { |
||||
return TRUE; |
||||
} |
||||
return FALSE; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_subsampled_422(enum pipe_format format) |
||||
{ |
||||
const struct util_format_description *desc = |
||||
util_format_description(format); |
||||
|
||||
return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED && |
||||
desc->block.width == 2 && |
||||
desc->block.height == 1 && |
||||
desc->block.bits == 32; |
||||
} |
||||
|
||||
boolean |
||||
util_format_is_supported(enum pipe_format format, unsigned bind) |
||||
{ |
||||
if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) { |
||||
return FALSE; |
||||
} |
||||
|
||||
#ifndef TEXTURE_FLOAT_ENABLED |
||||
if ((bind & PIPE_BIND_RENDER_TARGET) && |
||||
format != PIPE_FORMAT_R9G9B9E5_FLOAT && |
||||
format != PIPE_FORMAT_R11G11B10_FLOAT && |
||||
util_format_is_float(format)) { |
||||
return FALSE; |
||||
} |
||||
#endif |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Calculates the MRD for the depth format. MRD is used in depth bias |
||||
* for UNORM and unbound depth buffers. When the depth buffer is floating |
||||
* point, the depth bias calculation does not use the MRD. However, the |
||||
* default MRD will be 1.0 / ((1 << 24) - 1). |
||||
*/ |
||||
double |
||||
util_get_depth_format_mrd(const struct util_format_description *desc) |
||||
{ |
||||
/*
|
||||
* Depth buffer formats without a depth component OR scenarios |
||||
* without a bound depth buffer default to D24. |
||||
*/ |
||||
double mrd = 1.0 / ((1 << 24) - 1); |
||||
unsigned depth_channel; |
||||
|
||||
assert(desc); |
||||
|
||||
/*
|
||||
* Some depth formats do not store the depth component in the first |
||||
* channel, detect the format and adjust the depth channel. Get the |
||||
* swizzled depth component channel. |
||||
*/ |
||||
depth_channel = desc->swizzle[0]; |
||||
|
||||
if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED && |
||||
desc->channel[depth_channel].normalized) { |
||||
int depth_bits; |
||||
|
||||
depth_bits = desc->channel[depth_channel].size; |
||||
mrd = 1.0 / ((1ULL << depth_bits) - 1); |
||||
} |
||||
|
||||
return mrd; |
||||
} |
||||
|
||||
|
||||
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) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
const uint8_t *src_row; |
||||
float *dst_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); |
||||
dst_row = dst; |
||||
|
||||
format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, 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) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
uint8_t *dst_row; |
||||
const float *src_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); |
||||
src_row = src; |
||||
|
||||
format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, 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) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
const uint8_t *src_row; |
||||
uint8_t *dst_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); |
||||
dst_row = dst; |
||||
|
||||
format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, 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) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
uint8_t *dst_row; |
||||
const uint8_t *src_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); |
||||
src_row = src; |
||||
|
||||
format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); |
||||
} |
||||
|
||||
void |
||||
util_format_read_4ui(enum pipe_format format, |
||||
unsigned *dst, unsigned dst_stride, |
||||
const void *src, unsigned src_stride, |
||||
unsigned x, unsigned y, unsigned w, unsigned h) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
const uint8_t *src_row; |
||||
uint32_t *dst_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); |
||||
dst_row = dst; |
||||
|
||||
format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); |
||||
} |
||||
|
||||
void |
||||
util_format_write_4ui(enum pipe_format format, |
||||
const unsigned int *src, unsigned src_stride, |
||||
void *dst, unsigned dst_stride, |
||||
unsigned x, unsigned y, unsigned w, unsigned h) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
uint8_t *dst_row; |
||||
const uint32_t *src_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); |
||||
src_row = src; |
||||
|
||||
format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); |
||||
} |
||||
|
||||
void |
||||
util_format_read_4i(enum pipe_format format, |
||||
int *dst, unsigned dst_stride, |
||||
const void *src, unsigned src_stride, |
||||
unsigned x, unsigned y, unsigned w, unsigned h) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
const uint8_t *src_row; |
||||
int32_t *dst_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); |
||||
dst_row = dst; |
||||
|
||||
format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); |
||||
} |
||||
|
||||
void |
||||
util_format_write_4i(enum pipe_format format, |
||||
const int *src, unsigned src_stride, |
||||
void *dst, unsigned dst_stride, |
||||
unsigned x, unsigned y, unsigned w, unsigned h) |
||||
{ |
||||
const struct util_format_description *format_desc; |
||||
uint8_t *dst_row; |
||||
const int32_t *src_row; |
||||
|
||||
format_desc = util_format_description(format); |
||||
|
||||
assert(x % format_desc->block.width == 0); |
||||
assert(y % format_desc->block.height == 0); |
||||
|
||||
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); |
||||
src_row = src; |
||||
|
||||
format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); |
||||
} |
||||
|
||||
boolean |
||||
util_is_format_compatible(const struct util_format_description *src_desc, |
||||
const struct util_format_description *dst_desc) |
||||
{ |
||||
unsigned chan; |
||||
|
||||
if (src_desc->format == dst_desc->format) { |
||||
return TRUE; |
||||
} |
||||
|
||||
if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || |
||||
dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { |
||||
return FALSE; |
||||
} |
||||
|
||||
if (src_desc->block.bits != dst_desc->block.bits || |
||||
src_desc->nr_channels != dst_desc->nr_channels || |
||||
src_desc->colorspace != dst_desc->colorspace) { |
||||
return FALSE; |
||||
} |
||||
|
||||
for (chan = 0; chan < 4; ++chan) { |
||||
if (src_desc->channel[chan].size != |
||||
dst_desc->channel[chan].size) { |
||||
return FALSE; |
||||
} |
||||
} |
||||
|
||||
for (chan = 0; chan < 4; ++chan) { |
||||
enum util_format_swizzle swizzle = dst_desc->swizzle[chan]; |
||||
|
||||
if (swizzle < 4) { |
||||
if (src_desc->swizzle[chan] != swizzle) { |
||||
return FALSE; |
||||
} |
||||
if ((src_desc->channel[swizzle].type != |
||||
dst_desc->channel[swizzle].type) || |
||||
(src_desc->channel[swizzle].normalized != |
||||
dst_desc->channel[swizzle].normalized)) { |
||||
return FALSE; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
|
||||
boolean |
||||
util_format_fits_8unorm(const struct util_format_description *format_desc) |
||||
{ |
||||
unsigned chan; |
||||
|
||||
/*
|
||||
* After linearized sRGB values require more than 8bits. |
||||
*/ |
||||
|
||||
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { |
||||
return FALSE; |
||||
} |
||||
|
||||
switch (format_desc->layout) { |
||||
|
||||
case UTIL_FORMAT_LAYOUT_S3TC: |
||||
/*
|
||||
* These are straight forward. |
||||
*/ |
||||
return TRUE; |
||||
case UTIL_FORMAT_LAYOUT_RGTC: |
||||
if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM || |
||||
format_desc->format == PIPE_FORMAT_RGTC2_SNORM || |
||||
format_desc->format == PIPE_FORMAT_LATC1_SNORM || |
||||
format_desc->format == PIPE_FORMAT_LATC2_SNORM) |
||||
return FALSE; |
||||
return TRUE; |
||||
case UTIL_FORMAT_LAYOUT_BPTC: |
||||
if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM) |
||||
return TRUE; |
||||
return FALSE; |
||||
|
||||
case UTIL_FORMAT_LAYOUT_PLAIN: |
||||
/*
|
||||
* For these we can find a generic rule. |
||||
*/ |
||||
|
||||
for (chan = 0; chan < format_desc->nr_channels; ++chan) { |
||||
switch (format_desc->channel[chan].type) { |
||||
case UTIL_FORMAT_TYPE_VOID: |
||||
break; |
||||
case UTIL_FORMAT_TYPE_UNSIGNED: |
||||
if (!format_desc->channel[chan].normalized || |
||||
format_desc->channel[chan].size > 8) { |
||||
return FALSE; |
||||
} |
||||
break; |
||||
default: |
||||
return FALSE; |
||||
} |
||||
} |
||||
return TRUE; |
||||
|
||||
default: |
||||
/*
|
||||
* Handle all others on a case by case basis. |
||||
*/ |
||||
|
||||
switch (format_desc->format) { |
||||
case PIPE_FORMAT_R1_UNORM: |
||||
case PIPE_FORMAT_UYVY: |
||||
case PIPE_FORMAT_YUYV: |
||||
case PIPE_FORMAT_R8G8_B8G8_UNORM: |
||||
case PIPE_FORMAT_G8R8_G8B8_UNORM: |
||||
return TRUE; |
||||
|
||||
default: |
||||
return FALSE; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
boolean |
||||
util_format_translate(enum pipe_format dst_format, |
||||
void *dst, unsigned dst_stride, |
||||
unsigned dst_x, unsigned dst_y, |
||||
enum pipe_format src_format, |
||||
const void *src, unsigned src_stride, |
||||
unsigned src_x, unsigned src_y, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
const struct util_format_description *dst_format_desc; |
||||
const struct util_format_description *src_format_desc; |
||||
uint8_t *dst_row; |
||||
const uint8_t *src_row; |
||||
unsigned x_step, y_step; |
||||
unsigned dst_step; |
||||
unsigned src_step; |
||||
|
||||
dst_format_desc = util_format_description(dst_format); |
||||
src_format_desc = util_format_description(src_format); |
||||
|
||||
if (util_is_format_compatible(src_format_desc, dst_format_desc)) { |
||||
/*
|
||||
* Trivial case. |
||||
*/ |
||||
|
||||
util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, |
||||
width, height, src, (int)src_stride, |
||||
src_x, src_y); |
||||
return TRUE; |
||||
} |
||||
|
||||
assert(dst_x % dst_format_desc->block.width == 0); |
||||
assert(dst_y % dst_format_desc->block.height == 0); |
||||
assert(src_x % src_format_desc->block.width == 0); |
||||
assert(src_y % src_format_desc->block.height == 0); |
||||
|
||||
dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8); |
||||
src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8); |
||||
|
||||
/*
|
||||
* This works because all pixel formats have pixel blocks with power of two |
||||
* sizes. |
||||
*/ |
||||
|
||||
y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height); |
||||
x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width); |
||||
assert(y_step % dst_format_desc->block.height == 0); |
||||
assert(y_step % src_format_desc->block.height == 0); |
||||
|
||||
dst_step = y_step / dst_format_desc->block.height * dst_stride; |
||||
src_step = y_step / src_format_desc->block.height * src_stride; |
||||
|
||||
/*
|
||||
* TODO: double formats will loose precision |
||||
* TODO: Add a special case for formats that are mere swizzles of each other |
||||
*/ |
||||
|
||||
if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS || |
||||
dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { |
||||
float *tmp_z = NULL; |
||||
uint8_t *tmp_s = NULL; |
||||
|
||||
assert(x_step == 1); |
||||
assert(y_step == 1); |
||||
|
||||
if (src_format_desc->unpack_z_float && |
||||
dst_format_desc->pack_z_float) { |
||||
tmp_z = MALLOC(width * sizeof *tmp_z); |
||||
} |
||||
|
||||
if (src_format_desc->unpack_s_8uint && |
||||
dst_format_desc->pack_s_8uint) { |
||||
tmp_s = MALLOC(width * sizeof *tmp_s); |
||||
} |
||||
|
||||
while (height--) { |
||||
if (tmp_z) { |
||||
src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1); |
||||
dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1); |
||||
} |
||||
|
||||
if (tmp_s) { |
||||
src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1); |
||||
dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1); |
||||
} |
||||
|
||||
dst_row += dst_step; |
||||
src_row += src_step; |
||||
} |
||||
|
||||
FREE(tmp_s); |
||||
|
||||
FREE(tmp_z); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
if (util_format_fits_8unorm(src_format_desc) || |
||||
util_format_fits_8unorm(dst_format_desc)) { |
||||
unsigned tmp_stride; |
||||
uint8_t *tmp_row; |
||||
|
||||
if (!src_format_desc->unpack_rgba_8unorm || |
||||
!dst_format_desc->pack_rgba_8unorm) { |
||||
return FALSE; |
||||
} |
||||
|
||||
tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; |
||||
tmp_row = MALLOC(y_step * tmp_stride); |
||||
if (!tmp_row) |
||||
return FALSE; |
||||
|
||||
while (height >= y_step) { |
||||
src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); |
||||
dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); |
||||
|
||||
dst_row += dst_step; |
||||
src_row += src_step; |
||||
height -= y_step; |
||||
} |
||||
|
||||
if (height) { |
||||
src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height); |
||||
dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height); |
||||
} |
||||
|
||||
FREE(tmp_row); |
||||
} |
||||
else { |
||||
unsigned tmp_stride; |
||||
float *tmp_row; |
||||
|
||||
if (!src_format_desc->unpack_rgba_float || |
||||
!dst_format_desc->pack_rgba_float) { |
||||
return FALSE; |
||||
} |
||||
|
||||
tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; |
||||
tmp_row = MALLOC(y_step * tmp_stride); |
||||
if (!tmp_row) |
||||
return FALSE; |
||||
|
||||
while (height >= y_step) { |
||||
src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); |
||||
dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); |
||||
|
||||
dst_row += dst_step; |
||||
src_row += src_step; |
||||
height -= y_step; |
||||
} |
||||
|
||||
if (height) { |
||||
src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height); |
||||
dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height); |
||||
} |
||||
|
||||
FREE(tmp_row); |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
void util_format_compose_swizzles(const unsigned char swz1[4], |
||||
const unsigned char swz2[4], |
||||
unsigned char dst[4]) |
||||
{ |
||||
unsigned i; |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ? |
||||
swz1[swz2[i]] : swz2[i]; |
||||
} |
||||
} |
||||
|
||||
void util_format_apply_color_swizzle(union pipe_color_union *dst, |
||||
const union pipe_color_union *src, |
||||
const unsigned char swz[4], |
||||
const boolean is_integer) |
||||
{ |
||||
unsigned c; |
||||
|
||||
if (is_integer) { |
||||
for (c = 0; c < 4; ++c) { |
||||
switch (swz[c]) { |
||||
case PIPE_SWIZZLE_RED: dst->ui[c] = src->ui[0]; break; |
||||
case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break; |
||||
case PIPE_SWIZZLE_BLUE: dst->ui[c] = src->ui[2]; break; |
||||
case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break; |
||||
default: |
||||
dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0; |
||||
break; |
||||
} |
||||
} |
||||
} else { |
||||
for (c = 0; c < 4; ++c) { |
||||
switch (swz[c]) { |
||||
case PIPE_SWIZZLE_RED: dst->f[c] = src->f[0]; break; |
||||
case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break; |
||||
case PIPE_SWIZZLE_BLUE: dst->f[c] = src->f[2]; break; |
||||
case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break; |
||||
default: |
||||
dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void util_format_swizzle_4f(float *dst, const float *src, |
||||
const unsigned char swz[4]) |
||||
{ |
||||
unsigned i; |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
if (swz[i] <= UTIL_FORMAT_SWIZZLE_W) |
||||
dst[i] = src[swz[i]]; |
||||
else if (swz[i] == UTIL_FORMAT_SWIZZLE_0) |
||||
dst[i] = 0; |
||||
else if (swz[i] == UTIL_FORMAT_SWIZZLE_1) |
||||
dst[i] = 1; |
||||
} |
||||
} |
||||
|
||||
void util_format_unswizzle_4f(float *dst, const float *src, |
||||
const unsigned char swz[4]) |
||||
{ |
||||
unsigned i; |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
switch (swz[i]) { |
||||
case UTIL_FORMAT_SWIZZLE_X: |
||||
dst[0] = src[i]; |
||||
break; |
||||
case UTIL_FORMAT_SWIZZLE_Y: |
||||
dst[1] = src[i]; |
||||
break; |
||||
case UTIL_FORMAT_SWIZZLE_Z: |
||||
dst[2] = src[i]; |
||||
break; |
||||
case UTIL_FORMAT_SWIZZLE_W: |
||||
dst[3] = src[i]; |
||||
break; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
#include "pipe/p_compiler.h" |
||||
#include "util/u_debug.h" |
||||
#include "util/u_math.h" |
||||
#include "u_format_etc.h" |
||||
|
||||
/* define etc1_parse_block and etc. */ |
||||
|
||||
void |
||||
util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
void |
||||
util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
void |
||||
util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
@ -0,0 +1,167 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright (C) 2011 Red Hat Inc. |
||||
* |
||||
* 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 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#include <stdio.h> |
||||
#include "u_math.h" |
||||
#include "u_format.h" |
||||
#include "u_format_rgtc.h" |
||||
#include "u_format_latc.h" |
||||
#include "util/rgtc.h" |
||||
|
||||
void |
||||
util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rgtc1_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, |
||||
unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rgtc1_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rgtc1_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rgtc2_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rgtc2_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3); |
||||
} |
||||
|
||||
void |
||||
util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
@ -0,0 +1,472 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
#include "u_math.h" |
||||
#include "u_format_other.h" |
||||
#include "u_format_rgb9e5.h" |
||||
#include "u_format_r11g11b10f.h" |
||||
|
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
float *dst = dst_row; |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
rgb9e5_to_float3(value, dst); |
||||
dst[3] = 1; /* a */ |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
const float *src = src_row; |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = float3_to_rgb9e5(src); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*(uint32_t *)dst = value; |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j) |
||||
{ |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
rgb9e5_to_float3(value, dst); |
||||
dst[3] = 1; /* a */ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
float p[3]; |
||||
for(y = 0; y < height; y += 1) { |
||||
uint8_t *dst = dst_row; |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
rgb9e5_to_float3(value, p); |
||||
dst[0] = float_to_ubyte(p[0]); /* r */ |
||||
dst[1] = float_to_ubyte(p[1]); /* g */ |
||||
dst[2] = float_to_ubyte(p[2]); /* b */ |
||||
dst[3] = 255; /* a */ |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
float p[3]; |
||||
for(y = 0; y < height; y += 1) { |
||||
const uint8_t *src = src_row; |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value; |
||||
p[0] = ubyte_to_float(src[0]); |
||||
p[1] = ubyte_to_float(src[1]); |
||||
p[2] = ubyte_to_float(src[2]); |
||||
value = float3_to_rgb9e5(p); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*(uint32_t *)dst = value; |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
float *dst = dst_row; |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
r11g11b10f_to_float3(value, dst); |
||||
dst[3] = 1; /* a */ |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
const float *src = src_row; |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = float3_to_r11g11b10f(src); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*(uint32_t *)dst = value; |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j) |
||||
{ |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
r11g11b10f_to_float3(value, dst); |
||||
dst[3] = 1; /* a */ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
float p[3]; |
||||
for(y = 0; y < height; y += 1) { |
||||
uint8_t *dst = dst_row; |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value = *(const uint32_t *)src; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
r11g11b10f_to_float3(value, p); |
||||
dst[0] = float_to_ubyte(p[0]); /* r */ |
||||
dst[1] = float_to_ubyte(p[1]); /* g */ |
||||
dst[2] = float_to_ubyte(p[2]); /* b */ |
||||
dst[3] = 255; /* a */ |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
float p[3]; |
||||
for(y = 0; y < height; y += 1) { |
||||
const uint8_t *src = src_row; |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint32_t value; |
||||
p[0] = ubyte_to_float(src[0]); |
||||
p[1] = ubyte_to_float(src[1]); |
||||
p[2] = ubyte_to_float(src[2]); |
||||
value = float3_to_r11g11b10f(p); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*(uint32_t *)dst = value; |
||||
src += 4; |
||||
dst += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
|
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
|
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j) |
||||
{ |
||||
|
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
|
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* PIPE_FORMAT_R8G8Bx_SNORM |
||||
* |
||||
* A.k.a. D3DFMT_CxV8U8 |
||||
*/ |
||||
|
||||
static uint8_t |
||||
r8g8bx_derive(int16_t r, int16_t g) |
||||
{ |
||||
/* Derive blue from red and green components.
|
||||
* Apparently, we must always use integers to perform calculations, |
||||
* otherwise the results won't match D3D's CxV8U8 definition. |
||||
*/ |
||||
return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f; |
||||
} |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
|
||||
for(y = 0; y < height; y += 1) { |
||||
float *dst = dst_row; |
||||
const uint16_t *src = (const uint16_t *)src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint16_t value = *src++; |
||||
int16_t r, g; |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
|
||||
r = ((int16_t)(value << 8)) >> 8; |
||||
g = ((int16_t)(value << 0)) >> 8; |
||||
|
||||
dst[0] = (float)(r * (1.0f/0x7f)); /* r */ |
||||
dst[1] = (float)(g * (1.0f/0x7f)); /* g */ |
||||
dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */ |
||||
dst[3] = 1.0f; /* a */ |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
uint8_t *dst = dst_row; |
||||
const uint16_t *src = (const uint16_t *)src_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint16_t value = *src++; |
||||
int16_t r, g; |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
|
||||
r = ((int16_t)(value << 8)) >> 8; |
||||
g = ((int16_t)(value << 0)) >> 8; |
||||
|
||||
dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ |
||||
dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ |
||||
dst[2] = r8g8bx_derive(r, g); /* b */ |
||||
dst[3] = 255; /* a */ |
||||
dst += 4; |
||||
} |
||||
src_row += src_stride; |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; y += 1) { |
||||
const float *src = src_row; |
||||
uint16_t *dst = (uint16_t *)dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint16_t value = 0; |
||||
|
||||
value |= (uint16_t)(((int8_t)(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; |
||||
value |= (uint16_t)((((int8_t)(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ; |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
|
||||
*dst++ = value; |
||||
|
||||
src += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
|
||||
for(y = 0; y < height; y += 1) { |
||||
const uint8_t *src = src_row; |
||||
uint16_t *dst = (uint16_t *)dst_row; |
||||
for(x = 0; x < width; x += 1) { |
||||
uint16_t value = 0; |
||||
|
||||
value |= src[0] >> 1; |
||||
value |= (src[1] >> 1) << 8; |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
|
||||
*dst++ = value; |
||||
|
||||
src += 4; |
||||
} |
||||
dst_row += dst_stride; |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j) |
||||
{ |
||||
uint16_t value = *(const uint16_t *)src; |
||||
int16_t r, g; |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
|
||||
r = ((int16_t)(value << 8)) >> 8; |
||||
g = ((int16_t)(value << 0)) >> 8; |
||||
|
||||
dst[0] = r * (1.0f/0x7f); /* r */ |
||||
dst[1] = g * (1.0f/0x7f); /* g */ |
||||
dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */ |
||||
dst[3] = 1.0f; /* a */ |
||||
} |
@ -0,0 +1,232 @@ |
||||
/*
|
||||
* Copyright (C) 2011 Marek Olšák <maraeo@gmail.com> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J.
|
||||
* Available here: http://www.opengl-redbook.com/appendices/
|
||||
* The algorithm in the book contains a bug though, which is fixed in the code |
||||
* below. |
||||
*/ |
||||
|
||||
#define UF11(e, m) ((e << 6) | (m)) |
||||
#define UF11_EXPONENT_BIAS 15 |
||||
#define UF11_EXPONENT_BITS 0x1F |
||||
#define UF11_EXPONENT_SHIFT 6 |
||||
#define UF11_MANTISSA_BITS 0x3F |
||||
#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT) |
||||
#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT) |
||||
|
||||
#define UF10(e, m) ((e << 5) | (m)) |
||||
#define UF10_EXPONENT_BIAS 15 |
||||
#define UF10_EXPONENT_BITS 0x1F |
||||
#define UF10_EXPONENT_SHIFT 5 |
||||
#define UF10_MANTISSA_BITS 0x1F |
||||
#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT) |
||||
#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT) |
||||
|
||||
#define F32_INFINITY 0x7f800000 |
||||
|
||||
static INLINE unsigned f32_to_uf11(float val) |
||||
{ |
||||
union { |
||||
float f; |
||||
uint32_t ui; |
||||
} f32 = {val}; |
||||
|
||||
uint16_t uf11 = 0; |
||||
|
||||
/* Decode little-endian 32-bit floating-point value */ |
||||
int sign = (f32.ui >> 16) & 0x8000; |
||||
/* Map exponent to the range [-127,128] */ |
||||
int exponent = ((f32.ui >> 23) & 0xff) - 127; |
||||
int mantissa = f32.ui & 0x007fffff; |
||||
|
||||
if (exponent == 128) { /* Infinity or NaN */ |
||||
/* From the GL_EXT_packed_float spec:
|
||||
* |
||||
* "Additionally: negative infinity is converted to zero; positive |
||||
* infinity is converted to positive infinity; and both positive and |
||||
* negative NaN are converted to positive NaN." |
||||
*/ |
||||
uf11 = UF11_MAX_EXPONENT; |
||||
if (mantissa) { |
||||
uf11 |= 1; /* NaN */ |
||||
} else { |
||||
if (sign) |
||||
uf11 = 0; /* 0.0 */ |
||||
} |
||||
} else if (sign) { |
||||
return 0; |
||||
} else if (val > 65024.0f) { |
||||
/* From the GL_EXT_packed_float spec:
|
||||
* |
||||
* "Likewise, finite positive values greater than 65024 (the maximum |
||||
* finite representable unsigned 11-bit floating-point value) are |
||||
* converted to 65024." |
||||
*/ |
||||
uf11 = UF11(30, 63); |
||||
} |
||||
else if (exponent > -15) { /* Representable value */ |
||||
exponent += UF11_EXPONENT_BIAS; |
||||
mantissa >>= UF11_MANTISSA_SHIFT; |
||||
uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa; |
||||
} |
||||
|
||||
return uf11; |
||||
} |
||||
|
||||
static INLINE float uf11_to_f32(uint16_t val) |
||||
{ |
||||
union { |
||||
float f; |
||||
uint32_t ui; |
||||
} f32; |
||||
|
||||
int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT; |
||||
int mantissa = (val & 0x003f); |
||||
|
||||
f32.f = 0.0; |
||||
|
||||
if (exponent == 0) { |
||||
if (mantissa != 0) { |
||||
const float scale = 1.0 / (1 << 20); |
||||
f32.f = scale * mantissa; |
||||
} |
||||
} |
||||
else if (exponent == 31) { |
||||
f32.ui = F32_INFINITY | mantissa; |
||||
} |
||||
else { |
||||
float scale, decimal; |
||||
exponent -= 15; |
||||
if (exponent < 0) { |
||||
scale = 1.0f / (1 << -exponent); |
||||
} |
||||
else { |
||||
scale = (float) (1 << exponent); |
||||
} |
||||
decimal = 1.0f + (float) mantissa / 64; |
||||
f32.f = scale * decimal; |
||||
} |
||||
|
||||
return f32.f; |
||||
} |
||||
|
||||
static INLINE unsigned f32_to_uf10(float val) |
||||
{ |
||||
union { |
||||
float f; |
||||
uint32_t ui; |
||||
} f32 = {val}; |
||||
|
||||
uint16_t uf10 = 0; |
||||
|
||||
/* Decode little-endian 32-bit floating-point value */ |
||||
int sign = (f32.ui >> 16) & 0x8000; |
||||
/* Map exponent to the range [-127,128] */ |
||||
int exponent = ((f32.ui >> 23) & 0xff) - 127; |
||||
int mantissa = f32.ui & 0x007fffff; |
||||
|
||||
if (exponent == 128) { |
||||
/* From the GL_EXT_packed_float spec:
|
||||
* |
||||
* "Additionally: negative infinity is converted to zero; positive |
||||
* infinity is converted to positive infinity; and both positive and |
||||
* negative NaN are converted to positive NaN." |
||||
*/ |
||||
uf10 = UF10_MAX_EXPONENT; |
||||
if (mantissa) { |
||||
uf10 |= 1; /* NaN */ |
||||
} else { |
||||
if (sign) |
||||
uf10 = 0; /* 0.0 */ |
||||
} |
||||
} else if (sign) { |
||||
return 0; |
||||
} else if (val > 64512.0f) { |
||||
/* From the GL_EXT_packed_float spec:
|
||||
* |
||||
* "Likewise, finite positive values greater than 64512 (the maximum |
||||
* finite representable unsigned 10-bit floating-point value) are |
||||
* converted to 64512." |
||||
*/ |
||||
uf10 = UF10(30, 31); |
||||
} |
||||
else if (exponent > -15) { /* Representable value */ |
||||
exponent += UF10_EXPONENT_BIAS; |
||||
mantissa >>= UF10_MANTISSA_SHIFT; |
||||
uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa; |
||||
} |
||||
|
||||
return uf10; |
||||
} |
||||
|
||||
static INLINE float uf10_to_f32(uint16_t val) |
||||
{ |
||||
union { |
||||
float f; |
||||
uint32_t ui; |
||||
} f32; |
||||
|
||||
int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT; |
||||
int mantissa = (val & 0x001f); |
||||
|
||||
f32.f = 0.0; |
||||
|
||||
if (exponent == 0) { |
||||
if (mantissa != 0) { |
||||
const float scale = 1.0 / (1 << 20); |
||||
f32.f = scale * mantissa; |
||||
} |
||||
} |
||||
else if (exponent == 31) { |
||||
f32.ui = F32_INFINITY | mantissa; |
||||
} |
||||
else { |
||||
float scale, decimal; |
||||
exponent -= 15; |
||||
if (exponent < 0) { |
||||
scale = 1.0f / (1 << -exponent); |
||||
} |
||||
else { |
||||
scale = (float) (1 << exponent); |
||||
} |
||||
decimal = 1.0f + (float) mantissa / 32; |
||||
f32.f = scale * decimal; |
||||
} |
||||
|
||||
return f32.f; |
||||
} |
||||
|
||||
static INLINE unsigned float3_to_r11g11b10f(const float rgb[3]) |
||||
{ |
||||
return ( f32_to_uf11(rgb[0]) & 0x7ff) | |
||||
((f32_to_uf11(rgb[1]) & 0x7ff) << 11) | |
||||
((f32_to_uf10(rgb[2]) & 0x3ff) << 22); |
||||
} |
||||
|
||||
static INLINE void r11g11b10f_to_float3(unsigned rgb, float retval[3]) |
||||
{ |
||||
retval[0] = uf11_to_f32( rgb & 0x7ff); |
||||
retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff); |
||||
retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff); |
||||
} |
@ -0,0 +1,164 @@ |
||||
/*
|
||||
* Copyright (C) 2011 Marek Olšák <maraeo@gmail.com> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
/* Copied from EXT_texture_shared_exponent and edited. */ |
||||
|
||||
#ifndef RGB9E5_H |
||||
#define RGB9E5_H |
||||
|
||||
#include <math.h> |
||||
#include <assert.h> |
||||
|
||||
#define RGB9E5_EXPONENT_BITS 5 |
||||
#define RGB9E5_MANTISSA_BITS 9 |
||||
#define RGB9E5_EXP_BIAS 15 |
||||
#define RGB9E5_MAX_VALID_BIASED_EXP 31 |
||||
|
||||
#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) |
||||
#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS) |
||||
#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1) |
||||
#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP)) |
||||
#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS)) |
||||
|
||||
typedef union { |
||||
unsigned int raw; |
||||
float value; |
||||
struct { |
||||
#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) |
||||
unsigned int negative:1; |
||||
unsigned int biasedexponent:8; |
||||
unsigned int mantissa:23; |
||||
#else |
||||
unsigned int mantissa:23; |
||||
unsigned int biasedexponent:8; |
||||
unsigned int negative:1; |
||||
#endif |
||||
} field; |
||||
} float754; |
||||
|
||||
typedef union { |
||||
unsigned int raw; |
||||
struct { |
||||
#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) |
||||
unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; |
||||
unsigned int b:RGB9E5_MANTISSA_BITS; |
||||
unsigned int g:RGB9E5_MANTISSA_BITS; |
||||
unsigned int r:RGB9E5_MANTISSA_BITS; |
||||
#else |
||||
unsigned int r:RGB9E5_MANTISSA_BITS; |
||||
unsigned int g:RGB9E5_MANTISSA_BITS; |
||||
unsigned int b:RGB9E5_MANTISSA_BITS; |
||||
unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; |
||||
#endif |
||||
} field; |
||||
} rgb9e5; |
||||
|
||||
static INLINE float rgb9e5_ClampRange(float x) |
||||
{ |
||||
if (x > 0.0) { |
||||
if (x >= MAX_RGB9E5) { |
||||
return MAX_RGB9E5; |
||||
} else { |
||||
return x; |
||||
} |
||||
} else { |
||||
/* NaN gets here too since comparisons with NaN always fail! */ |
||||
return 0.0; |
||||
} |
||||
} |
||||
|
||||
/* Ok, FloorLog2 is not correct for the denorm and zero values, but we
|
||||
are going to do a max of this value with the minimum rgb9e5 exponent |
||||
that will hide these problem cases. */ |
||||
static INLINE int rgb9e5_FloorLog2(float x) |
||||
{ |
||||
float754 f; |
||||
|
||||
f.value = x; |
||||
return (f.field.biasedexponent - 127); |
||||
} |
||||
|
||||
static INLINE unsigned float3_to_rgb9e5(const float rgb[3]) |
||||
{ |
||||
rgb9e5 retval; |
||||
float maxrgb; |
||||
int rm, gm, bm; |
||||
float rc, gc, bc; |
||||
int exp_shared, maxm; |
||||
double denom; |
||||
|
||||
rc = rgb9e5_ClampRange(rgb[0]); |
||||
gc = rgb9e5_ClampRange(rgb[1]); |
||||
bc = rgb9e5_ClampRange(rgb[2]); |
||||
|
||||
maxrgb = MAX3(rc, gc, bc); |
||||
exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; |
||||
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); |
||||
assert(exp_shared >= 0); |
||||
/* This pow function could be replaced by a table. */ |
||||
denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); |
||||
|
||||
maxm = (int) floor(maxrgb / denom + 0.5); |
||||
if (maxm == MAX_RGB9E5_MANTISSA+1) { |
||||
denom *= 2; |
||||
exp_shared += 1; |
||||
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); |
||||
} else { |
||||
assert(maxm <= MAX_RGB9E5_MANTISSA); |
||||
} |
||||
|
||||
rm = (int) floor(rc / denom + 0.5); |
||||
gm = (int) floor(gc / denom + 0.5); |
||||
bm = (int) floor(bc / denom + 0.5); |
||||
|
||||
assert(rm <= MAX_RGB9E5_MANTISSA); |
||||
assert(gm <= MAX_RGB9E5_MANTISSA); |
||||
assert(bm <= MAX_RGB9E5_MANTISSA); |
||||
assert(rm >= 0); |
||||
assert(gm >= 0); |
||||
assert(bm >= 0); |
||||
|
||||
retval.field.r = rm; |
||||
retval.field.g = gm; |
||||
retval.field.b = bm; |
||||
retval.field.biasedexponent = exp_shared; |
||||
|
||||
return retval.raw; |
||||
} |
||||
|
||||
static INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3]) |
||||
{ |
||||
rgb9e5 v; |
||||
int exponent; |
||||
float scale; |
||||
|
||||
v.raw = rgb; |
||||
exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; |
||||
scale = (float) pow(2, exponent); |
||||
|
||||
retval[0] = v.field.r * scale; |
||||
retval[1] = v.field.g * scale; |
||||
retval[2] = v.field.b * scale; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,171 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright (C) 2011 Red Hat Inc. |
||||
* |
||||
* 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 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#include <stdio.h> |
||||
#include "u_math.h" |
||||
#include "u_format.h" |
||||
#include "u_format_rgtc.h" |
||||
#include "util/rgtc.h" |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row,
|
||||
unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
fprintf(stderr,"%s\n", __func__); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1); |
||||
} |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
} |
||||
|
@ -0,0 +1,732 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
||||
* Copyright (c) 2008 VMware, Inc. |
||||
* |
||||
* 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 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#include "u_math.h" |
||||
#include "u_format.h" |
||||
#include "u_format_s3tc.h" |
||||
#include "u_format_srgb.h" |
||||
|
||||
|
||||
static void |
||||
util_format_dxt1_rgb_fetch_stub(int src_stride, |
||||
const uint8_t *src, |
||||
int col, int row, |
||||
uint8_t *dst) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
|
||||
static void |
||||
util_format_dxt1_rgba_fetch_stub(int src_stride, |
||||
const uint8_t *src, |
||||
int col, int row, |
||||
uint8_t *dst ) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
|
||||
static void |
||||
util_format_dxt3_rgba_fetch_stub(int src_stride, |
||||
const uint8_t *src, |
||||
int col, int row, |
||||
uint8_t *dst ) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
|
||||
static void |
||||
util_format_dxt5_rgba_fetch_stub(int src_stride, |
||||
const uint8_t *src, |
||||
int col, int row, |
||||
uint8_t *dst ) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
|
||||
static void |
||||
util_format_dxtn_pack_stub(int src_comps, |
||||
int width, int height, |
||||
const uint8_t *src, |
||||
enum util_format_dxtn dst_format, |
||||
uint8_t *dst, |
||||
int dst_stride) |
||||
{ |
||||
assert(0); |
||||
} |
||||
|
||||
|
||||
boolean util_format_s3tc_enabled = FALSE; |
||||
|
||||
util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = util_format_dxt1_rgb_fetch_stub; |
||||
util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = util_format_dxt1_rgba_fetch_stub; |
||||
util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = util_format_dxt3_rgba_fetch_stub; |
||||
util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = util_format_dxt5_rgba_fetch_stub; |
||||
|
||||
util_format_dxtn_pack_t util_format_dxtn_pack = util_format_dxtn_pack_stub; |
||||
|
||||
|
||||
void |
||||
util_format_s3tc_init(void) |
||||
{ |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Pixel fetch. |
||||
*/ |
||||
|
||||
void |
||||
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
util_format_dxt1_rgb_fetch(0, src, i, j, dst); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
util_format_dxt1_rgba_fetch(0, src, i, j, dst); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
util_format_dxt3_rgba_fetch(0, src, i, j, dst); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
util_format_dxt5_rgba_fetch(0, src, i, j, dst); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgb_fetch(0, src, i, j, tmp); |
||||
dst[0] = ubyte_to_float(tmp[0]); |
||||
dst[1] = ubyte_to_float(tmp[1]); |
||||
dst[2] = ubyte_to_float(tmp[2]); |
||||
dst[3] = 1.0; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = ubyte_to_float(tmp[0]); |
||||
dst[1] = ubyte_to_float(tmp[1]); |
||||
dst[2] = ubyte_to_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt3_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = ubyte_to_float(tmp[0]); |
||||
dst[1] = ubyte_to_float(tmp[1]); |
||||
dst[2] = ubyte_to_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt5_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = ubyte_to_float(tmp[0]); |
||||
dst[1] = ubyte_to_float(tmp[1]); |
||||
dst[2] = ubyte_to_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Block decompression. |
||||
*/ |
||||
|
||||
static INLINE void |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height, |
||||
util_format_dxtn_fetch_t fetch, |
||||
unsigned block_size, boolean srgb) |
||||
{ |
||||
const unsigned bw = 4, bh = 4, comps = 4; |
||||
unsigned x, y, i, j; |
||||
for(y = 0; y < height; y += bh) { |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += bw) { |
||||
for(j = 0; j < bh; ++j) { |
||||
for(i = 0; i < bw; ++i) { |
||||
uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps; |
||||
fetch(0, src, i, j, dst); |
||||
if (srgb) { |
||||
dst[0] = util_format_srgb_to_linear_8unorm(dst[0]); |
||||
dst[1] = util_format_srgb_to_linear_8unorm(dst[1]); |
||||
dst[2] = util_format_srgb_to_linear_8unorm(dst[2]); |
||||
} |
||||
} |
||||
} |
||||
src += block_size; |
||||
} |
||||
src_row += src_stride; |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgb_fetch, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgba_fetch, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt3_rgba_fetch, |
||||
16, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt5_rgba_fetch, |
||||
16, FALSE); |
||||
} |
||||
|
||||
static INLINE void |
||||
util_format_dxtn_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height, |
||||
util_format_dxtn_fetch_t fetch, |
||||
unsigned block_size, boolean srgb) |
||||
{ |
||||
unsigned x, y, i, j; |
||||
for(y = 0; y < height; y += 4) { |
||||
const uint8_t *src = src_row; |
||||
for(x = 0; x < width; x += 4) { |
||||
for(j = 0; j < 4; ++j) { |
||||
for(i = 0; i < 4; ++i) { |
||||
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; |
||||
uint8_t tmp[4]; |
||||
fetch(0, src, i, j, tmp); |
||||
if (srgb) { |
||||
dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]); |
||||
dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]); |
||||
dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]); |
||||
} |
||||
else { |
||||
dst[0] = ubyte_to_float(tmp[0]); |
||||
dst[1] = ubyte_to_float(tmp[1]); |
||||
dst[2] = ubyte_to_float(tmp[2]); |
||||
} |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
} |
||||
src += block_size; |
||||
} |
||||
src_row += src_stride; |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgb_fetch, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgba_fetch, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt3_rgba_fetch, |
||||
16, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt5_rgba_fetch, |
||||
16, FALSE); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Block compression. |
||||
*/ |
||||
|
||||
static INLINE void |
||||
util_format_dxtn_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src, unsigned src_stride, |
||||
unsigned width, unsigned height, |
||||
enum util_format_dxtn format, |
||||
unsigned block_size, boolean srgb) |
||||
{ |
||||
const unsigned bw = 4, bh = 4, comps = 4; |
||||
unsigned x, y, i, j, k; |
||||
for(y = 0; y < height; y += bh) { |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += bw) { |
||||
uint8_t tmp[4][4][4]; /* [bh][bw][comps] */ |
||||
for(j = 0; j < bh; ++j) { |
||||
for(i = 0; i < bw; ++i) { |
||||
uint8_t src_tmp; |
||||
for(k = 0; k < 3; ++k) { |
||||
src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + k]; |
||||
if (srgb) { |
||||
tmp[j][i][k] = util_format_linear_to_srgb_8unorm(src_tmp); |
||||
} |
||||
else { |
||||
tmp[j][i][k] = src_tmp; |
||||
} |
||||
} |
||||
/* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */ |
||||
tmp[j][i][3] = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + 3]; |
||||
} |
||||
} |
||||
/* even for dxt1_rgb have 4 src comps */ |
||||
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0); |
||||
dst += block_size; |
||||
} |
||||
dst_row += dst_stride / sizeof(*dst_row); |
||||
} |
||||
|
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGB, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGBA, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT3_RGBA, |
||||
16, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT5_RGBA, |
||||
16, FALSE); |
||||
} |
||||
|
||||
static INLINE void |
||||
util_format_dxtn_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src, unsigned src_stride, |
||||
unsigned width, unsigned height, |
||||
enum util_format_dxtn format, |
||||
unsigned block_size, boolean srgb) |
||||
{ |
||||
unsigned x, y, i, j, k; |
||||
for(y = 0; y < height; y += 4) { |
||||
uint8_t *dst = dst_row; |
||||
for(x = 0; x < width; x += 4) { |
||||
uint8_t tmp[4][4][4]; |
||||
for(j = 0; j < 4; ++j) { |
||||
for(i = 0; i < 4; ++i) { |
||||
float src_tmp; |
||||
for(k = 0; k < 3; ++k) { |
||||
src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]; |
||||
if (srgb) { |
||||
tmp[j][i][k] = util_format_linear_float_to_srgb_8unorm(src_tmp); |
||||
} |
||||
else { |
||||
tmp[j][i][k] = float_to_ubyte(src_tmp); |
||||
} |
||||
} |
||||
/* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */ |
||||
src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + 3]; |
||||
tmp[j][i][3] = float_to_ubyte(src_tmp); |
||||
} |
||||
} |
||||
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0); |
||||
dst += block_size; |
||||
} |
||||
dst_row += 4*dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGB, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGBA, |
||||
8, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT3_RGBA, |
||||
16, FALSE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride, |
||||
width, height, UTIL_FORMAT_DXT5_RGBA, |
||||
16, FALSE); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* SRGB variants. |
||||
*/ |
||||
|
||||
void |
||||
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgb_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]); |
||||
dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]); |
||||
dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]); |
||||
dst[3] = 255; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]); |
||||
dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]); |
||||
dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]); |
||||
dst[3] = tmp[3]; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt3_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]); |
||||
dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]); |
||||
dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]); |
||||
dst[3] = tmp[3]; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt5_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]); |
||||
dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]); |
||||
dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]); |
||||
dst[3] = tmp[3]; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgb_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]); |
||||
dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]); |
||||
dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]); |
||||
dst[3] = 1.0f; |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt1_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]); |
||||
dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]); |
||||
dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt3_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]); |
||||
dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]); |
||||
dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) |
||||
{ |
||||
uint8_t tmp[4]; |
||||
util_format_dxt5_rgba_fetch(0, src, i, j, tmp); |
||||
dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]); |
||||
dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]); |
||||
dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]); |
||||
dst[3] = ubyte_to_float(tmp[3]); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgb_fetch, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgba_fetch, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt3_rgba_fetch, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt5_rgba_fetch, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgb_fetch, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt1_rgba_fetch, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt3_rgba_fetch, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height, |
||||
util_format_dxt5_rgba_fetch, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGB, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGBA, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT3_RGBA, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT5_RGBA, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGB, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT1_RGBA, |
||||
8, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT3_RGBA, |
||||
16, TRUE); |
||||
} |
||||
|
||||
void |
||||
util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, |
||||
width, height, UTIL_FORMAT_DXT5_RGBA, |
||||
16, TRUE); |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,973 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
#include "u_debug.h" |
||||
#include "u_math.h" |
||||
#include "u_format_zs.h" |
||||
|
||||
|
||||
/*
|
||||
* z32_unorm conversion functions |
||||
*/ |
||||
|
||||
static INLINE uint16_t |
||||
z32_unorm_to_z16_unorm(uint32_t z) |
||||
{ |
||||
/* z * 0xffff / 0xffffffff */ |
||||
return z >> 16; |
||||
} |
||||
|
||||
static INLINE uint32_t |
||||
z16_unorm_to_z32_unorm(uint16_t z) |
||||
{ |
||||
/* z * 0xffffffff / 0xffff */ |
||||
return (z << 16) | z; |
||||
} |
||||
|
||||
static INLINE uint32_t |
||||
z32_unorm_to_z24_unorm(uint32_t z) |
||||
{ |
||||
/* z * 0xffffff / 0xffffffff */ |
||||
return z >> 8; |
||||
} |
||||
|
||||
static INLINE uint32_t |
||||
z24_unorm_to_z32_unorm(uint32_t z) |
||||
{ |
||||
/* z * 0xffffffff / 0xffffff */ |
||||
return (z << 8) | (z >> 16); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* z32_float conversion functions |
||||
*/ |
||||
|
||||
static INLINE uint16_t |
||||
z32_float_to_z16_unorm(float z) |
||||
{ |
||||
const float scale = 0xffff; |
||||
return (uint16_t)(z * scale + 0.5f); |
||||
} |
||||
|
||||
static INLINE float |
||||
z16_unorm_to_z32_float(uint16_t z) |
||||
{ |
||||
const float scale = 1.0 / 0xffff; |
||||
return (float)(z * scale); |
||||
} |
||||
|
||||
static INLINE uint32_t |
||||
z32_float_to_z24_unorm(float z) |
||||
{ |
||||
const double scale = 0xffffff; |
||||
return (uint32_t)(z * scale) & 0xffffff; |
||||
} |
||||
|
||||
static INLINE float |
||||
z24_unorm_to_z32_float(uint32_t z) |
||||
{ |
||||
const double scale = 1.0 / 0xffffff; |
||||
return (float)(z * scale); |
||||
} |
||||
|
||||
static INLINE uint32_t |
||||
z32_float_to_z32_unorm(float z) |
||||
{ |
||||
const double scale = 0xffffffff; |
||||
return (uint32_t)(z * scale); |
||||
} |
||||
|
||||
static INLINE float |
||||
z32_unorm_to_z32_float(uint32_t z) |
||||
{ |
||||
const double scale = 1.0 / 0xffffffff; |
||||
return (float)(z * scale); |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint16_t *src = (const uint16_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint16_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
*dst++ = z16_unorm_to_z32_float(value); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint16_t *dst = (uint16_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint16_t value; |
||||
value = z32_float_to_z16_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const uint16_t *src = (const uint16_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint16_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
*dst++ = z16_unorm_to_z32_unorm(value); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
uint16_t *dst = (uint16_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint16_t value; |
||||
value = z32_unorm_to_z16_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap16(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z32_unorm_to_z32_float(value); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value; |
||||
value = z32_float_to_z32_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width * 4); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width * 4); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width * 4); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned y; |
||||
for(y = 0; y < height; ++y) { |
||||
memcpy(dst_row, src_row, width * 4); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const float *src = (const float *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst++ = z32_float_to_z32_unorm(*src++); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
float *dst = (float *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst++ = z32_unorm_to_z32_float(*src++); |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_float(value & 0xffffff); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0xff000000; |
||||
value |= z32_float_to_z24_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_unorm(value & 0xffffff); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value= *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0xff000000; |
||||
value |= z32_unorm_to_z24_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint8_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value >> 24; |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint8_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0x00ffffff; |
||||
value |= *src++ << 24; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_float(value >> 8); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0x000000ff; |
||||
value |= z32_float_to_z24_unorm(*src++) << 8; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_unorm(value >> 8); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0x000000ff; |
||||
value |= *src++ & 0xffffff00; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint8_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value & 0xff; |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint8_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *dst; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
value &= 0xffffff00; |
||||
value |= *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_float(value & 0xffffff); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value; |
||||
value = z32_float_to_z24_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_unorm(value & 0xffffff); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value; |
||||
value = z32_unorm_to_z24_unorm(*src++); |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const uint32_t *src = (uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_float(value >> 8); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value; |
||||
value = z32_float_to_z24_unorm(*src++) << 8; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const uint32_t *src = (const uint32_t *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value = *src++; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = z24_unorm_to_z32_unorm(value >> 8); |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
uint32_t *dst = (uint32_t *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
uint32_t value; |
||||
value = z32_unorm_to_z24_unorm(*src++) << 8; |
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
value = util_bswap32(value); |
||||
#endif |
||||
*dst++ = value; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_z_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
float *dst = dst_row; |
||||
const float *src = (const float *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst = *src; |
||||
src += 2; |
||||
dst += 1; |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const float *src = src_row; |
||||
float *dst = (float *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst = *src; |
||||
src += 1; |
||||
dst += 2; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint32_t *dst = dst_row; |
||||
const float *src = (const float *)src_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst = z32_float_to_z32_unorm(*src); |
||||
src += 2; |
||||
dst += 1; |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint32_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint32_t *src = src_row; |
||||
float *dst = (float *)dst_row; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst++ = z32_unorm_to_z32_float(*src++); |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
uint8_t *dst = dst_row; |
||||
const uint8_t *src = src_row + 4; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst = *src; |
||||
src += 8; |
||||
dst += 1; |
||||
} |
||||
src_row += src_stride/sizeof(*src_row); |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
} |
||||
} |
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
unsigned x, y; |
||||
for(y = 0; y < height; ++y) { |
||||
const uint8_t *src = src_row; |
||||
uint8_t *dst = dst_row + 4; |
||||
for(x = 0; x < width; ++x) { |
||||
*dst = *src; |
||||
src += 1; |
||||
dst += 8; |
||||
} |
||||
dst_row += dst_stride/sizeof(*dst_row); |
||||
src_row += src_stride/sizeof(*src_row); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_format_x24s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_z24_unorm_s8_uint_unpack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_x24s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_z24_unorm_s8_uint_pack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_s8_uint_z24_unorm_unpack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) |
||||
{ |
||||
util_format_s8_uint_z24_unorm_pack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
} |
||||
|
||||
void |
||||
util_format_x32_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_z32_float_s8x24_uint_unpack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
|
||||
} |
||||
|
||||
void |
||||
util_format_x32_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
util_format_z32_float_s8x24_uint_pack_s_8uint(dst_row, dst_stride, |
||||
src_row, src_stride, |
||||
width, height); |
||||
} |
@ -0,0 +1,137 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 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 "pipe/p_config.h" |
||||
#include "util/u_math.h" |
||||
#include "util/u_cpu_detect.h" |
||||
|
||||
#if defined(PIPE_ARCH_SSE) |
||||
#include <xmmintrin.h> |
||||
/* This is defined in pmmintrin.h, but it can only be included when -msse3 is
|
||||
* used, so just define it here to avoid further. */ |
||||
#define _MM_DENORMALS_ZERO_MASK 0x0040 |
||||
#endif |
||||
|
||||
|
||||
/** 2^x, for x in [-1.0, 1.0) */ |
||||
float pow2_table[POW2_TABLE_SIZE]; |
||||
|
||||
|
||||
static void |
||||
init_pow2_table(void) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < POW2_TABLE_SIZE; i++) |
||||
pow2_table[i] = (float) pow(2.0, (i - POW2_TABLE_OFFSET) / POW2_TABLE_SCALE); |
||||
} |
||||
|
||||
|
||||
/** log2(x), for x in [1.0, 2.0) */ |
||||
float log2_table[LOG2_TABLE_SIZE]; |
||||
|
||||
|
||||
static void
|
||||
init_log2_table(void) |
||||
{ |
||||
unsigned i; |
||||
for (i = 0; i < LOG2_TABLE_SIZE; i++) |
||||
log2_table[i] = (float) log2(1.0 + i * (1.0 / LOG2_TABLE_SCALE)); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* One time init for math utilities. |
||||
*/ |
||||
void |
||||
util_init_math(void) |
||||
{ |
||||
static boolean initialized = FALSE; |
||||
if (!initialized) { |
||||
init_pow2_table(); |
||||
init_log2_table(); |
||||
initialized = TRUE; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Fetches the contents of the fpstate (mxcsr on x86) register. |
||||
* |
||||
* On platforms without support for it just returns 0. |
||||
*/ |
||||
unsigned |
||||
util_fpstate_get(void) |
||||
{ |
||||
unsigned mxcsr = 0; |
||||
|
||||
#if defined(PIPE_ARCH_SSE) |
||||
if (util_cpu_caps.has_sse) { |
||||
mxcsr = _mm_getcsr(); |
||||
} |
||||
#endif |
||||
|
||||
return mxcsr; |
||||
} |
||||
|
||||
/**
|
||||
* Make sure that the fp treats the denormalized floating |
||||
* point numbers as zero. |
||||
* |
||||
* This is the behavior required by D3D10. OpenGL doesn't care. |
||||
*/ |
||||
unsigned |
||||
util_fpstate_set_denorms_to_zero(unsigned current_mxcsr) |
||||
{ |
||||
#if defined(PIPE_ARCH_SSE) |
||||
if (util_cpu_caps.has_sse) { |
||||
/* Enable flush to zero mode */ |
||||
current_mxcsr |= _MM_FLUSH_ZERO_MASK; |
||||
if (util_cpu_caps.has_daz) { |
||||
/* Enable denormals are zero mode */ |
||||
current_mxcsr |= _MM_DENORMALS_ZERO_MASK; |
||||
} |
||||
util_fpstate_set(current_mxcsr); |
||||
} |
||||
#endif |
||||
return current_mxcsr; |
||||
} |
||||
|
||||
/**
|
||||
* Set the state of the fpstate (mxcsr on x86) register. |
||||
* |
||||
* On platforms without support for it's a noop. |
||||
*/ |
||||
void |
||||
util_fpstate_set(unsigned mxcsr) |
||||
{ |
||||
#if defined(PIPE_ARCH_SSE) |
||||
if (util_cpu_caps.has_sse) { |
||||
_mm_setcsr(mxcsr); |
||||
} |
||||
#endif |
||||
} |
@ -0,0 +1,104 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 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_RECT_H |
||||
#define U_RECT_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "util/u_math.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct u_rect { |
||||
int x0, x1; |
||||
int y0, y1; |
||||
}; |
||||
|
||||
/* Do two rectangles intersect?
|
||||
*/ |
||||
static INLINE boolean |
||||
u_rect_test_intersection(const struct u_rect *a, |
||||
const struct u_rect *b) |
||||
{ |
||||
return (!(a->x1 < b->x0 || |
||||
b->x1 < a->x0 || |
||||
a->y1 < b->y0 || |
||||
b->y1 < a->y0)); |
||||
} |
||||
|
||||
/* Find the intersection of two rectangles known to intersect.
|
||||
*/ |
||||
static INLINE void |
||||
u_rect_find_intersection(const struct u_rect *a, |
||||
struct u_rect *b) |
||||
{ |
||||
/* Caller should verify intersection exists before calling.
|
||||
*/ |
||||
if (b->x0 < a->x0) b->x0 = a->x0; |
||||
if (b->x1 > a->x1) b->x1 = a->x1; |
||||
if (b->y0 < a->y0) b->y0 = a->y0; |
||||
if (b->y1 > a->y1) b->y1 = a->y1; |
||||
} |
||||
|
||||
|
||||
static INLINE int |
||||
u_rect_area(const struct u_rect *r) |
||||
{ |
||||
return (r->x1 - r->x0) * (r->y1 - r->y0); |
||||
} |
||||
|
||||
static INLINE void |
||||
u_rect_possible_intersection(const struct u_rect *a, |
||||
struct u_rect *b) |
||||
{ |
||||
if (u_rect_test_intersection(a,b)) { |
||||
u_rect_find_intersection(a,b); |
||||
} |
||||
else { |
||||
b->x0 = b->x1 = b->y0 = b->y1 = 0; |
||||
} |
||||
} |
||||
|
||||
/* Set @d to a rectangle that covers both @a and @b.
|
||||
*/ |
||||
static INLINE void |
||||
u_rect_union(struct u_rect *d, const struct u_rect *a, const struct u_rect *b) |
||||
{ |
||||
d->x0 = MIN2(a->x0, b->x0); |
||||
d->y0 = MIN2(a->y0, b->y0); |
||||
d->x1 = MAX2(a->x1, b->x1); |
||||
d->y1 = MAX2(a->y1, b->y1); |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_RECT_H */ |
@ -0,0 +1,684 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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 |
||||
* Surface utility functions. |
||||
*
|
||||
* @author Brian Paul |
||||
*/ |
||||
|
||||
|
||||
#include "pipe/p_defines.h" |
||||
#include "pipe/p_screen.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
#include "util/u_format.h" |
||||
#include "util/u_inlines.h" |
||||
#include "util/u_rect.h" |
||||
#include "util/u_surface.h" |
||||
#include "util/u_pack_color.h" |
||||
|
||||
|
||||
/**
|
||||
* Initialize a pipe_surface object. 'view' is considered to have |
||||
* uninitialized contents. |
||||
*/ |
||||
void |
||||
u_surface_default_template(struct pipe_surface *surf, |
||||
const struct pipe_resource *texture) |
||||
{ |
||||
memset(surf, 0, sizeof(*surf)); |
||||
|
||||
surf->format = texture->format; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Copy 2D rect from one place to another. |
||||
* Position and sizes are in pixels. |
||||
* src_stride may be negative to do vertical flip of pixels from source. |
||||
*/ |
||||
void |
||||
util_copy_rect(ubyte * dst, |
||||
enum pipe_format format, |
||||
unsigned dst_stride, |
||||
unsigned dst_x, |
||||
unsigned dst_y, |
||||
unsigned width, |
||||
unsigned height, |
||||
const ubyte * src, |
||||
int src_stride, |
||||
unsigned src_x, |
||||
unsigned src_y) |
||||
{ |
||||
unsigned i; |
||||
int src_stride_pos = src_stride < 0 ? -src_stride : src_stride; |
||||
int blocksize = util_format_get_blocksize(format); |
||||
int blockwidth = util_format_get_blockwidth(format); |
||||
int blockheight = util_format_get_blockheight(format); |
||||
|
||||
assert(blocksize > 0); |
||||
assert(blockwidth > 0); |
||||
assert(blockheight > 0); |
||||
|
||||
dst_x /= blockwidth; |
||||
dst_y /= blockheight; |
||||
width = (width + blockwidth - 1)/blockwidth; |
||||
height = (height + blockheight - 1)/blockheight; |
||||
src_x /= blockwidth; |
||||
src_y /= blockheight; |
||||
|
||||
dst += dst_x * blocksize; |
||||
src += src_x * blocksize; |
||||
dst += dst_y * dst_stride; |
||||
src += src_y * src_stride_pos; |
||||
width *= blocksize; |
||||
|
||||
if (width == dst_stride && width == src_stride) |
||||
memcpy(dst, src, height * width); |
||||
else { |
||||
for (i = 0; i < height; i++) { |
||||
memcpy(dst, src, width); |
||||
dst += dst_stride; |
||||
src += src_stride; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Copy 3D box from one place to another. |
||||
* Position and sizes are in pixels. |
||||
*/ |
||||
void |
||||
util_copy_box(ubyte * dst, |
||||
enum pipe_format format, |
||||
unsigned dst_stride, unsigned dst_slice_stride, |
||||
unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||||
unsigned width, unsigned height, unsigned depth, |
||||
const ubyte * src, |
||||
int src_stride, unsigned src_slice_stride, |
||||
unsigned src_x, unsigned src_y, unsigned src_z) |
||||
{ |
||||
unsigned z; |
||||
dst += dst_z * dst_slice_stride; |
||||
src += src_z * src_slice_stride; |
||||
for (z = 0; z < depth; ++z) { |
||||
util_copy_rect(dst, |
||||
format, |
||||
dst_stride, |
||||
dst_x, dst_y, |
||||
width, height, |
||||
src, |
||||
src_stride, |
||||
src_x, src_y); |
||||
|
||||
dst += dst_slice_stride; |
||||
src += src_slice_stride; |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_fill_rect(ubyte * dst, |
||||
enum pipe_format format, |
||||
unsigned dst_stride, |
||||
unsigned dst_x, |
||||
unsigned dst_y, |
||||
unsigned width, |
||||
unsigned height, |
||||
union util_color *uc) |
||||
{ |
||||
const struct util_format_description *desc = util_format_description(format); |
||||
unsigned i, j; |
||||
unsigned width_size; |
||||
int blocksize = desc->block.bits / 8; |
||||
int blockwidth = desc->block.width; |
||||
int blockheight = desc->block.height; |
||||
|
||||
assert(blocksize > 0); |
||||
assert(blockwidth > 0); |
||||
assert(blockheight > 0); |
||||
|
||||
dst_x /= blockwidth; |
||||
dst_y /= blockheight; |
||||
width = (width + blockwidth - 1)/blockwidth; |
||||
height = (height + blockheight - 1)/blockheight; |
||||
|
||||
dst += dst_x * blocksize; |
||||
dst += dst_y * dst_stride; |
||||
width_size = width * blocksize; |
||||
|
||||
switch (blocksize) { |
||||
case 1: |
||||
if(dst_stride == width_size) |
||||
memset(dst, uc->ub, height * width_size); |
||||
else { |
||||
for (i = 0; i < height; i++) { |
||||
memset(dst, uc->ub, width_size); |
||||
dst += dst_stride; |
||||
} |
||||
} |
||||
break; |
||||
case 2: |
||||
for (i = 0; i < height; i++) { |
||||
uint16_t *row = (uint16_t *)dst; |
||||
for (j = 0; j < width; j++) |
||||
*row++ = uc->us; |
||||
dst += dst_stride; |
||||
} |
||||
break; |
||||
case 4: |
||||
for (i = 0; i < height; i++) { |
||||
uint32_t *row = (uint32_t *)dst; |
||||
for (j = 0; j < width; j++) |
||||
*row++ = uc->ui[0]; |
||||
dst += dst_stride; |
||||
} |
||||
break; |
||||
default: |
||||
for (i = 0; i < height; i++) { |
||||
ubyte *row = dst; |
||||
for (j = 0; j < width; j++) { |
||||
memcpy(row, uc, blocksize); |
||||
row += blocksize; |
||||
} |
||||
dst += dst_stride; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
util_fill_box(ubyte * dst, |
||||
enum pipe_format format, |
||||
unsigned stride, |
||||
unsigned layer_stride, |
||||
unsigned x, |
||||
unsigned y, |
||||
unsigned z, |
||||
unsigned width, |
||||
unsigned height, |
||||
unsigned depth, |
||||
union util_color *uc) |
||||
{ |
||||
unsigned layer; |
||||
dst += z * layer_stride; |
||||
for (layer = z; layer < depth; layer++) { |
||||
util_fill_rect(dst, format, |
||||
stride, |
||||
x, y, width, height, uc); |
||||
dst += layer_stride; |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Fallback function for pipe->resource_copy_region(). |
||||
* Note: (X,Y)=(0,0) is always the upper-left corner. |
||||
*/ |
||||
void |
||||
util_resource_copy_region(struct pipe_context *pipe, |
||||
struct pipe_resource *dst, |
||||
unsigned dst_level, |
||||
unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||||
struct pipe_resource *src, |
||||
unsigned src_level, |
||||
const struct pipe_box *src_box) |
||||
{ |
||||
struct pipe_transfer *src_trans, *dst_trans; |
||||
uint8_t *dst_map; |
||||
const uint8_t *src_map; |
||||
enum pipe_format src_format, dst_format; |
||||
struct pipe_box dst_box; |
||||
|
||||
assert(src && dst); |
||||
if (!src || !dst) |
||||
return; |
||||
|
||||
assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || |
||||
(src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); |
||||
|
||||
src_format = src->format; |
||||
dst_format = dst->format; |
||||
|
||||
assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); |
||||
assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); |
||||
assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); |
||||
|
||||
src_map = pipe->transfer_map(pipe, |
||||
src, |
||||
src_level, |
||||
PIPE_TRANSFER_READ, |
||||
src_box, &src_trans); |
||||
assert(src_map); |
||||
if (!src_map) { |
||||
goto no_src_map; |
||||
} |
||||
|
||||
dst_box.x = dst_x; |
||||
dst_box.y = dst_y; |
||||
dst_box.z = dst_z; |
||||
dst_box.width = src_box->width; |
||||
dst_box.height = src_box->height; |
||||
dst_box.depth = src_box->depth; |
||||
|
||||
dst_map = pipe->transfer_map(pipe, |
||||
dst, |
||||
dst_level, |
||||
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
||||
&dst_box, &dst_trans); |
||||
assert(dst_map); |
||||
if (!dst_map) { |
||||
goto no_dst_map; |
||||
} |
||||
|
||||
if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { |
||||
assert(src_box->height == 1); |
||||
assert(src_box->depth == 1); |
||||
memcpy(dst_map, src_map, src_box->width); |
||||
} else { |
||||
util_copy_box(dst_map, |
||||
dst_format, |
||||
dst_trans->stride, dst_trans->layer_stride, |
||||
0, 0, 0, |
||||
src_box->width, src_box->height, src_box->depth, |
||||
src_map, |
||||
src_trans->stride, src_trans->layer_stride, |
||||
0, 0, 0); |
||||
} |
||||
|
||||
pipe->transfer_unmap(pipe, dst_trans); |
||||
no_dst_map: |
||||
pipe->transfer_unmap(pipe, src_trans); |
||||
no_src_map: |
||||
; |
||||
} |
||||
|
||||
|
||||
|
||||
#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) |
||||
|
||||
|
||||
/**
|
||||
* Fallback for pipe->clear_render_target() function. |
||||
* XXX this looks too hackish to be really useful. |
||||
* cpp > 4 looks like a gross hack at best... |
||||
* Plus can't use these transfer fallbacks when clearing |
||||
* multisampled surfaces for instance. |
||||
* Clears all bound layers. |
||||
*/ |
||||
void |
||||
util_clear_render_target(struct pipe_context *pipe, |
||||
struct pipe_surface *dst, |
||||
const union pipe_color_union *color, |
||||
unsigned dstx, unsigned dsty, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
struct pipe_transfer *dst_trans; |
||||
ubyte *dst_map; |
||||
union util_color uc; |
||||
unsigned max_layer; |
||||
|
||||
assert(dst->texture); |
||||
if (!dst->texture) |
||||
return; |
||||
|
||||
if (dst->texture->target == PIPE_BUFFER) { |
||||
/*
|
||||
* The fill naturally works on the surface format, however |
||||
* the transfer uses resource format which is just bytes for buffers. |
||||
*/ |
||||
unsigned dx, w; |
||||
unsigned pixstride = util_format_get_blocksize(dst->format); |
||||
dx = (dst->u.buf.first_element + dstx) * pixstride; |
||||
w = width * pixstride; |
||||
max_layer = 0; |
||||
dst_map = pipe_transfer_map(pipe, |
||||
dst->texture, |
||||
0, 0, |
||||
PIPE_TRANSFER_WRITE, |
||||
dx, 0, w, 1, |
||||
&dst_trans); |
||||
} |
||||
else { |
||||
max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer; |
||||
dst_map = pipe_transfer_map_3d(pipe, |
||||
dst->texture, |
||||
dst->u.tex.level, |
||||
PIPE_TRANSFER_WRITE, |
||||
dstx, dsty, dst->u.tex.first_layer, |
||||
width, height, max_layer + 1, &dst_trans); |
||||
} |
||||
|
||||
assert(dst_map); |
||||
|
||||
if (dst_map) { |
||||
enum pipe_format format = dst->format; |
||||
assert(dst_trans->stride > 0); |
||||
|
||||
if (util_format_is_pure_integer(format)) { |
||||
/*
|
||||
* We expect int/uint clear values here, though some APIs |
||||
* might disagree (but in any case util_pack_color() |
||||
* couldn't handle it)... |
||||
*/ |
||||
if (util_format_is_pure_sint(format)) { |
||||
util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); |
||||
} |
||||
else { |
||||
assert(util_format_is_pure_uint(format)); |
||||
util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); |
||||
} |
||||
} |
||||
else { |
||||
util_pack_color(color->f, dst->format, &uc); |
||||
} |
||||
|
||||
util_fill_box(dst_map, dst->format, |
||||
dst_trans->stride, dst_trans->layer_stride, |
||||
0, 0, 0, width, height, max_layer + 1, &uc); |
||||
|
||||
pipe->transfer_unmap(pipe, dst_trans); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Fallback for pipe->clear_stencil() function. |
||||
* sw fallback doesn't look terribly useful here. |
||||
* Plus can't use these transfer fallbacks when clearing |
||||
* multisampled surfaces for instance. |
||||
* Clears all bound layers. |
||||
*/ |
||||
void |
||||
util_clear_depth_stencil(struct pipe_context *pipe, |
||||
struct pipe_surface *dst, |
||||
unsigned clear_flags, |
||||
double depth, |
||||
unsigned stencil, |
||||
unsigned dstx, unsigned dsty, |
||||
unsigned width, unsigned height) |
||||
{ |
||||
enum pipe_format format = dst->format; |
||||
struct pipe_transfer *dst_trans; |
||||
ubyte *dst_map; |
||||
boolean need_rmw = FALSE; |
||||
unsigned max_layer, layer; |
||||
|
||||
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && |
||||
((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && |
||||
util_format_is_depth_and_stencil(format)) |
||||
need_rmw = TRUE; |
||||
|
||||
assert(dst->texture); |
||||
if (!dst->texture) |
||||
return; |
||||
|
||||
max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer; |
||||
dst_map = pipe_transfer_map_3d(pipe, |
||||
dst->texture, |
||||
dst->u.tex.level, |
||||
(need_rmw ? PIPE_TRANSFER_READ_WRITE : |
||||
PIPE_TRANSFER_WRITE), |
||||
dstx, dsty, dst->u.tex.first_layer, |
||||
width, height, max_layer + 1, &dst_trans); |
||||
assert(dst_map); |
||||
|
||||
if (dst_map) { |
||||
unsigned dst_stride = dst_trans->stride; |
||||
uint64_t zstencil = util_pack64_z_stencil(format, depth, stencil); |
||||
ubyte *dst_layer = dst_map; |
||||
unsigned i, j; |
||||
assert(dst_trans->stride > 0); |
||||
|
||||
for (layer = 0; layer <= max_layer; layer++) { |
||||
dst_map = dst_layer; |
||||
|
||||
switch (util_format_get_blocksize(format)) { |
||||
case 1: |
||||
assert(format == PIPE_FORMAT_S8_UINT); |
||||
if(dst_stride == width) |
||||
memset(dst_map, (uint8_t) zstencil, height * width); |
||||
else { |
||||
for (i = 0; i < height; i++) { |
||||
memset(dst_map, (uint8_t) zstencil, width); |
||||
dst_map += dst_stride; |
||||
} |
||||
} |
||||
break; |
||||
case 2: |
||||
assert(format == PIPE_FORMAT_Z16_UNORM); |
||||
for (i = 0; i < height; i++) { |
||||
uint16_t *row = (uint16_t *)dst_map; |
||||
for (j = 0; j < width; j++) |
||||
*row++ = (uint16_t) zstencil; |
||||
dst_map += dst_stride; |
||||
} |
||||
break; |
||||
case 4: |
||||
if (!need_rmw) { |
||||
for (i = 0; i < height; i++) { |
||||
uint32_t *row = (uint32_t *)dst_map; |
||||
for (j = 0; j < width; j++) |
||||
*row++ = (uint32_t) zstencil; |
||||
dst_map += dst_stride; |
||||
} |
||||
} |
||||
else { |
||||
uint32_t dst_mask; |
||||
if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT) |
||||
dst_mask = 0x00ffffff; |
||||
else { |
||||
assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM); |
||||
dst_mask = 0xffffff00; |
||||
} |
||||
if (clear_flags & PIPE_CLEAR_DEPTH) |
||||
dst_mask = ~dst_mask; |
||||
for (i = 0; i < height; i++) { |
||||
uint32_t *row = (uint32_t *)dst_map; |
||||
for (j = 0; j < width; j++) { |
||||
uint32_t tmp = *row & dst_mask; |
||||
*row++ = tmp | ((uint32_t) zstencil & ~dst_mask); |
||||
} |
||||
dst_map += dst_stride; |
||||
} |
||||
} |
||||
break; |
||||
case 8: |
||||
if (!need_rmw) { |
||||
for (i = 0; i < height; i++) { |
||||
uint64_t *row = (uint64_t *)dst_map; |
||||
for (j = 0; j < width; j++) |
||||
*row++ = zstencil; |
||||
dst_map += dst_stride; |
||||
} |
||||
} |
||||
else { |
||||
uint64_t src_mask; |
||||
|
||||
if (clear_flags & PIPE_CLEAR_DEPTH) |
||||
src_mask = 0x00000000ffffffffull; |
||||
else |
||||
src_mask = 0x000000ff00000000ull; |
||||
|
||||
for (i = 0; i < height; i++) { |
||||
uint64_t *row = (uint64_t *)dst_map; |
||||
for (j = 0; j < width; j++) { |
||||
uint64_t tmp = *row & ~src_mask; |
||||
*row++ = tmp | (zstencil & src_mask); |
||||
} |
||||
dst_map += dst_stride; |
||||
} |
||||
} |
||||
break; |
||||
default: |
||||
assert(0); |
||||
break; |
||||
} |
||||
dst_layer += dst_trans->layer_stride; |
||||
} |
||||
|
||||
pipe->transfer_unmap(pipe, dst_trans); |
||||
} |
||||
} |
||||
|
||||
|
||||
/* Return if the box is totally inside the resource.
|
||||
*/ |
||||
static boolean |
||||
is_box_inside_resource(const struct pipe_resource *res, |
||||
const struct pipe_box *box, |
||||
unsigned level) |
||||
{ |
||||
unsigned width = 1, height = 1, depth = 1; |
||||
|
||||
switch (res->target) { |
||||
case PIPE_BUFFER: |
||||
width = res->width0; |
||||
height = 1; |
||||
depth = 1; |
||||
break; |
||||
case PIPE_TEXTURE_1D: |
||||
width = u_minify(res->width0, level); |
||||
height = 1; |
||||
depth = 1; |
||||
break; |
||||
case PIPE_TEXTURE_2D: |
||||
case PIPE_TEXTURE_RECT: |
||||
width = u_minify(res->width0, level); |
||||
height = u_minify(res->height0, level); |
||||
depth = 1; |
||||
break; |
||||
case PIPE_TEXTURE_3D: |
||||
width = u_minify(res->width0, level); |
||||
height = u_minify(res->height0, level); |
||||
depth = u_minify(res->depth0, level); |
||||
break; |
||||
case PIPE_TEXTURE_CUBE: |
||||
width = u_minify(res->width0, level); |
||||
height = u_minify(res->height0, level); |
||||
depth = 6; |
||||
break; |
||||
case PIPE_TEXTURE_1D_ARRAY: |
||||
width = u_minify(res->width0, level); |
||||
height = 1; |
||||
depth = res->array_size; |
||||
break; |
||||
case PIPE_TEXTURE_2D_ARRAY: |
||||
width = u_minify(res->width0, level); |
||||
height = u_minify(res->height0, level); |
||||
depth = res->array_size; |
||||
break; |
||||
case PIPE_TEXTURE_CUBE_ARRAY: |
||||
width = u_minify(res->width0, level); |
||||
height = u_minify(res->height0, level); |
||||
depth = res->array_size; |
||||
assert(res->array_size % 6 == 0); |
||||
break; |
||||
case PIPE_MAX_TEXTURE_TYPES:; |
||||
} |
||||
|
||||
return box->x >= 0 && |
||||
box->x + box->width <= (int) width && |
||||
box->y >= 0 && |
||||
box->y + box->height <= (int) height && |
||||
box->z >= 0 && |
||||
box->z + box->depth <= (int) depth; |
||||
} |
||||
|
||||
static unsigned |
||||
get_sample_count(const struct pipe_resource *res) |
||||
{ |
||||
return res->nr_samples ? res->nr_samples : 1; |
||||
} |
||||
|
||||
/**
|
||||
* Try to do a blit using resource_copy_region. The function calls |
||||
* resource_copy_region if the blit description is compatible with it. |
||||
* |
||||
* It returns TRUE if the blit was done using resource_copy_region. |
||||
* |
||||
* It returns FALSE otherwise and the caller must fall back to a more generic |
||||
* codepath for the blit operation. (e.g. by using u_blitter) |
||||
*/ |
||||
boolean |
||||
util_try_blit_via_copy_region(struct pipe_context *ctx, |
||||
const struct pipe_blit_info *blit) |
||||
{ |
||||
unsigned mask = util_format_get_mask(blit->dst.format); |
||||
|
||||
/* No format conversions. */ |
||||
if (blit->src.resource->format != blit->src.format || |
||||
blit->dst.resource->format != blit->dst.format || |
||||
!util_is_format_compatible( |
||||
util_format_description(blit->src.resource->format), |
||||
util_format_description(blit->dst.resource->format))) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* No masks, no filtering, no scissor. */ |
||||
if ((blit->mask & mask) != mask || |
||||
blit->filter != PIPE_TEX_FILTER_NEAREST || |
||||
blit->scissor_enable) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* No flipping. */ |
||||
if (blit->src.box.width < 0 || |
||||
blit->src.box.height < 0 || |
||||
blit->src.box.depth < 0) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* No scaling. */ |
||||
if (blit->src.box.width != blit->dst.box.width || |
||||
blit->src.box.height != blit->dst.box.height || |
||||
blit->src.box.depth != blit->dst.box.depth) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* No out-of-bounds access. */ |
||||
if (!is_box_inside_resource(blit->src.resource, &blit->src.box, |
||||
blit->src.level) || |
||||
!is_box_inside_resource(blit->dst.resource, &blit->dst.box, |
||||
blit->dst.level)) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* Sample counts must match. */ |
||||
if (get_sample_count(blit->src.resource) != |
||||
get_sample_count(blit->dst.resource)) { |
||||
return FALSE; |
||||
} |
||||
|
||||
ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level, |
||||
blit->dst.box.x, blit->dst.box.y, blit->dst.box.z, |
||||
blit->src.resource, blit->src.level, |
||||
&blit->src.box); |
||||
return TRUE; |
||||
} |
Loading…
Reference in new issue