X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Ffreedreno_texture.c;h=5b0bec17f5da417e26f24bb3d598897896fb93e9;hb=836d41d77265a2d2ca42bdbfd25de07b9bb134c9;hp=07bfbd3ce362728f981e85c2e4cb31c3d3ddeb28;hpb=6173cc19c45d92ef0b7bc6aa008aa89bb29abbda;p=mesa.git diff --git a/src/gallium/drivers/freedreno/freedreno_texture.c b/src/gallium/drivers/freedreno/freedreno_texture.c index 07bfbd3ce36..5b0bec17f5d 100644 --- a/src/gallium/drivers/freedreno/freedreno_texture.c +++ b/src/gallium/drivers/freedreno/freedreno_texture.c @@ -1,5 +1,3 @@ -/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ - /* * Copyright (C) 2012 Rob Clark * @@ -32,110 +30,16 @@ #include "util/u_inlines.h" #include "freedreno_texture.h" +#include "freedreno_context.h" +#include "freedreno_resource.h" #include "freedreno_util.h" -static enum sq_tex_clamp -tex_clamp(unsigned wrap) -{ - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - return SQ_TEX_WRAP; - case PIPE_TEX_WRAP_CLAMP: - return SQ_TEX_CLAMP_HALF_BORDER; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - return SQ_TEX_CLAMP_LAST_TEXEL; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - return SQ_TEX_CLAMP_BORDER; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - return SQ_TEX_MIRROR; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - return SQ_TEX_MIRROR_ONCE_HALF_BORDER; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - return SQ_TEX_MIRROR_ONCE_LAST_TEXEL; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - return SQ_TEX_MIRROR_ONCE_BORDER; - default: - DBG("invalid wrap: %u", wrap); - return 0; - } -} - -static enum sq_tex_filter -tex_filter(unsigned filter) -{ - switch (filter) { - case PIPE_TEX_FILTER_NEAREST: - return SQ_TEX_FILTER_POINT; - case PIPE_TEX_FILTER_LINEAR: - return SQ_TEX_FILTER_BILINEAR; - default: - DBG("invalid filter: %u", filter); - return 0; - } -} - -static void * -fd_sampler_state_create(struct pipe_context *pctx, - const struct pipe_sampler_state *cso) -{ - struct fd_sampler_stateobj *so = CALLOC_STRUCT(fd_sampler_stateobj); - - if (!so) - return NULL; - - so->base = *cso; - - /* SQ_TEX0_PITCH() must be OR'd in later when we know the bound texture: */ - so->tex0 = - SQ_TEX0_CLAMP_X(tex_clamp(cso->wrap_s)) | - SQ_TEX0_CLAMP_Y(tex_clamp(cso->wrap_t)) | - SQ_TEX0_CLAMP_Z(tex_clamp(cso->wrap_r)); - - so->tex3 = - SQ_TEX3_XY_MAG_FILTER(tex_filter(cso->mag_img_filter)) | - SQ_TEX3_XY_MIN_FILTER(tex_filter(cso->min_img_filter)); - - so->tex4 = 0x00000000; /* ??? */ - so->tex5 = 0x00000200; /* ??? */ - - return so; -} - static void fd_sampler_state_delete(struct pipe_context *pctx, void *hwcso) { FREE(hwcso); } -static struct pipe_sampler_view * -fd_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, - const struct pipe_sampler_view *cso) -{ - struct fd_pipe_sampler_view *so = CALLOC_STRUCT(fd_pipe_sampler_view); - struct fd_resource *rsc = fd_resource(prsc); - - if (!so) - return NULL; - - so->base = *cso; - pipe_reference(NULL, &prsc->reference); - so->base.texture = prsc; - so->base.reference.count = 1; - so->base.context = pctx; - - so->tex_resource = rsc; - so->fmt = fd_pipe2surface(cso->format); - - so->tex0 = SQ_TEX0_PITCH(rsc->pitch); - so->tex2 = - SQ_TEX2_HEIGHT(prsc->height0) | - SQ_TEX2_WIDTH(prsc->width0); - so->tex3 = fd_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, - cso->swizzle_b, cso->swizzle_a); - - return &so->base; -} - static void fd_sampler_view_destroy(struct pipe_context *pctx, struct pipe_sampler_view *view) @@ -144,143 +48,128 @@ fd_sampler_view_destroy(struct pipe_context *pctx, FREE(view); } -static void bind_sampler_states(struct fd_texture_stateobj *prog, - unsigned nr, void **hwcso) +static void bind_sampler_states(struct fd_texture_stateobj *tex, + unsigned start, unsigned nr, void **hwcso) { unsigned i; for (i = 0; i < nr; i++) { - prog->samplers[i] = hwcso[i]; - prog->dirty_samplers |= (1 << i); - } - - for (; i < prog->num_samplers; i++) { - prog->samplers[i] = NULL; - prog->dirty_samplers |= (1 << i); + unsigned p = i + start; + tex->samplers[p] = hwcso[i]; + if (tex->samplers[p]) + tex->valid_samplers |= (1 << p); + else + tex->valid_samplers &= ~(1 << p); } - prog->num_samplers = nr; + tex->num_samplers = util_last_bit(tex->valid_samplers); } -static void set_sampler_views(struct fd_texture_stateobj *prog, - unsigned nr, struct pipe_sampler_view **views) +static void set_sampler_views(struct fd_texture_stateobj *tex, + unsigned start, unsigned nr, struct pipe_sampler_view **views) { unsigned i; + unsigned samplers = 0; for (i = 0; i < nr; i++) { - pipe_sampler_view_reference(&prog->textures[i], views[i]); - prog->dirty_samplers |= (1 << i); + struct pipe_sampler_view *view = views ? views[i] : NULL; + unsigned p = i + start; + pipe_sampler_view_reference(&tex->textures[p], view); + if (tex->textures[p]) { + fd_resource_set_usage(tex->textures[p]->texture, FD_DIRTY_TEX); + tex->valid_textures |= (1 << p); + } else { + tex->valid_textures &= ~(1 << p); + } } - for (; i < prog->num_textures; i++) { - pipe_sampler_view_reference(&prog->textures[i], NULL); - prog->dirty_samplers |= (1 << i); + tex->num_textures = util_last_bit(tex->valid_textures); + + for (i = 0; i < tex->num_textures; i++) { + uint nr_samples = fd_resource_nr_samples(tex->textures[i]->texture); + samplers |= (nr_samples >> 1) << (i * 2); } - prog->num_textures = nr; + tex->samples = samplers; } -static void -fd_fragtex_sampler_states_bind(struct pipe_context *pctx, +void +fd_sampler_states_bind(struct pipe_context *pctx, + enum pipe_shader_type shader, unsigned start, unsigned nr, void **hwcso) { struct fd_context *ctx = fd_context(pctx); - bind_sampler_states(&ctx->fragtex, nr, hwcso); - ctx->dirty |= FD_DIRTY_FRAGTEX; -} - -static void -fd_fragtex_set_sampler_views(struct pipe_context *pctx, unsigned nr, - struct pipe_sampler_view **views) -{ - struct fd_context *ctx = fd_context(pctx); - set_sampler_views(&ctx->fragtex, nr, views); - ctx->dirty |= FD_DIRTY_FRAGTEX; + bind_sampler_states(&ctx->tex[shader], start, nr, hwcso); + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_TEX; + ctx->dirty |= FD_DIRTY_TEX; } -static void -fd_verttex_sampler_states_bind(struct pipe_context *pctx, - unsigned nr, void **hwcso) -{ - struct fd_context *ctx = fd_context(pctx); - bind_sampler_states(&ctx->verttex, nr, hwcso); - ctx->dirty |= FD_DIRTY_VERTTEX; -} - - -static void -fd_verttex_set_sampler_views(struct pipe_context *pctx, unsigned nr, +void +fd_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader, + unsigned start, unsigned nr, struct pipe_sampler_view **views) { struct fd_context *ctx = fd_context(pctx); - set_sampler_views(&ctx->verttex, nr, views); - ctx->dirty |= FD_DIRTY_VERTTEX; -} - -static bool -tex_cmp(struct fd_texture_stateobj *tex1, unsigned samp_id1, - struct fd_texture_stateobj *tex2, unsigned samp_id2) -{ - if ((samp_id1 >= tex1->num_samplers) || - (samp_id2 >= tex2->num_samplers)) - return false; - - if ((tex1 == tex2) && (samp_id1 == samp_id2)) - return true; - if (tex1->textures[samp_id1]->texture != tex2->textures[samp_id2]->texture) - return false; - - if (memcmp(&tex1->samplers[samp_id1]->base, &tex2->samplers[samp_id2]->base, - sizeof(tex1->samplers[samp_id1]->base))) - return false; - - return true; + set_sampler_views(&ctx->tex[shader], start, nr, views); + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_TEX; + ctx->dirty |= FD_DIRTY_TEX; } -/* map gallium sampler-id to hw const-idx.. adreno uses a flat address - * space of samplers (const-idx), so we need to map the gallium sampler-id - * which is per-shader to a global const-idx space. - */ -unsigned -fd_get_const_idx(struct fd_context *ctx, struct fd_texture_stateobj *tex, - unsigned samp_id) +void +fd_texture_init(struct pipe_context *pctx) { - unsigned i, const_idx = 0; - - /* TODO maybe worth having some sort of cache, because we need to - * do this loop thru all the samplers both when patching shaders - * and also when emitting sampler state.. - */ - - for (i = 0; i < ctx->verttex.num_samplers; i++) { - if (tex_cmp(&ctx->verttex, i, tex, samp_id)) - return const_idx; - const_idx++; - } - - for (i = 0; i < ctx->fragtex.num_samplers; i++) { - if (tex_cmp(&ctx->fragtex, i, tex, samp_id)) - return const_idx; - const_idx++; - } - - return const_idx; + if (!pctx->delete_sampler_state) + pctx->delete_sampler_state = fd_sampler_state_delete; + if (!pctx->sampler_view_destroy) + pctx->sampler_view_destroy = fd_sampler_view_destroy; } +/* helper for setting up border-color buffer for a3xx/a4xx: */ void -fd_texture_init(struct pipe_context *pctx) +fd_setup_border_colors(struct fd_texture_stateobj *tex, void *ptr, + unsigned offset) { - pctx->create_sampler_state = fd_sampler_state_create; - pctx->delete_sampler_state = fd_sampler_state_delete; - - pctx->create_sampler_view = fd_sampler_view_create; - pctx->sampler_view_destroy = fd_sampler_view_destroy; - - pctx->bind_fragment_sampler_states = fd_fragtex_sampler_states_bind; - pctx->set_fragment_sampler_views = fd_fragtex_set_sampler_views; - - pctx->bind_vertex_sampler_states = fd_verttex_sampler_states_bind; - pctx->set_vertex_sampler_views = fd_verttex_set_sampler_views; + unsigned i, j; + + for (i = 0; i < tex->num_samplers; i++) { + struct pipe_sampler_state *sampler = tex->samplers[i]; + uint16_t *bcolor = (uint16_t *)((uint8_t *)ptr + + (BORDERCOLOR_SIZE * offset) + + (BORDERCOLOR_SIZE * i)); + uint32_t *bcolor32 = (uint32_t *)&bcolor[16]; + + if (!sampler) + continue; + + /* + * XXX HACK ALERT XXX + * + * The border colors need to be swizzled in a particular + * format-dependent order. Even though samplers don't know about + * formats, we can assume that with a GL state tracker, there's a + * 1:1 correspondence between sampler and texture. Take advantage + * of that knowledge. + */ + if (i < tex->num_textures && tex->textures[i]) { + const struct util_format_description *desc = + util_format_description(tex->textures[i]->format); + for (j = 0; j < 4; j++) { + if (desc->swizzle[j] >= 4) + continue; + + const struct util_format_channel_description *chan = + &desc->channel[desc->swizzle[j]]; + if (chan->pure_integer) { + bcolor32[desc->swizzle[j] + 4] = sampler->border_color.i[j]; + bcolor[desc->swizzle[j] + 8] = sampler->border_color.i[j]; + } else { + bcolor32[desc->swizzle[j]] = fui(sampler->border_color.f[j]); + bcolor[desc->swizzle[j]] = + util_float_to_half(sampler->border_color.f[j]); + } + } + } + } }