OSDN Git Service

71261e4f393d6739c5a58ccdccc912f9283c29ac
[android-x86/external-mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_pack.c
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27
28
29 #include "util/u_format.h"
30
31 #include "lp_bld_format.h"
32
33
34 LLVMValueRef
35 lp_build_pack_rgba(LLVMBuilderRef builder,
36                    enum pipe_format format,
37                    LLVMValueRef rgba)
38 {
39    const struct util_format_description *desc;
40    LLVMTypeRef type;
41    LLVMValueRef packed = NULL;
42    LLVMValueRef swizzles[4];
43    LLVMValueRef shifted, casted, scaled, unswizzled;
44    LLVMValueRef shifts[4];
45    LLVMValueRef scales[4];
46    bool normalized;
47    unsigned shift;
48    unsigned i, j;
49
50    desc = util_format_description(format);
51
52    assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
53    assert(desc->block.width == 1);
54    assert(desc->block.height == 1);
55
56    type = LLVMIntType(desc->block.bits);
57
58    /* Unswizzle the color components into the source vector. */
59    for (i = 0; i < 4; ++i) {
60       for (j = 0; j < 4; ++j) {
61          if (desc->swizzle[j] == i)
62             break;
63       }
64       if (j < 4)
65          swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0);
66       else
67          swizzles[i] = LLVMGetUndef(LLVMInt32Type());
68    }
69
70    unswizzled = LLVMBuildShuffleVector(builder, rgba,
71                                        LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)),
72                                        LLVMConstVector(swizzles, 4), "");
73
74    normalized = FALSE;
75    shift = 0;
76    for (i = 0; i < 4; ++i) {
77       unsigned bits = desc->channel[i].size;
78
79       if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
80          shifts[i] = LLVMGetUndef(LLVMInt32Type());
81          scales[i] =  LLVMGetUndef(LLVMFloatType());
82       }
83       else {
84          unsigned mask = (1 << bits) - 1;
85
86          assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
87          assert(bits < 32);
88
89          shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
90
91          if (desc->channel[i].normalized) {
92             scales[i] = LLVMConstReal(LLVMFloatType(), mask);
93             normalized = TRUE;
94          }
95          else
96             scales[i] =  LLVMConstReal(LLVMFloatType(), 1.0);
97       }
98
99       shift += bits;
100    }
101
102    if (normalized)
103       scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
104    else
105       scaled = unswizzled;
106
107    casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), "");
108
109    shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), "");
110    
111    /* Bitwise or all components */
112    for (i = 0; i < 4; ++i) {
113       if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
114          LLVMValueRef component = LLVMBuildExtractElement(builder, shifted, LLVMConstInt(LLVMInt32Type(), i, 0), "");
115          if (packed)
116             packed = LLVMBuildOr(builder, packed, component, "");
117          else
118             packed = component;
119       }
120    }
121
122    if (!packed)
123       packed = LLVMGetUndef(LLVMInt32Type());
124
125    if (desc->block.bits < 32)
126       packed = LLVMBuildTrunc(builder, packed, type, "");
127
128    return packed;
129 }
130