@@ -151,6 +151,10 @@ struct r300_texture_format_state { | |||
struct r300_sampler_view { | |||
struct pipe_sampler_view base; | |||
/* Swizzles in the UTIL_FORMAT_SWIZZLE_* representation, | |||
* derived from base. */ | |||
unsigned char swizzle[4]; | |||
/* Copy of r300_texture::texture_format_state with format-specific bits | |||
* added. */ | |||
struct r300_texture_format_state format; | |||
@@ -166,6 +170,13 @@ struct r300_texture_fb_state { | |||
uint32_t zb_format; /* R300_ZB_FORMAT */ | |||
}; | |||
struct r300_texture_sampler_state { | |||
struct r300_texture_format_state format; | |||
uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ | |||
uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ | |||
uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ | |||
}; | |||
struct r300_textures_state { | |||
/* Textures. */ | |||
struct r300_sampler_view *sampler_views[16]; | |||
@@ -177,12 +188,7 @@ struct r300_textures_state { | |||
/* This is the merge of the texture and sampler states. */ | |||
unsigned count; | |||
uint32_t tx_enable; /* R300_TX_ENABLE: 0x4101 */ | |||
struct r300_texture_sampler_state { | |||
struct r300_texture_format_state format; | |||
uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ | |||
uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ | |||
uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ | |||
} regs[16]; | |||
struct r300_texture_sampler_state regs[16]; | |||
}; | |||
struct r300_vertex_stream_state { |
@@ -137,6 +137,7 @@ static void get_external_state( | |||
{ | |||
struct r300_textures_state *texstate = r300->textures_state.state; | |||
unsigned i; | |||
unsigned char *swizzle; | |||
for (i = 0; i < texstate->sampler_state_count; i++) { | |||
struct r300_sampler_state* s = texstate->sampler_states[i]; | |||
@@ -148,9 +149,16 @@ static void get_external_state( | |||
if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { | |||
state->unit[i].compare_mode_enabled = 1; | |||
/* XXX Gallium doesn't provide us with any information regarding | |||
* this mode, so we are screwed. Let's set INTENSITY for now. */ | |||
state->unit[i].depth_texture_swizzle = RC_SWIZZLE_XYZW; | |||
/* Pass depth texture swizzling to the compiler. */ | |||
if (texstate->sampler_views[i]) { | |||
swizzle = texstate->sampler_views[i]->swizzle; | |||
state->unit[i].depth_texture_swizzle = | |||
RC_MAKE_SWIZZLE(swizzle[0], swizzle[1], | |||
swizzle[2], swizzle[3]); | |||
} else { | |||
state->unit[i].depth_texture_swizzle = RC_SWIZZLE_XYZW; | |||
} | |||
/* Fortunately, no need to translate this. */ | |||
state->unit[i].texture_compare_func = s->state.compare_func; |
@@ -1021,7 +1021,6 @@ r300_create_sampler_view(struct pipe_context *pipe, | |||
{ | |||
struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); | |||
struct r300_texture *tex = r300_texture(texture); | |||
unsigned char swizzle[4]; | |||
if (view) { | |||
view->base = *templ; | |||
@@ -1030,14 +1029,14 @@ r300_create_sampler_view(struct pipe_context *pipe, | |||
view->base.texture = NULL; | |||
pipe_resource_reference(&view->base.texture, texture); | |||
swizzle[0] = templ->swizzle_r; | |||
swizzle[1] = templ->swizzle_g; | |||
swizzle[2] = templ->swizzle_b; | |||
swizzle[3] = templ->swizzle_a; | |||
view->swizzle[0] = templ->swizzle_r; | |||
view->swizzle[1] = templ->swizzle_g; | |||
view->swizzle[2] = templ->swizzle_b; | |||
view->swizzle[3] = templ->swizzle_a; | |||
view->format = tex->tx_format; | |||
view->format.format1 |= r300_translate_texformat(templ->format, | |||
swizzle); | |||
view->swizzle); | |||
if (r300_screen(pipe->screen)->caps.is_r500) { | |||
view->format.format2 |= r500_tx_format_msb_bit(templ->format); | |||
} |
@@ -34,6 +34,7 @@ | |||
#include "r300_state.h" | |||
#include "r300_state_derived.h" | |||
#include "r300_state_inlines.h" | |||
#include "r300_texture.h" | |||
#include "r300_vs.h" | |||
/* r300_state_derived: Various bits of state which are dependent upon | |||
@@ -493,6 +494,12 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) | |||
unsigned min_level, max_level, i, size; | |||
unsigned count = MIN2(state->sampler_view_count, | |||
state->sampler_state_count); | |||
unsigned char depth_swizzle[4] = { | |||
UTIL_FORMAT_SWIZZLE_X, | |||
UTIL_FORMAT_SWIZZLE_X, | |||
UTIL_FORMAT_SWIZZLE_X, | |||
UTIL_FORMAT_SWIZZLE_X | |||
}; | |||
state->tx_enable = 0; | |||
state->count = 0; | |||
@@ -512,6 +519,20 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) | |||
texstate->filter1 = sampler->filter1; | |||
texstate->border_color = sampler->border_color; | |||
/* If compare mode is disabled, the sampler view swizzles | |||
* are stored in the format. | |||
* Otherwise, swizzles must be applied after the compare mode | |||
* in the fragment shader. */ | |||
if (util_format_is_depth_or_stencil(tex->b.b.format)) { | |||
if (sampler->state.compare_mode == PIPE_TEX_COMPARE_NONE) { | |||
texstate->format.format1 |= | |||
r300_get_swizzle_combined(depth_swizzle, view->swizzle); | |||
} else { | |||
texstate->format.format1 |= | |||
r300_get_swizzle_combined(depth_swizzle, 0); | |||
} | |||
} | |||
/* to emulate 1D textures through 2D ones correctly */ | |||
if (tex->b.b.target == PIPE_TEXTURE_1D) { | |||
texstate->filter0 &= ~R300_TX_WRAP_T_MASK; |
@@ -47,6 +47,60 @@ static const unsigned microblock_table[5][3][2] = { | |||
{{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ | |||
}; | |||
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, | |||
const unsigned char *swizzle_view) | |||
{ | |||
unsigned i; | |||
unsigned char swizzle[4]; | |||
unsigned result = 0; | |||
const uint32_t swizzle_shift[4] = { | |||
R300_TX_FORMAT_R_SHIFT, | |||
R300_TX_FORMAT_G_SHIFT, | |||
R300_TX_FORMAT_B_SHIFT, | |||
R300_TX_FORMAT_A_SHIFT | |||
}; | |||
const uint32_t swizzle_bit[4] = { | |||
R300_TX_FORMAT_X, | |||
R300_TX_FORMAT_Y, | |||
R300_TX_FORMAT_Z, | |||
R300_TX_FORMAT_W | |||
}; | |||
if (swizzle_view) { | |||
/* Combine two sets of swizzles. */ | |||
for (i = 0; i < 4; i++) { | |||
swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ? | |||
swizzle_format[swizzle_view[i]] : swizzle_view[i]; | |||
} | |||
} else { | |||
memcpy(swizzle, swizzle_format, 4); | |||
} | |||
/* Get swizzle. */ | |||
for (i = 0; i < 4; i++) { | |||
switch (swizzle[i]) { | |||
case UTIL_FORMAT_SWIZZLE_Y: | |||
result |= swizzle_bit[1] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_Z: | |||
result |= swizzle_bit[2] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_W: | |||
result |= swizzle_bit[3] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_0: | |||
result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_1: | |||
result |= R300_TX_FORMAT_ONE << swizzle_shift[i]; | |||
break; | |||
default: /* UTIL_FORMAT_SWIZZLE_X */ | |||
result |= swizzle_bit[0] << swizzle_shift[i]; | |||
} | |||
} | |||
return result; | |||
} | |||
/* Translate a pipe_format into a useful texture format for sampling. | |||
* | |||
* Some special formats are translated directly using R300_EASY_TX_FORMAT, | |||
@@ -66,38 +120,26 @@ uint32_t r300_translate_texformat(enum pipe_format format, | |||
const struct util_format_description *desc; | |||
unsigned i; | |||
boolean uniform = TRUE; | |||
const uint32_t swizzle_shift[4] = { | |||
R300_TX_FORMAT_R_SHIFT, | |||
R300_TX_FORMAT_G_SHIFT, | |||
R300_TX_FORMAT_B_SHIFT, | |||
R300_TX_FORMAT_A_SHIFT | |||
}; | |||
const uint32_t swizzle_bit[4] = { | |||
R300_TX_FORMAT_X, | |||
R300_TX_FORMAT_Y, | |||
R300_TX_FORMAT_Z, | |||
R300_TX_FORMAT_W | |||
}; | |||
const uint32_t sign_bit[4] = { | |||
R300_TX_FORMAT_SIGNED_X, | |||
R300_TX_FORMAT_SIGNED_Y, | |||
R300_TX_FORMAT_SIGNED_Z, | |||
R300_TX_FORMAT_SIGNED_W, | |||
}; | |||
unsigned char swizzle[4]; | |||
desc = util_format_description(format); | |||
/* Colorspace (return non-RGB formats directly). */ | |||
switch (desc->colorspace) { | |||
/* Depth stencil formats. */ | |||
/* Depth stencil formats. | |||
* Swizzles are added in r300_merge_textures_and_samplers. */ | |||
case UTIL_FORMAT_COLORSPACE_ZS: | |||
switch (format) { | |||
case PIPE_FORMAT_Z16_UNORM: | |||
return R300_EASY_TX_FORMAT(X, X, X, X, X16); | |||
return R300_TX_FORMAT_X16; | |||
case PIPE_FORMAT_X8Z24_UNORM: | |||
case PIPE_FORMAT_S8_USCALED_Z24_UNORM: | |||
return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP); | |||
return R300_TX_FORMAT_W24_FP; | |||
default: | |||
return ~0; /* Unsupported. */ | |||
} | |||
@@ -131,43 +173,7 @@ uint32_t r300_translate_texformat(enum pipe_format format, | |||
} | |||
} | |||
/* Get swizzle. */ | |||
if (swizzle_view) { | |||
/* Compose two sets of swizzles. */ | |||
for (i = 0; i < 4; i++) { | |||
swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ? | |||
desc->swizzle[swizzle_view[i]] : swizzle_view[i]; | |||
} | |||
} else { | |||
memcpy(swizzle, desc->swizzle, sizeof(swizzle)); | |||
} | |||
/* Add swizzle. */ | |||
for (i = 0; i < 4; i++) { | |||
switch (swizzle[i]) { | |||
case UTIL_FORMAT_SWIZZLE_X: | |||
case UTIL_FORMAT_SWIZZLE_NONE: | |||
result |= swizzle_bit[0] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_Y: | |||
result |= swizzle_bit[1] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_Z: | |||
result |= swizzle_bit[2] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_W: | |||
result |= swizzle_bit[3] << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_0: | |||
result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; | |||
break; | |||
case UTIL_FORMAT_SWIZZLE_1: | |||
result |= R300_TX_FORMAT_ONE << swizzle_shift[i]; | |||
break; | |||
default: | |||
return ~0; /* Unsupported. */ | |||
} | |||
} | |||
result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view); | |||
/* S3TC formats. */ | |||
if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { |
@@ -27,6 +27,9 @@ | |||
struct r300_texture; | |||
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, | |||
const unsigned char *swizzle_view); | |||
uint32_t r300_translate_texformat(enum pipe_format format, | |||
const unsigned char *swizzle_view); | |||