gallium/swr: add OpenSWR rasterizer
[mesa.git] / src / gallium / drivers / swr / rasterizer / core / format_conversion.h
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * @file format_conversion.h
24 *
25 * @brief API implementation
26 *
27 ******************************************************************************/
28 #include "format_types.h"
29 #include "format_traits.h"
30
31 //////////////////////////////////////////////////////////////////////////
32 /// @brief Load SIMD packed pixels in SOA format and converts to
33 /// SOA RGBA32_FLOAT format.
34 /// @param pSrc - source data in SOA form
35 /// @param dst - output data in SOA form
36 template<SWR_FORMAT SrcFormat>
37 INLINE void LoadSOA(const BYTE *pSrc, simdvector &dst)
38 {
39 // fast path for float32
40 if ((FormatTraits<SrcFormat>::GetType(0) == SWR_TYPE_FLOAT) && (FormatTraits<SrcFormat>::GetBPC(0) == 32))
41 {
42 auto lambda = [&](int comp)
43 {
44 simdscalar vComp = _simd_load_ps((const float*)(pSrc + comp*sizeof(simdscalar)));
45
46 dst.v[FormatTraits<SrcFormat>::swizzle(comp)] = vComp;
47 };
48
49 UnrollerL<0, FormatTraits<SrcFormat>::numComps, 1>::step(lambda);
50 return;
51 }
52
53 auto lambda = [&](int comp)
54 {
55 // load SIMD components
56 simdscalar vComp = FormatTraits<SrcFormat>::loadSOA(comp, pSrc);
57
58 // unpack
59 vComp = FormatTraits<SrcFormat>::unpack(comp, vComp);
60
61 // convert
62 if (FormatTraits<SrcFormat>::isNormalized(comp))
63 {
64 vComp = _simd_cvtepi32_ps(_simd_castps_si(vComp));
65 vComp = _simd_mul_ps(vComp, _simd_set1_ps(FormatTraits<SrcFormat>::toFloat(comp)));
66 }
67
68 dst.v[FormatTraits<SrcFormat>::swizzle(comp)] = vComp;
69
70 pSrc += (FormatTraits<SrcFormat>::GetBPC(comp) * KNOB_SIMD_WIDTH) / 8;
71 };
72
73 UnrollerL<0, FormatTraits<SrcFormat>::numComps, 1>::step(lambda);
74 }
75
76 //////////////////////////////////////////////////////////////////////////
77 /// @brief Clamps the given component based on the requirements on the
78 /// Format template arg
79 /// @param vComp - SIMD vector of floats
80 /// @param Component - component
81 template<SWR_FORMAT Format>
82 INLINE simdscalar Clamp(simdscalar vComp, uint32_t Component)
83 {
84 if (FormatTraits<Format>::isNormalized(Component))
85 {
86 if (FormatTraits<Format>::GetType(Component) == SWR_TYPE_UNORM)
87 {
88 vComp = _simd_max_ps(vComp, _simd_setzero_ps());
89 }
90
91 if (FormatTraits<Format>::GetType(Component) == SWR_TYPE_SNORM)
92 {
93 vComp = _simd_max_ps(vComp, _simd_set1_ps(-1.0f));
94 }
95 vComp = _simd_min_ps(vComp, _simd_set1_ps(1.0f));
96 }
97 else if (FormatTraits<Format>::GetBPC(Component) < 32)
98 {
99 if (FormatTraits<Format>::GetType(Component) == SWR_TYPE_UINT)
100 {
101 int iMax = (1 << FormatTraits<Format>::GetBPC(Component)) - 1;
102 int iMin = 0;
103 simdscalari vCompi = _simd_castps_si(vComp);
104 vCompi = _simd_max_epu32(vCompi, _simd_set1_epi32(iMin));
105 vCompi = _simd_min_epu32(vCompi, _simd_set1_epi32(iMax));
106 vComp = _simd_castsi_ps(vCompi);
107 }
108 else if (FormatTraits<Format>::GetType(Component) == SWR_TYPE_SINT)
109 {
110 int iMax = (1 << (FormatTraits<Format>::GetBPC(Component) - 1)) - 1;
111 int iMin = -1 - iMax;
112 simdscalari vCompi = _simd_castps_si(vComp);
113 vCompi = _simd_max_epi32(vCompi, _simd_set1_epi32(iMin));
114 vCompi = _simd_min_epi32(vCompi, _simd_set1_epi32(iMax));
115 vComp = _simd_castsi_ps(vCompi);
116 }
117 }
118
119 return vComp;
120 }
121
122 //////////////////////////////////////////////////////////////////////////
123 /// @brief Normalize the given component based on the requirements on the
124 /// Format template arg
125 /// @param vComp - SIMD vector of floats
126 /// @param Component - component
127 template<SWR_FORMAT Format>
128 INLINE simdscalar Normalize(simdscalar vComp, uint32_t Component)
129 {
130 if (FormatTraits<Format>::isNormalized(Component))
131 {
132 vComp = _simd_mul_ps(vComp, _simd_set1_ps(FormatTraits<Format>::fromFloat(Component)));
133 vComp = _simd_castsi_ps(_simd_cvtps_epi32(vComp));
134 }
135 return vComp;
136 }
137
138 //////////////////////////////////////////////////////////////////////////
139 /// @brief Convert and store simdvector of pixels in SOA
140 /// RGBA32_FLOAT to SOA format
141 /// @param src - source data in SOA form
142 /// @param dst - output data in SOA form
143 template<SWR_FORMAT DstFormat>
144 INLINE void StoreSOA(const simdvector &src, BYTE *pDst)
145 {
146 // fast path for float32
147 if ((FormatTraits<DstFormat>::GetType(0) == SWR_TYPE_FLOAT) && (FormatTraits<DstFormat>::GetBPC(0) == 32))
148 {
149 for (uint32_t comp = 0; comp < FormatTraits<DstFormat>::numComps; ++comp)
150 {
151 simdscalar vComp = src.v[FormatTraits<DstFormat>::swizzle(comp)];
152
153 // Gamma-correct
154 if (FormatTraits<DstFormat>::isSRGB)
155 {
156 if (comp < 3) // Input format is always RGBA32_FLOAT.
157 {
158 vComp = FormatTraits<R32G32B32A32_FLOAT>::convertSrgb(comp, vComp);
159 }
160 }
161
162 _simd_store_ps((float*)(pDst + comp*sizeof(simdscalar)), vComp);
163 }
164 return;
165 }
166
167 auto lambda = [&](int comp)
168 {
169 simdscalar vComp = src.v[FormatTraits<DstFormat>::swizzle(comp)];
170
171 // Gamma-correct
172 if (FormatTraits<DstFormat>::isSRGB)
173 {
174 if (comp < 3) // Input format is always RGBA32_FLOAT.
175 {
176 vComp = FormatTraits<R32G32B32A32_FLOAT>::convertSrgb(comp, vComp);
177 }
178 }
179
180 // clamp
181 vComp = Clamp<DstFormat>(vComp, comp);
182
183 // normalize
184 vComp = Normalize<DstFormat>(vComp, comp);
185
186 // pack
187 vComp = FormatTraits<DstFormat>::pack(comp, vComp);
188
189 // store
190 FormatTraits<DstFormat>::storeSOA(comp, pDst, vComp);
191
192 pDst += (FormatTraits<DstFormat>::GetBPC(comp) * KNOB_SIMD_WIDTH) / 8;
193 };
194
195 UnrollerL<0, FormatTraits<DstFormat>::numComps, 1>::step(lambda);
196 }