Commit 1c356ac9 authored by Marek Olšák's avatar Marek Olšák

r300g: cleanup handling of sampler views

The evolution of TX_FORMAT bits is as follows:
* When a texture is created, set bits independent of pipe_format.
* When a sampler view is created, add format-specific bits.
* When sampler states and views are getting merged, add min/max LOD.
parent 26a54ed6
......@@ -111,11 +111,12 @@ static void r300_hw_copy(struct pipe_context* pipe,
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
util_blitter_save_fragment_sampler_states(
r300->blitter, state->sampler_count, (void**)state->sampler_states);
r300->blitter, state->sampler_state_count,
(void**)state->sampler_states);
util_blitter_save_fragment_sampler_views(
r300->blitter, state->texture_count,
state->fragment_sampler_views);
r300->blitter, state->sampler_view_count,
(struct pipe_sampler_view**)state->sampler_views);
/* Do a copy */
util_blitter_copy(r300->blitter,
......
......@@ -130,6 +130,15 @@ struct r300_texture_format_state {
uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */
uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */
uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */
uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */
};
struct r300_sampler_view {
struct pipe_sampler_view base;
/* Copy of r300_texture::texture_format_state with format-specific bits
* added. */
struct r300_texture_format_state format;
};
struct r300_texture_fb_state {
......@@ -144,20 +153,20 @@ struct r300_texture_fb_state {
struct r300_textures_state {
/* Textures. */
struct pipe_sampler_view *fragment_sampler_views[16];
int texture_count;
struct r300_sampler_view *sampler_views[16];
int sampler_view_count;
/* Sampler states. */
struct r300_sampler_state *sampler_states[16];
int sampler_count;
int sampler_state_count;
/* These is the merge of the texture and sampler states. */
/* 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 {
uint32_t format[3]; /* R300_TX_FORMAT[0-2] */
uint32_t filter[2]; /* R300_TX_FILTER[0-1] */
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 */
uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */
} regs[16];
};
......@@ -266,7 +275,9 @@ struct r300_texture {
struct r300_winsys_buffer *buffer;
/* Registers carrying texture format data. */
struct r300_texture_format_state state;
/* Only format-independent bits should be filled in. */
struct r300_texture_format_state tx_format;
/* All bits should be filled in. */
struct r300_texture_fb_state fb_state;
/* Buffer tiling */
......
......@@ -159,7 +159,7 @@ static const float * get_shader_constant(
/* Factor for converting rectangle coords to
* normalized coords. Should only show up on non-r500. */
case RC_STATE_R300_TEXRECT_FACTOR:
tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture;
tex = texstate->sampler_views[constant->u.State[1]]->base.texture;
vec[0] = 1.0 / tex->width0;
vec[1] = 1.0 / tex->height0;
break;
......@@ -729,18 +729,18 @@ void r300_emit_textures_state(struct r300_context *r300,
if ((1 << i) & allstate->tx_enable) {
texstate = &allstate->regs[i];
OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter[0]);
OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter[1]);
OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0);
OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1);
OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4),
texstate->border_color);
OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format[0]);
OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format[1]);
OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]);
OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0);
OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1);
OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
OUT_CS_TEX_RELOC(r300_texture(allstate->fragment_sampler_views[i]->texture),
texstate->tile_config,
OUT_CS_TEX_RELOC(r300_texture(allstate->sampler_views[i]->base.texture),
texstate->format.tile_config,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
}
}
......@@ -1022,7 +1022,7 @@ validate:
continue;
}
tex = r300_texture(texstate->fragment_sampler_views[i]->texture);
tex = r300_texture(texstate->sampler_views[i]->base.texture);
if (!r300_add_texture(r300->rws, tex,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
r300->context.flush(&r300->context, 0, NULL);
......
......@@ -138,7 +138,7 @@ static void get_compare_state(
memset(state, 0, sizeof(*state));
for (int i = 0; i < texstate->sampler_count; i++) {
for (int i = 0; i < texstate->sampler_state_count; i++) {
struct r300_sampler_state* s = texstate->sampler_states[i];
if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
......
......@@ -37,6 +37,7 @@
#include "r300_screen_buffer.h"
#include "r300_state_inlines.h"
#include "r300_fs.h"
#include "r300_texture.h"
#include "r300_vs.h"
#include "r300_winsys.h"
......@@ -938,7 +939,7 @@ static void r300_bind_sampler_states(struct pipe_context* pipe,
}
memcpy(state->sampler_states, states, sizeof(void*) * count);
state->sampler_count = count;
state->sampler_state_count = count;
r300->textures_state.dirty = TRUE;
......@@ -980,9 +981,10 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
}
for (i = 0; i < count; i++) {
if (state->fragment_sampler_views[i] != views[i]) {
pipe_sampler_view_reference(&state->fragment_sampler_views[i],
views[i]);
if (&state->sampler_views[i]->base != views[i]) {
pipe_sampler_view_reference(
(struct pipe_sampler_view**)&state->sampler_views[i],
views[i]);
if (!views[i]) {
continue;
......@@ -1002,13 +1004,14 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
}
for (i = count; i < tex_units; i++) {
if (state->fragment_sampler_views[i]) {
pipe_sampler_view_reference(&state->fragment_sampler_views[i],
NULL);
if (state->sampler_views[i]) {
pipe_sampler_view_reference(
(struct pipe_sampler_view**)&state->sampler_views[i],
NULL);
}
}
state->texture_count = count;
state->sampler_view_count = count;
r300->textures_state.dirty = TRUE;
......@@ -1022,17 +1025,33 @@ r300_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture,
const struct pipe_sampler_view *templ)
{
struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
if (view) {
*view = *templ;
view->reference.count = 1;
view->texture = NULL;
pipe_resource_reference(&view->texture, texture);
view->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;
view->base.reference.count = 1;
view->base.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;
/* XXX Enable swizzles when they become supported. Now we get RGBA
* everywhere. And do testing! */
view->format = tex->tx_format;
view->format.format1 |= r300_translate_texformat(templ->format,
0); /*swizzle);*/
if (r300_screen(pipe->screen)->caps.is_r500) {
view->format.format2 |= r500_tx_format_msb_bit(templ->format);
}
}
return view;
return (struct pipe_sampler_view*)view;
}
static void
......
......@@ -456,74 +456,71 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
(struct r300_textures_state*)r300->textures_state.state;
struct r300_texture_sampler_state *texstate;
struct r300_sampler_state *sampler;
struct pipe_sampler_view *view;
struct r300_sampler_view *view;
struct r300_texture *tex;
unsigned min_level, max_level, i, size;
unsigned count = MIN2(state->texture_count, state->sampler_count);
unsigned count = MIN2(state->sampler_view_count,
state->sampler_state_count);
state->tx_enable = 0;
state->count = 0;
size = 2;
for (i = 0; i < count; i++) {
if (state->fragment_sampler_views[i] && state->sampler_states[i]) {
if (state->sampler_views[i] && state->sampler_states[i]) {
state->tx_enable |= 1 << i;
view = state->fragment_sampler_views[i];
tex = r300_texture(view->texture);
view = state->sampler_views[i];
tex = r300_texture(view->base.texture);
sampler = state->sampler_states[i];
assert(view->format == tex->b.b.format);
texstate = &state->regs[i];
memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3);
texstate->filter[0] = sampler->filter0;
texstate->filter[1] = sampler->filter1;
texstate->format = view->format;
texstate->filter0 = sampler->filter0;
texstate->filter1 = sampler->filter1;
texstate->border_color = sampler->border_color;
texstate->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
R300_TXO_MICRO_TILE(tex->microtile);
/* to emulate 1D textures through 2D ones correctly */
if (tex->b.b.target == PIPE_TEXTURE_1D) {
texstate->filter[0] &= ~R300_TX_WRAP_T_MASK;
texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
}
if (tex->uses_pitch) {
/* NPOT textures don't support mip filter, unfortunately.
* This prevents incorrect rendering. */
texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK;
texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
/* Set repeat or mirrored-repeat to clamp-to-edge. */
/* Wrap S. */
if ((texstate->filter[0] & R300_TX_WRAP_S_MASK) ==
if ((texstate->filter0 & R300_TX_WRAP_S_MASK) ==
R300_TX_WRAP_S(R300_TX_REPEAT) ||
(texstate->filter[0] & R300_TX_WRAP_S_MASK) ==
(texstate->filter0 & R300_TX_WRAP_S_MASK) ==
R300_TX_WRAP_S(R300_TX_MIRRORED)) {
texstate->filter[0] &= ~R300_TX_WRAP_S_MASK;
texstate->filter[0] |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE);
texstate->filter0 &= ~R300_TX_WRAP_S_MASK;
texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE);
}
/* Wrap T. */
if ((texstate->filter[0] & R300_TX_WRAP_T_MASK) ==
if ((texstate->filter0 & R300_TX_WRAP_T_MASK) ==
R300_TX_WRAP_T(R300_TX_REPEAT) ||
(texstate->filter[0] & R300_TX_WRAP_T_MASK) ==
(texstate->filter0 & R300_TX_WRAP_T_MASK) ==
R300_TX_WRAP_T(R300_TX_MIRRORED)) {
texstate->filter[0] &= ~R300_TX_WRAP_T_MASK;
texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
}
} else {
/* determine min/max levels */
/* the MAX_MIP level is the largest (finest) one */
max_level = MIN3(sampler->max_lod + view->first_level,
tex->b.b.last_level, view->last_level);
min_level = MIN2(sampler->min_lod + view->first_level,
max_level = MIN3(sampler->max_lod + view->base.first_level,
tex->b.b.last_level, view->base.last_level);
min_level = MIN2(sampler->min_lod + view->base.first_level,
max_level);
texstate->format[0] |= R300_TX_NUM_LEVELS(max_level);
texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level);
texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level);
texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
}
texstate->filter[0] |= i << 28;
texstate->filter0 |= i << 28;
size += 16;
state->count = i+1;
......
......@@ -28,6 +28,7 @@
#include "util/u_memory.h"
#include "r300_context.h"
#include "r300_reg.h"
#include "r300_texture.h"
#include "r300_transfer.h"
#include "r300_screen.h"
......@@ -72,7 +73,8 @@ static boolean r300_format_is_plain(enum pipe_format format)
*
* The FORMAT specifies how the texture sampler will treat the texture, and
* makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
static uint32_t r300_translate_texformat(enum pipe_format format)
uint32_t r300_translate_texformat(enum pipe_format format,
const unsigned char *swizzle)
{
uint32_t result = 0;
const struct util_format_description *desc;
......@@ -84,7 +86,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
R300_TX_FORMAT_B_SHIFT,
R300_TX_FORMAT_A_SHIFT
};
const uint32_t swizzle[4] = {
const uint32_t swizzle_bit[4] = {
R300_TX_FORMAT_X,
R300_TX_FORMAT_Y,
R300_TX_FORMAT_Z,
......@@ -141,20 +143,38 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
}
/* Add swizzle. */
if (!swizzle) {
swizzle = desc->swizzle;
} /*else {
if (swizzle[0] != desc->swizzle[0] ||
swizzle[1] != desc->swizzle[1] ||
swizzle[2] != desc->swizzle[2] ||
swizzle[3] != desc->swizzle[3])
{
const char n[6] = "RGBA01";
fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, "
"View: %c%c%c%c\n",
n[desc->swizzle[0]], n[desc->swizzle[1]],
n[desc->swizzle[2]], n[desc->swizzle[3]],
n[swizzle[0]], n[swizzle[1]], n[swizzle[2]],
n[swizzle[3]]);
}
}*/
for (i = 0; i < 4; i++) {
switch (desc->swizzle[i]) {
switch (swizzle[i]) {
case UTIL_FORMAT_SWIZZLE_X:
case UTIL_FORMAT_SWIZZLE_NONE:
result |= swizzle[0] << swizzle_shift[i];
result |= swizzle_bit[0] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_Y:
result |= swizzle[1] << swizzle_shift[i];
result |= swizzle_bit[1] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_Z:
result |= swizzle[2] << swizzle_shift[i];
result |= swizzle_bit[2] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_W:
result |= swizzle[3] << swizzle_shift[i];
result |= swizzle_bit[3] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_0:
result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
......@@ -317,7 +337,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
return ~0; /* Unsupported/unknown. */
}
static uint32_t r500_tx_format_msb_bit(enum pipe_format format)
uint32_t r500_tx_format_msb_bit(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_RGTC1_UNORM:
......@@ -527,51 +547,59 @@ boolean r300_is_zs_format_supported(enum pipe_format format)
boolean r300_is_sampler_format_supported(enum pipe_format format)
{
return r300_translate_texformat(format) != ~0;
return r300_translate_texformat(format, 0) != ~0;
}
static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex)
static void r300_texture_setup_immutable_state(struct r300_screen* screen,
struct r300_texture* tex)
{
struct r300_texture_format_state* state = &tex->state;
struct r300_texture_format_state* f = &tex->tx_format;
struct pipe_resource *pt = &tex->b.b;
unsigned i;
boolean is_r500 = screen->caps.is_r500;
/* Set sampler state. */
state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
if (tex->uses_pitch) {
/* rectangles love this */
state->format0 |= R300_TX_PITCH_EN;
state->format2 = (tex->pitch[0] - 1) & 0x1fff;
f->format0 |= R300_TX_PITCH_EN;
f->format2 = (tex->pitch[0] - 1) & 0x1fff;
} else {
/* power of two textures (3D, mipmaps, and no pitch) */
state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
}
state->format1 = r300_translate_texformat(pt->format);
f->format1 = 0;
if (pt->target == PIPE_TEXTURE_CUBE) {
state->format1 |= R300_TX_FORMAT_CUBIC_MAP;
f->format1 |= R300_TX_FORMAT_CUBIC_MAP;
}
if (pt->target == PIPE_TEXTURE_3D) {
state->format1 |= R300_TX_FORMAT_3D;
f->format1 |= R300_TX_FORMAT_3D;
}
/* large textures on r500 */
if (is_r500)
{
if (pt->width0 > 2048) {
state->format2 |= R500_TXWIDTH_BIT11;
f->format2 |= R500_TXWIDTH_BIT11;
}
if (pt->height0 > 2048) {
state->format2 |= R500_TXHEIGHT_BIT11;
f->format2 |= R500_TXHEIGHT_BIT11;
}
state->format2 |= r500_tx_format_msb_bit(pt->format);
}
f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
R300_TXO_MICRO_TILE(tex->microtile);
SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n",
pt->width0, pt->height0, pt->last_level);
}
static void r300_texture_setup_fb_state(struct r300_screen* screen,
struct r300_texture* tex)
{
unsigned i;
/* Set framebuffer state. */
if (util_format_is_depth_or_stencil(tex->b.b.format)) {
......@@ -605,7 +633,7 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
tex->format = new_format;
r300_setup_texture_state(r300_screen(screen), r300_texture(tex));
r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex));
}
unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
......@@ -807,7 +835,6 @@ static void r300_setup_tiling(struct pipe_screen *screen,
}
}
static unsigned r300_texture_is_referenced(struct pipe_context *context,
struct pipe_resource *texture,
unsigned face, unsigned level)
......@@ -894,7 +921,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
r300_setup_tiling(screen, tex);
}
r300_setup_miptree(rscreen, tex);
r300_setup_texture_state(rscreen, tex);
r300_texture_setup_immutable_state(rscreen, tex);
r300_texture_setup_fb_state(rscreen, tex);
tex->buffer = rws->buffer_create(rws, 2048,
PIPE_BIND_SAMPLER_VIEW, /* XXX */
......@@ -1019,7 +1047,8 @@ r300_texture_from_handle(struct pipe_screen* screen,
}
r300_setup_miptree(rscreen, tex);
r300_setup_texture_state(rscreen, tex);
r300_texture_setup_immutable_state(rscreen, tex);
r300_texture_setup_fb_state(rscreen, tex);
if (override_zb_flags) {
rws->buffer_set_tiling(rws, tex->buffer,
......
......@@ -25,10 +25,13 @@
#include "util/u_format.h"
#include "r300_reg.h"
struct r300_texture;
uint32_t r300_translate_texformat(enum pipe_format format,
const unsigned char *swizzle);
uint32_t r500_tx_format_msb_bit(enum pipe_format format);
unsigned r300_texture_get_stride(struct r300_screen* screen,
struct r300_texture* tex, unsigned level);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment