diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.h b/src/gallium/drivers/freedreno/a3xx/fd3_context.h index 250bcf89596..b4c2ebe570c 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.h @@ -73,22 +73,6 @@ struct fd3_context { */ struct fd_vertex_state blit_vbuf_state; - - /* - * Border color layout *appears* to be as arrays of 0x40 byte - * elements, with frag shader elements starting at (16 x 0x40). - * But at some point I should probably experiment more with - * samplers in vertex shaders to be sure. Unclear about why - * there is this offset when there are separate VS and FS base - * addr regs. - * - * The first 8 bytes of each entry are the requested border - * color in fp16. Unclear about the rest.. could be used for - * other formats, or could simply be for aligning the pitch - * to 32 pixels. - */ -#define BORDERCOLOR_SIZE 0x40 - struct u_upload_mgr *border_color_uploader; struct pipe_resource *border_color_buf; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 6f514ed05df..b81bc5a90a4 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -149,6 +149,8 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, &fd3_ctx->border_color_buf, &ptr); + fd_setup_border_colors(tex, ptr, tex_off[sb]); + if (tex->num_samplers > 0) { /* output sampler state: */ OUT_PKT3(ring, CP_LOAD_STATE, 2 + (2 * tex->num_samplers)); @@ -163,57 +165,6 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, const struct fd3_sampler_stateobj *sampler = tex->samplers[i] ? fd3_sampler_stateobj(tex->samplers[i]) : &dummy_sampler; - uint16_t *bcolor = (uint16_t *)((uint8_t *)ptr + - (BORDERCOLOR_SIZE * tex_off[sb]) + - (BORDERCOLOR_SIZE * i)); - uint32_t *bcolor32 = (uint32_t *)&bcolor[16]; - - /* - * 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]]; - int size = chan->size; - - /* The Z16 texture format we use seems to look in the - * 32-bit border color slots - */ - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) - size = 32; - - /* Formats like R11G11B10 or RGB9_E5 don't specify - * per-channel sizes properly. - */ - if (desc->layout == UTIL_FORMAT_LAYOUT_OTHER) - size = 16; - - if (chan->pure_integer && size > 16) - bcolor32[desc->swizzle[j] + 4] = - sampler->base.border_color.i[j]; - else if (size > 16) - bcolor32[desc->swizzle[j]] = - fui(sampler->base.border_color.f[j]); - else if (chan->pure_integer) - bcolor[desc->swizzle[j] + 8] = - sampler->base.border_color.i[j]; - else - bcolor[desc->swizzle[j]] = - util_float_to_half(sampler->base.border_color.f[j]); - } - } OUT_RING(ring, sampler->texsamp0); OUT_RING(ring, sampler->texsamp1); diff --git a/src/gallium/drivers/freedreno/freedreno_texture.c b/src/gallium/drivers/freedreno/freedreno_texture.c index eaa6629f2b8..04e4643b4c9 100644 --- a/src/gallium/drivers/freedreno/freedreno_texture.c +++ b/src/gallium/drivers/freedreno/freedreno_texture.c @@ -162,3 +162,69 @@ fd_texture_init(struct pipe_context *pctx) pctx->sampler_view_destroy = fd_sampler_view_destroy; } + +/* helper for setting up border-color buffer for a3xx/a4xx: */ +void +fd_setup_border_colors(struct fd_texture_stateobj *tex, void *ptr, + unsigned offset) +{ + 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]]; + int size = chan->size; + + /* The Z16 texture format we use seems to look in the + * 32-bit border color slots + */ + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) + size = 32; + + /* Formats like R11G11B10 or RGB9_E5 don't specify + * per-channel sizes properly. + */ + if (desc->layout == UTIL_FORMAT_LAYOUT_OTHER) + size = 16; + + if (chan->pure_integer && size > 16) + bcolor32[desc->swizzle[j] + 4] = + sampler->border_color.i[j]; + else if (size > 16) + bcolor32[desc->swizzle[j]] = + fui(sampler->border_color.f[j]); + else if (chan->pure_integer) + bcolor[desc->swizzle[j] + 8] = + sampler->border_color.i[j]; + else + bcolor[desc->swizzle[j]] = + util_float_to_half(sampler->border_color.f[j]); + } + } + } +} diff --git a/src/gallium/drivers/freedreno/freedreno_texture.h b/src/gallium/drivers/freedreno/freedreno_texture.h index 43571a9fa61..fa27d1c32af 100644 --- a/src/gallium/drivers/freedreno/freedreno_texture.h +++ b/src/gallium/drivers/freedreno/freedreno_texture.h @@ -41,4 +41,35 @@ void fd_set_sampler_views(struct pipe_context *pctx, unsigned shader, void fd_texture_init(struct pipe_context *pctx); +struct fd_texture_stateobj; + +/* Both a3xx/a4xx share the same layout for the border-color buffer, + * which contains the pre-swizzled (based on texture format) border + * color value, with the following layout (per sampler): + * + * offset | description + * -------+------------- + * 0x00: | fp16[0] \ + * | fp16[1] |___ swizzled fp16 channel values for "small float" + * | fp16[2] | formats (<= 16 bits per component, !integer) + * | fp16[3] / + * 0x08: | padding + * 0x10: | int16[0] \ + * | int16[1] |___ swizzled int16 channels for for "small integer" + * | int16[2] | formats (<= 16 bits per component, integer) + * | int16[3] / + * 0x18: | padding + * 0x20: | fp32[0] \ + * | fp32[1] |___ swizzled fp32 channel values for "large float" + * | fp32[2] | formats (> 16 bits per component, !integer) + * | fp32[3] / + * 0x30: | int32[0] \ + * | int32[1] |___ swizzled int32 channel values for "large int" + * | int32[2] | formats (> 16 bits per component, integer) + * | int32[3] / + */ +#define BORDERCOLOR_SIZE 0x40 +void fd_setup_border_colors(struct fd_texture_stateobj *tex, void *ptr, + unsigned offset); + #endif /* FREEDRENO_TEXTURE_H_ */