blob: 8bb80ec878a2226cd0c44ad2aaab8b2e34249810 [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 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -050047 byte *element = (byte*)buffer + (x + border) * bytes + (y + border) * pitchB + z * samples * sliceB;
John Bauman89401822014-05-06 15:04:28 -040048
Nicolas Capensbfa23b32017-12-11 10:06:37 -050049 for(int i = 0; i < samples; i++)
50 {
51 write(element, color);
52 element += sliceB;
53 }
John Bauman89401822014-05-06 15:04:28 -040054 }
55
56 void Surface::Buffer::write(int x, int y, const Color<float> &color)
57 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -050058 byte *element = (byte*)buffer + (x + border) * bytes + (y + border) * pitchB;
John Bauman89401822014-05-06 15:04:28 -040059
Nicolas Capensbfa23b32017-12-11 10:06:37 -050060 for(int i = 0; i < samples; i++)
61 {
62 write(element, color);
63 element += sliceB;
64 }
John Bauman89401822014-05-06 15:04:28 -040065 }
66
67 inline void Surface::Buffer::write(void *element, const Color<float> &color)
68 {
Nicolas Capens1efac522017-12-01 16:59:38 -050069 float r = color.r;
70 float g = color.g;
71 float b = color.b;
72 float a = color.a;
73
74 if(isSRGBformat(format))
75 {
76 r = linearToSRGB(r);
77 g = linearToSRGB(g);
78 b = linearToSRGB(b);
79 }
80
John Bauman89401822014-05-06 15:04:28 -040081 switch(format)
82 {
83 case FORMAT_A8:
Nicolas Capens1efac522017-12-01 16:59:38 -050084 *(unsigned char*)element = unorm<8>(a);
John Bauman89401822014-05-06 15:04:28 -040085 break;
Nicolas Capens975adb72017-12-19 15:34:20 -050086 case FORMAT_R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -050087 *(char*)element = snorm<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040088 break;
John Bauman89401822014-05-06 15:04:28 -040089 case FORMAT_R8:
Nicolas Capens1efac522017-12-01 16:59:38 -050090 *(unsigned char*)element = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -040091 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040092 case FORMAT_R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -050093 *(char*)element = scast<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040094 break;
95 case FORMAT_R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -050096 *(unsigned char*)element = ucast<8>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -040097 break;
98 case FORMAT_R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -050099 *(short*)element = scast<16>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400100 break;
101 case FORMAT_R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500102 *(unsigned short*)element = ucast<16>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400103 break;
104 case FORMAT_R32I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500105 *(int*)element = static_cast<int>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400106 break;
107 case FORMAT_R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500108 *(unsigned int*)element = static_cast<unsigned int>(r);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400109 break;
John Bauman89401822014-05-06 15:04:28 -0400110 case FORMAT_R3G3B2:
Nicolas Capens1efac522017-12-01 16:59:38 -0500111 *(unsigned char*)element = (unorm<3>(r) << 5) | (unorm<3>(g) << 2) | (unorm<2>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400112 break;
113 case FORMAT_A8R3G3B2:
Nicolas Capens1efac522017-12-01 16:59:38 -0500114 *(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 -0400115 break;
116 case FORMAT_X4R4G4B4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500117 *(unsigned short*)element = 0xF000 | (unorm<4>(r) << 8) | (unorm<4>(g) << 4) | (unorm<4>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400118 break;
119 case FORMAT_A4R4G4B4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500120 *(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 -0400121 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400122 case FORMAT_R4G4B4A4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500123 *(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 -0400124 break;
John Bauman89401822014-05-06 15:04:28 -0400125 case FORMAT_R5G6B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500126 *(unsigned short*)element = (unorm<5>(r) << 11) | (unorm<6>(g) << 5) | (unorm<5>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400127 break;
128 case FORMAT_A1R5G5B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500129 *(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 -0400130 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400131 case FORMAT_R5G5B5A1:
Nicolas Capens1efac522017-12-01 16:59:38 -0500132 *(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 -0400133 break;
John Bauman89401822014-05-06 15:04:28 -0400134 case FORMAT_X1R5G5B5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500135 *(unsigned short*)element = 0x8000 | (unorm<5>(r) << 10) | (unorm<5>(g) << 5) | (unorm<5>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400136 break;
137 case FORMAT_A8R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500138 *(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 -0400139 break;
140 case FORMAT_X8R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500141 *(unsigned int*)element = 0xFF000000 | (unorm<8>(r) << 16) | (unorm<8>(g) << 8) | (unorm<8>(b) << 0);
John Bauman89401822014-05-06 15:04:28 -0400142 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500143 case FORMAT_A8B8G8R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -0500144 *(unsigned int*)element = (static_cast<unsigned int>(snorm<8>(a)) << 24) |
145 (static_cast<unsigned int>(snorm<8>(b)) << 16) |
146 (static_cast<unsigned int>(snorm<8>(g)) << 8) |
147 (static_cast<unsigned int>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400148 break;
John Bauman89401822014-05-06 15:04:28 -0400149 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400150 case FORMAT_SRGB8_A8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500151 *(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 -0400152 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400153 case FORMAT_A8B8G8R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500154 *(unsigned int*)element = (static_cast<unsigned int>(scast<8>(a)) << 24) |
155 (static_cast<unsigned int>(scast<8>(b)) << 16) |
156 (static_cast<unsigned int>(scast<8>(g)) << 8) |
157 (static_cast<unsigned int>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400158 break;
159 case FORMAT_A8B8G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500160 *(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 -0400161 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500162 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400163 *(unsigned int*)element = 0x7F000000 |
Nicolas Capens1efac522017-12-01 16:59:38 -0500164 (static_cast<unsigned int>(snorm<8>(b)) << 16) |
165 (static_cast<unsigned int>(snorm<8>(g)) << 8) |
166 (static_cast<unsigned int>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400167 break;
John Bauman89401822014-05-06 15:04:28 -0400168 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400169 case FORMAT_SRGB8_X8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500170 *(unsigned int*)element = 0xFF000000 | (unorm<8>(b) << 16) | (unorm<8>(g) << 8) | (unorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400171 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400172 case FORMAT_X8B8G8R8I:
173 *(unsigned int*)element = 0x7F000000 |
Nicolas Capens1efac522017-12-01 16:59:38 -0500174 (static_cast<unsigned int>(scast<8>(b)) << 16) |
175 (static_cast<unsigned int>(scast<8>(g)) << 8) |
176 (static_cast<unsigned int>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400177 case FORMAT_X8B8G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500178 *(unsigned int*)element = 0xFF000000 | (ucast<8>(b) << 16) | (ucast<8>(g) << 8) | (ucast<8>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400179 break;
John Bauman89401822014-05-06 15:04:28 -0400180 case FORMAT_A2R10G10B10:
Nicolas Capens1efac522017-12-01 16:59:38 -0500181 *(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 -0400182 break;
183 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -0500184 case FORMAT_A2B10G10R10UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500185 *(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 -0400186 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500187 case FORMAT_G8R8_SNORM:
Nicolas Capens1efac522017-12-01 16:59:38 -0500188 *(unsigned short*)element = (static_cast<unsigned short>(snorm<8>(g)) << 8) |
189 (static_cast<unsigned short>(snorm<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400190 break;
John Bauman89401822014-05-06 15:04:28 -0400191 case FORMAT_G8R8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500192 *(unsigned short*)element = (unorm<8>(g) << 8) | (unorm<8>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400193 break;
194 case FORMAT_G8R8I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500195 *(unsigned short*)element = (static_cast<unsigned short>(scast<8>(g)) << 8) |
196 (static_cast<unsigned short>(scast<8>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400197 break;
198 case FORMAT_G8R8UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500199 *(unsigned short*)element = (ucast<8>(g) << 8) | (ucast<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400200 break;
201 case FORMAT_G16R16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500202 *(unsigned int*)element = (unorm<16>(g) << 16) | (unorm<16>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400203 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400204 case FORMAT_G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500205 *(unsigned int*)element = (static_cast<unsigned int>(scast<16>(g)) << 16) |
206 (static_cast<unsigned int>(scast<16>(r)) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400207 break;
208 case FORMAT_G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500209 *(unsigned int*)element = (ucast<16>(g) << 16) | (ucast<16>(r) << 0);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400210 break;
211 case FORMAT_G32R32I:
212 case FORMAT_G32R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500213 ((unsigned int*)element)[0] = static_cast<unsigned int>(r);
214 ((unsigned int*)element)[1] = static_cast<unsigned int>(g);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400215 break;
John Bauman89401822014-05-06 15:04:28 -0400216 case FORMAT_A16B16G16R16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500217 ((unsigned short*)element)[0] = unorm<16>(r);
218 ((unsigned short*)element)[1] = unorm<16>(g);
219 ((unsigned short*)element)[2] = unorm<16>(b);
220 ((unsigned short*)element)[3] = unorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400221 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400222 case FORMAT_A16B16G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500223 ((unsigned short*)element)[0] = static_cast<unsigned short>(scast<16>(r));
224 ((unsigned short*)element)[1] = static_cast<unsigned short>(scast<16>(g));
225 ((unsigned short*)element)[2] = static_cast<unsigned short>(scast<16>(b));
226 ((unsigned short*)element)[3] = static_cast<unsigned short>(scast<16>(a));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400227 break;
228 case FORMAT_A16B16G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500229 ((unsigned short*)element)[0] = static_cast<unsigned short>(ucast<16>(r));
230 ((unsigned short*)element)[1] = static_cast<unsigned short>(ucast<16>(g));
231 ((unsigned short*)element)[2] = static_cast<unsigned short>(ucast<16>(b));
232 ((unsigned short*)element)[3] = static_cast<unsigned short>(ucast<16>(a));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400233 break;
234 case FORMAT_X16B16G16R16I:
Nicolas Capens1efac522017-12-01 16:59:38 -0500235 ((unsigned short*)element)[0] = static_cast<unsigned short>(scast<16>(r));
236 ((unsigned short*)element)[1] = static_cast<unsigned short>(scast<16>(g));
237 ((unsigned short*)element)[2] = static_cast<unsigned short>(scast<16>(b));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400238 break;
239 case FORMAT_X16B16G16R16UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500240 ((unsigned short*)element)[0] = static_cast<unsigned short>(ucast<16>(r));
241 ((unsigned short*)element)[1] = static_cast<unsigned short>(ucast<16>(g));
242 ((unsigned short*)element)[2] = static_cast<unsigned short>(ucast<16>(b));
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400243 break;
244 case FORMAT_A32B32G32R32I:
245 case FORMAT_A32B32G32R32UI:
Nicolas Capens1efac522017-12-01 16:59:38 -0500246 ((unsigned int*)element)[0] = static_cast<unsigned int>(r);
247 ((unsigned int*)element)[1] = static_cast<unsigned int>(g);
248 ((unsigned int*)element)[2] = static_cast<unsigned int>(b);
249 ((unsigned int*)element)[3] = static_cast<unsigned int>(a);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400250 break;
251 case FORMAT_X32B32G32R32I:
252 case FORMAT_X32B32G32R32UI:
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);
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400256 break;
John Bauman89401822014-05-06 15:04:28 -0400257 case FORMAT_V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500258 *(unsigned short*)element = (snorm<8>(g) << 8) | (snorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400259 break;
260 case FORMAT_L6V5U5:
Nicolas Capens1efac522017-12-01 16:59:38 -0500261 *(unsigned short*)element = (unorm<6>(b) << 10) | (snorm<5>(g) << 5) | (snorm<5>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400262 break;
263 case FORMAT_Q8W8V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500264 *(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 -0400265 break;
266 case FORMAT_X8L8V8U8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500267 *(unsigned int*)element = 0xFF000000 | (unorm<8>(b) << 16) | (snorm<8>(g) << 8) | (snorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400268 break;
269 case FORMAT_V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500270 *(unsigned int*)element = (snorm<16>(g) << 16) | (snorm<16>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400271 break;
272 case FORMAT_A2W10V10U10:
Nicolas Capens1efac522017-12-01 16:59:38 -0500273 *(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 -0400274 break;
275 case FORMAT_A16W16V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500276 ((unsigned short*)element)[0] = snorm<16>(r);
277 ((unsigned short*)element)[1] = snorm<16>(g);
278 ((unsigned short*)element)[2] = snorm<16>(b);
279 ((unsigned short*)element)[3] = unorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400280 break;
281 case FORMAT_Q16W16V16U16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500282 ((unsigned short*)element)[0] = snorm<16>(r);
283 ((unsigned short*)element)[1] = snorm<16>(g);
284 ((unsigned short*)element)[2] = snorm<16>(b);
285 ((unsigned short*)element)[3] = snorm<16>(a);
John Bauman89401822014-05-06 15:04:28 -0400286 break;
287 case FORMAT_R8G8B8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500288 ((unsigned char*)element)[0] = unorm<8>(b);
289 ((unsigned char*)element)[1] = unorm<8>(g);
290 ((unsigned char*)element)[2] = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400291 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400292 case FORMAT_B8G8R8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500293 ((unsigned char*)element)[0] = unorm<8>(r);
294 ((unsigned char*)element)[1] = unorm<8>(g);
295 ((unsigned char*)element)[2] = unorm<8>(b);
Nicolas Capens80594422015-06-09 16:42:56 -0400296 break;
John Bauman89401822014-05-06 15:04:28 -0400297 case FORMAT_R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500298 *(half*)element = (half)r;
John Bauman89401822014-05-06 15:04:28 -0400299 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400300 case FORMAT_A16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500301 *(half*)element = (half)a;
Nicolas Capens80594422015-06-09 16:42:56 -0400302 break;
John Bauman89401822014-05-06 15:04:28 -0400303 case FORMAT_G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500304 ((half*)element)[0] = (half)r;
305 ((half*)element)[1] = (half)g;
John Bauman89401822014-05-06 15:04:28 -0400306 break;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500307 case FORMAT_X16B16G16R16F_UNSIGNED:
308 r = max(r, 0.0f); g = max(g, 0.0f); b = max(b, 0.0f);
309 // Fall through to FORMAT_X16B16G16R16F.
Nicolas Capensa6bc61d2017-12-20 11:07:45 -0500310 case FORMAT_X16B16G16R16F:
311 ((half*)element)[3] = 1.0f;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500312 // Fall through to FORMAT_B16G16R16F.
Nicolas Capens80594422015-06-09 16:42:56 -0400313 case FORMAT_B16G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500314 ((half*)element)[0] = (half)r;
315 ((half*)element)[1] = (half)g;
316 ((half*)element)[2] = (half)b;
Nicolas Capens80594422015-06-09 16:42:56 -0400317 break;
John Bauman89401822014-05-06 15:04:28 -0400318 case FORMAT_A16B16G16R16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500319 ((half*)element)[0] = (half)r;
320 ((half*)element)[1] = (half)g;
321 ((half*)element)[2] = (half)b;
322 ((half*)element)[3] = (half)a;
John Bauman89401822014-05-06 15:04:28 -0400323 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400324 case FORMAT_A32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500325 *(float*)element = a;
Nicolas Capens80594422015-06-09 16:42:56 -0400326 break;
John Bauman89401822014-05-06 15:04:28 -0400327 case FORMAT_R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500328 *(float*)element = r;
John Bauman89401822014-05-06 15:04:28 -0400329 break;
330 case FORMAT_G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500331 ((float*)element)[0] = r;
332 ((float*)element)[1] = g;
John Bauman89401822014-05-06 15:04:28 -0400333 break;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500334 case FORMAT_X32B32G32R32F_UNSIGNED:
335 r = max(r, 0.0f); g = max(g, 0.0f); b = max(b, 0.0f);
336 // Fall through to FORMAT_X32B32G32R32F.
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400337 case FORMAT_X32B32G32R32F:
338 ((float*)element)[3] = 1.0f;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500339 // Fall through to FORMAT_B32G32R32F.
Nicolas Capens80594422015-06-09 16:42:56 -0400340 case FORMAT_B32G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500341 ((float*)element)[0] = r;
342 ((float*)element)[1] = g;
343 ((float*)element)[2] = b;
Nicolas Capens80594422015-06-09 16:42:56 -0400344 break;
John Bauman89401822014-05-06 15:04:28 -0400345 case FORMAT_A32B32G32R32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500346 ((float*)element)[0] = r;
347 ((float*)element)[1] = g;
348 ((float*)element)[2] = b;
349 ((float*)element)[3] = a;
John Bauman89401822014-05-06 15:04:28 -0400350 break;
351 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500352 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -0400353 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400354 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500355 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -0400356 case FORMAT_D32FS8_SHADOW:
Nicolas Capens1efac522017-12-01 16:59:38 -0500357 *((float*)element) = r;
John Bauman89401822014-05-06 15:04:28 -0400358 break;
359 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500360 case FORMAT_D32FS8_COMPLEMENTARY:
Nicolas Capens1efac522017-12-01 16:59:38 -0500361 *((float*)element) = 1 - r;
John Bauman89401822014-05-06 15:04:28 -0400362 break;
363 case FORMAT_S8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500364 *((unsigned char*)element) = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400365 break;
366 case FORMAT_L8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500367 *(unsigned char*)element = unorm<8>(r);
John Bauman89401822014-05-06 15:04:28 -0400368 break;
369 case FORMAT_A4L4:
Nicolas Capens1efac522017-12-01 16:59:38 -0500370 *(unsigned char*)element = (unorm<4>(a) << 4) | (unorm<4>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400371 break;
372 case FORMAT_L16:
Nicolas Capens1efac522017-12-01 16:59:38 -0500373 *(unsigned short*)element = unorm<16>(r);
John Bauman89401822014-05-06 15:04:28 -0400374 break;
375 case FORMAT_A8L8:
Nicolas Capens1efac522017-12-01 16:59:38 -0500376 *(unsigned short*)element = (unorm<8>(a) << 8) | (unorm<8>(r) << 0);
John Bauman89401822014-05-06 15:04:28 -0400377 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400378 case FORMAT_L16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500379 *(half*)element = (half)r;
Nicolas Capens80594422015-06-09 16:42:56 -0400380 break;
381 case FORMAT_A16L16F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500382 ((half*)element)[0] = (half)r;
383 ((half*)element)[1] = (half)a;
Nicolas Capens80594422015-06-09 16:42:56 -0400384 break;
385 case FORMAT_L32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500386 *(float*)element = r;
Nicolas Capens80594422015-06-09 16:42:56 -0400387 break;
388 case FORMAT_A32L32F:
Nicolas Capens1efac522017-12-01 16:59:38 -0500389 ((float*)element)[0] = r;
390 ((float*)element)[1] = a;
Nicolas Capens80594422015-06-09 16:42:56 -0400391 break;
John Bauman89401822014-05-06 15:04:28 -0400392 default:
393 ASSERT(false);
394 }
395 }
396
397 Color<float> Surface::Buffer::read(int x, int y, int z) const
398 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500399 void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB + z * samples * sliceB;
John Bauman89401822014-05-06 15:04:28 -0400400
401 return read(element);
402 }
403
404 Color<float> Surface::Buffer::read(int x, int y) const
405 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -0500406 void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB;
John Bauman89401822014-05-06 15:04:28 -0400407
408 return read(element);
409 }
410
411 inline Color<float> Surface::Buffer::read(void *element) const
412 {
Nicolas Capens3f439242015-06-09 16:33:50 -0400413 float r = 0.0f;
414 float g = 0.0f;
415 float b = 0.0f;
416 float a = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400417
418 switch(format)
419 {
420 case FORMAT_P8:
421 {
422 ASSERT(palette);
423
424 unsigned int abgr = palette[*(unsigned char*)element];
Nicolas Capensc39901e2016-03-21 16:37:44 -0400425
John Bauman89401822014-05-06 15:04:28 -0400426 r = (abgr & 0x000000FF) * (1.0f / 0x000000FF);
427 g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00);
428 b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000);
429 a = (abgr & 0xFF000000) * (1.0f / 0xFF000000);
430 }
431 break;
432 case FORMAT_A8P8:
433 {
434 ASSERT(palette);
435
436 unsigned int bgr = palette[((unsigned char*)element)[0]];
Nicolas Capensc39901e2016-03-21 16:37:44 -0400437
John Bauman89401822014-05-06 15:04:28 -0400438 r = (bgr & 0x000000FF) * (1.0f / 0x000000FF);
439 g = (bgr & 0x0000FF00) * (1.0f / 0x0000FF00);
440 b = (bgr & 0x00FF0000) * (1.0f / 0x00FF0000);
441 a = ((unsigned char*)element)[1] * (1.0f / 0xFF);
442 }
443 break;
444 case FORMAT_A8:
445 r = 0;
446 g = 0;
447 b = 0;
448 a = *(unsigned char*)element * (1.0f / 0xFF);
449 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500450 case FORMAT_R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400451 r = max((*(signed char*)element) * (1.0f / 0x7F), -1.0f);
452 break;
John Bauman89401822014-05-06 15:04:28 -0400453 case FORMAT_R8:
454 r = *(unsigned char*)element * (1.0f / 0xFF);
455 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400456 case FORMAT_R8I:
457 r = *(signed char*)element;
458 break;
459 case FORMAT_R8UI:
460 r = *(unsigned char*)element;
461 break;
John Bauman89401822014-05-06 15:04:28 -0400462 case FORMAT_R3G3B2:
463 {
464 unsigned char rgb = *(unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400465
John Bauman89401822014-05-06 15:04:28 -0400466 r = (rgb & 0xE0) * (1.0f / 0xE0);
467 g = (rgb & 0x1C) * (1.0f / 0x1C);
468 b = (rgb & 0x03) * (1.0f / 0x03);
469 }
470 break;
471 case FORMAT_A8R3G3B2:
472 {
473 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400474
John Bauman89401822014-05-06 15:04:28 -0400475 a = (argb & 0xFF00) * (1.0f / 0xFF00);
476 r = (argb & 0x00E0) * (1.0f / 0x00E0);
477 g = (argb & 0x001C) * (1.0f / 0x001C);
478 b = (argb & 0x0003) * (1.0f / 0x0003);
479 }
480 break;
481 case FORMAT_X4R4G4B4:
482 {
483 unsigned short rgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400484
John Bauman89401822014-05-06 15:04:28 -0400485 r = (rgb & 0x0F00) * (1.0f / 0x0F00);
486 g = (rgb & 0x00F0) * (1.0f / 0x00F0);
487 b = (rgb & 0x000F) * (1.0f / 0x000F);
488 }
489 break;
490 case FORMAT_A4R4G4B4:
491 {
492 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400493
John Bauman89401822014-05-06 15:04:28 -0400494 a = (argb & 0xF000) * (1.0f / 0xF000);
495 r = (argb & 0x0F00) * (1.0f / 0x0F00);
496 g = (argb & 0x00F0) * (1.0f / 0x00F0);
497 b = (argb & 0x000F) * (1.0f / 0x000F);
498 }
499 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400500 case FORMAT_R4G4B4A4:
501 {
502 unsigned short rgba = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400503
Nicolas Capens80594422015-06-09 16:42:56 -0400504 r = (rgba & 0xF000) * (1.0f / 0xF000);
505 g = (rgba & 0x0F00) * (1.0f / 0x0F00);
506 b = (rgba & 0x00F0) * (1.0f / 0x00F0);
507 a = (rgba & 0x000F) * (1.0f / 0x000F);
508 }
509 break;
John Bauman89401822014-05-06 15:04:28 -0400510 case FORMAT_R5G6B5:
511 {
512 unsigned short rgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400513
John Bauman89401822014-05-06 15:04:28 -0400514 r = (rgb & 0xF800) * (1.0f / 0xF800);
515 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
516 b = (rgb & 0x001F) * (1.0f / 0x001F);
517 }
518 break;
519 case FORMAT_A1R5G5B5:
520 {
521 unsigned short argb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400522
John Bauman89401822014-05-06 15:04:28 -0400523 a = (argb & 0x8000) * (1.0f / 0x8000);
524 r = (argb & 0x7C00) * (1.0f / 0x7C00);
525 g = (argb & 0x03E0) * (1.0f / 0x03E0);
526 b = (argb & 0x001F) * (1.0f / 0x001F);
527 }
528 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400529 case FORMAT_R5G5B5A1:
530 {
531 unsigned short rgba = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400532
Nicolas Capens80594422015-06-09 16:42:56 -0400533 r = (rgba & 0xF800) * (1.0f / 0xF800);
534 g = (rgba & 0x07C0) * (1.0f / 0x07C0);
535 b = (rgba & 0x003E) * (1.0f / 0x003E);
536 a = (rgba & 0x0001) * (1.0f / 0x0001);
537 }
538 break;
John Bauman89401822014-05-06 15:04:28 -0400539 case FORMAT_X1R5G5B5:
540 {
541 unsigned short xrgb = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400542
John Bauman89401822014-05-06 15:04:28 -0400543 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
544 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
545 b = (xrgb & 0x001F) * (1.0f / 0x001F);
546 }
547 break;
548 case FORMAT_A8R8G8B8:
549 {
550 unsigned int argb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400551
John Bauman89401822014-05-06 15:04:28 -0400552 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
553 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
554 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
555 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
556 }
557 break;
558 case FORMAT_X8R8G8B8:
559 {
560 unsigned int xrgb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400561
John Bauman89401822014-05-06 15:04:28 -0400562 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
563 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
564 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
565 }
566 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500567 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400568 {
569 signed char* abgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400570
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400571 r = max(abgr[0] * (1.0f / 0x7F), -1.0f);
572 g = max(abgr[1] * (1.0f / 0x7F), -1.0f);
573 b = max(abgr[2] * (1.0f / 0x7F), -1.0f);
574 a = max(abgr[3] * (1.0f / 0x7F), -1.0f);
575 }
576 break;
John Bauman89401822014-05-06 15:04:28 -0400577 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400578 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400579 {
580 unsigned int abgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400581
John Bauman89401822014-05-06 15:04:28 -0400582 a = (abgr & 0xFF000000) * (1.0f / 0xFF000000);
583 b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000);
584 g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00);
585 r = (abgr & 0x000000FF) * (1.0f / 0x000000FF);
586 }
587 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400588 case FORMAT_A8B8G8R8I:
589 {
590 signed char* abgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400591
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400592 r = abgr[0];
593 g = abgr[1];
594 b = abgr[2];
595 a = abgr[3];
596 }
597 break;
598 case FORMAT_A8B8G8R8UI:
599 {
600 unsigned char* abgr = (unsigned char*)element;
601
602 r = abgr[0];
603 g = abgr[1];
604 b = abgr[2];
605 a = abgr[3];
606 }
607 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500608 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400609 {
610 signed char* bgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400611
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400612 r = max(bgr[0] * (1.0f / 0x7F), -1.0f);
613 g = max(bgr[1] * (1.0f / 0x7F), -1.0f);
614 b = max(bgr[2] * (1.0f / 0x7F), -1.0f);
615 }
616 break;
John Bauman89401822014-05-06 15:04:28 -0400617 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400618 case FORMAT_SRGB8_X8:
John Bauman89401822014-05-06 15:04:28 -0400619 {
620 unsigned int xbgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400621
John Bauman89401822014-05-06 15:04:28 -0400622 b = (xbgr & 0x00FF0000) * (1.0f / 0x00FF0000);
623 g = (xbgr & 0x0000FF00) * (1.0f / 0x0000FF00);
624 r = (xbgr & 0x000000FF) * (1.0f / 0x000000FF);
625 }
626 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400627 case FORMAT_X8B8G8R8I:
628 {
629 signed char* bgr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400630
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400631 r = bgr[0];
632 g = bgr[1];
633 b = bgr[2];
634 }
635 break;
636 case FORMAT_X8B8G8R8UI:
637 {
638 unsigned char* bgr = (unsigned char*)element;
639
640 r = bgr[0];
641 g = bgr[1];
642 b = bgr[2];
643 }
644 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500645 case FORMAT_G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400646 {
647 signed char* gr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400648
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400649 r = (gr[0] & 0xFF00) * (1.0f / 0xFF00);
650 g = (gr[1] & 0x00FF) * (1.0f / 0x00FF);
651 }
652 break;
John Bauman89401822014-05-06 15:04:28 -0400653 case FORMAT_G8R8:
654 {
655 unsigned short gr = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400656
John Bauman89401822014-05-06 15:04:28 -0400657 g = (gr & 0xFF00) * (1.0f / 0xFF00);
658 r = (gr & 0x00FF) * (1.0f / 0x00FF);
659 }
660 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400661 case FORMAT_G8R8I:
662 {
663 signed char* gr = (signed char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400664
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400665 r = gr[0];
666 g = gr[1];
667 }
668 break;
669 case FORMAT_G8R8UI:
670 {
671 unsigned char* gr = (unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400672
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400673 r = gr[0];
674 g = gr[1];
675 }
676 break;
677 case FORMAT_R16I:
678 r = *((short*)element);
679 break;
680 case FORMAT_R16UI:
681 r = *((unsigned short*)element);
682 break;
683 case FORMAT_G16R16I:
684 {
685 short* gr = (short*)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;
John Bauman89401822014-05-06 15:04:28 -0400691 case FORMAT_G16R16:
692 {
693 unsigned int gr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400694
John Bauman89401822014-05-06 15:04:28 -0400695 g = (gr & 0xFFFF0000) * (1.0f / 0xFFFF0000);
696 r = (gr & 0x0000FFFF) * (1.0f / 0x0000FFFF);
697 }
698 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400699 case FORMAT_G16R16UI:
700 {
701 unsigned short* gr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400702
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400703 r = gr[0];
704 g = gr[1];
705 }
706 break;
John Bauman89401822014-05-06 15:04:28 -0400707 case FORMAT_A2R10G10B10:
708 {
709 unsigned int argb = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400710
John Bauman89401822014-05-06 15:04:28 -0400711 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
712 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
713 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
714 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
715 }
716 break;
717 case FORMAT_A2B10G10R10:
718 {
719 unsigned int abgr = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400720
John Bauman89401822014-05-06 15:04:28 -0400721 a = (abgr & 0xC0000000) * (1.0f / 0xC0000000);
722 b = (abgr & 0x3FF00000) * (1.0f / 0x3FF00000);
723 g = (abgr & 0x000FFC00) * (1.0f / 0x000FFC00);
724 r = (abgr & 0x000003FF) * (1.0f / 0x000003FF);
725 }
726 break;
Nicolas Capens5555af42017-12-14 13:14:03 -0500727 case FORMAT_A2B10G10R10UI:
728 {
729 unsigned int abgr = *(unsigned int*)element;
730
731 a = static_cast<float>((abgr & 0xC0000000) >> 30);
732 b = static_cast<float>((abgr & 0x3FF00000) >> 20);
733 g = static_cast<float>((abgr & 0x000FFC00) >> 10);
734 r = static_cast<float>(abgr & 0x000003FF);
735 }
736 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400737 case FORMAT_A16B16G16R16I:
738 {
739 short* abgr = (short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400740
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400741 r = abgr[0];
742 g = abgr[1];
743 b = abgr[2];
744 a = abgr[3];
745 }
746 break;
John Bauman89401822014-05-06 15:04:28 -0400747 case FORMAT_A16B16G16R16:
748 r = ((unsigned short*)element)[0] * (1.0f / 0xFFFF);
749 g = ((unsigned short*)element)[1] * (1.0f / 0xFFFF);
750 b = ((unsigned short*)element)[2] * (1.0f / 0xFFFF);
751 a = ((unsigned short*)element)[3] * (1.0f / 0xFFFF);
752 break;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400753 case FORMAT_A16B16G16R16UI:
754 {
755 unsigned short* abgr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400756
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400757 r = abgr[0];
758 g = abgr[1];
759 b = abgr[2];
760 a = abgr[3];
761 }
762 break;
763 case FORMAT_X16B16G16R16I:
764 {
765 short* bgr = (short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400766
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400767 r = bgr[0];
768 g = bgr[1];
769 b = bgr[2];
770 }
771 break;
772 case FORMAT_X16B16G16R16UI:
773 {
774 unsigned short* bgr = (unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400775
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400776 r = bgr[0];
777 g = bgr[1];
778 b = bgr[2];
779 }
780 break;
781 case FORMAT_A32B32G32R32I:
782 {
783 int* abgr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400784
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400785 r = static_cast<float>(abgr[0]);
786 g = static_cast<float>(abgr[1]);
787 b = static_cast<float>(abgr[2]);
788 a = static_cast<float>(abgr[3]);
789 }
790 break;
791 case FORMAT_A32B32G32R32UI:
792 {
793 unsigned int* abgr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400794
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400795 r = static_cast<float>(abgr[0]);
796 g = static_cast<float>(abgr[1]);
797 b = static_cast<float>(abgr[2]);
798 a = static_cast<float>(abgr[3]);
799 }
800 break;
801 case FORMAT_X32B32G32R32I:
802 {
803 int* bgr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400804
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400805 r = static_cast<float>(bgr[0]);
806 g = static_cast<float>(bgr[1]);
807 b = static_cast<float>(bgr[2]);
808 }
809 break;
810 case FORMAT_X32B32G32R32UI:
811 {
812 unsigned int* bgr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400813
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400814 r = static_cast<float>(bgr[0]);
815 g = static_cast<float>(bgr[1]);
816 b = static_cast<float>(bgr[2]);
817 }
818 break;
819 case FORMAT_G32R32I:
820 {
821 int* gr = (int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400822
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400823 r = static_cast<float>(gr[0]);
824 g = static_cast<float>(gr[1]);
825 }
826 break;
827 case FORMAT_G32R32UI:
828 {
829 unsigned int* gr = (unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400830
Alexis Hetud3a2d3d2015-10-22 10:57:58 -0400831 r = static_cast<float>(gr[0]);
832 g = static_cast<float>(gr[1]);
833 }
834 break;
835 case FORMAT_R32I:
836 r = static_cast<float>(*((int*)element));
837 break;
838 case FORMAT_R32UI:
839 r = static_cast<float>(*((unsigned int*)element));
840 break;
John Bauman89401822014-05-06 15:04:28 -0400841 case FORMAT_V8U8:
842 {
843 unsigned short vu = *(unsigned short*)element;
844
845 r = ((int)(vu & 0x00FF) << 24) * (1.0f / 0x7F000000);
846 g = ((int)(vu & 0xFF00) << 16) * (1.0f / 0x7F000000);
847 }
848 break;
849 case FORMAT_L6V5U5:
850 {
851 unsigned short lvu = *(unsigned short*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400852
John Bauman89401822014-05-06 15:04:28 -0400853 r = ((int)(lvu & 0x001F) << 27) * (1.0f / 0x78000000);
854 g = ((int)(lvu & 0x03E0) << 22) * (1.0f / 0x78000000);
855 b = (lvu & 0xFC00) * (1.0f / 0xFC00);
856 }
857 break;
858 case FORMAT_Q8W8V8U8:
859 {
860 unsigned int qwvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400861
John Bauman89401822014-05-06 15:04:28 -0400862 r = ((int)(qwvu & 0x000000FF) << 24) * (1.0f / 0x7F000000);
863 g = ((int)(qwvu & 0x0000FF00) << 16) * (1.0f / 0x7F000000);
864 b = ((int)(qwvu & 0x00FF0000) << 8) * (1.0f / 0x7F000000);
865 a = ((int)(qwvu & 0xFF000000) << 0) * (1.0f / 0x7F000000);
866 }
867 break;
868 case FORMAT_X8L8V8U8:
869 {
870 unsigned int xlvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400871
John Bauman89401822014-05-06 15:04:28 -0400872 r = ((int)(xlvu & 0x000000FF) << 24) * (1.0f / 0x7F000000);
873 g = ((int)(xlvu & 0x0000FF00) << 16) * (1.0f / 0x7F000000);
874 b = (xlvu & 0x00FF0000) * (1.0f / 0x00FF0000);
875 }
876 break;
877 case FORMAT_R8G8B8:
878 r = ((unsigned char*)element)[2] * (1.0f / 0xFF);
879 g = ((unsigned char*)element)[1] * (1.0f / 0xFF);
880 b = ((unsigned char*)element)[0] * (1.0f / 0xFF);
881 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400882 case FORMAT_B8G8R8:
883 r = ((unsigned char*)element)[0] * (1.0f / 0xFF);
884 g = ((unsigned char*)element)[1] * (1.0f / 0xFF);
885 b = ((unsigned char*)element)[2] * (1.0f / 0xFF);
886 break;
John Bauman89401822014-05-06 15:04:28 -0400887 case FORMAT_V16U16:
888 {
889 unsigned int vu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400890
John Bauman89401822014-05-06 15:04:28 -0400891 r = ((int)(vu & 0x0000FFFF) << 16) * (1.0f / 0x7FFF0000);
892 g = ((int)(vu & 0xFFFF0000) << 0) * (1.0f / 0x7FFF0000);
893 }
894 break;
895 case FORMAT_A2W10V10U10:
896 {
897 unsigned int awvu = *(unsigned int*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400898
John Bauman89401822014-05-06 15:04:28 -0400899 r = ((int)(awvu & 0x000003FF) << 22) * (1.0f / 0x7FC00000);
900 g = ((int)(awvu & 0x000FFC00) << 12) * (1.0f / 0x7FC00000);
901 b = ((int)(awvu & 0x3FF00000) << 2) * (1.0f / 0x7FC00000);
902 a = (awvu & 0xC0000000) * (1.0f / 0xC0000000);
903 }
904 break;
905 case FORMAT_A16W16V16U16:
906 r = ((signed short*)element)[0] * (1.0f / 0x7FFF);
907 g = ((signed short*)element)[1] * (1.0f / 0x7FFF);
908 b = ((signed short*)element)[2] * (1.0f / 0x7FFF);
909 a = ((unsigned short*)element)[3] * (1.0f / 0xFFFF);
910 break;
911 case FORMAT_Q16W16V16U16:
912 r = ((signed short*)element)[0] * (1.0f / 0x7FFF);
913 g = ((signed short*)element)[1] * (1.0f / 0x7FFF);
914 b = ((signed short*)element)[2] * (1.0f / 0x7FFF);
915 a = ((signed short*)element)[3] * (1.0f / 0x7FFF);
916 break;
917 case FORMAT_L8:
918 r =
919 g =
920 b = *(unsigned char*)element * (1.0f / 0xFF);
921 break;
922 case FORMAT_A4L4:
923 {
924 unsigned char al = *(unsigned char*)element;
Nicolas Capensc39901e2016-03-21 16:37:44 -0400925
John Bauman89401822014-05-06 15:04:28 -0400926 r =
927 g =
928 b = (al & 0x0F) * (1.0f / 0x0F);
929 a = (al & 0xF0) * (1.0f / 0xF0);
930 }
931 break;
932 case FORMAT_L16:
933 r =
934 g =
935 b = *(unsigned short*)element * (1.0f / 0xFFFF);
936 break;
937 case FORMAT_A8L8:
938 r =
939 g =
940 b = ((unsigned char*)element)[0] * (1.0f / 0xFF);
941 a = ((unsigned char*)element)[1] * (1.0f / 0xFF);
942 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400943 case FORMAT_L16F:
944 r =
945 g =
946 b = *(half*)element;
947 break;
948 case FORMAT_A16L16F:
949 r =
950 g =
951 b = ((half*)element)[0];
952 a = ((half*)element)[1];
953 break;
954 case FORMAT_L32F:
955 r =
956 g =
957 b = *(float*)element;
958 break;
959 case FORMAT_A32L32F:
960 r =
961 g =
962 b = ((float*)element)[0];
963 a = ((float*)element)[1];
964 break;
965 case FORMAT_A16F:
966 a = *(half*)element;
967 break;
John Bauman89401822014-05-06 15:04:28 -0400968 case FORMAT_R16F:
969 r = *(half*)element;
970 break;
971 case FORMAT_G16R16F:
972 r = ((half*)element)[0];
973 g = ((half*)element)[1];
974 break;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -0500975 case FORMAT_X16B16G16R16F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500976 case FORMAT_X16B16G16R16F_UNSIGNED:
Nicolas Capens80594422015-06-09 16:42:56 -0400977 case FORMAT_B16G16R16F:
978 r = ((half*)element)[0];
979 g = ((half*)element)[1];
980 b = ((half*)element)[2];
981 break;
John Bauman89401822014-05-06 15:04:28 -0400982 case FORMAT_A16B16G16R16F:
983 r = ((half*)element)[0];
984 g = ((half*)element)[1];
985 b = ((half*)element)[2];
986 a = ((half*)element)[3];
987 break;
Nicolas Capens80594422015-06-09 16:42:56 -0400988 case FORMAT_A32F:
989 a = *(float*)element;
990 break;
John Bauman89401822014-05-06 15:04:28 -0400991 case FORMAT_R32F:
992 r = *(float*)element;
993 break;
994 case FORMAT_G32R32F:
995 r = ((float*)element)[0];
996 g = ((float*)element)[1];
997 break;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400998 case FORMAT_X32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500999 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capens80594422015-06-09 16:42:56 -04001000 case FORMAT_B32G32R32F:
1001 r = ((float*)element)[0];
1002 g = ((float*)element)[1];
1003 b = ((float*)element)[2];
1004 break;
John Bauman89401822014-05-06 15:04:28 -04001005 case FORMAT_A32B32G32R32F:
1006 r = ((float*)element)[0];
1007 g = ((float*)element)[1];
1008 b = ((float*)element)[2];
1009 a = ((float*)element)[3];
1010 break;
1011 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001012 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04001013 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04001014 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001015 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04001016 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04001017 r = *(float*)element;
1018 g = r;
1019 b = r;
1020 a = r;
1021 break;
1022 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001023 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman66b8ab22014-05-06 15:57:45 -04001024 r = 1.0f - *(float*)element;
John Bauman89401822014-05-06 15:04:28 -04001025 g = r;
1026 b = r;
1027 a = r;
1028 break;
1029 case FORMAT_S8:
1030 r = *(unsigned char*)element * (1.0f / 0xFF);
1031 break;
1032 default:
1033 ASSERT(false);
1034 }
1035
Nicolas Capens1efac522017-12-01 16:59:38 -05001036 if(isSRGBformat(format))
1037 {
1038 r = sRGBtoLinear(r);
1039 g = sRGBtoLinear(g);
1040 b = sRGBtoLinear(b);
1041 }
John Bauman89401822014-05-06 15:04:28 -04001042
1043 return Color<float>(r, g, b, a);
1044 }
1045
1046 Color<float> Surface::Buffer::sample(float x, float y, float z) const
1047 {
1048 x -= 0.5f;
1049 y -= 0.5f;
1050 z -= 0.5f;
1051
1052 int x0 = clamp((int)x, 0, width - 1);
1053 int x1 = (x0 + 1 >= width) ? x0 : x0 + 1;
1054
1055 int y0 = clamp((int)y, 0, height - 1);
1056 int y1 = (y0 + 1 >= height) ? y0 : y0 + 1;
1057
1058 int z0 = clamp((int)z, 0, depth - 1);
1059 int z1 = (z0 + 1 >= depth) ? z0 : z0 + 1;
1060
1061 Color<float> c000 = read(x0, y0, z0);
1062 Color<float> c100 = read(x1, y0, z0);
1063 Color<float> c010 = read(x0, y1, z0);
1064 Color<float> c110 = read(x1, y1, z0);
1065 Color<float> c001 = read(x0, y0, z1);
1066 Color<float> c101 = read(x1, y0, z1);
1067 Color<float> c011 = read(x0, y1, z1);
1068 Color<float> c111 = read(x1, y1, z1);
1069
1070 float fx = x - x0;
1071 float fy = y - y0;
1072 float fz = z - z0;
1073
1074 c000 *= (1 - fx) * (1 - fy) * (1 - fz);
1075 c100 *= fx * (1 - fy) * (1 - fz);
1076 c010 *= (1 - fx) * fy * (1 - fz);
1077 c110 *= fx * fy * (1 - fz);
1078 c001 *= (1 - fx) * (1 - fy) * fz;
1079 c101 *= fx * (1 - fy) * fz;
1080 c011 *= (1 - fx) * fy * fz;
1081 c111 *= fx * fy * fz;
1082
1083 return c000 + c100 + c010 + c110 + c001 + c101 + c011 + c111;
1084 }
1085
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001086 Color<float> Surface::Buffer::sample(float x, float y, int layer) const
John Bauman89401822014-05-06 15:04:28 -04001087 {
1088 x -= 0.5f;
1089 y -= 0.5f;
1090
1091 int x0 = clamp((int)x, 0, width - 1);
1092 int x1 = (x0 + 1 >= width) ? x0 : x0 + 1;
1093
1094 int y0 = clamp((int)y, 0, height - 1);
1095 int y1 = (y0 + 1 >= height) ? y0 : y0 + 1;
1096
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001097 Color<float> c00 = read(x0, y0, layer);
1098 Color<float> c10 = read(x1, y0, layer);
1099 Color<float> c01 = read(x0, y1, layer);
1100 Color<float> c11 = read(x1, y1, layer);
John Bauman89401822014-05-06 15:04:28 -04001101
1102 float fx = x - x0;
1103 float fy = y - y0;
1104
1105 c00 *= (1 - fx) * (1 - fy);
1106 c10 *= fx * (1 - fy);
1107 c01 *= (1 - fx) * fy;
1108 c11 *= fx * fy;
1109
1110 return c00 + c10 + c01 + c11;
1111 }
1112
John Bauman19bac1e2014-05-06 15:23:49 -04001113 void *Surface::Buffer::lockRect(int x, int y, int z, Lock lock)
John Bauman89401822014-05-06 15:04:28 -04001114 {
1115 this->lock = lock;
1116
1117 switch(lock)
1118 {
1119 case LOCK_UNLOCKED:
1120 case LOCK_READONLY:
Nicolas Capensae7756e2018-02-22 16:13:01 -05001121 case LOCK_UPDATE:
John Bauman89401822014-05-06 15:04:28 -04001122 break;
1123 case LOCK_WRITEONLY:
1124 case LOCK_READWRITE:
1125 case LOCK_DISCARD:
1126 dirty = true;
1127 break;
1128 default:
1129 ASSERT(false);
1130 }
1131
John Baumand4ae8632014-05-06 16:18:33 -04001132 if(buffer)
John Bauman89401822014-05-06 15:04:28 -04001133 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001134 x += border;
1135 y += border;
1136
John Baumand4ae8632014-05-06 16:18:33 -04001137 switch(format)
1138 {
John Baumand4ae8632014-05-06 16:18:33 -04001139 case FORMAT_DXT1:
John Baumand4ae8632014-05-06 16:18:33 -04001140 case FORMAT_ATI1:
Nicolas Capens22658242014-11-29 00:31:41 -05001141 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001142 case FORMAT_R11_EAC:
1143 case FORMAT_SIGNED_R11_EAC:
1144 case FORMAT_RGB8_ETC2:
1145 case FORMAT_SRGB8_ETC2:
1146 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1147 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Baumand4ae8632014-05-06 16:18:33 -04001148 return (unsigned char*)buffer + 8 * (x / 4) + (y / 4) * pitchB + z * sliceB;
Alexis Hetu460e41f2015-09-01 10:58:37 -04001149 case FORMAT_RG11_EAC:
1150 case FORMAT_SIGNED_RG11_EAC:
1151 case FORMAT_RGBA8_ETC2_EAC:
1152 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1153 case FORMAT_RGBA_ASTC_4x4_KHR:
1154 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1155 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1156 case FORMAT_RGBA_ASTC_5x4_KHR:
1157 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1158 return (unsigned char*)buffer + 16 * (x / 5) + (y / 4) * pitchB + z * sliceB;
1159 case FORMAT_RGBA_ASTC_5x5_KHR:
1160 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1161 return (unsigned char*)buffer + 16 * (x / 5) + (y / 5) * pitchB + z * sliceB;
1162 case FORMAT_RGBA_ASTC_6x5_KHR:
1163 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1164 return (unsigned char*)buffer + 16 * (x / 6) + (y / 5) * pitchB + z * sliceB;
1165 case FORMAT_RGBA_ASTC_6x6_KHR:
1166 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1167 return (unsigned char*)buffer + 16 * (x / 6) + (y / 6) * pitchB + z * sliceB;
1168 case FORMAT_RGBA_ASTC_8x5_KHR:
1169 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1170 return (unsigned char*)buffer + 16 * (x / 8) + (y / 5) * pitchB + z * sliceB;
1171 case FORMAT_RGBA_ASTC_8x6_KHR:
1172 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1173 return (unsigned char*)buffer + 16 * (x / 8) + (y / 6) * pitchB + z * sliceB;
1174 case FORMAT_RGBA_ASTC_8x8_KHR:
1175 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1176 return (unsigned char*)buffer + 16 * (x / 8) + (y / 8) * pitchB + z * sliceB;
1177 case FORMAT_RGBA_ASTC_10x5_KHR:
1178 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1179 return (unsigned char*)buffer + 16 * (x / 10) + (y / 5) * pitchB + z * sliceB;
1180 case FORMAT_RGBA_ASTC_10x6_KHR:
1181 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1182 return (unsigned char*)buffer + 16 * (x / 10) + (y / 6) * pitchB + z * sliceB;
1183 case FORMAT_RGBA_ASTC_10x8_KHR:
1184 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1185 return (unsigned char*)buffer + 16 * (x / 10) + (y / 8) * pitchB + z * sliceB;
1186 case FORMAT_RGBA_ASTC_10x10_KHR:
1187 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1188 return (unsigned char*)buffer + 16 * (x / 10) + (y / 10) * pitchB + z * sliceB;
1189 case FORMAT_RGBA_ASTC_12x10_KHR:
1190 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1191 return (unsigned char*)buffer + 16 * (x / 12) + (y / 10) * pitchB + z * sliceB;
1192 case FORMAT_RGBA_ASTC_12x12_KHR:
1193 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1194 return (unsigned char*)buffer + 16 * (x / 12) + (y / 12) * pitchB + z * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001195 case FORMAT_DXT3:
1196 case FORMAT_DXT5:
John Baumand4ae8632014-05-06 16:18:33 -04001197 case FORMAT_ATI2:
1198 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1199 default:
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001200 return (unsigned char*)buffer + x * bytes + y * pitchB + z * samples * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001201 }
John Bauman89401822014-05-06 15:04:28 -04001202 }
1203
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001204 return nullptr;
John Bauman89401822014-05-06 15:04:28 -04001205 }
1206
1207 void Surface::Buffer::unlockRect()
1208 {
1209 lock = LOCK_UNLOCKED;
1210 }
1211
Nicolas Capensf41f0332017-05-30 15:25:50 -04001212 class SurfaceImplementation : public Surface
1213 {
1214 public:
1215 SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1216 : Surface(width, height, depth, format, pixels, pitch, slice) {}
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001217 SurfaceImplementation(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0)
1218 : Surface(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchP) {}
Nicolas Capensf41f0332017-05-30 15:25:50 -04001219 ~SurfaceImplementation() override {};
1220
1221 void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override
1222 {
1223 return Surface::lockInternal(x, y, z, lock, client);
1224 }
1225
1226 void unlockInternal() override
1227 {
1228 Surface::unlockInternal();
1229 }
1230 };
1231
1232 Surface *Surface::create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1233 {
1234 return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice);
1235 }
1236
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001237 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 -04001238 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001239 return new SurfaceImplementation(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchPprovided);
Nicolas Capensf41f0332017-05-30 15:25:50 -04001240 }
1241
Nicolas Capens477314b2015-06-09 16:47:29 -04001242 Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
1243 {
1244 resource = new Resource(0);
1245 hasParent = false;
1246 ownExternal = false;
1247 depth = max(1, depth);
1248
1249 external.buffer = pixels;
1250 external.width = width;
1251 external.height = height;
1252 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001253 external.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001254 external.format = format;
1255 external.bytes = bytes(external.format);
1256 external.pitchB = pitch;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001257 external.pitchP = external.bytes ? pitch / external.bytes : 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001258 external.sliceB = slice;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001259 external.sliceP = external.bytes ? slice / external.bytes : 0;
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001260 external.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001261 external.lock = LOCK_UNLOCKED;
1262 external.dirty = true;
1263
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001264 internal.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001265 internal.width = width;
1266 internal.height = height;
1267 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001268 internal.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001269 internal.format = selectInternalFormat(format);
1270 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001271 internal.pitchB = pitchB(internal.width, 0, internal.format, false);
1272 internal.pitchP = pitchP(internal.width, 0, internal.format, false);
1273 internal.sliceB = sliceB(internal.width, internal.height, 0, internal.format, false);
1274 internal.sliceP = sliceP(internal.width, internal.height, 0, internal.format, false);
1275 internal.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001276 internal.lock = LOCK_UNLOCKED;
1277 internal.dirty = false;
1278
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001279 stencil.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001280 stencil.width = width;
1281 stencil.height = height;
1282 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001283 stencil.samples = 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001284 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
Nicolas Capens477314b2015-06-09 16:47:29 -04001285 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001286 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, false);
1287 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, false);
1288 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, false);
1289 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, false);
1290 stencil.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001291 stencil.lock = LOCK_UNLOCKED;
1292 stencil.dirty = false;
1293
Nicolas Capens73e18c12017-11-28 13:31:35 -05001294 dirtyContents = true;
Nicolas Capens477314b2015-06-09 16:47:29 -04001295 paletteUsed = 0;
1296 }
1297
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001298 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 -04001299 {
1300 resource = texture ? texture : new Resource(0);
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001301 hasParent = texture != nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001302 ownExternal = true;
John Bauman89401822014-05-06 15:04:28 -04001303 depth = max(1, depth);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001304 samples = max(1, samples);
John Bauman89401822014-05-06 15:04:28 -04001305
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001306 external.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001307 external.width = width;
1308 external.height = height;
1309 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001310 external.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001311 external.format = format;
1312 external.bytes = bytes(external.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001313 external.pitchB = pitchB(external.width, 0, external.format, renderTarget && !texture);
1314 external.pitchP = pitchP(external.width, 0, external.format, renderTarget && !texture);
1315 external.sliceB = sliceB(external.width, external.height, 0, external.format, renderTarget && !texture);
1316 external.sliceP = sliceP(external.width, external.height, 0, external.format, renderTarget && !texture);
1317 external.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001318 external.lock = LOCK_UNLOCKED;
1319 external.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001320
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001321 internal.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001322 internal.width = width;
1323 internal.height = height;
1324 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001325 internal.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001326 internal.format = selectInternalFormat(format);
1327 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001328 internal.pitchB = !pitchPprovided ? pitchB(internal.width, border, internal.format, renderTarget) : pitchPprovided * internal.bytes;
1329 internal.pitchP = !pitchPprovided ? pitchP(internal.width, border, internal.format, renderTarget) : pitchPprovided;
1330 internal.sliceB = sliceB(internal.width, internal.height, border, internal.format, renderTarget);
1331 internal.sliceP = sliceP(internal.width, internal.height, border, internal.format, renderTarget);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001332 internal.border = (short)border;
John Bauman89401822014-05-06 15:04:28 -04001333 internal.lock = LOCK_UNLOCKED;
1334 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001335
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001336 stencil.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001337 stencil.width = width;
1338 stencil.height = height;
1339 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001340 stencil.samples = (short)samples;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001341 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
John Bauman89401822014-05-06 15:04:28 -04001342 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001343 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, renderTarget);
1344 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, renderTarget);
1345 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1346 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1347 stencil.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001348 stencil.lock = LOCK_UNLOCKED;
1349 stencil.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001350
Nicolas Capens73e18c12017-11-28 13:31:35 -05001351 dirtyContents = true;
John Bauman66b8ab22014-05-06 15:57:45 -04001352 paletteUsed = 0;
John Bauman89401822014-05-06 15:04:28 -04001353 }
1354
1355 Surface::~Surface()
1356 {
Nicolas Capensbf7a8142017-05-19 10:57:28 -04001357 // sync() must be called before this destructor to ensure all locks have been released.
1358 // We can't call it here because the parent resource may already have been destroyed.
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001359 ASSERT(isUnlocked());
John Bauman8a4f6fc2014-05-06 15:26:18 -04001360
John Bauman89401822014-05-06 15:04:28 -04001361 if(!hasParent)
1362 {
1363 resource->destruct();
1364 }
1365
Nicolas Capens477314b2015-06-09 16:47:29 -04001366 if(ownExternal)
1367 {
1368 deallocate(external.buffer);
1369 }
John Bauman89401822014-05-06 15:04:28 -04001370
1371 if(internal.buffer != external.buffer)
1372 {
1373 deallocate(internal.buffer);
1374 }
1375
1376 deallocate(stencil.buffer);
1377
1378 external.buffer = 0;
1379 internal.buffer = 0;
1380 stencil.buffer = 0;
1381 }
1382
John Bauman19bac1e2014-05-06 15:23:49 -04001383 void *Surface::lockExternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001384 {
1385 resource->lock(client);
1386
1387 if(!external.buffer)
1388 {
1389 if(internal.buffer && identicalFormats())
1390 {
1391 external.buffer = internal.buffer;
1392 }
1393 else
1394 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001395 external.buffer = allocateBuffer(external.width, external.height, external.depth, external.border, external.samples, external.format);
John Bauman89401822014-05-06 15:04:28 -04001396 }
1397 }
1398
1399 if(internal.dirty)
1400 {
1401 if(lock != LOCK_DISCARD)
1402 {
1403 update(external, internal);
1404 }
John Bauman66b8ab22014-05-06 15:57:45 -04001405
1406 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001407 }
1408
1409 switch(lock)
1410 {
1411 case LOCK_READONLY:
1412 break;
1413 case LOCK_WRITEONLY:
1414 case LOCK_READWRITE:
1415 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001416 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001417 break;
1418 default:
1419 ASSERT(false);
1420 }
1421
John Bauman19bac1e2014-05-06 15:23:49 -04001422 return external.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001423 }
1424
1425 void Surface::unlockExternal()
1426 {
John Bauman89401822014-05-06 15:04:28 -04001427 external.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001428
1429 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001430 }
1431
John Bauman19bac1e2014-05-06 15:23:49 -04001432 void *Surface::lockInternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001433 {
1434 if(lock != LOCK_UNLOCKED)
1435 {
1436 resource->lock(client);
1437 }
1438
1439 if(!internal.buffer)
1440 {
1441 if(external.buffer && identicalFormats())
1442 {
1443 internal.buffer = external.buffer;
1444 }
1445 else
1446 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001447 internal.buffer = allocateBuffer(internal.width, internal.height, internal.depth, internal.border, internal.samples, internal.format);
John Bauman89401822014-05-06 15:04:28 -04001448 }
1449 }
1450
1451 // FIXME: WHQL requires conversion to lower external precision and back
1452 if(logPrecision >= WHQL)
1453 {
1454 if(internal.dirty && renderTarget && internal.format != external.format)
1455 {
1456 if(lock != LOCK_DISCARD)
1457 {
1458 switch(external.format)
1459 {
1460 case FORMAT_R3G3B2:
1461 case FORMAT_A8R3G3B2:
1462 case FORMAT_A1R5G5B5:
1463 case FORMAT_A2R10G10B10:
1464 case FORMAT_A2B10G10R10:
1465 lockExternal(0, 0, 0, LOCK_READWRITE, client);
1466 unlockExternal();
1467 break;
1468 default:
1469 // Difference passes WHQL
1470 break;
1471 }
1472 }
1473 }
1474 }
1475
John Bauman66b8ab22014-05-06 15:57:45 -04001476 if(external.dirty || (isPalette(external.format) && paletteUsed != Surface::paletteID))
John Bauman89401822014-05-06 15:04:28 -04001477 {
1478 if(lock != LOCK_DISCARD)
1479 {
1480 update(internal, external);
1481 }
John Bauman89401822014-05-06 15:04:28 -04001482
John Bauman66b8ab22014-05-06 15:57:45 -04001483 external.dirty = false;
1484 paletteUsed = Surface::paletteID;
John Bauman89401822014-05-06 15:04:28 -04001485 }
1486
1487 switch(lock)
1488 {
1489 case LOCK_UNLOCKED:
1490 case LOCK_READONLY:
1491 break;
1492 case LOCK_WRITEONLY:
1493 case LOCK_READWRITE:
1494 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001495 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001496 break;
1497 default:
1498 ASSERT(false);
1499 }
1500
1501 if(lock == LOCK_READONLY && client == PUBLIC)
1502 {
1503 resolve();
1504 }
1505
John Bauman19bac1e2014-05-06 15:23:49 -04001506 return internal.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001507 }
1508
1509 void Surface::unlockInternal()
1510 {
John Bauman89401822014-05-06 15:04:28 -04001511 internal.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001512
1513 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001514 }
1515
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001516 void *Surface::lockStencil(int x, int y, int front, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001517 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05001518 if(stencil.format == FORMAT_NULL)
1519 {
1520 return nullptr;
1521 }
1522
John Bauman89401822014-05-06 15:04:28 -04001523 resource->lock(client);
1524
1525 if(!stencil.buffer)
1526 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001527 stencil.buffer = allocateBuffer(stencil.width, stencil.height, stencil.depth, stencil.border, stencil.samples, stencil.format);
John Bauman89401822014-05-06 15:04:28 -04001528 }
1529
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001530 return stencil.lockRect(x, y, front, LOCK_READWRITE); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001531 }
1532
1533 void Surface::unlockStencil()
1534 {
John Bauman89401822014-05-06 15:04:28 -04001535 stencil.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001536
1537 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001538 }
1539
1540 int Surface::bytes(Format format)
1541 {
1542 switch(format)
1543 {
1544 case FORMAT_NULL: return 0;
1545 case FORMAT_P8: return 1;
1546 case FORMAT_A8P8: return 2;
1547 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001548 case FORMAT_R8I: return 1;
John Bauman89401822014-05-06 15:04:28 -04001549 case FORMAT_R8: return 1;
1550 case FORMAT_R3G3B2: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001551 case FORMAT_R16I: return 2;
1552 case FORMAT_R16UI: return 2;
John Bauman89401822014-05-06 15:04:28 -04001553 case FORMAT_A8R3G3B2: return 2;
1554 case FORMAT_R5G6B5: return 2;
1555 case FORMAT_A1R5G5B5: return 2;
1556 case FORMAT_X1R5G5B5: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001557 case FORMAT_R5G5B5A1: return 2;
John Bauman89401822014-05-06 15:04:28 -04001558 case FORMAT_X4R4G4B4: return 2;
1559 case FORMAT_A4R4G4B4: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001560 case FORMAT_R4G4B4A4: return 2;
John Bauman89401822014-05-06 15:04:28 -04001561 case FORMAT_R8G8B8: return 3;
Nicolas Capens80594422015-06-09 16:42:56 -04001562 case FORMAT_B8G8R8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001563 case FORMAT_R32I: return 4;
1564 case FORMAT_R32UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001565 case FORMAT_X8R8G8B8: return 4;
1566 // case FORMAT_X8G8R8B8Q: return 4;
1567 case FORMAT_A8R8G8B8: return 4;
1568 // case FORMAT_A8G8R8B8Q: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001569 case FORMAT_X8B8G8R8I: return 4;
John Bauman89401822014-05-06 15:04:28 -04001570 case FORMAT_X8B8G8R8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04001571 case FORMAT_SRGB8_X8: return 4;
1572 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001573 case FORMAT_A8B8G8R8I: return 4;
1574 case FORMAT_R8UI: return 1;
1575 case FORMAT_G8R8UI: return 2;
1576 case FORMAT_X8B8G8R8UI: return 4;
1577 case FORMAT_A8B8G8R8UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001578 case FORMAT_A8B8G8R8: return 4;
Nicolas Capens975adb72017-12-19 15:34:20 -05001579 case FORMAT_R8_SNORM: return 1;
1580 case FORMAT_G8R8_SNORM: return 2;
1581 case FORMAT_X8B8G8R8_SNORM: return 4;
1582 case FORMAT_A8B8G8R8_SNORM: return 4;
John Bauman89401822014-05-06 15:04:28 -04001583 case FORMAT_A2R10G10B10: return 4;
1584 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05001585 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001586 case FORMAT_G8R8I: return 2;
John Bauman89401822014-05-06 15:04:28 -04001587 case FORMAT_G8R8: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001588 case FORMAT_G16R16I: return 4;
1589 case FORMAT_G16R16UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001590 case FORMAT_G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001591 case FORMAT_G32R32I: return 8;
1592 case FORMAT_G32R32UI: return 8;
1593 case FORMAT_X16B16G16R16I: return 8;
1594 case FORMAT_X16B16G16R16UI: return 8;
1595 case FORMAT_A16B16G16R16I: return 8;
1596 case FORMAT_A16B16G16R16UI: return 8;
John Bauman89401822014-05-06 15:04:28 -04001597 case FORMAT_A16B16G16R16: return 8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001598 case FORMAT_X32B32G32R32I: return 16;
1599 case FORMAT_X32B32G32R32UI: return 16;
1600 case FORMAT_A32B32G32R32I: return 16;
1601 case FORMAT_A32B32G32R32UI: return 16;
John Bauman89401822014-05-06 15:04:28 -04001602 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04001603 case FORMAT_DXT1: return 2; // Column of four pixels
1604 case FORMAT_DXT3: return 4; // Column of four pixels
1605 case FORMAT_DXT5: return 4; // Column of four pixels
1606 case FORMAT_ATI1: return 2; // Column of four pixels
1607 case FORMAT_ATI2: return 4; // Column of four pixels
Nicolas Capens22658242014-11-29 00:31:41 -05001608 case FORMAT_ETC1: return 2; // Column of four pixels
Alexis Hetu460e41f2015-09-01 10:58:37 -04001609 case FORMAT_R11_EAC: return 2;
1610 case FORMAT_SIGNED_R11_EAC: return 2;
1611 case FORMAT_RG11_EAC: return 4;
1612 case FORMAT_SIGNED_RG11_EAC: return 4;
1613 case FORMAT_RGB8_ETC2: return 2;
1614 case FORMAT_SRGB8_ETC2: return 2;
1615 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1616 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1617 case FORMAT_RGBA8_ETC2_EAC: return 4;
1618 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: return 4;
1619 case FORMAT_RGBA_ASTC_4x4_KHR:
1620 case FORMAT_RGBA_ASTC_5x4_KHR:
1621 case FORMAT_RGBA_ASTC_5x5_KHR:
1622 case FORMAT_RGBA_ASTC_6x5_KHR:
1623 case FORMAT_RGBA_ASTC_6x6_KHR:
1624 case FORMAT_RGBA_ASTC_8x5_KHR:
1625 case FORMAT_RGBA_ASTC_8x6_KHR:
1626 case FORMAT_RGBA_ASTC_8x8_KHR:
1627 case FORMAT_RGBA_ASTC_10x5_KHR:
1628 case FORMAT_RGBA_ASTC_10x6_KHR:
1629 case FORMAT_RGBA_ASTC_10x8_KHR:
1630 case FORMAT_RGBA_ASTC_10x10_KHR:
1631 case FORMAT_RGBA_ASTC_12x10_KHR:
1632 case FORMAT_RGBA_ASTC_12x12_KHR:
1633 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1634 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1635 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1636 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1637 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1638 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1639 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1640 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1641 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1642 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1643 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1644 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1645 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1646 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR: return 0; // FIXME
John Bauman89401822014-05-06 15:04:28 -04001647 // Bumpmap formats
1648 case FORMAT_V8U8: return 2;
1649 case FORMAT_L6V5U5: return 2;
1650 case FORMAT_Q8W8V8U8: return 4;
1651 case FORMAT_X8L8V8U8: return 4;
1652 case FORMAT_A2W10V10U10: return 4;
1653 case FORMAT_V16U16: return 4;
1654 case FORMAT_A16W16V16U16: return 8;
1655 case FORMAT_Q16W16V16U16: return 8;
1656 // Luminance formats
1657 case FORMAT_L8: return 1;
1658 case FORMAT_A4L4: return 1;
1659 case FORMAT_L16: return 2;
1660 case FORMAT_A8L8: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001661 case FORMAT_L16F: return 2;
1662 case FORMAT_A16L16F: return 4;
1663 case FORMAT_L32F: return 4;
1664 case FORMAT_A32L32F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001665 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04001666 case FORMAT_A16F: return 2;
John Bauman89401822014-05-06 15:04:28 -04001667 case FORMAT_R16F: return 2;
1668 case FORMAT_G16R16F: return 4;
Nicolas Capens80594422015-06-09 16:42:56 -04001669 case FORMAT_B16G16R16F: return 6;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05001670 case FORMAT_X16B16G16R16F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001671 case FORMAT_A16B16G16R16F: return 8;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001672 case FORMAT_X16B16G16R16F_UNSIGNED: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001673 case FORMAT_A32F: return 4;
John Bauman89401822014-05-06 15:04:28 -04001674 case FORMAT_R32F: return 4;
1675 case FORMAT_G32R32F: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001676 case FORMAT_B32G32R32F: return 12;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04001677 case FORMAT_X32B32G32R32F: return 16;
John Bauman89401822014-05-06 15:04:28 -04001678 case FORMAT_A32B32G32R32F: return 16;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001679 case FORMAT_X32B32G32R32F_UNSIGNED: return 16;
John Bauman89401822014-05-06 15:04:28 -04001680 // Depth/stencil formats
1681 case FORMAT_D16: return 2;
1682 case FORMAT_D32: return 4;
1683 case FORMAT_D24X8: return 4;
1684 case FORMAT_D24S8: return 4;
1685 case FORMAT_D24FS8: return 4;
1686 case FORMAT_D32F: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001687 case FORMAT_D32FS8: return 4;
John Bauman89401822014-05-06 15:04:28 -04001688 case FORMAT_D32F_COMPLEMENTARY: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001689 case FORMAT_D32FS8_COMPLEMENTARY: return 4;
John Bauman89401822014-05-06 15:04:28 -04001690 case FORMAT_D32F_LOCKABLE: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001691 case FORMAT_D32FS8_TEXTURE: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001692 case FORMAT_D32F_SHADOW: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001693 case FORMAT_D32FS8_SHADOW: return 4;
1694 case FORMAT_DF24S8: return 4;
1695 case FORMAT_DF16S8: return 2;
John Bauman89401822014-05-06 15:04:28 -04001696 case FORMAT_INTZ: return 4;
1697 case FORMAT_S8: return 1;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001698 case FORMAT_YV12_BT601: return 1; // Y plane only
1699 case FORMAT_YV12_BT709: return 1; // Y plane only
1700 case FORMAT_YV12_JFIF: return 1; // Y plane only
John Bauman89401822014-05-06 15:04:28 -04001701 default:
1702 ASSERT(false);
1703 }
1704
1705 return 0;
1706 }
1707
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001708 int Surface::pitchB(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001709 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001710 width += 2 * border;
1711
John Bauman89401822014-05-06 15:04:28 -04001712 if(target || isDepth(format) || isStencil(format))
1713 {
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001714 width = align(width, 2);
John Bauman89401822014-05-06 15:04:28 -04001715 }
1716
1717 switch(format)
1718 {
John Bauman89401822014-05-06 15:04:28 -04001719 case FORMAT_DXT1:
Nicolas Capens22658242014-11-29 00:31:41 -05001720 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001721 case FORMAT_R11_EAC:
1722 case FORMAT_SIGNED_R11_EAC:
1723 case FORMAT_RGB8_ETC2:
1724 case FORMAT_SRGB8_ETC2:
1725 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1726 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Bauman89401822014-05-06 15:04:28 -04001727 return 8 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001728 case FORMAT_RG11_EAC:
1729 case FORMAT_SIGNED_RG11_EAC:
1730 case FORMAT_RGBA8_ETC2_EAC:
1731 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1732 case FORMAT_RGBA_ASTC_4x4_KHR:
1733 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1734 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1735 case FORMAT_RGBA_ASTC_5x4_KHR:
1736 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1737 case FORMAT_RGBA_ASTC_5x5_KHR:
1738 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1739 return 16 * ((width + 4) / 5);
1740 case FORMAT_RGBA_ASTC_6x5_KHR:
1741 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1742 case FORMAT_RGBA_ASTC_6x6_KHR:
1743 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1744 return 16 * ((width + 5) / 6);
1745 case FORMAT_RGBA_ASTC_8x5_KHR:
1746 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1747 case FORMAT_RGBA_ASTC_8x6_KHR:
1748 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1749 case FORMAT_RGBA_ASTC_8x8_KHR:
1750 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1751 return 16 * ((width + 7) / 8);
1752 case FORMAT_RGBA_ASTC_10x5_KHR:
1753 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1754 case FORMAT_RGBA_ASTC_10x6_KHR:
1755 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1756 case FORMAT_RGBA_ASTC_10x8_KHR:
1757 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1758 case FORMAT_RGBA_ASTC_10x10_KHR:
1759 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1760 return 16 * ((width + 9) / 10);
1761 case FORMAT_RGBA_ASTC_12x10_KHR:
1762 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1763 case FORMAT_RGBA_ASTC_12x12_KHR:
1764 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1765 return 16 * ((width + 11) / 12);
John Bauman89401822014-05-06 15:04:28 -04001766 case FORMAT_DXT3:
1767 case FORMAT_DXT5:
1768 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1769 case FORMAT_ATI1:
1770 return 2 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per row
1771 case FORMAT_ATI2:
1772 return 4 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per row
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001773 case FORMAT_YV12_BT601:
1774 case FORMAT_YV12_BT709:
1775 case FORMAT_YV12_JFIF:
1776 return align(width, 16);
John Bauman89401822014-05-06 15:04:28 -04001777 default:
1778 return bytes(format) * width;
1779 }
1780 }
1781
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001782 int Surface::pitchP(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001783 {
1784 int B = bytes(format);
1785
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001786 return B > 0 ? pitchB(width, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001787 }
1788
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001789 int Surface::sliceB(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001790 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001791 height += 2 * border;
1792
John Bauman89401822014-05-06 15:04:28 -04001793 if(target || isDepth(format) || isStencil(format))
1794 {
1795 height = ((height + 1) & ~1);
1796 }
1797
1798 switch(format)
1799 {
John Bauman89401822014-05-06 15:04:28 -04001800 case FORMAT_DXT1:
1801 case FORMAT_DXT3:
1802 case FORMAT_DXT5:
Nicolas Capens22658242014-11-29 00:31:41 -05001803 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001804 case FORMAT_R11_EAC:
1805 case FORMAT_SIGNED_R11_EAC:
1806 case FORMAT_RG11_EAC:
1807 case FORMAT_SIGNED_RG11_EAC:
1808 case FORMAT_RGB8_ETC2:
1809 case FORMAT_SRGB8_ETC2:
1810 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1811 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1812 case FORMAT_RGBA8_ETC2_EAC:
1813 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1814 case FORMAT_RGBA_ASTC_4x4_KHR:
1815 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1816 case FORMAT_RGBA_ASTC_5x4_KHR:
1817 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001818 return pitchB(width, border, format, target) * ((height + 3) / 4); // Pitch computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001819 case FORMAT_RGBA_ASTC_5x5_KHR:
1820 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1821 case FORMAT_RGBA_ASTC_6x5_KHR:
1822 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1823 case FORMAT_RGBA_ASTC_8x5_KHR:
1824 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1825 case FORMAT_RGBA_ASTC_10x5_KHR:
1826 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001827 return pitchB(width, border, format, target) * ((height + 4) / 5); // Pitch computed per 5 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001828 case FORMAT_RGBA_ASTC_6x6_KHR:
1829 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1830 case FORMAT_RGBA_ASTC_8x6_KHR:
1831 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1832 case FORMAT_RGBA_ASTC_10x6_KHR:
1833 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001834 return pitchB(width, border, format, target) * ((height + 5) / 6); // Pitch computed per 6 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001835 case FORMAT_RGBA_ASTC_8x8_KHR:
1836 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1837 case FORMAT_RGBA_ASTC_10x8_KHR:
1838 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001839 return pitchB(width, border, format, target) * ((height + 7) / 8); // Pitch computed per 8 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001840 case FORMAT_RGBA_ASTC_10x10_KHR:
1841 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1842 case FORMAT_RGBA_ASTC_12x10_KHR:
1843 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001844 return pitchB(width, border, format, target) * ((height + 9) / 10); // Pitch computed per 10 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001845 case FORMAT_RGBA_ASTC_12x12_KHR:
1846 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001847 return pitchB(width, border, format, target) * ((height + 11) / 12); // Pitch computed per 12 rows
Nicolas Capens22658242014-11-29 00:31:41 -05001848 case FORMAT_ATI1:
1849 case FORMAT_ATI2:
John Bauman89401822014-05-06 15:04:28 -04001850 default:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001851 return pitchB(width, border, format, target) * height; // Pitch computed per row
John Bauman89401822014-05-06 15:04:28 -04001852 }
1853 }
1854
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001855 int Surface::sliceP(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001856 {
1857 int B = bytes(format);
1858
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001859 return B > 0 ? sliceB(width, height, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001860 }
1861
1862 void Surface::update(Buffer &destination, Buffer &source)
1863 {
1864 // ASSERT(source.lock != LOCK_UNLOCKED);
1865 // ASSERT(destination.lock != LOCK_UNLOCKED);
Nicolas Capensc39901e2016-03-21 16:37:44 -04001866
John Bauman89401822014-05-06 15:04:28 -04001867 if(destination.buffer != source.buffer)
1868 {
1869 ASSERT(source.dirty && !destination.dirty);
1870
1871 switch(source.format)
1872 {
1873 case FORMAT_R8G8B8: decodeR8G8B8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001874 case FORMAT_X1R5G5B5: decodeX1R5G5B5(destination, source); break; // FIXME: Check destination format
1875 case FORMAT_A1R5G5B5: decodeA1R5G5B5(destination, source); break; // FIXME: Check destination format
1876 case FORMAT_X4R4G4B4: decodeX4R4G4B4(destination, source); break; // FIXME: Check destination format
1877 case FORMAT_A4R4G4B4: decodeA4R4G4B4(destination, source); break; // FIXME: Check destination format
1878 case FORMAT_P8: decodeP8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001879 case FORMAT_DXT1: decodeDXT1(destination, source); break; // FIXME: Check destination format
1880 case FORMAT_DXT3: decodeDXT3(destination, source); break; // FIXME: Check destination format
1881 case FORMAT_DXT5: decodeDXT5(destination, source); break; // FIXME: Check destination format
1882 case FORMAT_ATI1: decodeATI1(destination, source); break; // FIXME: Check destination format
1883 case FORMAT_ATI2: decodeATI2(destination, source); break; // FIXME: Check destination format
Alexis Hetu460e41f2015-09-01 10:58:37 -04001884 case FORMAT_R11_EAC: decodeEAC(destination, source, 1, false); break; // FIXME: Check destination format
1885 case FORMAT_SIGNED_R11_EAC: decodeEAC(destination, source, 1, true); break; // FIXME: Check destination format
1886 case FORMAT_RG11_EAC: decodeEAC(destination, source, 2, false); break; // FIXME: Check destination format
1887 case FORMAT_SIGNED_RG11_EAC: decodeEAC(destination, source, 2, true); break; // FIXME: Check destination format
Alexis Hetu0de50d42015-09-09 13:56:41 -04001888 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001889 case FORMAT_RGB8_ETC2: decodeETC2(destination, source, 0, false); break; // FIXME: Check destination format
1890 case FORMAT_SRGB8_ETC2: decodeETC2(destination, source, 0, true); break; // FIXME: Check destination format
1891 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, false); break; // FIXME: Check destination format
1892 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, true); break; // FIXME: Check destination format
1893 case FORMAT_RGBA8_ETC2_EAC: decodeETC2(destination, source, 8, false); break; // FIXME: Check destination format
1894 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: decodeETC2(destination, source, 8, true); break; // FIXME: Check destination format
1895 case FORMAT_RGBA_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, false); break; // FIXME: Check destination format
1896 case FORMAT_RGBA_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, false); break; // FIXME: Check destination format
1897 case FORMAT_RGBA_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, false); break; // FIXME: Check destination format
1898 case FORMAT_RGBA_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, false); break; // FIXME: Check destination format
1899 case FORMAT_RGBA_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, false); break; // FIXME: Check destination format
1900 case FORMAT_RGBA_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, false); break; // FIXME: Check destination format
1901 case FORMAT_RGBA_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, false); break; // FIXME: Check destination format
1902 case FORMAT_RGBA_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, false); break; // FIXME: Check destination format
1903 case FORMAT_RGBA_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, false); break; // FIXME: Check destination format
1904 case FORMAT_RGBA_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, false); break; // FIXME: Check destination format
1905 case FORMAT_RGBA_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, false); break; // FIXME: Check destination format
1906 case FORMAT_RGBA_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, false); break; // FIXME: Check destination format
1907 case FORMAT_RGBA_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, false); break; // FIXME: Check destination format
1908 case FORMAT_RGBA_ASTC_12x12_KHR: decodeASTC(destination, source, 12, 12, 1, false); break; // FIXME: Check destination format
1909 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, true); break; // FIXME: Check destination format
1910 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, true); break; // FIXME: Check destination format
1911 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, true); break; // FIXME: Check destination format
1912 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, true); break; // FIXME: Check destination format
1913 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, true); break; // FIXME: Check destination format
1914 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, true); break; // FIXME: Check destination format
1915 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, true); break; // FIXME: Check destination format
1916 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, true); break; // FIXME: Check destination format
1917 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, true); break; // FIXME: Check destination format
1918 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, true); break; // FIXME: Check destination format
1919 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, true); break; // FIXME: Check destination format
1920 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, true); break; // FIXME: Check destination format
1921 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, true); break; // FIXME: Check destination format
1922 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 -04001923 default: genericUpdate(destination, source); break;
1924 }
1925 }
John Bauman89401822014-05-06 15:04:28 -04001926 }
1927
1928 void Surface::genericUpdate(Buffer &destination, Buffer &source)
1929 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001930 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05001931 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04001932
1933 int depth = min(destination.depth, source.depth);
1934 int height = min(destination.height, source.height);
1935 int width = min(destination.width, source.width);
1936 int rowBytes = width * source.bytes;
1937
1938 for(int z = 0; z < depth; z++)
1939 {
1940 unsigned char *sourceRow = sourceSlice;
1941 unsigned char *destinationRow = destinationSlice;
1942
1943 for(int y = 0; y < height; y++)
1944 {
1945 if(source.format == destination.format)
1946 {
1947 memcpy(destinationRow, sourceRow, rowBytes);
1948 }
1949 else
1950 {
1951 unsigned char *sourceElement = sourceRow;
1952 unsigned char *destinationElement = destinationRow;
1953
1954 for(int x = 0; x < width; x++)
1955 {
1956 Color<float> color = source.read(sourceElement);
1957 destination.write(destinationElement, color);
1958
1959 sourceElement += source.bytes;
1960 destinationElement += destination.bytes;
1961 }
1962 }
1963
1964 sourceRow += source.pitchB;
1965 destinationRow += destination.pitchB;
1966 }
1967
1968 sourceSlice += source.sliceB;
1969 destinationSlice += destination.sliceB;
1970 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001971
1972 source.unlockRect();
1973 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04001974 }
1975
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001976 void Surface::decodeR8G8B8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04001977 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001978 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05001979 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04001980
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001981 int depth = min(destination.depth, source.depth);
1982 int height = min(destination.height, source.height);
1983 int width = min(destination.width, source.width);
1984
1985 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04001986 {
1987 unsigned char *sourceRow = sourceSlice;
1988 unsigned char *destinationRow = destinationSlice;
1989
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001990 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04001991 {
1992 unsigned char *sourceElement = sourceRow;
1993 unsigned char *destinationElement = destinationRow;
1994
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001995 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04001996 {
1997 unsigned int b = sourceElement[0];
1998 unsigned int g = sourceElement[1];
1999 unsigned int r = sourceElement[2];
2000
2001 *(unsigned int*)destinationElement = 0xFF000000 | (r << 16) | (g << 8) | (b << 0);
2002
2003 sourceElement += source.bytes;
2004 destinationElement += destination.bytes;
2005 }
2006
2007 sourceRow += source.pitchB;
2008 destinationRow += destination.pitchB;
2009 }
2010
2011 sourceSlice += source.sliceB;
2012 destinationSlice += destination.sliceB;
2013 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002014
2015 source.unlockRect();
2016 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002017 }
2018
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002019 void Surface::decodeX1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002020 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002021 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002022 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002023
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002024 int depth = min(destination.depth, source.depth);
2025 int height = min(destination.height, source.height);
2026 int width = min(destination.width, source.width);
2027
2028 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002029 {
2030 unsigned char *sourceRow = sourceSlice;
2031 unsigned char *destinationRow = destinationSlice;
2032
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002033 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002034 {
2035 unsigned char *sourceElement = sourceRow;
2036 unsigned char *destinationElement = destinationRow;
2037
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002038 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002039 {
2040 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002041
John Bauman89401822014-05-06 15:04:28 -04002042 unsigned int r = (((xrgb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2043 unsigned int g = (((xrgb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2044 unsigned int b = (((xrgb & 0x001F) * 2106 + 0x80) >> 8);
2045
2046 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2047
2048 sourceElement += source.bytes;
2049 destinationElement += destination.bytes;
2050 }
2051
2052 sourceRow += source.pitchB;
2053 destinationRow += destination.pitchB;
2054 }
2055
2056 sourceSlice += source.sliceB;
2057 destinationSlice += destination.sliceB;
2058 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002059
2060 source.unlockRect();
2061 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002062 }
2063
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002064 void Surface::decodeA1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002065 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002066 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002067 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002068
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002069 int depth = min(destination.depth, source.depth);
2070 int height = min(destination.height, source.height);
2071 int width = min(destination.width, source.width);
2072
2073 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002074 {
2075 unsigned char *sourceRow = sourceSlice;
2076 unsigned char *destinationRow = destinationSlice;
2077
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002078 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002079 {
2080 unsigned char *sourceElement = sourceRow;
2081 unsigned char *destinationElement = destinationRow;
2082
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002083 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002084 {
2085 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002086
John Bauman89401822014-05-06 15:04:28 -04002087 unsigned int a = (argb & 0x8000) * 130560;
2088 unsigned int r = (((argb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2089 unsigned int g = (((argb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2090 unsigned int b = (((argb & 0x001F) * 2106 + 0x80) >> 8);
2091
2092 *(unsigned int*)destinationElement = a | r | g | b;
2093
2094 sourceElement += source.bytes;
2095 destinationElement += destination.bytes;
2096 }
2097
2098 sourceRow += source.pitchB;
2099 destinationRow += destination.pitchB;
2100 }
2101
2102 sourceSlice += source.sliceB;
2103 destinationSlice += destination.sliceB;
2104 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002105
2106 source.unlockRect();
2107 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002108 }
2109
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002110 void Surface::decodeX4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002111 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002112 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002113 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002114
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002115 int depth = min(destination.depth, source.depth);
2116 int height = min(destination.height, source.height);
2117 int width = min(destination.width, source.width);
2118
2119 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002120 {
2121 unsigned char *sourceRow = sourceSlice;
2122 unsigned char *destinationRow = destinationSlice;
2123
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002124 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002125 {
2126 unsigned char *sourceElement = sourceRow;
2127 unsigned char *destinationElement = destinationRow;
2128
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002129 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002130 {
2131 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002132
John Bauman89401822014-05-06 15:04:28 -04002133 unsigned int r = ((xrgb & 0x0F00) * 0x00001100) & 0x00FF0000;
2134 unsigned int g = ((xrgb & 0x00F0) * 0x00000110) & 0x0000FF00;
2135 unsigned int b = (xrgb & 0x000F) * 0x00000011;
2136
2137 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2138
2139 sourceElement += source.bytes;
2140 destinationElement += destination.bytes;
2141 }
2142
2143 sourceRow += source.pitchB;
2144 destinationRow += destination.pitchB;
2145 }
2146
2147 sourceSlice += source.sliceB;
2148 destinationSlice += destination.sliceB;
2149 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002150
2151 source.unlockRect();
2152 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002153 }
2154
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002155 void Surface::decodeA4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002156 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002157 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002158 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002159
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002160 int depth = min(destination.depth, source.depth);
2161 int height = min(destination.height, source.height);
2162 int width = min(destination.width, source.width);
2163
2164 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002165 {
2166 unsigned char *sourceRow = sourceSlice;
2167 unsigned char *destinationRow = destinationSlice;
2168
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002169 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002170 {
2171 unsigned char *sourceElement = sourceRow;
2172 unsigned char *destinationElement = destinationRow;
2173
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002174 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002175 {
2176 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002177
John Bauman89401822014-05-06 15:04:28 -04002178 unsigned int a = ((argb & 0xF000) * 0x00011000) & 0xFF000000;
2179 unsigned int r = ((argb & 0x0F00) * 0x00001100) & 0x00FF0000;
2180 unsigned int g = ((argb & 0x00F0) * 0x00000110) & 0x0000FF00;
2181 unsigned int b = (argb & 0x000F) * 0x00000011;
2182
2183 *(unsigned int*)destinationElement = a | r | g | b;
2184
2185 sourceElement += source.bytes;
2186 destinationElement += destination.bytes;
2187 }
2188
2189 sourceRow += source.pitchB;
2190 destinationRow += destination.pitchB;
2191 }
2192
2193 sourceSlice += source.sliceB;
2194 destinationSlice += destination.sliceB;
2195 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002196
2197 source.unlockRect();
2198 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002199 }
2200
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002201 void Surface::decodeP8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002202 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002203 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
Nicolas Capensae7756e2018-02-22 16:13:01 -05002204 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_UPDATE);
John Bauman89401822014-05-06 15:04:28 -04002205
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002206 int depth = min(destination.depth, source.depth);
2207 int height = min(destination.height, source.height);
2208 int width = min(destination.width, source.width);
2209
2210 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002211 {
2212 unsigned char *sourceRow = sourceSlice;
2213 unsigned char *destinationRow = destinationSlice;
2214
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002215 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002216 {
2217 unsigned char *sourceElement = sourceRow;
2218 unsigned char *destinationElement = destinationRow;
2219
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002220 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002221 {
2222 unsigned int abgr = palette[*(unsigned char*)sourceElement];
2223
2224 unsigned int r = (abgr & 0x000000FF) << 16;
2225 unsigned int g = (abgr & 0x0000FF00) << 0;
2226 unsigned int b = (abgr & 0x00FF0000) >> 16;
2227 unsigned int a = (abgr & 0xFF000000) >> 0;
2228
2229 *(unsigned int*)destinationElement = a | r | g | b;
2230
2231 sourceElement += source.bytes;
2232 destinationElement += destination.bytes;
2233 }
2234
2235 sourceRow += source.pitchB;
2236 destinationRow += destination.pitchB;
2237 }
2238
2239 sourceSlice += source.sliceB;
2240 destinationSlice += destination.sliceB;
2241 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002242
2243 source.unlockRect();
2244 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002245 }
2246
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002247 void Surface::decodeDXT1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002248 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002249 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002250 const DXT1 *source = (const DXT1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002251
2252 for(int z = 0; z < external.depth; z++)
2253 {
2254 unsigned int *dest = destSlice;
2255
2256 for(int y = 0; y < external.height; y += 4)
2257 {
2258 for(int x = 0; x < external.width; x += 4)
2259 {
2260 Color<byte> c[4];
2261
2262 c[0] = source->c0;
2263 c[1] = source->c1;
2264
2265 if(source->c0 > source->c1) // No transparency
2266 {
2267 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2268 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2269 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2270 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2271 c[2].a = 0xFF;
2272
2273 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2274 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2275 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2276 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2277 c[3].a = 0xFF;
2278 }
2279 else // c3 transparent
2280 {
2281 // c2 = 1 / 2 * c0 + 1 / 2 * c1
2282 c[2].r = (byte)(((word)c[0].r + (word)c[1].r) / 2);
2283 c[2].g = (byte)(((word)c[0].g + (word)c[1].g) / 2);
2284 c[2].b = (byte)(((word)c[0].b + (word)c[1].b) / 2);
2285 c[2].a = 0xFF;
2286
2287 c[3].r = 0;
2288 c[3].g = 0;
2289 c[3].b = 0;
2290 c[3].a = 0;
2291 }
2292
2293 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2294 {
2295 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2296 {
2297 dest[(x + i) + (y + j) * internal.width] = c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4];
2298 }
2299 }
2300
2301 source++;
2302 }
2303 }
2304
2305 (byte*&)destSlice += internal.sliceB;
2306 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002307
2308 external.unlockRect();
2309 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002310 }
2311
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002312 void Surface::decodeDXT3(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002313 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002314 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002315 const DXT3 *source = (const DXT3*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002316
2317 for(int z = 0; z < external.depth; z++)
2318 {
2319 unsigned int *dest = destSlice;
2320
2321 for(int y = 0; y < external.height; y += 4)
2322 {
2323 for(int x = 0; x < external.width; x += 4)
2324 {
2325 Color<byte> c[4];
2326
2327 c[0] = source->c0;
2328 c[1] = source->c1;
2329
2330 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2331 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2332 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2333 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2334
2335 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2336 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2337 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2338 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2339
2340 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2341 {
2342 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2343 {
2344 unsigned int a = (unsigned int)(source->a >> 4 * (i + j * 4)) & 0x0F;
2345 unsigned int color = (c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | ((a << 28) + (a << 24));
2346
2347 dest[(x + i) + (y + j) * internal.width] = color;
2348 }
2349 }
2350
2351 source++;
2352 }
2353 }
2354
2355 (byte*&)destSlice += internal.sliceB;
2356 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002357
2358 external.unlockRect();
2359 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002360 }
2361
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002362 void Surface::decodeDXT5(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002363 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002364 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002365 const DXT5 *source = (const DXT5*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002366
2367 for(int z = 0; z < external.depth; z++)
2368 {
2369 unsigned int *dest = destSlice;
2370
2371 for(int y = 0; y < external.height; y += 4)
2372 {
2373 for(int x = 0; x < external.width; x += 4)
2374 {
2375 Color<byte> c[4];
2376
2377 c[0] = source->c0;
2378 c[1] = source->c1;
2379
2380 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2381 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2382 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2383 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2384
2385 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2386 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2387 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2388 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2389
2390 byte a[8];
2391
2392 a[0] = source->a0;
2393 a[1] = source->a1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002394
John Bauman89401822014-05-06 15:04:28 -04002395 if(a[0] > a[1])
2396 {
2397 a[2] = (byte)((6 * (word)a[0] + 1 * (word)a[1] + 3) / 7);
2398 a[3] = (byte)((5 * (word)a[0] + 2 * (word)a[1] + 3) / 7);
2399 a[4] = (byte)((4 * (word)a[0] + 3 * (word)a[1] + 3) / 7);
2400 a[5] = (byte)((3 * (word)a[0] + 4 * (word)a[1] + 3) / 7);
2401 a[6] = (byte)((2 * (word)a[0] + 5 * (word)a[1] + 3) / 7);
2402 a[7] = (byte)((1 * (word)a[0] + 6 * (word)a[1] + 3) / 7);
2403 }
2404 else
2405 {
2406 a[2] = (byte)((4 * (word)a[0] + 1 * (word)a[1] + 2) / 5);
2407 a[3] = (byte)((3 * (word)a[0] + 2 * (word)a[1] + 2) / 5);
2408 a[4] = (byte)((2 * (word)a[0] + 3 * (word)a[1] + 2) / 5);
2409 a[5] = (byte)((1 * (word)a[0] + 4 * (word)a[1] + 2) / 5);
2410 a[6] = 0;
2411 a[7] = 0xFF;
2412 }
2413
2414 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2415 {
2416 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2417 {
2418 unsigned int alpha = (unsigned int)a[(unsigned int)(source->alut >> (16 + 3 * (i + j * 4))) % 8] << 24;
2419 unsigned int color = (c[(source->clut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | alpha;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002420
John Bauman89401822014-05-06 15:04:28 -04002421 dest[(x + i) + (y + j) * internal.width] = color;
2422 }
2423 }
2424
2425 source++;
2426 }
2427 }
2428
2429 (byte*&)destSlice += internal.sliceB;
2430 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002431
2432 external.unlockRect();
2433 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002434 }
2435
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002436 void Surface::decodeATI1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002437 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002438 byte *destSlice = (byte*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002439 const ATI1 *source = (const ATI1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002440
2441 for(int z = 0; z < external.depth; z++)
2442 {
2443 byte *dest = destSlice;
2444
2445 for(int y = 0; y < external.height; y += 4)
2446 {
2447 for(int x = 0; x < external.width; x += 4)
2448 {
2449 byte r[8];
2450
2451 r[0] = source->r0;
2452 r[1] = source->r1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002453
John Bauman89401822014-05-06 15:04:28 -04002454 if(r[0] > r[1])
2455 {
2456 r[2] = (byte)((6 * (word)r[0] + 1 * (word)r[1] + 3) / 7);
2457 r[3] = (byte)((5 * (word)r[0] + 2 * (word)r[1] + 3) / 7);
2458 r[4] = (byte)((4 * (word)r[0] + 3 * (word)r[1] + 3) / 7);
2459 r[5] = (byte)((3 * (word)r[0] + 4 * (word)r[1] + 3) / 7);
2460 r[6] = (byte)((2 * (word)r[0] + 5 * (word)r[1] + 3) / 7);
2461 r[7] = (byte)((1 * (word)r[0] + 6 * (word)r[1] + 3) / 7);
2462 }
2463 else
2464 {
2465 r[2] = (byte)((4 * (word)r[0] + 1 * (word)r[1] + 2) / 5);
2466 r[3] = (byte)((3 * (word)r[0] + 2 * (word)r[1] + 2) / 5);
2467 r[4] = (byte)((2 * (word)r[0] + 3 * (word)r[1] + 2) / 5);
2468 r[5] = (byte)((1 * (word)r[0] + 4 * (word)r[1] + 2) / 5);
2469 r[6] = 0;
2470 r[7] = 0xFF;
2471 }
2472
2473 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2474 {
2475 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2476 {
2477 dest[(x + i) + (y + j) * internal.width] = r[(unsigned int)(source->rlut >> (16 + 3 * (i + j * 4))) % 8];
2478 }
2479 }
2480
2481 source++;
2482 }
2483 }
2484
2485 destSlice += internal.sliceB;
2486 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002487
2488 external.unlockRect();
2489 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002490 }
2491
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002492 void Surface::decodeATI2(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002493 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002494 word *destSlice = (word*)internal.lockRect(0, 0, 0, LOCK_UPDATE);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002495 const ATI2 *source = (const ATI2*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002496
2497 for(int z = 0; z < external.depth; z++)
2498 {
2499 word *dest = destSlice;
2500
2501 for(int y = 0; y < external.height; y += 4)
2502 {
2503 for(int x = 0; x < external.width; x += 4)
2504 {
2505 byte X[8];
2506
2507 X[0] = source->x0;
2508 X[1] = source->x1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002509
John Bauman89401822014-05-06 15:04:28 -04002510 if(X[0] > X[1])
2511 {
2512 X[2] = (byte)((6 * (word)X[0] + 1 * (word)X[1] + 3) / 7);
2513 X[3] = (byte)((5 * (word)X[0] + 2 * (word)X[1] + 3) / 7);
2514 X[4] = (byte)((4 * (word)X[0] + 3 * (word)X[1] + 3) / 7);
2515 X[5] = (byte)((3 * (word)X[0] + 4 * (word)X[1] + 3) / 7);
2516 X[6] = (byte)((2 * (word)X[0] + 5 * (word)X[1] + 3) / 7);
2517 X[7] = (byte)((1 * (word)X[0] + 6 * (word)X[1] + 3) / 7);
2518 }
2519 else
2520 {
2521 X[2] = (byte)((4 * (word)X[0] + 1 * (word)X[1] + 2) / 5);
2522 X[3] = (byte)((3 * (word)X[0] + 2 * (word)X[1] + 2) / 5);
2523 X[4] = (byte)((2 * (word)X[0] + 3 * (word)X[1] + 2) / 5);
2524 X[5] = (byte)((1 * (word)X[0] + 4 * (word)X[1] + 2) / 5);
2525 X[6] = 0;
2526 X[7] = 0xFF;
2527 }
2528
2529 byte Y[8];
2530
2531 Y[0] = source->y0;
2532 Y[1] = source->y1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002533
John Bauman89401822014-05-06 15:04:28 -04002534 if(Y[0] > Y[1])
2535 {
2536 Y[2] = (byte)((6 * (word)Y[0] + 1 * (word)Y[1] + 3) / 7);
2537 Y[3] = (byte)((5 * (word)Y[0] + 2 * (word)Y[1] + 3) / 7);
2538 Y[4] = (byte)((4 * (word)Y[0] + 3 * (word)Y[1] + 3) / 7);
2539 Y[5] = (byte)((3 * (word)Y[0] + 4 * (word)Y[1] + 3) / 7);
2540 Y[6] = (byte)((2 * (word)Y[0] + 5 * (word)Y[1] + 3) / 7);
2541 Y[7] = (byte)((1 * (word)Y[0] + 6 * (word)Y[1] + 3) / 7);
2542 }
2543 else
2544 {
2545 Y[2] = (byte)((4 * (word)Y[0] + 1 * (word)Y[1] + 2) / 5);
2546 Y[3] = (byte)((3 * (word)Y[0] + 2 * (word)Y[1] + 2) / 5);
2547 Y[4] = (byte)((2 * (word)Y[0] + 3 * (word)Y[1] + 2) / 5);
2548 Y[5] = (byte)((1 * (word)Y[0] + 4 * (word)Y[1] + 2) / 5);
2549 Y[6] = 0;
2550 Y[7] = 0xFF;
2551 }
2552
2553 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2554 {
2555 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2556 {
2557 word r = X[(unsigned int)(source->xlut >> (16 + 3 * (i + j * 4))) % 8];
2558 word g = Y[(unsigned int)(source->ylut >> (16 + 3 * (i + j * 4))) % 8];
2559
2560 dest[(x + i) + (y + j) * internal.width] = (g << 8) + r;
2561 }
2562 }
2563
2564 source++;
2565 }
2566 }
2567
2568 (byte*&)destSlice += internal.sliceB;
2569 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002570
2571 external.unlockRect();
2572 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002573 }
Nicolas Capens22658242014-11-29 00:31:41 -05002574
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002575 void Surface::decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002576 {
Nicolas Capensae7756e2018-02-22 16:13:01 -05002577 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 -04002578 (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 -05002579 external.unlockRect();
2580 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002581
Alexis Hetu0de50d42015-09-09 13:56:41 -04002582 if(isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002583 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002584 static byte sRGBtoLinearTable[256];
2585 static bool sRGBtoLinearTableDirty = true;
2586 if(sRGBtoLinearTableDirty)
Nicolas Capens22658242014-11-29 00:31:41 -05002587 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002588 for(int i = 0; i < 256; i++)
Nicolas Capens22658242014-11-29 00:31:41 -05002589 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002590 sRGBtoLinearTable[i] = static_cast<byte>(sRGBtoLinear(static_cast<float>(i) / 255.0f) * 255.0f + 0.5f);
Nicolas Capens22658242014-11-29 00:31:41 -05002591 }
Alexis Hetu0de50d42015-09-09 13:56:41 -04002592 sRGBtoLinearTableDirty = false;
Nicolas Capens22658242014-11-29 00:31:41 -05002593 }
2594
Alexis Hetu0de50d42015-09-09 13:56:41 -04002595 // Perform sRGB conversion in place after decoding
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002596 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002597 for(int y = 0; y < internal.height; y++)
2598 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002599 byte *srcRow = src + y * internal.pitchB;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002600 for(int x = 0; x < internal.width; x++)
2601 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002602 byte *srcPix = srcRow + x * internal.bytes;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002603 for(int i = 0; i < 3; i++)
2604 {
2605 srcPix[i] = sRGBtoLinearTable[srcPix[i]];
2606 }
2607 }
2608 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002609 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002610 }
2611 }
John Bauman89401822014-05-06 15:04:28 -04002612
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002613 void Surface::decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002614 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002615 ASSERT(nbChannels == 1 || nbChannels == 2);
Alexis Hetu460e41f2015-09-01 10:58:37 -04002616
Alexis Hetuf46493f2017-12-18 15:32:26 -05002617 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
2618 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 -04002619 (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 -05002620 external.unlockRect();
Alexis Hetu0de50d42015-09-09 13:56:41 -04002621
Alexis Hetuf46493f2017-12-18 15:32:26 -05002622 // FIXME: We convert EAC data to float, until signed short internal formats are supported
2623 // This code can be removed if ETC2 images are decoded to internal 16 bit signed R/RG formats
2624 const float normalization = isSigned ? (1.0f / (8.0f * 127.875f)) : (1.0f / (8.0f * 255.875f));
2625 for(int y = 0; y < internal.height; y++)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002626 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002627 byte* srcRow = src + y * internal.pitchB;
2628 for(int x = internal.width - 1; x >= 0; x--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002629 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002630 int* srcPix = reinterpret_cast<int*>(srcRow + x * internal.bytes);
2631 float* dstPix = reinterpret_cast<float*>(srcPix);
2632 for(int c = nbChannels - 1; c >= 0; c--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002633 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002634 dstPix[c] = clamp(static_cast<float>(srcPix[c]) * normalization, -1.0f, 1.0f);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002635 }
2636 }
2637 }
Alexis Hetuf46493f2017-12-18 15:32:26 -05002638
2639 internal.unlockRect();
Alexis Hetu460e41f2015-09-01 10:58:37 -04002640 }
2641
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002642 void Surface::decodeASTC(Buffer &internal, Buffer &external, int xBlockSize, int yBlockSize, int zBlockSize, bool isSRGB)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002643 {
2644 }
2645
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002646 unsigned int Surface::size(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04002647 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002648 width += 2 * border;
2649 height += 2 * border;
2650
Nicolas Capens00555c42015-07-21 15:15:30 -04002651 // Dimensions rounded up to multiples of 4, used for compressed formats
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002652 int width4 = align(width, 4);
2653 int height4 = align(height, 4);
John Bauman89401822014-05-06 15:04:28 -04002654
2655 switch(format)
2656 {
John Bauman89401822014-05-06 15:04:28 -04002657 case FORMAT_DXT1:
2658 case FORMAT_ATI1:
Nicolas Capens22658242014-11-29 00:31:41 -05002659 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04002660 case FORMAT_R11_EAC:
2661 case FORMAT_SIGNED_R11_EAC:
2662 case FORMAT_RGB8_ETC2:
2663 case FORMAT_SRGB8_ETC2:
2664 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2665 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Bauman89401822014-05-06 15:04:28 -04002666 return width4 * height4 * depth / 2;
2667 case FORMAT_DXT3:
2668 case FORMAT_DXT5:
2669 case FORMAT_ATI2:
Alexis Hetu460e41f2015-09-01 10:58:37 -04002670 case FORMAT_RG11_EAC:
2671 case FORMAT_SIGNED_RG11_EAC:
2672 case FORMAT_RGBA8_ETC2_EAC:
2673 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
2674 case FORMAT_RGBA_ASTC_4x4_KHR:
2675 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
John Bauman89401822014-05-06 15:04:28 -04002676 return width4 * height4 * depth;
Alexis Hetu460e41f2015-09-01 10:58:37 -04002677 case FORMAT_RGBA_ASTC_5x4_KHR:
2678 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
2679 return align(width, 5) * height4 * depth;
2680 case FORMAT_RGBA_ASTC_5x5_KHR:
2681 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
2682 return align(width, 5) * align(height, 5) * depth;
2683 case FORMAT_RGBA_ASTC_6x5_KHR:
2684 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
2685 return align(width, 6) * align(height, 5) * depth;
2686 case FORMAT_RGBA_ASTC_6x6_KHR:
2687 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
2688 return align(width, 6) * align(height, 6) * depth;
2689 case FORMAT_RGBA_ASTC_8x5_KHR:
2690 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
2691 return align(width, 8) * align(height, 5) * depth;
2692 case FORMAT_RGBA_ASTC_8x6_KHR:
2693 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
2694 return align(width, 8) * align(height, 6) * depth;
2695 case FORMAT_RGBA_ASTC_8x8_KHR:
2696 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
2697 return align(width, 8) * align(height, 8) * depth;
2698 case FORMAT_RGBA_ASTC_10x5_KHR:
2699 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
2700 return align(width, 10) * align(height, 5) * depth;
2701 case FORMAT_RGBA_ASTC_10x6_KHR:
2702 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
2703 return align(width, 10) * align(height, 6) * depth;
2704 case FORMAT_RGBA_ASTC_10x8_KHR:
2705 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
2706 return align(width, 10) * align(height, 8) * depth;
2707 case FORMAT_RGBA_ASTC_10x10_KHR:
2708 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
2709 return align(width, 10) * align(height, 10) * depth;
2710 case FORMAT_RGBA_ASTC_12x10_KHR:
2711 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
2712 return align(width, 12) * align(height, 10) * depth;
2713 case FORMAT_RGBA_ASTC_12x12_KHR:
2714 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
2715 return align(width, 12) * align(height, 12) * depth;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002716 case FORMAT_YV12_BT601:
2717 case FORMAT_YV12_BT709:
2718 case FORMAT_YV12_JFIF:
2719 {
2720 unsigned int YStride = align(width, 16);
2721 unsigned int YSize = YStride * height;
2722 unsigned int CStride = align(YStride / 2, 16);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002723 unsigned int CSize = CStride * height / 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002724
2725 return YSize + 2 * CSize;
2726 }
John Bauman89401822014-05-06 15:04:28 -04002727 default:
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002728 return bytes(format) * width * height * depth * samples;
John Bauman89401822014-05-06 15:04:28 -04002729 }
John Bauman89401822014-05-06 15:04:28 -04002730 }
2731
2732 bool Surface::isStencil(Format format)
2733 {
2734 switch(format)
2735 {
2736 case FORMAT_D32:
2737 case FORMAT_D16:
2738 case FORMAT_D24X8:
2739 case FORMAT_D32F:
2740 case FORMAT_D32F_COMPLEMENTARY:
2741 case FORMAT_D32F_LOCKABLE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002742 case FORMAT_D32F_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002743 return false;
2744 case FORMAT_D24S8:
2745 case FORMAT_D24FS8:
2746 case FORMAT_S8:
John Bauman66b8ab22014-05-06 15:57:45 -04002747 case FORMAT_DF24S8:
2748 case FORMAT_DF16S8:
2749 case FORMAT_D32FS8_TEXTURE:
2750 case FORMAT_D32FS8_SHADOW:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002751 case FORMAT_D32FS8:
2752 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002753 case FORMAT_INTZ:
2754 return true;
2755 default:
2756 return false;
2757 }
2758 }
2759
2760 bool Surface::isDepth(Format format)
2761 {
2762 switch(format)
2763 {
2764 case FORMAT_D32:
2765 case FORMAT_D16:
2766 case FORMAT_D24X8:
2767 case FORMAT_D24S8:
2768 case FORMAT_D24FS8:
2769 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002770 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002771 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002772 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002773 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002774 case FORMAT_DF24S8:
2775 case FORMAT_DF16S8:
2776 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002777 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002778 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002779 case FORMAT_INTZ:
2780 return true;
2781 case FORMAT_S8:
2782 return false;
2783 default:
2784 return false;
2785 }
2786 }
2787
Alexis Hetub9dda642016-10-06 11:25:32 -04002788 bool Surface::hasQuadLayout(Format format)
2789 {
2790 switch(format)
2791 {
2792 case FORMAT_D32:
2793 case FORMAT_D16:
2794 case FORMAT_D24X8:
2795 case FORMAT_D24S8:
2796 case FORMAT_D24FS8:
2797 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002798 case FORMAT_D32FS8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002799 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002800 case FORMAT_D32FS8_COMPLEMENTARY:
Alexis Hetub9dda642016-10-06 11:25:32 -04002801 case FORMAT_DF24S8:
2802 case FORMAT_DF16S8:
2803 case FORMAT_INTZ:
2804 case FORMAT_S8:
2805 case FORMAT_A8G8R8B8Q:
2806 case FORMAT_X8G8R8B8Q:
2807 return true;
2808 case FORMAT_D32F_LOCKABLE:
2809 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002810 case FORMAT_D32F_SHADOW:
Alexis Hetub9dda642016-10-06 11:25:32 -04002811 case FORMAT_D32FS8_SHADOW:
2812 default:
2813 break;
2814 }
2815
2816 return false;
2817 }
2818
John Bauman89401822014-05-06 15:04:28 -04002819 bool Surface::isPalette(Format format)
2820 {
2821 switch(format)
2822 {
2823 case FORMAT_P8:
2824 case FORMAT_A8P8:
2825 return true;
2826 default:
2827 return false;
2828 }
2829 }
2830
2831 bool Surface::isFloatFormat(Format format)
2832 {
2833 switch(format)
2834 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002835 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002836 case FORMAT_R8G8B8:
2837 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002838 case FORMAT_X8R8G8B8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002839 case FORMAT_X8B8G8R8I:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002840 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002841 case FORMAT_A8R8G8B8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002842 case FORMAT_SRGB8_X8:
2843 case FORMAT_SRGB8_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002844 case FORMAT_A8B8G8R8I:
2845 case FORMAT_R8UI:
2846 case FORMAT_G8R8UI:
2847 case FORMAT_X8B8G8R8UI:
2848 case FORMAT_A8B8G8R8UI:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002849 case FORMAT_A8B8G8R8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002850 case FORMAT_G8R8I:
John Bauman89401822014-05-06 15:04:28 -04002851 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002852 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002853 case FORMAT_A2B10G10R10UI:
Nicolas Capens975adb72017-12-19 15:34:20 -05002854 case FORMAT_R8_SNORM:
2855 case FORMAT_G8R8_SNORM:
2856 case FORMAT_X8B8G8R8_SNORM:
2857 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu43577b82015-10-21 15:32:16 -04002858 case FORMAT_R16I:
2859 case FORMAT_R16UI:
2860 case FORMAT_G16R16I:
2861 case FORMAT_G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002862 case FORMAT_G16R16:
Alexis Hetu43577b82015-10-21 15:32:16 -04002863 case FORMAT_X16B16G16R16I:
2864 case FORMAT_X16B16G16R16UI:
2865 case FORMAT_A16B16G16R16I:
2866 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002867 case FORMAT_A16B16G16R16:
2868 case FORMAT_V8U8:
2869 case FORMAT_Q8W8V8U8:
2870 case FORMAT_X8L8V8U8:
2871 case FORMAT_V16U16:
2872 case FORMAT_A16W16V16U16:
2873 case FORMAT_Q16W16V16U16:
2874 case FORMAT_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002875 case FORMAT_R8I:
John Bauman89401822014-05-06 15:04:28 -04002876 case FORMAT_R8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002877 case FORMAT_S8:
John Bauman89401822014-05-06 15:04:28 -04002878 case FORMAT_L8:
2879 case FORMAT_L16:
2880 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002881 case FORMAT_YV12_BT601:
2882 case FORMAT_YV12_BT709:
2883 case FORMAT_YV12_JFIF:
Alexis Hetu43577b82015-10-21 15:32:16 -04002884 case FORMAT_R32I:
2885 case FORMAT_R32UI:
2886 case FORMAT_G32R32I:
2887 case FORMAT_G32R32UI:
2888 case FORMAT_X32B32G32R32I:
2889 case FORMAT_X32B32G32R32UI:
2890 case FORMAT_A32B32G32R32I:
2891 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002892 return false;
Nicolas Capens400667e2017-03-29 14:40:14 -04002893 case FORMAT_R16F:
2894 case FORMAT_G16R16F:
2895 case FORMAT_B16G16R16F:
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05002896 case FORMAT_X16B16G16R16F:
Nicolas Capens400667e2017-03-29 14:40:14 -04002897 case FORMAT_A16B16G16R16F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002898 case FORMAT_X16B16G16R16F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002899 case FORMAT_R32F:
2900 case FORMAT_G32R32F:
Nicolas Capensc018e082016-12-13 10:19:33 -05002901 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002902 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002903 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002904 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002905 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002906 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002907 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002908 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002909 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002910 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002911 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002912 case FORMAT_D32FS8_SHADOW:
Nicolas Capens80594422015-06-09 16:42:56 -04002913 case FORMAT_L16F:
2914 case FORMAT_A16L16F:
2915 case FORMAT_L32F:
2916 case FORMAT_A32L32F:
John Bauman89401822014-05-06 15:04:28 -04002917 return true;
2918 default:
2919 ASSERT(false);
2920 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04002921
John Bauman89401822014-05-06 15:04:28 -04002922 return false;
2923 }
2924
2925 bool Surface::isUnsignedComponent(Format format, int component)
2926 {
2927 switch(format)
2928 {
2929 case FORMAT_NULL:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002930 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002931 case FORMAT_R8G8B8:
2932 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002933 case FORMAT_X8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002934 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002935 case FORMAT_A8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002936 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002937 case FORMAT_SRGB8_X8:
2938 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002939 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002940 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002941 case FORMAT_A2B10G10R10UI:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002942 case FORMAT_R16UI:
John Bauman89401822014-05-06 15:04:28 -04002943 case FORMAT_G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002944 case FORMAT_G16R16UI:
2945 case FORMAT_X16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002946 case FORMAT_A16B16G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002947 case FORMAT_A16B16G16R16UI:
2948 case FORMAT_R32UI:
2949 case FORMAT_G32R32UI:
2950 case FORMAT_X32B32G32R32UI:
2951 case FORMAT_A32B32G32R32UI:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002952 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002953 case FORMAT_R8UI:
2954 case FORMAT_G8R8UI:
2955 case FORMAT_X8B8G8R8UI:
2956 case FORMAT_A8B8G8R8UI:
John Bauman89401822014-05-06 15:04:28 -04002957 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002958 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002959 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002960 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002961 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002962 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002963 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002964 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002965 case FORMAT_A8:
2966 case FORMAT_R8:
2967 case FORMAT_L8:
2968 case FORMAT_L16:
2969 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002970 case FORMAT_YV12_BT601:
2971 case FORMAT_YV12_BT709:
2972 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002973 return true;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002974 case FORMAT_A8B8G8R8I:
2975 case FORMAT_A16B16G16R16I:
2976 case FORMAT_A32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002977 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002978 case FORMAT_Q8W8V8U8:
2979 case FORMAT_Q16W16V16U16:
2980 case FORMAT_A32B32G32R32F:
2981 return false;
2982 case FORMAT_R32F:
2983 case FORMAT_R8I:
2984 case FORMAT_R16I:
2985 case FORMAT_R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002986 case FORMAT_R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002987 return component >= 1;
John Bauman89401822014-05-06 15:04:28 -04002988 case FORMAT_V8U8:
2989 case FORMAT_X8L8V8U8:
2990 case FORMAT_V16U16:
John Bauman89401822014-05-06 15:04:28 -04002991 case FORMAT_G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002992 case FORMAT_G8R8I:
2993 case FORMAT_G16R16I:
2994 case FORMAT_G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002995 case FORMAT_G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002996 return component >= 2;
2997 case FORMAT_A16W16V16U16:
Nicolas Capens2e363b02016-12-14 10:32:36 -05002998 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002999 case FORMAT_X32B32G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003000 case FORMAT_X8B8G8R8I:
3001 case FORMAT_X16B16G16R16I:
3002 case FORMAT_X32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05003003 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003004 return component >= 3;
John Bauman89401822014-05-06 15:04:28 -04003005 default:
3006 ASSERT(false);
3007 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04003008
John Bauman89401822014-05-06 15:04:28 -04003009 return false;
3010 }
3011
3012 bool Surface::isSRGBreadable(Format format)
3013 {
3014 // Keep in sync with Capabilities::isSRGBreadable
3015 switch(format)
3016 {
3017 case FORMAT_L8:
3018 case FORMAT_A8L8:
3019 case FORMAT_R8G8B8:
3020 case FORMAT_A8R8G8B8:
3021 case FORMAT_X8R8G8B8:
3022 case FORMAT_A8B8G8R8:
3023 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04003024 case FORMAT_SRGB8_X8:
3025 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04003026 case FORMAT_R5G6B5:
3027 case FORMAT_X1R5G5B5:
3028 case FORMAT_A1R5G5B5:
3029 case FORMAT_A4R4G4B4:
John Bauman89401822014-05-06 15:04:28 -04003030 case FORMAT_DXT1:
3031 case FORMAT_DXT3:
3032 case FORMAT_DXT5:
3033 case FORMAT_ATI1:
3034 case FORMAT_ATI2:
John Bauman89401822014-05-06 15:04:28 -04003035 return true;
3036 default:
3037 return false;
3038 }
John Bauman89401822014-05-06 15:04:28 -04003039 }
3040
3041 bool Surface::isSRGBwritable(Format format)
3042 {
3043 // Keep in sync with Capabilities::isSRGBwritable
3044 switch(format)
3045 {
3046 case FORMAT_NULL:
3047 case FORMAT_A8R8G8B8:
3048 case FORMAT_X8R8G8B8:
3049 case FORMAT_A8B8G8R8:
3050 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04003051 case FORMAT_SRGB8_X8:
3052 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04003053 case FORMAT_R5G6B5:
3054 return true;
3055 default:
3056 return false;
3057 }
3058 }
3059
Nicolas Capens5555af42017-12-14 13:14:03 -05003060 bool Surface::isSRGBformat(Format format)
3061 {
3062 switch(format)
3063 {
3064 case FORMAT_SRGB8_X8:
3065 case FORMAT_SRGB8_A8:
3066 return true;
3067 default:
3068 return false;
3069 }
3070 }
3071
John Bauman89401822014-05-06 15:04:28 -04003072 bool Surface::isCompressed(Format format)
3073 {
3074 switch(format)
3075 {
John Bauman89401822014-05-06 15:04:28 -04003076 case FORMAT_DXT1:
3077 case FORMAT_DXT3:
3078 case FORMAT_DXT5:
3079 case FORMAT_ATI1:
3080 case FORMAT_ATI2:
Nicolas Capens22658242014-11-29 00:31:41 -05003081 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003082 case FORMAT_R11_EAC:
3083 case FORMAT_SIGNED_R11_EAC:
3084 case FORMAT_RG11_EAC:
3085 case FORMAT_SIGNED_RG11_EAC:
3086 case FORMAT_RGB8_ETC2:
3087 case FORMAT_SRGB8_ETC2:
3088 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3089 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3090 case FORMAT_RGBA8_ETC2_EAC:
3091 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3092 case FORMAT_RGBA_ASTC_4x4_KHR:
3093 case FORMAT_RGBA_ASTC_5x4_KHR:
3094 case FORMAT_RGBA_ASTC_5x5_KHR:
3095 case FORMAT_RGBA_ASTC_6x5_KHR:
3096 case FORMAT_RGBA_ASTC_6x6_KHR:
3097 case FORMAT_RGBA_ASTC_8x5_KHR:
3098 case FORMAT_RGBA_ASTC_8x6_KHR:
3099 case FORMAT_RGBA_ASTC_8x8_KHR:
3100 case FORMAT_RGBA_ASTC_10x5_KHR:
3101 case FORMAT_RGBA_ASTC_10x6_KHR:
3102 case FORMAT_RGBA_ASTC_10x8_KHR:
3103 case FORMAT_RGBA_ASTC_10x10_KHR:
3104 case FORMAT_RGBA_ASTC_12x10_KHR:
3105 case FORMAT_RGBA_ASTC_12x12_KHR:
3106 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3107 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3108 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3109 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3110 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3111 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3112 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3113 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3114 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3115 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3116 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3117 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3118 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3119 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
John Bauman89401822014-05-06 15:04:28 -04003120 return true;
John Bauman89401822014-05-06 15:04:28 -04003121 default:
3122 return false;
3123 }
3124 }
3125
Nicolas Capens492887a2017-03-27 14:50:51 -04003126 bool Surface::isSignedNonNormalizedInteger(Format format)
Alexis Hetu43577b82015-10-21 15:32:16 -04003127 {
3128 switch(format)
3129 {
3130 case FORMAT_A8B8G8R8I:
3131 case FORMAT_X8B8G8R8I:
3132 case FORMAT_G8R8I:
3133 case FORMAT_R8I:
Alexis Hetu43577b82015-10-21 15:32:16 -04003134 case FORMAT_A16B16G16R16I:
3135 case FORMAT_X16B16G16R16I:
3136 case FORMAT_G16R16I:
3137 case FORMAT_R16I:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003138 case FORMAT_A32B32G32R32I:
3139 case FORMAT_X32B32G32R32I:
3140 case FORMAT_G32R32I:
3141 case FORMAT_R32I:
Nicolas Capens492887a2017-03-27 14:50:51 -04003142 return true;
3143 default:
3144 return false;
3145 }
3146 }
3147
3148 bool Surface::isUnsignedNonNormalizedInteger(Format format)
3149 {
3150 switch(format)
3151 {
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003152 case FORMAT_A8B8G8R8UI:
3153 case FORMAT_X8B8G8R8UI:
3154 case FORMAT_G8R8UI:
3155 case FORMAT_R8UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003156 case FORMAT_A16B16G16R16UI:
3157 case FORMAT_X16B16G16R16UI:
3158 case FORMAT_G16R16UI:
3159 case FORMAT_R16UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003160 case FORMAT_A32B32G32R32UI:
3161 case FORMAT_X32B32G32R32UI:
3162 case FORMAT_G32R32UI:
3163 case FORMAT_R32UI:
3164 return true;
3165 default:
3166 return false;
3167 }
3168 }
3169
Nicolas Capens492887a2017-03-27 14:50:51 -04003170 bool Surface::isNonNormalizedInteger(Format format)
3171 {
3172 return isSignedNonNormalizedInteger(format) ||
3173 isUnsignedNonNormalizedInteger(format);
3174 }
3175
3176 bool Surface::isNormalizedInteger(Format format)
3177 {
3178 return !isFloatFormat(format) &&
3179 !isNonNormalizedInteger(format) &&
3180 !isCompressed(format) &&
3181 !isDepth(format) &&
3182 !isStencil(format);
3183 }
3184
John Bauman89401822014-05-06 15:04:28 -04003185 int Surface::componentCount(Format format)
3186 {
3187 switch(format)
3188 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003189 case FORMAT_R5G6B5: return 3;
3190 case FORMAT_X8R8G8B8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003191 case FORMAT_X8B8G8R8I: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003192 case FORMAT_X8B8G8R8: return 3;
3193 case FORMAT_A8R8G8B8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04003194 case FORMAT_SRGB8_X8: return 3;
3195 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003196 case FORMAT_A8B8G8R8I: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003197 case FORMAT_A8B8G8R8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003198 case FORMAT_G8R8I: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003199 case FORMAT_G8R8: return 2;
Nicolas Capens975adb72017-12-19 15:34:20 -05003200 case FORMAT_R8_SNORM: return 1;
3201 case FORMAT_G8R8_SNORM: return 2;
3202 case FORMAT_X8B8G8R8_SNORM:return 3;
3203 case FORMAT_A8B8G8R8_SNORM:return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003204 case FORMAT_R8UI: return 1;
3205 case FORMAT_G8R8UI: return 2;
3206 case FORMAT_X8B8G8R8UI: return 3;
3207 case FORMAT_A8B8G8R8UI: return 4;
Alexis Hetuf999a002015-12-17 11:09:36 -05003208 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05003209 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003210 case FORMAT_G16R16I: return 2;
3211 case FORMAT_G16R16UI: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003212 case FORMAT_G16R16: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003213 case FORMAT_G32R32I: return 2;
3214 case FORMAT_G32R32UI: return 2;
3215 case FORMAT_X16B16G16R16I: return 3;
3216 case FORMAT_X16B16G16R16UI: return 3;
3217 case FORMAT_A16B16G16R16I: return 4;
3218 case FORMAT_A16B16G16R16UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003219 case FORMAT_A16B16G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003220 case FORMAT_X32B32G32R32I: return 3;
3221 case FORMAT_X32B32G32R32UI: return 3;
3222 case FORMAT_A32B32G32R32I: return 4;
3223 case FORMAT_A32B32G32R32UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003224 case FORMAT_V8U8: return 2;
3225 case FORMAT_Q8W8V8U8: return 4;
3226 case FORMAT_X8L8V8U8: return 3;
3227 case FORMAT_V16U16: return 2;
3228 case FORMAT_A16W16V16U16: return 4;
3229 case FORMAT_Q16W16V16U16: return 4;
3230 case FORMAT_R32F: return 1;
3231 case FORMAT_G32R32F: return 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003232 case FORMAT_X32B32G32R32F: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003233 case FORMAT_A32B32G32R32F: return 4;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003234 case FORMAT_X32B32G32R32F_UNSIGNED: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003235 case FORMAT_D32F: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003236 case FORMAT_D32FS8: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003237 case FORMAT_D32F_LOCKABLE: return 1;
3238 case FORMAT_D32FS8_TEXTURE: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003239 case FORMAT_D32F_SHADOW: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003240 case FORMAT_D32FS8_SHADOW: return 1;
3241 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003242 case FORMAT_R8I: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003243 case FORMAT_R8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003244 case FORMAT_R16I: return 1;
3245 case FORMAT_R16UI: return 1;
3246 case FORMAT_R32I: return 1;
3247 case FORMAT_R32UI: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003248 case FORMAT_L8: return 1;
3249 case FORMAT_L16: return 1;
3250 case FORMAT_A8L8: return 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003251 case FORMAT_YV12_BT601: return 3;
3252 case FORMAT_YV12_BT709: return 3;
3253 case FORMAT_YV12_JFIF: return 3;
John Bauman89401822014-05-06 15:04:28 -04003254 default:
3255 ASSERT(false);
3256 }
3257
3258 return 1;
3259 }
3260
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003261 void *Surface::allocateBuffer(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04003262 {
Nicolas Capensdb17b5d2015-06-26 11:15:58 -04003263 // Render targets require 2x2 quads
3264 int width2 = (width + 1) & ~1;
3265 int height2 = (height + 1) & ~1;
John Bauman89401822014-05-06 15:04:28 -04003266
Nicolas Capens6ea71872015-06-26 13:00:48 -04003267 // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
Nicolas Capens48ef1252016-11-07 15:30:33 -05003268 // and stencil operations also read 8 bytes per four 8-bit stencil values,
Nicolas Capens6ea71872015-06-26 13:00:48 -04003269 // so we have to allocate 4 extra bytes to avoid buffer overruns.
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003270 return allocate(size(width2, height2, depth, border, samples, format) + 4);
John Bauman89401822014-05-06 15:04:28 -04003271 }
3272
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003273 void Surface::memfill4(void *buffer, int pattern, int bytes)
John Bauman89401822014-05-06 15:04:28 -04003274 {
3275 while((size_t)buffer & 0x1 && bytes >= 1)
3276 {
3277 *(char*)buffer = (char)pattern;
3278 (char*&)buffer += 1;
3279 bytes -= 1;
3280 }
3281
3282 while((size_t)buffer & 0x3 && bytes >= 2)
3283 {
3284 *(short*)buffer = (short)pattern;
3285 (short*&)buffer += 1;
3286 bytes -= 2;
3287 }
3288
Nicolas Capens47dc8672017-04-25 12:54:39 -04003289 #if defined(__i386__) || defined(__x86_64__)
3290 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04003291 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04003292 while((size_t)buffer & 0xF && bytes >= 4)
3293 {
3294 *(int*)buffer = pattern;
3295 (int*&)buffer += 1;
3296 bytes -= 4;
3297 }
3298
3299 __m128 quad = _mm_set_ps1((float&)pattern);
3300
3301 float *pointer = (float*)buffer;
3302 int qxwords = bytes / 64;
3303 bytes -= qxwords * 64;
3304
3305 while(qxwords--)
3306 {
3307 _mm_stream_ps(pointer + 0, quad);
3308 _mm_stream_ps(pointer + 4, quad);
3309 _mm_stream_ps(pointer + 8, quad);
3310 _mm_stream_ps(pointer + 12, quad);
3311
3312 pointer += 16;
3313 }
3314
3315 buffer = pointer;
John Bauman89401822014-05-06 15:04:28 -04003316 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04003317 #endif
John Bauman89401822014-05-06 15:04:28 -04003318
3319 while(bytes >= 4)
3320 {
3321 *(int*)buffer = (int)pattern;
3322 (int*&)buffer += 1;
3323 bytes -= 4;
3324 }
3325
3326 while(bytes >= 2)
3327 {
3328 *(short*)buffer = (short)pattern;
3329 (short*&)buffer += 1;
3330 bytes -= 2;
3331 }
3332
3333 while(bytes >= 1)
3334 {
3335 *(char*)buffer = (char)pattern;
3336 (char*&)buffer += 1;
3337 bytes -= 1;
3338 }
3339 }
3340
Nicolas Capensbf7a8142017-05-19 10:57:28 -04003341 void Surface::sync()
3342 {
3343 resource->lock(EXCLUSIVE);
3344 resource->unlock();
3345 }
3346
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003347 bool Surface::isEntire(const Rect& rect) const
John Bauman89401822014-05-06 15:04:28 -04003348 {
Alexis Hetu75b650f2015-11-19 17:40:15 -05003349 return (rect.x0 == 0 && rect.y0 == 0 && rect.x1 == internal.width && rect.y1 == internal.height && internal.depth == 1);
3350 }
John Bauman89401822014-05-06 15:04:28 -04003351
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003352 Rect Surface::getRect() const
Alexis Hetu75b650f2015-11-19 17:40:15 -05003353 {
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003354 return Rect(0, 0, internal.width, internal.height);
John Bauman89401822014-05-06 15:04:28 -04003355 }
3356
Nicolas Capensc39901e2016-03-21 16:37:44 -04003357 void Surface::clearDepth(float depth, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003358 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003359 if(width == 0 || height == 0) return;
3360
John Bauman89401822014-05-06 15:04:28 -04003361 // Not overlapping
3362 if(x0 > internal.width) return;
3363 if(y0 > internal.height) return;
3364 if(x0 + width < 0) return;
3365 if(y0 + height < 0) return;
3366
3367 // Clip against dimensions
3368 if(x0 < 0) {width += x0; x0 = 0;}
3369 if(x0 + width > internal.width) width = internal.width - x0;
3370 if(y0 < 0) {height += y0; y0 = 0;}
3371 if(y0 + height > internal.height) height = internal.height - y0;
3372
3373 const bool entire = x0 == 0 && y0 == 0 && width == internal.width && height == internal.height;
3374 const Lock lock = entire ? LOCK_DISCARD : LOCK_WRITEONLY;
3375
John Bauman89401822014-05-06 15:04:28 -04003376 int x1 = x0 + width;
3377 int y1 = y0 + height;
3378
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003379 if(!hasQuadLayout(internal.format))
John Bauman89401822014-05-06 15:04:28 -04003380 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003381 float *target = (float*)lockInternal(x0, y0, 0, lock, PUBLIC);
John Bauman89401822014-05-06 15:04:28 -04003382
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003383 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003384 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003385 float *row = target;
John Bauman89401822014-05-06 15:04:28 -04003386 for(int y = y0; y < y1; y++)
3387 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003388 memfill4(row, (int&)depth, width * sizeof(float));
3389 row += internal.pitchP;
John Bauman89401822014-05-06 15:04:28 -04003390 }
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003391 target += internal.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003392 }
3393
3394 unlockInternal();
3395 }
3396 else // Quad layout
3397 {
3398 if(complementaryDepthBuffer)
3399 {
3400 depth = 1 - depth;
3401 }
3402
3403 float *buffer = (float*)lockInternal(0, 0, 0, lock, PUBLIC);
3404
Alexis Hetu358a1442015-12-03 14:23:10 -05003405 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3406 int oddX1 = (x1 & ~1) * 2;
3407 int evenX0 = ((x0 + 1) & ~1) * 2;
3408 int evenBytes = (oddX1 - evenX0) * sizeof(float);
3409
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003410 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003411 {
3412 for(int y = y0; y < y1; y++)
3413 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003414 float *target = buffer + (y & ~1) * internal.pitchP + (y & 1) * 2;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003415
John Bauman89401822014-05-06 15:04:28 -04003416 if((y & 1) == 0 && y + 1 < y1) // Fill quad line at once
3417 {
3418 if((x0 & 1) != 0)
3419 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003420 target[oddX0 + 0] = depth;
3421 target[oddX0 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003422 }
3423
Alexis Hetu358a1442015-12-03 14:23:10 -05003424 // for(int x2 = evenX0; x2 < x1 * 2; x2 += 4)
John Bauman89401822014-05-06 15:04:28 -04003425 // {
3426 // target[x2 + 0] = depth;
3427 // target[x2 + 1] = depth;
3428 // target[x2 + 2] = depth;
3429 // target[x2 + 3] = depth;
3430 // }
3431
3432 // __asm
3433 // {
3434 // movss xmm0, depth
3435 // shufps xmm0, xmm0, 0x00
3436 //
3437 // mov eax, x0
3438 // add eax, 1
3439 // and eax, 0xFFFFFFFE
3440 // cmp eax, x1
3441 // jge qEnd
3442 //
3443 // mov edi, target
3444 //
3445 // qLoop:
3446 // movntps [edi+8*eax], xmm0
3447 //
3448 // add eax, 2
3449 // cmp eax, x1
3450 // jl qLoop
3451 // qEnd:
3452 // }
3453
Alexis Hetu358a1442015-12-03 14:23:10 -05003454 memfill4(&target[evenX0], (int&)depth, evenBytes);
John Bauman89401822014-05-06 15:04:28 -04003455
3456 if((x1 & 1) != 0)
3457 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003458 target[oddX1 + 0] = depth;
3459 target[oddX1 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003460 }
3461
3462 y++;
3463 }
3464 else
3465 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003466 for(int x = x0, i = oddX0; x < x1; x++, i = (x & ~1) * 2 + (x & 1))
John Bauman89401822014-05-06 15:04:28 -04003467 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003468 target[i] = depth;
John Bauman89401822014-05-06 15:04:28 -04003469 }
3470 }
3471 }
3472
3473 buffer += internal.sliceP;
3474 }
3475
3476 unlockInternal();
3477 }
3478 }
3479
Nicolas Capensc39901e2016-03-21 16:37:44 -04003480 void Surface::clearStencil(unsigned char s, unsigned char mask, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003481 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003482 if(mask == 0 || width == 0 || height == 0) return;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003483
John Bauman89401822014-05-06 15:04:28 -04003484 // Not overlapping
3485 if(x0 > internal.width) return;
3486 if(y0 > internal.height) return;
3487 if(x0 + width < 0) return;
3488 if(y0 + height < 0) return;
3489
3490 // Clip against dimensions
3491 if(x0 < 0) {width += x0; x0 = 0;}
3492 if(x0 + width > internal.width) width = internal.width - x0;
3493 if(y0 < 0) {height += y0; y0 = 0;}
3494 if(y0 + height > internal.height) height = internal.height - y0;
3495
John Bauman89401822014-05-06 15:04:28 -04003496 int x1 = x0 + width;
3497 int y1 = y0 + height;
3498
Alexis Hetu358a1442015-12-03 14:23:10 -05003499 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3500 int oddX1 = (x1 & ~1) * 2;
3501 int evenX0 = ((x0 + 1) & ~1) * 2;
3502 int evenBytes = oddX1 - evenX0;
3503
John Bauman89401822014-05-06 15:04:28 -04003504 unsigned char maskedS = s & mask;
3505 unsigned char invMask = ~mask;
3506 unsigned int fill = maskedS;
Tom Anderson69bc6e82017-03-20 11:54:29 -07003507 fill = fill | (fill << 8) | (fill << 16) | (fill << 24);
John Bauman89401822014-05-06 15:04:28 -04003508
Alexis Hetua52dfbd2016-10-05 17:03:30 -04003509 char *buffer = (char*)lockStencil(0, 0, 0, PUBLIC);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003510
3511 // Stencil buffers are assumed to use quad layout
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003512 for(int z = 0; z < stencil.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003513 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003514 for(int y = y0; y < y1; y++)
John Bauman89401822014-05-06 15:04:28 -04003515 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003516 char *target = buffer + (y & ~1) * stencil.pitchP + (y & 1) * 2;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003517
3518 if((y & 1) == 0 && y + 1 < y1 && mask == 0xFF) // Fill quad line at once
John Bauman89401822014-05-06 15:04:28 -04003519 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003520 if((x0 & 1) != 0)
John Bauman89401822014-05-06 15:04:28 -04003521 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003522 target[oddX0 + 0] = fill;
3523 target[oddX0 + 2] = fill;
John Bauman89401822014-05-06 15:04:28 -04003524 }
3525
Alexis Hetu358a1442015-12-03 14:23:10 -05003526 memfill4(&target[evenX0], fill, evenBytes);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003527
3528 if((x1 & 1) != 0)
3529 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003530 target[oddX1 + 0] = fill;
3531 target[oddX1 + 2] = fill;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003532 }
3533
3534 y++;
3535 }
3536 else
3537 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003538 for(int x = x0; x < x1; x++)
Alexis Hetu2b052f82015-11-25 13:57:28 -05003539 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003540 int i = (x & ~1) * 2 + (x & 1);
Alexis Hetu358a1442015-12-03 14:23:10 -05003541 target[i] = maskedS | (target[i] & invMask);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003542 }
John Bauman89401822014-05-06 15:04:28 -04003543 }
3544 }
3545
Alexis Hetu2b052f82015-11-25 13:57:28 -05003546 buffer += stencil.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003547 }
John Bauman89401822014-05-06 15:04:28 -04003548
Alexis Hetu2b052f82015-11-25 13:57:28 -05003549 unlockStencil();
John Bauman89401822014-05-06 15:04:28 -04003550 }
3551
3552 void Surface::fill(const Color<float> &color, int x0, int y0, int width, int height)
3553 {
3554 unsigned char *row;
3555 Buffer *buffer;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003556
John Bauman89401822014-05-06 15:04:28 -04003557 if(internal.dirty)
3558 {
3559 row = (unsigned char*)lockInternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3560 buffer = &internal;
3561 }
3562 else
3563 {
3564 row = (unsigned char*)lockExternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3565 buffer = &external;
3566 }
3567
3568 if(buffer->bytes <= 4)
3569 {
3570 int c;
3571 buffer->write(&c, color);
3572
3573 if(buffer->bytes <= 1) c = (c << 8) | c;
3574 if(buffer->bytes <= 2) c = (c << 16) | c;
3575
3576 for(int y = 0; y < height; y++)
3577 {
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003578 memfill4(row, c, width * buffer->bytes);
John Bauman89401822014-05-06 15:04:28 -04003579
3580 row += buffer->pitchB;
3581 }
3582 }
3583 else // Generic
3584 {
3585 for(int y = 0; y < height; y++)
3586 {
3587 unsigned char *element = row;
3588
3589 for(int x = 0; x < width; x++)
3590 {
3591 buffer->write(element, color);
3592
3593 element += buffer->bytes;
3594 }
3595
3596 row += buffer->pitchB;
3597 }
3598 }
3599
3600 if(buffer == &internal)
3601 {
3602 unlockInternal();
3603 }
3604 else
3605 {
3606 unlockExternal();
3607 }
3608 }
3609
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003610 void Surface::copyInternal(const Surface *source, int x, int y, float srcX, float srcY, bool filter)
John Bauman89401822014-05-06 15:04:28 -04003611 {
Alexis Hetu43577b82015-10-21 15:32:16 -04003612 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
John Bauman89401822014-05-06 15:04:28 -04003613
Alexis Hetu43577b82015-10-21 15:32:16 -04003614 sw::Color<float> color;
John Bauman89401822014-05-06 15:04:28 -04003615
Alexis Hetu43577b82015-10-21 15:32:16 -04003616 if(!filter)
3617 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003618 color = source->internal.read((int)srcX, (int)srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003619 }
3620 else // Bilinear filtering
3621 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003622 color = source->internal.sample(srcX, srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003623 }
John Bauman89401822014-05-06 15:04:28 -04003624
3625 internal.write(x, y, color);
3626 }
3627
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003628 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 -04003629 {
3630 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
3631
3632 sw::Color<float> color;
3633
3634 if(!filter)
3635 {
3636 color = source->internal.read((int)srcX, (int)srcY, int(srcZ));
3637 }
3638 else // Bilinear filtering
3639 {
3640 color = source->internal.sample(srcX, srcY, srcZ);
3641 }
3642
3643 internal.write(x, y, z, color);
3644 }
3645
Alexis Hetua76a1bf2016-11-29 17:17:26 -05003646 void Surface::copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge)
3647 {
3648 Surface *dst = this;
3649
3650 // Figure out if the edges to be copied in reverse order respectively from one another
3651 // The copy should be reversed whenever the same edges are contiguous or if we're
3652 // copying top <-> right or bottom <-> left. This is explained by the layout, which is:
3653 //
3654 // | +y |
3655 // | -x | +z | +x | -z |
3656 // | -y |
3657
3658 bool reverse = (srcEdge == dstEdge) ||
3659 ((srcEdge == TOP) && (dstEdge == RIGHT)) ||
3660 ((srcEdge == RIGHT) && (dstEdge == TOP)) ||
3661 ((srcEdge == BOTTOM) && (dstEdge == LEFT)) ||
3662 ((srcEdge == LEFT) && (dstEdge == BOTTOM));
3663
3664 int srcBytes = src->bytes(src->Surface::getInternalFormat());
3665 int srcPitch = src->getInternalPitchB();
3666 int dstBytes = dst->bytes(dst->Surface::getInternalFormat());
3667 int dstPitch = dst->getInternalPitchB();
3668
3669 int srcW = src->getWidth();
3670 int srcH = src->getHeight();
3671 int dstW = dst->getWidth();
3672 int dstH = dst->getHeight();
3673
3674 ASSERT(srcW == srcH && dstW == dstH && srcW == dstW && srcBytes == dstBytes);
3675
3676 // Src is expressed in the regular [0, width-1], [0, height-1] space
3677 int srcDelta = ((srcEdge == TOP) || (srcEdge == BOTTOM)) ? srcBytes : srcPitch;
3678 int srcStart = ((srcEdge == BOTTOM) ? srcPitch * (srcH - 1) : ((srcEdge == RIGHT) ? srcBytes * (srcW - 1) : 0));
3679
3680 // Dst contains borders, so it is expressed in the [-1, width+1], [-1, height+1] space
3681 int dstDelta = (((dstEdge == TOP) || (dstEdge == BOTTOM)) ? dstBytes : dstPitch) * (reverse ? -1 : 1);
3682 int dstStart = ((dstEdge == BOTTOM) ? dstPitch * (dstH + 1) : ((dstEdge == RIGHT) ? dstBytes * (dstW + 1) : 0)) + (reverse ? dstW * -dstDelta : dstDelta);
3683
3684 char *srcBuf = (char*)src->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PRIVATE) + srcStart;
3685 char *dstBuf = (char*)dst->lockInternal(-1, -1, 0, sw::LOCK_READWRITE, sw::PRIVATE) + dstStart;
3686
3687 for(int i = 0; i < srcW; ++i, dstBuf += dstDelta, srcBuf += srcDelta)
3688 {
3689 memcpy(dstBuf, srcBuf, srcBytes);
3690 }
3691
3692 if(dstEdge == LEFT || dstEdge == RIGHT)
3693 {
3694 // TOP and BOTTOM are already set, let's average out the corners
3695 int x0 = (dstEdge == RIGHT) ? dstW : -1;
3696 int y0 = -1;
3697 int x1 = (dstEdge == RIGHT) ? dstW - 1 : 0;
3698 int y1 = 0;
3699 dst->computeCubeCorner(x0, y0, x1, y1);
3700 y0 = dstH;
3701 y1 = dstH - 1;
3702 dst->computeCubeCorner(x0, y0, x1, y1);
3703 }
3704
3705 src->unlockInternal();
3706 dst->unlockInternal();
3707 }
3708
3709 void Surface::computeCubeCorner(int x0, int y0, int x1, int y1)
3710 {
3711 ASSERT(internal.lock != LOCK_UNLOCKED);
3712
3713 sw::Color<float> color = internal.read(x0, y1);
3714 color += internal.read(x1, y0);
3715 color += internal.read(x1, y1);
3716 color *= (1.0f / 3.0f);
3717
3718 internal.write(x0, y0, color);
3719 }
3720
John Bauman89401822014-05-06 15:04:28 -04003721 bool Surface::hasStencil() const
3722 {
3723 return isStencil(external.format);
3724 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04003725
John Bauman89401822014-05-06 15:04:28 -04003726 bool Surface::hasDepth() const
3727 {
3728 return isDepth(external.format);
3729 }
3730
3731 bool Surface::hasPalette() const
3732 {
3733 return isPalette(external.format);
3734 }
3735
3736 bool Surface::isRenderTarget() const
3737 {
3738 return renderTarget;
3739 }
3740
Nicolas Capens73e18c12017-11-28 13:31:35 -05003741 bool Surface::hasDirtyContents() const
John Bauman89401822014-05-06 15:04:28 -04003742 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003743 return dirtyContents;
John Bauman89401822014-05-06 15:04:28 -04003744 }
3745
Nicolas Capens73e18c12017-11-28 13:31:35 -05003746 void Surface::markContentsClean()
John Bauman89401822014-05-06 15:04:28 -04003747 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003748 dirtyContents = false;
John Bauman89401822014-05-06 15:04:28 -04003749 }
3750
3751 Resource *Surface::getResource()
3752 {
3753 return resource;
3754 }
3755
3756 bool Surface::identicalFormats() const
3757 {
John Bauman66b8ab22014-05-06 15:57:45 -04003758 return external.format == internal.format &&
3759 external.width == internal.width &&
Nicolas Capens22658242014-11-29 00:31:41 -05003760 external.height == internal.height &&
3761 external.depth == internal.depth &&
3762 external.pitchB == internal.pitchB &&
Alexis Hetu9c6d5222016-11-29 17:02:14 -05003763 external.sliceB == internal.sliceB &&
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003764 external.border == internal.border &&
3765 external.samples == internal.samples;
John Bauman89401822014-05-06 15:04:28 -04003766 }
3767
3768 Format Surface::selectInternalFormat(Format format) const
3769 {
3770 switch(format)
3771 {
3772 case FORMAT_NULL:
3773 return FORMAT_NULL;
3774 case FORMAT_P8:
3775 case FORMAT_A8P8:
3776 case FORMAT_A4R4G4B4:
3777 case FORMAT_A1R5G5B5:
3778 case FORMAT_A8R3G3B2:
3779 return FORMAT_A8R8G8B8;
3780 case FORMAT_A8:
3781 return FORMAT_A8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003782 case FORMAT_R8I:
3783 return FORMAT_R8I;
3784 case FORMAT_R8UI:
3785 return FORMAT_R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003786 case FORMAT_R8_SNORM:
3787 return FORMAT_R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003788 case FORMAT_R8:
3789 return FORMAT_R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003790 case FORMAT_R16I:
3791 return FORMAT_R16I;
3792 case FORMAT_R16UI:
3793 return FORMAT_R16UI;
3794 case FORMAT_R32I:
3795 return FORMAT_R32I;
3796 case FORMAT_R32UI:
3797 return FORMAT_R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003798 case FORMAT_X16B16G16R16I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003799 return FORMAT_X16B16G16R16I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003800 case FORMAT_A16B16G16R16I:
3801 return FORMAT_A16B16G16R16I;
3802 case FORMAT_X16B16G16R16UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003803 return FORMAT_X16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003804 case FORMAT_A16B16G16R16UI:
3805 return FORMAT_A16B16G16R16UI;
Alexis Hetuf999a002015-12-17 11:09:36 -05003806 case FORMAT_A2R10G10B10:
3807 case FORMAT_A2B10G10R10:
John Bauman89401822014-05-06 15:04:28 -04003808 case FORMAT_A16B16G16R16:
3809 return FORMAT_A16B16G16R16;
Nicolas Capens5555af42017-12-14 13:14:03 -05003810 case FORMAT_A2B10G10R10UI:
3811 return FORMAT_A16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003812 case FORMAT_X32B32G32R32I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003813 return FORMAT_X32B32G32R32I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003814 case FORMAT_A32B32G32R32I:
3815 return FORMAT_A32B32G32R32I;
3816 case FORMAT_X32B32G32R32UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003817 return FORMAT_X32B32G32R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003818 case FORMAT_A32B32G32R32UI:
3819 return FORMAT_A32B32G32R32UI;
3820 case FORMAT_G8R8I:
3821 return FORMAT_G8R8I;
3822 case FORMAT_G8R8UI:
3823 return FORMAT_G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003824 case FORMAT_G8R8_SNORM:
3825 return FORMAT_G8R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003826 case FORMAT_G8R8:
3827 return FORMAT_G8R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003828 case FORMAT_G16R16I:
3829 return FORMAT_G16R16I;
3830 case FORMAT_G16R16UI:
3831 return FORMAT_G16R16UI;
John Bauman89401822014-05-06 15:04:28 -04003832 case FORMAT_G16R16:
3833 return FORMAT_G16R16;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003834 case FORMAT_G32R32I:
3835 return FORMAT_G32R32I;
3836 case FORMAT_G32R32UI:
3837 return FORMAT_G32R32UI;
John Bauman89401822014-05-06 15:04:28 -04003838 case FORMAT_A8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003839 if(lockable || !quadLayoutEnabled)
3840 {
3841 return FORMAT_A8R8G8B8;
3842 }
3843 else
3844 {
3845 return FORMAT_A8G8R8B8Q;
3846 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003847 case FORMAT_A8B8G8R8I:
3848 return FORMAT_A8B8G8R8I;
3849 case FORMAT_A8B8G8R8UI:
3850 return FORMAT_A8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003851 case FORMAT_A8B8G8R8_SNORM:
3852 return FORMAT_A8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003853 case FORMAT_R5G5B5A1:
3854 case FORMAT_R4G4B4A4:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003855 case FORMAT_A8B8G8R8:
3856 return FORMAT_A8B8G8R8;
John Bauman89401822014-05-06 15:04:28 -04003857 case FORMAT_R5G6B5:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003858 return FORMAT_R5G6B5;
3859 case FORMAT_R3G3B2:
John Bauman89401822014-05-06 15:04:28 -04003860 case FORMAT_R8G8B8:
3861 case FORMAT_X4R4G4B4:
3862 case FORMAT_X1R5G5B5:
3863 case FORMAT_X8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003864 if(lockable || !quadLayoutEnabled)
3865 {
3866 return FORMAT_X8R8G8B8;
3867 }
3868 else
3869 {
3870 return FORMAT_X8G8R8B8Q;
3871 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003872 case FORMAT_X8B8G8R8I:
3873 return FORMAT_X8B8G8R8I;
3874 case FORMAT_X8B8G8R8UI:
3875 return FORMAT_X8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003876 case FORMAT_X8B8G8R8_SNORM:
3877 return FORMAT_X8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003878 case FORMAT_B8G8R8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003879 case FORMAT_X8B8G8R8:
3880 return FORMAT_X8B8G8R8;
Alexis Hetu049a1872016-04-25 16:59:58 -04003881 case FORMAT_SRGB8_X8:
3882 return FORMAT_SRGB8_X8;
3883 case FORMAT_SRGB8_A8:
3884 return FORMAT_SRGB8_A8;
John Bauman89401822014-05-06 15:04:28 -04003885 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04003886 case FORMAT_DXT1:
3887 case FORMAT_DXT3:
3888 case FORMAT_DXT5:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003889 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3890 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3891 case FORMAT_RGBA8_ETC2_EAC:
3892 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3893 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3894 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3895 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3896 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3897 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3898 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3899 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3900 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3901 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3902 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3903 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3904 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3905 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3906 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
3907 return FORMAT_A8R8G8B8;
3908 case FORMAT_RGBA_ASTC_4x4_KHR:
3909 case FORMAT_RGBA_ASTC_5x4_KHR:
3910 case FORMAT_RGBA_ASTC_5x5_KHR:
3911 case FORMAT_RGBA_ASTC_6x5_KHR:
3912 case FORMAT_RGBA_ASTC_6x6_KHR:
3913 case FORMAT_RGBA_ASTC_8x5_KHR:
3914 case FORMAT_RGBA_ASTC_8x6_KHR:
3915 case FORMAT_RGBA_ASTC_8x8_KHR:
3916 case FORMAT_RGBA_ASTC_10x5_KHR:
3917 case FORMAT_RGBA_ASTC_10x6_KHR:
3918 case FORMAT_RGBA_ASTC_10x8_KHR:
3919 case FORMAT_RGBA_ASTC_10x10_KHR:
3920 case FORMAT_RGBA_ASTC_12x10_KHR:
3921 case FORMAT_RGBA_ASTC_12x12_KHR:
3922 // ASTC supports HDR, so a floating point format is required to represent it properly
3923 return FORMAT_A32B32G32R32F; // FIXME: 16FP is probably sufficient, but it's currently unsupported
John Bauman89401822014-05-06 15:04:28 -04003924 case FORMAT_ATI1:
3925 return FORMAT_R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003926 case FORMAT_R11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003927 case FORMAT_SIGNED_R11_EAC:
3928 return FORMAT_R32F; // FIXME: Signed 8bit format would be sufficient
John Bauman89401822014-05-06 15:04:28 -04003929 case FORMAT_ATI2:
3930 return FORMAT_G8R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003931 case FORMAT_RG11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003932 case FORMAT_SIGNED_RG11_EAC:
3933 return FORMAT_G32R32F; // FIXME: Signed 8bit format would be sufficient
Nicolas Capens22658242014-11-29 00:31:41 -05003934 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003935 case FORMAT_RGB8_ETC2:
3936 case FORMAT_SRGB8_ETC2:
Nicolas Capens22658242014-11-29 00:31:41 -05003937 return FORMAT_X8R8G8B8;
John Bauman89401822014-05-06 15:04:28 -04003938 // Bumpmap formats
3939 case FORMAT_V8U8: return FORMAT_V8U8;
3940 case FORMAT_L6V5U5: return FORMAT_X8L8V8U8;
3941 case FORMAT_Q8W8V8U8: return FORMAT_Q8W8V8U8;
3942 case FORMAT_X8L8V8U8: return FORMAT_X8L8V8U8;
3943 case FORMAT_V16U16: return FORMAT_V16U16;
3944 case FORMAT_A2W10V10U10: return FORMAT_A16W16V16U16;
3945 case FORMAT_Q16W16V16U16: return FORMAT_Q16W16V16U16;
3946 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04003947 case FORMAT_A16F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003948 case FORMAT_R16F: return FORMAT_R32F;
3949 case FORMAT_G16R16F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003950 case FORMAT_B16G16R16F: return FORMAT_X32B32G32R32F;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05003951 case FORMAT_X16B16G16R16F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003952 case FORMAT_A16B16G16R16F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003953 case FORMAT_X16B16G16R16F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
Nicolas Capens80594422015-06-09 16:42:56 -04003954 case FORMAT_A32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003955 case FORMAT_R32F: return FORMAT_R32F;
3956 case FORMAT_G32R32F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003957 case FORMAT_B32G32R32F: return FORMAT_X32B32G32R32F;
3958 case FORMAT_X32B32G32R32F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003959 case FORMAT_A32B32G32R32F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003960 case FORMAT_X32B32G32R32F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
John Bauman89401822014-05-06 15:04:28 -04003961 // Luminance formats
3962 case FORMAT_L8: return FORMAT_L8;
3963 case FORMAT_A4L4: return FORMAT_A8L8;
3964 case FORMAT_L16: return FORMAT_L16;
3965 case FORMAT_A8L8: return FORMAT_A8L8;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003966 case FORMAT_L16F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003967 case FORMAT_A16L16F: return FORMAT_A32B32G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003968 case FORMAT_L32F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003969 case FORMAT_A32L32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003970 // Depth/stencil formats
3971 case FORMAT_D16:
3972 case FORMAT_D32:
3973 case FORMAT_D24X8:
John Bauman89401822014-05-06 15:04:28 -04003974 if(hasParent) // Texture
3975 {
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003976 return FORMAT_D32F_SHADOW;
John Bauman89401822014-05-06 15:04:28 -04003977 }
3978 else if(complementaryDepthBuffer)
3979 {
3980 return FORMAT_D32F_COMPLEMENTARY;
3981 }
3982 else
3983 {
3984 return FORMAT_D32F;
3985 }
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003986 case FORMAT_D24S8:
3987 case FORMAT_D24FS8:
3988 if(hasParent) // Texture
3989 {
3990 return FORMAT_D32FS8_SHADOW;
3991 }
3992 else if(complementaryDepthBuffer)
3993 {
3994 return FORMAT_D32FS8_COMPLEMENTARY;
3995 }
3996 else
3997 {
3998 return FORMAT_D32FS8;
3999 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04004000 case FORMAT_D32F: return FORMAT_D32F;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05004001 case FORMAT_D32FS8: return FORMAT_D32FS8;
John Bauman66b8ab22014-05-06 15:57:45 -04004002 case FORMAT_D32F_LOCKABLE: return FORMAT_D32F_LOCKABLE;
4003 case FORMAT_D32FS8_TEXTURE: return FORMAT_D32FS8_TEXTURE;
4004 case FORMAT_INTZ: return FORMAT_D32FS8_TEXTURE;
4005 case FORMAT_DF24S8: return FORMAT_D32FS8_SHADOW;
4006 case FORMAT_DF16S8: return FORMAT_D32FS8_SHADOW;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05004007 case FORMAT_S8: return FORMAT_S8;
4008 // YUV formats
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04004009 case FORMAT_YV12_BT601: return FORMAT_YV12_BT601;
4010 case FORMAT_YV12_BT709: return FORMAT_YV12_BT709;
4011 case FORMAT_YV12_JFIF: return FORMAT_YV12_JFIF;
John Bauman89401822014-05-06 15:04:28 -04004012 default:
4013 ASSERT(false);
4014 }
4015
4016 return FORMAT_NULL;
4017 }
4018
4019 void Surface::setTexturePalette(unsigned int *palette)
4020 {
4021 Surface::palette = palette;
4022 Surface::paletteID++;
4023 }
4024
4025 void Surface::resolve()
4026 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004027 if(internal.samples <= 1 || !internal.dirty || !renderTarget || internal.format == FORMAT_NULL)
John Bauman89401822014-05-06 15:04:28 -04004028 {
4029 return;
4030 }
4031
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004032 ASSERT(internal.depth == 1); // Unimplemented
4033
John Bauman89401822014-05-06 15:04:28 -04004034 void *source = internal.lockRect(0, 0, 0, LOCK_READWRITE);
4035
John Bauman89401822014-05-06 15:04:28 -04004036 int width = internal.width;
4037 int height = internal.height;
4038 int pitch = internal.pitchB;
4039 int slice = internal.sliceB;
4040
4041 unsigned char *source0 = (unsigned char*)source;
4042 unsigned char *source1 = source0 + slice;
4043 unsigned char *source2 = source1 + slice;
4044 unsigned char *source3 = source2 + slice;
4045 unsigned char *source4 = source3 + slice;
4046 unsigned char *source5 = source4 + slice;
4047 unsigned char *source6 = source5 + slice;
4048 unsigned char *source7 = source6 + slice;
4049 unsigned char *source8 = source7 + slice;
4050 unsigned char *source9 = source8 + slice;
4051 unsigned char *sourceA = source9 + slice;
4052 unsigned char *sourceB = sourceA + slice;
4053 unsigned char *sourceC = sourceB + slice;
4054 unsigned char *sourceD = sourceC + slice;
4055 unsigned char *sourceE = sourceD + slice;
4056 unsigned char *sourceF = sourceE + slice;
4057
Alexis Hetu049a1872016-04-25 16:59:58 -04004058 if(internal.format == FORMAT_X8R8G8B8 || internal.format == FORMAT_A8R8G8B8 ||
4059 internal.format == FORMAT_X8B8G8R8 || internal.format == FORMAT_A8B8G8R8 ||
4060 internal.format == FORMAT_SRGB8_X8 || internal.format == FORMAT_SRGB8_A8)
John Bauman89401822014-05-06 15:04:28 -04004061 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004062 #if defined(__i386__) || defined(__x86_64__)
4063 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004064 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004065 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004066 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004067 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004068 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004069 for(int x = 0; x < width; x += 4)
4070 {
4071 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4072 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004073
Nicolas Capens47dc8672017-04-25 12:54:39 -04004074 c0 = _mm_avg_epu8(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004075
Nicolas Capens47dc8672017-04-25 12:54:39 -04004076 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4077 }
4078
4079 source0 += pitch;
4080 source1 += 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 == 4)
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));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004093
Nicolas Capens47dc8672017-04-25 12:54:39 -04004094 c0 = _mm_avg_epu8(c0, c1);
4095 c2 = _mm_avg_epu8(c2, c3);
4096 c0 = _mm_avg_epu8(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004097
Nicolas Capens47dc8672017-04-25 12:54:39 -04004098 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4099 }
4100
4101 source0 += pitch;
4102 source1 += pitch;
4103 source2 += pitch;
4104 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004105 }
John Bauman89401822014-05-06 15:04:28 -04004106 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004107 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004108 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004109 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004110 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004111 for(int x = 0; x < width; x += 4)
4112 {
4113 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4114 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4115 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4116 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4117 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4118 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4119 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4120 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004121
Nicolas Capens47dc8672017-04-25 12:54:39 -04004122 c0 = _mm_avg_epu8(c0, c1);
4123 c2 = _mm_avg_epu8(c2, c3);
4124 c4 = _mm_avg_epu8(c4, c5);
4125 c6 = _mm_avg_epu8(c6, c7);
4126 c0 = _mm_avg_epu8(c0, c2);
4127 c4 = _mm_avg_epu8(c4, c6);
4128 c0 = _mm_avg_epu8(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004129
Nicolas Capens47dc8672017-04-25 12:54:39 -04004130 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4131 }
4132
4133 source0 += pitch;
4134 source1 += pitch;
4135 source2 += pitch;
4136 source3 += pitch;
4137 source4 += pitch;
4138 source5 += pitch;
4139 source6 += pitch;
4140 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004141 }
John Bauman89401822014-05-06 15:04:28 -04004142 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004143 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004144 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004145 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004146 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004147 for(int x = 0; x < width; x += 4)
4148 {
4149 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4150 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4151 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4152 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4153 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4154 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4155 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4156 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4157 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4158 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4159 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4160 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4161 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4162 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4163 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4164 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004165
Nicolas Capens47dc8672017-04-25 12:54:39 -04004166 c0 = _mm_avg_epu8(c0, c1);
4167 c2 = _mm_avg_epu8(c2, c3);
4168 c4 = _mm_avg_epu8(c4, c5);
4169 c6 = _mm_avg_epu8(c6, c7);
4170 c8 = _mm_avg_epu8(c8, c9);
4171 cA = _mm_avg_epu8(cA, cB);
4172 cC = _mm_avg_epu8(cC, cD);
4173 cE = _mm_avg_epu8(cE, cF);
4174 c0 = _mm_avg_epu8(c0, c2);
4175 c4 = _mm_avg_epu8(c4, c6);
4176 c8 = _mm_avg_epu8(c8, cA);
4177 cC = _mm_avg_epu8(cC, cE);
4178 c0 = _mm_avg_epu8(c0, c4);
4179 c8 = _mm_avg_epu8(c8, cC);
4180 c0 = _mm_avg_epu8(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004181
Nicolas Capens47dc8672017-04-25 12:54:39 -04004182 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4183 }
4184
4185 source0 += pitch;
4186 source1 += pitch;
4187 source2 += pitch;
4188 source3 += pitch;
4189 source4 += pitch;
4190 source5 += pitch;
4191 source6 += pitch;
4192 source7 += pitch;
4193 source8 += pitch;
4194 source9 += pitch;
4195 sourceA += pitch;
4196 sourceB += pitch;
4197 sourceC += pitch;
4198 sourceD += pitch;
4199 sourceE += pitch;
4200 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004201 }
John Bauman89401822014-05-06 15:04:28 -04004202 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004203 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004204 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004205 else
4206 #endif
John Bauman89401822014-05-06 15:04:28 -04004207 {
4208 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7F7F7F7F) + (((x) ^ (y)) & 0x01010101))
4209
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004210 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004211 {
4212 for(int y = 0; y < height; y++)
4213 {
4214 for(int x = 0; x < width; x++)
4215 {
4216 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4217 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4218
4219 c0 = AVERAGE(c0, c1);
4220
4221 *(unsigned int*)(source0 + 4 * x) = c0;
4222 }
4223
4224 source0 += pitch;
4225 source1 += pitch;
4226 }
4227 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004228 else if(internal.samples == 4)
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
4239 c0 = AVERAGE(c0, c1);
4240 c2 = AVERAGE(c2, c3);
4241 c0 = AVERAGE(c0, c2);
4242
4243 *(unsigned int*)(source0 + 4 * x) = c0;
4244 }
4245
4246 source0 += pitch;
4247 source1 += pitch;
4248 source2 += pitch;
4249 source3 += pitch;
4250 }
4251 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004252 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004253 {
4254 for(int y = 0; y < height; y++)
4255 {
4256 for(int x = 0; x < width; x++)
4257 {
4258 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4259 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4260 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4261 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4262 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4263 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4264 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4265 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4266
4267 c0 = AVERAGE(c0, c1);
4268 c2 = AVERAGE(c2, c3);
4269 c4 = AVERAGE(c4, c5);
4270 c6 = AVERAGE(c6, c7);
4271 c0 = AVERAGE(c0, c2);
4272 c4 = AVERAGE(c4, c6);
4273 c0 = AVERAGE(c0, c4);
4274
4275 *(unsigned int*)(source0 + 4 * x) = c0;
4276 }
4277
4278 source0 += pitch;
4279 source1 += pitch;
4280 source2 += pitch;
4281 source3 += pitch;
4282 source4 += pitch;
4283 source5 += pitch;
4284 source6 += pitch;
4285 source7 += pitch;
4286 }
4287 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004288 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004289 {
4290 for(int y = 0; y < height; y++)
4291 {
4292 for(int x = 0; x < width; x++)
4293 {
4294 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4295 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4296 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4297 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4298 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4299 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4300 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4301 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4302 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4303 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4304 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4305 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4306 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4307 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4308 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4309 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4310
4311 c0 = AVERAGE(c0, c1);
4312 c2 = AVERAGE(c2, c3);
4313 c4 = AVERAGE(c4, c5);
4314 c6 = AVERAGE(c6, c7);
4315 c8 = AVERAGE(c8, c9);
4316 cA = AVERAGE(cA, cB);
4317 cC = AVERAGE(cC, cD);
4318 cE = AVERAGE(cE, cF);
4319 c0 = AVERAGE(c0, c2);
4320 c4 = AVERAGE(c4, c6);
4321 c8 = AVERAGE(c8, cA);
4322 cC = AVERAGE(cC, cE);
4323 c0 = AVERAGE(c0, c4);
4324 c8 = AVERAGE(c8, cC);
4325 c0 = AVERAGE(c0, c8);
4326
4327 *(unsigned int*)(source0 + 4 * x) = c0;
4328 }
4329
4330 source0 += pitch;
4331 source1 += pitch;
4332 source2 += pitch;
4333 source3 += pitch;
4334 source4 += pitch;
4335 source5 += pitch;
4336 source6 += pitch;
4337 source7 += pitch;
4338 source8 += pitch;
4339 source9 += pitch;
4340 sourceA += pitch;
4341 sourceB += pitch;
4342 sourceC += pitch;
4343 sourceD += pitch;
4344 sourceE += pitch;
4345 sourceF += pitch;
4346 }
4347 }
4348 else ASSERT(false);
4349
4350 #undef AVERAGE
4351 }
4352 }
4353 else if(internal.format == FORMAT_G16R16)
4354 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004355
4356 #if defined(__i386__) || defined(__x86_64__)
4357 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004358 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004359 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004360 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004361 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004362 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004363 for(int x = 0; x < width; x += 4)
4364 {
4365 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4366 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004367
Nicolas Capens47dc8672017-04-25 12:54:39 -04004368 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004369
Nicolas Capens47dc8672017-04-25 12:54:39 -04004370 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4371 }
4372
4373 source0 += pitch;
4374 source1 += 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 == 4)
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));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004387
Nicolas Capens47dc8672017-04-25 12:54:39 -04004388 c0 = _mm_avg_epu16(c0, c1);
4389 c2 = _mm_avg_epu16(c2, c3);
4390 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004391
Nicolas Capens47dc8672017-04-25 12:54:39 -04004392 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4393 }
4394
4395 source0 += pitch;
4396 source1 += pitch;
4397 source2 += pitch;
4398 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004399 }
John Bauman89401822014-05-06 15:04:28 -04004400 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004401 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004402 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004403 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004404 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004405 for(int x = 0; x < width; x += 4)
4406 {
4407 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4408 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4409 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4410 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4411 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4412 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4413 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4414 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004415
Nicolas Capens47dc8672017-04-25 12:54:39 -04004416 c0 = _mm_avg_epu16(c0, c1);
4417 c2 = _mm_avg_epu16(c2, c3);
4418 c4 = _mm_avg_epu16(c4, c5);
4419 c6 = _mm_avg_epu16(c6, c7);
4420 c0 = _mm_avg_epu16(c0, c2);
4421 c4 = _mm_avg_epu16(c4, c6);
4422 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004423
Nicolas Capens47dc8672017-04-25 12:54:39 -04004424 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4425 }
4426
4427 source0 += pitch;
4428 source1 += pitch;
4429 source2 += pitch;
4430 source3 += pitch;
4431 source4 += pitch;
4432 source5 += pitch;
4433 source6 += pitch;
4434 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004435 }
John Bauman89401822014-05-06 15:04:28 -04004436 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004437 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004438 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004439 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004440 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004441 for(int x = 0; x < width; x += 4)
4442 {
4443 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4444 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4445 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4446 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4447 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4448 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4449 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4450 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4451 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4452 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4453 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4454 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4455 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4456 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4457 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4458 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004459
Nicolas Capens47dc8672017-04-25 12:54:39 -04004460 c0 = _mm_avg_epu16(c0, c1);
4461 c2 = _mm_avg_epu16(c2, c3);
4462 c4 = _mm_avg_epu16(c4, c5);
4463 c6 = _mm_avg_epu16(c6, c7);
4464 c8 = _mm_avg_epu16(c8, c9);
4465 cA = _mm_avg_epu16(cA, cB);
4466 cC = _mm_avg_epu16(cC, cD);
4467 cE = _mm_avg_epu16(cE, cF);
4468 c0 = _mm_avg_epu16(c0, c2);
4469 c4 = _mm_avg_epu16(c4, c6);
4470 c8 = _mm_avg_epu16(c8, cA);
4471 cC = _mm_avg_epu16(cC, cE);
4472 c0 = _mm_avg_epu16(c0, c4);
4473 c8 = _mm_avg_epu16(c8, cC);
4474 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004475
Nicolas Capens47dc8672017-04-25 12:54:39 -04004476 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4477 }
4478
4479 source0 += pitch;
4480 source1 += pitch;
4481 source2 += pitch;
4482 source3 += pitch;
4483 source4 += pitch;
4484 source5 += pitch;
4485 source6 += pitch;
4486 source7 += pitch;
4487 source8 += pitch;
4488 source9 += pitch;
4489 sourceA += pitch;
4490 sourceB += pitch;
4491 sourceC += pitch;
4492 sourceD += pitch;
4493 sourceE += pitch;
4494 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004495 }
John Bauman89401822014-05-06 15:04:28 -04004496 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004497 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004498 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004499 else
4500 #endif
John Bauman89401822014-05-06 15:04:28 -04004501 {
4502 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4503
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004504 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004505 {
4506 for(int y = 0; y < height; y++)
4507 {
4508 for(int x = 0; x < width; x++)
4509 {
4510 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4511 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4512
4513 c0 = AVERAGE(c0, c1);
4514
4515 *(unsigned int*)(source0 + 4 * x) = c0;
4516 }
4517
4518 source0 += pitch;
4519 source1 += pitch;
4520 }
4521 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004522 else if(internal.samples == 4)
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
4533 c0 = AVERAGE(c0, c1);
4534 c2 = AVERAGE(c2, c3);
4535 c0 = AVERAGE(c0, c2);
4536
4537 *(unsigned int*)(source0 + 4 * x) = c0;
4538 }
4539
4540 source0 += pitch;
4541 source1 += pitch;
4542 source2 += pitch;
4543 source3 += pitch;
4544 }
4545 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004546 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004547 {
4548 for(int y = 0; y < height; y++)
4549 {
4550 for(int x = 0; x < width; x++)
4551 {
4552 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4553 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4554 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4555 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4556 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4557 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4558 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4559 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4560
4561 c0 = AVERAGE(c0, c1);
4562 c2 = AVERAGE(c2, c3);
4563 c4 = AVERAGE(c4, c5);
4564 c6 = AVERAGE(c6, c7);
4565 c0 = AVERAGE(c0, c2);
4566 c4 = AVERAGE(c4, c6);
4567 c0 = AVERAGE(c0, c4);
4568
4569 *(unsigned int*)(source0 + 4 * x) = c0;
4570 }
4571
4572 source0 += pitch;
4573 source1 += pitch;
4574 source2 += pitch;
4575 source3 += pitch;
4576 source4 += pitch;
4577 source5 += pitch;
4578 source6 += pitch;
4579 source7 += pitch;
4580 }
4581 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004582 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004583 {
4584 for(int y = 0; y < height; y++)
4585 {
4586 for(int x = 0; x < width; x++)
4587 {
4588 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4589 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4590 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4591 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4592 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4593 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4594 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4595 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4596 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4597 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4598 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4599 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4600 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4601 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4602 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4603 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4604
4605 c0 = AVERAGE(c0, c1);
4606 c2 = AVERAGE(c2, c3);
4607 c4 = AVERAGE(c4, c5);
4608 c6 = AVERAGE(c6, c7);
4609 c8 = AVERAGE(c8, c9);
4610 cA = AVERAGE(cA, cB);
4611 cC = AVERAGE(cC, cD);
4612 cE = AVERAGE(cE, cF);
4613 c0 = AVERAGE(c0, c2);
4614 c4 = AVERAGE(c4, c6);
4615 c8 = AVERAGE(c8, cA);
4616 cC = AVERAGE(cC, cE);
4617 c0 = AVERAGE(c0, c4);
4618 c8 = AVERAGE(c8, cC);
4619 c0 = AVERAGE(c0, c8);
4620
4621 *(unsigned int*)(source0 + 4 * x) = c0;
4622 }
4623
4624 source0 += pitch;
4625 source1 += pitch;
4626 source2 += pitch;
4627 source3 += pitch;
4628 source4 += pitch;
4629 source5 += pitch;
4630 source6 += pitch;
4631 source7 += pitch;
4632 source8 += pitch;
4633 source9 += pitch;
4634 sourceA += pitch;
4635 sourceB += pitch;
4636 sourceC += pitch;
4637 sourceD += pitch;
4638 sourceE += pitch;
4639 sourceF += pitch;
4640 }
4641 }
4642 else ASSERT(false);
4643
4644 #undef AVERAGE
4645 }
4646 }
4647 else if(internal.format == FORMAT_A16B16G16R16)
4648 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004649 #if defined(__i386__) || defined(__x86_64__)
4650 if(CPUID::supportsSSE2() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04004651 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004652 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004653 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004654 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004655 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004656 for(int x = 0; x < width; x += 2)
4657 {
4658 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4659 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004660
Nicolas Capens47dc8672017-04-25 12:54:39 -04004661 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004662
Nicolas Capens47dc8672017-04-25 12:54:39 -04004663 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4664 }
4665
4666 source0 += pitch;
4667 source1 += 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 == 4)
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));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004680
Nicolas Capens47dc8672017-04-25 12:54:39 -04004681 c0 = _mm_avg_epu16(c0, c1);
4682 c2 = _mm_avg_epu16(c2, c3);
4683 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004684
Nicolas Capens47dc8672017-04-25 12:54:39 -04004685 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4686 }
4687
4688 source0 += pitch;
4689 source1 += pitch;
4690 source2 += pitch;
4691 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004692 }
John Bauman89401822014-05-06 15:04:28 -04004693 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004694 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004695 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004696 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004697 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004698 for(int x = 0; x < width; x += 2)
4699 {
4700 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4701 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4702 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4703 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4704 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4705 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4706 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4707 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004708
Nicolas Capens47dc8672017-04-25 12:54:39 -04004709 c0 = _mm_avg_epu16(c0, c1);
4710 c2 = _mm_avg_epu16(c2, c3);
4711 c4 = _mm_avg_epu16(c4, c5);
4712 c6 = _mm_avg_epu16(c6, c7);
4713 c0 = _mm_avg_epu16(c0, c2);
4714 c4 = _mm_avg_epu16(c4, c6);
4715 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004716
Nicolas Capens47dc8672017-04-25 12:54:39 -04004717 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4718 }
4719
4720 source0 += pitch;
4721 source1 += pitch;
4722 source2 += pitch;
4723 source3 += pitch;
4724 source4 += pitch;
4725 source5 += pitch;
4726 source6 += pitch;
4727 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004728 }
John Bauman89401822014-05-06 15:04:28 -04004729 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004730 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004731 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004732 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004733 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004734 for(int x = 0; x < width; x += 2)
4735 {
4736 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4737 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4738 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4739 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4740 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4741 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4742 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4743 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
4744 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 8 * x));
4745 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 8 * x));
4746 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 8 * x));
4747 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 8 * x));
4748 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 8 * x));
4749 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 8 * x));
4750 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 8 * x));
4751 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04004752
Nicolas Capens47dc8672017-04-25 12:54:39 -04004753 c0 = _mm_avg_epu16(c0, c1);
4754 c2 = _mm_avg_epu16(c2, c3);
4755 c4 = _mm_avg_epu16(c4, c5);
4756 c6 = _mm_avg_epu16(c6, c7);
4757 c8 = _mm_avg_epu16(c8, c9);
4758 cA = _mm_avg_epu16(cA, cB);
4759 cC = _mm_avg_epu16(cC, cD);
4760 cE = _mm_avg_epu16(cE, cF);
4761 c0 = _mm_avg_epu16(c0, c2);
4762 c4 = _mm_avg_epu16(c4, c6);
4763 c8 = _mm_avg_epu16(c8, cA);
4764 cC = _mm_avg_epu16(cC, cE);
4765 c0 = _mm_avg_epu16(c0, c4);
4766 c8 = _mm_avg_epu16(c8, cC);
4767 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004768
Nicolas Capens47dc8672017-04-25 12:54:39 -04004769 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4770 }
4771
4772 source0 += pitch;
4773 source1 += pitch;
4774 source2 += pitch;
4775 source3 += pitch;
4776 source4 += pitch;
4777 source5 += pitch;
4778 source6 += pitch;
4779 source7 += pitch;
4780 source8 += pitch;
4781 source9 += pitch;
4782 sourceA += pitch;
4783 sourceB += pitch;
4784 sourceC += pitch;
4785 sourceD += pitch;
4786 sourceE += pitch;
4787 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004788 }
John Bauman89401822014-05-06 15:04:28 -04004789 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004790 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004791 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004792 else
4793 #endif
John Bauman89401822014-05-06 15:04:28 -04004794 {
4795 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4796
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004797 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004798 {
4799 for(int y = 0; y < height; y++)
4800 {
4801 for(int x = 0; x < 2 * width; x++)
4802 {
4803 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4804 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4805
4806 c0 = AVERAGE(c0, c1);
4807
4808 *(unsigned int*)(source0 + 4 * x) = c0;
4809 }
4810
4811 source0 += pitch;
4812 source1 += pitch;
4813 }
4814 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004815 else if(internal.samples == 4)
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
4826 c0 = AVERAGE(c0, c1);
4827 c2 = AVERAGE(c2, c3);
4828 c0 = AVERAGE(c0, c2);
4829
4830 *(unsigned int*)(source0 + 4 * x) = c0;
4831 }
4832
4833 source0 += pitch;
4834 source1 += pitch;
4835 source2 += pitch;
4836 source3 += pitch;
4837 }
4838 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004839 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004840 {
4841 for(int y = 0; y < height; y++)
4842 {
4843 for(int x = 0; x < 2 * width; x++)
4844 {
4845 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4846 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4847 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4848 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4849 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4850 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4851 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4852 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4853
4854 c0 = AVERAGE(c0, c1);
4855 c2 = AVERAGE(c2, c3);
4856 c4 = AVERAGE(c4, c5);
4857 c6 = AVERAGE(c6, c7);
4858 c0 = AVERAGE(c0, c2);
4859 c4 = AVERAGE(c4, c6);
4860 c0 = AVERAGE(c0, c4);
4861
4862 *(unsigned int*)(source0 + 4 * x) = c0;
4863 }
4864
4865 source0 += pitch;
4866 source1 += pitch;
4867 source2 += pitch;
4868 source3 += pitch;
4869 source4 += pitch;
4870 source5 += pitch;
4871 source6 += pitch;
4872 source7 += pitch;
4873 }
4874 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004875 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004876 {
4877 for(int y = 0; y < height; y++)
4878 {
4879 for(int x = 0; x < 2 * width; x++)
4880 {
4881 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4882 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4883 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4884 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4885 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4886 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4887 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4888 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4889 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4890 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4891 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4892 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4893 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4894 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4895 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4896 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4897
4898 c0 = AVERAGE(c0, c1);
4899 c2 = AVERAGE(c2, c3);
4900 c4 = AVERAGE(c4, c5);
4901 c6 = AVERAGE(c6, c7);
4902 c8 = AVERAGE(c8, c9);
4903 cA = AVERAGE(cA, cB);
4904 cC = AVERAGE(cC, cD);
4905 cE = AVERAGE(cE, cF);
4906 c0 = AVERAGE(c0, c2);
4907 c4 = AVERAGE(c4, c6);
4908 c8 = AVERAGE(c8, cA);
4909 cC = AVERAGE(cC, cE);
4910 c0 = AVERAGE(c0, c4);
4911 c8 = AVERAGE(c8, cC);
4912 c0 = AVERAGE(c0, c8);
4913
4914 *(unsigned int*)(source0 + 4 * x) = c0;
4915 }
4916
4917 source0 += pitch;
4918 source1 += pitch;
4919 source2 += pitch;
4920 source3 += pitch;
4921 source4 += pitch;
4922 source5 += pitch;
4923 source6 += pitch;
4924 source7 += pitch;
4925 source8 += pitch;
4926 source9 += pitch;
4927 sourceA += pitch;
4928 sourceB += pitch;
4929 sourceC += pitch;
4930 sourceD += pitch;
4931 sourceE += pitch;
4932 sourceF += pitch;
4933 }
4934 }
4935 else ASSERT(false);
4936
4937 #undef AVERAGE
4938 }
4939 }
4940 else if(internal.format == FORMAT_R32F)
4941 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004942 #if defined(__i386__) || defined(__x86_64__)
4943 if(CPUID::supportsSSE() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004944 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004945 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004946 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004947 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004948 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004949 for(int x = 0; x < width; x += 4)
4950 {
4951 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4952 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004953
Nicolas Capens47dc8672017-04-25 12:54:39 -04004954 c0 = _mm_add_ps(c0, c1);
4955 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04004956
Nicolas Capens47dc8672017-04-25 12:54:39 -04004957 _mm_store_ps((float*)(source0 + 4 * x), c0);
4958 }
4959
4960 source0 += pitch;
4961 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004962 }
John Bauman89401822014-05-06 15:04:28 -04004963 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004964 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004965 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004966 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004967 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004968 for(int x = 0; x < width; x += 4)
4969 {
4970 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4971 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4972 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4973 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004974
Nicolas Capens47dc8672017-04-25 12:54:39 -04004975 c0 = _mm_add_ps(c0, c1);
4976 c2 = _mm_add_ps(c2, c3);
4977 c0 = _mm_add_ps(c0, c2);
4978 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04004979
Nicolas Capens47dc8672017-04-25 12:54:39 -04004980 _mm_store_ps((float*)(source0 + 4 * x), c0);
4981 }
4982
4983 source0 += pitch;
4984 source1 += pitch;
4985 source2 += pitch;
4986 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004987 }
John Bauman89401822014-05-06 15:04:28 -04004988 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004989 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004990 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004991 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004992 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004993 for(int x = 0; x < width; x += 4)
4994 {
4995 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4996 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4997 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4998 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
4999 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
5000 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
5001 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
5002 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005003
Nicolas Capens47dc8672017-04-25 12:54:39 -04005004 c0 = _mm_add_ps(c0, c1);
5005 c2 = _mm_add_ps(c2, c3);
5006 c4 = _mm_add_ps(c4, c5);
5007 c6 = _mm_add_ps(c6, c7);
5008 c0 = _mm_add_ps(c0, c2);
5009 c4 = _mm_add_ps(c4, c6);
5010 c0 = _mm_add_ps(c0, c4);
5011 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005012
Nicolas Capens47dc8672017-04-25 12:54:39 -04005013 _mm_store_ps((float*)(source0 + 4 * x), c0);
5014 }
5015
5016 source0 += pitch;
5017 source1 += pitch;
5018 source2 += pitch;
5019 source3 += pitch;
5020 source4 += pitch;
5021 source5 += pitch;
5022 source6 += pitch;
5023 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005024 }
John Bauman89401822014-05-06 15:04:28 -04005025 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005026 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005027 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005028 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005029 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005030 for(int x = 0; x < width; x += 4)
5031 {
5032 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
5033 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
5034 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
5035 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
5036 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
5037 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
5038 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
5039 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
5040 __m128 c8 = _mm_load_ps((float*)(source8 + 4 * x));
5041 __m128 c9 = _mm_load_ps((float*)(source9 + 4 * x));
5042 __m128 cA = _mm_load_ps((float*)(sourceA + 4 * x));
5043 __m128 cB = _mm_load_ps((float*)(sourceB + 4 * x));
5044 __m128 cC = _mm_load_ps((float*)(sourceC + 4 * x));
5045 __m128 cD = _mm_load_ps((float*)(sourceD + 4 * x));
5046 __m128 cE = _mm_load_ps((float*)(sourceE + 4 * x));
5047 __m128 cF = _mm_load_ps((float*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04005048
Nicolas Capens47dc8672017-04-25 12:54:39 -04005049 c0 = _mm_add_ps(c0, c1);
5050 c2 = _mm_add_ps(c2, c3);
5051 c4 = _mm_add_ps(c4, c5);
5052 c6 = _mm_add_ps(c6, c7);
5053 c8 = _mm_add_ps(c8, c9);
5054 cA = _mm_add_ps(cA, cB);
5055 cC = _mm_add_ps(cC, cD);
5056 cE = _mm_add_ps(cE, cF);
5057 c0 = _mm_add_ps(c0, c2);
5058 c4 = _mm_add_ps(c4, c6);
5059 c8 = _mm_add_ps(c8, cA);
5060 cC = _mm_add_ps(cC, cE);
5061 c0 = _mm_add_ps(c0, c4);
5062 c8 = _mm_add_ps(c8, cC);
5063 c0 = _mm_add_ps(c0, c8);
5064 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005065
Nicolas Capens47dc8672017-04-25 12:54:39 -04005066 _mm_store_ps((float*)(source0 + 4 * x), c0);
5067 }
5068
5069 source0 += pitch;
5070 source1 += pitch;
5071 source2 += pitch;
5072 source3 += pitch;
5073 source4 += pitch;
5074 source5 += pitch;
5075 source6 += pitch;
5076 source7 += pitch;
5077 source8 += pitch;
5078 source9 += pitch;
5079 sourceA += pitch;
5080 sourceB += pitch;
5081 sourceC += pitch;
5082 sourceD += pitch;
5083 sourceE += pitch;
5084 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005085 }
John Bauman89401822014-05-06 15:04:28 -04005086 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005087 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005088 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005089 else
5090 #endif
John Bauman89401822014-05-06 15:04:28 -04005091 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005092 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005093 {
5094 for(int y = 0; y < height; y++)
5095 {
5096 for(int x = 0; x < width; x++)
5097 {
5098 float c0 = *(float*)(source0 + 4 * x);
5099 float c1 = *(float*)(source1 + 4 * x);
5100
5101 c0 = c0 + c1;
5102 c0 *= 1.0f / 2.0f;
5103
5104 *(float*)(source0 + 4 * x) = c0;
5105 }
5106
5107 source0 += pitch;
5108 source1 += pitch;
5109 }
5110 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005111 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005112 {
5113 for(int y = 0; y < height; y++)
5114 {
5115 for(int x = 0; x < width; x++)
5116 {
5117 float c0 = *(float*)(source0 + 4 * x);
5118 float c1 = *(float*)(source1 + 4 * x);
5119 float c2 = *(float*)(source2 + 4 * x);
5120 float c3 = *(float*)(source3 + 4 * x);
5121
5122 c0 = c0 + c1;
5123 c2 = c2 + c3;
5124 c0 = c0 + c2;
5125 c0 *= 1.0f / 4.0f;
5126
5127 *(float*)(source0 + 4 * x) = c0;
5128 }
5129
5130 source0 += pitch;
5131 source1 += pitch;
5132 source2 += pitch;
5133 source3 += pitch;
5134 }
5135 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005136 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005137 {
5138 for(int y = 0; y < height; y++)
5139 {
5140 for(int x = 0; x < width; x++)
5141 {
5142 float c0 = *(float*)(source0 + 4 * x);
5143 float c1 = *(float*)(source1 + 4 * x);
5144 float c2 = *(float*)(source2 + 4 * x);
5145 float c3 = *(float*)(source3 + 4 * x);
5146 float c4 = *(float*)(source4 + 4 * x);
5147 float c5 = *(float*)(source5 + 4 * x);
5148 float c6 = *(float*)(source6 + 4 * x);
5149 float c7 = *(float*)(source7 + 4 * x);
5150
5151 c0 = c0 + c1;
5152 c2 = c2 + c3;
5153 c4 = c4 + c5;
5154 c6 = c6 + c7;
5155 c0 = c0 + c2;
5156 c4 = c4 + c6;
5157 c0 = c0 + c4;
5158 c0 *= 1.0f / 8.0f;
5159
5160 *(float*)(source0 + 4 * x) = c0;
5161 }
5162
5163 source0 += pitch;
5164 source1 += pitch;
5165 source2 += pitch;
5166 source3 += pitch;
5167 source4 += pitch;
5168 source5 += pitch;
5169 source6 += pitch;
5170 source7 += pitch;
5171 }
5172 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005173 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005174 {
5175 for(int y = 0; y < height; y++)
5176 {
5177 for(int x = 0; x < width; x++)
5178 {
5179 float c0 = *(float*)(source0 + 4 * x);
5180 float c1 = *(float*)(source1 + 4 * x);
5181 float c2 = *(float*)(source2 + 4 * x);
5182 float c3 = *(float*)(source3 + 4 * x);
5183 float c4 = *(float*)(source4 + 4 * x);
5184 float c5 = *(float*)(source5 + 4 * x);
5185 float c6 = *(float*)(source6 + 4 * x);
5186 float c7 = *(float*)(source7 + 4 * x);
5187 float c8 = *(float*)(source8 + 4 * x);
5188 float c9 = *(float*)(source9 + 4 * x);
5189 float cA = *(float*)(sourceA + 4 * x);
5190 float cB = *(float*)(sourceB + 4 * x);
5191 float cC = *(float*)(sourceC + 4 * x);
5192 float cD = *(float*)(sourceD + 4 * x);
5193 float cE = *(float*)(sourceE + 4 * x);
5194 float cF = *(float*)(sourceF + 4 * x);
5195
5196 c0 = c0 + c1;
5197 c2 = c2 + c3;
5198 c4 = c4 + c5;
5199 c6 = c6 + c7;
5200 c8 = c8 + c9;
5201 cA = cA + cB;
5202 cC = cC + cD;
5203 cE = cE + cF;
5204 c0 = c0 + c2;
5205 c4 = c4 + c6;
5206 c8 = c8 + cA;
5207 cC = cC + cE;
5208 c0 = c0 + c4;
5209 c8 = c8 + cC;
5210 c0 = c0 + c8;
5211 c0 *= 1.0f / 16.0f;
5212
5213 *(float*)(source0 + 4 * x) = c0;
5214 }
5215
5216 source0 += pitch;
5217 source1 += pitch;
5218 source2 += pitch;
5219 source3 += pitch;
5220 source4 += pitch;
5221 source5 += pitch;
5222 source6 += pitch;
5223 source7 += pitch;
5224 source8 += pitch;
5225 source9 += pitch;
5226 sourceA += pitch;
5227 sourceB += pitch;
5228 sourceC += pitch;
5229 sourceD += pitch;
5230 sourceE += pitch;
5231 sourceF += pitch;
5232 }
5233 }
5234 else ASSERT(false);
5235 }
5236 }
5237 else if(internal.format == FORMAT_G32R32F)
5238 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005239 #if defined(__i386__) || defined(__x86_64__)
5240 if(CPUID::supportsSSE() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04005241 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005242 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005243 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005244 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005245 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005246 for(int x = 0; x < width; x += 2)
5247 {
5248 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5249 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005250
Nicolas Capens47dc8672017-04-25 12:54:39 -04005251 c0 = _mm_add_ps(c0, c1);
5252 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005253
Nicolas Capens47dc8672017-04-25 12:54:39 -04005254 _mm_store_ps((float*)(source0 + 8 * x), c0);
5255 }
5256
5257 source0 += pitch;
5258 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005259 }
John Bauman89401822014-05-06 15:04:28 -04005260 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005261 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005262 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005263 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005264 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005265 for(int x = 0; x < width; x += 2)
5266 {
5267 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5268 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5269 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5270 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005271
Nicolas Capens47dc8672017-04-25 12:54:39 -04005272 c0 = _mm_add_ps(c0, c1);
5273 c2 = _mm_add_ps(c2, c3);
5274 c0 = _mm_add_ps(c0, c2);
5275 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005276
Nicolas Capens47dc8672017-04-25 12:54:39 -04005277 _mm_store_ps((float*)(source0 + 8 * x), c0);
5278 }
5279
5280 source0 += pitch;
5281 source1 += pitch;
5282 source2 += pitch;
5283 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005284 }
John Bauman89401822014-05-06 15:04:28 -04005285 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005286 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005287 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005288 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005289 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005290 for(int x = 0; x < width; x += 2)
5291 {
5292 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5293 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5294 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5295 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5296 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5297 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5298 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5299 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005300
Nicolas Capens47dc8672017-04-25 12:54:39 -04005301 c0 = _mm_add_ps(c0, c1);
5302 c2 = _mm_add_ps(c2, c3);
5303 c4 = _mm_add_ps(c4, c5);
5304 c6 = _mm_add_ps(c6, c7);
5305 c0 = _mm_add_ps(c0, c2);
5306 c4 = _mm_add_ps(c4, c6);
5307 c0 = _mm_add_ps(c0, c4);
5308 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005309
Nicolas Capens47dc8672017-04-25 12:54:39 -04005310 _mm_store_ps((float*)(source0 + 8 * x), c0);
5311 }
5312
5313 source0 += pitch;
5314 source1 += pitch;
5315 source2 += pitch;
5316 source3 += pitch;
5317 source4 += pitch;
5318 source5 += pitch;
5319 source6 += pitch;
5320 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005321 }
John Bauman89401822014-05-06 15:04:28 -04005322 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005323 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005324 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005325 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005326 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005327 for(int x = 0; x < width; x += 2)
5328 {
5329 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5330 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5331 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5332 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5333 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5334 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5335 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5336 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
5337 __m128 c8 = _mm_load_ps((float*)(source8 + 8 * x));
5338 __m128 c9 = _mm_load_ps((float*)(source9 + 8 * x));
5339 __m128 cA = _mm_load_ps((float*)(sourceA + 8 * x));
5340 __m128 cB = _mm_load_ps((float*)(sourceB + 8 * x));
5341 __m128 cC = _mm_load_ps((float*)(sourceC + 8 * x));
5342 __m128 cD = _mm_load_ps((float*)(sourceD + 8 * x));
5343 __m128 cE = _mm_load_ps((float*)(sourceE + 8 * x));
5344 __m128 cF = _mm_load_ps((float*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04005345
Nicolas Capens47dc8672017-04-25 12:54:39 -04005346 c0 = _mm_add_ps(c0, c1);
5347 c2 = _mm_add_ps(c2, c3);
5348 c4 = _mm_add_ps(c4, c5);
5349 c6 = _mm_add_ps(c6, c7);
5350 c8 = _mm_add_ps(c8, c9);
5351 cA = _mm_add_ps(cA, cB);
5352 cC = _mm_add_ps(cC, cD);
5353 cE = _mm_add_ps(cE, cF);
5354 c0 = _mm_add_ps(c0, c2);
5355 c4 = _mm_add_ps(c4, c6);
5356 c8 = _mm_add_ps(c8, cA);
5357 cC = _mm_add_ps(cC, cE);
5358 c0 = _mm_add_ps(c0, c4);
5359 c8 = _mm_add_ps(c8, cC);
5360 c0 = _mm_add_ps(c0, c8);
5361 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005362
Nicolas Capens47dc8672017-04-25 12:54:39 -04005363 _mm_store_ps((float*)(source0 + 8 * x), c0);
5364 }
5365
5366 source0 += pitch;
5367 source1 += pitch;
5368 source2 += pitch;
5369 source3 += pitch;
5370 source4 += pitch;
5371 source5 += pitch;
5372 source6 += pitch;
5373 source7 += pitch;
5374 source8 += pitch;
5375 source9 += pitch;
5376 sourceA += pitch;
5377 sourceB += pitch;
5378 sourceC += pitch;
5379 sourceD += pitch;
5380 sourceE += pitch;
5381 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005382 }
John Bauman89401822014-05-06 15:04:28 -04005383 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005384 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005385 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005386 else
5387 #endif
John Bauman89401822014-05-06 15:04:28 -04005388 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005389 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005390 {
5391 for(int y = 0; y < height; y++)
5392 {
5393 for(int x = 0; x < 2 * width; x++)
5394 {
5395 float c0 = *(float*)(source0 + 4 * x);
5396 float c1 = *(float*)(source1 + 4 * x);
5397
5398 c0 = c0 + c1;
5399 c0 *= 1.0f / 2.0f;
5400
5401 *(float*)(source0 + 4 * x) = c0;
5402 }
5403
5404 source0 += pitch;
5405 source1 += pitch;
5406 }
5407 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005408 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005409 {
5410 for(int y = 0; y < height; y++)
5411 {
5412 for(int x = 0; x < 2 * width; x++)
5413 {
5414 float c0 = *(float*)(source0 + 4 * x);
5415 float c1 = *(float*)(source1 + 4 * x);
5416 float c2 = *(float*)(source2 + 4 * x);
5417 float c3 = *(float*)(source3 + 4 * x);
5418
5419 c0 = c0 + c1;
5420 c2 = c2 + c3;
5421 c0 = c0 + c2;
5422 c0 *= 1.0f / 4.0f;
5423
5424 *(float*)(source0 + 4 * x) = c0;
5425 }
5426
5427 source0 += pitch;
5428 source1 += pitch;
5429 source2 += pitch;
5430 source3 += pitch;
5431 }
5432 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005433 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005434 {
5435 for(int y = 0; y < height; y++)
5436 {
5437 for(int x = 0; x < 2 * width; x++)
5438 {
5439 float c0 = *(float*)(source0 + 4 * x);
5440 float c1 = *(float*)(source1 + 4 * x);
5441 float c2 = *(float*)(source2 + 4 * x);
5442 float c3 = *(float*)(source3 + 4 * x);
5443 float c4 = *(float*)(source4 + 4 * x);
5444 float c5 = *(float*)(source5 + 4 * x);
5445 float c6 = *(float*)(source6 + 4 * x);
5446 float c7 = *(float*)(source7 + 4 * x);
5447
5448 c0 = c0 + c1;
5449 c2 = c2 + c3;
5450 c4 = c4 + c5;
5451 c6 = c6 + c7;
5452 c0 = c0 + c2;
5453 c4 = c4 + c6;
5454 c0 = c0 + c4;
5455 c0 *= 1.0f / 8.0f;
5456
5457 *(float*)(source0 + 4 * x) = c0;
5458 }
5459
5460 source0 += pitch;
5461 source1 += pitch;
5462 source2 += pitch;
5463 source3 += pitch;
5464 source4 += pitch;
5465 source5 += pitch;
5466 source6 += pitch;
5467 source7 += pitch;
5468 }
5469 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005470 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005471 {
5472 for(int y = 0; y < height; y++)
5473 {
5474 for(int x = 0; x < 2 * width; x++)
5475 {
5476 float c0 = *(float*)(source0 + 4 * x);
5477 float c1 = *(float*)(source1 + 4 * x);
5478 float c2 = *(float*)(source2 + 4 * x);
5479 float c3 = *(float*)(source3 + 4 * x);
5480 float c4 = *(float*)(source4 + 4 * x);
5481 float c5 = *(float*)(source5 + 4 * x);
5482 float c6 = *(float*)(source6 + 4 * x);
5483 float c7 = *(float*)(source7 + 4 * x);
5484 float c8 = *(float*)(source8 + 4 * x);
5485 float c9 = *(float*)(source9 + 4 * x);
5486 float cA = *(float*)(sourceA + 4 * x);
5487 float cB = *(float*)(sourceB + 4 * x);
5488 float cC = *(float*)(sourceC + 4 * x);
5489 float cD = *(float*)(sourceD + 4 * x);
5490 float cE = *(float*)(sourceE + 4 * x);
5491 float cF = *(float*)(sourceF + 4 * x);
5492
5493 c0 = c0 + c1;
5494 c2 = c2 + c3;
5495 c4 = c4 + c5;
5496 c6 = c6 + c7;
5497 c8 = c8 + c9;
5498 cA = cA + cB;
5499 cC = cC + cD;
5500 cE = cE + cF;
5501 c0 = c0 + c2;
5502 c4 = c4 + c6;
5503 c8 = c8 + cA;
5504 cC = cC + cE;
5505 c0 = c0 + c4;
5506 c8 = c8 + cC;
5507 c0 = c0 + c8;
5508 c0 *= 1.0f / 16.0f;
5509
5510 *(float*)(source0 + 4 * x) = c0;
5511 }
5512
5513 source0 += pitch;
5514 source1 += pitch;
5515 source2 += pitch;
5516 source3 += pitch;
5517 source4 += pitch;
5518 source5 += pitch;
5519 source6 += pitch;
5520 source7 += pitch;
5521 source8 += pitch;
5522 source9 += pitch;
5523 sourceA += pitch;
5524 sourceB += pitch;
5525 sourceC += pitch;
5526 sourceD += pitch;
5527 sourceE += pitch;
5528 sourceF += pitch;
5529 }
5530 }
5531 else ASSERT(false);
5532 }
5533 }
Nicolas Capens67fdd832017-12-21 11:20:54 -05005534 else if(internal.format == FORMAT_A32B32G32R32F ||
5535 internal.format == FORMAT_X32B32G32R32F ||
5536 internal.format == FORMAT_X32B32G32R32F_UNSIGNED)
John Bauman89401822014-05-06 15:04:28 -04005537 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005538 #if defined(__i386__) || defined(__x86_64__)
5539 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04005540 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005541 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005542 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005543 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005544 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005545 for(int x = 0; x < width; x++)
5546 {
5547 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5548 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005549
Nicolas Capens47dc8672017-04-25 12:54:39 -04005550 c0 = _mm_add_ps(c0, c1);
5551 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005552
Nicolas Capens47dc8672017-04-25 12:54:39 -04005553 _mm_store_ps((float*)(source0 + 16 * x), c0);
5554 }
5555
5556 source0 += pitch;
5557 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005558 }
John Bauman89401822014-05-06 15:04:28 -04005559 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005560 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005561 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005562 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005563 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005564 for(int x = 0; x < width; x++)
5565 {
5566 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5567 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5568 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5569 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005570
Nicolas Capens47dc8672017-04-25 12:54:39 -04005571 c0 = _mm_add_ps(c0, c1);
5572 c2 = _mm_add_ps(c2, c3);
5573 c0 = _mm_add_ps(c0, c2);
5574 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005575
Nicolas Capens47dc8672017-04-25 12:54:39 -04005576 _mm_store_ps((float*)(source0 + 16 * x), c0);
5577 }
5578
5579 source0 += pitch;
5580 source1 += pitch;
5581 source2 += pitch;
5582 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005583 }
John Bauman89401822014-05-06 15:04:28 -04005584 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005585 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005586 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005587 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005588 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005589 for(int x = 0; x < width; x++)
5590 {
5591 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5592 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5593 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5594 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5595 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5596 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5597 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5598 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005599
Nicolas Capens47dc8672017-04-25 12:54:39 -04005600 c0 = _mm_add_ps(c0, c1);
5601 c2 = _mm_add_ps(c2, c3);
5602 c4 = _mm_add_ps(c4, c5);
5603 c6 = _mm_add_ps(c6, c7);
5604 c0 = _mm_add_ps(c0, c2);
5605 c4 = _mm_add_ps(c4, c6);
5606 c0 = _mm_add_ps(c0, c4);
5607 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005608
Nicolas Capens47dc8672017-04-25 12:54:39 -04005609 _mm_store_ps((float*)(source0 + 16 * x), c0);
5610 }
5611
5612 source0 += pitch;
5613 source1 += pitch;
5614 source2 += pitch;
5615 source3 += pitch;
5616 source4 += pitch;
5617 source5 += pitch;
5618 source6 += pitch;
5619 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005620 }
John Bauman89401822014-05-06 15:04:28 -04005621 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005622 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005623 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005624 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005625 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005626 for(int x = 0; x < width; x++)
5627 {
5628 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5629 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5630 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5631 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5632 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5633 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5634 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5635 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
5636 __m128 c8 = _mm_load_ps((float*)(source8 + 16 * x));
5637 __m128 c9 = _mm_load_ps((float*)(source9 + 16 * x));
5638 __m128 cA = _mm_load_ps((float*)(sourceA + 16 * x));
5639 __m128 cB = _mm_load_ps((float*)(sourceB + 16 * x));
5640 __m128 cC = _mm_load_ps((float*)(sourceC + 16 * x));
5641 __m128 cD = _mm_load_ps((float*)(sourceD + 16 * x));
5642 __m128 cE = _mm_load_ps((float*)(sourceE + 16 * x));
5643 __m128 cF = _mm_load_ps((float*)(sourceF + 16 * x));
John Bauman89401822014-05-06 15:04:28 -04005644
Nicolas Capens47dc8672017-04-25 12:54:39 -04005645 c0 = _mm_add_ps(c0, c1);
5646 c2 = _mm_add_ps(c2, c3);
5647 c4 = _mm_add_ps(c4, c5);
5648 c6 = _mm_add_ps(c6, c7);
5649 c8 = _mm_add_ps(c8, c9);
5650 cA = _mm_add_ps(cA, cB);
5651 cC = _mm_add_ps(cC, cD);
5652 cE = _mm_add_ps(cE, cF);
5653 c0 = _mm_add_ps(c0, c2);
5654 c4 = _mm_add_ps(c4, c6);
5655 c8 = _mm_add_ps(c8, cA);
5656 cC = _mm_add_ps(cC, cE);
5657 c0 = _mm_add_ps(c0, c4);
5658 c8 = _mm_add_ps(c8, cC);
5659 c0 = _mm_add_ps(c0, c8);
5660 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005661
Nicolas Capens47dc8672017-04-25 12:54:39 -04005662 _mm_store_ps((float*)(source0 + 16 * x), c0);
5663 }
5664
5665 source0 += pitch;
5666 source1 += pitch;
5667 source2 += pitch;
5668 source3 += pitch;
5669 source4 += pitch;
5670 source5 += pitch;
5671 source6 += pitch;
5672 source7 += pitch;
5673 source8 += pitch;
5674 source9 += pitch;
5675 sourceA += pitch;
5676 sourceB += pitch;
5677 sourceC += pitch;
5678 sourceD += pitch;
5679 sourceE += pitch;
5680 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005681 }
John Bauman89401822014-05-06 15:04:28 -04005682 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005683 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005684 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005685 else
5686 #endif
John Bauman89401822014-05-06 15:04:28 -04005687 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005688 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005689 {
5690 for(int y = 0; y < height; y++)
5691 {
5692 for(int x = 0; x < 4 * width; x++)
5693 {
5694 float c0 = *(float*)(source0 + 4 * x);
5695 float c1 = *(float*)(source1 + 4 * x);
5696
5697 c0 = c0 + c1;
5698 c0 *= 1.0f / 2.0f;
5699
5700 *(float*)(source0 + 4 * x) = c0;
5701 }
5702
5703 source0 += pitch;
5704 source1 += pitch;
5705 }
5706 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005707 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005708 {
5709 for(int y = 0; y < height; y++)
5710 {
5711 for(int x = 0; x < 4 * width; x++)
5712 {
5713 float c0 = *(float*)(source0 + 4 * x);
5714 float c1 = *(float*)(source1 + 4 * x);
5715 float c2 = *(float*)(source2 + 4 * x);
5716 float c3 = *(float*)(source3 + 4 * x);
5717
5718 c0 = c0 + c1;
5719 c2 = c2 + c3;
5720 c0 = c0 + c2;
5721 c0 *= 1.0f / 4.0f;
5722
5723 *(float*)(source0 + 4 * x) = c0;
5724 }
5725
5726 source0 += pitch;
5727 source1 += pitch;
5728 source2 += pitch;
5729 source3 += pitch;
5730 }
5731 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005732 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005733 {
5734 for(int y = 0; y < height; y++)
5735 {
5736 for(int x = 0; x < 4 * width; x++)
5737 {
5738 float c0 = *(float*)(source0 + 4 * x);
5739 float c1 = *(float*)(source1 + 4 * x);
5740 float c2 = *(float*)(source2 + 4 * x);
5741 float c3 = *(float*)(source3 + 4 * x);
5742 float c4 = *(float*)(source4 + 4 * x);
5743 float c5 = *(float*)(source5 + 4 * x);
5744 float c6 = *(float*)(source6 + 4 * x);
5745 float c7 = *(float*)(source7 + 4 * x);
5746
5747 c0 = c0 + c1;
5748 c2 = c2 + c3;
5749 c4 = c4 + c5;
5750 c6 = c6 + c7;
5751 c0 = c0 + c2;
5752 c4 = c4 + c6;
5753 c0 = c0 + c4;
5754 c0 *= 1.0f / 8.0f;
5755
5756 *(float*)(source0 + 4 * x) = c0;
5757 }
5758
5759 source0 += pitch;
5760 source1 += pitch;
5761 source2 += pitch;
5762 source3 += pitch;
5763 source4 += pitch;
5764 source5 += pitch;
5765 source6 += pitch;
5766 source7 += pitch;
5767 }
5768 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005769 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005770 {
5771 for(int y = 0; y < height; y++)
5772 {
5773 for(int x = 0; x < 4 * width; x++)
5774 {
5775 float c0 = *(float*)(source0 + 4 * x);
5776 float c1 = *(float*)(source1 + 4 * x);
5777 float c2 = *(float*)(source2 + 4 * x);
5778 float c3 = *(float*)(source3 + 4 * x);
5779 float c4 = *(float*)(source4 + 4 * x);
5780 float c5 = *(float*)(source5 + 4 * x);
5781 float c6 = *(float*)(source6 + 4 * x);
5782 float c7 = *(float*)(source7 + 4 * x);
5783 float c8 = *(float*)(source8 + 4 * x);
5784 float c9 = *(float*)(source9 + 4 * x);
5785 float cA = *(float*)(sourceA + 4 * x);
5786 float cB = *(float*)(sourceB + 4 * x);
5787 float cC = *(float*)(sourceC + 4 * x);
5788 float cD = *(float*)(sourceD + 4 * x);
5789 float cE = *(float*)(sourceE + 4 * x);
5790 float cF = *(float*)(sourceF + 4 * x);
5791
5792 c0 = c0 + c1;
5793 c2 = c2 + c3;
5794 c4 = c4 + c5;
5795 c6 = c6 + c7;
5796 c8 = c8 + c9;
5797 cA = cA + cB;
5798 cC = cC + cD;
5799 cE = cE + cF;
5800 c0 = c0 + c2;
5801 c4 = c4 + c6;
5802 c8 = c8 + cA;
5803 cC = cC + cE;
5804 c0 = c0 + c4;
5805 c8 = c8 + cC;
5806 c0 = c0 + c8;
5807 c0 *= 1.0f / 16.0f;
5808
5809 *(float*)(source0 + 4 * x) = c0;
5810 }
5811
5812 source0 += pitch;
5813 source1 += pitch;
5814 source2 += pitch;
5815 source3 += pitch;
5816 source4 += pitch;
5817 source5 += pitch;
5818 source6 += pitch;
5819 source7 += pitch;
5820 source8 += pitch;
5821 source9 += pitch;
5822 sourceA += pitch;
5823 sourceB += pitch;
5824 sourceC += pitch;
5825 sourceD += pitch;
5826 sourceE += pitch;
5827 sourceF += pitch;
5828 }
5829 }
5830 else ASSERT(false);
5831 }
5832 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005833 else if(internal.format == FORMAT_R5G6B5)
5834 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005835 #if defined(__i386__) || defined(__x86_64__)
5836 if(CPUID::supportsSSE2() && (width % 8) == 0)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005837 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005838 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005839 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005840 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005841 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005842 for(int x = 0; x < width; x += 8)
5843 {
5844 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5845 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005846
Nicolas Capens47dc8672017-04-25 12:54:39 -04005847 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5848 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5849 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5850 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5851 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5852 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005853
Nicolas Capens47dc8672017-04-25 12:54:39 -04005854 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5855 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5856 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5857 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5858 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005859
Nicolas Capens47dc8672017-04-25 12:54:39 -04005860 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5861 }
5862
5863 source0 += pitch;
5864 source1 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005865 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005866 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005867 else if(internal.samples == 4)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005868 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005869 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005870 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005871 for(int x = 0; x < width; x += 8)
5872 {
5873 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5874 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5875 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5876 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005877
Nicolas Capens47dc8672017-04-25 12:54:39 -04005878 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5879 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5880 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5881 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5882 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5883 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5884 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5885 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5886 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5887 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005888
Nicolas Capens47dc8672017-04-25 12:54:39 -04005889 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5890 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5891 c0 = _mm_avg_epu8(c0, c2);
5892 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5893 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5894 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5895 c1 = _mm_avg_epu16(c1, c3);
5896 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5897 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005898
Nicolas Capens47dc8672017-04-25 12:54:39 -04005899 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5900 }
5901
5902 source0 += pitch;
5903 source1 += pitch;
5904 source2 += pitch;
5905 source3 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005906 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005907 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005908 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005909 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005910 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005911 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005912 for(int x = 0; x < width; x += 8)
5913 {
5914 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5915 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5916 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5917 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5918 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5919 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5920 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5921 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005922
Nicolas Capens47dc8672017-04-25 12:54:39 -04005923 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5924 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5925 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5926 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5927 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5928 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5929 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5930 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5931 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5932 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
5933 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
5934 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
5935 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
5936 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
5937 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
5938 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
5939 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
5940 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005941
Nicolas Capens47dc8672017-04-25 12:54:39 -04005942 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5943 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5944 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
5945 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
5946 c0 = _mm_avg_epu8(c0, c2);
5947 c4 = _mm_avg_epu8(c4, c6);
5948 c0 = _mm_avg_epu8(c0, c4);
5949 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5950 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5951 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5952 c5 = _mm_avg_epu16(c4__g_, c5__g_);
5953 c7 = _mm_avg_epu16(c6__g_, c7__g_);
5954 c1 = _mm_avg_epu16(c1, c3);
5955 c5 = _mm_avg_epu16(c5, c7);
5956 c1 = _mm_avg_epu16(c1, c5);
5957 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5958 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005959
Nicolas Capens47dc8672017-04-25 12:54:39 -04005960 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5961 }
5962
5963 source0 += pitch;
5964 source1 += pitch;
5965 source2 += pitch;
5966 source3 += pitch;
5967 source4 += pitch;
5968 source5 += pitch;
5969 source6 += pitch;
5970 source7 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005971 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005972 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005973 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005974 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005975 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005976 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005977 for(int x = 0; x < width; x += 8)
5978 {
5979 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5980 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5981 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5982 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5983 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5984 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5985 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5986 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
5987 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 2 * x));
5988 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 2 * x));
5989 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 2 * x));
5990 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 2 * x));
5991 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 2 * x));
5992 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 2 * x));
5993 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 2 * x));
5994 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 2 * x));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005995
Nicolas Capens47dc8672017-04-25 12:54:39 -04005996 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5997 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5998 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5999 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
6000 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
6001 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
6002 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
6003 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
6004 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
6005 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
6006 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
6007 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
6008 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
6009 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
6010 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
6011 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
6012 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
6013 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
6014 __m128i c8_r_b = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(r_b));
6015 __m128i c8__g_ = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(_g_));
6016 __m128i c9_r_b = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(r_b));
6017 __m128i c9__g_ = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(_g_));
6018 __m128i cA_r_b = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(r_b));
6019 __m128i cA__g_ = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(_g_));
6020 __m128i cB_r_b = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(r_b));
6021 __m128i cB__g_ = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(_g_));
6022 __m128i cC_r_b = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(r_b));
6023 __m128i cC__g_ = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(_g_));
6024 __m128i cD_r_b = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(r_b));
6025 __m128i cD__g_ = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(_g_));
6026 __m128i cE_r_b = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(r_b));
6027 __m128i cE__g_ = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(_g_));
6028 __m128i cF_r_b = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(r_b));
6029 __m128i cF__g_ = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04006030
Nicolas Capens47dc8672017-04-25 12:54:39 -04006031 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
6032 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
6033 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
6034 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
6035 c8 = _mm_avg_epu8(c8_r_b, c9_r_b);
6036 cA = _mm_avg_epu8(cA_r_b, cB_r_b);
6037 cC = _mm_avg_epu8(cC_r_b, cD_r_b);
6038 cE = _mm_avg_epu8(cE_r_b, cF_r_b);
6039 c0 = _mm_avg_epu8(c0, c2);
6040 c4 = _mm_avg_epu8(c4, c6);
6041 c8 = _mm_avg_epu8(c8, cA);
6042 cC = _mm_avg_epu8(cC, cE);
6043 c0 = _mm_avg_epu8(c0, c4);
6044 c8 = _mm_avg_epu8(c8, cC);
6045 c0 = _mm_avg_epu8(c0, c8);
6046 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
6047 c1 = _mm_avg_epu16(c0__g_, c1__g_);
6048 c3 = _mm_avg_epu16(c2__g_, c3__g_);
6049 c5 = _mm_avg_epu16(c4__g_, c5__g_);
6050 c7 = _mm_avg_epu16(c6__g_, c7__g_);
6051 c9 = _mm_avg_epu16(c8__g_, c9__g_);
6052 cB = _mm_avg_epu16(cA__g_, cB__g_);
6053 cD = _mm_avg_epu16(cC__g_, cD__g_);
6054 cF = _mm_avg_epu16(cE__g_, cF__g_);
6055 c1 = _mm_avg_epu8(c1, c3);
6056 c5 = _mm_avg_epu8(c5, c7);
6057 c9 = _mm_avg_epu8(c9, cB);
6058 cD = _mm_avg_epu8(cD, cF);
6059 c1 = _mm_avg_epu8(c1, c5);
6060 c9 = _mm_avg_epu8(c9, cD);
6061 c1 = _mm_avg_epu8(c1, c9);
6062 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
6063 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006064
Nicolas Capens47dc8672017-04-25 12:54:39 -04006065 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
6066 }
6067
6068 source0 += pitch;
6069 source1 += pitch;
6070 source2 += pitch;
6071 source3 += pitch;
6072 source4 += pitch;
6073 source5 += pitch;
6074 source6 += pitch;
6075 source7 += pitch;
6076 source8 += pitch;
6077 source9 += pitch;
6078 sourceA += pitch;
6079 sourceB += pitch;
6080 sourceC += pitch;
6081 sourceD += pitch;
6082 sourceE += pitch;
6083 sourceF += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04006084 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04006085 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006086 else ASSERT(false);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006087 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006088 else
6089 #endif
Nicolas Capens0e12a922015-09-04 09:18:15 -04006090 {
6091 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7BEF) + (((x) ^ (y)) & 0x0821))
6092
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006093 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006094 {
6095 for(int y = 0; y < height; y++)
6096 {
6097 for(int x = 0; x < width; x++)
6098 {
6099 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6100 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6101
6102 c0 = AVERAGE(c0, c1);
6103
6104 *(unsigned short*)(source0 + 2 * x) = c0;
6105 }
6106
6107 source0 += pitch;
6108 source1 += pitch;
6109 }
6110 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006111 else if(internal.samples == 4)
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
6122 c0 = AVERAGE(c0, c1);
6123 c2 = AVERAGE(c2, c3);
6124 c0 = AVERAGE(c0, c2);
6125
6126 *(unsigned short*)(source0 + 2 * x) = c0;
6127 }
6128
6129 source0 += pitch;
6130 source1 += pitch;
6131 source2 += pitch;
6132 source3 += pitch;
6133 }
6134 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006135 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006136 {
6137 for(int y = 0; y < height; y++)
6138 {
6139 for(int x = 0; x < width; x++)
6140 {
6141 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6142 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6143 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6144 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6145 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6146 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6147 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6148 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6149
6150 c0 = AVERAGE(c0, c1);
6151 c2 = AVERAGE(c2, c3);
6152 c4 = AVERAGE(c4, c5);
6153 c6 = AVERAGE(c6, c7);
6154 c0 = AVERAGE(c0, c2);
6155 c4 = AVERAGE(c4, c6);
6156 c0 = AVERAGE(c0, c4);
6157
6158 *(unsigned short*)(source0 + 2 * x) = c0;
6159 }
6160
6161 source0 += pitch;
6162 source1 += pitch;
6163 source2 += pitch;
6164 source3 += pitch;
6165 source4 += pitch;
6166 source5 += pitch;
6167 source6 += pitch;
6168 source7 += pitch;
6169 }
6170 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006171 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006172 {
6173 for(int y = 0; y < height; y++)
6174 {
6175 for(int x = 0; x < width; x++)
6176 {
6177 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6178 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6179 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6180 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6181 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6182 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6183 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6184 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6185 unsigned short c8 = *(unsigned short*)(source8 + 2 * x);
6186 unsigned short c9 = *(unsigned short*)(source9 + 2 * x);
6187 unsigned short cA = *(unsigned short*)(sourceA + 2 * x);
6188 unsigned short cB = *(unsigned short*)(sourceB + 2 * x);
6189 unsigned short cC = *(unsigned short*)(sourceC + 2 * x);
6190 unsigned short cD = *(unsigned short*)(sourceD + 2 * x);
6191 unsigned short cE = *(unsigned short*)(sourceE + 2 * x);
6192 unsigned short cF = *(unsigned short*)(sourceF + 2 * x);
6193
6194 c0 = AVERAGE(c0, c1);
6195 c2 = AVERAGE(c2, c3);
6196 c4 = AVERAGE(c4, c5);
6197 c6 = AVERAGE(c6, c7);
6198 c8 = AVERAGE(c8, c9);
6199 cA = AVERAGE(cA, cB);
6200 cC = AVERAGE(cC, cD);
6201 cE = AVERAGE(cE, cF);
6202 c0 = AVERAGE(c0, c2);
6203 c4 = AVERAGE(c4, c6);
6204 c8 = AVERAGE(c8, cA);
6205 cC = AVERAGE(cC, cE);
6206 c0 = AVERAGE(c0, c4);
6207 c8 = AVERAGE(c8, cC);
6208 c0 = AVERAGE(c0, c8);
6209
6210 *(unsigned short*)(source0 + 2 * x) = c0;
6211 }
6212
6213 source0 += pitch;
6214 source1 += pitch;
6215 source2 += pitch;
6216 source3 += pitch;
6217 source4 += pitch;
6218 source5 += pitch;
6219 source6 += pitch;
6220 source7 += pitch;
6221 source8 += pitch;
6222 source9 += pitch;
6223 sourceA += pitch;
6224 sourceB += pitch;
6225 sourceC += pitch;
6226 sourceD += pitch;
6227 sourceE += pitch;
6228 sourceF += pitch;
6229 }
6230 }
6231 else ASSERT(false);
6232
6233 #undef AVERAGE
6234 }
6235 }
John Bauman89401822014-05-06 15:04:28 -04006236 else
6237 {
6238 // UNIMPLEMENTED();
6239 }
6240 }
6241}