blob: e06f2bd8be6806435e128adeee79cdf8f056a326 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "Surface.hpp"
16
17#include "Color.hpp"
18#include "Context.hpp"
Alexis Hetu0de50d42015-09-09 13:56:41 -040019#include "ETC_Decoder.hpp"
John Bauman19bac1e2014-05-06 15:23:49 -040020#include "Renderer.hpp"
John Bauman89401822014-05-06 15:04:28 -040021#include "Common/Half.hpp"
22#include "Common/Memory.hpp"
23#include "Common/CPUID.hpp"
24#include "Common/Resource.hpp"
25#include "Common/Debug.hpp"
John Bauman19bac1e2014-05-06 15:23:49 -040026#include "Reactor/Reactor.hpp"
John Bauman89401822014-05-06 15:04:28 -040027
Nicolas Capens47dc8672017-04-25 12:54:39 -040028#if defined(__i386__) || defined(__x86_64__)
29 #include <xmmintrin.h>
30 #include <emmintrin.h>
31#endif
John Bauman89401822014-05-06 15:04:28 -040032
33#undef min
34#undef max
35
36namespace sw
37{
38 extern bool quadLayoutEnabled;
39 extern bool complementaryDepthBuffer;
40 extern TranscendentalPrecision logPrecision;
41
42 unsigned int *Surface::palette = 0;
43 unsigned int Surface::paletteID = 0;
44
45 void Surface::Buffer::write(int x, int y, int z, const Color<float> &color)
46 {
Alexis Hetu1fa20672018-06-18 15:19:55 -040047 ASSERT((x >= -border) && (x < (width + border)));
48 ASSERT((y >= -border) && (y < (height + border)));
49 ASSERT((z >= 0) && (z < depth));
Nicolas Capens700a1a62018-06-15 11:41:28 -040050
Nicolas Capensbfa23b32017-12-11 10:06:37 -050051 byte *element = (byte*)buffer + (x + border) * bytes + (y + border) * pitchB + z * samples * sliceB;
John Bauman89401822014-05-06 15:04:28 -040052
Nicolas Capensbfa23b32017-12-11 10:06:37 -050053 for(int i = 0; i < samples; i++)
54 {
55 write(element, color);
56 element += sliceB;
57 }
John Bauman89401822014-05-06 15:04:28 -040058 }
59
60 void Surface::Buffer::write(int x, int y, const Color<float> &color)
61 {
Alexis Hetu1fa20672018-06-18 15:19:55 -040062 ASSERT((x >= -border) && (x < (width + border)));
63 ASSERT((y >= -border) && (y < (height + border)));
Nicolas Capens700a1a62018-06-15 11:41:28 -040064
Nicolas Capensbfa23b32017-12-11 10:06:37 -050065 byte *element = (byte*)buffer + (x + border) * bytes + (y + border) * pitchB;
John Bauman89401822014-05-06 15:04:28 -040066
Nicolas Capensbfa23b32017-12-11 10:06:37 -050067 for(int i = 0; i < samples; i++)
68 {
69 write(element, color);
70 element += sliceB;
71 }
John Bauman89401822014-05-06 15:04:28 -040072 }
73
74 inline void Surface::Buffer::write(void *element, const Color<float> &color)
75 {
Nicolas Capens1efac522017-12-01 16:59:38 -050076 float r = color.r;
77 float g = color.g;
78 float b = color.b;
79 float a = color.a;
80
81 if(isSRGBformat(format))
82 {
83 r = linearToSRGB(r);
84 g = linearToSRGB(g);
85 b = linearToSRGB(b);
86 }
87
John Bauman89401822014-05-06 15:04:28 -040088 switch(format)
89 {
90 case FORMAT_A8:
Nicolas Capens1efac522017-12-01 16:59:38 -050091 *(unsigned char*)element = unorm<8>(a);
John Bauman89401822014-05-06 15:04:28 -040092 break;
Nicolas Capens975adb72017-12-19 15:34:20 -050093 case FORMAT_R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -050094 *(char*)element = snorm<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040095 break;
John Bauman89401822014-05-06 15:04:28 -040096 case FORMAT_R8:
Nicolas Capens1efac522017-12-01 16:59:38 -050097 *(unsigned char*)element = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -040098 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040099 case FORMAT_R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500100 *(char*)element = scast<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400101 break;
102 case FORMAT_R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500103 *(unsigned char*)element = ucast<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400104 break;
105 case FORMAT_R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500106 *(short*)element = scast<16>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400107 break;
108 case FORMAT_R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500109 *(unsigned short*)element = ucast<16>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400110 break;
111 case FORMAT_R32I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500112 *(int*)element = static_cast<int>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400113 break;
114 case FORMAT_R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500115 *(unsigned int*)element = static_cast<unsigned int>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400116 break;
John Bauman89401822014-05-06 15:04:28 -0400117 case FORMAT_R3G3B2:
Nicolas Capens1efac522017-12-01 16:59:38 -0500118 *(unsigned char*)element = (unorm<3>(r) << 5) | (unorm<3>(g) << 2) | (unorm<2>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400119 break;
120 case FORMAT_A8R3G3B2:
Nicolas Capens1efac522017-12-01 16:59:38 -0500121 *(unsigned short*)element = (unorm<8>(a) << 8) | (unorm<3>(r) << 5) | (unorm<3>(g) << 2) | (unorm<2>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400122 break;
123 case FORMAT_X4R4G4B4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500124 *(unsigned short*)element = 0xF000 | (unorm<4>(r) << 8) | (unorm<4>(g) << 4) | (unorm<4>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400125 break;
126 case FORMAT_A4R4G4B4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500127 *(unsigned short*)element = (unorm<4>(a) << 12) | (unorm<4>(r) << 8) | (unorm<4>(g) << 4) | (unorm<4>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400128 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400129 case FORMAT_R4G4B4A4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500130 *(unsigned short*)element = (unorm<4>(r) << 12) | (unorm<4>(g) << 8) | (unorm<4>(b) << 4) | (unorm<4>(a) << 0);
Nicolas Capens80594422015-06-09 16:42:56 -0400131 break;
John Bauman89401822014-05-06 15:04:28 -0400132 case FORMAT_R5G6B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500133 *(unsigned short*)element = (unorm<5>(r) << 11) | (unorm<6>(g) << 5) | (unorm<5>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400134 break;
135 case FORMAT_A1R5G5B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500136 *(unsigned short*)element = (unorm<1>(a) << 15) | (unorm<5>(r) << 10) | (unorm<5>(g) << 5) | (unorm<5>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400137 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400138 case FORMAT_R5G5B5A1:
Nicolas Capens1efac522017-12-01 16:59:38 -0500139 *(unsigned short*)element = (unorm<5>(r) << 11) | (unorm<5>(g) << 6) | (unorm<5>(b) << 1) | (unorm<5>(a) << 0);
Nicolas Capens80594422015-06-09 16:42:56 -0400140 break;
John Bauman89401822014-05-06 15:04:28 -0400141 case FORMAT_X1R5G5B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500142 *(unsigned short*)element = 0x8000 | (unorm<5>(r) << 10) | (unorm<5>(g) << 5) | (unorm<5>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400143 break;
144 case FORMAT_A8R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500145 *(unsigned int*)element = (unorm<8>(a) << 24) | (unorm<8>(r) << 16) | (unorm<8>(g) << 8) | (unorm<8>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400146 break;
147 case FORMAT_X8R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500148 *(unsigned int*)element = 0xFF000000 | (unorm<8>(r) << 16) | (unorm<8>(g) << 8) | (unorm<8>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400149 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500150 case FORMAT_A8B8G8R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -0500151 *(unsigned int*)element = (static_cast<unsigned int>(snorm<8>(a)) << 24) |
152 (static_cast<unsigned int>(snorm<8>(b)) << 16) |
153 (static_cast<unsigned int>(snorm<8>(g)) << 8) |
154 (static_cast<unsigned int>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400155 break;
John Bauman89401822014-05-06 15:04:28 -0400156 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400157 case FORMAT_SRGB8_A8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500158 *(unsigned int*)element = (unorm<8>(a) << 24) | (unorm<8>(b) << 16) | (unorm<8>(g) << 8) | (unorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400159 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400160 case FORMAT_A8B8G8R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500161 *(unsigned int*)element = (static_cast<unsigned int>(scast<8>(a)) << 24) |
162 (static_cast<unsigned int>(scast<8>(b)) << 16) |
163 (static_cast<unsigned int>(scast<8>(g)) << 8) |
164 (static_cast<unsigned int>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400165 break;
166 case FORMAT_A8B8G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500167 *(unsigned int*)element = (ucast<8>(a) << 24) | (ucast<8>(b) << 16) | (ucast<8>(g) << 8) | (ucast<8>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400168 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500169 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400170 *(unsigned int*)element = 0x7F000000 |
Nicolas Capens1efac522017-12-01 16:59:38 -0500171 (static_cast<unsigned int>(snorm<8>(b)) << 16) |
172 (static_cast<unsigned int>(snorm<8>(g)) << 8) |
173 (static_cast<unsigned int>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400174 break;
John Bauman89401822014-05-06 15:04:28 -0400175 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400176 case FORMAT_SRGB8_X8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500177 *(unsigned int*)element = 0xFF000000 | (unorm<8>(b) << 16) | (unorm<8>(g) << 8) | (unorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400178 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400179 case FORMAT_X8B8G8R8I:
180 *(unsigned int*)element = 0x7F000000 |
Nicolas Capens1efac522017-12-01 16:59:38 -0500181 (static_cast<unsigned int>(scast<8>(b)) << 16) |
182 (static_cast<unsigned int>(scast<8>(g)) << 8) |
183 (static_cast<unsigned int>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400184 case FORMAT_X8B8G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500185 *(unsigned int*)element = 0xFF000000 | (ucast<8>(b) << 16) | (ucast<8>(g) << 8) | (ucast<8>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400186 break;
John Bauman89401822014-05-06 15:04:28 -0400187 case FORMAT_A2R10G10B10:
Nicolas Capens1efac522017-12-01 16:59:38 -0500188 *(unsigned int*)element = (unorm<2>(a) << 30) | (unorm<10>(r) << 20) | (unorm<10>(g) << 10) | (unorm<10>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400189 break;
190 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -0500191 case FORMAT_A2B10G10R10UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500192 *(unsigned int*)element = (unorm<2>(a) << 30) | (unorm<10>(b) << 20) | (unorm<10>(g) << 10) | (unorm<10>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400193 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500194 case FORMAT_G8R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -0500195 *(unsigned short*)element = (static_cast<unsigned short>(snorm<8>(g)) << 8) |
196 (static_cast<unsigned short>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400197 break;
John Bauman89401822014-05-06 15:04:28 -0400198 case FORMAT_G8R8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500199 *(unsigned short*)element = (unorm<8>(g) << 8) | (unorm<8>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400200 break;
201 case FORMAT_G8R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500202 *(unsigned short*)element = (static_cast<unsigned short>(scast<8>(g)) << 8) |
203 (static_cast<unsigned short>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400204 break;
205 case FORMAT_G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500206 *(unsigned short*)element = (ucast<8>(g) << 8) | (ucast<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400207 break;
208 case FORMAT_G16R16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500209 *(unsigned int*)element = (unorm<16>(g) << 16) | (unorm<16>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400210 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400211 case FORMAT_G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500212 *(unsigned int*)element = (static_cast<unsigned int>(scast<16>(g)) << 16) |
213 (static_cast<unsigned int>(scast<16>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400214 break;
215 case FORMAT_G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500216 *(unsigned int*)element = (ucast<16>(g) << 16) | (ucast<16>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400217 break;
218 case FORMAT_G32R32I:
219 case FORMAT_G32R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500220 ((unsigned int*)element)[0] = static_cast<unsigned int>(r);
221 ((unsigned int*)element)[1] = static_cast<unsigned int>(g);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400222 break;
John Bauman89401822014-05-06 15:04:28 -0400223 case FORMAT_A16B16G16R16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500224 ((unsigned short*)element)[0] = unorm<16>(r);
225 ((unsigned short*)element)[1] = unorm<16>(g);
226 ((unsigned short*)element)[2] = unorm<16>(b);
227 ((unsigned short*)element)[3] = unorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400228 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400229 case FORMAT_A16B16G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500230 ((unsigned short*)element)[0] = static_cast<unsigned short>(scast<16>(r));
231 ((unsigned short*)element)[1] = static_cast<unsigned short>(scast<16>(g));
232 ((unsigned short*)element)[2] = static_cast<unsigned short>(scast<16>(b));
233 ((unsigned short*)element)[3] = static_cast<unsigned short>(scast<16>(a));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400234 break;
235 case FORMAT_A16B16G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500236 ((unsigned short*)element)[0] = static_cast<unsigned short>(ucast<16>(r));
237 ((unsigned short*)element)[1] = static_cast<unsigned short>(ucast<16>(g));
238 ((unsigned short*)element)[2] = static_cast<unsigned short>(ucast<16>(b));
239 ((unsigned short*)element)[3] = static_cast<unsigned short>(ucast<16>(a));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400240 break;
241 case FORMAT_X16B16G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500242 ((unsigned short*)element)[0] = static_cast<unsigned short>(scast<16>(r));
243 ((unsigned short*)element)[1] = static_cast<unsigned short>(scast<16>(g));
244 ((unsigned short*)element)[2] = static_cast<unsigned short>(scast<16>(b));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400245 break;
246 case FORMAT_X16B16G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500247 ((unsigned short*)element)[0] = static_cast<unsigned short>(ucast<16>(r));
248 ((unsigned short*)element)[1] = static_cast<unsigned short>(ucast<16>(g));
249 ((unsigned short*)element)[2] = static_cast<unsigned short>(ucast<16>(b));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400250 break;
251 case FORMAT_A32B32G32R32I:
252 case FORMAT_A32B32G32R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500253 ((unsigned int*)element)[0] = static_cast<unsigned int>(r);
254 ((unsigned int*)element)[1] = static_cast<unsigned int>(g);
255 ((unsigned int*)element)[2] = static_cast<unsigned int>(b);
256 ((unsigned int*)element)[3] = static_cast<unsigned int>(a);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400257 break;
258 case FORMAT_X32B32G32R32I:
259 case FORMAT_X32B32G32R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500260 ((unsigned int*)element)[0] = static_cast<unsigned int>(r);
261 ((unsigned int*)element)[1] = static_cast<unsigned int>(g);
262 ((unsigned int*)element)[2] = static_cast<unsigned int>(b);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400263 break;
John Bauman89401822014-05-06 15:04:28 -0400264 case FORMAT_V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500265 *(unsigned short*)element = (snorm<8>(g) << 8) | (snorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400266 break;
267 case FORMAT_L6V5U5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500268 *(unsigned short*)element = (unorm<6>(b) << 10) | (snorm<5>(g) << 5) | (snorm<5>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400269 break;
270 case FORMAT_Q8W8V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500271 *(unsigned int*)element = (snorm<8>(a) << 24) | (snorm<8>(b) << 16) | (snorm<8>(g) << 8) | (snorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400272 break;
273 case FORMAT_X8L8V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500274 *(unsigned int*)element = 0xFF000000 | (unorm<8>(b) << 16) | (snorm<8>(g) << 8) | (snorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400275 break;
276 case FORMAT_V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500277 *(unsigned int*)element = (snorm<16>(g) << 16) | (snorm<16>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400278 break;
279 case FORMAT_A2W10V10U10:
Nicolas Capens1efac522017-12-01 16:59:38 -0500280 *(unsigned int*)element = (unorm<2>(a) << 30) | (snorm<10>(b) << 20) | (snorm<10>(g) << 10) | (snorm<10>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400281 break;
282 case FORMAT_A16W16V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500283 ((unsigned short*)element)[0] = snorm<16>(r);
284 ((unsigned short*)element)[1] = snorm<16>(g);
285 ((unsigned short*)element)[2] = snorm<16>(b);
286 ((unsigned short*)element)[3] = unorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400287 break;
288 case FORMAT_Q16W16V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500289 ((unsigned short*)element)[0] = snorm<16>(r);
290 ((unsigned short*)element)[1] = snorm<16>(g);
291 ((unsigned short*)element)[2] = snorm<16>(b);
292 ((unsigned short*)element)[3] = snorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400293 break;
294 case FORMAT_R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500295 ((unsigned char*)element)[0] = unorm<8>(b);
296 ((unsigned char*)element)[1] = unorm<8>(g);
297 ((unsigned char*)element)[2] = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400298 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400299 case FORMAT_B8G8R8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500300 ((unsigned char*)element)[0] = unorm<8>(r);
301 ((unsigned char*)element)[1] = unorm<8>(g);
302 ((unsigned char*)element)[2] = unorm<8>(b);
Nicolas Capens80594422015-06-09 16:42:56 -0400303 break;
John Bauman89401822014-05-06 15:04:28 -0400304 case FORMAT_R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500305 *(half*)element = (half)r;
John Bauman89401822014-05-06 15:04:28 -0400306 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400307 case FORMAT_A16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500308 *(half*)element = (half)a;
Nicolas Capens80594422015-06-09 16:42:56 -0400309 break;
John Bauman89401822014-05-06 15:04:28 -0400310 case FORMAT_G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500311 ((half*)element)[0] = (half)r;
312 ((half*)element)[1] = (half)g;
John Bauman89401822014-05-06 15:04:28 -0400313 break;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500314 case FORMAT_X16B16G16R16F_UNSIGNED:
315 r = max(r, 0.0f); g = max(g, 0.0f); b = max(b, 0.0f);
316 // Fall through to FORMAT_X16B16G16R16F.
Nicolas Capensa6bc61d2017-12-20 11:07:45 -0500317 case FORMAT_X16B16G16R16F:
318 ((half*)element)[3] = 1.0f;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500319 // Fall through to FORMAT_B16G16R16F.
Nicolas Capens80594422015-06-09 16:42:56 -0400320 case FORMAT_B16G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500321 ((half*)element)[0] = (half)r;
322 ((half*)element)[1] = (half)g;
323 ((half*)element)[2] = (half)b;
Nicolas Capens80594422015-06-09 16:42:56 -0400324 break;
John Bauman89401822014-05-06 15:04:28 -0400325 case FORMAT_A16B16G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500326 ((half*)element)[0] = (half)r;
327 ((half*)element)[1] = (half)g;
328 ((half*)element)[2] = (half)b;
329 ((half*)element)[3] = (half)a;
John Bauman89401822014-05-06 15:04:28 -0400330 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400331 case FORMAT_A32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500332 *(float*)element = a;
Nicolas Capens80594422015-06-09 16:42:56 -0400333 break;
John Bauman89401822014-05-06 15:04:28 -0400334 case FORMAT_R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500335 *(float*)element = r;
John Bauman89401822014-05-06 15:04:28 -0400336 break;
337 case FORMAT_G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500338 ((float*)element)[0] = r;
339 ((float*)element)[1] = g;
John Bauman89401822014-05-06 15:04:28 -0400340 break;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500341 case FORMAT_X32B32G32R32F_UNSIGNED:
342 r = max(r, 0.0f); g = max(g, 0.0f); b = max(b, 0.0f);
343 // Fall through to FORMAT_X32B32G32R32F.
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400344 case FORMAT_X32B32G32R32F:
345 ((float*)element)[3] = 1.0f;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500346 // Fall through to FORMAT_B32G32R32F.
Nicolas Capens80594422015-06-09 16:42:56 -0400347 case FORMAT_B32G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500348 ((float*)element)[0] = r;
349 ((float*)element)[1] = g;
350 ((float*)element)[2] = b;
Nicolas Capens80594422015-06-09 16:42:56 -0400351 break;
John Bauman89401822014-05-06 15:04:28 -0400352 case FORMAT_A32B32G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500353 ((float*)element)[0] = r;
354 ((float*)element)[1] = g;
355 ((float*)element)[2] = b;
356 ((float*)element)[3] = a;
John Bauman89401822014-05-06 15:04:28 -0400357 break;
358 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500359 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -0400360 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400361 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500362 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -0400363 case FORMAT_D32FS8_SHADOW:
Nicolas Capens1efac522017-12-01 16:59:38 -0500364 *((float*)element) = r;
John Bauman89401822014-05-06 15:04:28 -0400365 break;
366 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500367 case FORMAT_D32FS8_COMPLEMENTARY:
Nicolas Capens1efac522017-12-01 16:59:38 -0500368 *((float*)element) = 1 - r;
John Bauman89401822014-05-06 15:04:28 -0400369 break;
370 case FORMAT_S8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500371 *((unsigned char*)element) = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400372 break;
373 case FORMAT_L8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500374 *(unsigned char*)element = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400375 break;
376 case FORMAT_A4L4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500377 *(unsigned char*)element = (unorm<4>(a) << 4) | (unorm<4>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400378 break;
379 case FORMAT_L16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500380 *(unsigned short*)element = unorm<16>(r);
John Bauman89401822014-05-06 15:04:28 -0400381 break;
382 case FORMAT_A8L8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500383 *(unsigned short*)element = (unorm<8>(a) << 8) | (unorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400384 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400385 case FORMAT_L16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500386 *(half*)element = (half)r;
Nicolas Capens80594422015-06-09 16:42:56 -0400387 break;
388 case FORMAT_A16L16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500389 ((half*)element)[0] = (half)r;
390 ((half*)element)[1] = (half)a;
Nicolas Capens80594422015-06-09 16:42:56 -0400391 break;
392 case FORMAT_L32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500393 *(float*)element = r;
Nicolas Capens80594422015-06-09 16:42:56 -0400394 break;
395 case FORMAT_A32L32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500396 ((float*)element)[0] = r;
397 ((float*)element)[1] = a;
Nicolas Capens80594422015-06-09 16:42:56 -0400398 break;
John Bauman89401822014-05-06 15:04:28 -0400399 default:
400 ASSERT(false);
401 }
402 }
403
404 Color<float> Surface::Buffer::read(int x, int y, int z) const
405 {
Alexis Hetu1fa20672018-06-18 15:19:55 -0400406 ASSERT((x >= -border) && (x < (width + border)));
407 ASSERT((y >= -border) && (y < (height + border)));
408 ASSERT((z >= 0) && (z < depth));
Nicolas Capens700a1a62018-06-15 11:41:28 -0400409
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500410 void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB + z * samples * sliceB;
John Bauman89401822014-05-06 15:04:28 -0400411
412 return read(element);
413 }
414
415 Color<float> Surface::Buffer::read(int x, int y) const
416 {
Alexis Hetu1fa20672018-06-18 15:19:55 -0400417 ASSERT((x >= -border) && (x < (width + border)));
418 ASSERT((y >= -border) && (y < (height + border)));
Nicolas Capens700a1a62018-06-15 11:41:28 -0400419
Alexis Hetu9c6d5222016-11-29 17:02:14 -0500420 void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB;
John Bauman89401822014-05-06 15:04:28 -0400421
422 return read(element);
423 }
424
425 inline Color<float> Surface::Buffer::read(void *element) const
426 {
Nicolas Capens3f439242015-06-09 16:33:50 -0400427 float r = 0.0f;
428 float g = 0.0f;
429 float b = 0.0f;
430 float a = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400431
432 switch(format)
433 {
434 case FORMAT_P8:
435 {
436 ASSERT(palette);
437
438 unsigned int abgr = palette[*(unsigned char*)element];
Nicolas Capensc39901e2016-03-21 16:37:44 -0400439
John Bauman89401822014-05-06 15:04:28 -0400440 r = (abgr & 0x000000FF) * (1.0f / 0x000000FF);
441 g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00);
442 b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000);
443 a = (abgr & 0xFF000000) * (1.0f / 0xFF000000);
444 }
445 break;
446 case FORMAT_A8P8:
447 {
448 ASSERT(palette);
449
450 unsigned int bgr = palette[((unsigned char*)element)[0]];
Nicolas Capensc39901e2016-03-21 16:37:44 -0400451
John Bauman89401822014-05-06 15:04:28 -0400452 r = (bgr & 0x000000FF) * (1.0f / 0x000000FF);
453 g = (bgr & 0x0000FF00) * (1.0f / 0x0000FF00);
454 b = (bgr & 0x00FF0000) * (1.0f / 0x00FF0000);
455 a = ((unsigned char*)element)[1] * (1.0f / 0xFF);
456 }
457 break;
458 case FORMAT_A8:
459 r = 0;
460 g = 0;
461 b = 0;
462 a = *(unsigned char*)element * (1.0f / 0xFF);
463 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500464 case FORMAT_R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400465 r = max((*(signed char*)element) * (1.0f / 0x7F), -1.0f);
466 break;
John Bauman89401822014-05-06 15:04:28 -0400467 case FORMAT_R8:
468 r = *(unsigned char*)element * (1.0f / 0xFF);
469 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400470 case FORMAT_R8I:
471 r = *(signed char*)element;
472 break;
473 case FORMAT_R8UI:
474 r = *(unsigned char*)element;
475 break;
John Bauman89401822014-05-06 15:04:28 -0400476 case FORMAT_R3G3B2:
477 {
478 unsigned char rgb = *(unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400479
John Bauman89401822014-05-06 15:04:28 -0400480 r = (rgb & 0xE0) * (1.0f / 0xE0);
481 g = (rgb & 0x1C) * (1.0f / 0x1C);
482 b = (rgb & 0x03) * (1.0f / 0x03);
483 }
484 break;
485 case FORMAT_A8R3G3B2:
486 {
487 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400488
John Bauman89401822014-05-06 15:04:28 -0400489 a = (argb & 0xFF00) * (1.0f / 0xFF00);
490 r = (argb & 0x00E0) * (1.0f / 0x00E0);
491 g = (argb & 0x001C) * (1.0f / 0x001C);
492 b = (argb & 0x0003) * (1.0f / 0x0003);
493 }
494 break;
495 case FORMAT_X4R4G4B4:
496 {
497 unsigned short rgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400498
John Bauman89401822014-05-06 15:04:28 -0400499 r = (rgb & 0x0F00) * (1.0f / 0x0F00);
500 g = (rgb & 0x00F0) * (1.0f / 0x00F0);
501 b = (rgb & 0x000F) * (1.0f / 0x000F);
502 }
503 break;
504 case FORMAT_A4R4G4B4:
505 {
506 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400507
John Bauman89401822014-05-06 15:04:28 -0400508 a = (argb & 0xF000) * (1.0f / 0xF000);
509 r = (argb & 0x0F00) * (1.0f / 0x0F00);
510 g = (argb & 0x00F0) * (1.0f / 0x00F0);
511 b = (argb & 0x000F) * (1.0f / 0x000F);
512 }
513 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400514 case FORMAT_R4G4B4A4:
515 {
516 unsigned short rgba = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400517
Nicolas Capens80594422015-06-09 16:42:56 -0400518 r = (rgba & 0xF000) * (1.0f / 0xF000);
519 g = (rgba & 0x0F00) * (1.0f / 0x0F00);
520 b = (rgba & 0x00F0) * (1.0f / 0x00F0);
521 a = (rgba & 0x000F) * (1.0f / 0x000F);
522 }
523 break;
John Bauman89401822014-05-06 15:04:28 -0400524 case FORMAT_R5G6B5:
525 {
526 unsigned short rgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400527
John Bauman89401822014-05-06 15:04:28 -0400528 r = (rgb & 0xF800) * (1.0f / 0xF800);
529 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
530 b = (rgb & 0x001F) * (1.0f / 0x001F);
531 }
532 break;
533 case FORMAT_A1R5G5B5:
534 {
535 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400536
John Bauman89401822014-05-06 15:04:28 -0400537 a = (argb & 0x8000) * (1.0f / 0x8000);
538 r = (argb & 0x7C00) * (1.0f / 0x7C00);
539 g = (argb & 0x03E0) * (1.0f / 0x03E0);
540 b = (argb & 0x001F) * (1.0f / 0x001F);
541 }
542 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400543 case FORMAT_R5G5B5A1:
544 {
545 unsigned short rgba = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400546
Nicolas Capens80594422015-06-09 16:42:56 -0400547 r = (rgba & 0xF800) * (1.0f / 0xF800);
548 g = (rgba & 0x07C0) * (1.0f / 0x07C0);
549 b = (rgba & 0x003E) * (1.0f / 0x003E);
550 a = (rgba & 0x0001) * (1.0f / 0x0001);
551 }
552 break;
John Bauman89401822014-05-06 15:04:28 -0400553 case FORMAT_X1R5G5B5:
554 {
555 unsigned short xrgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400556
John Bauman89401822014-05-06 15:04:28 -0400557 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
558 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
559 b = (xrgb & 0x001F) * (1.0f / 0x001F);
560 }
561 break;
562 case FORMAT_A8R8G8B8:
563 {
564 unsigned int argb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400565
John Bauman89401822014-05-06 15:04:28 -0400566 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
567 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
568 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
569 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
570 }
571 break;
572 case FORMAT_X8R8G8B8:
573 {
574 unsigned int xrgb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400575
John Bauman89401822014-05-06 15:04:28 -0400576 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
577 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
578 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
579 }
580 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500581 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400582 {
583 signed char* abgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400584
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400585 r = max(abgr[0] * (1.0f / 0x7F), -1.0f);
586 g = max(abgr[1] * (1.0f / 0x7F), -1.0f);
587 b = max(abgr[2] * (1.0f / 0x7F), -1.0f);
588 a = max(abgr[3] * (1.0f / 0x7F), -1.0f);
589 }
590 break;
John Bauman89401822014-05-06 15:04:28 -0400591 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400592 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400593 {
594 unsigned int abgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400595
John Bauman89401822014-05-06 15:04:28 -0400596 a = (abgr & 0xFF000000) * (1.0f / 0xFF000000);
597 b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000);
598 g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00);
599 r = (abgr & 0x000000FF) * (1.0f / 0x000000FF);
600 }
601 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400602 case FORMAT_A8B8G8R8I:
603 {
604 signed char* abgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400605
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400606 r = abgr[0];
607 g = abgr[1];
608 b = abgr[2];
609 a = abgr[3];
610 }
611 break;
612 case FORMAT_A8B8G8R8UI:
613 {
614 unsigned char* abgr = (unsigned char*)element;
615
616 r = abgr[0];
617 g = abgr[1];
618 b = abgr[2];
619 a = abgr[3];
620 }
621 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500622 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400623 {
624 signed char* bgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400625
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400626 r = max(bgr[0] * (1.0f / 0x7F), -1.0f);
627 g = max(bgr[1] * (1.0f / 0x7F), -1.0f);
628 b = max(bgr[2] * (1.0f / 0x7F), -1.0f);
629 }
630 break;
John Bauman89401822014-05-06 15:04:28 -0400631 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400632 case FORMAT_SRGB8_X8:
John Bauman89401822014-05-06 15:04:28 -0400633 {
634 unsigned int xbgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400635
John Bauman89401822014-05-06 15:04:28 -0400636 b = (xbgr & 0x00FF0000) * (1.0f / 0x00FF0000);
637 g = (xbgr & 0x0000FF00) * (1.0f / 0x0000FF00);
638 r = (xbgr & 0x000000FF) * (1.0f / 0x000000FF);
639 }
640 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400641 case FORMAT_X8B8G8R8I:
642 {
643 signed char* bgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400644
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400645 r = bgr[0];
646 g = bgr[1];
647 b = bgr[2];
648 }
649 break;
650 case FORMAT_X8B8G8R8UI:
651 {
652 unsigned char* bgr = (unsigned char*)element;
653
654 r = bgr[0];
655 g = bgr[1];
656 b = bgr[2];
657 }
658 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500659 case FORMAT_G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400660 {
661 signed char* gr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400662
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400663 r = (gr[0] & 0xFF00) * (1.0f / 0xFF00);
664 g = (gr[1] & 0x00FF) * (1.0f / 0x00FF);
665 }
666 break;
John Bauman89401822014-05-06 15:04:28 -0400667 case FORMAT_G8R8:
668 {
669 unsigned short gr = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400670
John Bauman89401822014-05-06 15:04:28 -0400671 g = (gr & 0xFF00) * (1.0f / 0xFF00);
672 r = (gr & 0x00FF) * (1.0f / 0x00FF);
673 }
674 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400675 case FORMAT_G8R8I:
676 {
677 signed char* gr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400678
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400679 r = gr[0];
680 g = gr[1];
681 }
682 break;
683 case FORMAT_G8R8UI:
684 {
685 unsigned char* gr = (unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400686
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400687 r = gr[0];
688 g = gr[1];
689 }
690 break;
691 case FORMAT_R16I:
692 r = *((short*)element);
693 break;
694 case FORMAT_R16UI:
695 r = *((unsigned short*)element);
696 break;
697 case FORMAT_G16R16I:
698 {
699 short* gr = (short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400700
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400701 r = gr[0];
702 g = gr[1];
703 }
704 break;
John Bauman89401822014-05-06 15:04:28 -0400705 case FORMAT_G16R16:
706 {
707 unsigned int gr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400708
John Bauman89401822014-05-06 15:04:28 -0400709 g = (gr & 0xFFFF0000) * (1.0f / 0xFFFF0000);
710 r = (gr & 0x0000FFFF) * (1.0f / 0x0000FFFF);
711 }
712 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400713 case FORMAT_G16R16UI:
714 {
715 unsigned short* gr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400716
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400717 r = gr[0];
718 g = gr[1];
719 }
720 break;
John Bauman89401822014-05-06 15:04:28 -0400721 case FORMAT_A2R10G10B10:
722 {
723 unsigned int argb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400724
John Bauman89401822014-05-06 15:04:28 -0400725 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
726 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
727 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
728 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
729 }
730 break;
731 case FORMAT_A2B10G10R10:
732 {
733 unsigned int abgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400734
John Bauman89401822014-05-06 15:04:28 -0400735 a = (abgr & 0xC0000000) * (1.0f / 0xC0000000);
736 b = (abgr & 0x3FF00000) * (1.0f / 0x3FF00000);
737 g = (abgr & 0x000FFC00) * (1.0f / 0x000FFC00);
738 r = (abgr & 0x000003FF) * (1.0f / 0x000003FF);
739 }
740 break;
Nicolas Capens5555af42017-12-14 13:14:03 -0500741 case FORMAT_A2B10G10R10UI:
742 {
743 unsigned int abgr = *(unsigned int*)element;
744
745 a = static_cast<float>((abgr & 0xC0000000) >> 30);
746 b = static_cast<float>((abgr & 0x3FF00000) >> 20);
747 g = static_cast<float>((abgr & 0x000FFC00) >> 10);
748 r = static_cast<float>(abgr & 0x000003FF);
749 }
750 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400751 case FORMAT_A16B16G16R16I:
752 {
753 short* abgr = (short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400754
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400755 r = abgr[0];
756 g = abgr[1];
757 b = abgr[2];
758 a = abgr[3];
759 }
760 break;
John Bauman89401822014-05-06 15:04:28 -0400761 case FORMAT_A16B16G16R16:
762 r = ((unsigned short*)element)[0] * (1.0f / 0xFFFF);
763 g = ((unsigned short*)element)[1] * (1.0f / 0xFFFF);
764 b = ((unsigned short*)element)[2] * (1.0f / 0xFFFF);
765 a = ((unsigned short*)element)[3] * (1.0f / 0xFFFF);
766 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400767 case FORMAT_A16B16G16R16UI:
768 {
769 unsigned short* abgr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400770
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400771 r = abgr[0];
772 g = abgr[1];
773 b = abgr[2];
774 a = abgr[3];
775 }
776 break;
777 case FORMAT_X16B16G16R16I:
778 {
779 short* bgr = (short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400780
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400781 r = bgr[0];
782 g = bgr[1];
783 b = bgr[2];
784 }
785 break;
786 case FORMAT_X16B16G16R16UI:
787 {
788 unsigned short* bgr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400789
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400790 r = bgr[0];
791 g = bgr[1];
792 b = bgr[2];
793 }
794 break;
795 case FORMAT_A32B32G32R32I:
796 {
797 int* abgr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400798
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400799 r = static_cast<float>(abgr[0]);
800 g = static_cast<float>(abgr[1]);
801 b = static_cast<float>(abgr[2]);
802 a = static_cast<float>(abgr[3]);
803 }
804 break;
805 case FORMAT_A32B32G32R32UI:
806 {
807 unsigned int* abgr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400808
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400809 r = static_cast<float>(abgr[0]);
810 g = static_cast<float>(abgr[1]);
811 b = static_cast<float>(abgr[2]);
812 a = static_cast<float>(abgr[3]);
813 }
814 break;
815 case FORMAT_X32B32G32R32I:
816 {
817 int* bgr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400818
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400819 r = static_cast<float>(bgr[0]);
820 g = static_cast<float>(bgr[1]);
821 b = static_cast<float>(bgr[2]);
822 }
823 break;
824 case FORMAT_X32B32G32R32UI:
825 {
826 unsigned int* bgr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400827
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400828 r = static_cast<float>(bgr[0]);
829 g = static_cast<float>(bgr[1]);
830 b = static_cast<float>(bgr[2]);
831 }
832 break;
833 case FORMAT_G32R32I:
834 {
835 int* gr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400836
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400837 r = static_cast<float>(gr[0]);
838 g = static_cast<float>(gr[1]);
839 }
840 break;
841 case FORMAT_G32R32UI:
842 {
843 unsigned int* gr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400844
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400845 r = static_cast<float>(gr[0]);
846 g = static_cast<float>(gr[1]);
847 }
848 break;
849 case FORMAT_R32I:
850 r = static_cast<float>(*((int*)element));
851 break;
852 case FORMAT_R32UI:
853 r = static_cast<float>(*((unsigned int*)element));
854 break;
John Bauman89401822014-05-06 15:04:28 -0400855 case FORMAT_V8U8:
856 {
857 unsigned short vu = *(unsigned short*)element;
858
859 r = ((int)(vu & 0x00FF) << 24) * (1.0f / 0x7F000000);
860 g = ((int)(vu & 0xFF00) << 16) * (1.0f / 0x7F000000);
861 }
862 break;
863 case FORMAT_L6V5U5:
864 {
865 unsigned short lvu = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400866
John Bauman89401822014-05-06 15:04:28 -0400867 r = ((int)(lvu & 0x001F) << 27) * (1.0f / 0x78000000);
868 g = ((int)(lvu & 0x03E0) << 22) * (1.0f / 0x78000000);
869 b = (lvu & 0xFC00) * (1.0f / 0xFC00);
870 }
871 break;
872 case FORMAT_Q8W8V8U8:
873 {
874 unsigned int qwvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400875
John Bauman89401822014-05-06 15:04:28 -0400876 r = ((int)(qwvu & 0x000000FF) << 24) * (1.0f / 0x7F000000);
877 g = ((int)(qwvu & 0x0000FF00) << 16) * (1.0f / 0x7F000000);
878 b = ((int)(qwvu & 0x00FF0000) << 8) * (1.0f / 0x7F000000);
879 a = ((int)(qwvu & 0xFF000000) << 0) * (1.0f / 0x7F000000);
880 }
881 break;
882 case FORMAT_X8L8V8U8:
883 {
884 unsigned int xlvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400885
John Bauman89401822014-05-06 15:04:28 -0400886 r = ((int)(xlvu & 0x000000FF) << 24) * (1.0f / 0x7F000000);
887 g = ((int)(xlvu & 0x0000FF00) << 16) * (1.0f / 0x7F000000);
888 b = (xlvu & 0x00FF0000) * (1.0f / 0x00FF0000);
889 }
890 break;
891 case FORMAT_R8G8B8:
892 r = ((unsigned char*)element)[2] * (1.0f / 0xFF);
893 g = ((unsigned char*)element)[1] * (1.0f / 0xFF);
894 b = ((unsigned char*)element)[0] * (1.0f / 0xFF);
895 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400896 case FORMAT_B8G8R8:
897 r = ((unsigned char*)element)[0] * (1.0f / 0xFF);
898 g = ((unsigned char*)element)[1] * (1.0f / 0xFF);
899 b = ((unsigned char*)element)[2] * (1.0f / 0xFF);
900 break;
John Bauman89401822014-05-06 15:04:28 -0400901 case FORMAT_V16U16:
902 {
903 unsigned int vu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400904
John Bauman89401822014-05-06 15:04:28 -0400905 r = ((int)(vu & 0x0000FFFF) << 16) * (1.0f / 0x7FFF0000);
906 g = ((int)(vu & 0xFFFF0000) << 0) * (1.0f / 0x7FFF0000);
907 }
908 break;
909 case FORMAT_A2W10V10U10:
910 {
911 unsigned int awvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400912
John Bauman89401822014-05-06 15:04:28 -0400913 r = ((int)(awvu & 0x000003FF) << 22) * (1.0f / 0x7FC00000);
914 g = ((int)(awvu & 0x000FFC00) << 12) * (1.0f / 0x7FC00000);
915 b = ((int)(awvu & 0x3FF00000) << 2) * (1.0f / 0x7FC00000);
916 a = (awvu & 0xC0000000) * (1.0f / 0xC0000000);
917 }
918 break;
919 case FORMAT_A16W16V16U16:
920 r = ((signed short*)element)[0] * (1.0f / 0x7FFF);
921 g = ((signed short*)element)[1] * (1.0f / 0x7FFF);
922 b = ((signed short*)element)[2] * (1.0f / 0x7FFF);
923 a = ((unsigned short*)element)[3] * (1.0f / 0xFFFF);
924 break;
925 case FORMAT_Q16W16V16U16:
926 r = ((signed short*)element)[0] * (1.0f / 0x7FFF);
927 g = ((signed short*)element)[1] * (1.0f / 0x7FFF);
928 b = ((signed short*)element)[2] * (1.0f / 0x7FFF);
929 a = ((signed short*)element)[3] * (1.0f / 0x7FFF);
930 break;
931 case FORMAT_L8:
932 r =
933 g =
934 b = *(unsigned char*)element * (1.0f / 0xFF);
935 break;
936 case FORMAT_A4L4:
937 {
938 unsigned char al = *(unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400939
John Bauman89401822014-05-06 15:04:28 -0400940 r =
941 g =
942 b = (al & 0x0F) * (1.0f / 0x0F);
943 a = (al & 0xF0) * (1.0f / 0xF0);
944 }
945 break;
946 case FORMAT_L16:
947 r =
948 g =
949 b = *(unsigned short*)element * (1.0f / 0xFFFF);
950 break;
951 case FORMAT_A8L8:
952 r =
953 g =
954 b = ((unsigned char*)element)[0] * (1.0f / 0xFF);
955 a = ((unsigned char*)element)[1] * (1.0f / 0xFF);
956 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400957 case FORMAT_L16F:
958 r =
959 g =
960 b = *(half*)element;
961 break;
962 case FORMAT_A16L16F:
963 r =
964 g =
965 b = ((half*)element)[0];
966 a = ((half*)element)[1];
967 break;
968 case FORMAT_L32F:
969 r =
970 g =
971 b = *(float*)element;
972 break;
973 case FORMAT_A32L32F:
974 r =
975 g =
976 b = ((float*)element)[0];
977 a = ((float*)element)[1];
978 break;
979 case FORMAT_A16F:
980 a = *(half*)element;
981 break;
John Bauman89401822014-05-06 15:04:28 -0400982 case FORMAT_R16F:
983 r = *(half*)element;
984 break;
985 case FORMAT_G16R16F:
986 r = ((half*)element)[0];
987 g = ((half*)element)[1];
988 break;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -0500989 case FORMAT_X16B16G16R16F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500990 case FORMAT_X16B16G16R16F_UNSIGNED:
Nicolas Capens80594422015-06-09 16:42:56 -0400991 case FORMAT_B16G16R16F:
992 r = ((half*)element)[0];
993 g = ((half*)element)[1];
994 b = ((half*)element)[2];
995 break;
John Bauman89401822014-05-06 15:04:28 -0400996 case FORMAT_A16B16G16R16F:
997 r = ((half*)element)[0];
998 g = ((half*)element)[1];
999 b = ((half*)element)[2];
1000 a = ((half*)element)[3];
1001 break;
Nicolas Capens80594422015-06-09 16:42:56 -04001002 case FORMAT_A32F:
1003 a = *(float*)element;
1004 break;
John Bauman89401822014-05-06 15:04:28 -04001005 case FORMAT_R32F:
1006 r = *(float*)element;
1007 break;
1008 case FORMAT_G32R32F:
1009 r = ((float*)element)[0];
1010 g = ((float*)element)[1];
1011 break;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04001012 case FORMAT_X32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05001013 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capens80594422015-06-09 16:42:56 -04001014 case FORMAT_B32G32R32F:
1015 r = ((float*)element)[0];
1016 g = ((float*)element)[1];
1017 b = ((float*)element)[2];
1018 break;
John Bauman89401822014-05-06 15:04:28 -04001019 case FORMAT_A32B32G32R32F:
1020 r = ((float*)element)[0];
1021 g = ((float*)element)[1];
1022 b = ((float*)element)[2];
1023 a = ((float*)element)[3];
1024 break;
1025 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001026 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04001027 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04001028 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001029 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04001030 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04001031 r = *(float*)element;
1032 g = r;
1033 b = r;
1034 a = r;
1035 break;
1036 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001037 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman66b8ab22014-05-06 15:57:45 -04001038 r = 1.0f - *(float*)element;
John Bauman89401822014-05-06 15:04:28 -04001039 g = r;
1040 b = r;
1041 a = r;
1042 break;
1043 case FORMAT_S8:
1044 r = *(unsigned char*)element * (1.0f / 0xFF);
1045 break;
1046 default:
1047 ASSERT(false);
1048 }
1049
Nicolas Capens1efac522017-12-01 16:59:38 -05001050 if(isSRGBformat(format))
1051 {
1052 r = sRGBtoLinear(r);
1053 g = sRGBtoLinear(g);
1054 b = sRGBtoLinear(b);
1055 }
John Bauman89401822014-05-06 15:04:28 -04001056
1057 return Color<float>(r, g, b, a);
1058 }
1059
1060 Color<float> Surface::Buffer::sample(float x, float y, float z) const
1061 {
1062 x -= 0.5f;
1063 y -= 0.5f;
1064 z -= 0.5f;
1065
1066 int x0 = clamp((int)x, 0, width - 1);
1067 int x1 = (x0 + 1 >= width) ? x0 : x0 + 1;
1068
1069 int y0 = clamp((int)y, 0, height - 1);
1070 int y1 = (y0 + 1 >= height) ? y0 : y0 + 1;
1071
1072 int z0 = clamp((int)z, 0, depth - 1);
1073 int z1 = (z0 + 1 >= depth) ? z0 : z0 + 1;
1074
1075 Color<float> c000 = read(x0, y0, z0);
1076 Color<float> c100 = read(x1, y0, z0);
1077 Color<float> c010 = read(x0, y1, z0);
1078 Color<float> c110 = read(x1, y1, z0);
1079 Color<float> c001 = read(x0, y0, z1);
1080 Color<float> c101 = read(x1, y0, z1);
1081 Color<float> c011 = read(x0, y1, z1);
1082 Color<float> c111 = read(x1, y1, z1);
1083
1084 float fx = x - x0;
1085 float fy = y - y0;
1086 float fz = z - z0;
1087
1088 c000 *= (1 - fx) * (1 - fy) * (1 - fz);
1089 c100 *= fx * (1 - fy) * (1 - fz);
1090 c010 *= (1 - fx) * fy * (1 - fz);
1091 c110 *= fx * fy * (1 - fz);
1092 c001 *= (1 - fx) * (1 - fy) * fz;
1093 c101 *= fx * (1 - fy) * fz;
1094 c011 *= (1 - fx) * fy * fz;
1095 c111 *= fx * fy * fz;
1096
1097 return c000 + c100 + c010 + c110 + c001 + c101 + c011 + c111;
1098 }
1099
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001100 Color<float> Surface::Buffer::sample(float x, float y, int layer) const
John Bauman89401822014-05-06 15:04:28 -04001101 {
1102 x -= 0.5f;
1103 y -= 0.5f;
1104
1105 int x0 = clamp((int)x, 0, width - 1);
1106 int x1 = (x0 + 1 >= width) ? x0 : x0 + 1;
1107
1108 int y0 = clamp((int)y, 0, height - 1);
1109 int y1 = (y0 + 1 >= height) ? y0 : y0 + 1;
1110
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001111 Color<float> c00 = read(x0, y0, layer);
1112 Color<float> c10 = read(x1, y0, layer);
1113 Color<float> c01 = read(x0, y1, layer);
1114 Color<float> c11 = read(x1, y1, layer);
John Bauman89401822014-05-06 15:04:28 -04001115
1116 float fx = x - x0;
1117 float fy = y - y0;
1118
1119 c00 *= (1 - fx) * (1 - fy);
1120 c10 *= fx * (1 - fy);
1121 c01 *= (1 - fx) * fy;
1122 c11 *= fx * fy;
1123
1124 return c00 + c10 + c01 + c11;
1125 }
1126
John Bauman19bac1e2014-05-06 15:23:49 -04001127 void *Surface::Buffer::lockRect(int x, int y, int z, Lock lock)
John Bauman89401822014-05-06 15:04:28 -04001128 {
1129 this->lock = lock;
1130
1131 switch(lock)
1132 {
1133 case LOCK_UNLOCKED:
1134 case LOCK_READONLY:
Nicolas Capensae7756e2018-02-22 16:13:01 -05001135 case LOCK_UPDATE:
John Bauman89401822014-05-06 15:04:28 -04001136 break;
1137 case LOCK_WRITEONLY:
1138 case LOCK_READWRITE:
1139 case LOCK_DISCARD:
1140 dirty = true;
1141 break;
1142 default:
1143 ASSERT(false);
1144 }
1145
John Baumand4ae8632014-05-06 16:18:33 -04001146 if(buffer)
John Bauman89401822014-05-06 15:04:28 -04001147 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001148 x += border;
1149 y += border;
1150
John Baumand4ae8632014-05-06 16:18:33 -04001151 switch(format)
1152 {
John Baumand4ae8632014-05-06 16:18:33 -04001153 case FORMAT_DXT1:
John Baumand4ae8632014-05-06 16:18:33 -04001154 case FORMAT_ATI1:
Nicolas Capens22658242014-11-29 00:31:41 -05001155 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001156 case FORMAT_R11_EAC:
1157 case FORMAT_SIGNED_R11_EAC:
1158 case FORMAT_RGB8_ETC2:
1159 case FORMAT_SRGB8_ETC2:
1160 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1161 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Baumand4ae8632014-05-06 16:18:33 -04001162 return (unsigned char*)buffer + 8 * (x / 4) + (y / 4) * pitchB + z * sliceB;
Alexis Hetu460e41f2015-09-01 10:58:37 -04001163 case FORMAT_RG11_EAC:
1164 case FORMAT_SIGNED_RG11_EAC:
1165 case FORMAT_RGBA8_ETC2_EAC:
1166 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1167 case FORMAT_RGBA_ASTC_4x4_KHR:
1168 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1169 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1170 case FORMAT_RGBA_ASTC_5x4_KHR:
1171 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1172 return (unsigned char*)buffer + 16 * (x / 5) + (y / 4) * pitchB + z * sliceB;
1173 case FORMAT_RGBA_ASTC_5x5_KHR:
1174 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1175 return (unsigned char*)buffer + 16 * (x / 5) + (y / 5) * pitchB + z * sliceB;
1176 case FORMAT_RGBA_ASTC_6x5_KHR:
1177 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1178 return (unsigned char*)buffer + 16 * (x / 6) + (y / 5) * pitchB + z * sliceB;
1179 case FORMAT_RGBA_ASTC_6x6_KHR:
1180 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1181 return (unsigned char*)buffer + 16 * (x / 6) + (y / 6) * pitchB + z * sliceB;
1182 case FORMAT_RGBA_ASTC_8x5_KHR:
1183 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1184 return (unsigned char*)buffer + 16 * (x / 8) + (y / 5) * pitchB + z * sliceB;
1185 case FORMAT_RGBA_ASTC_8x6_KHR:
1186 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1187 return (unsigned char*)buffer + 16 * (x / 8) + (y / 6) * pitchB + z * sliceB;
1188 case FORMAT_RGBA_ASTC_8x8_KHR:
1189 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1190 return (unsigned char*)buffer + 16 * (x / 8) + (y / 8) * pitchB + z * sliceB;
1191 case FORMAT_RGBA_ASTC_10x5_KHR:
1192 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1193 return (unsigned char*)buffer + 16 * (x / 10) + (y / 5) * pitchB + z * sliceB;
1194 case FORMAT_RGBA_ASTC_10x6_KHR:
1195 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1196 return (unsigned char*)buffer + 16 * (x / 10) + (y / 6) * pitchB + z * sliceB;
1197 case FORMAT_RGBA_ASTC_10x8_KHR:
1198 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1199 return (unsigned char*)buffer + 16 * (x / 10) + (y / 8) * pitchB + z * sliceB;
1200 case FORMAT_RGBA_ASTC_10x10_KHR:
1201 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1202 return (unsigned char*)buffer + 16 * (x / 10) + (y / 10) * pitchB + z * sliceB;
1203 case FORMAT_RGBA_ASTC_12x10_KHR:
1204 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1205 return (unsigned char*)buffer + 16 * (x / 12) + (y / 10) * pitchB + z * sliceB;
1206 case FORMAT_RGBA_ASTC_12x12_KHR:
1207 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1208 return (unsigned char*)buffer + 16 * (x / 12) + (y / 12) * pitchB + z * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001209 case FORMAT_DXT3:
1210 case FORMAT_DXT5:
John Baumand4ae8632014-05-06 16:18:33 -04001211 case FORMAT_ATI2:
1212 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1213 default:
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001214 return (unsigned char*)buffer + x * bytes + y * pitchB + z * samples * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001215 }
John Bauman89401822014-05-06 15:04:28 -04001216 }
1217
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001218 return nullptr;
John Bauman89401822014-05-06 15:04:28 -04001219 }
1220
1221 void Surface::Buffer::unlockRect()
1222 {
1223 lock = LOCK_UNLOCKED;
1224 }
1225
Nicolas Capensf41f0332017-05-30 15:25:50 -04001226 class SurfaceImplementation : public Surface
1227 {
1228 public:
1229 SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1230 : Surface(width, height, depth, format, pixels, pitch, slice) {}
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001231 SurfaceImplementation(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0)
1232 : Surface(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchP) {}
Nicolas Capensf41f0332017-05-30 15:25:50 -04001233 ~SurfaceImplementation() override {};
1234
1235 void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override
1236 {
1237 return Surface::lockInternal(x, y, z, lock, client);
1238 }
1239
1240 void unlockInternal() override
1241 {
1242 Surface::unlockInternal();
1243 }
1244 };
1245
1246 Surface *Surface::create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1247 {
1248 return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice);
1249 }
1250
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001251 Surface *Surface::create(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchPprovided)
Nicolas Capensf41f0332017-05-30 15:25:50 -04001252 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001253 return new SurfaceImplementation(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchPprovided);
Nicolas Capensf41f0332017-05-30 15:25:50 -04001254 }
1255
Nicolas Capens477314b2015-06-09 16:47:29 -04001256 Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
1257 {
1258 resource = new Resource(0);
1259 hasParent = false;
1260 ownExternal = false;
1261 depth = max(1, depth);
1262
1263 external.buffer = pixels;
1264 external.width = width;
1265 external.height = height;
1266 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001267 external.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001268 external.format = format;
1269 external.bytes = bytes(external.format);
1270 external.pitchB = pitch;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001271 external.pitchP = external.bytes ? pitch / external.bytes : 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001272 external.sliceB = slice;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001273 external.sliceP = external.bytes ? slice / external.bytes : 0;
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001274 external.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001275 external.lock = LOCK_UNLOCKED;
1276 external.dirty = true;
1277
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001278 internal.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001279 internal.width = width;
1280 internal.height = height;
1281 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001282 internal.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001283 internal.format = selectInternalFormat(format);
1284 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001285 internal.pitchB = pitchB(internal.width, 0, internal.format, false);
1286 internal.pitchP = pitchP(internal.width, 0, internal.format, false);
1287 internal.sliceB = sliceB(internal.width, internal.height, 0, internal.format, false);
1288 internal.sliceP = sliceP(internal.width, internal.height, 0, internal.format, false);
1289 internal.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001290 internal.lock = LOCK_UNLOCKED;
1291 internal.dirty = false;
1292
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001293 stencil.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001294 stencil.width = width;
1295 stencil.height = height;
1296 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001297 stencil.samples = 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001298 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
Nicolas Capens477314b2015-06-09 16:47:29 -04001299 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001300 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, false);
1301 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, false);
1302 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, false);
1303 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, false);
1304 stencil.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001305 stencil.lock = LOCK_UNLOCKED;
1306 stencil.dirty = false;
1307
Nicolas Capens73e18c12017-11-28 13:31:35 -05001308 dirtyContents = true;
Nicolas Capens477314b2015-06-09 16:47:29 -04001309 paletteUsed = 0;
1310 }
1311
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001312 Surface::Surface(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchPprovided) : lockable(lockable), renderTarget(renderTarget)
John Bauman89401822014-05-06 15:04:28 -04001313 {
1314 resource = texture ? texture : new Resource(0);
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001315 hasParent = texture != nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001316 ownExternal = true;
John Bauman89401822014-05-06 15:04:28 -04001317 depth = max(1, depth);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001318 samples = max(1, samples);
John Bauman89401822014-05-06 15:04:28 -04001319
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001320 external.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001321 external.width = width;
1322 external.height = height;
1323 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001324 external.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001325 external.format = format;
1326 external.bytes = bytes(external.format);
Alexis Hetu5fd1cfa2018-05-11 15:31:12 -04001327 external.pitchB = !pitchPprovided ? pitchB(external.width, 0, external.format, renderTarget && !texture) : pitchPprovided * external.bytes;
1328 external.pitchP = !pitchPprovided ? pitchP(external.width, 0, external.format, renderTarget && !texture) : pitchPprovided;
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001329 external.sliceB = sliceB(external.width, external.height, 0, external.format, renderTarget && !texture);
1330 external.sliceP = sliceP(external.width, external.height, 0, external.format, renderTarget && !texture);
1331 external.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001332 external.lock = LOCK_UNLOCKED;
1333 external.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001334
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001335 internal.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001336 internal.width = width;
1337 internal.height = height;
1338 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001339 internal.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001340 internal.format = selectInternalFormat(format);
1341 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001342 internal.pitchB = !pitchPprovided ? pitchB(internal.width, border, internal.format, renderTarget) : pitchPprovided * internal.bytes;
1343 internal.pitchP = !pitchPprovided ? pitchP(internal.width, border, internal.format, renderTarget) : pitchPprovided;
1344 internal.sliceB = sliceB(internal.width, internal.height, border, internal.format, renderTarget);
1345 internal.sliceP = sliceP(internal.width, internal.height, border, internal.format, renderTarget);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001346 internal.border = (short)border;
John Bauman89401822014-05-06 15:04:28 -04001347 internal.lock = LOCK_UNLOCKED;
1348 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001349
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001350 stencil.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001351 stencil.width = width;
1352 stencil.height = height;
1353 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001354 stencil.samples = (short)samples;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001355 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
John Bauman89401822014-05-06 15:04:28 -04001356 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001357 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, renderTarget);
1358 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, renderTarget);
1359 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1360 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1361 stencil.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001362 stencil.lock = LOCK_UNLOCKED;
1363 stencil.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001364
Nicolas Capens73e18c12017-11-28 13:31:35 -05001365 dirtyContents = true;
John Bauman66b8ab22014-05-06 15:57:45 -04001366 paletteUsed = 0;
John Bauman89401822014-05-06 15:04:28 -04001367 }
1368
1369 Surface::~Surface()
1370 {
Nicolas Capensbf7a8142017-05-19 10:57:28 -04001371 // sync() must be called before this destructor to ensure all locks have been released.
1372 // We can't call it here because the parent resource may already have been destroyed.
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001373 ASSERT(isUnlocked());
John Bauman8a4f6fc2014-05-06 15:26:18 -04001374
John Bauman89401822014-05-06 15:04:28 -04001375 if(!hasParent)
1376 {
1377 resource->destruct();
1378 }
1379
Nicolas Capens477314b2015-06-09 16:47:29 -04001380 if(ownExternal)
1381 {
1382 deallocate(external.buffer);
1383 }
John Bauman89401822014-05-06 15:04:28 -04001384
1385 if(internal.buffer != external.buffer)
1386 {
1387 deallocate(internal.buffer);
1388 }
1389
1390 deallocate(stencil.buffer);
1391
Nicolas Capens810f3db2018-09-29 11:58:42 -04001392 external.buffer = nullptr;
1393 internal.buffer = nullptr;
1394 stencil.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001395 }
1396
John Bauman19bac1e2014-05-06 15:23:49 -04001397 void *Surface::lockExternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001398 {
1399 resource->lock(client);
1400
1401 if(!external.buffer)
1402 {
Nicolas Capens539468c2018-06-28 11:28:40 -04001403 if(internal.buffer && identicalBuffers())
John Bauman89401822014-05-06 15:04:28 -04001404 {
1405 external.buffer = internal.buffer;
1406 }
1407 else
1408 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001409 external.buffer = allocateBuffer(external.width, external.height, external.depth, external.border, external.samples, external.format);
John Bauman89401822014-05-06 15:04:28 -04001410 }
1411 }
1412
1413 if(internal.dirty)
1414 {
1415 if(lock != LOCK_DISCARD)
1416 {
1417 update(external, internal);
1418 }
John Bauman66b8ab22014-05-06 15:57:45 -04001419
1420 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001421 }
1422
1423 switch(lock)
1424 {
1425 case LOCK_READONLY:
1426 break;
1427 case LOCK_WRITEONLY:
1428 case LOCK_READWRITE:
1429 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001430 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001431 break;
1432 default:
1433 ASSERT(false);
1434 }
1435
John Bauman19bac1e2014-05-06 15:23:49 -04001436 return external.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001437 }
1438
1439 void Surface::unlockExternal()
1440 {
John Bauman89401822014-05-06 15:04:28 -04001441 external.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001442
1443 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001444 }
1445
John Bauman19bac1e2014-05-06 15:23:49 -04001446 void *Surface::lockInternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001447 {
1448 if(lock != LOCK_UNLOCKED)
1449 {
1450 resource->lock(client);
1451 }
1452
1453 if(!internal.buffer)
1454 {
Nicolas Capens539468c2018-06-28 11:28:40 -04001455 if(external.buffer && identicalBuffers())
John Bauman89401822014-05-06 15:04:28 -04001456 {
1457 internal.buffer = external.buffer;
1458 }
1459 else
1460 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001461 internal.buffer = allocateBuffer(internal.width, internal.height, internal.depth, internal.border, internal.samples, internal.format);
John Bauman89401822014-05-06 15:04:28 -04001462 }
1463 }
1464
1465 // FIXME: WHQL requires conversion to lower external precision and back
1466 if(logPrecision >= WHQL)
1467 {
1468 if(internal.dirty && renderTarget && internal.format != external.format)
1469 {
1470 if(lock != LOCK_DISCARD)
1471 {
1472 switch(external.format)
1473 {
1474 case FORMAT_R3G3B2:
1475 case FORMAT_A8R3G3B2:
1476 case FORMAT_A1R5G5B5:
1477 case FORMAT_A2R10G10B10:
1478 case FORMAT_A2B10G10R10:
1479 lockExternal(0, 0, 0, LOCK_READWRITE, client);
1480 unlockExternal();
1481 break;
1482 default:
1483 // Difference passes WHQL
1484 break;
1485 }
1486 }
1487 }
1488 }
1489
John Bauman66b8ab22014-05-06 15:57:45 -04001490 if(external.dirty || (isPalette(external.format) && paletteUsed != Surface::paletteID))
John Bauman89401822014-05-06 15:04:28 -04001491 {
1492 if(lock != LOCK_DISCARD)
1493 {
1494 update(internal, external);
1495 }
John Bauman89401822014-05-06 15:04:28 -04001496
John Bauman66b8ab22014-05-06 15:57:45 -04001497 external.dirty = false;
1498 paletteUsed = Surface::paletteID;
John Bauman89401822014-05-06 15:04:28 -04001499 }
1500
1501 switch(lock)
1502 {
1503 case LOCK_UNLOCKED:
1504 case LOCK_READONLY:
1505 break;
1506 case LOCK_WRITEONLY:
1507 case LOCK_READWRITE:
1508 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001509 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001510 break;
1511 default:
1512 ASSERT(false);
1513 }
1514
1515 if(lock == LOCK_READONLY && client == PUBLIC)
1516 {
1517 resolve();
1518 }
1519
John Bauman19bac1e2014-05-06 15:23:49 -04001520 return internal.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001521 }
1522
1523 void Surface::unlockInternal()
1524 {
John Bauman89401822014-05-06 15:04:28 -04001525 internal.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001526
1527 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001528 }
1529
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001530 void *Surface::lockStencil(int x, int y, int front, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001531 {
Nicolas Capens810f3db2018-09-29 11:58:42 -04001532 resource->lock(client);
1533
Nicolas Capensae7756e2018-02-22 16:13:01 -05001534 if(stencil.format == FORMAT_NULL)
1535 {
1536 return nullptr;
1537 }
1538
John Bauman89401822014-05-06 15:04:28 -04001539 if(!stencil.buffer)
1540 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001541 stencil.buffer = allocateBuffer(stencil.width, stencil.height, stencil.depth, stencil.border, stencil.samples, stencil.format);
John Bauman89401822014-05-06 15:04:28 -04001542 }
1543
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001544 return stencil.lockRect(x, y, front, LOCK_READWRITE); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001545 }
1546
1547 void Surface::unlockStencil()
1548 {
John Bauman89401822014-05-06 15:04:28 -04001549 stencil.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001550
1551 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001552 }
1553
1554 int Surface::bytes(Format format)
1555 {
1556 switch(format)
1557 {
1558 case FORMAT_NULL: return 0;
1559 case FORMAT_P8: return 1;
1560 case FORMAT_A8P8: return 2;
1561 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001562 case FORMAT_R8I: return 1;
John Bauman89401822014-05-06 15:04:28 -04001563 case FORMAT_R8: return 1;
1564 case FORMAT_R3G3B2: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001565 case FORMAT_R16I: return 2;
1566 case FORMAT_R16UI: return 2;
John Bauman89401822014-05-06 15:04:28 -04001567 case FORMAT_A8R3G3B2: return 2;
1568 case FORMAT_R5G6B5: return 2;
1569 case FORMAT_A1R5G5B5: return 2;
1570 case FORMAT_X1R5G5B5: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001571 case FORMAT_R5G5B5A1: return 2;
John Bauman89401822014-05-06 15:04:28 -04001572 case FORMAT_X4R4G4B4: return 2;
1573 case FORMAT_A4R4G4B4: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001574 case FORMAT_R4G4B4A4: return 2;
John Bauman89401822014-05-06 15:04:28 -04001575 case FORMAT_R8G8B8: return 3;
Nicolas Capens80594422015-06-09 16:42:56 -04001576 case FORMAT_B8G8R8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001577 case FORMAT_R32I: return 4;
1578 case FORMAT_R32UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001579 case FORMAT_X8R8G8B8: return 4;
1580 // case FORMAT_X8G8R8B8Q: return 4;
1581 case FORMAT_A8R8G8B8: return 4;
1582 // case FORMAT_A8G8R8B8Q: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001583 case FORMAT_X8B8G8R8I: return 4;
John Bauman89401822014-05-06 15:04:28 -04001584 case FORMAT_X8B8G8R8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04001585 case FORMAT_SRGB8_X8: return 4;
1586 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001587 case FORMAT_A8B8G8R8I: return 4;
1588 case FORMAT_R8UI: return 1;
1589 case FORMAT_G8R8UI: return 2;
1590 case FORMAT_X8B8G8R8UI: return 4;
1591 case FORMAT_A8B8G8R8UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001592 case FORMAT_A8B8G8R8: return 4;
Nicolas Capens975adb72017-12-19 15:34:20 -05001593 case FORMAT_R8_SNORM: return 1;
1594 case FORMAT_G8R8_SNORM: return 2;
1595 case FORMAT_X8B8G8R8_SNORM: return 4;
1596 case FORMAT_A8B8G8R8_SNORM: return 4;
John Bauman89401822014-05-06 15:04:28 -04001597 case FORMAT_A2R10G10B10: return 4;
1598 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05001599 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001600 case FORMAT_G8R8I: return 2;
John Bauman89401822014-05-06 15:04:28 -04001601 case FORMAT_G8R8: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001602 case FORMAT_G16R16I: return 4;
1603 case FORMAT_G16R16UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001604 case FORMAT_G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001605 case FORMAT_G32R32I: return 8;
1606 case FORMAT_G32R32UI: return 8;
1607 case FORMAT_X16B16G16R16I: return 8;
1608 case FORMAT_X16B16G16R16UI: return 8;
1609 case FORMAT_A16B16G16R16I: return 8;
1610 case FORMAT_A16B16G16R16UI: return 8;
John Bauman89401822014-05-06 15:04:28 -04001611 case FORMAT_A16B16G16R16: return 8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001612 case FORMAT_X32B32G32R32I: return 16;
1613 case FORMAT_X32B32G32R32UI: return 16;
1614 case FORMAT_A32B32G32R32I: return 16;
1615 case FORMAT_A32B32G32R32UI: return 16;
John Bauman89401822014-05-06 15:04:28 -04001616 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04001617 case FORMAT_DXT1: return 2; // Column of four pixels
1618 case FORMAT_DXT3: return 4; // Column of four pixels
1619 case FORMAT_DXT5: return 4; // Column of four pixels
1620 case FORMAT_ATI1: return 2; // Column of four pixels
1621 case FORMAT_ATI2: return 4; // Column of four pixels
Nicolas Capens22658242014-11-29 00:31:41 -05001622 case FORMAT_ETC1: return 2; // Column of four pixels
Alexis Hetu460e41f2015-09-01 10:58:37 -04001623 case FORMAT_R11_EAC: return 2;
1624 case FORMAT_SIGNED_R11_EAC: return 2;
1625 case FORMAT_RG11_EAC: return 4;
1626 case FORMAT_SIGNED_RG11_EAC: return 4;
1627 case FORMAT_RGB8_ETC2: return 2;
1628 case FORMAT_SRGB8_ETC2: return 2;
1629 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1630 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1631 case FORMAT_RGBA8_ETC2_EAC: return 4;
1632 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: return 4;
1633 case FORMAT_RGBA_ASTC_4x4_KHR:
1634 case FORMAT_RGBA_ASTC_5x4_KHR:
1635 case FORMAT_RGBA_ASTC_5x5_KHR:
1636 case FORMAT_RGBA_ASTC_6x5_KHR:
1637 case FORMAT_RGBA_ASTC_6x6_KHR:
1638 case FORMAT_RGBA_ASTC_8x5_KHR:
1639 case FORMAT_RGBA_ASTC_8x6_KHR:
1640 case FORMAT_RGBA_ASTC_8x8_KHR:
1641 case FORMAT_RGBA_ASTC_10x5_KHR:
1642 case FORMAT_RGBA_ASTC_10x6_KHR:
1643 case FORMAT_RGBA_ASTC_10x8_KHR:
1644 case FORMAT_RGBA_ASTC_10x10_KHR:
1645 case FORMAT_RGBA_ASTC_12x10_KHR:
1646 case FORMAT_RGBA_ASTC_12x12_KHR:
1647 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1648 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1649 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1650 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1651 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1652 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1653 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1654 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1655 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1656 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1657 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1658 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1659 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1660 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR: return 0; // FIXME
John Bauman89401822014-05-06 15:04:28 -04001661 // Bumpmap formats
1662 case FORMAT_V8U8: return 2;
1663 case FORMAT_L6V5U5: return 2;
1664 case FORMAT_Q8W8V8U8: return 4;
1665 case FORMAT_X8L8V8U8: return 4;
1666 case FORMAT_A2W10V10U10: return 4;
1667 case FORMAT_V16U16: return 4;
1668 case FORMAT_A16W16V16U16: return 8;
1669 case FORMAT_Q16W16V16U16: return 8;
1670 // Luminance formats
1671 case FORMAT_L8: return 1;
1672 case FORMAT_A4L4: return 1;
1673 case FORMAT_L16: return 2;
1674 case FORMAT_A8L8: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001675 case FORMAT_L16F: return 2;
1676 case FORMAT_A16L16F: return 4;
1677 case FORMAT_L32F: return 4;
1678 case FORMAT_A32L32F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001679 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04001680 case FORMAT_A16F: return 2;
John Bauman89401822014-05-06 15:04:28 -04001681 case FORMAT_R16F: return 2;
1682 case FORMAT_G16R16F: return 4;
Nicolas Capens80594422015-06-09 16:42:56 -04001683 case FORMAT_B16G16R16F: return 6;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05001684 case FORMAT_X16B16G16R16F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001685 case FORMAT_A16B16G16R16F: return 8;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001686 case FORMAT_X16B16G16R16F_UNSIGNED: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001687 case FORMAT_A32F: return 4;
John Bauman89401822014-05-06 15:04:28 -04001688 case FORMAT_R32F: return 4;
1689 case FORMAT_G32R32F: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001690 case FORMAT_B32G32R32F: return 12;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04001691 case FORMAT_X32B32G32R32F: return 16;
John Bauman89401822014-05-06 15:04:28 -04001692 case FORMAT_A32B32G32R32F: return 16;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001693 case FORMAT_X32B32G32R32F_UNSIGNED: return 16;
John Bauman89401822014-05-06 15:04:28 -04001694 // Depth/stencil formats
1695 case FORMAT_D16: return 2;
1696 case FORMAT_D32: return 4;
1697 case FORMAT_D24X8: return 4;
1698 case FORMAT_D24S8: return 4;
1699 case FORMAT_D24FS8: return 4;
1700 case FORMAT_D32F: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001701 case FORMAT_D32FS8: return 4;
John Bauman89401822014-05-06 15:04:28 -04001702 case FORMAT_D32F_COMPLEMENTARY: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001703 case FORMAT_D32FS8_COMPLEMENTARY: return 4;
John Bauman89401822014-05-06 15:04:28 -04001704 case FORMAT_D32F_LOCKABLE: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001705 case FORMAT_D32FS8_TEXTURE: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001706 case FORMAT_D32F_SHADOW: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001707 case FORMAT_D32FS8_SHADOW: return 4;
1708 case FORMAT_DF24S8: return 4;
1709 case FORMAT_DF16S8: return 2;
John Bauman89401822014-05-06 15:04:28 -04001710 case FORMAT_INTZ: return 4;
1711 case FORMAT_S8: return 1;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001712 case FORMAT_YV12_BT601: return 1; // Y plane only
1713 case FORMAT_YV12_BT709: return 1; // Y plane only
1714 case FORMAT_YV12_JFIF: return 1; // Y plane only
John Bauman89401822014-05-06 15:04:28 -04001715 default:
1716 ASSERT(false);
1717 }
1718
1719 return 0;
1720 }
1721
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001722 int Surface::pitchB(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001723 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001724 width += 2 * border;
1725
Nicolas Capens419a5802018-05-08 17:20:50 -04001726 // Render targets require 2x2 quads
John Bauman89401822014-05-06 15:04:28 -04001727 if(target || isDepth(format) || isStencil(format))
1728 {
Nicolas Capens419a5802018-05-08 17:20:50 -04001729 width = align<2>(width);
John Bauman89401822014-05-06 15:04:28 -04001730 }
1731
1732 switch(format)
1733 {
John Bauman89401822014-05-06 15:04:28 -04001734 case FORMAT_DXT1:
Nicolas Capens22658242014-11-29 00:31:41 -05001735 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001736 case FORMAT_R11_EAC:
1737 case FORMAT_SIGNED_R11_EAC:
1738 case FORMAT_RGB8_ETC2:
1739 case FORMAT_SRGB8_ETC2:
1740 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1741 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Bauman89401822014-05-06 15:04:28 -04001742 return 8 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001743 case FORMAT_RG11_EAC:
1744 case FORMAT_SIGNED_RG11_EAC:
1745 case FORMAT_RGBA8_ETC2_EAC:
1746 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1747 case FORMAT_RGBA_ASTC_4x4_KHR:
1748 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1749 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1750 case FORMAT_RGBA_ASTC_5x4_KHR:
1751 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1752 case FORMAT_RGBA_ASTC_5x5_KHR:
1753 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1754 return 16 * ((width + 4) / 5);
1755 case FORMAT_RGBA_ASTC_6x5_KHR:
1756 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1757 case FORMAT_RGBA_ASTC_6x6_KHR:
1758 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1759 return 16 * ((width + 5) / 6);
1760 case FORMAT_RGBA_ASTC_8x5_KHR:
1761 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1762 case FORMAT_RGBA_ASTC_8x6_KHR:
1763 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1764 case FORMAT_RGBA_ASTC_8x8_KHR:
1765 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1766 return 16 * ((width + 7) / 8);
1767 case FORMAT_RGBA_ASTC_10x5_KHR:
1768 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1769 case FORMAT_RGBA_ASTC_10x6_KHR:
1770 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1771 case FORMAT_RGBA_ASTC_10x8_KHR:
1772 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1773 case FORMAT_RGBA_ASTC_10x10_KHR:
1774 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1775 return 16 * ((width + 9) / 10);
1776 case FORMAT_RGBA_ASTC_12x10_KHR:
1777 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1778 case FORMAT_RGBA_ASTC_12x12_KHR:
1779 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1780 return 16 * ((width + 11) / 12);
John Bauman89401822014-05-06 15:04:28 -04001781 case FORMAT_DXT3:
1782 case FORMAT_DXT5:
1783 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1784 case FORMAT_ATI1:
1785 return 2 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per row
1786 case FORMAT_ATI2:
1787 return 4 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per row
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001788 case FORMAT_YV12_BT601:
1789 case FORMAT_YV12_BT709:
1790 case FORMAT_YV12_JFIF:
Nicolas Capens419a5802018-05-08 17:20:50 -04001791 return align<16>(width);
John Bauman89401822014-05-06 15:04:28 -04001792 default:
1793 return bytes(format) * width;
1794 }
1795 }
1796
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001797 int Surface::pitchP(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001798 {
1799 int B = bytes(format);
1800
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001801 return B > 0 ? pitchB(width, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001802 }
1803
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001804 int Surface::sliceB(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001805 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001806 height += 2 * border;
1807
Nicolas Capens419a5802018-05-08 17:20:50 -04001808 // Render targets require 2x2 quads
John Bauman89401822014-05-06 15:04:28 -04001809 if(target || isDepth(format) || isStencil(format))
1810 {
Nicolas Capens419a5802018-05-08 17:20:50 -04001811 height = align<2>(height);
John Bauman89401822014-05-06 15:04:28 -04001812 }
1813
1814 switch(format)
1815 {
John Bauman89401822014-05-06 15:04:28 -04001816 case FORMAT_DXT1:
1817 case FORMAT_DXT3:
1818 case FORMAT_DXT5:
Nicolas Capens22658242014-11-29 00:31:41 -05001819 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001820 case FORMAT_R11_EAC:
1821 case FORMAT_SIGNED_R11_EAC:
1822 case FORMAT_RG11_EAC:
1823 case FORMAT_SIGNED_RG11_EAC:
1824 case FORMAT_RGB8_ETC2:
1825 case FORMAT_SRGB8_ETC2:
1826 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1827 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1828 case FORMAT_RGBA8_ETC2_EAC:
1829 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1830 case FORMAT_RGBA_ASTC_4x4_KHR:
1831 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1832 case FORMAT_RGBA_ASTC_5x4_KHR:
1833 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001834 return pitchB(width, border, format, target) * ((height + 3) / 4); // Pitch computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001835 case FORMAT_RGBA_ASTC_5x5_KHR:
1836 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1837 case FORMAT_RGBA_ASTC_6x5_KHR:
1838 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1839 case FORMAT_RGBA_ASTC_8x5_KHR:
1840 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1841 case FORMAT_RGBA_ASTC_10x5_KHR:
1842 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001843 return pitchB(width, border, format, target) * ((height + 4) / 5); // Pitch computed per 5 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001844 case FORMAT_RGBA_ASTC_6x6_KHR:
1845 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1846 case FORMAT_RGBA_ASTC_8x6_KHR:
1847 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1848 case FORMAT_RGBA_ASTC_10x6_KHR:
1849 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001850 return pitchB(width, border, format, target) * ((height + 5) / 6); // Pitch computed per 6 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001851 case FORMAT_RGBA_ASTC_8x8_KHR:
1852 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1853 case FORMAT_RGBA_ASTC_10x8_KHR:
1854 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001855 return pitchB(width, border, format, target) * ((height + 7) / 8); // Pitch computed per 8 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001856 case FORMAT_RGBA_ASTC_10x10_KHR:
1857 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1858 case FORMAT_RGBA_ASTC_12x10_KHR:
1859 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001860 return pitchB(width, border, format, target) * ((height + 9) / 10); // Pitch computed per 10 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001861 case FORMAT_RGBA_ASTC_12x12_KHR:
1862 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001863 return pitchB(width, border, format, target) * ((height + 11) / 12); // Pitch computed per 12 rows
Nicolas Capens22658242014-11-29 00:31:41 -05001864 case FORMAT_ATI1:
1865 case FORMAT_ATI2:
Nicolas Capens419a5802018-05-08 17:20:50 -04001866 return pitchB(width, border, format, target) * align<4>(height); // Pitch computed per row
John Bauman89401822014-05-06 15:04:28 -04001867 default:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001868 return pitchB(width, border, format, target) * height; // Pitch computed per row
John Bauman89401822014-05-06 15:04:28 -04001869 }
1870 }
1871
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001872 int Surface::sliceP(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001873 {
1874 int B = bytes(format);
1875
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001876 return B > 0 ? sliceB(width, height, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001877 }
1878
1879 void Surface::update(Buffer &destination, Buffer &source)
1880 {
1881 // ASSERT(source.lock != LOCK_UNLOCKED);
1882 // ASSERT(destination.lock != LOCK_UNLOCKED);
Nicolas Capensc39901e2016-03-21 16:37:44 -04001883
John Bauman89401822014-05-06 15:04:28 -04001884 if(destination.buffer != source.buffer)
1885 {
1886 ASSERT(source.dirty && !destination.dirty);
1887
1888 switch(source.format)
1889 {
1890 case FORMAT_R8G8B8: decodeR8G8B8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001891 case FORMAT_X1R5G5B5: decodeX1R5G5B5(destination, source); break; // FIXME: Check destination format
1892 case FORMAT_A1R5G5B5: decodeA1R5G5B5(destination, source); break; // FIXME: Check destination format
1893 case FORMAT_X4R4G4B4: decodeX4R4G4B4(destination, source); break; // FIXME: Check destination format
1894 case FORMAT_A4R4G4B4: decodeA4R4G4B4(destination, source); break; // FIXME: Check destination format
1895 case FORMAT_P8: decodeP8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001896 case FORMAT_DXT1: decodeDXT1(destination, source); break; // FIXME: Check destination format
1897 case FORMAT_DXT3: decodeDXT3(destination, source); break; // FIXME: Check destination format
1898 case FORMAT_DXT5: decodeDXT5(destination, source); break; // FIXME: Check destination format
1899 case FORMAT_ATI1: decodeATI1(destination, source); break; // FIXME: Check destination format
1900 case FORMAT_ATI2: decodeATI2(destination, source); break; // FIXME: Check destination format
Alexis Hetu460e41f2015-09-01 10:58:37 -04001901 case FORMAT_R11_EAC: decodeEAC(destination, source, 1, false); break; // FIXME: Check destination format
1902 case FORMAT_SIGNED_R11_EAC: decodeEAC(destination, source, 1, true); break; // FIXME: Check destination format
1903 case FORMAT_RG11_EAC: decodeEAC(destination, source, 2, false); break; // FIXME: Check destination format
1904 case FORMAT_SIGNED_RG11_EAC: decodeEAC(destination, source, 2, true); break; // FIXME: Check destination format
Alexis Hetu0de50d42015-09-09 13:56:41 -04001905 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001906 case FORMAT_RGB8_ETC2: decodeETC2(destination, source, 0, false); break; // FIXME: Check destination format
1907 case FORMAT_SRGB8_ETC2: decodeETC2(destination, source, 0, true); break; // FIXME: Check destination format
1908 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, false); break; // FIXME: Check destination format
1909 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, true); break; // FIXME: Check destination format
1910 case FORMAT_RGBA8_ETC2_EAC: decodeETC2(destination, source, 8, false); break; // FIXME: Check destination format
1911 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: decodeETC2(destination, source, 8, true); break; // FIXME: Check destination format
1912 case FORMAT_RGBA_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, false); break; // FIXME: Check destination format
1913 case FORMAT_RGBA_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, false); break; // FIXME: Check destination format
1914 case FORMAT_RGBA_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, false); break; // FIXME: Check destination format
1915 case FORMAT_RGBA_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, false); break; // FIXME: Check destination format
1916 case FORMAT_RGBA_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, false); break; // FIXME: Check destination format
1917 case FORMAT_RGBA_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, false); break; // FIXME: Check destination format
1918 case FORMAT_RGBA_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, false); break; // FIXME: Check destination format
1919 case FORMAT_RGBA_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, false); break; // FIXME: Check destination format
1920 case FORMAT_RGBA_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, false); break; // FIXME: Check destination format
1921 case FORMAT_RGBA_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, false); break; // FIXME: Check destination format
1922 case FORMAT_RGBA_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, false); break; // FIXME: Check destination format
1923 case FORMAT_RGBA_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, false); break; // FIXME: Check destination format
1924 case FORMAT_RGBA_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, false); break; // FIXME: Check destination format
1925 case FORMAT_RGBA_ASTC_12x12_KHR: decodeASTC(destination, source, 12, 12, 1, false); break; // FIXME: Check destination format
1926 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, true); break; // FIXME: Check destination format
1927 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, true); break; // FIXME: Check destination format
1928 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, true); break; // FIXME: Check destination format
1929 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, true); break; // FIXME: Check destination format
1930 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, true); break; // FIXME: Check destination format
1931 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, true); break; // FIXME: Check destination format
1932 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, true); break; // FIXME: Check destination format
1933 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, true); break; // FIXME: Check destination format
1934 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, true); break; // FIXME: Check destination format
1935 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, true); break; // FIXME: Check destination format
1936 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, true); break; // FIXME: Check destination format
1937 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, true); break; // FIXME: Check destination format
1938 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, true); break; // FIXME: Check destination format
1939 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR: decodeASTC(destination, source, 12, 12, 1, true); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001940 default: genericUpdate(destination, source); break;
1941 }
1942 }
John Bauman89401822014-05-06 15:04:28 -04001943 }
1944
1945 void Surface::genericUpdate(Buffer &destination, Buffer &source)
1946 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001947 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05001948 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04001949
1950 int depth = min(destination.depth, source.depth);
1951 int height = min(destination.height, source.height);
1952 int width = min(destination.width, source.width);
1953 int rowBytes = width * source.bytes;
1954
1955 for(int z = 0; z < depth; z++)
1956 {
1957 unsigned char *sourceRow = sourceSlice;
1958 unsigned char *destinationRow = destinationSlice;
1959
1960 for(int y = 0; y < height; y++)
1961 {
1962 if(source.format == destination.format)
1963 {
1964 memcpy(destinationRow, sourceRow, rowBytes);
1965 }
1966 else
1967 {
1968 unsigned char *sourceElement = sourceRow;
1969 unsigned char *destinationElement = destinationRow;
1970
1971 for(int x = 0; x < width; x++)
1972 {
1973 Color<float> color = source.read(sourceElement);
1974 destination.write(destinationElement, color);
1975
1976 sourceElement += source.bytes;
1977 destinationElement += destination.bytes;
1978 }
1979 }
1980
1981 sourceRow += source.pitchB;
1982 destinationRow += destination.pitchB;
1983 }
1984
1985 sourceSlice += source.sliceB;
1986 destinationSlice += destination.sliceB;
1987 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001988
1989 source.unlockRect();
1990 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04001991 }
1992
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001993 void Surface::decodeR8G8B8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04001994 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001995 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05001996 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04001997
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001998 int depth = min(destination.depth, source.depth);
1999 int height = min(destination.height, source.height);
2000 int width = min(destination.width, source.width);
2001
2002 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002003 {
2004 unsigned char *sourceRow = sourceSlice;
2005 unsigned char *destinationRow = destinationSlice;
2006
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002007 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002008 {
2009 unsigned char *sourceElement = sourceRow;
2010 unsigned char *destinationElement = destinationRow;
2011
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002012 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002013 {
2014 unsigned int b = sourceElement[0];
2015 unsigned int g = sourceElement[1];
2016 unsigned int r = sourceElement[2];
2017
2018 *(unsigned int*)destinationElement = 0xFF000000 | (r << 16) | (g << 8) | (b << 0);
2019
2020 sourceElement += source.bytes;
2021 destinationElement += destination.bytes;
2022 }
2023
2024 sourceRow += source.pitchB;
2025 destinationRow += destination.pitchB;
2026 }
2027
2028 sourceSlice += source.sliceB;
2029 destinationSlice += destination.sliceB;
2030 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002031
2032 source.unlockRect();
2033 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002034 }
2035
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002036 void Surface::decodeX1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002037 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002038 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002039 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002040
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002041 int depth = min(destination.depth, source.depth);
2042 int height = min(destination.height, source.height);
2043 int width = min(destination.width, source.width);
2044
2045 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002046 {
2047 unsigned char *sourceRow = sourceSlice;
2048 unsigned char *destinationRow = destinationSlice;
2049
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002050 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002051 {
2052 unsigned char *sourceElement = sourceRow;
2053 unsigned char *destinationElement = destinationRow;
2054
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002055 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002056 {
2057 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002058
John Bauman89401822014-05-06 15:04:28 -04002059 unsigned int r = (((xrgb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2060 unsigned int g = (((xrgb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2061 unsigned int b = (((xrgb & 0x001F) * 2106 + 0x80) >> 8);
2062
2063 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2064
2065 sourceElement += source.bytes;
2066 destinationElement += destination.bytes;
2067 }
2068
2069 sourceRow += source.pitchB;
2070 destinationRow += destination.pitchB;
2071 }
2072
2073 sourceSlice += source.sliceB;
2074 destinationSlice += destination.sliceB;
2075 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002076
2077 source.unlockRect();
2078 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002079 }
2080
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002081 void Surface::decodeA1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002082 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002083 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002084 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002085
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002086 int depth = min(destination.depth, source.depth);
2087 int height = min(destination.height, source.height);
2088 int width = min(destination.width, source.width);
2089
2090 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002091 {
2092 unsigned char *sourceRow = sourceSlice;
2093 unsigned char *destinationRow = destinationSlice;
2094
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002095 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002096 {
2097 unsigned char *sourceElement = sourceRow;
2098 unsigned char *destinationElement = destinationRow;
2099
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002100 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002101 {
2102 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002103
John Bauman89401822014-05-06 15:04:28 -04002104 unsigned int a = (argb & 0x8000) * 130560;
2105 unsigned int r = (((argb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2106 unsigned int g = (((argb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2107 unsigned int b = (((argb & 0x001F) * 2106 + 0x80) >> 8);
2108
2109 *(unsigned int*)destinationElement = a | r | g | b;
2110
2111 sourceElement += source.bytes;
2112 destinationElement += destination.bytes;
2113 }
2114
2115 sourceRow += source.pitchB;
2116 destinationRow += destination.pitchB;
2117 }
2118
2119 sourceSlice += source.sliceB;
2120 destinationSlice += destination.sliceB;
2121 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002122
2123 source.unlockRect();
2124 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002125 }
2126
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002127 void Surface::decodeX4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002128 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002129 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002130 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002131
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002132 int depth = min(destination.depth, source.depth);
2133 int height = min(destination.height, source.height);
2134 int width = min(destination.width, source.width);
2135
2136 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002137 {
2138 unsigned char *sourceRow = sourceSlice;
2139 unsigned char *destinationRow = destinationSlice;
2140
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002141 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002142 {
2143 unsigned char *sourceElement = sourceRow;
2144 unsigned char *destinationElement = destinationRow;
2145
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002146 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002147 {
2148 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002149
John Bauman89401822014-05-06 15:04:28 -04002150 unsigned int r = ((xrgb & 0x0F00) * 0x00001100) & 0x00FF0000;
2151 unsigned int g = ((xrgb & 0x00F0) * 0x00000110) & 0x0000FF00;
2152 unsigned int b = (xrgb & 0x000F) * 0x00000011;
2153
2154 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2155
2156 sourceElement += source.bytes;
2157 destinationElement += destination.bytes;
2158 }
2159
2160 sourceRow += source.pitchB;
2161 destinationRow += destination.pitchB;
2162 }
2163
2164 sourceSlice += source.sliceB;
2165 destinationSlice += destination.sliceB;
2166 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002167
2168 source.unlockRect();
2169 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002170 }
2171
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002172 void Surface::decodeA4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002173 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002174 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002175 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002176
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002177 int depth = min(destination.depth, source.depth);
2178 int height = min(destination.height, source.height);
2179 int width = min(destination.width, source.width);
2180
2181 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002182 {
2183 unsigned char *sourceRow = sourceSlice;
2184 unsigned char *destinationRow = destinationSlice;
2185
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002186 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002187 {
2188 unsigned char *sourceElement = sourceRow;
2189 unsigned char *destinationElement = destinationRow;
2190
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002191 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002192 {
2193 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002194
John Bauman89401822014-05-06 15:04:28 -04002195 unsigned int a = ((argb & 0xF000) * 0x00011000) & 0xFF000000;
2196 unsigned int r = ((argb & 0x0F00) * 0x00001100) & 0x00FF0000;
2197 unsigned int g = ((argb & 0x00F0) * 0x00000110) & 0x0000FF00;
2198 unsigned int b = (argb & 0x000F) * 0x00000011;
2199
2200 *(unsigned int*)destinationElement = a | r | g | b;
2201
2202 sourceElement += source.bytes;
2203 destinationElement += destination.bytes;
2204 }
2205
2206 sourceRow += source.pitchB;
2207 destinationRow += destination.pitchB;
2208 }
2209
2210 sourceSlice += source.sliceB;
2211 destinationSlice += destination.sliceB;
2212 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002213
2214 source.unlockRect();
2215 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002216 }
2217
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002218 void Surface::decodeP8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002219 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002220 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002221 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002222
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002223 int depth = min(destination.depth, source.depth);
2224 int height = min(destination.height, source.height);
2225 int width = min(destination.width, source.width);
2226
2227 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002228 {
2229 unsigned char *sourceRow = sourceSlice;
2230 unsigned char *destinationRow = destinationSlice;
2231
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002232 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002233 {
2234 unsigned char *sourceElement = sourceRow;
2235 unsigned char *destinationElement = destinationRow;
2236
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002237 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002238 {
2239 unsigned int abgr = palette[*(unsigned char*)sourceElement];
2240
2241 unsigned int r = (abgr & 0x000000FF) << 16;
2242 unsigned int g = (abgr & 0x0000FF00) << 0;
2243 unsigned int b = (abgr & 0x00FF0000) >> 16;
2244 unsigned int a = (abgr & 0xFF000000) >> 0;
2245
2246 *(unsigned int*)destinationElement = a | r | g | b;
2247
2248 sourceElement += source.bytes;
2249 destinationElement += destination.bytes;
2250 }
2251
2252 sourceRow += source.pitchB;
2253 destinationRow += destination.pitchB;
2254 }
2255
2256 sourceSlice += source.sliceB;
2257 destinationSlice += destination.sliceB;
2258 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002259
2260 source.unlockRect();
2261 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002262 }
2263
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002264 void Surface::decodeDXT1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002265 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002266 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002267 const DXT1 *source = (const DXT1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002268
2269 for(int z = 0; z < external.depth; z++)
2270 {
2271 unsigned int *dest = destSlice;
2272
2273 for(int y = 0; y < external.height; y += 4)
2274 {
2275 for(int x = 0; x < external.width; x += 4)
2276 {
2277 Color<byte> c[4];
2278
2279 c[0] = source->c0;
2280 c[1] = source->c1;
2281
2282 if(source->c0 > source->c1) // No transparency
2283 {
2284 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2285 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2286 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2287 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2288 c[2].a = 0xFF;
2289
2290 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2291 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2292 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2293 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2294 c[3].a = 0xFF;
2295 }
2296 else // c3 transparent
2297 {
2298 // c2 = 1 / 2 * c0 + 1 / 2 * c1
2299 c[2].r = (byte)(((word)c[0].r + (word)c[1].r) / 2);
2300 c[2].g = (byte)(((word)c[0].g + (word)c[1].g) / 2);
2301 c[2].b = (byte)(((word)c[0].b + (word)c[1].b) / 2);
2302 c[2].a = 0xFF;
2303
2304 c[3].r = 0;
2305 c[3].g = 0;
2306 c[3].b = 0;
2307 c[3].a = 0;
2308 }
2309
2310 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2311 {
2312 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2313 {
Nicolas Capens539468c2018-06-28 11:28:40 -04002314 dest[(x + i) + (y + j) * internal.pitchP] = c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4];
John Bauman89401822014-05-06 15:04:28 -04002315 }
2316 }
2317
2318 source++;
2319 }
2320 }
2321
2322 (byte*&)destSlice += internal.sliceB;
2323 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002324
2325 external.unlockRect();
2326 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002327 }
2328
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002329 void Surface::decodeDXT3(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002330 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002331 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002332 const DXT3 *source = (const DXT3*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002333
2334 for(int z = 0; z < external.depth; z++)
2335 {
2336 unsigned int *dest = destSlice;
2337
2338 for(int y = 0; y < external.height; y += 4)
2339 {
2340 for(int x = 0; x < external.width; x += 4)
2341 {
2342 Color<byte> c[4];
2343
2344 c[0] = source->c0;
2345 c[1] = source->c1;
2346
2347 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2348 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2349 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2350 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2351
2352 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2353 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2354 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2355 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2356
2357 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2358 {
2359 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2360 {
2361 unsigned int a = (unsigned int)(source->a >> 4 * (i + j * 4)) & 0x0F;
2362 unsigned int color = (c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | ((a << 28) + (a << 24));
2363
Nicolas Capens539468c2018-06-28 11:28:40 -04002364 dest[(x + i) + (y + j) * internal.pitchP] = color;
John Bauman89401822014-05-06 15:04:28 -04002365 }
2366 }
2367
2368 source++;
2369 }
2370 }
2371
2372 (byte*&)destSlice += internal.sliceB;
2373 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002374
2375 external.unlockRect();
2376 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002377 }
2378
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002379 void Surface::decodeDXT5(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002380 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002381 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002382 const DXT5 *source = (const DXT5*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002383
2384 for(int z = 0; z < external.depth; z++)
2385 {
2386 unsigned int *dest = destSlice;
2387
2388 for(int y = 0; y < external.height; y += 4)
2389 {
2390 for(int x = 0; x < external.width; x += 4)
2391 {
2392 Color<byte> c[4];
2393
2394 c[0] = source->c0;
2395 c[1] = source->c1;
2396
2397 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2398 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2399 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2400 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2401
2402 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2403 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2404 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2405 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2406
2407 byte a[8];
2408
2409 a[0] = source->a0;
2410 a[1] = source->a1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002411
John Bauman89401822014-05-06 15:04:28 -04002412 if(a[0] > a[1])
2413 {
2414 a[2] = (byte)((6 * (word)a[0] + 1 * (word)a[1] + 3) / 7);
2415 a[3] = (byte)((5 * (word)a[0] + 2 * (word)a[1] + 3) / 7);
2416 a[4] = (byte)((4 * (word)a[0] + 3 * (word)a[1] + 3) / 7);
2417 a[5] = (byte)((3 * (word)a[0] + 4 * (word)a[1] + 3) / 7);
2418 a[6] = (byte)((2 * (word)a[0] + 5 * (word)a[1] + 3) / 7);
2419 a[7] = (byte)((1 * (word)a[0] + 6 * (word)a[1] + 3) / 7);
2420 }
2421 else
2422 {
2423 a[2] = (byte)((4 * (word)a[0] + 1 * (word)a[1] + 2) / 5);
2424 a[3] = (byte)((3 * (word)a[0] + 2 * (word)a[1] + 2) / 5);
2425 a[4] = (byte)((2 * (word)a[0] + 3 * (word)a[1] + 2) / 5);
2426 a[5] = (byte)((1 * (word)a[0] + 4 * (word)a[1] + 2) / 5);
2427 a[6] = 0;
2428 a[7] = 0xFF;
2429 }
2430
2431 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2432 {
2433 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2434 {
2435 unsigned int alpha = (unsigned int)a[(unsigned int)(source->alut >> (16 + 3 * (i + j * 4))) % 8] << 24;
2436 unsigned int color = (c[(source->clut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | alpha;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002437
Nicolas Capens539468c2018-06-28 11:28:40 -04002438 dest[(x + i) + (y + j) * internal.pitchP] = color;
John Bauman89401822014-05-06 15:04:28 -04002439 }
2440 }
2441
2442 source++;
2443 }
2444 }
2445
2446 (byte*&)destSlice += internal.sliceB;
2447 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002448
2449 external.unlockRect();
2450 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002451 }
2452
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002453 void Surface::decodeATI1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002454 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002455 byte *destSlice = (byte*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002456 const ATI1 *source = (const ATI1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002457
2458 for(int z = 0; z < external.depth; z++)
2459 {
2460 byte *dest = destSlice;
2461
2462 for(int y = 0; y < external.height; y += 4)
2463 {
2464 for(int x = 0; x < external.width; x += 4)
2465 {
2466 byte r[8];
2467
2468 r[0] = source->r0;
2469 r[1] = source->r1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002470
John Bauman89401822014-05-06 15:04:28 -04002471 if(r[0] > r[1])
2472 {
2473 r[2] = (byte)((6 * (word)r[0] + 1 * (word)r[1] + 3) / 7);
2474 r[3] = (byte)((5 * (word)r[0] + 2 * (word)r[1] + 3) / 7);
2475 r[4] = (byte)((4 * (word)r[0] + 3 * (word)r[1] + 3) / 7);
2476 r[5] = (byte)((3 * (word)r[0] + 4 * (word)r[1] + 3) / 7);
2477 r[6] = (byte)((2 * (word)r[0] + 5 * (word)r[1] + 3) / 7);
2478 r[7] = (byte)((1 * (word)r[0] + 6 * (word)r[1] + 3) / 7);
2479 }
2480 else
2481 {
2482 r[2] = (byte)((4 * (word)r[0] + 1 * (word)r[1] + 2) / 5);
2483 r[3] = (byte)((3 * (word)r[0] + 2 * (word)r[1] + 2) / 5);
2484 r[4] = (byte)((2 * (word)r[0] + 3 * (word)r[1] + 2) / 5);
2485 r[5] = (byte)((1 * (word)r[0] + 4 * (word)r[1] + 2) / 5);
2486 r[6] = 0;
2487 r[7] = 0xFF;
2488 }
2489
2490 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2491 {
2492 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2493 {
Nicolas Capens539468c2018-06-28 11:28:40 -04002494 dest[(x + i) + (y + j) * internal.pitchP] = r[(unsigned int)(source->rlut >> (16 + 3 * (i + j * 4))) % 8];
John Bauman89401822014-05-06 15:04:28 -04002495 }
2496 }
2497
2498 source++;
2499 }
2500 }
2501
2502 destSlice += internal.sliceB;
2503 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002504
2505 external.unlockRect();
2506 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002507 }
2508
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002509 void Surface::decodeATI2(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002510 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002511 word *destSlice = (word*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002512 const ATI2 *source = (const ATI2*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002513
2514 for(int z = 0; z < external.depth; z++)
2515 {
2516 word *dest = destSlice;
2517
2518 for(int y = 0; y < external.height; y += 4)
2519 {
2520 for(int x = 0; x < external.width; x += 4)
2521 {
2522 byte X[8];
2523
2524 X[0] = source->x0;
2525 X[1] = source->x1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002526
John Bauman89401822014-05-06 15:04:28 -04002527 if(X[0] > X[1])
2528 {
2529 X[2] = (byte)((6 * (word)X[0] + 1 * (word)X[1] + 3) / 7);
2530 X[3] = (byte)((5 * (word)X[0] + 2 * (word)X[1] + 3) / 7);
2531 X[4] = (byte)((4 * (word)X[0] + 3 * (word)X[1] + 3) / 7);
2532 X[5] = (byte)((3 * (word)X[0] + 4 * (word)X[1] + 3) / 7);
2533 X[6] = (byte)((2 * (word)X[0] + 5 * (word)X[1] + 3) / 7);
2534 X[7] = (byte)((1 * (word)X[0] + 6 * (word)X[1] + 3) / 7);
2535 }
2536 else
2537 {
2538 X[2] = (byte)((4 * (word)X[0] + 1 * (word)X[1] + 2) / 5);
2539 X[3] = (byte)((3 * (word)X[0] + 2 * (word)X[1] + 2) / 5);
2540 X[4] = (byte)((2 * (word)X[0] + 3 * (word)X[1] + 2) / 5);
2541 X[5] = (byte)((1 * (word)X[0] + 4 * (word)X[1] + 2) / 5);
2542 X[6] = 0;
2543 X[7] = 0xFF;
2544 }
2545
2546 byte Y[8];
2547
2548 Y[0] = source->y0;
2549 Y[1] = source->y1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002550
John Bauman89401822014-05-06 15:04:28 -04002551 if(Y[0] > Y[1])
2552 {
2553 Y[2] = (byte)((6 * (word)Y[0] + 1 * (word)Y[1] + 3) / 7);
2554 Y[3] = (byte)((5 * (word)Y[0] + 2 * (word)Y[1] + 3) / 7);
2555 Y[4] = (byte)((4 * (word)Y[0] + 3 * (word)Y[1] + 3) / 7);
2556 Y[5] = (byte)((3 * (word)Y[0] + 4 * (word)Y[1] + 3) / 7);
2557 Y[6] = (byte)((2 * (word)Y[0] + 5 * (word)Y[1] + 3) / 7);
2558 Y[7] = (byte)((1 * (word)Y[0] + 6 * (word)Y[1] + 3) / 7);
2559 }
2560 else
2561 {
2562 Y[2] = (byte)((4 * (word)Y[0] + 1 * (word)Y[1] + 2) / 5);
2563 Y[3] = (byte)((3 * (word)Y[0] + 2 * (word)Y[1] + 2) / 5);
2564 Y[4] = (byte)((2 * (word)Y[0] + 3 * (word)Y[1] + 2) / 5);
2565 Y[5] = (byte)((1 * (word)Y[0] + 4 * (word)Y[1] + 2) / 5);
2566 Y[6] = 0;
2567 Y[7] = 0xFF;
2568 }
2569
2570 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2571 {
2572 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2573 {
2574 word r = X[(unsigned int)(source->xlut >> (16 + 3 * (i + j * 4))) % 8];
2575 word g = Y[(unsigned int)(source->ylut >> (16 + 3 * (i + j * 4))) % 8];
2576
Nicolas Capens539468c2018-06-28 11:28:40 -04002577 dest[(x + i) + (y + j) * internal.pitchP] = (g << 8) + r;
John Bauman89401822014-05-06 15:04:28 -04002578 }
2579 }
2580
2581 source++;
2582 }
2583 }
2584
2585 (byte*&)destSlice += internal.sliceB;
2586 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002587
2588 external.unlockRect();
2589 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002590 }
Nicolas Capens22658242014-11-29 00:31:41 -05002591
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002592 void Surface::decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002593 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002594 ETC_Decoder::Decode((const byte*)external.lockRect(0, 0, 0, LOCK_READONLY), (byte*)internal.lockRect(0, 0, 0, LOCK_UPDATE), external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes,
Alexis Hetu0de50d42015-09-09 13:56:41 -04002595 (nbAlphaBits == 8) ? ETC_Decoder::ETC_RGBA : ((nbAlphaBits == 1) ? ETC_Decoder::ETC_RGB_PUNCHTHROUGH_ALPHA : ETC_Decoder::ETC_RGB));
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002596 external.unlockRect();
2597 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002598
Alexis Hetu0de50d42015-09-09 13:56:41 -04002599 if(isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002600 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002601 static byte sRGBtoLinearTable[256];
2602 static bool sRGBtoLinearTableDirty = true;
2603 if(sRGBtoLinearTableDirty)
Nicolas Capens22658242014-11-29 00:31:41 -05002604 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002605 for(int i = 0; i < 256; i++)
Nicolas Capens22658242014-11-29 00:31:41 -05002606 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002607 sRGBtoLinearTable[i] = static_cast<byte>(sRGBtoLinear(static_cast<float>(i) / 255.0f) * 255.0f + 0.5f);
Nicolas Capens22658242014-11-29 00:31:41 -05002608 }
Alexis Hetu0de50d42015-09-09 13:56:41 -04002609 sRGBtoLinearTableDirty = false;
Nicolas Capens22658242014-11-29 00:31:41 -05002610 }
2611
Alexis Hetu0de50d42015-09-09 13:56:41 -04002612 // Perform sRGB conversion in place after decoding
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002613 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002614 for(int y = 0; y < internal.height; y++)
2615 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002616 byte *srcRow = src + y * internal.pitchB;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002617 for(int x = 0; x < internal.width; x++)
2618 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002619 byte *srcPix = srcRow + x * internal.bytes;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002620 for(int i = 0; i < 3; i++)
2621 {
2622 srcPix[i] = sRGBtoLinearTable[srcPix[i]];
2623 }
2624 }
2625 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002626 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002627 }
2628 }
John Bauman89401822014-05-06 15:04:28 -04002629
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002630 void Surface::decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002631 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002632 ASSERT(nbChannels == 1 || nbChannels == 2);
Alexis Hetu460e41f2015-09-01 10:58:37 -04002633
Alexis Hetuf46493f2017-12-18 15:32:26 -05002634 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
2635 ETC_Decoder::Decode((const byte*)external.lockRect(0, 0, 0, LOCK_READONLY), src, external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes,
Alexis Hetu0de50d42015-09-09 13:56:41 -04002636 (nbChannels == 1) ? (isSigned ? ETC_Decoder::ETC_R_SIGNED : ETC_Decoder::ETC_R_UNSIGNED) : (isSigned ? ETC_Decoder::ETC_RG_SIGNED : ETC_Decoder::ETC_RG_UNSIGNED));
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002637 external.unlockRect();
Alexis Hetu0de50d42015-09-09 13:56:41 -04002638
Alexis Hetuf46493f2017-12-18 15:32:26 -05002639 // FIXME: We convert EAC data to float, until signed short internal formats are supported
2640 // This code can be removed if ETC2 images are decoded to internal 16 bit signed R/RG formats
2641 const float normalization = isSigned ? (1.0f / (8.0f * 127.875f)) : (1.0f / (8.0f * 255.875f));
2642 for(int y = 0; y < internal.height; y++)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002643 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002644 byte* srcRow = src + y * internal.pitchB;
2645 for(int x = internal.width - 1; x >= 0; x--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002646 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002647 int* srcPix = reinterpret_cast<int*>(srcRow + x * internal.bytes);
2648 float* dstPix = reinterpret_cast<float*>(srcPix);
2649 for(int c = nbChannels - 1; c >= 0; c--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002650 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002651 dstPix[c] = clamp(static_cast<float>(srcPix[c]) * normalization, -1.0f, 1.0f);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002652 }
2653 }
2654 }
Alexis Hetuf46493f2017-12-18 15:32:26 -05002655
2656 internal.unlockRect();
Alexis Hetu460e41f2015-09-01 10:58:37 -04002657 }
2658
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002659 void Surface::decodeASTC(Buffer &internal, Buffer &external, int xBlockSize, int yBlockSize, int zBlockSize, bool isSRGB)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002660 {
2661 }
2662
Nicolas Capens419a5802018-05-08 17:20:50 -04002663 size_t Surface::size(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04002664 {
Nicolas Capens607771b2018-05-08 17:20:50 -04002665 samples = max(1, samples);
2666
John Bauman89401822014-05-06 15:04:28 -04002667 switch(format)
2668 {
Nicolas Capens419a5802018-05-08 17:20:50 -04002669 default:
Nicolas Capens607771b2018-05-08 17:20:50 -04002670 {
2671 uint64_t size = (uint64_t)sliceB(width, height, border, format, true) * depth * samples;
Nicolas Capens419a5802018-05-08 17:20:50 -04002672
Nicolas Capens607771b2018-05-08 17:20:50 -04002673 // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
2674 // and stencil operations also read 8 bytes per four 8-bit stencil values,
2675 // so we have to allocate 4 extra bytes to avoid buffer overruns.
2676 size += 4;
2677
2678 // We can only sample buffers smaller than 2 GiB.
2679 // Force an out-of-memory if larger, or let the caller report an error.
2680 return size < 0x80000000u ? (size_t)size : std::numeric_limits<size_t>::max();
2681 }
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002682 case FORMAT_YV12_BT601:
2683 case FORMAT_YV12_BT709:
2684 case FORMAT_YV12_JFIF:
2685 {
Nicolas Capens419a5802018-05-08 17:20:50 -04002686 width += 2 * border;
2687 height += 2 * border;
2688
2689 size_t YStride = align<16>(width);
2690 size_t YSize = YStride * height;
2691 size_t CStride = align<16>(YStride / 2);
2692 size_t CSize = CStride * height / 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002693
2694 return YSize + 2 * CSize;
2695 }
John Bauman89401822014-05-06 15:04:28 -04002696 }
John Bauman89401822014-05-06 15:04:28 -04002697 }
2698
2699 bool Surface::isStencil(Format format)
2700 {
2701 switch(format)
2702 {
2703 case FORMAT_D32:
2704 case FORMAT_D16:
2705 case FORMAT_D24X8:
2706 case FORMAT_D32F:
2707 case FORMAT_D32F_COMPLEMENTARY:
2708 case FORMAT_D32F_LOCKABLE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002709 case FORMAT_D32F_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002710 return false;
2711 case FORMAT_D24S8:
2712 case FORMAT_D24FS8:
2713 case FORMAT_S8:
John Bauman66b8ab22014-05-06 15:57:45 -04002714 case FORMAT_DF24S8:
2715 case FORMAT_DF16S8:
2716 case FORMAT_D32FS8_TEXTURE:
2717 case FORMAT_D32FS8_SHADOW:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002718 case FORMAT_D32FS8:
2719 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002720 case FORMAT_INTZ:
2721 return true;
2722 default:
2723 return false;
2724 }
2725 }
2726
2727 bool Surface::isDepth(Format format)
2728 {
2729 switch(format)
2730 {
2731 case FORMAT_D32:
2732 case FORMAT_D16:
2733 case FORMAT_D24X8:
2734 case FORMAT_D24S8:
2735 case FORMAT_D24FS8:
2736 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002737 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002738 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002739 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002740 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002741 case FORMAT_DF24S8:
2742 case FORMAT_DF16S8:
2743 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002744 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002745 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002746 case FORMAT_INTZ:
2747 return true;
2748 case FORMAT_S8:
2749 return false;
2750 default:
2751 return false;
2752 }
2753 }
2754
Alexis Hetub9dda642016-10-06 11:25:32 -04002755 bool Surface::hasQuadLayout(Format format)
2756 {
2757 switch(format)
2758 {
2759 case FORMAT_D32:
2760 case FORMAT_D16:
2761 case FORMAT_D24X8:
2762 case FORMAT_D24S8:
2763 case FORMAT_D24FS8:
2764 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002765 case FORMAT_D32FS8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002766 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002767 case FORMAT_D32FS8_COMPLEMENTARY:
Alexis Hetub9dda642016-10-06 11:25:32 -04002768 case FORMAT_DF24S8:
2769 case FORMAT_DF16S8:
2770 case FORMAT_INTZ:
2771 case FORMAT_S8:
2772 case FORMAT_A8G8R8B8Q:
2773 case FORMAT_X8G8R8B8Q:
2774 return true;
2775 case FORMAT_D32F_LOCKABLE:
2776 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002777 case FORMAT_D32F_SHADOW:
Alexis Hetub9dda642016-10-06 11:25:32 -04002778 case FORMAT_D32FS8_SHADOW:
2779 default:
2780 break;
2781 }
2782
2783 return false;
2784 }
2785
John Bauman89401822014-05-06 15:04:28 -04002786 bool Surface::isPalette(Format format)
2787 {
2788 switch(format)
2789 {
2790 case FORMAT_P8:
2791 case FORMAT_A8P8:
2792 return true;
2793 default:
2794 return false;
2795 }
2796 }
2797
2798 bool Surface::isFloatFormat(Format format)
2799 {
2800 switch(format)
2801 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002802 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002803 case FORMAT_R8G8B8:
2804 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002805 case FORMAT_X8R8G8B8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002806 case FORMAT_X8B8G8R8I:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002807 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002808 case FORMAT_A8R8G8B8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002809 case FORMAT_SRGB8_X8:
2810 case FORMAT_SRGB8_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002811 case FORMAT_A8B8G8R8I:
2812 case FORMAT_R8UI:
2813 case FORMAT_G8R8UI:
2814 case FORMAT_X8B8G8R8UI:
2815 case FORMAT_A8B8G8R8UI:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002816 case FORMAT_A8B8G8R8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002817 case FORMAT_G8R8I:
John Bauman89401822014-05-06 15:04:28 -04002818 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002819 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002820 case FORMAT_A2B10G10R10UI:
Nicolas Capens975adb72017-12-19 15:34:20 -05002821 case FORMAT_R8_SNORM:
2822 case FORMAT_G8R8_SNORM:
2823 case FORMAT_X8B8G8R8_SNORM:
2824 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu43577b82015-10-21 15:32:16 -04002825 case FORMAT_R16I:
2826 case FORMAT_R16UI:
2827 case FORMAT_G16R16I:
2828 case FORMAT_G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002829 case FORMAT_G16R16:
Alexis Hetu43577b82015-10-21 15:32:16 -04002830 case FORMAT_X16B16G16R16I:
2831 case FORMAT_X16B16G16R16UI:
2832 case FORMAT_A16B16G16R16I:
2833 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002834 case FORMAT_A16B16G16R16:
2835 case FORMAT_V8U8:
2836 case FORMAT_Q8W8V8U8:
2837 case FORMAT_X8L8V8U8:
2838 case FORMAT_V16U16:
2839 case FORMAT_A16W16V16U16:
2840 case FORMAT_Q16W16V16U16:
2841 case FORMAT_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002842 case FORMAT_R8I:
John Bauman89401822014-05-06 15:04:28 -04002843 case FORMAT_R8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002844 case FORMAT_S8:
John Bauman89401822014-05-06 15:04:28 -04002845 case FORMAT_L8:
2846 case FORMAT_L16:
2847 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002848 case FORMAT_YV12_BT601:
2849 case FORMAT_YV12_BT709:
2850 case FORMAT_YV12_JFIF:
Alexis Hetu43577b82015-10-21 15:32:16 -04002851 case FORMAT_R32I:
2852 case FORMAT_R32UI:
2853 case FORMAT_G32R32I:
2854 case FORMAT_G32R32UI:
2855 case FORMAT_X32B32G32R32I:
2856 case FORMAT_X32B32G32R32UI:
2857 case FORMAT_A32B32G32R32I:
2858 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002859 return false;
Nicolas Capens400667e2017-03-29 14:40:14 -04002860 case FORMAT_R16F:
2861 case FORMAT_G16R16F:
2862 case FORMAT_B16G16R16F:
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05002863 case FORMAT_X16B16G16R16F:
Nicolas Capens400667e2017-03-29 14:40:14 -04002864 case FORMAT_A16B16G16R16F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002865 case FORMAT_X16B16G16R16F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002866 case FORMAT_R32F:
2867 case FORMAT_G32R32F:
Nicolas Capensc018e082016-12-13 10:19:33 -05002868 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002869 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002870 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002871 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002872 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002873 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002874 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002875 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002876 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002877 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002878 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002879 case FORMAT_D32FS8_SHADOW:
Nicolas Capens80594422015-06-09 16:42:56 -04002880 case FORMAT_L16F:
2881 case FORMAT_A16L16F:
2882 case FORMAT_L32F:
2883 case FORMAT_A32L32F:
John Bauman89401822014-05-06 15:04:28 -04002884 return true;
2885 default:
2886 ASSERT(false);
2887 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04002888
John Bauman89401822014-05-06 15:04:28 -04002889 return false;
2890 }
2891
2892 bool Surface::isUnsignedComponent(Format format, int component)
2893 {
2894 switch(format)
2895 {
2896 case FORMAT_NULL:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002897 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002898 case FORMAT_R8G8B8:
2899 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002900 case FORMAT_X8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002901 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002902 case FORMAT_A8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002903 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002904 case FORMAT_SRGB8_X8:
2905 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002906 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002907 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002908 case FORMAT_A2B10G10R10UI:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002909 case FORMAT_R16UI:
John Bauman89401822014-05-06 15:04:28 -04002910 case FORMAT_G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002911 case FORMAT_G16R16UI:
2912 case FORMAT_X16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002913 case FORMAT_A16B16G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002914 case FORMAT_A16B16G16R16UI:
2915 case FORMAT_R32UI:
2916 case FORMAT_G32R32UI:
2917 case FORMAT_X32B32G32R32UI:
2918 case FORMAT_A32B32G32R32UI:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002919 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002920 case FORMAT_R8UI:
2921 case FORMAT_G8R8UI:
2922 case FORMAT_X8B8G8R8UI:
2923 case FORMAT_A8B8G8R8UI:
John Bauman89401822014-05-06 15:04:28 -04002924 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002925 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002926 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002927 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002928 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002929 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002930 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002931 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002932 case FORMAT_A8:
2933 case FORMAT_R8:
2934 case FORMAT_L8:
2935 case FORMAT_L16:
2936 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002937 case FORMAT_YV12_BT601:
2938 case FORMAT_YV12_BT709:
2939 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002940 return true;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002941 case FORMAT_A8B8G8R8I:
2942 case FORMAT_A16B16G16R16I:
2943 case FORMAT_A32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002944 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002945 case FORMAT_Q8W8V8U8:
2946 case FORMAT_Q16W16V16U16:
2947 case FORMAT_A32B32G32R32F:
2948 return false;
2949 case FORMAT_R32F:
2950 case FORMAT_R8I:
2951 case FORMAT_R16I:
2952 case FORMAT_R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002953 case FORMAT_R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002954 return component >= 1;
John Bauman89401822014-05-06 15:04:28 -04002955 case FORMAT_V8U8:
2956 case FORMAT_X8L8V8U8:
2957 case FORMAT_V16U16:
John Bauman89401822014-05-06 15:04:28 -04002958 case FORMAT_G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002959 case FORMAT_G8R8I:
2960 case FORMAT_G16R16I:
2961 case FORMAT_G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002962 case FORMAT_G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002963 return component >= 2;
2964 case FORMAT_A16W16V16U16:
Nicolas Capens2e363b02016-12-14 10:32:36 -05002965 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002966 case FORMAT_X32B32G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002967 case FORMAT_X8B8G8R8I:
2968 case FORMAT_X16B16G16R16I:
2969 case FORMAT_X32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002970 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002971 return component >= 3;
John Bauman89401822014-05-06 15:04:28 -04002972 default:
2973 ASSERT(false);
2974 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04002975
John Bauman89401822014-05-06 15:04:28 -04002976 return false;
2977 }
2978
2979 bool Surface::isSRGBreadable(Format format)
2980 {
2981 // Keep in sync with Capabilities::isSRGBreadable
2982 switch(format)
2983 {
2984 case FORMAT_L8:
2985 case FORMAT_A8L8:
2986 case FORMAT_R8G8B8:
2987 case FORMAT_A8R8G8B8:
2988 case FORMAT_X8R8G8B8:
2989 case FORMAT_A8B8G8R8:
2990 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002991 case FORMAT_SRGB8_X8:
2992 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002993 case FORMAT_R5G6B5:
2994 case FORMAT_X1R5G5B5:
2995 case FORMAT_A1R5G5B5:
2996 case FORMAT_A4R4G4B4:
John Bauman89401822014-05-06 15:04:28 -04002997 case FORMAT_DXT1:
2998 case FORMAT_DXT3:
2999 case FORMAT_DXT5:
3000 case FORMAT_ATI1:
3001 case FORMAT_ATI2:
John Bauman89401822014-05-06 15:04:28 -04003002 return true;
3003 default:
3004 return false;
3005 }
John Bauman89401822014-05-06 15:04:28 -04003006 }
3007
3008 bool Surface::isSRGBwritable(Format format)
3009 {
3010 // Keep in sync with Capabilities::isSRGBwritable
3011 switch(format)
3012 {
3013 case FORMAT_NULL:
3014 case FORMAT_A8R8G8B8:
3015 case FORMAT_X8R8G8B8:
3016 case FORMAT_A8B8G8R8:
3017 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04003018 case FORMAT_SRGB8_X8:
3019 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04003020 case FORMAT_R5G6B5:
3021 return true;
3022 default:
3023 return false;
3024 }
3025 }
3026
Nicolas Capens5555af42017-12-14 13:14:03 -05003027 bool Surface::isSRGBformat(Format format)
3028 {
3029 switch(format)
3030 {
3031 case FORMAT_SRGB8_X8:
3032 case FORMAT_SRGB8_A8:
3033 return true;
3034 default:
3035 return false;
3036 }
3037 }
3038
John Bauman89401822014-05-06 15:04:28 -04003039 bool Surface::isCompressed(Format format)
3040 {
3041 switch(format)
3042 {
John Bauman89401822014-05-06 15:04:28 -04003043 case FORMAT_DXT1:
3044 case FORMAT_DXT3:
3045 case FORMAT_DXT5:
3046 case FORMAT_ATI1:
3047 case FORMAT_ATI2:
Nicolas Capens22658242014-11-29 00:31:41 -05003048 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003049 case FORMAT_R11_EAC:
3050 case FORMAT_SIGNED_R11_EAC:
3051 case FORMAT_RG11_EAC:
3052 case FORMAT_SIGNED_RG11_EAC:
3053 case FORMAT_RGB8_ETC2:
3054 case FORMAT_SRGB8_ETC2:
3055 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3056 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3057 case FORMAT_RGBA8_ETC2_EAC:
3058 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3059 case FORMAT_RGBA_ASTC_4x4_KHR:
3060 case FORMAT_RGBA_ASTC_5x4_KHR:
3061 case FORMAT_RGBA_ASTC_5x5_KHR:
3062 case FORMAT_RGBA_ASTC_6x5_KHR:
3063 case FORMAT_RGBA_ASTC_6x6_KHR:
3064 case FORMAT_RGBA_ASTC_8x5_KHR:
3065 case FORMAT_RGBA_ASTC_8x6_KHR:
3066 case FORMAT_RGBA_ASTC_8x8_KHR:
3067 case FORMAT_RGBA_ASTC_10x5_KHR:
3068 case FORMAT_RGBA_ASTC_10x6_KHR:
3069 case FORMAT_RGBA_ASTC_10x8_KHR:
3070 case FORMAT_RGBA_ASTC_10x10_KHR:
3071 case FORMAT_RGBA_ASTC_12x10_KHR:
3072 case FORMAT_RGBA_ASTC_12x12_KHR:
3073 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3074 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3075 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3076 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3077 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3078 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3079 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3080 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3081 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3082 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3083 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3084 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3085 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3086 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
John Bauman89401822014-05-06 15:04:28 -04003087 return true;
John Bauman89401822014-05-06 15:04:28 -04003088 default:
3089 return false;
3090 }
3091 }
3092
Nicolas Capens492887a2017-03-27 14:50:51 -04003093 bool Surface::isSignedNonNormalizedInteger(Format format)
Alexis Hetu43577b82015-10-21 15:32:16 -04003094 {
3095 switch(format)
3096 {
3097 case FORMAT_A8B8G8R8I:
3098 case FORMAT_X8B8G8R8I:
3099 case FORMAT_G8R8I:
3100 case FORMAT_R8I:
Alexis Hetu43577b82015-10-21 15:32:16 -04003101 case FORMAT_A16B16G16R16I:
3102 case FORMAT_X16B16G16R16I:
3103 case FORMAT_G16R16I:
3104 case FORMAT_R16I:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003105 case FORMAT_A32B32G32R32I:
3106 case FORMAT_X32B32G32R32I:
3107 case FORMAT_G32R32I:
3108 case FORMAT_R32I:
Nicolas Capens492887a2017-03-27 14:50:51 -04003109 return true;
3110 default:
3111 return false;
3112 }
3113 }
3114
3115 bool Surface::isUnsignedNonNormalizedInteger(Format format)
3116 {
3117 switch(format)
3118 {
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003119 case FORMAT_A8B8G8R8UI:
3120 case FORMAT_X8B8G8R8UI:
3121 case FORMAT_G8R8UI:
3122 case FORMAT_R8UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003123 case FORMAT_A16B16G16R16UI:
3124 case FORMAT_X16B16G16R16UI:
3125 case FORMAT_G16R16UI:
3126 case FORMAT_R16UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003127 case FORMAT_A32B32G32R32UI:
3128 case FORMAT_X32B32G32R32UI:
3129 case FORMAT_G32R32UI:
3130 case FORMAT_R32UI:
3131 return true;
3132 default:
3133 return false;
3134 }
3135 }
3136
Nicolas Capens492887a2017-03-27 14:50:51 -04003137 bool Surface::isNonNormalizedInteger(Format format)
3138 {
3139 return isSignedNonNormalizedInteger(format) ||
3140 isUnsignedNonNormalizedInteger(format);
3141 }
3142
3143 bool Surface::isNormalizedInteger(Format format)
3144 {
3145 return !isFloatFormat(format) &&
3146 !isNonNormalizedInteger(format) &&
3147 !isCompressed(format) &&
3148 !isDepth(format) &&
3149 !isStencil(format);
3150 }
3151
John Bauman89401822014-05-06 15:04:28 -04003152 int Surface::componentCount(Format format)
3153 {
3154 switch(format)
3155 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003156 case FORMAT_R5G6B5: return 3;
3157 case FORMAT_X8R8G8B8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003158 case FORMAT_X8B8G8R8I: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003159 case FORMAT_X8B8G8R8: return 3;
3160 case FORMAT_A8R8G8B8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04003161 case FORMAT_SRGB8_X8: return 3;
3162 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003163 case FORMAT_A8B8G8R8I: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003164 case FORMAT_A8B8G8R8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003165 case FORMAT_G8R8I: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003166 case FORMAT_G8R8: return 2;
Nicolas Capens975adb72017-12-19 15:34:20 -05003167 case FORMAT_R8_SNORM: return 1;
3168 case FORMAT_G8R8_SNORM: return 2;
3169 case FORMAT_X8B8G8R8_SNORM:return 3;
3170 case FORMAT_A8B8G8R8_SNORM:return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003171 case FORMAT_R8UI: return 1;
3172 case FORMAT_G8R8UI: return 2;
3173 case FORMAT_X8B8G8R8UI: return 3;
3174 case FORMAT_A8B8G8R8UI: return 4;
Alexis Hetuf999a002015-12-17 11:09:36 -05003175 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05003176 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003177 case FORMAT_G16R16I: return 2;
3178 case FORMAT_G16R16UI: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003179 case FORMAT_G16R16: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003180 case FORMAT_G32R32I: return 2;
3181 case FORMAT_G32R32UI: return 2;
3182 case FORMAT_X16B16G16R16I: return 3;
3183 case FORMAT_X16B16G16R16UI: return 3;
3184 case FORMAT_A16B16G16R16I: return 4;
3185 case FORMAT_A16B16G16R16UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003186 case FORMAT_A16B16G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003187 case FORMAT_X32B32G32R32I: return 3;
3188 case FORMAT_X32B32G32R32UI: return 3;
3189 case FORMAT_A32B32G32R32I: return 4;
3190 case FORMAT_A32B32G32R32UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003191 case FORMAT_V8U8: return 2;
3192 case FORMAT_Q8W8V8U8: return 4;
3193 case FORMAT_X8L8V8U8: return 3;
3194 case FORMAT_V16U16: return 2;
3195 case FORMAT_A16W16V16U16: return 4;
3196 case FORMAT_Q16W16V16U16: return 4;
3197 case FORMAT_R32F: return 1;
3198 case FORMAT_G32R32F: return 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003199 case FORMAT_X32B32G32R32F: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003200 case FORMAT_A32B32G32R32F: return 4;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003201 case FORMAT_X32B32G32R32F_UNSIGNED: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003202 case FORMAT_D32F: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003203 case FORMAT_D32FS8: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003204 case FORMAT_D32F_LOCKABLE: return 1;
3205 case FORMAT_D32FS8_TEXTURE: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003206 case FORMAT_D32F_SHADOW: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003207 case FORMAT_D32FS8_SHADOW: return 1;
3208 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003209 case FORMAT_R8I: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003210 case FORMAT_R8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003211 case FORMAT_R16I: return 1;
3212 case FORMAT_R16UI: return 1;
3213 case FORMAT_R32I: return 1;
3214 case FORMAT_R32UI: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003215 case FORMAT_L8: return 1;
3216 case FORMAT_L16: return 1;
3217 case FORMAT_A8L8: return 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003218 case FORMAT_YV12_BT601: return 3;
3219 case FORMAT_YV12_BT709: return 3;
3220 case FORMAT_YV12_JFIF: return 3;
John Bauman89401822014-05-06 15:04:28 -04003221 default:
3222 ASSERT(false);
3223 }
3224
3225 return 1;
3226 }
3227
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003228 void *Surface::allocateBuffer(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04003229 {
Nicolas Capens419a5802018-05-08 17:20:50 -04003230 return allocate(size(width, height, depth, border, samples, format));
John Bauman89401822014-05-06 15:04:28 -04003231 }
3232
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003233 void Surface::memfill4(void *buffer, int pattern, int bytes)
John Bauman89401822014-05-06 15:04:28 -04003234 {
3235 while((size_t)buffer & 0x1 && bytes >= 1)
3236 {
3237 *(char*)buffer = (char)pattern;
3238 (char*&)buffer += 1;
3239 bytes -= 1;
3240 }
3241
3242 while((size_t)buffer & 0x3 && bytes >= 2)
3243 {
3244 *(short*)buffer = (short)pattern;
3245 (short*&)buffer += 1;
3246 bytes -= 2;
3247 }
3248
Nicolas Capens47dc8672017-04-25 12:54:39 -04003249 #if defined(__i386__) || defined(__x86_64__)
3250 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04003251 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04003252 while((size_t)buffer & 0xF && bytes >= 4)
3253 {
3254 *(int*)buffer = pattern;
3255 (int*&)buffer += 1;
3256 bytes -= 4;
3257 }
3258
3259 __m128 quad = _mm_set_ps1((float&)pattern);
3260
3261 float *pointer = (float*)buffer;
3262 int qxwords = bytes / 64;
3263 bytes -= qxwords * 64;
3264
3265 while(qxwords--)
3266 {
3267 _mm_stream_ps(pointer + 0, quad);
3268 _mm_stream_ps(pointer + 4, quad);
3269 _mm_stream_ps(pointer + 8, quad);
3270 _mm_stream_ps(pointer + 12, quad);
3271
3272 pointer += 16;
3273 }
3274
3275 buffer = pointer;
John Bauman89401822014-05-06 15:04:28 -04003276 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04003277 #endif
John Bauman89401822014-05-06 15:04:28 -04003278
3279 while(bytes >= 4)
3280 {
3281 *(int*)buffer = (int)pattern;
3282 (int*&)buffer += 1;
3283 bytes -= 4;
3284 }
3285
3286 while(bytes >= 2)
3287 {
3288 *(short*)buffer = (short)pattern;
3289 (short*&)buffer += 1;
3290 bytes -= 2;
3291 }
3292
3293 while(bytes >= 1)
3294 {
3295 *(char*)buffer = (char)pattern;
3296 (char*&)buffer += 1;
3297 bytes -= 1;
3298 }
3299 }
3300
Nicolas Capensbf7a8142017-05-19 10:57:28 -04003301 void Surface::sync()
3302 {
3303 resource->lock(EXCLUSIVE);
3304 resource->unlock();
3305 }
3306
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003307 bool Surface::isEntire(const Rect& rect) const
John Bauman89401822014-05-06 15:04:28 -04003308 {
Alexis Hetu75b650f2015-11-19 17:40:15 -05003309 return (rect.x0 == 0 && rect.y0 == 0 && rect.x1 == internal.width && rect.y1 == internal.height && internal.depth == 1);
3310 }
John Bauman89401822014-05-06 15:04:28 -04003311
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003312 Rect Surface::getRect() const
Alexis Hetu75b650f2015-11-19 17:40:15 -05003313 {
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003314 return Rect(0, 0, internal.width, internal.height);
John Bauman89401822014-05-06 15:04:28 -04003315 }
3316
Nicolas Capensc39901e2016-03-21 16:37:44 -04003317 void Surface::clearDepth(float depth, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003318 {
Nicolas Capens38488762018-04-12 16:31:32 -04003319 if(width == 0 || height == 0)
3320 {
3321 return;
3322 }
3323
3324 if(internal.format == FORMAT_NULL)
3325 {
3326 return;
3327 }
Alexis Hetu358a1442015-12-03 14:23:10 -05003328
John Bauman89401822014-05-06 15:04:28 -04003329 // Not overlapping
3330 if(x0 > internal.width) return;
3331 if(y0 > internal.height) return;
3332 if(x0 + width < 0) return;
3333 if(y0 + height < 0) return;
3334
3335 // Clip against dimensions
3336 if(x0 < 0) {width += x0; x0 = 0;}
3337 if(x0 + width > internal.width) width = internal.width - x0;
3338 if(y0 < 0) {height += y0; y0 = 0;}
3339 if(y0 + height > internal.height) height = internal.height - y0;
3340
3341 const bool entire = x0 == 0 && y0 == 0 && width == internal.width && height == internal.height;
3342 const Lock lock = entire ? LOCK_DISCARD : LOCK_WRITEONLY;
3343
John Bauman89401822014-05-06 15:04:28 -04003344 int x1 = x0 + width;
3345 int y1 = y0 + height;
3346
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003347 if(!hasQuadLayout(internal.format))
John Bauman89401822014-05-06 15:04:28 -04003348 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003349 float *target = (float*)lockInternal(x0, y0, 0, lock, PUBLIC);
John Bauman89401822014-05-06 15:04:28 -04003350
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003351 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003352 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003353 float *row = target;
John Bauman89401822014-05-06 15:04:28 -04003354 for(int y = y0; y < y1; y++)
3355 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003356 memfill4(row, (int&)depth, width * sizeof(float));
3357 row += internal.pitchP;
John Bauman89401822014-05-06 15:04:28 -04003358 }
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003359 target += internal.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003360 }
3361
3362 unlockInternal();
3363 }
3364 else // Quad layout
3365 {
3366 if(complementaryDepthBuffer)
3367 {
3368 depth = 1 - depth;
3369 }
3370
3371 float *buffer = (float*)lockInternal(0, 0, 0, lock, PUBLIC);
3372
Alexis Hetu358a1442015-12-03 14:23:10 -05003373 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3374 int oddX1 = (x1 & ~1) * 2;
3375 int evenX0 = ((x0 + 1) & ~1) * 2;
3376 int evenBytes = (oddX1 - evenX0) * sizeof(float);
3377
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003378 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003379 {
3380 for(int y = y0; y < y1; y++)
3381 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003382 float *target = buffer + (y & ~1) * internal.pitchP + (y & 1) * 2;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003383
John Bauman89401822014-05-06 15:04:28 -04003384 if((y & 1) == 0 && y + 1 < y1) // Fill quad line at once
3385 {
3386 if((x0 & 1) != 0)
3387 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003388 target[oddX0 + 0] = depth;
3389 target[oddX0 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003390 }
3391
Alexis Hetu358a1442015-12-03 14:23:10 -05003392 // for(int x2 = evenX0; x2 < x1 * 2; x2 += 4)
John Bauman89401822014-05-06 15:04:28 -04003393 // {
3394 // target[x2 + 0] = depth;
3395 // target[x2 + 1] = depth;
3396 // target[x2 + 2] = depth;
3397 // target[x2 + 3] = depth;
3398 // }
3399
3400 // __asm
3401 // {
3402 // movss xmm0, depth
3403 // shufps xmm0, xmm0, 0x00
3404 //
3405 // mov eax, x0
3406 // add eax, 1
3407 // and eax, 0xFFFFFFFE
3408 // cmp eax, x1
3409 // jge qEnd
3410 //
3411 // mov edi, target
3412 //
3413 // qLoop:
3414 // movntps [edi+8*eax], xmm0
3415 //
3416 // add eax, 2
3417 // cmp eax, x1
3418 // jl qLoop
3419 // qEnd:
3420 // }
3421
Alexis Hetu358a1442015-12-03 14:23:10 -05003422 memfill4(&target[evenX0], (int&)depth, evenBytes);
John Bauman89401822014-05-06 15:04:28 -04003423
3424 if((x1 & 1) != 0)
3425 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003426 target[oddX1 + 0] = depth;
3427 target[oddX1 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003428 }
3429
3430 y++;
3431 }
3432 else
3433 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003434 for(int x = x0, i = oddX0; x < x1; x++, i = (x & ~1) * 2 + (x & 1))
John Bauman89401822014-05-06 15:04:28 -04003435 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003436 target[i] = depth;
John Bauman89401822014-05-06 15:04:28 -04003437 }
3438 }
3439 }
3440
3441 buffer += internal.sliceP;
3442 }
3443
3444 unlockInternal();
3445 }
3446 }
3447
Nicolas Capensc39901e2016-03-21 16:37:44 -04003448 void Surface::clearStencil(unsigned char s, unsigned char mask, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003449 {
Nicolas Capens38488762018-04-12 16:31:32 -04003450 if(mask == 0 || width == 0 || height == 0)
3451 {
3452 return;
3453 }
3454
3455 if(stencil.format == FORMAT_NULL)
3456 {
3457 return;
3458 }
Alexis Hetu2b052f82015-11-25 13:57:28 -05003459
John Bauman89401822014-05-06 15:04:28 -04003460 // Not overlapping
3461 if(x0 > internal.width) return;
3462 if(y0 > internal.height) return;
3463 if(x0 + width < 0) return;
3464 if(y0 + height < 0) return;
3465
3466 // Clip against dimensions
3467 if(x0 < 0) {width += x0; x0 = 0;}
3468 if(x0 + width > internal.width) width = internal.width - x0;
3469 if(y0 < 0) {height += y0; y0 = 0;}
3470 if(y0 + height > internal.height) height = internal.height - y0;
3471
John Bauman89401822014-05-06 15:04:28 -04003472 int x1 = x0 + width;
3473 int y1 = y0 + height;
3474
Alexis Hetu358a1442015-12-03 14:23:10 -05003475 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3476 int oddX1 = (x1 & ~1) * 2;
3477 int evenX0 = ((x0 + 1) & ~1) * 2;
3478 int evenBytes = oddX1 - evenX0;
3479
John Bauman89401822014-05-06 15:04:28 -04003480 unsigned char maskedS = s & mask;
3481 unsigned char invMask = ~mask;
3482 unsigned int fill = maskedS;
Tom Anderson69bc6e82017-03-20 11:54:29 -07003483 fill = fill | (fill << 8) | (fill << 16) | (fill << 24);
John Bauman89401822014-05-06 15:04:28 -04003484
Alexis Hetua52dfbd2016-10-05 17:03:30 -04003485 char *buffer = (char*)lockStencil(0, 0, 0, PUBLIC);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003486
3487 // Stencil buffers are assumed to use quad layout
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003488 for(int z = 0; z < stencil.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003489 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003490 for(int y = y0; y < y1; y++)
John Bauman89401822014-05-06 15:04:28 -04003491 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003492 char *target = buffer + (y & ~1) * stencil.pitchP + (y & 1) * 2;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003493
3494 if((y & 1) == 0 && y + 1 < y1 && mask == 0xFF) // Fill quad line at once
John Bauman89401822014-05-06 15:04:28 -04003495 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003496 if((x0 & 1) != 0)
John Bauman89401822014-05-06 15:04:28 -04003497 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003498 target[oddX0 + 0] = fill;
3499 target[oddX0 + 2] = fill;
John Bauman89401822014-05-06 15:04:28 -04003500 }
3501
Alexis Hetu358a1442015-12-03 14:23:10 -05003502 memfill4(&target[evenX0], fill, evenBytes);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003503
3504 if((x1 & 1) != 0)
3505 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003506 target[oddX1 + 0] = fill;
3507 target[oddX1 + 2] = fill;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003508 }
3509
3510 y++;
3511 }
3512 else
3513 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003514 for(int x = x0; x < x1; x++)
Alexis Hetu2b052f82015-11-25 13:57:28 -05003515 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003516 int i = (x & ~1) * 2 + (x & 1);
Alexis Hetu358a1442015-12-03 14:23:10 -05003517 target[i] = maskedS | (target[i] & invMask);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003518 }
John Bauman89401822014-05-06 15:04:28 -04003519 }
3520 }
3521
Alexis Hetu2b052f82015-11-25 13:57:28 -05003522 buffer += stencil.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003523 }
John Bauman89401822014-05-06 15:04:28 -04003524
Alexis Hetu2b052f82015-11-25 13:57:28 -05003525 unlockStencil();
John Bauman89401822014-05-06 15:04:28 -04003526 }
3527
3528 void Surface::fill(const Color<float> &color, int x0, int y0, int width, int height)
3529 {
3530 unsigned char *row;
3531 Buffer *buffer;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003532
John Bauman89401822014-05-06 15:04:28 -04003533 if(internal.dirty)
3534 {
3535 row = (unsigned char*)lockInternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3536 buffer = &internal;
3537 }
3538 else
3539 {
3540 row = (unsigned char*)lockExternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3541 buffer = &external;
3542 }
3543
3544 if(buffer->bytes <= 4)
3545 {
3546 int c;
3547 buffer->write(&c, color);
3548
3549 if(buffer->bytes <= 1) c = (c << 8) | c;
3550 if(buffer->bytes <= 2) c = (c << 16) | c;
3551
3552 for(int y = 0; y < height; y++)
3553 {
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003554 memfill4(row, c, width * buffer->bytes);
John Bauman89401822014-05-06 15:04:28 -04003555
3556 row += buffer->pitchB;
3557 }
3558 }
3559 else // Generic
3560 {
3561 for(int y = 0; y < height; y++)
3562 {
3563 unsigned char *element = row;
3564
3565 for(int x = 0; x < width; x++)
3566 {
3567 buffer->write(element, color);
3568
3569 element += buffer->bytes;
3570 }
3571
3572 row += buffer->pitchB;
3573 }
3574 }
3575
3576 if(buffer == &internal)
3577 {
3578 unlockInternal();
3579 }
3580 else
3581 {
3582 unlockExternal();
3583 }
3584 }
3585
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003586 void Surface::copyInternal(const Surface *source, int x, int y, float srcX, float srcY, bool filter)
John Bauman89401822014-05-06 15:04:28 -04003587 {
Alexis Hetu43577b82015-10-21 15:32:16 -04003588 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
John Bauman89401822014-05-06 15:04:28 -04003589
Alexis Hetu43577b82015-10-21 15:32:16 -04003590 sw::Color<float> color;
John Bauman89401822014-05-06 15:04:28 -04003591
Alexis Hetu43577b82015-10-21 15:32:16 -04003592 if(!filter)
3593 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003594 color = source->internal.read((int)srcX, (int)srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003595 }
3596 else // Bilinear filtering
3597 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003598 color = source->internal.sample(srcX, srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003599 }
John Bauman89401822014-05-06 15:04:28 -04003600
3601 internal.write(x, y, color);
3602 }
3603
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003604 void Surface::copyInternal(const Surface *source, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter)
Alexis Hetu43577b82015-10-21 15:32:16 -04003605 {
3606 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
3607
3608 sw::Color<float> color;
3609
3610 if(!filter)
3611 {
3612 color = source->internal.read((int)srcX, (int)srcY, int(srcZ));
3613 }
3614 else // Bilinear filtering
3615 {
3616 color = source->internal.sample(srcX, srcY, srcZ);
3617 }
3618
3619 internal.write(x, y, z, color);
3620 }
3621
Alexis Hetua76a1bf2016-11-29 17:17:26 -05003622 void Surface::copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge)
3623 {
3624 Surface *dst = this;
3625
3626 // Figure out if the edges to be copied in reverse order respectively from one another
3627 // The copy should be reversed whenever the same edges are contiguous or if we're
3628 // copying top <-> right or bottom <-> left. This is explained by the layout, which is:
3629 //
3630 // | +y |
3631 // | -x | +z | +x | -z |
3632 // | -y |
3633
3634 bool reverse = (srcEdge == dstEdge) ||
3635 ((srcEdge == TOP) && (dstEdge == RIGHT)) ||
3636 ((srcEdge == RIGHT) && (dstEdge == TOP)) ||
3637 ((srcEdge == BOTTOM) && (dstEdge == LEFT)) ||
3638 ((srcEdge == LEFT) && (dstEdge == BOTTOM));
3639
3640 int srcBytes = src->bytes(src->Surface::getInternalFormat());
3641 int srcPitch = src->getInternalPitchB();
3642 int dstBytes = dst->bytes(dst->Surface::getInternalFormat());
3643 int dstPitch = dst->getInternalPitchB();
3644
3645 int srcW = src->getWidth();
3646 int srcH = src->getHeight();
3647 int dstW = dst->getWidth();
3648 int dstH = dst->getHeight();
3649
3650 ASSERT(srcW == srcH && dstW == dstH && srcW == dstW && srcBytes == dstBytes);
3651
3652 // Src is expressed in the regular [0, width-1], [0, height-1] space
3653 int srcDelta = ((srcEdge == TOP) || (srcEdge == BOTTOM)) ? srcBytes : srcPitch;
3654 int srcStart = ((srcEdge == BOTTOM) ? srcPitch * (srcH - 1) : ((srcEdge == RIGHT) ? srcBytes * (srcW - 1) : 0));
3655
3656 // Dst contains borders, so it is expressed in the [-1, width+1], [-1, height+1] space
3657 int dstDelta = (((dstEdge == TOP) || (dstEdge == BOTTOM)) ? dstBytes : dstPitch) * (reverse ? -1 : 1);
3658 int dstStart = ((dstEdge == BOTTOM) ? dstPitch * (dstH + 1) : ((dstEdge == RIGHT) ? dstBytes * (dstW + 1) : 0)) + (reverse ? dstW * -dstDelta : dstDelta);
3659
3660 char *srcBuf = (char*)src->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PRIVATE) + srcStart;
3661 char *dstBuf = (char*)dst->lockInternal(-1, -1, 0, sw::LOCK_READWRITE, sw::PRIVATE) + dstStart;
3662
3663 for(int i = 0; i < srcW; ++i, dstBuf += dstDelta, srcBuf += srcDelta)
3664 {
3665 memcpy(dstBuf, srcBuf, srcBytes);
3666 }
3667
3668 if(dstEdge == LEFT || dstEdge == RIGHT)
3669 {
3670 // TOP and BOTTOM are already set, let's average out the corners
3671 int x0 = (dstEdge == RIGHT) ? dstW : -1;
3672 int y0 = -1;
3673 int x1 = (dstEdge == RIGHT) ? dstW - 1 : 0;
3674 int y1 = 0;
3675 dst->computeCubeCorner(x0, y0, x1, y1);
3676 y0 = dstH;
3677 y1 = dstH - 1;
3678 dst->computeCubeCorner(x0, y0, x1, y1);
3679 }
3680
3681 src->unlockInternal();
3682 dst->unlockInternal();
3683 }
3684
3685 void Surface::computeCubeCorner(int x0, int y0, int x1, int y1)
3686 {
3687 ASSERT(internal.lock != LOCK_UNLOCKED);
3688
3689 sw::Color<float> color = internal.read(x0, y1);
3690 color += internal.read(x1, y0);
3691 color += internal.read(x1, y1);
3692 color *= (1.0f / 3.0f);
3693
3694 internal.write(x0, y0, color);
3695 }
3696
John Bauman89401822014-05-06 15:04:28 -04003697 bool Surface::hasStencil() const
3698 {
3699 return isStencil(external.format);
3700 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04003701
John Bauman89401822014-05-06 15:04:28 -04003702 bool Surface::hasDepth() const
3703 {
3704 return isDepth(external.format);
3705 }
3706
3707 bool Surface::hasPalette() const
3708 {
3709 return isPalette(external.format);
3710 }
3711
3712 bool Surface::isRenderTarget() const
3713 {
3714 return renderTarget;
3715 }
3716
Nicolas Capens73e18c12017-11-28 13:31:35 -05003717 bool Surface::hasDirtyContents() const
John Bauman89401822014-05-06 15:04:28 -04003718 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003719 return dirtyContents;
John Bauman89401822014-05-06 15:04:28 -04003720 }
3721
Nicolas Capens73e18c12017-11-28 13:31:35 -05003722 void Surface::markContentsClean()
John Bauman89401822014-05-06 15:04:28 -04003723 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003724 dirtyContents = false;
John Bauman89401822014-05-06 15:04:28 -04003725 }
3726
3727 Resource *Surface::getResource()
3728 {
3729 return resource;
3730 }
3731
Nicolas Capens539468c2018-06-28 11:28:40 -04003732 bool Surface::identicalBuffers() const
John Bauman89401822014-05-06 15:04:28 -04003733 {
John Bauman66b8ab22014-05-06 15:57:45 -04003734 return external.format == internal.format &&
3735 external.width == internal.width &&
Nicolas Capens22658242014-11-29 00:31:41 -05003736 external.height == internal.height &&
3737 external.depth == internal.depth &&
3738 external.pitchB == internal.pitchB &&
Alexis Hetu9c6d5222016-11-29 17:02:14 -05003739 external.sliceB == internal.sliceB &&
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003740 external.border == internal.border &&
3741 external.samples == internal.samples;
John Bauman89401822014-05-06 15:04:28 -04003742 }
3743
3744 Format Surface::selectInternalFormat(Format format) const
3745 {
3746 switch(format)
3747 {
3748 case FORMAT_NULL:
3749 return FORMAT_NULL;
3750 case FORMAT_P8:
3751 case FORMAT_A8P8:
3752 case FORMAT_A4R4G4B4:
3753 case FORMAT_A1R5G5B5:
3754 case FORMAT_A8R3G3B2:
3755 return FORMAT_A8R8G8B8;
3756 case FORMAT_A8:
3757 return FORMAT_A8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003758 case FORMAT_R8I:
3759 return FORMAT_R8I;
3760 case FORMAT_R8UI:
3761 return FORMAT_R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003762 case FORMAT_R8_SNORM:
3763 return FORMAT_R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003764 case FORMAT_R8:
3765 return FORMAT_R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003766 case FORMAT_R16I:
3767 return FORMAT_R16I;
3768 case FORMAT_R16UI:
3769 return FORMAT_R16UI;
3770 case FORMAT_R32I:
3771 return FORMAT_R32I;
3772 case FORMAT_R32UI:
3773 return FORMAT_R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003774 case FORMAT_X16B16G16R16I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003775 return FORMAT_X16B16G16R16I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003776 case FORMAT_A16B16G16R16I:
3777 return FORMAT_A16B16G16R16I;
3778 case FORMAT_X16B16G16R16UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003779 return FORMAT_X16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003780 case FORMAT_A16B16G16R16UI:
3781 return FORMAT_A16B16G16R16UI;
Alexis Hetuf999a002015-12-17 11:09:36 -05003782 case FORMAT_A2R10G10B10:
3783 case FORMAT_A2B10G10R10:
John Bauman89401822014-05-06 15:04:28 -04003784 case FORMAT_A16B16G16R16:
3785 return FORMAT_A16B16G16R16;
Nicolas Capens5555af42017-12-14 13:14:03 -05003786 case FORMAT_A2B10G10R10UI:
3787 return FORMAT_A16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003788 case FORMAT_X32B32G32R32I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003789 return FORMAT_X32B32G32R32I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003790 case FORMAT_A32B32G32R32I:
3791 return FORMAT_A32B32G32R32I;
3792 case FORMAT_X32B32G32R32UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003793 return FORMAT_X32B32G32R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003794 case FORMAT_A32B32G32R32UI:
3795 return FORMAT_A32B32G32R32UI;
3796 case FORMAT_G8R8I:
3797 return FORMAT_G8R8I;
3798 case FORMAT_G8R8UI:
3799 return FORMAT_G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003800 case FORMAT_G8R8_SNORM:
3801 return FORMAT_G8R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003802 case FORMAT_G8R8:
3803 return FORMAT_G8R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003804 case FORMAT_G16R16I:
3805 return FORMAT_G16R16I;
3806 case FORMAT_G16R16UI:
3807 return FORMAT_G16R16UI;
John Bauman89401822014-05-06 15:04:28 -04003808 case FORMAT_G16R16:
3809 return FORMAT_G16R16;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003810 case FORMAT_G32R32I:
3811 return FORMAT_G32R32I;
3812 case FORMAT_G32R32UI:
3813 return FORMAT_G32R32UI;
John Bauman89401822014-05-06 15:04:28 -04003814 case FORMAT_A8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003815 if(lockable || !quadLayoutEnabled)
3816 {
3817 return FORMAT_A8R8G8B8;
3818 }
3819 else
3820 {
3821 return FORMAT_A8G8R8B8Q;
3822 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003823 case FORMAT_A8B8G8R8I:
3824 return FORMAT_A8B8G8R8I;
3825 case FORMAT_A8B8G8R8UI:
3826 return FORMAT_A8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003827 case FORMAT_A8B8G8R8_SNORM:
3828 return FORMAT_A8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003829 case FORMAT_R5G5B5A1:
3830 case FORMAT_R4G4B4A4:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003831 case FORMAT_A8B8G8R8:
3832 return FORMAT_A8B8G8R8;
John Bauman89401822014-05-06 15:04:28 -04003833 case FORMAT_R5G6B5:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003834 return FORMAT_R5G6B5;
3835 case FORMAT_R3G3B2:
John Bauman89401822014-05-06 15:04:28 -04003836 case FORMAT_R8G8B8:
3837 case FORMAT_X4R4G4B4:
3838 case FORMAT_X1R5G5B5:
3839 case FORMAT_X8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003840 if(lockable || !quadLayoutEnabled)
3841 {
3842 return FORMAT_X8R8G8B8;
3843 }
3844 else
3845 {
3846 return FORMAT_X8G8R8B8Q;
3847 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003848 case FORMAT_X8B8G8R8I:
3849 return FORMAT_X8B8G8R8I;
3850 case FORMAT_X8B8G8R8UI:
3851 return FORMAT_X8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003852 case FORMAT_X8B8G8R8_SNORM:
3853 return FORMAT_X8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003854 case FORMAT_B8G8R8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003855 case FORMAT_X8B8G8R8:
3856 return FORMAT_X8B8G8R8;
Alexis Hetu049a1872016-04-25 16:59:58 -04003857 case FORMAT_SRGB8_X8:
3858 return FORMAT_SRGB8_X8;
3859 case FORMAT_SRGB8_A8:
3860 return FORMAT_SRGB8_A8;
John Bauman89401822014-05-06 15:04:28 -04003861 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04003862 case FORMAT_DXT1:
3863 case FORMAT_DXT3:
3864 case FORMAT_DXT5:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003865 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3866 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3867 case FORMAT_RGBA8_ETC2_EAC:
3868 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3869 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3870 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3871 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3872 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3873 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3874 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3875 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3876 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3877 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3878 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3879 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3880 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3881 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3882 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
3883 return FORMAT_A8R8G8B8;
3884 case FORMAT_RGBA_ASTC_4x4_KHR:
3885 case FORMAT_RGBA_ASTC_5x4_KHR:
3886 case FORMAT_RGBA_ASTC_5x5_KHR:
3887 case FORMAT_RGBA_ASTC_6x5_KHR:
3888 case FORMAT_RGBA_ASTC_6x6_KHR:
3889 case FORMAT_RGBA_ASTC_8x5_KHR:
3890 case FORMAT_RGBA_ASTC_8x6_KHR:
3891 case FORMAT_RGBA_ASTC_8x8_KHR:
3892 case FORMAT_RGBA_ASTC_10x5_KHR:
3893 case FORMAT_RGBA_ASTC_10x6_KHR:
3894 case FORMAT_RGBA_ASTC_10x8_KHR:
3895 case FORMAT_RGBA_ASTC_10x10_KHR:
3896 case FORMAT_RGBA_ASTC_12x10_KHR:
3897 case FORMAT_RGBA_ASTC_12x12_KHR:
3898 // ASTC supports HDR, so a floating point format is required to represent it properly
3899 return FORMAT_A32B32G32R32F; // FIXME: 16FP is probably sufficient, but it's currently unsupported
John Bauman89401822014-05-06 15:04:28 -04003900 case FORMAT_ATI1:
3901 return FORMAT_R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003902 case FORMAT_R11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003903 case FORMAT_SIGNED_R11_EAC:
3904 return FORMAT_R32F; // FIXME: Signed 8bit format would be sufficient
John Bauman89401822014-05-06 15:04:28 -04003905 case FORMAT_ATI2:
3906 return FORMAT_G8R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003907 case FORMAT_RG11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003908 case FORMAT_SIGNED_RG11_EAC:
3909 return FORMAT_G32R32F; // FIXME: Signed 8bit format would be sufficient
Nicolas Capens22658242014-11-29 00:31:41 -05003910 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003911 case FORMAT_RGB8_ETC2:
3912 case FORMAT_SRGB8_ETC2:
Nicolas Capens22658242014-11-29 00:31:41 -05003913 return FORMAT_X8R8G8B8;
John Bauman89401822014-05-06 15:04:28 -04003914 // Bumpmap formats
3915 case FORMAT_V8U8: return FORMAT_V8U8;
3916 case FORMAT_L6V5U5: return FORMAT_X8L8V8U8;
3917 case FORMAT_Q8W8V8U8: return FORMAT_Q8W8V8U8;
3918 case FORMAT_X8L8V8U8: return FORMAT_X8L8V8U8;
3919 case FORMAT_V16U16: return FORMAT_V16U16;
3920 case FORMAT_A2W10V10U10: return FORMAT_A16W16V16U16;
3921 case FORMAT_Q16W16V16U16: return FORMAT_Q16W16V16U16;
3922 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04003923 case FORMAT_A16F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003924 case FORMAT_R16F: return FORMAT_R32F;
3925 case FORMAT_G16R16F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003926 case FORMAT_B16G16R16F: return FORMAT_X32B32G32R32F;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05003927 case FORMAT_X16B16G16R16F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003928 case FORMAT_A16B16G16R16F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003929 case FORMAT_X16B16G16R16F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
Nicolas Capens80594422015-06-09 16:42:56 -04003930 case FORMAT_A32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003931 case FORMAT_R32F: return FORMAT_R32F;
3932 case FORMAT_G32R32F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003933 case FORMAT_B32G32R32F: return FORMAT_X32B32G32R32F;
3934 case FORMAT_X32B32G32R32F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003935 case FORMAT_A32B32G32R32F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003936 case FORMAT_X32B32G32R32F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
John Bauman89401822014-05-06 15:04:28 -04003937 // Luminance formats
3938 case FORMAT_L8: return FORMAT_L8;
3939 case FORMAT_A4L4: return FORMAT_A8L8;
3940 case FORMAT_L16: return FORMAT_L16;
3941 case FORMAT_A8L8: return FORMAT_A8L8;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003942 case FORMAT_L16F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003943 case FORMAT_A16L16F: return FORMAT_A32B32G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003944 case FORMAT_L32F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003945 case FORMAT_A32L32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003946 // Depth/stencil formats
3947 case FORMAT_D16:
3948 case FORMAT_D32:
3949 case FORMAT_D24X8:
John Bauman89401822014-05-06 15:04:28 -04003950 if(hasParent) // Texture
3951 {
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003952 return FORMAT_D32F_SHADOW;
John Bauman89401822014-05-06 15:04:28 -04003953 }
3954 else if(complementaryDepthBuffer)
3955 {
3956 return FORMAT_D32F_COMPLEMENTARY;
3957 }
3958 else
3959 {
3960 return FORMAT_D32F;
3961 }
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003962 case FORMAT_D24S8:
3963 case FORMAT_D24FS8:
3964 if(hasParent) // Texture
3965 {
3966 return FORMAT_D32FS8_SHADOW;
3967 }
3968 else if(complementaryDepthBuffer)
3969 {
3970 return FORMAT_D32FS8_COMPLEMENTARY;
3971 }
3972 else
3973 {
3974 return FORMAT_D32FS8;
3975 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003976 case FORMAT_D32F: return FORMAT_D32F;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003977 case FORMAT_D32FS8: return FORMAT_D32FS8;
John Bauman66b8ab22014-05-06 15:57:45 -04003978 case FORMAT_D32F_LOCKABLE: return FORMAT_D32F_LOCKABLE;
3979 case FORMAT_D32FS8_TEXTURE: return FORMAT_D32FS8_TEXTURE;
3980 case FORMAT_INTZ: return FORMAT_D32FS8_TEXTURE;
3981 case FORMAT_DF24S8: return FORMAT_D32FS8_SHADOW;
3982 case FORMAT_DF16S8: return FORMAT_D32FS8_SHADOW;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003983 case FORMAT_S8: return FORMAT_S8;
3984 // YUV formats
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003985 case FORMAT_YV12_BT601: return FORMAT_YV12_BT601;
3986 case FORMAT_YV12_BT709: return FORMAT_YV12_BT709;
3987 case FORMAT_YV12_JFIF: return FORMAT_YV12_JFIF;
John Bauman89401822014-05-06 15:04:28 -04003988 default:
3989 ASSERT(false);
3990 }
3991
3992 return FORMAT_NULL;
3993 }
3994
3995 void Surface::setTexturePalette(unsigned int *palette)
3996 {
3997 Surface::palette = palette;
3998 Surface::paletteID++;
3999 }
4000
4001 void Surface::resolve()
4002 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004003 if(internal.samples <= 1 || !internal.dirty || !renderTarget || internal.format == FORMAT_NULL)
John Bauman89401822014-05-06 15:04:28 -04004004 {
4005 return;
4006 }
4007
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004008 ASSERT(internal.depth == 1); // Unimplemented
4009
John Bauman89401822014-05-06 15:04:28 -04004010 void *source = internal.lockRect(0, 0, 0, LOCK_READWRITE);
4011
John Bauman89401822014-05-06 15:04:28 -04004012 int width = internal.width;
4013 int height = internal.height;
4014 int pitch = internal.pitchB;
4015 int slice = internal.sliceB;
4016
4017 unsigned char *source0 = (unsigned char*)source;
4018 unsigned char *source1 = source0 + slice;
4019 unsigned char *source2 = source1 + slice;
4020 unsigned char *source3 = source2 + slice;
4021 unsigned char *source4 = source3 + slice;
4022 unsigned char *source5 = source4 + slice;
4023 unsigned char *source6 = source5 + slice;
4024 unsigned char *source7 = source6 + slice;
4025 unsigned char *source8 = source7 + slice;
4026 unsigned char *source9 = source8 + slice;
4027 unsigned char *sourceA = source9 + slice;
4028 unsigned char *sourceB = sourceA + slice;
4029 unsigned char *sourceC = sourceB + slice;
4030 unsigned char *sourceD = sourceC + slice;
4031 unsigned char *sourceE = sourceD + slice;
4032 unsigned char *sourceF = sourceE + slice;
4033
Alexis Hetu049a1872016-04-25 16:59:58 -04004034 if(internal.format == FORMAT_X8R8G8B8 || internal.format == FORMAT_A8R8G8B8 ||
4035 internal.format == FORMAT_X8B8G8R8 || internal.format == FORMAT_A8B8G8R8 ||
4036 internal.format == FORMAT_SRGB8_X8 || internal.format == FORMAT_SRGB8_A8)
John Bauman89401822014-05-06 15:04:28 -04004037 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004038 #if defined(__i386__) || defined(__x86_64__)
4039 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004040 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004041 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004042 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004043 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004044 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004045 for(int x = 0; x < width; x += 4)
4046 {
4047 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4048 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004049
Nicolas Capens47dc8672017-04-25 12:54:39 -04004050 c0 = _mm_avg_epu8(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004051
Nicolas Capens47dc8672017-04-25 12:54:39 -04004052 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4053 }
4054
4055 source0 += pitch;
4056 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004057 }
John Bauman89401822014-05-06 15:04:28 -04004058 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004059 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004060 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004061 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004062 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004063 for(int x = 0; x < width; x += 4)
4064 {
4065 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4066 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4067 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4068 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004069
Nicolas Capens47dc8672017-04-25 12:54:39 -04004070 c0 = _mm_avg_epu8(c0, c1);
4071 c2 = _mm_avg_epu8(c2, c3);
4072 c0 = _mm_avg_epu8(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004073
Nicolas Capens47dc8672017-04-25 12:54:39 -04004074 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4075 }
4076
4077 source0 += pitch;
4078 source1 += pitch;
4079 source2 += pitch;
4080 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004081 }
John Bauman89401822014-05-06 15:04:28 -04004082 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004083 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004084 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004085 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004086 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004087 for(int x = 0; x < width; x += 4)
4088 {
4089 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4090 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4091 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4092 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4093 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4094 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4095 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4096 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004097
Nicolas Capens47dc8672017-04-25 12:54:39 -04004098 c0 = _mm_avg_epu8(c0, c1);
4099 c2 = _mm_avg_epu8(c2, c3);
4100 c4 = _mm_avg_epu8(c4, c5);
4101 c6 = _mm_avg_epu8(c6, c7);
4102 c0 = _mm_avg_epu8(c0, c2);
4103 c4 = _mm_avg_epu8(c4, c6);
4104 c0 = _mm_avg_epu8(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004105
Nicolas Capens47dc8672017-04-25 12:54:39 -04004106 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4107 }
4108
4109 source0 += pitch;
4110 source1 += pitch;
4111 source2 += pitch;
4112 source3 += pitch;
4113 source4 += pitch;
4114 source5 += pitch;
4115 source6 += pitch;
4116 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004117 }
John Bauman89401822014-05-06 15:04:28 -04004118 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004119 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004120 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004121 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004122 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004123 for(int x = 0; x < width; x += 4)
4124 {
4125 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4126 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4127 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4128 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4129 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4130 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4131 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4132 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4133 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4134 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4135 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4136 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4137 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4138 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4139 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4140 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004141
Nicolas Capens47dc8672017-04-25 12:54:39 -04004142 c0 = _mm_avg_epu8(c0, c1);
4143 c2 = _mm_avg_epu8(c2, c3);
4144 c4 = _mm_avg_epu8(c4, c5);
4145 c6 = _mm_avg_epu8(c6, c7);
4146 c8 = _mm_avg_epu8(c8, c9);
4147 cA = _mm_avg_epu8(cA, cB);
4148 cC = _mm_avg_epu8(cC, cD);
4149 cE = _mm_avg_epu8(cE, cF);
4150 c0 = _mm_avg_epu8(c0, c2);
4151 c4 = _mm_avg_epu8(c4, c6);
4152 c8 = _mm_avg_epu8(c8, cA);
4153 cC = _mm_avg_epu8(cC, cE);
4154 c0 = _mm_avg_epu8(c0, c4);
4155 c8 = _mm_avg_epu8(c8, cC);
4156 c0 = _mm_avg_epu8(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004157
Nicolas Capens47dc8672017-04-25 12:54:39 -04004158 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4159 }
4160
4161 source0 += pitch;
4162 source1 += pitch;
4163 source2 += pitch;
4164 source3 += pitch;
4165 source4 += pitch;
4166 source5 += pitch;
4167 source6 += pitch;
4168 source7 += pitch;
4169 source8 += pitch;
4170 source9 += pitch;
4171 sourceA += pitch;
4172 sourceB += pitch;
4173 sourceC += pitch;
4174 sourceD += pitch;
4175 sourceE += pitch;
4176 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004177 }
John Bauman89401822014-05-06 15:04:28 -04004178 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004179 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004180 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004181 else
4182 #endif
John Bauman89401822014-05-06 15:04:28 -04004183 {
4184 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7F7F7F7F) + (((x) ^ (y)) & 0x01010101))
4185
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004186 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004187 {
4188 for(int y = 0; y < height; y++)
4189 {
4190 for(int x = 0; x < width; x++)
4191 {
4192 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4193 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4194
4195 c0 = AVERAGE(c0, c1);
4196
4197 *(unsigned int*)(source0 + 4 * x) = c0;
4198 }
4199
4200 source0 += pitch;
4201 source1 += pitch;
4202 }
4203 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004204 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004205 {
4206 for(int y = 0; y < height; y++)
4207 {
4208 for(int x = 0; x < width; x++)
4209 {
4210 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4211 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4212 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4213 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4214
4215 c0 = AVERAGE(c0, c1);
4216 c2 = AVERAGE(c2, c3);
4217 c0 = AVERAGE(c0, c2);
4218
4219 *(unsigned int*)(source0 + 4 * x) = c0;
4220 }
4221
4222 source0 += pitch;
4223 source1 += pitch;
4224 source2 += pitch;
4225 source3 += pitch;
4226 }
4227 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004228 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004229 {
4230 for(int y = 0; y < height; y++)
4231 {
4232 for(int x = 0; x < width; x++)
4233 {
4234 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4235 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4236 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4237 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4238 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4239 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4240 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4241 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4242
4243 c0 = AVERAGE(c0, c1);
4244 c2 = AVERAGE(c2, c3);
4245 c4 = AVERAGE(c4, c5);
4246 c6 = AVERAGE(c6, c7);
4247 c0 = AVERAGE(c0, c2);
4248 c4 = AVERAGE(c4, c6);
4249 c0 = AVERAGE(c0, c4);
4250
4251 *(unsigned int*)(source0 + 4 * x) = c0;
4252 }
4253
4254 source0 += pitch;
4255 source1 += pitch;
4256 source2 += pitch;
4257 source3 += pitch;
4258 source4 += pitch;
4259 source5 += pitch;
4260 source6 += pitch;
4261 source7 += pitch;
4262 }
4263 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004264 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004265 {
4266 for(int y = 0; y < height; y++)
4267 {
4268 for(int x = 0; x < width; x++)
4269 {
4270 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4271 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4272 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4273 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4274 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4275 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4276 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4277 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4278 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4279 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4280 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4281 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4282 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4283 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4284 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4285 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4286
4287 c0 = AVERAGE(c0, c1);
4288 c2 = AVERAGE(c2, c3);
4289 c4 = AVERAGE(c4, c5);
4290 c6 = AVERAGE(c6, c7);
4291 c8 = AVERAGE(c8, c9);
4292 cA = AVERAGE(cA, cB);
4293 cC = AVERAGE(cC, cD);
4294 cE = AVERAGE(cE, cF);
4295 c0 = AVERAGE(c0, c2);
4296 c4 = AVERAGE(c4, c6);
4297 c8 = AVERAGE(c8, cA);
4298 cC = AVERAGE(cC, cE);
4299 c0 = AVERAGE(c0, c4);
4300 c8 = AVERAGE(c8, cC);
4301 c0 = AVERAGE(c0, c8);
4302
4303 *(unsigned int*)(source0 + 4 * x) = c0;
4304 }
4305
4306 source0 += pitch;
4307 source1 += pitch;
4308 source2 += pitch;
4309 source3 += pitch;
4310 source4 += pitch;
4311 source5 += pitch;
4312 source6 += pitch;
4313 source7 += pitch;
4314 source8 += pitch;
4315 source9 += pitch;
4316 sourceA += pitch;
4317 sourceB += pitch;
4318 sourceC += pitch;
4319 sourceD += pitch;
4320 sourceE += pitch;
4321 sourceF += pitch;
4322 }
4323 }
4324 else ASSERT(false);
4325
4326 #undef AVERAGE
4327 }
4328 }
4329 else if(internal.format == FORMAT_G16R16)
4330 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004331
4332 #if defined(__i386__) || defined(__x86_64__)
4333 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004334 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004335 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004336 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004337 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004338 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004339 for(int x = 0; x < width; x += 4)
4340 {
4341 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4342 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004343
Nicolas Capens47dc8672017-04-25 12:54:39 -04004344 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004345
Nicolas Capens47dc8672017-04-25 12:54:39 -04004346 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4347 }
4348
4349 source0 += pitch;
4350 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004351 }
John Bauman89401822014-05-06 15:04:28 -04004352 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004353 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004354 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004355 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004356 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004357 for(int x = 0; x < width; x += 4)
4358 {
4359 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4360 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4361 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4362 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004363
Nicolas Capens47dc8672017-04-25 12:54:39 -04004364 c0 = _mm_avg_epu16(c0, c1);
4365 c2 = _mm_avg_epu16(c2, c3);
4366 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004367
Nicolas Capens47dc8672017-04-25 12:54:39 -04004368 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4369 }
4370
4371 source0 += pitch;
4372 source1 += pitch;
4373 source2 += pitch;
4374 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004375 }
John Bauman89401822014-05-06 15:04:28 -04004376 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004377 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004378 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004379 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004380 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004381 for(int x = 0; x < width; x += 4)
4382 {
4383 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4384 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4385 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4386 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4387 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4388 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4389 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4390 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004391
Nicolas Capens47dc8672017-04-25 12:54:39 -04004392 c0 = _mm_avg_epu16(c0, c1);
4393 c2 = _mm_avg_epu16(c2, c3);
4394 c4 = _mm_avg_epu16(c4, c5);
4395 c6 = _mm_avg_epu16(c6, c7);
4396 c0 = _mm_avg_epu16(c0, c2);
4397 c4 = _mm_avg_epu16(c4, c6);
4398 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004399
Nicolas Capens47dc8672017-04-25 12:54:39 -04004400 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4401 }
4402
4403 source0 += pitch;
4404 source1 += pitch;
4405 source2 += pitch;
4406 source3 += pitch;
4407 source4 += pitch;
4408 source5 += pitch;
4409 source6 += pitch;
4410 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004411 }
John Bauman89401822014-05-06 15:04:28 -04004412 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004413 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004414 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004415 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004416 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004417 for(int x = 0; x < width; x += 4)
4418 {
4419 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4420 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4421 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4422 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4423 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4424 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4425 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4426 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4427 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4428 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4429 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4430 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4431 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4432 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4433 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4434 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004435
Nicolas Capens47dc8672017-04-25 12:54:39 -04004436 c0 = _mm_avg_epu16(c0, c1);
4437 c2 = _mm_avg_epu16(c2, c3);
4438 c4 = _mm_avg_epu16(c4, c5);
4439 c6 = _mm_avg_epu16(c6, c7);
4440 c8 = _mm_avg_epu16(c8, c9);
4441 cA = _mm_avg_epu16(cA, cB);
4442 cC = _mm_avg_epu16(cC, cD);
4443 cE = _mm_avg_epu16(cE, cF);
4444 c0 = _mm_avg_epu16(c0, c2);
4445 c4 = _mm_avg_epu16(c4, c6);
4446 c8 = _mm_avg_epu16(c8, cA);
4447 cC = _mm_avg_epu16(cC, cE);
4448 c0 = _mm_avg_epu16(c0, c4);
4449 c8 = _mm_avg_epu16(c8, cC);
4450 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004451
Nicolas Capens47dc8672017-04-25 12:54:39 -04004452 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4453 }
4454
4455 source0 += pitch;
4456 source1 += pitch;
4457 source2 += pitch;
4458 source3 += pitch;
4459 source4 += pitch;
4460 source5 += pitch;
4461 source6 += pitch;
4462 source7 += pitch;
4463 source8 += pitch;
4464 source9 += pitch;
4465 sourceA += pitch;
4466 sourceB += pitch;
4467 sourceC += pitch;
4468 sourceD += pitch;
4469 sourceE += pitch;
4470 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004471 }
John Bauman89401822014-05-06 15:04:28 -04004472 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004473 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004474 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004475 else
4476 #endif
John Bauman89401822014-05-06 15:04:28 -04004477 {
4478 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4479
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004480 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004481 {
4482 for(int y = 0; y < height; y++)
4483 {
4484 for(int x = 0; x < width; x++)
4485 {
4486 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4487 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4488
4489 c0 = AVERAGE(c0, c1);
4490
4491 *(unsigned int*)(source0 + 4 * x) = c0;
4492 }
4493
4494 source0 += pitch;
4495 source1 += pitch;
4496 }
4497 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004498 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004499 {
4500 for(int y = 0; y < height; y++)
4501 {
4502 for(int x = 0; x < width; x++)
4503 {
4504 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4505 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4506 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4507 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4508
4509 c0 = AVERAGE(c0, c1);
4510 c2 = AVERAGE(c2, c3);
4511 c0 = AVERAGE(c0, c2);
4512
4513 *(unsigned int*)(source0 + 4 * x) = c0;
4514 }
4515
4516 source0 += pitch;
4517 source1 += pitch;
4518 source2 += pitch;
4519 source3 += pitch;
4520 }
4521 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004522 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004523 {
4524 for(int y = 0; y < height; y++)
4525 {
4526 for(int x = 0; x < width; x++)
4527 {
4528 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4529 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4530 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4531 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4532 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4533 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4534 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4535 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4536
4537 c0 = AVERAGE(c0, c1);
4538 c2 = AVERAGE(c2, c3);
4539 c4 = AVERAGE(c4, c5);
4540 c6 = AVERAGE(c6, c7);
4541 c0 = AVERAGE(c0, c2);
4542 c4 = AVERAGE(c4, c6);
4543 c0 = AVERAGE(c0, c4);
4544
4545 *(unsigned int*)(source0 + 4 * x) = c0;
4546 }
4547
4548 source0 += pitch;
4549 source1 += pitch;
4550 source2 += pitch;
4551 source3 += pitch;
4552 source4 += pitch;
4553 source5 += pitch;
4554 source6 += pitch;
4555 source7 += pitch;
4556 }
4557 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004558 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004559 {
4560 for(int y = 0; y < height; y++)
4561 {
4562 for(int x = 0; x < width; x++)
4563 {
4564 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4565 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4566 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4567 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4568 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4569 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4570 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4571 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4572 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4573 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4574 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4575 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4576 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4577 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4578 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4579 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4580
4581 c0 = AVERAGE(c0, c1);
4582 c2 = AVERAGE(c2, c3);
4583 c4 = AVERAGE(c4, c5);
4584 c6 = AVERAGE(c6, c7);
4585 c8 = AVERAGE(c8, c9);
4586 cA = AVERAGE(cA, cB);
4587 cC = AVERAGE(cC, cD);
4588 cE = AVERAGE(cE, cF);
4589 c0 = AVERAGE(c0, c2);
4590 c4 = AVERAGE(c4, c6);
4591 c8 = AVERAGE(c8, cA);
4592 cC = AVERAGE(cC, cE);
4593 c0 = AVERAGE(c0, c4);
4594 c8 = AVERAGE(c8, cC);
4595 c0 = AVERAGE(c0, c8);
4596
4597 *(unsigned int*)(source0 + 4 * x) = c0;
4598 }
4599
4600 source0 += pitch;
4601 source1 += pitch;
4602 source2 += pitch;
4603 source3 += pitch;
4604 source4 += pitch;
4605 source5 += pitch;
4606 source6 += pitch;
4607 source7 += pitch;
4608 source8 += pitch;
4609 source9 += pitch;
4610 sourceA += pitch;
4611 sourceB += pitch;
4612 sourceC += pitch;
4613 sourceD += pitch;
4614 sourceE += pitch;
4615 sourceF += pitch;
4616 }
4617 }
4618 else ASSERT(false);
4619
4620 #undef AVERAGE
4621 }
4622 }
4623 else if(internal.format == FORMAT_A16B16G16R16)
4624 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004625 #if defined(__i386__) || defined(__x86_64__)
4626 if(CPUID::supportsSSE2() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04004627 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004628 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004629 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004630 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004631 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004632 for(int x = 0; x < width; x += 2)
4633 {
4634 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4635 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004636
Nicolas Capens47dc8672017-04-25 12:54:39 -04004637 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004638
Nicolas Capens47dc8672017-04-25 12:54:39 -04004639 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4640 }
4641
4642 source0 += pitch;
4643 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004644 }
John Bauman89401822014-05-06 15:04:28 -04004645 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004646 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004647 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004648 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004649 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004650 for(int x = 0; x < width; x += 2)
4651 {
4652 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4653 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4654 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4655 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004656
Nicolas Capens47dc8672017-04-25 12:54:39 -04004657 c0 = _mm_avg_epu16(c0, c1);
4658 c2 = _mm_avg_epu16(c2, c3);
4659 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004660
Nicolas Capens47dc8672017-04-25 12:54:39 -04004661 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4662 }
4663
4664 source0 += pitch;
4665 source1 += pitch;
4666 source2 += pitch;
4667 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004668 }
John Bauman89401822014-05-06 15:04:28 -04004669 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004670 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004671 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004672 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004673 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004674 for(int x = 0; x < width; x += 2)
4675 {
4676 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4677 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4678 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4679 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4680 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4681 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4682 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4683 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004684
Nicolas Capens47dc8672017-04-25 12:54:39 -04004685 c0 = _mm_avg_epu16(c0, c1);
4686 c2 = _mm_avg_epu16(c2, c3);
4687 c4 = _mm_avg_epu16(c4, c5);
4688 c6 = _mm_avg_epu16(c6, c7);
4689 c0 = _mm_avg_epu16(c0, c2);
4690 c4 = _mm_avg_epu16(c4, c6);
4691 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004692
Nicolas Capens47dc8672017-04-25 12:54:39 -04004693 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4694 }
4695
4696 source0 += pitch;
4697 source1 += pitch;
4698 source2 += pitch;
4699 source3 += pitch;
4700 source4 += pitch;
4701 source5 += pitch;
4702 source6 += pitch;
4703 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004704 }
John Bauman89401822014-05-06 15:04:28 -04004705 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004706 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004707 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004708 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004709 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004710 for(int x = 0; x < width; x += 2)
4711 {
4712 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4713 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4714 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4715 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4716 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4717 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4718 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4719 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
4720 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 8 * x));
4721 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 8 * x));
4722 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 8 * x));
4723 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 8 * x));
4724 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 8 * x));
4725 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 8 * x));
4726 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 8 * x));
4727 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04004728
Nicolas Capens47dc8672017-04-25 12:54:39 -04004729 c0 = _mm_avg_epu16(c0, c1);
4730 c2 = _mm_avg_epu16(c2, c3);
4731 c4 = _mm_avg_epu16(c4, c5);
4732 c6 = _mm_avg_epu16(c6, c7);
4733 c8 = _mm_avg_epu16(c8, c9);
4734 cA = _mm_avg_epu16(cA, cB);
4735 cC = _mm_avg_epu16(cC, cD);
4736 cE = _mm_avg_epu16(cE, cF);
4737 c0 = _mm_avg_epu16(c0, c2);
4738 c4 = _mm_avg_epu16(c4, c6);
4739 c8 = _mm_avg_epu16(c8, cA);
4740 cC = _mm_avg_epu16(cC, cE);
4741 c0 = _mm_avg_epu16(c0, c4);
4742 c8 = _mm_avg_epu16(c8, cC);
4743 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004744
Nicolas Capens47dc8672017-04-25 12:54:39 -04004745 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4746 }
4747
4748 source0 += pitch;
4749 source1 += pitch;
4750 source2 += pitch;
4751 source3 += pitch;
4752 source4 += pitch;
4753 source5 += pitch;
4754 source6 += pitch;
4755 source7 += pitch;
4756 source8 += pitch;
4757 source9 += pitch;
4758 sourceA += pitch;
4759 sourceB += pitch;
4760 sourceC += pitch;
4761 sourceD += pitch;
4762 sourceE += pitch;
4763 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004764 }
John Bauman89401822014-05-06 15:04:28 -04004765 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004766 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004767 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004768 else
4769 #endif
John Bauman89401822014-05-06 15:04:28 -04004770 {
4771 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4772
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004773 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004774 {
4775 for(int y = 0; y < height; y++)
4776 {
4777 for(int x = 0; x < 2 * width; x++)
4778 {
4779 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4780 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4781
4782 c0 = AVERAGE(c0, c1);
4783
4784 *(unsigned int*)(source0 + 4 * x) = c0;
4785 }
4786
4787 source0 += pitch;
4788 source1 += pitch;
4789 }
4790 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004791 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004792 {
4793 for(int y = 0; y < height; y++)
4794 {
4795 for(int x = 0; x < 2 * width; x++)
4796 {
4797 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4798 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4799 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4800 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4801
4802 c0 = AVERAGE(c0, c1);
4803 c2 = AVERAGE(c2, c3);
4804 c0 = AVERAGE(c0, c2);
4805
4806 *(unsigned int*)(source0 + 4 * x) = c0;
4807 }
4808
4809 source0 += pitch;
4810 source1 += pitch;
4811 source2 += pitch;
4812 source3 += pitch;
4813 }
4814 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004815 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004816 {
4817 for(int y = 0; y < height; y++)
4818 {
4819 for(int x = 0; x < 2 * width; x++)
4820 {
4821 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4822 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4823 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4824 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4825 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4826 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4827 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4828 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4829
4830 c0 = AVERAGE(c0, c1);
4831 c2 = AVERAGE(c2, c3);
4832 c4 = AVERAGE(c4, c5);
4833 c6 = AVERAGE(c6, c7);
4834 c0 = AVERAGE(c0, c2);
4835 c4 = AVERAGE(c4, c6);
4836 c0 = AVERAGE(c0, c4);
4837
4838 *(unsigned int*)(source0 + 4 * x) = c0;
4839 }
4840
4841 source0 += pitch;
4842 source1 += pitch;
4843 source2 += pitch;
4844 source3 += pitch;
4845 source4 += pitch;
4846 source5 += pitch;
4847 source6 += pitch;
4848 source7 += pitch;
4849 }
4850 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004851 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004852 {
4853 for(int y = 0; y < height; y++)
4854 {
4855 for(int x = 0; x < 2 * width; x++)
4856 {
4857 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4858 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4859 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4860 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4861 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4862 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4863 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4864 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4865 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4866 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4867 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4868 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4869 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4870 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4871 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4872 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4873
4874 c0 = AVERAGE(c0, c1);
4875 c2 = AVERAGE(c2, c3);
4876 c4 = AVERAGE(c4, c5);
4877 c6 = AVERAGE(c6, c7);
4878 c8 = AVERAGE(c8, c9);
4879 cA = AVERAGE(cA, cB);
4880 cC = AVERAGE(cC, cD);
4881 cE = AVERAGE(cE, cF);
4882 c0 = AVERAGE(c0, c2);
4883 c4 = AVERAGE(c4, c6);
4884 c8 = AVERAGE(c8, cA);
4885 cC = AVERAGE(cC, cE);
4886 c0 = AVERAGE(c0, c4);
4887 c8 = AVERAGE(c8, cC);
4888 c0 = AVERAGE(c0, c8);
4889
4890 *(unsigned int*)(source0 + 4 * x) = c0;
4891 }
4892
4893 source0 += pitch;
4894 source1 += pitch;
4895 source2 += pitch;
4896 source3 += pitch;
4897 source4 += pitch;
4898 source5 += pitch;
4899 source6 += pitch;
4900 source7 += pitch;
4901 source8 += pitch;
4902 source9 += pitch;
4903 sourceA += pitch;
4904 sourceB += pitch;
4905 sourceC += pitch;
4906 sourceD += pitch;
4907 sourceE += pitch;
4908 sourceF += pitch;
4909 }
4910 }
4911 else ASSERT(false);
4912
4913 #undef AVERAGE
4914 }
4915 }
4916 else if(internal.format == FORMAT_R32F)
4917 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004918 #if defined(__i386__) || defined(__x86_64__)
4919 if(CPUID::supportsSSE() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004920 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004921 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004922 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004923 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004924 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004925 for(int x = 0; x < width; x += 4)
4926 {
4927 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4928 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004929
Nicolas Capens47dc8672017-04-25 12:54:39 -04004930 c0 = _mm_add_ps(c0, c1);
4931 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04004932
Nicolas Capens47dc8672017-04-25 12:54:39 -04004933 _mm_store_ps((float*)(source0 + 4 * x), c0);
4934 }
4935
4936 source0 += pitch;
4937 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004938 }
John Bauman89401822014-05-06 15:04:28 -04004939 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004940 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004941 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004942 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004943 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004944 for(int x = 0; x < width; x += 4)
4945 {
4946 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4947 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4948 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4949 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004950
Nicolas Capens47dc8672017-04-25 12:54:39 -04004951 c0 = _mm_add_ps(c0, c1);
4952 c2 = _mm_add_ps(c2, c3);
4953 c0 = _mm_add_ps(c0, c2);
4954 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04004955
Nicolas Capens47dc8672017-04-25 12:54:39 -04004956 _mm_store_ps((float*)(source0 + 4 * x), c0);
4957 }
4958
4959 source0 += pitch;
4960 source1 += pitch;
4961 source2 += pitch;
4962 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004963 }
John Bauman89401822014-05-06 15:04:28 -04004964 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004965 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004966 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004967 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004968 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004969 for(int x = 0; x < width; x += 4)
4970 {
4971 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4972 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4973 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4974 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
4975 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
4976 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
4977 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
4978 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004979
Nicolas Capens47dc8672017-04-25 12:54:39 -04004980 c0 = _mm_add_ps(c0, c1);
4981 c2 = _mm_add_ps(c2, c3);
4982 c4 = _mm_add_ps(c4, c5);
4983 c6 = _mm_add_ps(c6, c7);
4984 c0 = _mm_add_ps(c0, c2);
4985 c4 = _mm_add_ps(c4, c6);
4986 c0 = _mm_add_ps(c0, c4);
4987 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04004988
Nicolas Capens47dc8672017-04-25 12:54:39 -04004989 _mm_store_ps((float*)(source0 + 4 * x), c0);
4990 }
4991
4992 source0 += pitch;
4993 source1 += pitch;
4994 source2 += pitch;
4995 source3 += pitch;
4996 source4 += pitch;
4997 source5 += pitch;
4998 source6 += pitch;
4999 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005000 }
John Bauman89401822014-05-06 15:04:28 -04005001 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005002 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005003 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005004 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005005 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005006 for(int x = 0; x < width; x += 4)
5007 {
5008 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
5009 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
5010 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
5011 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
5012 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
5013 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
5014 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
5015 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
5016 __m128 c8 = _mm_load_ps((float*)(source8 + 4 * x));
5017 __m128 c9 = _mm_load_ps((float*)(source9 + 4 * x));
5018 __m128 cA = _mm_load_ps((float*)(sourceA + 4 * x));
5019 __m128 cB = _mm_load_ps((float*)(sourceB + 4 * x));
5020 __m128 cC = _mm_load_ps((float*)(sourceC + 4 * x));
5021 __m128 cD = _mm_load_ps((float*)(sourceD + 4 * x));
5022 __m128 cE = _mm_load_ps((float*)(sourceE + 4 * x));
5023 __m128 cF = _mm_load_ps((float*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04005024
Nicolas Capens47dc8672017-04-25 12:54:39 -04005025 c0 = _mm_add_ps(c0, c1);
5026 c2 = _mm_add_ps(c2, c3);
5027 c4 = _mm_add_ps(c4, c5);
5028 c6 = _mm_add_ps(c6, c7);
5029 c8 = _mm_add_ps(c8, c9);
5030 cA = _mm_add_ps(cA, cB);
5031 cC = _mm_add_ps(cC, cD);
5032 cE = _mm_add_ps(cE, cF);
5033 c0 = _mm_add_ps(c0, c2);
5034 c4 = _mm_add_ps(c4, c6);
5035 c8 = _mm_add_ps(c8, cA);
5036 cC = _mm_add_ps(cC, cE);
5037 c0 = _mm_add_ps(c0, c4);
5038 c8 = _mm_add_ps(c8, cC);
5039 c0 = _mm_add_ps(c0, c8);
5040 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005041
Nicolas Capens47dc8672017-04-25 12:54:39 -04005042 _mm_store_ps((float*)(source0 + 4 * x), c0);
5043 }
5044
5045 source0 += pitch;
5046 source1 += pitch;
5047 source2 += pitch;
5048 source3 += pitch;
5049 source4 += pitch;
5050 source5 += pitch;
5051 source6 += pitch;
5052 source7 += pitch;
5053 source8 += pitch;
5054 source9 += pitch;
5055 sourceA += pitch;
5056 sourceB += pitch;
5057 sourceC += pitch;
5058 sourceD += pitch;
5059 sourceE += pitch;
5060 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005061 }
John Bauman89401822014-05-06 15:04:28 -04005062 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005063 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005064 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005065 else
5066 #endif
John Bauman89401822014-05-06 15:04:28 -04005067 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005068 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005069 {
5070 for(int y = 0; y < height; y++)
5071 {
5072 for(int x = 0; x < width; x++)
5073 {
5074 float c0 = *(float*)(source0 + 4 * x);
5075 float c1 = *(float*)(source1 + 4 * x);
5076
5077 c0 = c0 + c1;
5078 c0 *= 1.0f / 2.0f;
5079
5080 *(float*)(source0 + 4 * x) = c0;
5081 }
5082
5083 source0 += pitch;
5084 source1 += pitch;
5085 }
5086 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005087 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005088 {
5089 for(int y = 0; y < height; y++)
5090 {
5091 for(int x = 0; x < width; x++)
5092 {
5093 float c0 = *(float*)(source0 + 4 * x);
5094 float c1 = *(float*)(source1 + 4 * x);
5095 float c2 = *(float*)(source2 + 4 * x);
5096 float c3 = *(float*)(source3 + 4 * x);
5097
5098 c0 = c0 + c1;
5099 c2 = c2 + c3;
5100 c0 = c0 + c2;
5101 c0 *= 1.0f / 4.0f;
5102
5103 *(float*)(source0 + 4 * x) = c0;
5104 }
5105
5106 source0 += pitch;
5107 source1 += pitch;
5108 source2 += pitch;
5109 source3 += pitch;
5110 }
5111 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005112 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005113 {
5114 for(int y = 0; y < height; y++)
5115 {
5116 for(int x = 0; x < width; x++)
5117 {
5118 float c0 = *(float*)(source0 + 4 * x);
5119 float c1 = *(float*)(source1 + 4 * x);
5120 float c2 = *(float*)(source2 + 4 * x);
5121 float c3 = *(float*)(source3 + 4 * x);
5122 float c4 = *(float*)(source4 + 4 * x);
5123 float c5 = *(float*)(source5 + 4 * x);
5124 float c6 = *(float*)(source6 + 4 * x);
5125 float c7 = *(float*)(source7 + 4 * x);
5126
5127 c0 = c0 + c1;
5128 c2 = c2 + c3;
5129 c4 = c4 + c5;
5130 c6 = c6 + c7;
5131 c0 = c0 + c2;
5132 c4 = c4 + c6;
5133 c0 = c0 + c4;
5134 c0 *= 1.0f / 8.0f;
5135
5136 *(float*)(source0 + 4 * x) = c0;
5137 }
5138
5139 source0 += pitch;
5140 source1 += pitch;
5141 source2 += pitch;
5142 source3 += pitch;
5143 source4 += pitch;
5144 source5 += pitch;
5145 source6 += pitch;
5146 source7 += pitch;
5147 }
5148 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005149 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005150 {
5151 for(int y = 0; y < height; y++)
5152 {
5153 for(int x = 0; x < width; x++)
5154 {
5155 float c0 = *(float*)(source0 + 4 * x);
5156 float c1 = *(float*)(source1 + 4 * x);
5157 float c2 = *(float*)(source2 + 4 * x);
5158 float c3 = *(float*)(source3 + 4 * x);
5159 float c4 = *(float*)(source4 + 4 * x);
5160 float c5 = *(float*)(source5 + 4 * x);
5161 float c6 = *(float*)(source6 + 4 * x);
5162 float c7 = *(float*)(source7 + 4 * x);
5163 float c8 = *(float*)(source8 + 4 * x);
5164 float c9 = *(float*)(source9 + 4 * x);
5165 float cA = *(float*)(sourceA + 4 * x);
5166 float cB = *(float*)(sourceB + 4 * x);
5167 float cC = *(float*)(sourceC + 4 * x);
5168 float cD = *(float*)(sourceD + 4 * x);
5169 float cE = *(float*)(sourceE + 4 * x);
5170 float cF = *(float*)(sourceF + 4 * x);
5171
5172 c0 = c0 + c1;
5173 c2 = c2 + c3;
5174 c4 = c4 + c5;
5175 c6 = c6 + c7;
5176 c8 = c8 + c9;
5177 cA = cA + cB;
5178 cC = cC + cD;
5179 cE = cE + cF;
5180 c0 = c0 + c2;
5181 c4 = c4 + c6;
5182 c8 = c8 + cA;
5183 cC = cC + cE;
5184 c0 = c0 + c4;
5185 c8 = c8 + cC;
5186 c0 = c0 + c8;
5187 c0 *= 1.0f / 16.0f;
5188
5189 *(float*)(source0 + 4 * x) = c0;
5190 }
5191
5192 source0 += pitch;
5193 source1 += pitch;
5194 source2 += pitch;
5195 source3 += pitch;
5196 source4 += pitch;
5197 source5 += pitch;
5198 source6 += pitch;
5199 source7 += pitch;
5200 source8 += pitch;
5201 source9 += pitch;
5202 sourceA += pitch;
5203 sourceB += pitch;
5204 sourceC += pitch;
5205 sourceD += pitch;
5206 sourceE += pitch;
5207 sourceF += pitch;
5208 }
5209 }
5210 else ASSERT(false);
5211 }
5212 }
5213 else if(internal.format == FORMAT_G32R32F)
5214 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005215 #if defined(__i386__) || defined(__x86_64__)
5216 if(CPUID::supportsSSE() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04005217 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005218 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005219 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005220 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005221 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005222 for(int x = 0; x < width; x += 2)
5223 {
5224 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5225 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005226
Nicolas Capens47dc8672017-04-25 12:54:39 -04005227 c0 = _mm_add_ps(c0, c1);
5228 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005229
Nicolas Capens47dc8672017-04-25 12:54:39 -04005230 _mm_store_ps((float*)(source0 + 8 * x), c0);
5231 }
5232
5233 source0 += pitch;
5234 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005235 }
John Bauman89401822014-05-06 15:04:28 -04005236 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005237 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005238 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005239 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005240 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005241 for(int x = 0; x < width; x += 2)
5242 {
5243 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5244 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5245 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5246 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005247
Nicolas Capens47dc8672017-04-25 12:54:39 -04005248 c0 = _mm_add_ps(c0, c1);
5249 c2 = _mm_add_ps(c2, c3);
5250 c0 = _mm_add_ps(c0, c2);
5251 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005252
Nicolas Capens47dc8672017-04-25 12:54:39 -04005253 _mm_store_ps((float*)(source0 + 8 * x), c0);
5254 }
5255
5256 source0 += pitch;
5257 source1 += pitch;
5258 source2 += pitch;
5259 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005260 }
John Bauman89401822014-05-06 15:04:28 -04005261 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005262 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005263 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005264 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005265 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005266 for(int x = 0; x < width; x += 2)
5267 {
5268 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5269 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5270 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5271 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5272 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5273 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5274 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5275 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005276
Nicolas Capens47dc8672017-04-25 12:54:39 -04005277 c0 = _mm_add_ps(c0, c1);
5278 c2 = _mm_add_ps(c2, c3);
5279 c4 = _mm_add_ps(c4, c5);
5280 c6 = _mm_add_ps(c6, c7);
5281 c0 = _mm_add_ps(c0, c2);
5282 c4 = _mm_add_ps(c4, c6);
5283 c0 = _mm_add_ps(c0, c4);
5284 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005285
Nicolas Capens47dc8672017-04-25 12:54:39 -04005286 _mm_store_ps((float*)(source0 + 8 * x), c0);
5287 }
5288
5289 source0 += pitch;
5290 source1 += pitch;
5291 source2 += pitch;
5292 source3 += pitch;
5293 source4 += pitch;
5294 source5 += pitch;
5295 source6 += pitch;
5296 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005297 }
John Bauman89401822014-05-06 15:04:28 -04005298 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005299 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005300 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005301 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005302 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005303 for(int x = 0; x < width; x += 2)
5304 {
5305 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5306 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5307 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5308 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5309 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5310 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5311 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5312 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
5313 __m128 c8 = _mm_load_ps((float*)(source8 + 8 * x));
5314 __m128 c9 = _mm_load_ps((float*)(source9 + 8 * x));
5315 __m128 cA = _mm_load_ps((float*)(sourceA + 8 * x));
5316 __m128 cB = _mm_load_ps((float*)(sourceB + 8 * x));
5317 __m128 cC = _mm_load_ps((float*)(sourceC + 8 * x));
5318 __m128 cD = _mm_load_ps((float*)(sourceD + 8 * x));
5319 __m128 cE = _mm_load_ps((float*)(sourceE + 8 * x));
5320 __m128 cF = _mm_load_ps((float*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04005321
Nicolas Capens47dc8672017-04-25 12:54:39 -04005322 c0 = _mm_add_ps(c0, c1);
5323 c2 = _mm_add_ps(c2, c3);
5324 c4 = _mm_add_ps(c4, c5);
5325 c6 = _mm_add_ps(c6, c7);
5326 c8 = _mm_add_ps(c8, c9);
5327 cA = _mm_add_ps(cA, cB);
5328 cC = _mm_add_ps(cC, cD);
5329 cE = _mm_add_ps(cE, cF);
5330 c0 = _mm_add_ps(c0, c2);
5331 c4 = _mm_add_ps(c4, c6);
5332 c8 = _mm_add_ps(c8, cA);
5333 cC = _mm_add_ps(cC, cE);
5334 c0 = _mm_add_ps(c0, c4);
5335 c8 = _mm_add_ps(c8, cC);
5336 c0 = _mm_add_ps(c0, c8);
5337 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005338
Nicolas Capens47dc8672017-04-25 12:54:39 -04005339 _mm_store_ps((float*)(source0 + 8 * x), c0);
5340 }
5341
5342 source0 += pitch;
5343 source1 += pitch;
5344 source2 += pitch;
5345 source3 += pitch;
5346 source4 += pitch;
5347 source5 += pitch;
5348 source6 += pitch;
5349 source7 += pitch;
5350 source8 += pitch;
5351 source9 += pitch;
5352 sourceA += pitch;
5353 sourceB += pitch;
5354 sourceC += pitch;
5355 sourceD += pitch;
5356 sourceE += pitch;
5357 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005358 }
John Bauman89401822014-05-06 15:04:28 -04005359 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005360 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005361 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005362 else
5363 #endif
John Bauman89401822014-05-06 15:04:28 -04005364 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005365 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005366 {
5367 for(int y = 0; y < height; y++)
5368 {
5369 for(int x = 0; x < 2 * width; x++)
5370 {
5371 float c0 = *(float*)(source0 + 4 * x);
5372 float c1 = *(float*)(source1 + 4 * x);
5373
5374 c0 = c0 + c1;
5375 c0 *= 1.0f / 2.0f;
5376
5377 *(float*)(source0 + 4 * x) = c0;
5378 }
5379
5380 source0 += pitch;
5381 source1 += pitch;
5382 }
5383 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005384 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005385 {
5386 for(int y = 0; y < height; y++)
5387 {
5388 for(int x = 0; x < 2 * width; x++)
5389 {
5390 float c0 = *(float*)(source0 + 4 * x);
5391 float c1 = *(float*)(source1 + 4 * x);
5392 float c2 = *(float*)(source2 + 4 * x);
5393 float c3 = *(float*)(source3 + 4 * x);
5394
5395 c0 = c0 + c1;
5396 c2 = c2 + c3;
5397 c0 = c0 + c2;
5398 c0 *= 1.0f / 4.0f;
5399
5400 *(float*)(source0 + 4 * x) = c0;
5401 }
5402
5403 source0 += pitch;
5404 source1 += pitch;
5405 source2 += pitch;
5406 source3 += pitch;
5407 }
5408 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005409 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005410 {
5411 for(int y = 0; y < height; y++)
5412 {
5413 for(int x = 0; x < 2 * width; x++)
5414 {
5415 float c0 = *(float*)(source0 + 4 * x);
5416 float c1 = *(float*)(source1 + 4 * x);
5417 float c2 = *(float*)(source2 + 4 * x);
5418 float c3 = *(float*)(source3 + 4 * x);
5419 float c4 = *(float*)(source4 + 4 * x);
5420 float c5 = *(float*)(source5 + 4 * x);
5421 float c6 = *(float*)(source6 + 4 * x);
5422 float c7 = *(float*)(source7 + 4 * x);
5423
5424 c0 = c0 + c1;
5425 c2 = c2 + c3;
5426 c4 = c4 + c5;
5427 c6 = c6 + c7;
5428 c0 = c0 + c2;
5429 c4 = c4 + c6;
5430 c0 = c0 + c4;
5431 c0 *= 1.0f / 8.0f;
5432
5433 *(float*)(source0 + 4 * x) = c0;
5434 }
5435
5436 source0 += pitch;
5437 source1 += pitch;
5438 source2 += pitch;
5439 source3 += pitch;
5440 source4 += pitch;
5441 source5 += pitch;
5442 source6 += pitch;
5443 source7 += pitch;
5444 }
5445 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005446 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005447 {
5448 for(int y = 0; y < height; y++)
5449 {
5450 for(int x = 0; x < 2 * width; x++)
5451 {
5452 float c0 = *(float*)(source0 + 4 * x);
5453 float c1 = *(float*)(source1 + 4 * x);
5454 float c2 = *(float*)(source2 + 4 * x);
5455 float c3 = *(float*)(source3 + 4 * x);
5456 float c4 = *(float*)(source4 + 4 * x);
5457 float c5 = *(float*)(source5 + 4 * x);
5458 float c6 = *(float*)(source6 + 4 * x);
5459 float c7 = *(float*)(source7 + 4 * x);
5460 float c8 = *(float*)(source8 + 4 * x);
5461 float c9 = *(float*)(source9 + 4 * x);
5462 float cA = *(float*)(sourceA + 4 * x);
5463 float cB = *(float*)(sourceB + 4 * x);
5464 float cC = *(float*)(sourceC + 4 * x);
5465 float cD = *(float*)(sourceD + 4 * x);
5466 float cE = *(float*)(sourceE + 4 * x);
5467 float cF = *(float*)(sourceF + 4 * x);
5468
5469 c0 = c0 + c1;
5470 c2 = c2 + c3;
5471 c4 = c4 + c5;
5472 c6 = c6 + c7;
5473 c8 = c8 + c9;
5474 cA = cA + cB;
5475 cC = cC + cD;
5476 cE = cE + cF;
5477 c0 = c0 + c2;
5478 c4 = c4 + c6;
5479 c8 = c8 + cA;
5480 cC = cC + cE;
5481 c0 = c0 + c4;
5482 c8 = c8 + cC;
5483 c0 = c0 + c8;
5484 c0 *= 1.0f / 16.0f;
5485
5486 *(float*)(source0 + 4 * x) = c0;
5487 }
5488
5489 source0 += pitch;
5490 source1 += pitch;
5491 source2 += pitch;
5492 source3 += pitch;
5493 source4 += pitch;
5494 source5 += pitch;
5495 source6 += pitch;
5496 source7 += pitch;
5497 source8 += pitch;
5498 source9 += pitch;
5499 sourceA += pitch;
5500 sourceB += pitch;
5501 sourceC += pitch;
5502 sourceD += pitch;
5503 sourceE += pitch;
5504 sourceF += pitch;
5505 }
5506 }
5507 else ASSERT(false);
5508 }
5509 }
Nicolas Capens67fdd832017-12-21 11:20:54 -05005510 else if(internal.format == FORMAT_A32B32G32R32F ||
5511 internal.format == FORMAT_X32B32G32R32F ||
5512 internal.format == FORMAT_X32B32G32R32F_UNSIGNED)
John Bauman89401822014-05-06 15:04:28 -04005513 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005514 #if defined(__i386__) || defined(__x86_64__)
5515 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04005516 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005517 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005518 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005519 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005520 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005521 for(int x = 0; x < width; x++)
5522 {
5523 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5524 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005525
Nicolas Capens47dc8672017-04-25 12:54:39 -04005526 c0 = _mm_add_ps(c0, c1);
5527 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005528
Nicolas Capens47dc8672017-04-25 12:54:39 -04005529 _mm_store_ps((float*)(source0 + 16 * x), c0);
5530 }
5531
5532 source0 += pitch;
5533 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005534 }
John Bauman89401822014-05-06 15:04:28 -04005535 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005536 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005537 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005538 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005539 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005540 for(int x = 0; x < width; x++)
5541 {
5542 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5543 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5544 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5545 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005546
Nicolas Capens47dc8672017-04-25 12:54:39 -04005547 c0 = _mm_add_ps(c0, c1);
5548 c2 = _mm_add_ps(c2, c3);
5549 c0 = _mm_add_ps(c0, c2);
5550 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005551
Nicolas Capens47dc8672017-04-25 12:54:39 -04005552 _mm_store_ps((float*)(source0 + 16 * x), c0);
5553 }
5554
5555 source0 += pitch;
5556 source1 += pitch;
5557 source2 += pitch;
5558 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005559 }
John Bauman89401822014-05-06 15:04:28 -04005560 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005561 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005562 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005563 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005564 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005565 for(int x = 0; x < width; x++)
5566 {
5567 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5568 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5569 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5570 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5571 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5572 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5573 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5574 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005575
Nicolas Capens47dc8672017-04-25 12:54:39 -04005576 c0 = _mm_add_ps(c0, c1);
5577 c2 = _mm_add_ps(c2, c3);
5578 c4 = _mm_add_ps(c4, c5);
5579 c6 = _mm_add_ps(c6, c7);
5580 c0 = _mm_add_ps(c0, c2);
5581 c4 = _mm_add_ps(c4, c6);
5582 c0 = _mm_add_ps(c0, c4);
5583 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005584
Nicolas Capens47dc8672017-04-25 12:54:39 -04005585 _mm_store_ps((float*)(source0 + 16 * x), c0);
5586 }
5587
5588 source0 += pitch;
5589 source1 += pitch;
5590 source2 += pitch;
5591 source3 += pitch;
5592 source4 += pitch;
5593 source5 += pitch;
5594 source6 += pitch;
5595 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005596 }
John Bauman89401822014-05-06 15:04:28 -04005597 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005598 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005599 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005600 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005601 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005602 for(int x = 0; x < width; x++)
5603 {
5604 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5605 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5606 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5607 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5608 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5609 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5610 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5611 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
5612 __m128 c8 = _mm_load_ps((float*)(source8 + 16 * x));
5613 __m128 c9 = _mm_load_ps((float*)(source9 + 16 * x));
5614 __m128 cA = _mm_load_ps((float*)(sourceA + 16 * x));
5615 __m128 cB = _mm_load_ps((float*)(sourceB + 16 * x));
5616 __m128 cC = _mm_load_ps((float*)(sourceC + 16 * x));
5617 __m128 cD = _mm_load_ps((float*)(sourceD + 16 * x));
5618 __m128 cE = _mm_load_ps((float*)(sourceE + 16 * x));
5619 __m128 cF = _mm_load_ps((float*)(sourceF + 16 * x));
John Bauman89401822014-05-06 15:04:28 -04005620
Nicolas Capens47dc8672017-04-25 12:54:39 -04005621 c0 = _mm_add_ps(c0, c1);
5622 c2 = _mm_add_ps(c2, c3);
5623 c4 = _mm_add_ps(c4, c5);
5624 c6 = _mm_add_ps(c6, c7);
5625 c8 = _mm_add_ps(c8, c9);
5626 cA = _mm_add_ps(cA, cB);
5627 cC = _mm_add_ps(cC, cD);
5628 cE = _mm_add_ps(cE, cF);
5629 c0 = _mm_add_ps(c0, c2);
5630 c4 = _mm_add_ps(c4, c6);
5631 c8 = _mm_add_ps(c8, cA);
5632 cC = _mm_add_ps(cC, cE);
5633 c0 = _mm_add_ps(c0, c4);
5634 c8 = _mm_add_ps(c8, cC);
5635 c0 = _mm_add_ps(c0, c8);
5636 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005637
Nicolas Capens47dc8672017-04-25 12:54:39 -04005638 _mm_store_ps((float*)(source0 + 16 * x), c0);
5639 }
5640
5641 source0 += pitch;
5642 source1 += pitch;
5643 source2 += pitch;
5644 source3 += pitch;
5645 source4 += pitch;
5646 source5 += pitch;
5647 source6 += pitch;
5648 source7 += pitch;
5649 source8 += pitch;
5650 source9 += pitch;
5651 sourceA += pitch;
5652 sourceB += pitch;
5653 sourceC += pitch;
5654 sourceD += pitch;
5655 sourceE += pitch;
5656 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005657 }
John Bauman89401822014-05-06 15:04:28 -04005658 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005659 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005660 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005661 else
5662 #endif
John Bauman89401822014-05-06 15:04:28 -04005663 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005664 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005665 {
5666 for(int y = 0; y < height; y++)
5667 {
5668 for(int x = 0; x < 4 * width; x++)
5669 {
5670 float c0 = *(float*)(source0 + 4 * x);
5671 float c1 = *(float*)(source1 + 4 * x);
5672
5673 c0 = c0 + c1;
5674 c0 *= 1.0f / 2.0f;
5675
5676 *(float*)(source0 + 4 * x) = c0;
5677 }
5678
5679 source0 += pitch;
5680 source1 += pitch;
5681 }
5682 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005683 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005684 {
5685 for(int y = 0; y < height; y++)
5686 {
5687 for(int x = 0; x < 4 * width; x++)
5688 {
5689 float c0 = *(float*)(source0 + 4 * x);
5690 float c1 = *(float*)(source1 + 4 * x);
5691 float c2 = *(float*)(source2 + 4 * x);
5692 float c3 = *(float*)(source3 + 4 * x);
5693
5694 c0 = c0 + c1;
5695 c2 = c2 + c3;
5696 c0 = c0 + c2;
5697 c0 *= 1.0f / 4.0f;
5698
5699 *(float*)(source0 + 4 * x) = c0;
5700 }
5701
5702 source0 += pitch;
5703 source1 += pitch;
5704 source2 += pitch;
5705 source3 += pitch;
5706 }
5707 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005708 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005709 {
5710 for(int y = 0; y < height; y++)
5711 {
5712 for(int x = 0; x < 4 * width; x++)
5713 {
5714 float c0 = *(float*)(source0 + 4 * x);
5715 float c1 = *(float*)(source1 + 4 * x);
5716 float c2 = *(float*)(source2 + 4 * x);
5717 float c3 = *(float*)(source3 + 4 * x);
5718 float c4 = *(float*)(source4 + 4 * x);
5719 float c5 = *(float*)(source5 + 4 * x);
5720 float c6 = *(float*)(source6 + 4 * x);
5721 float c7 = *(float*)(source7 + 4 * x);
5722
5723 c0 = c0 + c1;
5724 c2 = c2 + c3;
5725 c4 = c4 + c5;
5726 c6 = c6 + c7;
5727 c0 = c0 + c2;
5728 c4 = c4 + c6;
5729 c0 = c0 + c4;
5730 c0 *= 1.0f / 8.0f;
5731
5732 *(float*)(source0 + 4 * x) = c0;
5733 }
5734
5735 source0 += pitch;
5736 source1 += pitch;
5737 source2 += pitch;
5738 source3 += pitch;
5739 source4 += pitch;
5740 source5 += pitch;
5741 source6 += pitch;
5742 source7 += pitch;
5743 }
5744 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005745 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005746 {
5747 for(int y = 0; y < height; y++)
5748 {
5749 for(int x = 0; x < 4 * width; x++)
5750 {
5751 float c0 = *(float*)(source0 + 4 * x);
5752 float c1 = *(float*)(source1 + 4 * x);
5753 float c2 = *(float*)(source2 + 4 * x);
5754 float c3 = *(float*)(source3 + 4 * x);
5755 float c4 = *(float*)(source4 + 4 * x);
5756 float c5 = *(float*)(source5 + 4 * x);
5757 float c6 = *(float*)(source6 + 4 * x);
5758 float c7 = *(float*)(source7 + 4 * x);
5759 float c8 = *(float*)(source8 + 4 * x);
5760 float c9 = *(float*)(source9 + 4 * x);
5761 float cA = *(float*)(sourceA + 4 * x);
5762 float cB = *(float*)(sourceB + 4 * x);
5763 float cC = *(float*)(sourceC + 4 * x);
5764 float cD = *(float*)(sourceD + 4 * x);
5765 float cE = *(float*)(sourceE + 4 * x);
5766 float cF = *(float*)(sourceF + 4 * x);
5767
5768 c0 = c0 + c1;
5769 c2 = c2 + c3;
5770 c4 = c4 + c5;
5771 c6 = c6 + c7;
5772 c8 = c8 + c9;
5773 cA = cA + cB;
5774 cC = cC + cD;
5775 cE = cE + cF;
5776 c0 = c0 + c2;
5777 c4 = c4 + c6;
5778 c8 = c8 + cA;
5779 cC = cC + cE;
5780 c0 = c0 + c4;
5781 c8 = c8 + cC;
5782 c0 = c0 + c8;
5783 c0 *= 1.0f / 16.0f;
5784
5785 *(float*)(source0 + 4 * x) = c0;
5786 }
5787
5788 source0 += pitch;
5789 source1 += pitch;
5790 source2 += pitch;
5791 source3 += pitch;
5792 source4 += pitch;
5793 source5 += pitch;
5794 source6 += pitch;
5795 source7 += pitch;
5796 source8 += pitch;
5797 source9 += pitch;
5798 sourceA += pitch;
5799 sourceB += pitch;
5800 sourceC += pitch;
5801 sourceD += pitch;
5802 sourceE += pitch;
5803 sourceF += pitch;
5804 }
5805 }
5806 else ASSERT(false);
5807 }
5808 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005809 else if(internal.format == FORMAT_R5G6B5)
5810 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005811 #if defined(__i386__) || defined(__x86_64__)
5812 if(CPUID::supportsSSE2() && (width % 8) == 0)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005813 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005814 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005815 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005816 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005817 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005818 for(int x = 0; x < width; x += 8)
5819 {
5820 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5821 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005822
Nicolas Capens47dc8672017-04-25 12:54:39 -04005823 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5824 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5825 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5826 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5827 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5828 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005829
Nicolas Capens47dc8672017-04-25 12:54:39 -04005830 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5831 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5832 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5833 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5834 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005835
Nicolas Capens47dc8672017-04-25 12:54:39 -04005836 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5837 }
5838
5839 source0 += pitch;
5840 source1 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005841 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005842 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005843 else if(internal.samples == 4)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005844 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005845 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005846 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005847 for(int x = 0; x < width; x += 8)
5848 {
5849 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5850 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5851 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5852 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005853
Nicolas Capens47dc8672017-04-25 12:54:39 -04005854 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5855 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5856 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5857 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5858 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5859 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5860 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5861 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5862 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5863 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005864
Nicolas Capens47dc8672017-04-25 12:54:39 -04005865 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5866 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5867 c0 = _mm_avg_epu8(c0, c2);
5868 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5869 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5870 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5871 c1 = _mm_avg_epu16(c1, c3);
5872 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5873 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005874
Nicolas Capens47dc8672017-04-25 12:54:39 -04005875 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5876 }
5877
5878 source0 += pitch;
5879 source1 += pitch;
5880 source2 += pitch;
5881 source3 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005882 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005883 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005884 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005885 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005886 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005887 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005888 for(int x = 0; x < width; x += 8)
5889 {
5890 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5891 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5892 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5893 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5894 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5895 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5896 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5897 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005898
Nicolas Capens47dc8672017-04-25 12:54:39 -04005899 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5900 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5901 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5902 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5903 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5904 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5905 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5906 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5907 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5908 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
5909 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
5910 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
5911 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
5912 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
5913 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
5914 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
5915 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
5916 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005917
Nicolas Capens47dc8672017-04-25 12:54:39 -04005918 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5919 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5920 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
5921 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
5922 c0 = _mm_avg_epu8(c0, c2);
5923 c4 = _mm_avg_epu8(c4, c6);
5924 c0 = _mm_avg_epu8(c0, c4);
5925 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5926 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5927 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5928 c5 = _mm_avg_epu16(c4__g_, c5__g_);
5929 c7 = _mm_avg_epu16(c6__g_, c7__g_);
5930 c1 = _mm_avg_epu16(c1, c3);
5931 c5 = _mm_avg_epu16(c5, c7);
5932 c1 = _mm_avg_epu16(c1, c5);
5933 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5934 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005935
Nicolas Capens47dc8672017-04-25 12:54:39 -04005936 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5937 }
5938
5939 source0 += pitch;
5940 source1 += pitch;
5941 source2 += pitch;
5942 source3 += pitch;
5943 source4 += pitch;
5944 source5 += pitch;
5945 source6 += pitch;
5946 source7 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005947 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005948 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005949 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005950 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005951 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005952 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005953 for(int x = 0; x < width; x += 8)
5954 {
5955 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5956 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5957 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5958 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5959 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5960 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5961 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5962 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
5963 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 2 * x));
5964 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 2 * x));
5965 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 2 * x));
5966 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 2 * x));
5967 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 2 * x));
5968 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 2 * x));
5969 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 2 * x));
5970 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 2 * x));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005971
Nicolas Capens47dc8672017-04-25 12:54:39 -04005972 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5973 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5974 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5975 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5976 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5977 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5978 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5979 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5980 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5981 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
5982 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
5983 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
5984 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
5985 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
5986 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
5987 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
5988 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
5989 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
5990 __m128i c8_r_b = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(r_b));
5991 __m128i c8__g_ = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(_g_));
5992 __m128i c9_r_b = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(r_b));
5993 __m128i c9__g_ = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(_g_));
5994 __m128i cA_r_b = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(r_b));
5995 __m128i cA__g_ = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(_g_));
5996 __m128i cB_r_b = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(r_b));
5997 __m128i cB__g_ = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(_g_));
5998 __m128i cC_r_b = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(r_b));
5999 __m128i cC__g_ = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(_g_));
6000 __m128i cD_r_b = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(r_b));
6001 __m128i cD__g_ = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(_g_));
6002 __m128i cE_r_b = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(r_b));
6003 __m128i cE__g_ = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(_g_));
6004 __m128i cF_r_b = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(r_b));
6005 __m128i cF__g_ = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04006006
Nicolas Capens47dc8672017-04-25 12:54:39 -04006007 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
6008 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
6009 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
6010 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
6011 c8 = _mm_avg_epu8(c8_r_b, c9_r_b);
6012 cA = _mm_avg_epu8(cA_r_b, cB_r_b);
6013 cC = _mm_avg_epu8(cC_r_b, cD_r_b);
6014 cE = _mm_avg_epu8(cE_r_b, cF_r_b);
6015 c0 = _mm_avg_epu8(c0, c2);
6016 c4 = _mm_avg_epu8(c4, c6);
6017 c8 = _mm_avg_epu8(c8, cA);
6018 cC = _mm_avg_epu8(cC, cE);
6019 c0 = _mm_avg_epu8(c0, c4);
6020 c8 = _mm_avg_epu8(c8, cC);
6021 c0 = _mm_avg_epu8(c0, c8);
6022 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
6023 c1 = _mm_avg_epu16(c0__g_, c1__g_);
6024 c3 = _mm_avg_epu16(c2__g_, c3__g_);
6025 c5 = _mm_avg_epu16(c4__g_, c5__g_);
6026 c7 = _mm_avg_epu16(c6__g_, c7__g_);
6027 c9 = _mm_avg_epu16(c8__g_, c9__g_);
6028 cB = _mm_avg_epu16(cA__g_, cB__g_);
6029 cD = _mm_avg_epu16(cC__g_, cD__g_);
6030 cF = _mm_avg_epu16(cE__g_, cF__g_);
6031 c1 = _mm_avg_epu8(c1, c3);
6032 c5 = _mm_avg_epu8(c5, c7);
6033 c9 = _mm_avg_epu8(c9, cB);
6034 cD = _mm_avg_epu8(cD, cF);
6035 c1 = _mm_avg_epu8(c1, c5);
6036 c9 = _mm_avg_epu8(c9, cD);
6037 c1 = _mm_avg_epu8(c1, c9);
6038 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
6039 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006040
Nicolas Capens47dc8672017-04-25 12:54:39 -04006041 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
6042 }
6043
6044 source0 += pitch;
6045 source1 += pitch;
6046 source2 += pitch;
6047 source3 += pitch;
6048 source4 += pitch;
6049 source5 += pitch;
6050 source6 += pitch;
6051 source7 += pitch;
6052 source8 += pitch;
6053 source9 += pitch;
6054 sourceA += pitch;
6055 sourceB += pitch;
6056 sourceC += pitch;
6057 sourceD += pitch;
6058 sourceE += pitch;
6059 sourceF += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04006060 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04006061 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006062 else ASSERT(false);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006063 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006064 else
6065 #endif
Nicolas Capens0e12a922015-09-04 09:18:15 -04006066 {
6067 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7BEF) + (((x) ^ (y)) & 0x0821))
6068
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006069 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006070 {
6071 for(int y = 0; y < height; y++)
6072 {
6073 for(int x = 0; x < width; x++)
6074 {
6075 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6076 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6077
6078 c0 = AVERAGE(c0, c1);
6079
6080 *(unsigned short*)(source0 + 2 * x) = c0;
6081 }
6082
6083 source0 += pitch;
6084 source1 += pitch;
6085 }
6086 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006087 else if(internal.samples == 4)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006088 {
6089 for(int y = 0; y < height; y++)
6090 {
6091 for(int x = 0; x < width; x++)
6092 {
6093 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6094 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6095 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6096 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6097
6098 c0 = AVERAGE(c0, c1);
6099 c2 = AVERAGE(c2, c3);
6100 c0 = AVERAGE(c0, c2);
6101
6102 *(unsigned short*)(source0 + 2 * x) = c0;
6103 }
6104
6105 source0 += pitch;
6106 source1 += pitch;
6107 source2 += pitch;
6108 source3 += pitch;
6109 }
6110 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006111 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006112 {
6113 for(int y = 0; y < height; y++)
6114 {
6115 for(int x = 0; x < width; x++)
6116 {
6117 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6118 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6119 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6120 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6121 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6122 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6123 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6124 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6125
6126 c0 = AVERAGE(c0, c1);
6127 c2 = AVERAGE(c2, c3);
6128 c4 = AVERAGE(c4, c5);
6129 c6 = AVERAGE(c6, c7);
6130 c0 = AVERAGE(c0, c2);
6131 c4 = AVERAGE(c4, c6);
6132 c0 = AVERAGE(c0, c4);
6133
6134 *(unsigned short*)(source0 + 2 * x) = c0;
6135 }
6136
6137 source0 += pitch;
6138 source1 += pitch;
6139 source2 += pitch;
6140 source3 += pitch;
6141 source4 += pitch;
6142 source5 += pitch;
6143 source6 += pitch;
6144 source7 += pitch;
6145 }
6146 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006147 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006148 {
6149 for(int y = 0; y < height; y++)
6150 {
6151 for(int x = 0; x < width; x++)
6152 {
6153 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6154 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6155 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6156 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6157 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6158 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6159 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6160 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6161 unsigned short c8 = *(unsigned short*)(source8 + 2 * x);
6162 unsigned short c9 = *(unsigned short*)(source9 + 2 * x);
6163 unsigned short cA = *(unsigned short*)(sourceA + 2 * x);
6164 unsigned short cB = *(unsigned short*)(sourceB + 2 * x);
6165 unsigned short cC = *(unsigned short*)(sourceC + 2 * x);
6166 unsigned short cD = *(unsigned short*)(sourceD + 2 * x);
6167 unsigned short cE = *(unsigned short*)(sourceE + 2 * x);
6168 unsigned short cF = *(unsigned short*)(sourceF + 2 * x);
6169
6170 c0 = AVERAGE(c0, c1);
6171 c2 = AVERAGE(c2, c3);
6172 c4 = AVERAGE(c4, c5);
6173 c6 = AVERAGE(c6, c7);
6174 c8 = AVERAGE(c8, c9);
6175 cA = AVERAGE(cA, cB);
6176 cC = AVERAGE(cC, cD);
6177 cE = AVERAGE(cE, cF);
6178 c0 = AVERAGE(c0, c2);
6179 c4 = AVERAGE(c4, c6);
6180 c8 = AVERAGE(c8, cA);
6181 cC = AVERAGE(cC, cE);
6182 c0 = AVERAGE(c0, c4);
6183 c8 = AVERAGE(c8, cC);
6184 c0 = AVERAGE(c0, c8);
6185
6186 *(unsigned short*)(source0 + 2 * x) = c0;
6187 }
6188
6189 source0 += pitch;
6190 source1 += pitch;
6191 source2 += pitch;
6192 source3 += pitch;
6193 source4 += pitch;
6194 source5 += pitch;
6195 source6 += pitch;
6196 source7 += pitch;
6197 source8 += pitch;
6198 source9 += pitch;
6199 sourceA += pitch;
6200 sourceB += pitch;
6201 sourceC += pitch;
6202 sourceD += pitch;
6203 sourceE += pitch;
6204 sourceF += pitch;
6205 }
6206 }
6207 else ASSERT(false);
6208
6209 #undef AVERAGE
6210 }
6211 }
John Bauman89401822014-05-06 15:04:28 -04006212 else
6213 {
6214 // UNIMPLEMENTED();
6215 }
6216 }
6217}