parent
03e3116a75
commit
b6f2d8f531
@ -0,0 +1,328 @@ |
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* 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 |
||||||
|
* Generic bitmask implementation. |
||||||
|
*
|
||||||
|
* @author Jose Fonseca <jfonseca@vmware.com> |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "pipe/p_compiler.h" |
||||||
|
#include "util/u_debug.h" |
||||||
|
|
||||||
|
#include "util/u_memory.h" |
||||||
|
#include "util/u_bitmask.h" |
||||||
|
|
||||||
|
|
||||||
|
typedef uint32_t util_bitmask_word;
|
||||||
|
|
||||||
|
|
||||||
|
#define UTIL_BITMASK_INITIAL_WORDS 16 |
||||||
|
#define UTIL_BITMASK_BITS_PER_BYTE 8 |
||||||
|
#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE) |
||||||
|
|
||||||
|
|
||||||
|
struct util_bitmask |
||||||
|
{ |
||||||
|
util_bitmask_word *words; |
||||||
|
|
||||||
|
/** Number of bits we can currently hold */ |
||||||
|
unsigned size; |
||||||
|
|
||||||
|
/** Number of consecutive bits set at the start of the bitmask */ |
||||||
|
unsigned filled; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
struct util_bitmask * |
||||||
|
util_bitmask_create(void) |
||||||
|
{ |
||||||
|
struct util_bitmask *bm; |
||||||
|
|
||||||
|
bm = MALLOC_STRUCT(util_bitmask); |
||||||
|
if(!bm) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
bm->words = (util_bitmask_word *)CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word)); |
||||||
|
if(!bm->words) { |
||||||
|
FREE(bm); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
bm->filled = 0; |
||||||
|
|
||||||
|
return bm; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the bitmask if necessary
|
||||||
|
*/ |
||||||
|
static INLINE boolean |
||||||
|
util_bitmask_resize(struct util_bitmask *bm, |
||||||
|
unsigned minimum_index) |
||||||
|
{ |
||||||
|
unsigned minimum_size = minimum_index + 1; |
||||||
|
unsigned new_size; |
||||||
|
util_bitmask_word *new_words; |
||||||
|
|
||||||
|
/* Check integer overflow */ |
||||||
|
if(!minimum_size) |
||||||
|
return FALSE; |
||||||
|
|
||||||
|
if(bm->size >= minimum_size) |
||||||
|
return TRUE; |
||||||
|
|
||||||
|
assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0); |
||||||
|
new_size = bm->size; |
||||||
|
while(new_size < minimum_size) { |
||||||
|
new_size *= 2; |
||||||
|
/* Check integer overflow */ |
||||||
|
if(new_size < bm->size) |
||||||
|
return FALSE; |
||||||
|
} |
||||||
|
assert(new_size); |
||||||
|
assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0); |
||||||
|
|
||||||
|
new_words = (util_bitmask_word *)REALLOC((void *)bm->words, |
||||||
|
bm->size / UTIL_BITMASK_BITS_PER_BYTE, |
||||||
|
new_size / UTIL_BITMASK_BITS_PER_BYTE); |
||||||
|
if(!new_words) |
||||||
|
return FALSE; |
||||||
|
|
||||||
|
memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD,
|
||||||
|
0,
|
||||||
|
(new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE); |
||||||
|
|
||||||
|
bm->size = new_size; |
||||||
|
bm->words = new_words; |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazily update the filled. |
||||||
|
*/ |
||||||
|
static INLINE void |
||||||
|
util_bitmask_filled_set(struct util_bitmask *bm, |
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
assert(bm->filled <= bm->size); |
||||||
|
assert(index < bm->size); |
||||||
|
|
||||||
|
if(index == bm->filled) { |
||||||
|
++bm->filled; |
||||||
|
assert(bm->filled <= bm->size); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static INLINE void |
||||||
|
util_bitmask_filled_unset(struct util_bitmask *bm, |
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
assert(bm->filled <= bm->size); |
||||||
|
assert(index < bm->size); |
||||||
|
|
||||||
|
if(index < bm->filled) |
||||||
|
bm->filled = index; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
unsigned |
||||||
|
util_bitmask_add(struct util_bitmask *bm) |
||||||
|
{ |
||||||
|
unsigned word; |
||||||
|
unsigned bit; |
||||||
|
util_bitmask_word mask; |
||||||
|
|
||||||
|
assert(bm); |
||||||
|
|
||||||
|
/* linear search for an empty index */ |
||||||
|
word = bm->filled / UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
mask = 1 << bit; |
||||||
|
while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { |
||||||
|
while(bit < UTIL_BITMASK_BITS_PER_WORD) { |
||||||
|
if(!(bm->words[word] & mask)) |
||||||
|
goto found; |
||||||
|
++bm->filled; |
||||||
|
++bit; |
||||||
|
mask <<= 1; |
||||||
|
} |
||||||
|
++word; |
||||||
|
bit = 0; |
||||||
|
mask = 1; |
||||||
|
} |
||||||
|
found: |
||||||
|
|
||||||
|
/* grow the bitmask if necessary */ |
||||||
|
if(!util_bitmask_resize(bm, bm->filled)) |
||||||
|
return UTIL_BITMASK_INVALID_INDEX; |
||||||
|
|
||||||
|
assert(!(bm->words[word] & mask)); |
||||||
|
bm->words[word] |= mask; |
||||||
|
|
||||||
|
return bm->filled++; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
unsigned |
||||||
|
util_bitmask_set(struct util_bitmask *bm,
|
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
unsigned word; |
||||||
|
unsigned bit; |
||||||
|
util_bitmask_word mask; |
||||||
|
|
||||||
|
assert(bm); |
||||||
|
|
||||||
|
/* grow the bitmask if necessary */ |
||||||
|
if(!util_bitmask_resize(bm, index)) |
||||||
|
return UTIL_BITMASK_INVALID_INDEX; |
||||||
|
|
||||||
|
word = index / UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
bit = index % UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
mask = 1 << bit; |
||||||
|
|
||||||
|
bm->words[word] |= mask; |
||||||
|
|
||||||
|
util_bitmask_filled_set(bm, index); |
||||||
|
|
||||||
|
return index; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void |
||||||
|
util_bitmask_clear(struct util_bitmask *bm,
|
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
unsigned word; |
||||||
|
unsigned bit; |
||||||
|
util_bitmask_word mask; |
||||||
|
|
||||||
|
assert(bm); |
||||||
|
|
||||||
|
if(index >= bm->size) |
||||||
|
return; |
||||||
|
|
||||||
|
word = index / UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
bit = index % UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
mask = 1 << bit; |
||||||
|
|
||||||
|
bm->words[word] &= ~mask; |
||||||
|
|
||||||
|
util_bitmask_filled_unset(bm, index); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
boolean |
||||||
|
util_bitmask_get(struct util_bitmask *bm,
|
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
util_bitmask_word mask = 1 << bit; |
||||||
|
|
||||||
|
assert(bm); |
||||||
|
|
||||||
|
if(index < bm->filled) { |
||||||
|
assert(bm->words[word] & mask); |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
if(index >= bm->size) |
||||||
|
return FALSE; |
||||||
|
|
||||||
|
if(bm->words[word] & mask) { |
||||||
|
util_bitmask_filled_set(bm, index); |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
else |
||||||
|
return FALSE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
unsigned |
||||||
|
util_bitmask_get_next_index(struct util_bitmask *bm,
|
||||||
|
unsigned index) |
||||||
|
{ |
||||||
|
unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; |
||||||
|
util_bitmask_word mask = 1 << bit; |
||||||
|
|
||||||
|
if(index < bm->filled) { |
||||||
|
assert(bm->words[word] & mask); |
||||||
|
return index; |
||||||
|
} |
||||||
|
|
||||||
|
if(index >= bm->size) { |
||||||
|
return UTIL_BITMASK_INVALID_INDEX; |
||||||
|
} |
||||||
|
|
||||||
|
/* Do a linear search */ |
||||||
|
while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { |
||||||
|
while(bit < UTIL_BITMASK_BITS_PER_WORD) { |
||||||
|
if(bm->words[word] & mask) { |
||||||
|
if(index == bm->filled) { |
||||||
|
++bm->filled; |
||||||
|
assert(bm->filled <= bm->size); |
||||||
|
} |
||||||
|
return index; |
||||||
|
} |
||||||
|
++index; |
||||||
|
++bit; |
||||||
|
mask <<= 1; |
||||||
|
} |
||||||
|
++word; |
||||||
|
bit = 0; |
||||||
|
mask = 1; |
||||||
|
} |
||||||
|
|
||||||
|
return UTIL_BITMASK_INVALID_INDEX; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
unsigned |
||||||
|
util_bitmask_get_first_index(struct util_bitmask *bm) |
||||||
|
{ |
||||||
|
return util_bitmask_get_next_index(bm, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void |
||||||
|
util_bitmask_destroy(struct util_bitmask *bm) |
||||||
|
{ |
||||||
|
assert(bm); |
||||||
|
|
||||||
|
FREE(bm->words); |
||||||
|
FREE(bm); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,110 @@ |
|||||||
|
/**************************************************************************
|
||||||
|
* |
||||||
|
* Copyright 2008 VMware, Inc. |
||||||
|
* All Rights Reserved. |
||||||
|
* Copyright 2008 VMware, Inc. All rights reserved. |
||||||
|
* Copyright 2009 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, 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 |
||||||
|
* Texture mapping utility functions. |
||||||
|
* |
||||||
|
* @author Brian Paul |
||||||
|
* Marek Olšák |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "pipe/p_defines.h" |
||||||
|
|
||||||
|
#include "util/u_debug.h" |
||||||
|
#include "util/u_texture.h" |
||||||
|
|
||||||
|
void util_map_texcoords2d_onto_cubemap(unsigned face, |
||||||
|
const float *in_st, unsigned in_stride, |
||||||
|
float *out_str, unsigned out_stride, |
||||||
|
boolean allow_scale) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
float rx, ry, rz; |
||||||
|
|
||||||
|
/* loop over quad verts */ |
||||||
|
for (i = 0; i < 4; i++) { |
||||||
|
/* Compute sc = +/-scale and tc = +/-scale.
|
||||||
|
* Not +/-1 to avoid cube face selection ambiguity near the edges, |
||||||
|
* though that can still sometimes happen with this scale factor... |
||||||
|
* |
||||||
|
* XXX: Yep, there is no safe scale factor that will prevent sampling |
||||||
|
* the neighbouring face when stretching out. A more reliable solution |
||||||
|
* would be to clamp (sc, tc) against +/- 1.0-1.0/mipsize, in the shader. |
||||||
|
* |
||||||
|
* Also, this is not necessary when minifying, or 1:1 blits. |
||||||
|
*/ |
||||||
|
const float scale = allow_scale ? 0.9999f : 1.0f; |
||||||
|
const float sc = (2 * in_st[0] - 1) * scale; |
||||||
|
const float tc = (2 * in_st[1] - 1) * scale; |
||||||
|
|
||||||
|
switch (face) { |
||||||
|
case PIPE_TEX_FACE_POS_X: |
||||||
|
rx = 1; |
||||||
|
ry = -tc; |
||||||
|
rz = -sc; |
||||||
|
break; |
||||||
|
case PIPE_TEX_FACE_NEG_X: |
||||||
|
rx = -1; |
||||||
|
ry = -tc; |
||||||
|
rz = sc; |
||||||
|
break; |
||||||
|
case PIPE_TEX_FACE_POS_Y: |
||||||
|
rx = sc; |
||||||
|
ry = 1; |
||||||
|
rz = tc; |
||||||
|
break; |
||||||
|
case PIPE_TEX_FACE_NEG_Y: |
||||||
|
rx = sc; |
||||||
|
ry = -1; |
||||||
|
rz = -tc; |
||||||
|
break; |
||||||
|
case PIPE_TEX_FACE_POS_Z: |
||||||
|
rx = sc; |
||||||
|
ry = -tc; |
||||||
|
rz = 1; |
||||||
|
break; |
||||||
|
case PIPE_TEX_FACE_NEG_Z: |
||||||
|
rx = -sc; |
||||||
|
ry = -tc; |
||||||
|
rz = -1; |
||||||
|
break; |
||||||
|
default: |
||||||
|
rx = ry = rz = 0; |
||||||
|
assert(0); |
||||||
|
} |
||||||
|
|
||||||
|
out_str[0] = rx; /*s*/ |
||||||
|
out_str[1] = ry; /*t*/ |
||||||
|
out_str[2] = rz; /*r*/ |
||||||
|
|
||||||
|
in_st += in_stride; |
||||||
|
out_str += out_stride; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue