summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorRoland Scheidegger <[email protected]>2014-03-20 16:43:36 +0100
committerRoland Scheidegger <[email protected]>2014-03-21 17:23:38 +0100
commit9477d8c862b206c35de0bc957a08524188abc898 (patch)
tree9fd13f6453dc28723b30b054451a41156b96a8e8 /src/gallium/drivers
parent2aa77f2777ad35d7fe249939b0d828306f13eade (diff)
llvmpipe: add support for b5g6r5_srgb
The conversion code for srgb was tuned for n x 4x8bit AoS -> 4 x nxfloat SoA (and vice versa), fix this to handle also 16bit 565-style srgb formats. Still not really all that generic, things like r10g10b10a2_srgb or r4g4b4a4_srgb wouldn't work (the latter trivial to fix, the former would not require more work to not crash but near certainly need some higher precision calculation) but not needed right now. The code is not fully optimized for this (could use more direct calculation instead of expanding to 8-bit range first) but should be good enough. Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c39
2 files changed, 36 insertions, 4 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index c8e95fe329e..fe06e34f675 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -342,6 +342,7 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
if (bind & PIPE_BIND_RENDER_TARGET) {
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
+ /* this is a lie actually other formats COULD exist where we would fail */
if (format_desc->nr_channels < 3)
return FALSE;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 2f9f907edd6..5e28f0ec4ea 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -868,12 +868,12 @@ lp_mem_type_from_format_desc(const struct util_format_description *format_desc,
unsigned chan;
if (format_expands_to_float_soa(format_desc)) {
- /* just make this a 32bit uint */
+ /* just make this a uint with width of block */
type->floating = false;
type->fixed = false;
type->sign = false;
type->norm = false;
- type->width = 32;
+ type->width = format_desc->block.bits;
type->length = 1;
return;
}
@@ -1137,12 +1137,24 @@ convert_to_blend_type(struct gallivm_state *gallivm,
* This is pretty suboptimal for this case blending in SoA would be much
* better, since conversion gets us SoA values so need to convert back.
*/
- assert(src_type.width == 32);
+ assert(src_type.width == 32 || src_type.width == 16);
assert(dst_type.floating);
assert(dst_type.width == 32);
assert(dst_type.length % 4 == 0);
assert(num_srcs % 4 == 0);
+ if (src_type.width == 16) {
+ /* expand 4x16bit values to 4x32bit */
+ struct lp_type type32x4 = src_type;
+ LLVMTypeRef ltype32x4;
+ unsigned num_fetch = dst_type.length == 8 ? num_srcs / 2 : num_srcs / 4;
+ type32x4.width = 32;
+ ltype32x4 = lp_build_vec_type(gallivm, type32x4);
+ for (i = 0; i < num_fetch; i++) {
+ src[i] = LLVMBuildZExt(builder, src[i], ltype32x4, "");
+ }
+ src_type.width = 32;
+ }
for (i = 0; i < 4; i++) {
tmpsrc[i] = src[i];
}
@@ -1298,7 +1310,7 @@ convert_from_blend_type(struct gallivm_state *gallivm,
assert(src_type.floating);
assert(src_type.width == 32);
assert(src_type.length % 4 == 0);
- assert(dst_type.width == 32);
+ assert(dst_type.width == 32 || dst_type.width == 16);
for (i = 0; i < num_srcs / 4; i++) {
LLVMValueRef tmpsoa[4], tmpdst;
@@ -1333,6 +1345,25 @@ convert_from_blend_type(struct gallivm_state *gallivm,
src[i] = tmpdst;
}
}
+ if (dst_type.width == 16) {
+ struct lp_type type16x8 = dst_type;
+ struct lp_type type32x4 = dst_type;
+ LLVMTypeRef ltype16x4, ltypei64, ltypei128;
+ unsigned num_fetch = src_type.length == 8 ? num_srcs / 2 : num_srcs / 4;
+ type16x8.length = 8;
+ type32x4.width = 32;
+ ltypei128 = LLVMIntTypeInContext(gallivm->context, 128);
+ ltypei64 = LLVMIntTypeInContext(gallivm->context, 64);
+ ltype16x4 = lp_build_vec_type(gallivm, dst_type);
+ /* We could do vector truncation but it doesn't generate very good code */
+ for (i = 0; i < num_fetch; i++) {
+ src[i] = lp_build_pack2(gallivm, type32x4, type16x8,
+ src[i], lp_build_zero(gallivm, type32x4));
+ src[i] = LLVMBuildBitCast(builder, src[i], ltypei128, "");
+ src[i] = LLVMBuildTrunc(builder, src[i], ltypei64, "");
+ src[i] = LLVMBuildBitCast(builder, src[i], ltype16x4, "");
+ }
+ }
return;
}