From: Eric Anholt Date: Thu, 2 Oct 2014 21:01:29 +0000 (-0700) Subject: vc4: Add support for sampling from sRGB. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=24d998056275f4fab9bf3e98c962d91245ef1b7b;p=mesa.git vc4: Add support for sampling from sRGB. This isn't perfect -- the filtering is happening on the srgb values, and we're decoding afterwards, which is not what you want. I think that's the cause of some additional texwrap(GL_CLAMP, LINEAR) failures, though many other texwrap tests on srgb start to pass since unfiltered values come out correct. --- diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 544ae662825..1a7e51e8dbc 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -29,6 +29,7 @@ #include "util/u_hash.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "util/format_srgb.h" #include "util/ralloc.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_info.h" @@ -271,6 +272,22 @@ tgsi_to_qir_alu(struct vc4_compile *c, return dst; } +static struct qreg +qir_srgb_decode(struct vc4_compile *c, struct qreg srgb) +{ + struct qreg low = qir_FMUL(c, srgb, qir_uniform_f(c, 1.0 / 12.92)); + struct qreg high = qir_POW(c, + qir_FMUL(c, + qir_FADD(c, + srgb, + qir_uniform_f(c, 0.055)), + qir_uniform_f(c, 1.0 / 1.055)), + qir_uniform_f(c, 2.4)); + + qir_SF(c, qir_FSUB(c, srgb, qir_uniform_f(c, 0.04045))); + return qir_SEL_X_Y_NS(c, low, high); +} + static struct qreg tgsi_to_qir_umul(struct vc4_compile *c, struct tgsi_full_instruction *tgsi_inst, @@ -639,14 +656,25 @@ tgsi_to_qir_tex(struct vc4_compile *c, } const uint8_t *format_swiz = vc4_get_format_swizzle(format); - uint8_t swiz[4]; - util_format_compose_swizzles(format_swiz, c->key->tex[unit].swizzle, swiz); + struct qreg texture_output[4]; + for (int i = 0; i < 4; i++) { + texture_output[i] = get_swizzled_channel(c, unpacked, + format_swiz[i]); + } + + if (util_format_is_srgb(format)) { + for (int i = 0; i < 3; i++) + texture_output[i] = qir_srgb_decode(c, + texture_output[i]); + } + for (int i = 0; i < 4; i++) { if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i))) continue; update_dst(c, tgsi_inst, i, - get_swizzled_channel(c, unpacked, swiz[i])); + get_swizzled_channel(c, texture_output, + c->key->tex[unit].swizzle[i])); } } @@ -657,9 +685,7 @@ tgsi_to_qir_pow(struct vc4_compile *c, { /* Note that this instruction replicates its result from the x channel */ - return qir_EXP2(c, qir_FMUL(c, - src[1 * 4 + 0], - qir_LOG2(c, src[0 * 4 + 0]))); + return qir_POW(c, src[0 * 4 + 0], src[1 * 4 + 0]); } static struct qreg @@ -1754,8 +1780,7 @@ vc4_setup_shared_key(struct vc4_key *key, struct vc4_texture_stateobj *texstate) texstate->samplers[i]; if (sampler) { - struct pipe_resource *prsc = sampler->texture; - key->tex[i].format = prsc->format; + key->tex[i].format = sampler->format; key->tex[i].swizzle[0] = sampler->swizzle_r; key->tex[i].swizzle[1] = sampler->swizzle_g; key->tex[i].swizzle[2] = sampler->swizzle_b; @@ -2039,12 +2064,21 @@ write_texture_border_color(struct vc4_context *vc4, const struct util_format_description *tex_format_desc = util_format_description(texture->format); + float border_color[4]; + for (int i = 0; i < 4; i++) + border_color[i] = sampler->border_color.f[i]; + if (util_format_is_srgb(texture->format)) { + for (int i = 0; i < 3; i++) + border_color[i] = + util_format_linear_to_srgb_float(border_color[i]); + } + /* Turn the border color into the layout of channels that it would * have when stored as texture contents. */ float storage_color[4]; util_format_unswizzle_4f(storage_color, - sampler->border_color.f, + border_color, tex_format_desc->swizzle); /* Now, pack so that when the vc4_format-sampled texture contents are diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index 3d8caeb8a29..67355bb05a4 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -410,4 +410,12 @@ qir_UNPACK_8(struct vc4_compile *c, struct qreg src, int i) return t; } +static inline struct qreg +qir_POW(struct vc4_compile *c, struct qreg x, struct qreg y) +{ + return qir_EXP2(c, qir_FMUL(c, + y, + qir_LOG2(c, x))); +} + #endif /* VC4_QIR_H */