blob: a2a783d24fc5124d7327f4da5314f3a9d3e3dbbe [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:
1121 break;
1122 case LOCK_WRITEONLY:
1123 case LOCK_READWRITE:
1124 case LOCK_DISCARD:
1125 dirty = true;
1126 break;
1127 default:
1128 ASSERT(false);
1129 }
1130
John Baumand4ae8632014-05-06 16:18:33 -04001131 if(buffer)
John Bauman89401822014-05-06 15:04:28 -04001132 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001133 x += border;
1134 y += border;
1135
John Baumand4ae8632014-05-06 16:18:33 -04001136 switch(format)
1137 {
John Baumand4ae8632014-05-06 16:18:33 -04001138 case FORMAT_DXT1:
John Baumand4ae8632014-05-06 16:18:33 -04001139 case FORMAT_ATI1:
Nicolas Capens22658242014-11-29 00:31:41 -05001140 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001141 case FORMAT_R11_EAC:
1142 case FORMAT_SIGNED_R11_EAC:
1143 case FORMAT_RGB8_ETC2:
1144 case FORMAT_SRGB8_ETC2:
1145 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1146 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Baumand4ae8632014-05-06 16:18:33 -04001147 return (unsigned char*)buffer + 8 * (x / 4) + (y / 4) * pitchB + z * sliceB;
Alexis Hetu460e41f2015-09-01 10:58:37 -04001148 case FORMAT_RG11_EAC:
1149 case FORMAT_SIGNED_RG11_EAC:
1150 case FORMAT_RGBA8_ETC2_EAC:
1151 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1152 case FORMAT_RGBA_ASTC_4x4_KHR:
1153 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1154 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1155 case FORMAT_RGBA_ASTC_5x4_KHR:
1156 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1157 return (unsigned char*)buffer + 16 * (x / 5) + (y / 4) * pitchB + z * sliceB;
1158 case FORMAT_RGBA_ASTC_5x5_KHR:
1159 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1160 return (unsigned char*)buffer + 16 * (x / 5) + (y / 5) * pitchB + z * sliceB;
1161 case FORMAT_RGBA_ASTC_6x5_KHR:
1162 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1163 return (unsigned char*)buffer + 16 * (x / 6) + (y / 5) * pitchB + z * sliceB;
1164 case FORMAT_RGBA_ASTC_6x6_KHR:
1165 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1166 return (unsigned char*)buffer + 16 * (x / 6) + (y / 6) * pitchB + z * sliceB;
1167 case FORMAT_RGBA_ASTC_8x5_KHR:
1168 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1169 return (unsigned char*)buffer + 16 * (x / 8) + (y / 5) * pitchB + z * sliceB;
1170 case FORMAT_RGBA_ASTC_8x6_KHR:
1171 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1172 return (unsigned char*)buffer + 16 * (x / 8) + (y / 6) * pitchB + z * sliceB;
1173 case FORMAT_RGBA_ASTC_8x8_KHR:
1174 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1175 return (unsigned char*)buffer + 16 * (x / 8) + (y / 8) * pitchB + z * sliceB;
1176 case FORMAT_RGBA_ASTC_10x5_KHR:
1177 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1178 return (unsigned char*)buffer + 16 * (x / 10) + (y / 5) * pitchB + z * sliceB;
1179 case FORMAT_RGBA_ASTC_10x6_KHR:
1180 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1181 return (unsigned char*)buffer + 16 * (x / 10) + (y / 6) * pitchB + z * sliceB;
1182 case FORMAT_RGBA_ASTC_10x8_KHR:
1183 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1184 return (unsigned char*)buffer + 16 * (x / 10) + (y / 8) * pitchB + z * sliceB;
1185 case FORMAT_RGBA_ASTC_10x10_KHR:
1186 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1187 return (unsigned char*)buffer + 16 * (x / 10) + (y / 10) * pitchB + z * sliceB;
1188 case FORMAT_RGBA_ASTC_12x10_KHR:
1189 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1190 return (unsigned char*)buffer + 16 * (x / 12) + (y / 10) * pitchB + z * sliceB;
1191 case FORMAT_RGBA_ASTC_12x12_KHR:
1192 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1193 return (unsigned char*)buffer + 16 * (x / 12) + (y / 12) * pitchB + z * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001194 case FORMAT_DXT3:
1195 case FORMAT_DXT5:
John Baumand4ae8632014-05-06 16:18:33 -04001196 case FORMAT_ATI2:
1197 return (unsigned char*)buffer + 16 * (x / 4) + (y / 4) * pitchB + z * sliceB;
1198 default:
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001199 return (unsigned char*)buffer + x * bytes + y * pitchB + z * samples * sliceB;
John Baumand4ae8632014-05-06 16:18:33 -04001200 }
John Bauman89401822014-05-06 15:04:28 -04001201 }
1202
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001203 return nullptr;
John Bauman89401822014-05-06 15:04:28 -04001204 }
1205
1206 void Surface::Buffer::unlockRect()
1207 {
1208 lock = LOCK_UNLOCKED;
1209 }
1210
Nicolas Capensf41f0332017-05-30 15:25:50 -04001211 class SurfaceImplementation : public Surface
1212 {
1213 public:
1214 SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1215 : Surface(width, height, depth, format, pixels, pitch, slice) {}
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001216 SurfaceImplementation(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0)
1217 : Surface(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchP) {}
Nicolas Capensf41f0332017-05-30 15:25:50 -04001218 ~SurfaceImplementation() override {};
1219
1220 void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override
1221 {
1222 return Surface::lockInternal(x, y, z, lock, client);
1223 }
1224
1225 void unlockInternal() override
1226 {
1227 Surface::unlockInternal();
1228 }
1229 };
1230
1231 Surface *Surface::create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
1232 {
1233 return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice);
1234 }
1235
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001236 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 -04001237 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001238 return new SurfaceImplementation(texture, width, height, depth, border, samples, format, lockable, renderTarget, pitchPprovided);
Nicolas Capensf41f0332017-05-30 15:25:50 -04001239 }
1240
Nicolas Capens477314b2015-06-09 16:47:29 -04001241 Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
1242 {
1243 resource = new Resource(0);
1244 hasParent = false;
1245 ownExternal = false;
1246 depth = max(1, depth);
1247
1248 external.buffer = pixels;
1249 external.width = width;
1250 external.height = height;
1251 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001252 external.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001253 external.format = format;
1254 external.bytes = bytes(external.format);
1255 external.pitchB = pitch;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001256 external.pitchP = external.bytes ? pitch / external.bytes : 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001257 external.sliceB = slice;
Nicolas Capens0a8d3d12016-02-12 17:10:58 -05001258 external.sliceP = external.bytes ? slice / external.bytes : 0;
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001259 external.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001260 external.lock = LOCK_UNLOCKED;
1261 external.dirty = true;
1262
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001263 internal.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001264 internal.width = width;
1265 internal.height = height;
1266 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001267 internal.samples = 1;
Nicolas Capens477314b2015-06-09 16:47:29 -04001268 internal.format = selectInternalFormat(format);
1269 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001270 internal.pitchB = pitchB(internal.width, 0, internal.format, false);
1271 internal.pitchP = pitchP(internal.width, 0, internal.format, false);
1272 internal.sliceB = sliceB(internal.width, internal.height, 0, internal.format, false);
1273 internal.sliceP = sliceP(internal.width, internal.height, 0, internal.format, false);
1274 internal.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001275 internal.lock = LOCK_UNLOCKED;
1276 internal.dirty = false;
1277
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001278 stencil.buffer = nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001279 stencil.width = width;
1280 stencil.height = height;
1281 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001282 stencil.samples = 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001283 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
Nicolas Capens477314b2015-06-09 16:47:29 -04001284 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001285 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, false);
1286 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, false);
1287 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, false);
1288 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, false);
1289 stencil.border = 0;
Nicolas Capens477314b2015-06-09 16:47:29 -04001290 stencil.lock = LOCK_UNLOCKED;
1291 stencil.dirty = false;
1292
Nicolas Capens73e18c12017-11-28 13:31:35 -05001293 dirtyContents = true;
Nicolas Capens477314b2015-06-09 16:47:29 -04001294 paletteUsed = 0;
1295 }
1296
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001297 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 -04001298 {
1299 resource = texture ? texture : new Resource(0);
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001300 hasParent = texture != nullptr;
Nicolas Capens477314b2015-06-09 16:47:29 -04001301 ownExternal = true;
John Bauman89401822014-05-06 15:04:28 -04001302 depth = max(1, depth);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001303 samples = max(1, samples);
John Bauman89401822014-05-06 15:04:28 -04001304
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001305 external.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001306 external.width = width;
1307 external.height = height;
1308 external.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001309 external.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001310 external.format = format;
1311 external.bytes = bytes(external.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001312 external.pitchB = pitchB(external.width, 0, external.format, renderTarget && !texture);
1313 external.pitchP = pitchP(external.width, 0, external.format, renderTarget && !texture);
1314 external.sliceB = sliceB(external.width, external.height, 0, external.format, renderTarget && !texture);
1315 external.sliceP = sliceP(external.width, external.height, 0, external.format, renderTarget && !texture);
1316 external.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001317 external.lock = LOCK_UNLOCKED;
1318 external.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001319
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001320 internal.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001321 internal.width = width;
1322 internal.height = height;
1323 internal.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001324 internal.samples = (short)samples;
John Bauman89401822014-05-06 15:04:28 -04001325 internal.format = selectInternalFormat(format);
1326 internal.bytes = bytes(internal.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001327 internal.pitchB = !pitchPprovided ? pitchB(internal.width, border, internal.format, renderTarget) : pitchPprovided * internal.bytes;
1328 internal.pitchP = !pitchPprovided ? pitchP(internal.width, border, internal.format, renderTarget) : pitchPprovided;
1329 internal.sliceB = sliceB(internal.width, internal.height, border, internal.format, renderTarget);
1330 internal.sliceP = sliceP(internal.width, internal.height, border, internal.format, renderTarget);
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001331 internal.border = (short)border;
John Bauman89401822014-05-06 15:04:28 -04001332 internal.lock = LOCK_UNLOCKED;
1333 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001334
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001335 stencil.buffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001336 stencil.width = width;
1337 stencil.height = height;
1338 stencil.depth = depth;
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001339 stencil.samples = (short)samples;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001340 stencil.format = isStencil(format) ? FORMAT_S8 : FORMAT_NULL;
John Bauman89401822014-05-06 15:04:28 -04001341 stencil.bytes = bytes(stencil.format);
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001342 stencil.pitchB = pitchB(stencil.width, 0, stencil.format, renderTarget);
1343 stencil.pitchP = pitchP(stencil.width, 0, stencil.format, renderTarget);
1344 stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1345 stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, renderTarget);
1346 stencil.border = 0;
John Bauman89401822014-05-06 15:04:28 -04001347 stencil.lock = LOCK_UNLOCKED;
1348 stencil.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001349
Nicolas Capens73e18c12017-11-28 13:31:35 -05001350 dirtyContents = true;
John Bauman66b8ab22014-05-06 15:57:45 -04001351 paletteUsed = 0;
John Bauman89401822014-05-06 15:04:28 -04001352 }
1353
1354 Surface::~Surface()
1355 {
Nicolas Capensbf7a8142017-05-19 10:57:28 -04001356 // sync() must be called before this destructor to ensure all locks have been released.
1357 // We can't call it here because the parent resource may already have been destroyed.
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001358 ASSERT(isUnlocked());
John Bauman8a4f6fc2014-05-06 15:26:18 -04001359
John Bauman89401822014-05-06 15:04:28 -04001360 if(!hasParent)
1361 {
1362 resource->destruct();
1363 }
1364
Nicolas Capens477314b2015-06-09 16:47:29 -04001365 if(ownExternal)
1366 {
1367 deallocate(external.buffer);
1368 }
John Bauman89401822014-05-06 15:04:28 -04001369
1370 if(internal.buffer != external.buffer)
1371 {
1372 deallocate(internal.buffer);
1373 }
1374
1375 deallocate(stencil.buffer);
1376
1377 external.buffer = 0;
1378 internal.buffer = 0;
1379 stencil.buffer = 0;
1380 }
1381
John Bauman19bac1e2014-05-06 15:23:49 -04001382 void *Surface::lockExternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001383 {
1384 resource->lock(client);
1385
1386 if(!external.buffer)
1387 {
1388 if(internal.buffer && identicalFormats())
1389 {
1390 external.buffer = internal.buffer;
1391 }
1392 else
1393 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001394 external.buffer = allocateBuffer(external.width, external.height, external.depth, external.border, external.samples, external.format);
John Bauman89401822014-05-06 15:04:28 -04001395 }
1396 }
1397
1398 if(internal.dirty)
1399 {
1400 if(lock != LOCK_DISCARD)
1401 {
1402 update(external, internal);
1403 }
John Bauman66b8ab22014-05-06 15:57:45 -04001404
1405 internal.dirty = false;
John Bauman89401822014-05-06 15:04:28 -04001406 }
1407
1408 switch(lock)
1409 {
1410 case LOCK_READONLY:
1411 break;
1412 case LOCK_WRITEONLY:
1413 case LOCK_READWRITE:
1414 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001415 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001416 break;
1417 default:
1418 ASSERT(false);
1419 }
1420
John Bauman19bac1e2014-05-06 15:23:49 -04001421 return external.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001422 }
1423
1424 void Surface::unlockExternal()
1425 {
John Bauman89401822014-05-06 15:04:28 -04001426 external.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001427
1428 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001429 }
1430
John Bauman19bac1e2014-05-06 15:23:49 -04001431 void *Surface::lockInternal(int x, int y, int z, Lock lock, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001432 {
1433 if(lock != LOCK_UNLOCKED)
1434 {
1435 resource->lock(client);
1436 }
1437
1438 if(!internal.buffer)
1439 {
1440 if(external.buffer && identicalFormats())
1441 {
1442 internal.buffer = external.buffer;
1443 }
1444 else
1445 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001446 internal.buffer = allocateBuffer(internal.width, internal.height, internal.depth, internal.border, internal.samples, internal.format);
John Bauman89401822014-05-06 15:04:28 -04001447 }
1448 }
1449
1450 // FIXME: WHQL requires conversion to lower external precision and back
1451 if(logPrecision >= WHQL)
1452 {
1453 if(internal.dirty && renderTarget && internal.format != external.format)
1454 {
1455 if(lock != LOCK_DISCARD)
1456 {
1457 switch(external.format)
1458 {
1459 case FORMAT_R3G3B2:
1460 case FORMAT_A8R3G3B2:
1461 case FORMAT_A1R5G5B5:
1462 case FORMAT_A2R10G10B10:
1463 case FORMAT_A2B10G10R10:
1464 lockExternal(0, 0, 0, LOCK_READWRITE, client);
1465 unlockExternal();
1466 break;
1467 default:
1468 // Difference passes WHQL
1469 break;
1470 }
1471 }
1472 }
1473 }
1474
John Bauman66b8ab22014-05-06 15:57:45 -04001475 if(external.dirty || (isPalette(external.format) && paletteUsed != Surface::paletteID))
John Bauman89401822014-05-06 15:04:28 -04001476 {
1477 if(lock != LOCK_DISCARD)
1478 {
1479 update(internal, external);
1480 }
John Bauman89401822014-05-06 15:04:28 -04001481
John Bauman66b8ab22014-05-06 15:57:45 -04001482 external.dirty = false;
1483 paletteUsed = Surface::paletteID;
John Bauman89401822014-05-06 15:04:28 -04001484 }
1485
1486 switch(lock)
1487 {
1488 case LOCK_UNLOCKED:
1489 case LOCK_READONLY:
1490 break;
1491 case LOCK_WRITEONLY:
1492 case LOCK_READWRITE:
1493 case LOCK_DISCARD:
Nicolas Capens73e18c12017-11-28 13:31:35 -05001494 dirtyContents = true;
John Bauman89401822014-05-06 15:04:28 -04001495 break;
1496 default:
1497 ASSERT(false);
1498 }
1499
1500 if(lock == LOCK_READONLY && client == PUBLIC)
1501 {
1502 resolve();
1503 }
1504
John Bauman19bac1e2014-05-06 15:23:49 -04001505 return internal.lockRect(x, y, z, lock);
John Bauman89401822014-05-06 15:04:28 -04001506 }
1507
1508 void Surface::unlockInternal()
1509 {
John Bauman89401822014-05-06 15:04:28 -04001510 internal.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001511
1512 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001513 }
1514
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001515 void *Surface::lockStencil(int x, int y, int front, Accessor client)
John Bauman89401822014-05-06 15:04:28 -04001516 {
1517 resource->lock(client);
1518
1519 if(!stencil.buffer)
1520 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001521 stencil.buffer = allocateBuffer(stencil.width, stencil.height, stencil.depth, stencil.border, stencil.samples, stencil.format);
John Bauman89401822014-05-06 15:04:28 -04001522 }
1523
Alexis Hetua52dfbd2016-10-05 17:03:30 -04001524 return stencil.lockRect(x, y, front, LOCK_READWRITE); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001525 }
1526
1527 void Surface::unlockStencil()
1528 {
John Bauman89401822014-05-06 15:04:28 -04001529 stencil.unlockRect();
Antoine Labourfc2b84d2017-06-09 18:14:05 -07001530
1531 resource->unlock();
John Bauman89401822014-05-06 15:04:28 -04001532 }
1533
1534 int Surface::bytes(Format format)
1535 {
1536 switch(format)
1537 {
1538 case FORMAT_NULL: return 0;
1539 case FORMAT_P8: return 1;
1540 case FORMAT_A8P8: return 2;
1541 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001542 case FORMAT_R8I: return 1;
John Bauman89401822014-05-06 15:04:28 -04001543 case FORMAT_R8: return 1;
1544 case FORMAT_R3G3B2: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001545 case FORMAT_R16I: return 2;
1546 case FORMAT_R16UI: return 2;
John Bauman89401822014-05-06 15:04:28 -04001547 case FORMAT_A8R3G3B2: return 2;
1548 case FORMAT_R5G6B5: return 2;
1549 case FORMAT_A1R5G5B5: return 2;
1550 case FORMAT_X1R5G5B5: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001551 case FORMAT_R5G5B5A1: return 2;
John Bauman89401822014-05-06 15:04:28 -04001552 case FORMAT_X4R4G4B4: return 2;
1553 case FORMAT_A4R4G4B4: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001554 case FORMAT_R4G4B4A4: return 2;
John Bauman89401822014-05-06 15:04:28 -04001555 case FORMAT_R8G8B8: return 3;
Nicolas Capens80594422015-06-09 16:42:56 -04001556 case FORMAT_B8G8R8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001557 case FORMAT_R32I: return 4;
1558 case FORMAT_R32UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001559 case FORMAT_X8R8G8B8: return 4;
1560 // case FORMAT_X8G8R8B8Q: return 4;
1561 case FORMAT_A8R8G8B8: return 4;
1562 // case FORMAT_A8G8R8B8Q: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001563 case FORMAT_X8B8G8R8I: return 4;
John Bauman89401822014-05-06 15:04:28 -04001564 case FORMAT_X8B8G8R8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04001565 case FORMAT_SRGB8_X8: return 4;
1566 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001567 case FORMAT_A8B8G8R8I: return 4;
1568 case FORMAT_R8UI: return 1;
1569 case FORMAT_G8R8UI: return 2;
1570 case FORMAT_X8B8G8R8UI: return 4;
1571 case FORMAT_A8B8G8R8UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001572 case FORMAT_A8B8G8R8: return 4;
Nicolas Capens975adb72017-12-19 15:34:20 -05001573 case FORMAT_R8_SNORM: return 1;
1574 case FORMAT_G8R8_SNORM: return 2;
1575 case FORMAT_X8B8G8R8_SNORM: return 4;
1576 case FORMAT_A8B8G8R8_SNORM: return 4;
John Bauman89401822014-05-06 15:04:28 -04001577 case FORMAT_A2R10G10B10: return 4;
1578 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05001579 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001580 case FORMAT_G8R8I: return 2;
John Bauman89401822014-05-06 15:04:28 -04001581 case FORMAT_G8R8: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001582 case FORMAT_G16R16I: return 4;
1583 case FORMAT_G16R16UI: return 4;
John Bauman89401822014-05-06 15:04:28 -04001584 case FORMAT_G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001585 case FORMAT_G32R32I: return 8;
1586 case FORMAT_G32R32UI: return 8;
1587 case FORMAT_X16B16G16R16I: return 8;
1588 case FORMAT_X16B16G16R16UI: return 8;
1589 case FORMAT_A16B16G16R16I: return 8;
1590 case FORMAT_A16B16G16R16UI: return 8;
John Bauman89401822014-05-06 15:04:28 -04001591 case FORMAT_A16B16G16R16: return 8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04001592 case FORMAT_X32B32G32R32I: return 16;
1593 case FORMAT_X32B32G32R32UI: return 16;
1594 case FORMAT_A32B32G32R32I: return 16;
1595 case FORMAT_A32B32G32R32UI: return 16;
John Bauman89401822014-05-06 15:04:28 -04001596 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04001597 case FORMAT_DXT1: return 2; // Column of four pixels
1598 case FORMAT_DXT3: return 4; // Column of four pixels
1599 case FORMAT_DXT5: return 4; // Column of four pixels
1600 case FORMAT_ATI1: return 2; // Column of four pixels
1601 case FORMAT_ATI2: return 4; // Column of four pixels
Nicolas Capens22658242014-11-29 00:31:41 -05001602 case FORMAT_ETC1: return 2; // Column of four pixels
Alexis Hetu460e41f2015-09-01 10:58:37 -04001603 case FORMAT_R11_EAC: return 2;
1604 case FORMAT_SIGNED_R11_EAC: return 2;
1605 case FORMAT_RG11_EAC: return 4;
1606 case FORMAT_SIGNED_RG11_EAC: return 4;
1607 case FORMAT_RGB8_ETC2: return 2;
1608 case FORMAT_SRGB8_ETC2: return 2;
1609 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1610 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return 2;
1611 case FORMAT_RGBA8_ETC2_EAC: return 4;
1612 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: return 4;
1613 case FORMAT_RGBA_ASTC_4x4_KHR:
1614 case FORMAT_RGBA_ASTC_5x4_KHR:
1615 case FORMAT_RGBA_ASTC_5x5_KHR:
1616 case FORMAT_RGBA_ASTC_6x5_KHR:
1617 case FORMAT_RGBA_ASTC_6x6_KHR:
1618 case FORMAT_RGBA_ASTC_8x5_KHR:
1619 case FORMAT_RGBA_ASTC_8x6_KHR:
1620 case FORMAT_RGBA_ASTC_8x8_KHR:
1621 case FORMAT_RGBA_ASTC_10x5_KHR:
1622 case FORMAT_RGBA_ASTC_10x6_KHR:
1623 case FORMAT_RGBA_ASTC_10x8_KHR:
1624 case FORMAT_RGBA_ASTC_10x10_KHR:
1625 case FORMAT_RGBA_ASTC_12x10_KHR:
1626 case FORMAT_RGBA_ASTC_12x12_KHR:
1627 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1628 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1629 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1630 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1631 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1632 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1633 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1634 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1635 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1636 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1637 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1638 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1639 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1640 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR: return 0; // FIXME
John Bauman89401822014-05-06 15:04:28 -04001641 // Bumpmap formats
1642 case FORMAT_V8U8: return 2;
1643 case FORMAT_L6V5U5: return 2;
1644 case FORMAT_Q8W8V8U8: return 4;
1645 case FORMAT_X8L8V8U8: return 4;
1646 case FORMAT_A2W10V10U10: return 4;
1647 case FORMAT_V16U16: return 4;
1648 case FORMAT_A16W16V16U16: return 8;
1649 case FORMAT_Q16W16V16U16: return 8;
1650 // Luminance formats
1651 case FORMAT_L8: return 1;
1652 case FORMAT_A4L4: return 1;
1653 case FORMAT_L16: return 2;
1654 case FORMAT_A8L8: return 2;
Nicolas Capens80594422015-06-09 16:42:56 -04001655 case FORMAT_L16F: return 2;
1656 case FORMAT_A16L16F: return 4;
1657 case FORMAT_L32F: return 4;
1658 case FORMAT_A32L32F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001659 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04001660 case FORMAT_A16F: return 2;
John Bauman89401822014-05-06 15:04:28 -04001661 case FORMAT_R16F: return 2;
1662 case FORMAT_G16R16F: return 4;
Nicolas Capens80594422015-06-09 16:42:56 -04001663 case FORMAT_B16G16R16F: return 6;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05001664 case FORMAT_X16B16G16R16F: return 8;
John Bauman89401822014-05-06 15:04:28 -04001665 case FORMAT_A16B16G16R16F: return 8;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001666 case FORMAT_X16B16G16R16F_UNSIGNED: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001667 case FORMAT_A32F: return 4;
John Bauman89401822014-05-06 15:04:28 -04001668 case FORMAT_R32F: return 4;
1669 case FORMAT_G32R32F: return 8;
Nicolas Capens80594422015-06-09 16:42:56 -04001670 case FORMAT_B32G32R32F: return 12;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04001671 case FORMAT_X32B32G32R32F: return 16;
John Bauman89401822014-05-06 15:04:28 -04001672 case FORMAT_A32B32G32R32F: return 16;
Nicolas Capens67fdd832017-12-21 11:20:54 -05001673 case FORMAT_X32B32G32R32F_UNSIGNED: return 16;
John Bauman89401822014-05-06 15:04:28 -04001674 // Depth/stencil formats
1675 case FORMAT_D16: return 2;
1676 case FORMAT_D32: return 4;
1677 case FORMAT_D24X8: return 4;
1678 case FORMAT_D24S8: return 4;
1679 case FORMAT_D24FS8: return 4;
1680 case FORMAT_D32F: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001681 case FORMAT_D32FS8: return 4;
John Bauman89401822014-05-06 15:04:28 -04001682 case FORMAT_D32F_COMPLEMENTARY: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001683 case FORMAT_D32FS8_COMPLEMENTARY: return 4;
John Bauman89401822014-05-06 15:04:28 -04001684 case FORMAT_D32F_LOCKABLE: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001685 case FORMAT_D32FS8_TEXTURE: return 4;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05001686 case FORMAT_D32F_SHADOW: return 4;
John Bauman66b8ab22014-05-06 15:57:45 -04001687 case FORMAT_D32FS8_SHADOW: return 4;
1688 case FORMAT_DF24S8: return 4;
1689 case FORMAT_DF16S8: return 2;
John Bauman89401822014-05-06 15:04:28 -04001690 case FORMAT_INTZ: return 4;
1691 case FORMAT_S8: return 1;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001692 case FORMAT_YV12_BT601: return 1; // Y plane only
1693 case FORMAT_YV12_BT709: return 1; // Y plane only
1694 case FORMAT_YV12_JFIF: return 1; // Y plane only
John Bauman89401822014-05-06 15:04:28 -04001695 default:
1696 ASSERT(false);
1697 }
1698
1699 return 0;
1700 }
1701
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001702 int Surface::pitchB(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001703 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001704 width += 2 * border;
1705
John Bauman89401822014-05-06 15:04:28 -04001706 if(target || isDepth(format) || isStencil(format))
1707 {
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001708 width = align(width, 2);
John Bauman89401822014-05-06 15:04:28 -04001709 }
1710
1711 switch(format)
1712 {
John Bauman89401822014-05-06 15:04:28 -04001713 case FORMAT_DXT1:
Nicolas Capens22658242014-11-29 00:31:41 -05001714 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001715 case FORMAT_R11_EAC:
1716 case FORMAT_SIGNED_R11_EAC:
1717 case FORMAT_RGB8_ETC2:
1718 case FORMAT_SRGB8_ETC2:
1719 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1720 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Bauman89401822014-05-06 15:04:28 -04001721 return 8 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001722 case FORMAT_RG11_EAC:
1723 case FORMAT_SIGNED_RG11_EAC:
1724 case FORMAT_RGBA8_ETC2_EAC:
1725 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1726 case FORMAT_RGBA_ASTC_4x4_KHR:
1727 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1728 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1729 case FORMAT_RGBA_ASTC_5x4_KHR:
1730 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
1731 case FORMAT_RGBA_ASTC_5x5_KHR:
1732 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1733 return 16 * ((width + 4) / 5);
1734 case FORMAT_RGBA_ASTC_6x5_KHR:
1735 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1736 case FORMAT_RGBA_ASTC_6x6_KHR:
1737 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1738 return 16 * ((width + 5) / 6);
1739 case FORMAT_RGBA_ASTC_8x5_KHR:
1740 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1741 case FORMAT_RGBA_ASTC_8x6_KHR:
1742 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1743 case FORMAT_RGBA_ASTC_8x8_KHR:
1744 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1745 return 16 * ((width + 7) / 8);
1746 case FORMAT_RGBA_ASTC_10x5_KHR:
1747 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
1748 case FORMAT_RGBA_ASTC_10x6_KHR:
1749 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
1750 case FORMAT_RGBA_ASTC_10x8_KHR:
1751 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
1752 case FORMAT_RGBA_ASTC_10x10_KHR:
1753 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1754 return 16 * ((width + 9) / 10);
1755 case FORMAT_RGBA_ASTC_12x10_KHR:
1756 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
1757 case FORMAT_RGBA_ASTC_12x12_KHR:
1758 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
1759 return 16 * ((width + 11) / 12);
John Bauman89401822014-05-06 15:04:28 -04001760 case FORMAT_DXT3:
1761 case FORMAT_DXT5:
1762 return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
1763 case FORMAT_ATI1:
1764 return 2 * ((width + 3) / 4); // 64 bit per 4x4 block, computed per row
1765 case FORMAT_ATI2:
1766 return 4 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per row
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001767 case FORMAT_YV12_BT601:
1768 case FORMAT_YV12_BT709:
1769 case FORMAT_YV12_JFIF:
1770 return align(width, 16);
John Bauman89401822014-05-06 15:04:28 -04001771 default:
1772 return bytes(format) * width;
1773 }
1774 }
1775
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001776 int Surface::pitchP(int width, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001777 {
1778 int B = bytes(format);
1779
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001780 return B > 0 ? pitchB(width, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001781 }
1782
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001783 int Surface::sliceB(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001784 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001785 height += 2 * border;
1786
John Bauman89401822014-05-06 15:04:28 -04001787 if(target || isDepth(format) || isStencil(format))
1788 {
1789 height = ((height + 1) & ~1);
1790 }
1791
1792 switch(format)
1793 {
John Bauman89401822014-05-06 15:04:28 -04001794 case FORMAT_DXT1:
1795 case FORMAT_DXT3:
1796 case FORMAT_DXT5:
Nicolas Capens22658242014-11-29 00:31:41 -05001797 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001798 case FORMAT_R11_EAC:
1799 case FORMAT_SIGNED_R11_EAC:
1800 case FORMAT_RG11_EAC:
1801 case FORMAT_SIGNED_RG11_EAC:
1802 case FORMAT_RGB8_ETC2:
1803 case FORMAT_SRGB8_ETC2:
1804 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1805 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1806 case FORMAT_RGBA8_ETC2_EAC:
1807 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
1808 case FORMAT_RGBA_ASTC_4x4_KHR:
1809 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
1810 case FORMAT_RGBA_ASTC_5x4_KHR:
1811 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001812 return pitchB(width, border, format, target) * ((height + 3) / 4); // Pitch computed per 4 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001813 case FORMAT_RGBA_ASTC_5x5_KHR:
1814 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
1815 case FORMAT_RGBA_ASTC_6x5_KHR:
1816 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
1817 case FORMAT_RGBA_ASTC_8x5_KHR:
1818 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
1819 case FORMAT_RGBA_ASTC_10x5_KHR:
1820 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001821 return pitchB(width, border, format, target) * ((height + 4) / 5); // Pitch computed per 5 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001822 case FORMAT_RGBA_ASTC_6x6_KHR:
1823 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
1824 case FORMAT_RGBA_ASTC_8x6_KHR:
1825 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
1826 case FORMAT_RGBA_ASTC_10x6_KHR:
1827 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001828 return pitchB(width, border, format, target) * ((height + 5) / 6); // Pitch computed per 6 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001829 case FORMAT_RGBA_ASTC_8x8_KHR:
1830 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
1831 case FORMAT_RGBA_ASTC_10x8_KHR:
1832 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001833 return pitchB(width, border, format, target) * ((height + 7) / 8); // Pitch computed per 8 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001834 case FORMAT_RGBA_ASTC_10x10_KHR:
1835 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
1836 case FORMAT_RGBA_ASTC_12x10_KHR:
1837 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001838 return pitchB(width, border, format, target) * ((height + 9) / 10); // Pitch computed per 10 rows
Alexis Hetu460e41f2015-09-01 10:58:37 -04001839 case FORMAT_RGBA_ASTC_12x12_KHR:
1840 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001841 return pitchB(width, border, format, target) * ((height + 11) / 12); // Pitch computed per 12 rows
Nicolas Capens22658242014-11-29 00:31:41 -05001842 case FORMAT_ATI1:
1843 case FORMAT_ATI2:
John Bauman89401822014-05-06 15:04:28 -04001844 default:
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001845 return pitchB(width, border, format, target) * height; // Pitch computed per row
John Bauman89401822014-05-06 15:04:28 -04001846 }
1847 }
1848
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001849 int Surface::sliceP(int width, int height, int border, Format format, bool target)
John Bauman89401822014-05-06 15:04:28 -04001850 {
1851 int B = bytes(format);
1852
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001853 return B > 0 ? sliceB(width, height, border, format, target) / B : 0;
John Bauman89401822014-05-06 15:04:28 -04001854 }
1855
1856 void Surface::update(Buffer &destination, Buffer &source)
1857 {
1858 // ASSERT(source.lock != LOCK_UNLOCKED);
1859 // ASSERT(destination.lock != LOCK_UNLOCKED);
Nicolas Capensc39901e2016-03-21 16:37:44 -04001860
John Bauman89401822014-05-06 15:04:28 -04001861 if(destination.buffer != source.buffer)
1862 {
1863 ASSERT(source.dirty && !destination.dirty);
1864
1865 switch(source.format)
1866 {
1867 case FORMAT_R8G8B8: decodeR8G8B8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001868 case FORMAT_X1R5G5B5: decodeX1R5G5B5(destination, source); break; // FIXME: Check destination format
1869 case FORMAT_A1R5G5B5: decodeA1R5G5B5(destination, source); break; // FIXME: Check destination format
1870 case FORMAT_X4R4G4B4: decodeX4R4G4B4(destination, source); break; // FIXME: Check destination format
1871 case FORMAT_A4R4G4B4: decodeA4R4G4B4(destination, source); break; // FIXME: Check destination format
1872 case FORMAT_P8: decodeP8(destination, source); break; // FIXME: Check destination format
John Bauman89401822014-05-06 15:04:28 -04001873 case FORMAT_DXT1: decodeDXT1(destination, source); break; // FIXME: Check destination format
1874 case FORMAT_DXT3: decodeDXT3(destination, source); break; // FIXME: Check destination format
1875 case FORMAT_DXT5: decodeDXT5(destination, source); break; // FIXME: Check destination format
1876 case FORMAT_ATI1: decodeATI1(destination, source); break; // FIXME: Check destination format
1877 case FORMAT_ATI2: decodeATI2(destination, source); break; // FIXME: Check destination format
Alexis Hetu460e41f2015-09-01 10:58:37 -04001878 case FORMAT_R11_EAC: decodeEAC(destination, source, 1, false); break; // FIXME: Check destination format
1879 case FORMAT_SIGNED_R11_EAC: decodeEAC(destination, source, 1, true); break; // FIXME: Check destination format
1880 case FORMAT_RG11_EAC: decodeEAC(destination, source, 2, false); break; // FIXME: Check destination format
1881 case FORMAT_SIGNED_RG11_EAC: decodeEAC(destination, source, 2, true); break; // FIXME: Check destination format
Alexis Hetu0de50d42015-09-09 13:56:41 -04001882 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04001883 case FORMAT_RGB8_ETC2: decodeETC2(destination, source, 0, false); break; // FIXME: Check destination format
1884 case FORMAT_SRGB8_ETC2: decodeETC2(destination, source, 0, true); break; // FIXME: Check destination format
1885 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, false); break; // FIXME: Check destination format
1886 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: decodeETC2(destination, source, 1, true); break; // FIXME: Check destination format
1887 case FORMAT_RGBA8_ETC2_EAC: decodeETC2(destination, source, 8, false); break; // FIXME: Check destination format
1888 case FORMAT_SRGB8_ALPHA8_ETC2_EAC: decodeETC2(destination, source, 8, true); break; // FIXME: Check destination format
1889 case FORMAT_RGBA_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, false); break; // FIXME: Check destination format
1890 case FORMAT_RGBA_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, false); break; // FIXME: Check destination format
1891 case FORMAT_RGBA_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, false); break; // FIXME: Check destination format
1892 case FORMAT_RGBA_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, false); break; // FIXME: Check destination format
1893 case FORMAT_RGBA_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, false); break; // FIXME: Check destination format
1894 case FORMAT_RGBA_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, false); break; // FIXME: Check destination format
1895 case FORMAT_RGBA_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, false); break; // FIXME: Check destination format
1896 case FORMAT_RGBA_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, false); break; // FIXME: Check destination format
1897 case FORMAT_RGBA_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, false); break; // FIXME: Check destination format
1898 case FORMAT_RGBA_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, false); break; // FIXME: Check destination format
1899 case FORMAT_RGBA_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, false); break; // FIXME: Check destination format
1900 case FORMAT_RGBA_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, false); break; // FIXME: Check destination format
1901 case FORMAT_RGBA_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, false); break; // FIXME: Check destination format
1902 case FORMAT_RGBA_ASTC_12x12_KHR: decodeASTC(destination, source, 12, 12, 1, false); break; // FIXME: Check destination format
1903 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR: decodeASTC(destination, source, 4, 4, 1, true); break; // FIXME: Check destination format
1904 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR: decodeASTC(destination, source, 5, 4, 1, true); break; // FIXME: Check destination format
1905 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR: decodeASTC(destination, source, 5, 5, 1, true); break; // FIXME: Check destination format
1906 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR: decodeASTC(destination, source, 6, 5, 1, true); break; // FIXME: Check destination format
1907 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR: decodeASTC(destination, source, 6, 6, 1, true); break; // FIXME: Check destination format
1908 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR: decodeASTC(destination, source, 8, 5, 1, true); break; // FIXME: Check destination format
1909 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR: decodeASTC(destination, source, 8, 6, 1, true); break; // FIXME: Check destination format
1910 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR: decodeASTC(destination, source, 8, 8, 1, true); break; // FIXME: Check destination format
1911 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR: decodeASTC(destination, source, 10, 5, 1, true); break; // FIXME: Check destination format
1912 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR: decodeASTC(destination, source, 10, 6, 1, true); break; // FIXME: Check destination format
1913 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR: decodeASTC(destination, source, 10, 8, 1, true); break; // FIXME: Check destination format
1914 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR: decodeASTC(destination, source, 10, 10, 1, true); break; // FIXME: Check destination format
1915 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR: decodeASTC(destination, source, 12, 10, 1, true); break; // FIXME: Check destination format
1916 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 -04001917 default: genericUpdate(destination, source); break;
1918 }
1919 }
John Bauman89401822014-05-06 15:04:28 -04001920 }
1921
1922 void Surface::genericUpdate(Buffer &destination, Buffer &source)
1923 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001924 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
1925 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04001926
1927 int depth = min(destination.depth, source.depth);
1928 int height = min(destination.height, source.height);
1929 int width = min(destination.width, source.width);
1930 int rowBytes = width * source.bytes;
1931
1932 for(int z = 0; z < depth; z++)
1933 {
1934 unsigned char *sourceRow = sourceSlice;
1935 unsigned char *destinationRow = destinationSlice;
1936
1937 for(int y = 0; y < height; y++)
1938 {
1939 if(source.format == destination.format)
1940 {
1941 memcpy(destinationRow, sourceRow, rowBytes);
1942 }
1943 else
1944 {
1945 unsigned char *sourceElement = sourceRow;
1946 unsigned char *destinationElement = destinationRow;
1947
1948 for(int x = 0; x < width; x++)
1949 {
1950 Color<float> color = source.read(sourceElement);
1951 destination.write(destinationElement, color);
1952
1953 sourceElement += source.bytes;
1954 destinationElement += destination.bytes;
1955 }
1956 }
1957
1958 sourceRow += source.pitchB;
1959 destinationRow += destination.pitchB;
1960 }
1961
1962 sourceSlice += source.sliceB;
1963 destinationSlice += destination.sliceB;
1964 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001965
1966 source.unlockRect();
1967 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04001968 }
1969
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001970 void Surface::decodeR8G8B8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04001971 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05001972 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
1973 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04001974
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001975 int depth = min(destination.depth, source.depth);
1976 int height = min(destination.height, source.height);
1977 int width = min(destination.width, source.width);
1978
1979 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04001980 {
1981 unsigned char *sourceRow = sourceSlice;
1982 unsigned char *destinationRow = destinationSlice;
1983
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001984 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04001985 {
1986 unsigned char *sourceElement = sourceRow;
1987 unsigned char *destinationElement = destinationRow;
1988
Nicolas Capensbfa23b32017-12-11 10:06:37 -05001989 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04001990 {
1991 unsigned int b = sourceElement[0];
1992 unsigned int g = sourceElement[1];
1993 unsigned int r = sourceElement[2];
1994
1995 *(unsigned int*)destinationElement = 0xFF000000 | (r << 16) | (g << 8) | (b << 0);
1996
1997 sourceElement += source.bytes;
1998 destinationElement += destination.bytes;
1999 }
2000
2001 sourceRow += source.pitchB;
2002 destinationRow += destination.pitchB;
2003 }
2004
2005 sourceSlice += source.sliceB;
2006 destinationSlice += destination.sliceB;
2007 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002008
2009 source.unlockRect();
2010 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002011 }
2012
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002013 void Surface::decodeX1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002014 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002015 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
2016 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04002017
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002018 int depth = min(destination.depth, source.depth);
2019 int height = min(destination.height, source.height);
2020 int width = min(destination.width, source.width);
2021
2022 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002023 {
2024 unsigned char *sourceRow = sourceSlice;
2025 unsigned char *destinationRow = destinationSlice;
2026
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002027 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002028 {
2029 unsigned char *sourceElement = sourceRow;
2030 unsigned char *destinationElement = destinationRow;
2031
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002032 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002033 {
2034 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002035
John Bauman89401822014-05-06 15:04:28 -04002036 unsigned int r = (((xrgb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2037 unsigned int g = (((xrgb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2038 unsigned int b = (((xrgb & 0x001F) * 2106 + 0x80) >> 8);
2039
2040 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2041
2042 sourceElement += source.bytes;
2043 destinationElement += destination.bytes;
2044 }
2045
2046 sourceRow += source.pitchB;
2047 destinationRow += destination.pitchB;
2048 }
2049
2050 sourceSlice += source.sliceB;
2051 destinationSlice += destination.sliceB;
2052 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002053
2054 source.unlockRect();
2055 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002056 }
2057
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002058 void Surface::decodeA1R5G5B5(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002059 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002060 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
2061 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04002062
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002063 int depth = min(destination.depth, source.depth);
2064 int height = min(destination.height, source.height);
2065 int width = min(destination.width, source.width);
2066
2067 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002068 {
2069 unsigned char *sourceRow = sourceSlice;
2070 unsigned char *destinationRow = destinationSlice;
2071
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002072 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002073 {
2074 unsigned char *sourceElement = sourceRow;
2075 unsigned char *destinationElement = destinationRow;
2076
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002077 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002078 {
2079 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002080
John Bauman89401822014-05-06 15:04:28 -04002081 unsigned int a = (argb & 0x8000) * 130560;
2082 unsigned int r = (((argb & 0x7C00) * 134771 + 0x800000) >> 8) & 0x00FF0000;
2083 unsigned int g = (((argb & 0x03E0) * 16846 + 0x8000) >> 8) & 0x0000FF00;
2084 unsigned int b = (((argb & 0x001F) * 2106 + 0x80) >> 8);
2085
2086 *(unsigned int*)destinationElement = a | r | g | b;
2087
2088 sourceElement += source.bytes;
2089 destinationElement += destination.bytes;
2090 }
2091
2092 sourceRow += source.pitchB;
2093 destinationRow += destination.pitchB;
2094 }
2095
2096 sourceSlice += source.sliceB;
2097 destinationSlice += destination.sliceB;
2098 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002099
2100 source.unlockRect();
2101 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002102 }
2103
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002104 void Surface::decodeX4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002105 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002106 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
2107 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04002108
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002109 int depth = min(destination.depth, source.depth);
2110 int height = min(destination.height, source.height);
2111 int width = min(destination.width, source.width);
2112
2113 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002114 {
2115 unsigned char *sourceRow = sourceSlice;
2116 unsigned char *destinationRow = destinationSlice;
2117
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002118 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002119 {
2120 unsigned char *sourceElement = sourceRow;
2121 unsigned char *destinationElement = destinationRow;
2122
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002123 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002124 {
2125 unsigned int xrgb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002126
John Bauman89401822014-05-06 15:04:28 -04002127 unsigned int r = ((xrgb & 0x0F00) * 0x00001100) & 0x00FF0000;
2128 unsigned int g = ((xrgb & 0x00F0) * 0x00000110) & 0x0000FF00;
2129 unsigned int b = (xrgb & 0x000F) * 0x00000011;
2130
2131 *(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
2132
2133 sourceElement += source.bytes;
2134 destinationElement += destination.bytes;
2135 }
2136
2137 sourceRow += source.pitchB;
2138 destinationRow += destination.pitchB;
2139 }
2140
2141 sourceSlice += source.sliceB;
2142 destinationSlice += destination.sliceB;
2143 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002144
2145 source.unlockRect();
2146 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002147 }
2148
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002149 void Surface::decodeA4R4G4B4(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002150 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002151 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
2152 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04002153
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002154 int depth = min(destination.depth, source.depth);
2155 int height = min(destination.height, source.height);
2156 int width = min(destination.width, source.width);
2157
2158 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002159 {
2160 unsigned char *sourceRow = sourceSlice;
2161 unsigned char *destinationRow = destinationSlice;
2162
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002163 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002164 {
2165 unsigned char *sourceElement = sourceRow;
2166 unsigned char *destinationElement = destinationRow;
2167
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002168 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002169 {
2170 unsigned int argb = *(unsigned short*)sourceElement;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002171
John Bauman89401822014-05-06 15:04:28 -04002172 unsigned int a = ((argb & 0xF000) * 0x00011000) & 0xFF000000;
2173 unsigned int r = ((argb & 0x0F00) * 0x00001100) & 0x00FF0000;
2174 unsigned int g = ((argb & 0x00F0) * 0x00000110) & 0x0000FF00;
2175 unsigned int b = (argb & 0x000F) * 0x00000011;
2176
2177 *(unsigned int*)destinationElement = a | r | g | b;
2178
2179 sourceElement += source.bytes;
2180 destinationElement += destination.bytes;
2181 }
2182
2183 sourceRow += source.pitchB;
2184 destinationRow += destination.pitchB;
2185 }
2186
2187 sourceSlice += source.sliceB;
2188 destinationSlice += destination.sliceB;
2189 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002190
2191 source.unlockRect();
2192 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002193 }
2194
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002195 void Surface::decodeP8(Buffer &destination, Buffer &source)
John Bauman89401822014-05-06 15:04:28 -04002196 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002197 unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
2198 unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -04002199
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002200 int depth = min(destination.depth, source.depth);
2201 int height = min(destination.height, source.height);
2202 int width = min(destination.width, source.width);
2203
2204 for(int z = 0; z < depth; z++)
John Bauman89401822014-05-06 15:04:28 -04002205 {
2206 unsigned char *sourceRow = sourceSlice;
2207 unsigned char *destinationRow = destinationSlice;
2208
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002209 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04002210 {
2211 unsigned char *sourceElement = sourceRow;
2212 unsigned char *destinationElement = destinationRow;
2213
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002214 for(int x = 0; x < width; x++)
John Bauman89401822014-05-06 15:04:28 -04002215 {
2216 unsigned int abgr = palette[*(unsigned char*)sourceElement];
2217
2218 unsigned int r = (abgr & 0x000000FF) << 16;
2219 unsigned int g = (abgr & 0x0000FF00) << 0;
2220 unsigned int b = (abgr & 0x00FF0000) >> 16;
2221 unsigned int a = (abgr & 0xFF000000) >> 0;
2222
2223 *(unsigned int*)destinationElement = a | r | g | b;
2224
2225 sourceElement += source.bytes;
2226 destinationElement += destination.bytes;
2227 }
2228
2229 sourceRow += source.pitchB;
2230 destinationRow += destination.pitchB;
2231 }
2232
2233 sourceSlice += source.sliceB;
2234 destinationSlice += destination.sliceB;
2235 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002236
2237 source.unlockRect();
2238 destination.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002239 }
2240
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002241 void Surface::decodeDXT1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002242 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002243 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
2244 const DXT1 *source = (const DXT1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002245
2246 for(int z = 0; z < external.depth; z++)
2247 {
2248 unsigned int *dest = destSlice;
2249
2250 for(int y = 0; y < external.height; y += 4)
2251 {
2252 for(int x = 0; x < external.width; x += 4)
2253 {
2254 Color<byte> c[4];
2255
2256 c[0] = source->c0;
2257 c[1] = source->c1;
2258
2259 if(source->c0 > source->c1) // No transparency
2260 {
2261 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2262 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2263 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2264 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2265 c[2].a = 0xFF;
2266
2267 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2268 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2269 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2270 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2271 c[3].a = 0xFF;
2272 }
2273 else // c3 transparent
2274 {
2275 // c2 = 1 / 2 * c0 + 1 / 2 * c1
2276 c[2].r = (byte)(((word)c[0].r + (word)c[1].r) / 2);
2277 c[2].g = (byte)(((word)c[0].g + (word)c[1].g) / 2);
2278 c[2].b = (byte)(((word)c[0].b + (word)c[1].b) / 2);
2279 c[2].a = 0xFF;
2280
2281 c[3].r = 0;
2282 c[3].g = 0;
2283 c[3].b = 0;
2284 c[3].a = 0;
2285 }
2286
2287 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2288 {
2289 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2290 {
2291 dest[(x + i) + (y + j) * internal.width] = c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4];
2292 }
2293 }
2294
2295 source++;
2296 }
2297 }
2298
2299 (byte*&)destSlice += internal.sliceB;
2300 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002301
2302 external.unlockRect();
2303 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002304 }
2305
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002306 void Surface::decodeDXT3(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002307 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002308 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
2309 const DXT3 *source = (const DXT3*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002310
2311 for(int z = 0; z < external.depth; z++)
2312 {
2313 unsigned int *dest = destSlice;
2314
2315 for(int y = 0; y < external.height; y += 4)
2316 {
2317 for(int x = 0; x < external.width; x += 4)
2318 {
2319 Color<byte> c[4];
2320
2321 c[0] = source->c0;
2322 c[1] = source->c1;
2323
2324 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2325 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2326 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2327 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2328
2329 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2330 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2331 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2332 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2333
2334 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2335 {
2336 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2337 {
2338 unsigned int a = (unsigned int)(source->a >> 4 * (i + j * 4)) & 0x0F;
2339 unsigned int color = (c[(unsigned int)(source->lut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | ((a << 28) + (a << 24));
2340
2341 dest[(x + i) + (y + j) * internal.width] = color;
2342 }
2343 }
2344
2345 source++;
2346 }
2347 }
2348
2349 (byte*&)destSlice += internal.sliceB;
2350 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002351
2352 external.unlockRect();
2353 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002354 }
2355
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002356 void Surface::decodeDXT5(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002357 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002358 unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
2359 const DXT5 *source = (const DXT5*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002360
2361 for(int z = 0; z < external.depth; z++)
2362 {
2363 unsigned int *dest = destSlice;
2364
2365 for(int y = 0; y < external.height; y += 4)
2366 {
2367 for(int x = 0; x < external.width; x += 4)
2368 {
2369 Color<byte> c[4];
2370
2371 c[0] = source->c0;
2372 c[1] = source->c1;
2373
2374 // c2 = 2 / 3 * c0 + 1 / 3 * c1
2375 c[2].r = (byte)((2 * (word)c[0].r + (word)c[1].r + 1) / 3);
2376 c[2].g = (byte)((2 * (word)c[0].g + (word)c[1].g + 1) / 3);
2377 c[2].b = (byte)((2 * (word)c[0].b + (word)c[1].b + 1) / 3);
2378
2379 // c3 = 1 / 3 * c0 + 2 / 3 * c1
2380 c[3].r = (byte)(((word)c[0].r + 2 * (word)c[1].r + 1) / 3);
2381 c[3].g = (byte)(((word)c[0].g + 2 * (word)c[1].g + 1) / 3);
2382 c[3].b = (byte)(((word)c[0].b + 2 * (word)c[1].b + 1) / 3);
2383
2384 byte a[8];
2385
2386 a[0] = source->a0;
2387 a[1] = source->a1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002388
John Bauman89401822014-05-06 15:04:28 -04002389 if(a[0] > a[1])
2390 {
2391 a[2] = (byte)((6 * (word)a[0] + 1 * (word)a[1] + 3) / 7);
2392 a[3] = (byte)((5 * (word)a[0] + 2 * (word)a[1] + 3) / 7);
2393 a[4] = (byte)((4 * (word)a[0] + 3 * (word)a[1] + 3) / 7);
2394 a[5] = (byte)((3 * (word)a[0] + 4 * (word)a[1] + 3) / 7);
2395 a[6] = (byte)((2 * (word)a[0] + 5 * (word)a[1] + 3) / 7);
2396 a[7] = (byte)((1 * (word)a[0] + 6 * (word)a[1] + 3) / 7);
2397 }
2398 else
2399 {
2400 a[2] = (byte)((4 * (word)a[0] + 1 * (word)a[1] + 2) / 5);
2401 a[3] = (byte)((3 * (word)a[0] + 2 * (word)a[1] + 2) / 5);
2402 a[4] = (byte)((2 * (word)a[0] + 3 * (word)a[1] + 2) / 5);
2403 a[5] = (byte)((1 * (word)a[0] + 4 * (word)a[1] + 2) / 5);
2404 a[6] = 0;
2405 a[7] = 0xFF;
2406 }
2407
2408 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2409 {
2410 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2411 {
2412 unsigned int alpha = (unsigned int)a[(unsigned int)(source->alut >> (16 + 3 * (i + j * 4))) % 8] << 24;
2413 unsigned int color = (c[(source->clut >> 2 * (i + j * 4)) % 4] & 0x00FFFFFF) | alpha;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002414
John Bauman89401822014-05-06 15:04:28 -04002415 dest[(x + i) + (y + j) * internal.width] = color;
2416 }
2417 }
2418
2419 source++;
2420 }
2421 }
2422
2423 (byte*&)destSlice += internal.sliceB;
2424 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002425
2426 external.unlockRect();
2427 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002428 }
2429
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002430 void Surface::decodeATI1(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002431 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002432 byte *destSlice = (byte*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
2433 const ATI1 *source = (const ATI1*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002434
2435 for(int z = 0; z < external.depth; z++)
2436 {
2437 byte *dest = destSlice;
2438
2439 for(int y = 0; y < external.height; y += 4)
2440 {
2441 for(int x = 0; x < external.width; x += 4)
2442 {
2443 byte r[8];
2444
2445 r[0] = source->r0;
2446 r[1] = source->r1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002447
John Bauman89401822014-05-06 15:04:28 -04002448 if(r[0] > r[1])
2449 {
2450 r[2] = (byte)((6 * (word)r[0] + 1 * (word)r[1] + 3) / 7);
2451 r[3] = (byte)((5 * (word)r[0] + 2 * (word)r[1] + 3) / 7);
2452 r[4] = (byte)((4 * (word)r[0] + 3 * (word)r[1] + 3) / 7);
2453 r[5] = (byte)((3 * (word)r[0] + 4 * (word)r[1] + 3) / 7);
2454 r[6] = (byte)((2 * (word)r[0] + 5 * (word)r[1] + 3) / 7);
2455 r[7] = (byte)((1 * (word)r[0] + 6 * (word)r[1] + 3) / 7);
2456 }
2457 else
2458 {
2459 r[2] = (byte)((4 * (word)r[0] + 1 * (word)r[1] + 2) / 5);
2460 r[3] = (byte)((3 * (word)r[0] + 2 * (word)r[1] + 2) / 5);
2461 r[4] = (byte)((2 * (word)r[0] + 3 * (word)r[1] + 2) / 5);
2462 r[5] = (byte)((1 * (word)r[0] + 4 * (word)r[1] + 2) / 5);
2463 r[6] = 0;
2464 r[7] = 0xFF;
2465 }
2466
2467 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2468 {
2469 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2470 {
2471 dest[(x + i) + (y + j) * internal.width] = r[(unsigned int)(source->rlut >> (16 + 3 * (i + j * 4))) % 8];
2472 }
2473 }
2474
2475 source++;
2476 }
2477 }
2478
2479 destSlice += internal.sliceB;
2480 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002481
2482 external.unlockRect();
2483 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002484 }
2485
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002486 void Surface::decodeATI2(Buffer &internal, Buffer &external)
John Bauman89401822014-05-06 15:04:28 -04002487 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002488 word *destSlice = (word*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
2489 const ATI2 *source = (const ATI2*)external.lockRect(0, 0, 0, LOCK_READONLY);
John Bauman89401822014-05-06 15:04:28 -04002490
2491 for(int z = 0; z < external.depth; z++)
2492 {
2493 word *dest = destSlice;
2494
2495 for(int y = 0; y < external.height; y += 4)
2496 {
2497 for(int x = 0; x < external.width; x += 4)
2498 {
2499 byte X[8];
2500
2501 X[0] = source->x0;
2502 X[1] = source->x1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002503
John Bauman89401822014-05-06 15:04:28 -04002504 if(X[0] > X[1])
2505 {
2506 X[2] = (byte)((6 * (word)X[0] + 1 * (word)X[1] + 3) / 7);
2507 X[3] = (byte)((5 * (word)X[0] + 2 * (word)X[1] + 3) / 7);
2508 X[4] = (byte)((4 * (word)X[0] + 3 * (word)X[1] + 3) / 7);
2509 X[5] = (byte)((3 * (word)X[0] + 4 * (word)X[1] + 3) / 7);
2510 X[6] = (byte)((2 * (word)X[0] + 5 * (word)X[1] + 3) / 7);
2511 X[7] = (byte)((1 * (word)X[0] + 6 * (word)X[1] + 3) / 7);
2512 }
2513 else
2514 {
2515 X[2] = (byte)((4 * (word)X[0] + 1 * (word)X[1] + 2) / 5);
2516 X[3] = (byte)((3 * (word)X[0] + 2 * (word)X[1] + 2) / 5);
2517 X[4] = (byte)((2 * (word)X[0] + 3 * (word)X[1] + 2) / 5);
2518 X[5] = (byte)((1 * (word)X[0] + 4 * (word)X[1] + 2) / 5);
2519 X[6] = 0;
2520 X[7] = 0xFF;
2521 }
2522
2523 byte Y[8];
2524
2525 Y[0] = source->y0;
2526 Y[1] = source->y1;
Nicolas Capensc39901e2016-03-21 16:37:44 -04002527
John Bauman89401822014-05-06 15:04:28 -04002528 if(Y[0] > Y[1])
2529 {
2530 Y[2] = (byte)((6 * (word)Y[0] + 1 * (word)Y[1] + 3) / 7);
2531 Y[3] = (byte)((5 * (word)Y[0] + 2 * (word)Y[1] + 3) / 7);
2532 Y[4] = (byte)((4 * (word)Y[0] + 3 * (word)Y[1] + 3) / 7);
2533 Y[5] = (byte)((3 * (word)Y[0] + 4 * (word)Y[1] + 3) / 7);
2534 Y[6] = (byte)((2 * (word)Y[0] + 5 * (word)Y[1] + 3) / 7);
2535 Y[7] = (byte)((1 * (word)Y[0] + 6 * (word)Y[1] + 3) / 7);
2536 }
2537 else
2538 {
2539 Y[2] = (byte)((4 * (word)Y[0] + 1 * (word)Y[1] + 2) / 5);
2540 Y[3] = (byte)((3 * (word)Y[0] + 2 * (word)Y[1] + 2) / 5);
2541 Y[4] = (byte)((2 * (word)Y[0] + 3 * (word)Y[1] + 2) / 5);
2542 Y[5] = (byte)((1 * (word)Y[0] + 4 * (word)Y[1] + 2) / 5);
2543 Y[6] = 0;
2544 Y[7] = 0xFF;
2545 }
2546
2547 for(int j = 0; j < 4 && (y + j) < internal.height; j++)
2548 {
2549 for(int i = 0; i < 4 && (x + i) < internal.width; i++)
2550 {
2551 word r = X[(unsigned int)(source->xlut >> (16 + 3 * (i + j * 4))) % 8];
2552 word g = Y[(unsigned int)(source->ylut >> (16 + 3 * (i + j * 4))) % 8];
2553
2554 dest[(x + i) + (y + j) * internal.width] = (g << 8) + r;
2555 }
2556 }
2557
2558 source++;
2559 }
2560 }
2561
2562 (byte*&)destSlice += internal.sliceB;
2563 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002564
2565 external.unlockRect();
2566 internal.unlockRect();
John Bauman89401822014-05-06 15:04:28 -04002567 }
Nicolas Capens22658242014-11-29 00:31:41 -05002568
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002569 void Surface::decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002570 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002571 ETC_Decoder::Decode((const byte*)external.lockRect(0, 0, 0, LOCK_READONLY), (byte*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY), external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes,
Alexis Hetu0de50d42015-09-09 13:56:41 -04002572 (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 -05002573 external.unlockRect();
2574 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002575
Alexis Hetu0de50d42015-09-09 13:56:41 -04002576 if(isSRGB)
Nicolas Capens22658242014-11-29 00:31:41 -05002577 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002578 static byte sRGBtoLinearTable[256];
2579 static bool sRGBtoLinearTableDirty = true;
2580 if(sRGBtoLinearTableDirty)
Nicolas Capens22658242014-11-29 00:31:41 -05002581 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002582 for(int i = 0; i < 256; i++)
Nicolas Capens22658242014-11-29 00:31:41 -05002583 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002584 sRGBtoLinearTable[i] = static_cast<byte>(sRGBtoLinear(static_cast<float>(i) / 255.0f) * 255.0f + 0.5f);
Nicolas Capens22658242014-11-29 00:31:41 -05002585 }
Alexis Hetu0de50d42015-09-09 13:56:41 -04002586 sRGBtoLinearTableDirty = false;
Nicolas Capens22658242014-11-29 00:31:41 -05002587 }
2588
Alexis Hetu0de50d42015-09-09 13:56:41 -04002589 // Perform sRGB conversion in place after decoding
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002590 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002591 for(int y = 0; y < internal.height; y++)
2592 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002593 byte *srcRow = src + y * internal.pitchB;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002594 for(int x = 0; x < internal.width; x++)
2595 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002596 byte *srcPix = srcRow + x * internal.bytes;
Alexis Hetu0de50d42015-09-09 13:56:41 -04002597 for(int i = 0; i < 3; i++)
2598 {
2599 srcPix[i] = sRGBtoLinearTable[srcPix[i]];
2600 }
2601 }
2602 }
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002603 internal.unlockRect();
Nicolas Capens22658242014-11-29 00:31:41 -05002604 }
2605 }
John Bauman89401822014-05-06 15:04:28 -04002606
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002607 void Surface::decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002608 {
Alexis Hetu0de50d42015-09-09 13:56:41 -04002609 ASSERT(nbChannels == 1 || nbChannels == 2);
Alexis Hetu460e41f2015-09-01 10:58:37 -04002610
Alexis Hetuf46493f2017-12-18 15:32:26 -05002611 byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
2612 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 -04002613 (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 -05002614 external.unlockRect();
Alexis Hetu0de50d42015-09-09 13:56:41 -04002615
Alexis Hetuf46493f2017-12-18 15:32:26 -05002616 // FIXME: We convert EAC data to float, until signed short internal formats are supported
2617 // This code can be removed if ETC2 images are decoded to internal 16 bit signed R/RG formats
2618 const float normalization = isSigned ? (1.0f / (8.0f * 127.875f)) : (1.0f / (8.0f * 255.875f));
2619 for(int y = 0; y < internal.height; y++)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002620 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002621 byte* srcRow = src + y * internal.pitchB;
2622 for(int x = internal.width - 1; x >= 0; x--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002623 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002624 int* srcPix = reinterpret_cast<int*>(srcRow + x * internal.bytes);
2625 float* dstPix = reinterpret_cast<float*>(srcPix);
2626 for(int c = nbChannels - 1; c >= 0; c--)
Alexis Hetu0de50d42015-09-09 13:56:41 -04002627 {
Alexis Hetuf46493f2017-12-18 15:32:26 -05002628 dstPix[c] = clamp(static_cast<float>(srcPix[c]) * normalization, -1.0f, 1.0f);
Alexis Hetu0de50d42015-09-09 13:56:41 -04002629 }
2630 }
2631 }
Alexis Hetuf46493f2017-12-18 15:32:26 -05002632
2633 internal.unlockRect();
Alexis Hetu460e41f2015-09-01 10:58:37 -04002634 }
2635
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002636 void Surface::decodeASTC(Buffer &internal, Buffer &external, int xBlockSize, int yBlockSize, int zBlockSize, bool isSRGB)
Alexis Hetu460e41f2015-09-01 10:58:37 -04002637 {
2638 }
2639
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002640 unsigned int Surface::size(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04002641 {
Alexis Hetu9c6d5222016-11-29 17:02:14 -05002642 width += 2 * border;
2643 height += 2 * border;
2644
Nicolas Capens00555c42015-07-21 15:15:30 -04002645 // Dimensions rounded up to multiples of 4, used for compressed formats
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002646 int width4 = align(width, 4);
2647 int height4 = align(height, 4);
John Bauman89401822014-05-06 15:04:28 -04002648
2649 switch(format)
2650 {
John Bauman89401822014-05-06 15:04:28 -04002651 case FORMAT_DXT1:
2652 case FORMAT_ATI1:
Nicolas Capens22658242014-11-29 00:31:41 -05002653 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04002654 case FORMAT_R11_EAC:
2655 case FORMAT_SIGNED_R11_EAC:
2656 case FORMAT_RGB8_ETC2:
2657 case FORMAT_SRGB8_ETC2:
2658 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2659 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
John Bauman89401822014-05-06 15:04:28 -04002660 return width4 * height4 * depth / 2;
2661 case FORMAT_DXT3:
2662 case FORMAT_DXT5:
2663 case FORMAT_ATI2:
Alexis Hetu460e41f2015-09-01 10:58:37 -04002664 case FORMAT_RG11_EAC:
2665 case FORMAT_SIGNED_RG11_EAC:
2666 case FORMAT_RGBA8_ETC2_EAC:
2667 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
2668 case FORMAT_RGBA_ASTC_4x4_KHR:
2669 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
John Bauman89401822014-05-06 15:04:28 -04002670 return width4 * height4 * depth;
Alexis Hetu460e41f2015-09-01 10:58:37 -04002671 case FORMAT_RGBA_ASTC_5x4_KHR:
2672 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
2673 return align(width, 5) * height4 * depth;
2674 case FORMAT_RGBA_ASTC_5x5_KHR:
2675 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
2676 return align(width, 5) * align(height, 5) * depth;
2677 case FORMAT_RGBA_ASTC_6x5_KHR:
2678 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
2679 return align(width, 6) * align(height, 5) * depth;
2680 case FORMAT_RGBA_ASTC_6x6_KHR:
2681 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
2682 return align(width, 6) * align(height, 6) * depth;
2683 case FORMAT_RGBA_ASTC_8x5_KHR:
2684 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
2685 return align(width, 8) * align(height, 5) * depth;
2686 case FORMAT_RGBA_ASTC_8x6_KHR:
2687 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
2688 return align(width, 8) * align(height, 6) * depth;
2689 case FORMAT_RGBA_ASTC_8x8_KHR:
2690 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
2691 return align(width, 8) * align(height, 8) * depth;
2692 case FORMAT_RGBA_ASTC_10x5_KHR:
2693 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
2694 return align(width, 10) * align(height, 5) * depth;
2695 case FORMAT_RGBA_ASTC_10x6_KHR:
2696 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
2697 return align(width, 10) * align(height, 6) * depth;
2698 case FORMAT_RGBA_ASTC_10x8_KHR:
2699 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
2700 return align(width, 10) * align(height, 8) * depth;
2701 case FORMAT_RGBA_ASTC_10x10_KHR:
2702 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
2703 return align(width, 10) * align(height, 10) * depth;
2704 case FORMAT_RGBA_ASTC_12x10_KHR:
2705 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
2706 return align(width, 12) * align(height, 10) * depth;
2707 case FORMAT_RGBA_ASTC_12x12_KHR:
2708 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
2709 return align(width, 12) * align(height, 12) * depth;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002710 case FORMAT_YV12_BT601:
2711 case FORMAT_YV12_BT709:
2712 case FORMAT_YV12_JFIF:
2713 {
2714 unsigned int YStride = align(width, 16);
2715 unsigned int YSize = YStride * height;
2716 unsigned int CStride = align(YStride / 2, 16);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002717 unsigned int CSize = CStride * height / 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002718
2719 return YSize + 2 * CSize;
2720 }
John Bauman89401822014-05-06 15:04:28 -04002721 default:
Nicolas Capensbfa23b32017-12-11 10:06:37 -05002722 return bytes(format) * width * height * depth * samples;
John Bauman89401822014-05-06 15:04:28 -04002723 }
John Bauman89401822014-05-06 15:04:28 -04002724 }
2725
2726 bool Surface::isStencil(Format format)
2727 {
2728 switch(format)
2729 {
2730 case FORMAT_D32:
2731 case FORMAT_D16:
2732 case FORMAT_D24X8:
2733 case FORMAT_D32F:
2734 case FORMAT_D32F_COMPLEMENTARY:
2735 case FORMAT_D32F_LOCKABLE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002736 case FORMAT_D32F_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002737 return false;
2738 case FORMAT_D24S8:
2739 case FORMAT_D24FS8:
2740 case FORMAT_S8:
John Bauman66b8ab22014-05-06 15:57:45 -04002741 case FORMAT_DF24S8:
2742 case FORMAT_DF16S8:
2743 case FORMAT_D32FS8_TEXTURE:
2744 case FORMAT_D32FS8_SHADOW:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002745 case FORMAT_D32FS8:
2746 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002747 case FORMAT_INTZ:
2748 return true;
2749 default:
2750 return false;
2751 }
2752 }
2753
2754 bool Surface::isDepth(Format format)
2755 {
2756 switch(format)
2757 {
2758 case FORMAT_D32:
2759 case FORMAT_D16:
2760 case FORMAT_D24X8:
2761 case FORMAT_D24S8:
2762 case FORMAT_D24FS8:
2763 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002764 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002765 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002766 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002767 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002768 case FORMAT_DF24S8:
2769 case FORMAT_DF16S8:
2770 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002771 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002772 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002773 case FORMAT_INTZ:
2774 return true;
2775 case FORMAT_S8:
2776 return false;
2777 default:
2778 return false;
2779 }
2780 }
2781
Alexis Hetub9dda642016-10-06 11:25:32 -04002782 bool Surface::hasQuadLayout(Format format)
2783 {
2784 switch(format)
2785 {
2786 case FORMAT_D32:
2787 case FORMAT_D16:
2788 case FORMAT_D24X8:
2789 case FORMAT_D24S8:
2790 case FORMAT_D24FS8:
2791 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002792 case FORMAT_D32FS8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002793 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002794 case FORMAT_D32FS8_COMPLEMENTARY:
Alexis Hetub9dda642016-10-06 11:25:32 -04002795 case FORMAT_DF24S8:
2796 case FORMAT_DF16S8:
2797 case FORMAT_INTZ:
2798 case FORMAT_S8:
2799 case FORMAT_A8G8R8B8Q:
2800 case FORMAT_X8G8R8B8Q:
2801 return true;
2802 case FORMAT_D32F_LOCKABLE:
2803 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002804 case FORMAT_D32F_SHADOW:
Alexis Hetub9dda642016-10-06 11:25:32 -04002805 case FORMAT_D32FS8_SHADOW:
2806 default:
2807 break;
2808 }
2809
2810 return false;
2811 }
2812
John Bauman89401822014-05-06 15:04:28 -04002813 bool Surface::isPalette(Format format)
2814 {
2815 switch(format)
2816 {
2817 case FORMAT_P8:
2818 case FORMAT_A8P8:
2819 return true;
2820 default:
2821 return false;
2822 }
2823 }
2824
2825 bool Surface::isFloatFormat(Format format)
2826 {
2827 switch(format)
2828 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002829 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002830 case FORMAT_R8G8B8:
2831 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002832 case FORMAT_X8R8G8B8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002833 case FORMAT_X8B8G8R8I:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002834 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002835 case FORMAT_A8R8G8B8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002836 case FORMAT_SRGB8_X8:
2837 case FORMAT_SRGB8_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002838 case FORMAT_A8B8G8R8I:
2839 case FORMAT_R8UI:
2840 case FORMAT_G8R8UI:
2841 case FORMAT_X8B8G8R8UI:
2842 case FORMAT_A8B8G8R8UI:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002843 case FORMAT_A8B8G8R8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002844 case FORMAT_G8R8I:
John Bauman89401822014-05-06 15:04:28 -04002845 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002846 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002847 case FORMAT_A2B10G10R10UI:
Nicolas Capens975adb72017-12-19 15:34:20 -05002848 case FORMAT_R8_SNORM:
2849 case FORMAT_G8R8_SNORM:
2850 case FORMAT_X8B8G8R8_SNORM:
2851 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu43577b82015-10-21 15:32:16 -04002852 case FORMAT_R16I:
2853 case FORMAT_R16UI:
2854 case FORMAT_G16R16I:
2855 case FORMAT_G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002856 case FORMAT_G16R16:
Alexis Hetu43577b82015-10-21 15:32:16 -04002857 case FORMAT_X16B16G16R16I:
2858 case FORMAT_X16B16G16R16UI:
2859 case FORMAT_A16B16G16R16I:
2860 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002861 case FORMAT_A16B16G16R16:
2862 case FORMAT_V8U8:
2863 case FORMAT_Q8W8V8U8:
2864 case FORMAT_X8L8V8U8:
2865 case FORMAT_V16U16:
2866 case FORMAT_A16W16V16U16:
2867 case FORMAT_Q16W16V16U16:
2868 case FORMAT_A8:
Alexis Hetu43577b82015-10-21 15:32:16 -04002869 case FORMAT_R8I:
John Bauman89401822014-05-06 15:04:28 -04002870 case FORMAT_R8:
Alexis Hetub9dda642016-10-06 11:25:32 -04002871 case FORMAT_S8:
John Bauman89401822014-05-06 15:04:28 -04002872 case FORMAT_L8:
2873 case FORMAT_L16:
2874 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002875 case FORMAT_YV12_BT601:
2876 case FORMAT_YV12_BT709:
2877 case FORMAT_YV12_JFIF:
Alexis Hetu43577b82015-10-21 15:32:16 -04002878 case FORMAT_R32I:
2879 case FORMAT_R32UI:
2880 case FORMAT_G32R32I:
2881 case FORMAT_G32R32UI:
2882 case FORMAT_X32B32G32R32I:
2883 case FORMAT_X32B32G32R32UI:
2884 case FORMAT_A32B32G32R32I:
2885 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002886 return false;
Nicolas Capens400667e2017-03-29 14:40:14 -04002887 case FORMAT_R16F:
2888 case FORMAT_G16R16F:
2889 case FORMAT_B16G16R16F:
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05002890 case FORMAT_X16B16G16R16F:
Nicolas Capens400667e2017-03-29 14:40:14 -04002891 case FORMAT_A16B16G16R16F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002892 case FORMAT_X16B16G16R16F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002893 case FORMAT_R32F:
2894 case FORMAT_G32R32F:
Nicolas Capensc018e082016-12-13 10:19:33 -05002895 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002896 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002897 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002898 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002899 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002900 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002901 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002902 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002903 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002904 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002905 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002906 case FORMAT_D32FS8_SHADOW:
Nicolas Capens80594422015-06-09 16:42:56 -04002907 case FORMAT_L16F:
2908 case FORMAT_A16L16F:
2909 case FORMAT_L32F:
2910 case FORMAT_A32L32F:
John Bauman89401822014-05-06 15:04:28 -04002911 return true;
2912 default:
2913 ASSERT(false);
2914 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04002915
John Bauman89401822014-05-06 15:04:28 -04002916 return false;
2917 }
2918
2919 bool Surface::isUnsignedComponent(Format format, int component)
2920 {
2921 switch(format)
2922 {
2923 case FORMAT_NULL:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04002924 case FORMAT_R5G6B5:
Alexis Hetu925c2822015-11-24 14:09:34 -05002925 case FORMAT_R8G8B8:
2926 case FORMAT_B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002927 case FORMAT_X8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002928 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002929 case FORMAT_A8R8G8B8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04002930 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002931 case FORMAT_SRGB8_X8:
2932 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002933 case FORMAT_G8R8:
Alexis Hetuf999a002015-12-17 11:09:36 -05002934 case FORMAT_A2B10G10R10:
Nicolas Capens5555af42017-12-14 13:14:03 -05002935 case FORMAT_A2B10G10R10UI:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002936 case FORMAT_R16UI:
John Bauman89401822014-05-06 15:04:28 -04002937 case FORMAT_G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002938 case FORMAT_G16R16UI:
2939 case FORMAT_X16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002940 case FORMAT_A16B16G16R16:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002941 case FORMAT_A16B16G16R16UI:
2942 case FORMAT_R32UI:
2943 case FORMAT_G32R32UI:
2944 case FORMAT_X32B32G32R32UI:
2945 case FORMAT_A32B32G32R32UI:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002946 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002947 case FORMAT_R8UI:
2948 case FORMAT_G8R8UI:
2949 case FORMAT_X8B8G8R8UI:
2950 case FORMAT_A8B8G8R8UI:
John Bauman89401822014-05-06 15:04:28 -04002951 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002952 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002953 case FORMAT_D32F_COMPLEMENTARY:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002954 case FORMAT_D32FS8_COMPLEMENTARY:
John Bauman89401822014-05-06 15:04:28 -04002955 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002956 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002957 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002958 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04002959 case FORMAT_A8:
2960 case FORMAT_R8:
2961 case FORMAT_L8:
2962 case FORMAT_L16:
2963 case FORMAT_A8L8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002964 case FORMAT_YV12_BT601:
2965 case FORMAT_YV12_BT709:
2966 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002967 return true;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002968 case FORMAT_A8B8G8R8I:
2969 case FORMAT_A16B16G16R16I:
2970 case FORMAT_A32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002971 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002972 case FORMAT_Q8W8V8U8:
2973 case FORMAT_Q16W16V16U16:
2974 case FORMAT_A32B32G32R32F:
2975 return false;
2976 case FORMAT_R32F:
2977 case FORMAT_R8I:
2978 case FORMAT_R16I:
2979 case FORMAT_R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002980 case FORMAT_R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002981 return component >= 1;
John Bauman89401822014-05-06 15:04:28 -04002982 case FORMAT_V8U8:
2983 case FORMAT_X8L8V8U8:
2984 case FORMAT_V16U16:
John Bauman89401822014-05-06 15:04:28 -04002985 case FORMAT_G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002986 case FORMAT_G8R8I:
2987 case FORMAT_G16R16I:
2988 case FORMAT_G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002989 case FORMAT_G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002990 return component >= 2;
2991 case FORMAT_A16W16V16U16:
Nicolas Capens2e363b02016-12-14 10:32:36 -05002992 case FORMAT_B32G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002993 case FORMAT_X32B32G32R32F:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002994 case FORMAT_X8B8G8R8I:
2995 case FORMAT_X16B16G16R16I:
2996 case FORMAT_X32B32G32R32I:
Nicolas Capens975adb72017-12-19 15:34:20 -05002997 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04002998 return component >= 3;
John Bauman89401822014-05-06 15:04:28 -04002999 default:
3000 ASSERT(false);
3001 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04003002
John Bauman89401822014-05-06 15:04:28 -04003003 return false;
3004 }
3005
3006 bool Surface::isSRGBreadable(Format format)
3007 {
3008 // Keep in sync with Capabilities::isSRGBreadable
3009 switch(format)
3010 {
3011 case FORMAT_L8:
3012 case FORMAT_A8L8:
3013 case FORMAT_R8G8B8:
3014 case FORMAT_A8R8G8B8:
3015 case FORMAT_X8R8G8B8:
3016 case FORMAT_A8B8G8R8:
3017 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04003018 case FORMAT_SRGB8_X8:
3019 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04003020 case FORMAT_R5G6B5:
3021 case FORMAT_X1R5G5B5:
3022 case FORMAT_A1R5G5B5:
3023 case FORMAT_A4R4G4B4:
John Bauman89401822014-05-06 15:04:28 -04003024 case FORMAT_DXT1:
3025 case FORMAT_DXT3:
3026 case FORMAT_DXT5:
3027 case FORMAT_ATI1:
3028 case FORMAT_ATI2:
John Bauman89401822014-05-06 15:04:28 -04003029 return true;
3030 default:
3031 return false;
3032 }
John Bauman89401822014-05-06 15:04:28 -04003033 }
3034
3035 bool Surface::isSRGBwritable(Format format)
3036 {
3037 // Keep in sync with Capabilities::isSRGBwritable
3038 switch(format)
3039 {
3040 case FORMAT_NULL:
3041 case FORMAT_A8R8G8B8:
3042 case FORMAT_X8R8G8B8:
3043 case FORMAT_A8B8G8R8:
3044 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04003045 case FORMAT_SRGB8_X8:
3046 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04003047 case FORMAT_R5G6B5:
3048 return true;
3049 default:
3050 return false;
3051 }
3052 }
3053
Nicolas Capens5555af42017-12-14 13:14:03 -05003054 bool Surface::isSRGBformat(Format format)
3055 {
3056 switch(format)
3057 {
3058 case FORMAT_SRGB8_X8:
3059 case FORMAT_SRGB8_A8:
3060 return true;
3061 default:
3062 return false;
3063 }
3064 }
3065
John Bauman89401822014-05-06 15:04:28 -04003066 bool Surface::isCompressed(Format format)
3067 {
3068 switch(format)
3069 {
John Bauman89401822014-05-06 15:04:28 -04003070 case FORMAT_DXT1:
3071 case FORMAT_DXT3:
3072 case FORMAT_DXT5:
3073 case FORMAT_ATI1:
3074 case FORMAT_ATI2:
Nicolas Capens22658242014-11-29 00:31:41 -05003075 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003076 case FORMAT_R11_EAC:
3077 case FORMAT_SIGNED_R11_EAC:
3078 case FORMAT_RG11_EAC:
3079 case FORMAT_SIGNED_RG11_EAC:
3080 case FORMAT_RGB8_ETC2:
3081 case FORMAT_SRGB8_ETC2:
3082 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3083 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3084 case FORMAT_RGBA8_ETC2_EAC:
3085 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3086 case FORMAT_RGBA_ASTC_4x4_KHR:
3087 case FORMAT_RGBA_ASTC_5x4_KHR:
3088 case FORMAT_RGBA_ASTC_5x5_KHR:
3089 case FORMAT_RGBA_ASTC_6x5_KHR:
3090 case FORMAT_RGBA_ASTC_6x6_KHR:
3091 case FORMAT_RGBA_ASTC_8x5_KHR:
3092 case FORMAT_RGBA_ASTC_8x6_KHR:
3093 case FORMAT_RGBA_ASTC_8x8_KHR:
3094 case FORMAT_RGBA_ASTC_10x5_KHR:
3095 case FORMAT_RGBA_ASTC_10x6_KHR:
3096 case FORMAT_RGBA_ASTC_10x8_KHR:
3097 case FORMAT_RGBA_ASTC_10x10_KHR:
3098 case FORMAT_RGBA_ASTC_12x10_KHR:
3099 case FORMAT_RGBA_ASTC_12x12_KHR:
3100 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3101 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3102 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3103 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3104 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3105 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3106 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3107 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3108 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3109 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3110 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3111 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3112 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3113 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
John Bauman89401822014-05-06 15:04:28 -04003114 return true;
John Bauman89401822014-05-06 15:04:28 -04003115 default:
3116 return false;
3117 }
3118 }
3119
Nicolas Capens492887a2017-03-27 14:50:51 -04003120 bool Surface::isSignedNonNormalizedInteger(Format format)
Alexis Hetu43577b82015-10-21 15:32:16 -04003121 {
3122 switch(format)
3123 {
3124 case FORMAT_A8B8G8R8I:
3125 case FORMAT_X8B8G8R8I:
3126 case FORMAT_G8R8I:
3127 case FORMAT_R8I:
Alexis Hetu43577b82015-10-21 15:32:16 -04003128 case FORMAT_A16B16G16R16I:
3129 case FORMAT_X16B16G16R16I:
3130 case FORMAT_G16R16I:
3131 case FORMAT_R16I:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003132 case FORMAT_A32B32G32R32I:
3133 case FORMAT_X32B32G32R32I:
3134 case FORMAT_G32R32I:
3135 case FORMAT_R32I:
Nicolas Capens492887a2017-03-27 14:50:51 -04003136 return true;
3137 default:
3138 return false;
3139 }
3140 }
3141
3142 bool Surface::isUnsignedNonNormalizedInteger(Format format)
3143 {
3144 switch(format)
3145 {
Alexis Hetu91dd1c42017-07-18 13:03:42 -04003146 case FORMAT_A8B8G8R8UI:
3147 case FORMAT_X8B8G8R8UI:
3148 case FORMAT_G8R8UI:
3149 case FORMAT_R8UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003150 case FORMAT_A16B16G16R16UI:
3151 case FORMAT_X16B16G16R16UI:
3152 case FORMAT_G16R16UI:
3153 case FORMAT_R16UI:
Alexis Hetu43577b82015-10-21 15:32:16 -04003154 case FORMAT_A32B32G32R32UI:
3155 case FORMAT_X32B32G32R32UI:
3156 case FORMAT_G32R32UI:
3157 case FORMAT_R32UI:
3158 return true;
3159 default:
3160 return false;
3161 }
3162 }
3163
Nicolas Capens492887a2017-03-27 14:50:51 -04003164 bool Surface::isNonNormalizedInteger(Format format)
3165 {
3166 return isSignedNonNormalizedInteger(format) ||
3167 isUnsignedNonNormalizedInteger(format);
3168 }
3169
3170 bool Surface::isNormalizedInteger(Format format)
3171 {
3172 return !isFloatFormat(format) &&
3173 !isNonNormalizedInteger(format) &&
3174 !isCompressed(format) &&
3175 !isDepth(format) &&
3176 !isStencil(format);
3177 }
3178
John Bauman89401822014-05-06 15:04:28 -04003179 int Surface::componentCount(Format format)
3180 {
3181 switch(format)
3182 {
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003183 case FORMAT_R5G6B5: return 3;
3184 case FORMAT_X8R8G8B8: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003185 case FORMAT_X8B8G8R8I: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003186 case FORMAT_X8B8G8R8: return 3;
3187 case FORMAT_A8R8G8B8: return 4;
Alexis Hetu049a1872016-04-25 16:59:58 -04003188 case FORMAT_SRGB8_X8: return 3;
3189 case FORMAT_SRGB8_A8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003190 case FORMAT_A8B8G8R8I: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003191 case FORMAT_A8B8G8R8: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003192 case FORMAT_G8R8I: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003193 case FORMAT_G8R8: return 2;
Nicolas Capens975adb72017-12-19 15:34:20 -05003194 case FORMAT_R8_SNORM: return 1;
3195 case FORMAT_G8R8_SNORM: return 2;
3196 case FORMAT_X8B8G8R8_SNORM:return 3;
3197 case FORMAT_A8B8G8R8_SNORM:return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003198 case FORMAT_R8UI: return 1;
3199 case FORMAT_G8R8UI: return 2;
3200 case FORMAT_X8B8G8R8UI: return 3;
3201 case FORMAT_A8B8G8R8UI: return 4;
Alexis Hetuf999a002015-12-17 11:09:36 -05003202 case FORMAT_A2B10G10R10: return 4;
Nicolas Capens5555af42017-12-14 13:14:03 -05003203 case FORMAT_A2B10G10R10UI: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003204 case FORMAT_G16R16I: return 2;
3205 case FORMAT_G16R16UI: return 2;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003206 case FORMAT_G16R16: return 2;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003207 case FORMAT_G32R32I: return 2;
3208 case FORMAT_G32R32UI: return 2;
3209 case FORMAT_X16B16G16R16I: return 3;
3210 case FORMAT_X16B16G16R16UI: return 3;
3211 case FORMAT_A16B16G16R16I: return 4;
3212 case FORMAT_A16B16G16R16UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003213 case FORMAT_A16B16G16R16: return 4;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003214 case FORMAT_X32B32G32R32I: return 3;
3215 case FORMAT_X32B32G32R32UI: return 3;
3216 case FORMAT_A32B32G32R32I: return 4;
3217 case FORMAT_A32B32G32R32UI: return 4;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003218 case FORMAT_V8U8: return 2;
3219 case FORMAT_Q8W8V8U8: return 4;
3220 case FORMAT_X8L8V8U8: return 3;
3221 case FORMAT_V16U16: return 2;
3222 case FORMAT_A16W16V16U16: return 4;
3223 case FORMAT_Q16W16V16U16: return 4;
3224 case FORMAT_R32F: return 1;
3225 case FORMAT_G32R32F: return 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003226 case FORMAT_X32B32G32R32F: return 3;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003227 case FORMAT_A32B32G32R32F: return 4;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003228 case FORMAT_X32B32G32R32F_UNSIGNED: return 3;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003229 case FORMAT_D32F: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003230 case FORMAT_D32FS8: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003231 case FORMAT_D32F_LOCKABLE: return 1;
3232 case FORMAT_D32FS8_TEXTURE: return 1;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003233 case FORMAT_D32F_SHADOW: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003234 case FORMAT_D32FS8_SHADOW: return 1;
3235 case FORMAT_A8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003236 case FORMAT_R8I: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003237 case FORMAT_R8: return 1;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003238 case FORMAT_R16I: return 1;
3239 case FORMAT_R16UI: return 1;
3240 case FORMAT_R32I: return 1;
3241 case FORMAT_R32UI: return 1;
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003242 case FORMAT_L8: return 1;
3243 case FORMAT_L16: return 1;
3244 case FORMAT_A8L8: return 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003245 case FORMAT_YV12_BT601: return 3;
3246 case FORMAT_YV12_BT709: return 3;
3247 case FORMAT_YV12_JFIF: return 3;
John Bauman89401822014-05-06 15:04:28 -04003248 default:
3249 ASSERT(false);
3250 }
3251
3252 return 1;
3253 }
3254
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003255 void *Surface::allocateBuffer(int width, int height, int depth, int border, int samples, Format format)
John Bauman89401822014-05-06 15:04:28 -04003256 {
Nicolas Capensdb17b5d2015-06-26 11:15:58 -04003257 // Render targets require 2x2 quads
3258 int width2 = (width + 1) & ~1;
3259 int height2 = (height + 1) & ~1;
John Bauman89401822014-05-06 15:04:28 -04003260
Nicolas Capens6ea71872015-06-26 13:00:48 -04003261 // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
Nicolas Capens48ef1252016-11-07 15:30:33 -05003262 // and stencil operations also read 8 bytes per four 8-bit stencil values,
Nicolas Capens6ea71872015-06-26 13:00:48 -04003263 // so we have to allocate 4 extra bytes to avoid buffer overruns.
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003264 return allocate(size(width2, height2, depth, border, samples, format) + 4);
John Bauman89401822014-05-06 15:04:28 -04003265 }
3266
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003267 void Surface::memfill4(void *buffer, int pattern, int bytes)
John Bauman89401822014-05-06 15:04:28 -04003268 {
3269 while((size_t)buffer & 0x1 && bytes >= 1)
3270 {
3271 *(char*)buffer = (char)pattern;
3272 (char*&)buffer += 1;
3273 bytes -= 1;
3274 }
3275
3276 while((size_t)buffer & 0x3 && bytes >= 2)
3277 {
3278 *(short*)buffer = (short)pattern;
3279 (short*&)buffer += 1;
3280 bytes -= 2;
3281 }
3282
Nicolas Capens47dc8672017-04-25 12:54:39 -04003283 #if defined(__i386__) || defined(__x86_64__)
3284 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04003285 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04003286 while((size_t)buffer & 0xF && bytes >= 4)
3287 {
3288 *(int*)buffer = pattern;
3289 (int*&)buffer += 1;
3290 bytes -= 4;
3291 }
3292
3293 __m128 quad = _mm_set_ps1((float&)pattern);
3294
3295 float *pointer = (float*)buffer;
3296 int qxwords = bytes / 64;
3297 bytes -= qxwords * 64;
3298
3299 while(qxwords--)
3300 {
3301 _mm_stream_ps(pointer + 0, quad);
3302 _mm_stream_ps(pointer + 4, quad);
3303 _mm_stream_ps(pointer + 8, quad);
3304 _mm_stream_ps(pointer + 12, quad);
3305
3306 pointer += 16;
3307 }
3308
3309 buffer = pointer;
John Bauman89401822014-05-06 15:04:28 -04003310 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04003311 #endif
John Bauman89401822014-05-06 15:04:28 -04003312
3313 while(bytes >= 4)
3314 {
3315 *(int*)buffer = (int)pattern;
3316 (int*&)buffer += 1;
3317 bytes -= 4;
3318 }
3319
3320 while(bytes >= 2)
3321 {
3322 *(short*)buffer = (short)pattern;
3323 (short*&)buffer += 1;
3324 bytes -= 2;
3325 }
3326
3327 while(bytes >= 1)
3328 {
3329 *(char*)buffer = (char)pattern;
3330 (char*&)buffer += 1;
3331 bytes -= 1;
3332 }
3333 }
3334
Nicolas Capensbf7a8142017-05-19 10:57:28 -04003335 void Surface::sync()
3336 {
3337 resource->lock(EXCLUSIVE);
3338 resource->unlock();
3339 }
3340
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003341 bool Surface::isEntire(const Rect& rect) const
John Bauman89401822014-05-06 15:04:28 -04003342 {
Alexis Hetu75b650f2015-11-19 17:40:15 -05003343 return (rect.x0 == 0 && rect.y0 == 0 && rect.x1 == internal.width && rect.y1 == internal.height && internal.depth == 1);
3344 }
John Bauman89401822014-05-06 15:04:28 -04003345
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003346 Rect Surface::getRect() const
Alexis Hetu75b650f2015-11-19 17:40:15 -05003347 {
Nicolas Capens426cb5e2017-07-20 14:14:09 -04003348 return Rect(0, 0, internal.width, internal.height);
John Bauman89401822014-05-06 15:04:28 -04003349 }
3350
Nicolas Capensc39901e2016-03-21 16:37:44 -04003351 void Surface::clearDepth(float depth, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003352 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003353 if(width == 0 || height == 0) return;
3354
John Bauman89401822014-05-06 15:04:28 -04003355 // Not overlapping
3356 if(x0 > internal.width) return;
3357 if(y0 > internal.height) return;
3358 if(x0 + width < 0) return;
3359 if(y0 + height < 0) return;
3360
3361 // Clip against dimensions
3362 if(x0 < 0) {width += x0; x0 = 0;}
3363 if(x0 + width > internal.width) width = internal.width - x0;
3364 if(y0 < 0) {height += y0; y0 = 0;}
3365 if(y0 + height > internal.height) height = internal.height - y0;
3366
3367 const bool entire = x0 == 0 && y0 == 0 && width == internal.width && height == internal.height;
3368 const Lock lock = entire ? LOCK_DISCARD : LOCK_WRITEONLY;
3369
John Bauman89401822014-05-06 15:04:28 -04003370 int x1 = x0 + width;
3371 int y1 = y0 + height;
3372
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003373 if(!hasQuadLayout(internal.format))
John Bauman89401822014-05-06 15:04:28 -04003374 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003375 float *target = (float*)lockInternal(x0, y0, 0, lock, PUBLIC);
John Bauman89401822014-05-06 15:04:28 -04003376
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003377 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003378 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003379 float *row = target;
John Bauman89401822014-05-06 15:04:28 -04003380 for(int y = y0; y < y1; y++)
3381 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003382 memfill4(row, (int&)depth, width * sizeof(float));
3383 row += internal.pitchP;
John Bauman89401822014-05-06 15:04:28 -04003384 }
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003385 target += internal.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003386 }
3387
3388 unlockInternal();
3389 }
3390 else // Quad layout
3391 {
3392 if(complementaryDepthBuffer)
3393 {
3394 depth = 1 - depth;
3395 }
3396
3397 float *buffer = (float*)lockInternal(0, 0, 0, lock, PUBLIC);
3398
Alexis Hetu358a1442015-12-03 14:23:10 -05003399 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3400 int oddX1 = (x1 & ~1) * 2;
3401 int evenX0 = ((x0 + 1) & ~1) * 2;
3402 int evenBytes = (oddX1 - evenX0) * sizeof(float);
3403
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003404 for(int z = 0; z < internal.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003405 {
3406 for(int y = y0; y < y1; y++)
3407 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003408 float *target = buffer + (y & ~1) * internal.pitchP + (y & 1) * 2;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003409
John Bauman89401822014-05-06 15:04:28 -04003410 if((y & 1) == 0 && y + 1 < y1) // Fill quad line at once
3411 {
3412 if((x0 & 1) != 0)
3413 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003414 target[oddX0 + 0] = depth;
3415 target[oddX0 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003416 }
3417
Alexis Hetu358a1442015-12-03 14:23:10 -05003418 // for(int x2 = evenX0; x2 < x1 * 2; x2 += 4)
John Bauman89401822014-05-06 15:04:28 -04003419 // {
3420 // target[x2 + 0] = depth;
3421 // target[x2 + 1] = depth;
3422 // target[x2 + 2] = depth;
3423 // target[x2 + 3] = depth;
3424 // }
3425
3426 // __asm
3427 // {
3428 // movss xmm0, depth
3429 // shufps xmm0, xmm0, 0x00
3430 //
3431 // mov eax, x0
3432 // add eax, 1
3433 // and eax, 0xFFFFFFFE
3434 // cmp eax, x1
3435 // jge qEnd
3436 //
3437 // mov edi, target
3438 //
3439 // qLoop:
3440 // movntps [edi+8*eax], xmm0
3441 //
3442 // add eax, 2
3443 // cmp eax, x1
3444 // jl qLoop
3445 // qEnd:
3446 // }
3447
Alexis Hetu358a1442015-12-03 14:23:10 -05003448 memfill4(&target[evenX0], (int&)depth, evenBytes);
John Bauman89401822014-05-06 15:04:28 -04003449
3450 if((x1 & 1) != 0)
3451 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003452 target[oddX1 + 0] = depth;
3453 target[oddX1 + 2] = depth;
John Bauman89401822014-05-06 15:04:28 -04003454 }
3455
3456 y++;
3457 }
3458 else
3459 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003460 for(int x = x0, i = oddX0; x < x1; x++, i = (x & ~1) * 2 + (x & 1))
John Bauman89401822014-05-06 15:04:28 -04003461 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003462 target[i] = depth;
John Bauman89401822014-05-06 15:04:28 -04003463 }
3464 }
3465 }
3466
3467 buffer += internal.sliceP;
3468 }
3469
3470 unlockInternal();
3471 }
3472 }
3473
Nicolas Capensc39901e2016-03-21 16:37:44 -04003474 void Surface::clearStencil(unsigned char s, unsigned char mask, int x0, int y0, int width, int height)
John Bauman89401822014-05-06 15:04:28 -04003475 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003476 if(mask == 0 || width == 0 || height == 0) return;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003477
John Bauman89401822014-05-06 15:04:28 -04003478 // Not overlapping
3479 if(x0 > internal.width) return;
3480 if(y0 > internal.height) return;
3481 if(x0 + width < 0) return;
3482 if(y0 + height < 0) return;
3483
3484 // Clip against dimensions
3485 if(x0 < 0) {width += x0; x0 = 0;}
3486 if(x0 + width > internal.width) width = internal.width - x0;
3487 if(y0 < 0) {height += y0; y0 = 0;}
3488 if(y0 + height > internal.height) height = internal.height - y0;
3489
John Bauman89401822014-05-06 15:04:28 -04003490 int x1 = x0 + width;
3491 int y1 = y0 + height;
3492
Alexis Hetu358a1442015-12-03 14:23:10 -05003493 int oddX0 = (x0 & ~1) * 2 + (x0 & 1);
3494 int oddX1 = (x1 & ~1) * 2;
3495 int evenX0 = ((x0 + 1) & ~1) * 2;
3496 int evenBytes = oddX1 - evenX0;
3497
John Bauman89401822014-05-06 15:04:28 -04003498 unsigned char maskedS = s & mask;
3499 unsigned char invMask = ~mask;
3500 unsigned int fill = maskedS;
Tom Anderson69bc6e82017-03-20 11:54:29 -07003501 fill = fill | (fill << 8) | (fill << 16) | (fill << 24);
John Bauman89401822014-05-06 15:04:28 -04003502
Alexis Hetua52dfbd2016-10-05 17:03:30 -04003503 char *buffer = (char*)lockStencil(0, 0, 0, PUBLIC);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003504
3505 // Stencil buffers are assumed to use quad layout
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003506 for(int z = 0; z < stencil.samples; z++)
John Bauman89401822014-05-06 15:04:28 -04003507 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003508 for(int y = y0; y < y1; y++)
John Bauman89401822014-05-06 15:04:28 -04003509 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003510 char *target = buffer + (y & ~1) * stencil.pitchP + (y & 1) * 2;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003511
3512 if((y & 1) == 0 && y + 1 < y1 && mask == 0xFF) // Fill quad line at once
John Bauman89401822014-05-06 15:04:28 -04003513 {
Alexis Hetu2b052f82015-11-25 13:57:28 -05003514 if((x0 & 1) != 0)
John Bauman89401822014-05-06 15:04:28 -04003515 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003516 target[oddX0 + 0] = fill;
3517 target[oddX0 + 2] = fill;
John Bauman89401822014-05-06 15:04:28 -04003518 }
3519
Alexis Hetu358a1442015-12-03 14:23:10 -05003520 memfill4(&target[evenX0], fill, evenBytes);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003521
3522 if((x1 & 1) != 0)
3523 {
Alexis Hetu358a1442015-12-03 14:23:10 -05003524 target[oddX1 + 0] = fill;
3525 target[oddX1 + 2] = fill;
Alexis Hetu2b052f82015-11-25 13:57:28 -05003526 }
3527
3528 y++;
3529 }
3530 else
3531 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003532 for(int x = x0; x < x1; x++)
Alexis Hetu2b052f82015-11-25 13:57:28 -05003533 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003534 int i = (x & ~1) * 2 + (x & 1);
Alexis Hetu358a1442015-12-03 14:23:10 -05003535 target[i] = maskedS | (target[i] & invMask);
Alexis Hetu2b052f82015-11-25 13:57:28 -05003536 }
John Bauman89401822014-05-06 15:04:28 -04003537 }
3538 }
3539
Alexis Hetu2b052f82015-11-25 13:57:28 -05003540 buffer += stencil.sliceP;
John Bauman89401822014-05-06 15:04:28 -04003541 }
John Bauman89401822014-05-06 15:04:28 -04003542
Alexis Hetu2b052f82015-11-25 13:57:28 -05003543 unlockStencil();
John Bauman89401822014-05-06 15:04:28 -04003544 }
3545
3546 void Surface::fill(const Color<float> &color, int x0, int y0, int width, int height)
3547 {
3548 unsigned char *row;
3549 Buffer *buffer;
Nicolas Capensc39901e2016-03-21 16:37:44 -04003550
John Bauman89401822014-05-06 15:04:28 -04003551 if(internal.dirty)
3552 {
3553 row = (unsigned char*)lockInternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3554 buffer = &internal;
3555 }
3556 else
3557 {
3558 row = (unsigned char*)lockExternal(x0, y0, 0, LOCK_WRITEONLY, PUBLIC);
3559 buffer = &external;
3560 }
3561
3562 if(buffer->bytes <= 4)
3563 {
3564 int c;
3565 buffer->write(&c, color);
3566
3567 if(buffer->bytes <= 1) c = (c << 8) | c;
3568 if(buffer->bytes <= 2) c = (c << 16) | c;
3569
3570 for(int y = 0; y < height; y++)
3571 {
Nicolas Capens5ba566b2015-05-25 17:11:04 -04003572 memfill4(row, c, width * buffer->bytes);
John Bauman89401822014-05-06 15:04:28 -04003573
3574 row += buffer->pitchB;
3575 }
3576 }
3577 else // Generic
3578 {
3579 for(int y = 0; y < height; y++)
3580 {
3581 unsigned char *element = row;
3582
3583 for(int x = 0; x < width; x++)
3584 {
3585 buffer->write(element, color);
3586
3587 element += buffer->bytes;
3588 }
3589
3590 row += buffer->pitchB;
3591 }
3592 }
3593
3594 if(buffer == &internal)
3595 {
3596 unlockInternal();
3597 }
3598 else
3599 {
3600 unlockExternal();
3601 }
3602 }
3603
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003604 void Surface::copyInternal(const Surface *source, int x, int y, float srcX, float srcY, bool filter)
John Bauman89401822014-05-06 15:04:28 -04003605 {
Alexis Hetu43577b82015-10-21 15:32:16 -04003606 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
John Bauman89401822014-05-06 15:04:28 -04003607
Alexis Hetu43577b82015-10-21 15:32:16 -04003608 sw::Color<float> color;
John Bauman89401822014-05-06 15:04:28 -04003609
Alexis Hetu43577b82015-10-21 15:32:16 -04003610 if(!filter)
3611 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003612 color = source->internal.read((int)srcX, (int)srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003613 }
3614 else // Bilinear filtering
3615 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003616 color = source->internal.sample(srcX, srcY, 0);
Alexis Hetu43577b82015-10-21 15:32:16 -04003617 }
John Bauman89401822014-05-06 15:04:28 -04003618
3619 internal.write(x, y, color);
3620 }
3621
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003622 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 -04003623 {
3624 ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
3625
3626 sw::Color<float> color;
3627
3628 if(!filter)
3629 {
3630 color = source->internal.read((int)srcX, (int)srcY, int(srcZ));
3631 }
3632 else // Bilinear filtering
3633 {
3634 color = source->internal.sample(srcX, srcY, srcZ);
3635 }
3636
3637 internal.write(x, y, z, color);
3638 }
3639
Alexis Hetua76a1bf2016-11-29 17:17:26 -05003640 void Surface::copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge)
3641 {
3642 Surface *dst = this;
3643
3644 // Figure out if the edges to be copied in reverse order respectively from one another
3645 // The copy should be reversed whenever the same edges are contiguous or if we're
3646 // copying top <-> right or bottom <-> left. This is explained by the layout, which is:
3647 //
3648 // | +y |
3649 // | -x | +z | +x | -z |
3650 // | -y |
3651
3652 bool reverse = (srcEdge == dstEdge) ||
3653 ((srcEdge == TOP) && (dstEdge == RIGHT)) ||
3654 ((srcEdge == RIGHT) && (dstEdge == TOP)) ||
3655 ((srcEdge == BOTTOM) && (dstEdge == LEFT)) ||
3656 ((srcEdge == LEFT) && (dstEdge == BOTTOM));
3657
3658 int srcBytes = src->bytes(src->Surface::getInternalFormat());
3659 int srcPitch = src->getInternalPitchB();
3660 int dstBytes = dst->bytes(dst->Surface::getInternalFormat());
3661 int dstPitch = dst->getInternalPitchB();
3662
3663 int srcW = src->getWidth();
3664 int srcH = src->getHeight();
3665 int dstW = dst->getWidth();
3666 int dstH = dst->getHeight();
3667
3668 ASSERT(srcW == srcH && dstW == dstH && srcW == dstW && srcBytes == dstBytes);
3669
3670 // Src is expressed in the regular [0, width-1], [0, height-1] space
3671 int srcDelta = ((srcEdge == TOP) || (srcEdge == BOTTOM)) ? srcBytes : srcPitch;
3672 int srcStart = ((srcEdge == BOTTOM) ? srcPitch * (srcH - 1) : ((srcEdge == RIGHT) ? srcBytes * (srcW - 1) : 0));
3673
3674 // Dst contains borders, so it is expressed in the [-1, width+1], [-1, height+1] space
3675 int dstDelta = (((dstEdge == TOP) || (dstEdge == BOTTOM)) ? dstBytes : dstPitch) * (reverse ? -1 : 1);
3676 int dstStart = ((dstEdge == BOTTOM) ? dstPitch * (dstH + 1) : ((dstEdge == RIGHT) ? dstBytes * (dstW + 1) : 0)) + (reverse ? dstW * -dstDelta : dstDelta);
3677
3678 char *srcBuf = (char*)src->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PRIVATE) + srcStart;
3679 char *dstBuf = (char*)dst->lockInternal(-1, -1, 0, sw::LOCK_READWRITE, sw::PRIVATE) + dstStart;
3680
3681 for(int i = 0; i < srcW; ++i, dstBuf += dstDelta, srcBuf += srcDelta)
3682 {
3683 memcpy(dstBuf, srcBuf, srcBytes);
3684 }
3685
3686 if(dstEdge == LEFT || dstEdge == RIGHT)
3687 {
3688 // TOP and BOTTOM are already set, let's average out the corners
3689 int x0 = (dstEdge == RIGHT) ? dstW : -1;
3690 int y0 = -1;
3691 int x1 = (dstEdge == RIGHT) ? dstW - 1 : 0;
3692 int y1 = 0;
3693 dst->computeCubeCorner(x0, y0, x1, y1);
3694 y0 = dstH;
3695 y1 = dstH - 1;
3696 dst->computeCubeCorner(x0, y0, x1, y1);
3697 }
3698
3699 src->unlockInternal();
3700 dst->unlockInternal();
3701 }
3702
3703 void Surface::computeCubeCorner(int x0, int y0, int x1, int y1)
3704 {
3705 ASSERT(internal.lock != LOCK_UNLOCKED);
3706
3707 sw::Color<float> color = internal.read(x0, y1);
3708 color += internal.read(x1, y0);
3709 color += internal.read(x1, y1);
3710 color *= (1.0f / 3.0f);
3711
3712 internal.write(x0, y0, color);
3713 }
3714
John Bauman89401822014-05-06 15:04:28 -04003715 bool Surface::hasStencil() const
3716 {
3717 return isStencil(external.format);
3718 }
Nicolas Capensc39901e2016-03-21 16:37:44 -04003719
John Bauman89401822014-05-06 15:04:28 -04003720 bool Surface::hasDepth() const
3721 {
3722 return isDepth(external.format);
3723 }
3724
3725 bool Surface::hasPalette() const
3726 {
3727 return isPalette(external.format);
3728 }
3729
3730 bool Surface::isRenderTarget() const
3731 {
3732 return renderTarget;
3733 }
3734
Nicolas Capens73e18c12017-11-28 13:31:35 -05003735 bool Surface::hasDirtyContents() const
John Bauman89401822014-05-06 15:04:28 -04003736 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003737 return dirtyContents;
John Bauman89401822014-05-06 15:04:28 -04003738 }
3739
Nicolas Capens73e18c12017-11-28 13:31:35 -05003740 void Surface::markContentsClean()
John Bauman89401822014-05-06 15:04:28 -04003741 {
Nicolas Capens73e18c12017-11-28 13:31:35 -05003742 dirtyContents = false;
John Bauman89401822014-05-06 15:04:28 -04003743 }
3744
3745 Resource *Surface::getResource()
3746 {
3747 return resource;
3748 }
3749
3750 bool Surface::identicalFormats() const
3751 {
John Bauman66b8ab22014-05-06 15:57:45 -04003752 return external.format == internal.format &&
3753 external.width == internal.width &&
Nicolas Capens22658242014-11-29 00:31:41 -05003754 external.height == internal.height &&
3755 external.depth == internal.depth &&
3756 external.pitchB == internal.pitchB &&
Alexis Hetu9c6d5222016-11-29 17:02:14 -05003757 external.sliceB == internal.sliceB &&
Nicolas Capensbfa23b32017-12-11 10:06:37 -05003758 external.border == internal.border &&
3759 external.samples == internal.samples;
John Bauman89401822014-05-06 15:04:28 -04003760 }
3761
3762 Format Surface::selectInternalFormat(Format format) const
3763 {
3764 switch(format)
3765 {
3766 case FORMAT_NULL:
3767 return FORMAT_NULL;
3768 case FORMAT_P8:
3769 case FORMAT_A8P8:
3770 case FORMAT_A4R4G4B4:
3771 case FORMAT_A1R5G5B5:
3772 case FORMAT_A8R3G3B2:
3773 return FORMAT_A8R8G8B8;
3774 case FORMAT_A8:
3775 return FORMAT_A8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003776 case FORMAT_R8I:
3777 return FORMAT_R8I;
3778 case FORMAT_R8UI:
3779 return FORMAT_R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003780 case FORMAT_R8_SNORM:
3781 return FORMAT_R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003782 case FORMAT_R8:
3783 return FORMAT_R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003784 case FORMAT_R16I:
3785 return FORMAT_R16I;
3786 case FORMAT_R16UI:
3787 return FORMAT_R16UI;
3788 case FORMAT_R32I:
3789 return FORMAT_R32I;
3790 case FORMAT_R32UI:
3791 return FORMAT_R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003792 case FORMAT_X16B16G16R16I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003793 return FORMAT_X16B16G16R16I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003794 case FORMAT_A16B16G16R16I:
3795 return FORMAT_A16B16G16R16I;
3796 case FORMAT_X16B16G16R16UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003797 return FORMAT_X16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003798 case FORMAT_A16B16G16R16UI:
3799 return FORMAT_A16B16G16R16UI;
Alexis Hetuf999a002015-12-17 11:09:36 -05003800 case FORMAT_A2R10G10B10:
3801 case FORMAT_A2B10G10R10:
John Bauman89401822014-05-06 15:04:28 -04003802 case FORMAT_A16B16G16R16:
3803 return FORMAT_A16B16G16R16;
Nicolas Capens5555af42017-12-14 13:14:03 -05003804 case FORMAT_A2B10G10R10UI:
3805 return FORMAT_A16B16G16R16UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003806 case FORMAT_X32B32G32R32I:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003807 return FORMAT_X32B32G32R32I;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003808 case FORMAT_A32B32G32R32I:
3809 return FORMAT_A32B32G32R32I;
3810 case FORMAT_X32B32G32R32UI:
Nicolas Capense4a88b92017-11-30 00:14:57 -05003811 return FORMAT_X32B32G32R32UI;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003812 case FORMAT_A32B32G32R32UI:
3813 return FORMAT_A32B32G32R32UI;
3814 case FORMAT_G8R8I:
3815 return FORMAT_G8R8I;
3816 case FORMAT_G8R8UI:
3817 return FORMAT_G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003818 case FORMAT_G8R8_SNORM:
3819 return FORMAT_G8R8_SNORM;
John Bauman89401822014-05-06 15:04:28 -04003820 case FORMAT_G8R8:
3821 return FORMAT_G8R8;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003822 case FORMAT_G16R16I:
3823 return FORMAT_G16R16I;
3824 case FORMAT_G16R16UI:
3825 return FORMAT_G16R16UI;
John Bauman89401822014-05-06 15:04:28 -04003826 case FORMAT_G16R16:
3827 return FORMAT_G16R16;
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003828 case FORMAT_G32R32I:
3829 return FORMAT_G32R32I;
3830 case FORMAT_G32R32UI:
3831 return FORMAT_G32R32UI;
John Bauman89401822014-05-06 15:04:28 -04003832 case FORMAT_A8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003833 if(lockable || !quadLayoutEnabled)
3834 {
3835 return FORMAT_A8R8G8B8;
3836 }
3837 else
3838 {
3839 return FORMAT_A8G8R8B8Q;
3840 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003841 case FORMAT_A8B8G8R8I:
3842 return FORMAT_A8B8G8R8I;
3843 case FORMAT_A8B8G8R8UI:
3844 return FORMAT_A8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003845 case FORMAT_A8B8G8R8_SNORM:
3846 return FORMAT_A8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003847 case FORMAT_R5G5B5A1:
3848 case FORMAT_R4G4B4A4:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003849 case FORMAT_A8B8G8R8:
3850 return FORMAT_A8B8G8R8;
John Bauman89401822014-05-06 15:04:28 -04003851 case FORMAT_R5G6B5:
Nicolas Capens5a86ee92015-09-04 10:45:43 -04003852 return FORMAT_R5G6B5;
3853 case FORMAT_R3G3B2:
John Bauman89401822014-05-06 15:04:28 -04003854 case FORMAT_R8G8B8:
3855 case FORMAT_X4R4G4B4:
3856 case FORMAT_X1R5G5B5:
3857 case FORMAT_X8R8G8B8:
John Bauman89401822014-05-06 15:04:28 -04003858 if(lockable || !quadLayoutEnabled)
3859 {
3860 return FORMAT_X8R8G8B8;
3861 }
3862 else
3863 {
3864 return FORMAT_X8G8R8B8Q;
3865 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003866 case FORMAT_X8B8G8R8I:
3867 return FORMAT_X8B8G8R8I;
3868 case FORMAT_X8B8G8R8UI:
3869 return FORMAT_X8B8G8R8UI;
Nicolas Capens975adb72017-12-19 15:34:20 -05003870 case FORMAT_X8B8G8R8_SNORM:
3871 return FORMAT_X8B8G8R8_SNORM;
Nicolas Capens80594422015-06-09 16:42:56 -04003872 case FORMAT_B8G8R8:
Nicolas Capensef77ac12015-03-28 21:48:51 -04003873 case FORMAT_X8B8G8R8:
3874 return FORMAT_X8B8G8R8;
Alexis Hetu049a1872016-04-25 16:59:58 -04003875 case FORMAT_SRGB8_X8:
3876 return FORMAT_SRGB8_X8;
3877 case FORMAT_SRGB8_A8:
3878 return FORMAT_SRGB8_A8;
John Bauman89401822014-05-06 15:04:28 -04003879 // Compressed formats
John Bauman89401822014-05-06 15:04:28 -04003880 case FORMAT_DXT1:
3881 case FORMAT_DXT3:
3882 case FORMAT_DXT5:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003883 case FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3884 case FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3885 case FORMAT_RGBA8_ETC2_EAC:
3886 case FORMAT_SRGB8_ALPHA8_ETC2_EAC:
3887 case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
3888 case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
3889 case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
3890 case FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR:
3891 case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
3892 case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
3893 case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
3894 case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
3895 case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
3896 case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
3897 case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
3898 case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
3899 case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
3900 case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
3901 return FORMAT_A8R8G8B8;
3902 case FORMAT_RGBA_ASTC_4x4_KHR:
3903 case FORMAT_RGBA_ASTC_5x4_KHR:
3904 case FORMAT_RGBA_ASTC_5x5_KHR:
3905 case FORMAT_RGBA_ASTC_6x5_KHR:
3906 case FORMAT_RGBA_ASTC_6x6_KHR:
3907 case FORMAT_RGBA_ASTC_8x5_KHR:
3908 case FORMAT_RGBA_ASTC_8x6_KHR:
3909 case FORMAT_RGBA_ASTC_8x8_KHR:
3910 case FORMAT_RGBA_ASTC_10x5_KHR:
3911 case FORMAT_RGBA_ASTC_10x6_KHR:
3912 case FORMAT_RGBA_ASTC_10x8_KHR:
3913 case FORMAT_RGBA_ASTC_10x10_KHR:
3914 case FORMAT_RGBA_ASTC_12x10_KHR:
3915 case FORMAT_RGBA_ASTC_12x12_KHR:
3916 // ASTC supports HDR, so a floating point format is required to represent it properly
3917 return FORMAT_A32B32G32R32F; // FIXME: 16FP is probably sufficient, but it's currently unsupported
John Bauman89401822014-05-06 15:04:28 -04003918 case FORMAT_ATI1:
3919 return FORMAT_R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003920 case FORMAT_R11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003921 case FORMAT_SIGNED_R11_EAC:
3922 return FORMAT_R32F; // FIXME: Signed 8bit format would be sufficient
John Bauman89401822014-05-06 15:04:28 -04003923 case FORMAT_ATI2:
3924 return FORMAT_G8R8;
Alexis Hetuf46493f2017-12-18 15:32:26 -05003925 case FORMAT_RG11_EAC:
Alexis Hetu0de50d42015-09-09 13:56:41 -04003926 case FORMAT_SIGNED_RG11_EAC:
3927 return FORMAT_G32R32F; // FIXME: Signed 8bit format would be sufficient
Nicolas Capens22658242014-11-29 00:31:41 -05003928 case FORMAT_ETC1:
Alexis Hetu460e41f2015-09-01 10:58:37 -04003929 case FORMAT_RGB8_ETC2:
3930 case FORMAT_SRGB8_ETC2:
Nicolas Capens22658242014-11-29 00:31:41 -05003931 return FORMAT_X8R8G8B8;
John Bauman89401822014-05-06 15:04:28 -04003932 // Bumpmap formats
3933 case FORMAT_V8U8: return FORMAT_V8U8;
3934 case FORMAT_L6V5U5: return FORMAT_X8L8V8U8;
3935 case FORMAT_Q8W8V8U8: return FORMAT_Q8W8V8U8;
3936 case FORMAT_X8L8V8U8: return FORMAT_X8L8V8U8;
3937 case FORMAT_V16U16: return FORMAT_V16U16;
3938 case FORMAT_A2W10V10U10: return FORMAT_A16W16V16U16;
3939 case FORMAT_Q16W16V16U16: return FORMAT_Q16W16V16U16;
3940 // Floating-point formats
Nicolas Capens80594422015-06-09 16:42:56 -04003941 case FORMAT_A16F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003942 case FORMAT_R16F: return FORMAT_R32F;
3943 case FORMAT_G16R16F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003944 case FORMAT_B16G16R16F: return FORMAT_X32B32G32R32F;
Nicolas Capensa6bc61d2017-12-20 11:07:45 -05003945 case FORMAT_X16B16G16R16F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003946 case FORMAT_A16B16G16R16F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003947 case FORMAT_X16B16G16R16F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
Nicolas Capens80594422015-06-09 16:42:56 -04003948 case FORMAT_A32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003949 case FORMAT_R32F: return FORMAT_R32F;
3950 case FORMAT_G32R32F: return FORMAT_G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003951 case FORMAT_B32G32R32F: return FORMAT_X32B32G32R32F;
3952 case FORMAT_X32B32G32R32F: return FORMAT_X32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003953 case FORMAT_A32B32G32R32F: return FORMAT_A32B32G32R32F;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003954 case FORMAT_X32B32G32R32F_UNSIGNED: return FORMAT_X32B32G32R32F_UNSIGNED;
John Bauman89401822014-05-06 15:04:28 -04003955 // Luminance formats
3956 case FORMAT_L8: return FORMAT_L8;
3957 case FORMAT_A4L4: return FORMAT_A8L8;
3958 case FORMAT_L16: return FORMAT_L16;
3959 case FORMAT_A8L8: return FORMAT_A8L8;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003960 case FORMAT_L16F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003961 case FORMAT_A16L16F: return FORMAT_A32B32G32R32F;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003962 case FORMAT_L32F: return FORMAT_X32B32G32R32F;
Nicolas Capens80594422015-06-09 16:42:56 -04003963 case FORMAT_A32L32F: return FORMAT_A32B32G32R32F;
John Bauman89401822014-05-06 15:04:28 -04003964 // Depth/stencil formats
3965 case FORMAT_D16:
3966 case FORMAT_D32:
3967 case FORMAT_D24X8:
John Bauman89401822014-05-06 15:04:28 -04003968 if(hasParent) // Texture
3969 {
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003970 return FORMAT_D32F_SHADOW;
John Bauman89401822014-05-06 15:04:28 -04003971 }
3972 else if(complementaryDepthBuffer)
3973 {
3974 return FORMAT_D32F_COMPLEMENTARY;
3975 }
3976 else
3977 {
3978 return FORMAT_D32F;
3979 }
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003980 case FORMAT_D24S8:
3981 case FORMAT_D24FS8:
3982 if(hasParent) // Texture
3983 {
3984 return FORMAT_D32FS8_SHADOW;
3985 }
3986 else if(complementaryDepthBuffer)
3987 {
3988 return FORMAT_D32FS8_COMPLEMENTARY;
3989 }
3990 else
3991 {
3992 return FORMAT_D32FS8;
3993 }
Alexis Hetud3a2d3d2015-10-22 10:57:58 -04003994 case FORMAT_D32F: return FORMAT_D32F;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003995 case FORMAT_D32FS8: return FORMAT_D32FS8;
John Bauman66b8ab22014-05-06 15:57:45 -04003996 case FORMAT_D32F_LOCKABLE: return FORMAT_D32F_LOCKABLE;
3997 case FORMAT_D32FS8_TEXTURE: return FORMAT_D32FS8_TEXTURE;
3998 case FORMAT_INTZ: return FORMAT_D32FS8_TEXTURE;
3999 case FORMAT_DF24S8: return FORMAT_D32FS8_SHADOW;
4000 case FORMAT_DF16S8: return FORMAT_D32FS8_SHADOW;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05004001 case FORMAT_S8: return FORMAT_S8;
4002 // YUV formats
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04004003 case FORMAT_YV12_BT601: return FORMAT_YV12_BT601;
4004 case FORMAT_YV12_BT709: return FORMAT_YV12_BT709;
4005 case FORMAT_YV12_JFIF: return FORMAT_YV12_JFIF;
John Bauman89401822014-05-06 15:04:28 -04004006 default:
4007 ASSERT(false);
4008 }
4009
4010 return FORMAT_NULL;
4011 }
4012
4013 void Surface::setTexturePalette(unsigned int *palette)
4014 {
4015 Surface::palette = palette;
4016 Surface::paletteID++;
4017 }
4018
4019 void Surface::resolve()
4020 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004021 if(internal.samples <= 1 || !internal.dirty || !renderTarget || internal.format == FORMAT_NULL)
John Bauman89401822014-05-06 15:04:28 -04004022 {
4023 return;
4024 }
4025
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004026 ASSERT(internal.depth == 1); // Unimplemented
4027
John Bauman89401822014-05-06 15:04:28 -04004028 void *source = internal.lockRect(0, 0, 0, LOCK_READWRITE);
4029
John Bauman89401822014-05-06 15:04:28 -04004030 int width = internal.width;
4031 int height = internal.height;
4032 int pitch = internal.pitchB;
4033 int slice = internal.sliceB;
4034
4035 unsigned char *source0 = (unsigned char*)source;
4036 unsigned char *source1 = source0 + slice;
4037 unsigned char *source2 = source1 + slice;
4038 unsigned char *source3 = source2 + slice;
4039 unsigned char *source4 = source3 + slice;
4040 unsigned char *source5 = source4 + slice;
4041 unsigned char *source6 = source5 + slice;
4042 unsigned char *source7 = source6 + slice;
4043 unsigned char *source8 = source7 + slice;
4044 unsigned char *source9 = source8 + slice;
4045 unsigned char *sourceA = source9 + slice;
4046 unsigned char *sourceB = sourceA + slice;
4047 unsigned char *sourceC = sourceB + slice;
4048 unsigned char *sourceD = sourceC + slice;
4049 unsigned char *sourceE = sourceD + slice;
4050 unsigned char *sourceF = sourceE + slice;
4051
Alexis Hetu049a1872016-04-25 16:59:58 -04004052 if(internal.format == FORMAT_X8R8G8B8 || internal.format == FORMAT_A8R8G8B8 ||
4053 internal.format == FORMAT_X8B8G8R8 || internal.format == FORMAT_A8B8G8R8 ||
4054 internal.format == FORMAT_SRGB8_X8 || internal.format == FORMAT_SRGB8_A8)
John Bauman89401822014-05-06 15:04:28 -04004055 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004056 #if defined(__i386__) || defined(__x86_64__)
4057 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004058 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004059 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004060 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004061 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004062 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004063 for(int x = 0; x < width; x += 4)
4064 {
4065 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4066 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004067
Nicolas Capens47dc8672017-04-25 12:54:39 -04004068 c0 = _mm_avg_epu8(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004069
Nicolas Capens47dc8672017-04-25 12:54:39 -04004070 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4071 }
4072
4073 source0 += pitch;
4074 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004075 }
John Bauman89401822014-05-06 15:04:28 -04004076 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004077 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004078 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004079 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004080 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004081 for(int x = 0; x < width; x += 4)
4082 {
4083 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4084 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4085 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4086 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004087
Nicolas Capens47dc8672017-04-25 12:54:39 -04004088 c0 = _mm_avg_epu8(c0, c1);
4089 c2 = _mm_avg_epu8(c2, c3);
4090 c0 = _mm_avg_epu8(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004091
Nicolas Capens47dc8672017-04-25 12:54:39 -04004092 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4093 }
4094
4095 source0 += pitch;
4096 source1 += pitch;
4097 source2 += pitch;
4098 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004099 }
John Bauman89401822014-05-06 15:04:28 -04004100 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004101 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004102 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004103 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004104 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004105 for(int x = 0; x < width; x += 4)
4106 {
4107 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4108 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4109 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4110 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4111 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4112 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4113 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4114 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004115
Nicolas Capens47dc8672017-04-25 12:54:39 -04004116 c0 = _mm_avg_epu8(c0, c1);
4117 c2 = _mm_avg_epu8(c2, c3);
4118 c4 = _mm_avg_epu8(c4, c5);
4119 c6 = _mm_avg_epu8(c6, c7);
4120 c0 = _mm_avg_epu8(c0, c2);
4121 c4 = _mm_avg_epu8(c4, c6);
4122 c0 = _mm_avg_epu8(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004123
Nicolas Capens47dc8672017-04-25 12:54:39 -04004124 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4125 }
4126
4127 source0 += pitch;
4128 source1 += pitch;
4129 source2 += pitch;
4130 source3 += pitch;
4131 source4 += pitch;
4132 source5 += pitch;
4133 source6 += pitch;
4134 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004135 }
John Bauman89401822014-05-06 15:04:28 -04004136 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004137 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004138 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004139 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004140 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004141 for(int x = 0; x < width; x += 4)
4142 {
4143 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4144 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4145 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4146 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4147 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4148 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4149 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4150 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4151 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4152 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4153 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4154 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4155 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4156 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4157 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4158 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004159
Nicolas Capens47dc8672017-04-25 12:54:39 -04004160 c0 = _mm_avg_epu8(c0, c1);
4161 c2 = _mm_avg_epu8(c2, c3);
4162 c4 = _mm_avg_epu8(c4, c5);
4163 c6 = _mm_avg_epu8(c6, c7);
4164 c8 = _mm_avg_epu8(c8, c9);
4165 cA = _mm_avg_epu8(cA, cB);
4166 cC = _mm_avg_epu8(cC, cD);
4167 cE = _mm_avg_epu8(cE, cF);
4168 c0 = _mm_avg_epu8(c0, c2);
4169 c4 = _mm_avg_epu8(c4, c6);
4170 c8 = _mm_avg_epu8(c8, cA);
4171 cC = _mm_avg_epu8(cC, cE);
4172 c0 = _mm_avg_epu8(c0, c4);
4173 c8 = _mm_avg_epu8(c8, cC);
4174 c0 = _mm_avg_epu8(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004175
Nicolas Capens47dc8672017-04-25 12:54:39 -04004176 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4177 }
4178
4179 source0 += pitch;
4180 source1 += pitch;
4181 source2 += pitch;
4182 source3 += pitch;
4183 source4 += pitch;
4184 source5 += pitch;
4185 source6 += pitch;
4186 source7 += pitch;
4187 source8 += pitch;
4188 source9 += pitch;
4189 sourceA += pitch;
4190 sourceB += pitch;
4191 sourceC += pitch;
4192 sourceD += pitch;
4193 sourceE += pitch;
4194 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004195 }
John Bauman89401822014-05-06 15:04:28 -04004196 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004197 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004198 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004199 else
4200 #endif
John Bauman89401822014-05-06 15:04:28 -04004201 {
4202 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7F7F7F7F) + (((x) ^ (y)) & 0x01010101))
4203
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004204 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004205 {
4206 for(int y = 0; y < height; y++)
4207 {
4208 for(int x = 0; x < width; x++)
4209 {
4210 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4211 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4212
4213 c0 = AVERAGE(c0, c1);
4214
4215 *(unsigned int*)(source0 + 4 * x) = c0;
4216 }
4217
4218 source0 += pitch;
4219 source1 += pitch;
4220 }
4221 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004222 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004223 {
4224 for(int y = 0; y < height; y++)
4225 {
4226 for(int x = 0; x < width; x++)
4227 {
4228 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4229 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4230 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4231 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4232
4233 c0 = AVERAGE(c0, c1);
4234 c2 = AVERAGE(c2, c3);
4235 c0 = AVERAGE(c0, c2);
4236
4237 *(unsigned int*)(source0 + 4 * x) = c0;
4238 }
4239
4240 source0 += pitch;
4241 source1 += pitch;
4242 source2 += pitch;
4243 source3 += pitch;
4244 }
4245 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004246 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004247 {
4248 for(int y = 0; y < height; y++)
4249 {
4250 for(int x = 0; x < width; x++)
4251 {
4252 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4253 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4254 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4255 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4256 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4257 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4258 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4259 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4260
4261 c0 = AVERAGE(c0, c1);
4262 c2 = AVERAGE(c2, c3);
4263 c4 = AVERAGE(c4, c5);
4264 c6 = AVERAGE(c6, c7);
4265 c0 = AVERAGE(c0, c2);
4266 c4 = AVERAGE(c4, c6);
4267 c0 = AVERAGE(c0, c4);
4268
4269 *(unsigned int*)(source0 + 4 * x) = c0;
4270 }
4271
4272 source0 += pitch;
4273 source1 += pitch;
4274 source2 += pitch;
4275 source3 += pitch;
4276 source4 += pitch;
4277 source5 += pitch;
4278 source6 += pitch;
4279 source7 += pitch;
4280 }
4281 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004282 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004283 {
4284 for(int y = 0; y < height; y++)
4285 {
4286 for(int x = 0; x < width; x++)
4287 {
4288 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4289 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4290 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4291 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4292 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4293 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4294 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4295 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4296 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4297 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4298 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4299 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4300 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4301 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4302 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4303 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4304
4305 c0 = AVERAGE(c0, c1);
4306 c2 = AVERAGE(c2, c3);
4307 c4 = AVERAGE(c4, c5);
4308 c6 = AVERAGE(c6, c7);
4309 c8 = AVERAGE(c8, c9);
4310 cA = AVERAGE(cA, cB);
4311 cC = AVERAGE(cC, cD);
4312 cE = AVERAGE(cE, cF);
4313 c0 = AVERAGE(c0, c2);
4314 c4 = AVERAGE(c4, c6);
4315 c8 = AVERAGE(c8, cA);
4316 cC = AVERAGE(cC, cE);
4317 c0 = AVERAGE(c0, c4);
4318 c8 = AVERAGE(c8, cC);
4319 c0 = AVERAGE(c0, c8);
4320
4321 *(unsigned int*)(source0 + 4 * x) = c0;
4322 }
4323
4324 source0 += pitch;
4325 source1 += pitch;
4326 source2 += pitch;
4327 source3 += pitch;
4328 source4 += pitch;
4329 source5 += pitch;
4330 source6 += pitch;
4331 source7 += pitch;
4332 source8 += pitch;
4333 source9 += pitch;
4334 sourceA += pitch;
4335 sourceB += pitch;
4336 sourceC += pitch;
4337 sourceD += pitch;
4338 sourceE += pitch;
4339 sourceF += pitch;
4340 }
4341 }
4342 else ASSERT(false);
4343
4344 #undef AVERAGE
4345 }
4346 }
4347 else if(internal.format == FORMAT_G16R16)
4348 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004349
4350 #if defined(__i386__) || defined(__x86_64__)
4351 if(CPUID::supportsSSE2() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004352 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004353 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004354 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004355 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004356 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004357 for(int x = 0; x < width; x += 4)
4358 {
4359 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4360 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004361
Nicolas Capens47dc8672017-04-25 12:54:39 -04004362 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004363
Nicolas Capens47dc8672017-04-25 12:54:39 -04004364 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4365 }
4366
4367 source0 += pitch;
4368 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004369 }
John Bauman89401822014-05-06 15:04:28 -04004370 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004371 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004372 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004373 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004374 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004375 for(int x = 0; x < width; x += 4)
4376 {
4377 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4378 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4379 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4380 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004381
Nicolas Capens47dc8672017-04-25 12:54:39 -04004382 c0 = _mm_avg_epu16(c0, c1);
4383 c2 = _mm_avg_epu16(c2, c3);
4384 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004385
Nicolas Capens47dc8672017-04-25 12:54:39 -04004386 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4387 }
4388
4389 source0 += pitch;
4390 source1 += pitch;
4391 source2 += pitch;
4392 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004393 }
John Bauman89401822014-05-06 15:04:28 -04004394 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004395 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004396 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004397 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004398 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004399 for(int x = 0; x < width; x += 4)
4400 {
4401 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4402 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4403 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4404 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4405 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4406 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4407 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4408 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004409
Nicolas Capens47dc8672017-04-25 12:54:39 -04004410 c0 = _mm_avg_epu16(c0, c1);
4411 c2 = _mm_avg_epu16(c2, c3);
4412 c4 = _mm_avg_epu16(c4, c5);
4413 c6 = _mm_avg_epu16(c6, c7);
4414 c0 = _mm_avg_epu16(c0, c2);
4415 c4 = _mm_avg_epu16(c4, c6);
4416 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004417
Nicolas Capens47dc8672017-04-25 12:54:39 -04004418 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4419 }
4420
4421 source0 += pitch;
4422 source1 += pitch;
4423 source2 += pitch;
4424 source3 += pitch;
4425 source4 += pitch;
4426 source5 += pitch;
4427 source6 += pitch;
4428 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004429 }
John Bauman89401822014-05-06 15:04:28 -04004430 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004431 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004432 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004433 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004434 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004435 for(int x = 0; x < width; x += 4)
4436 {
4437 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 4 * x));
4438 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 4 * x));
4439 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 4 * x));
4440 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 4 * x));
4441 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 4 * x));
4442 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 4 * x));
4443 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 4 * x));
4444 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 4 * x));
4445 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 4 * x));
4446 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 4 * x));
4447 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 4 * x));
4448 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 4 * x));
4449 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 4 * x));
4450 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 4 * x));
4451 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 4 * x));
4452 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04004453
Nicolas Capens47dc8672017-04-25 12:54:39 -04004454 c0 = _mm_avg_epu16(c0, c1);
4455 c2 = _mm_avg_epu16(c2, c3);
4456 c4 = _mm_avg_epu16(c4, c5);
4457 c6 = _mm_avg_epu16(c6, c7);
4458 c8 = _mm_avg_epu16(c8, c9);
4459 cA = _mm_avg_epu16(cA, cB);
4460 cC = _mm_avg_epu16(cC, cD);
4461 cE = _mm_avg_epu16(cE, cF);
4462 c0 = _mm_avg_epu16(c0, c2);
4463 c4 = _mm_avg_epu16(c4, c6);
4464 c8 = _mm_avg_epu16(c8, cA);
4465 cC = _mm_avg_epu16(cC, cE);
4466 c0 = _mm_avg_epu16(c0, c4);
4467 c8 = _mm_avg_epu16(c8, cC);
4468 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004469
Nicolas Capens47dc8672017-04-25 12:54:39 -04004470 _mm_store_si128((__m128i*)(source0 + 4 * x), c0);
4471 }
4472
4473 source0 += pitch;
4474 source1 += pitch;
4475 source2 += pitch;
4476 source3 += pitch;
4477 source4 += pitch;
4478 source5 += pitch;
4479 source6 += pitch;
4480 source7 += pitch;
4481 source8 += pitch;
4482 source9 += pitch;
4483 sourceA += pitch;
4484 sourceB += pitch;
4485 sourceC += pitch;
4486 sourceD += pitch;
4487 sourceE += pitch;
4488 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004489 }
John Bauman89401822014-05-06 15:04:28 -04004490 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004491 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004492 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004493 else
4494 #endif
John Bauman89401822014-05-06 15:04:28 -04004495 {
4496 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4497
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004498 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004499 {
4500 for(int y = 0; y < height; y++)
4501 {
4502 for(int x = 0; x < width; x++)
4503 {
4504 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4505 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4506
4507 c0 = AVERAGE(c0, c1);
4508
4509 *(unsigned int*)(source0 + 4 * x) = c0;
4510 }
4511
4512 source0 += pitch;
4513 source1 += pitch;
4514 }
4515 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004516 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004517 {
4518 for(int y = 0; y < height; y++)
4519 {
4520 for(int x = 0; x < width; x++)
4521 {
4522 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4523 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4524 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4525 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4526
4527 c0 = AVERAGE(c0, c1);
4528 c2 = AVERAGE(c2, c3);
4529 c0 = AVERAGE(c0, c2);
4530
4531 *(unsigned int*)(source0 + 4 * x) = c0;
4532 }
4533
4534 source0 += pitch;
4535 source1 += pitch;
4536 source2 += pitch;
4537 source3 += pitch;
4538 }
4539 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004540 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004541 {
4542 for(int y = 0; y < height; y++)
4543 {
4544 for(int x = 0; x < width; x++)
4545 {
4546 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4547 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4548 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4549 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4550 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4551 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4552 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4553 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4554
4555 c0 = AVERAGE(c0, c1);
4556 c2 = AVERAGE(c2, c3);
4557 c4 = AVERAGE(c4, c5);
4558 c6 = AVERAGE(c6, c7);
4559 c0 = AVERAGE(c0, c2);
4560 c4 = AVERAGE(c4, c6);
4561 c0 = AVERAGE(c0, c4);
4562
4563 *(unsigned int*)(source0 + 4 * x) = c0;
4564 }
4565
4566 source0 += pitch;
4567 source1 += pitch;
4568 source2 += pitch;
4569 source3 += pitch;
4570 source4 += pitch;
4571 source5 += pitch;
4572 source6 += pitch;
4573 source7 += pitch;
4574 }
4575 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004576 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004577 {
4578 for(int y = 0; y < height; y++)
4579 {
4580 for(int x = 0; x < width; x++)
4581 {
4582 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4583 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4584 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4585 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4586 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4587 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4588 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4589 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4590 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4591 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4592 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4593 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4594 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4595 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4596 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4597 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4598
4599 c0 = AVERAGE(c0, c1);
4600 c2 = AVERAGE(c2, c3);
4601 c4 = AVERAGE(c4, c5);
4602 c6 = AVERAGE(c6, c7);
4603 c8 = AVERAGE(c8, c9);
4604 cA = AVERAGE(cA, cB);
4605 cC = AVERAGE(cC, cD);
4606 cE = AVERAGE(cE, cF);
4607 c0 = AVERAGE(c0, c2);
4608 c4 = AVERAGE(c4, c6);
4609 c8 = AVERAGE(c8, cA);
4610 cC = AVERAGE(cC, cE);
4611 c0 = AVERAGE(c0, c4);
4612 c8 = AVERAGE(c8, cC);
4613 c0 = AVERAGE(c0, c8);
4614
4615 *(unsigned int*)(source0 + 4 * x) = c0;
4616 }
4617
4618 source0 += pitch;
4619 source1 += pitch;
4620 source2 += pitch;
4621 source3 += pitch;
4622 source4 += pitch;
4623 source5 += pitch;
4624 source6 += pitch;
4625 source7 += pitch;
4626 source8 += pitch;
4627 source9 += pitch;
4628 sourceA += pitch;
4629 sourceB += pitch;
4630 sourceC += pitch;
4631 sourceD += pitch;
4632 sourceE += pitch;
4633 sourceF += pitch;
4634 }
4635 }
4636 else ASSERT(false);
4637
4638 #undef AVERAGE
4639 }
4640 }
4641 else if(internal.format == FORMAT_A16B16G16R16)
4642 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004643 #if defined(__i386__) || defined(__x86_64__)
4644 if(CPUID::supportsSSE2() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04004645 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004646 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004647 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004648 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004649 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004650 for(int x = 0; x < width; x += 2)
4651 {
4652 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4653 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004654
Nicolas Capens47dc8672017-04-25 12:54:39 -04004655 c0 = _mm_avg_epu16(c0, c1);
John Bauman89401822014-05-06 15:04:28 -04004656
Nicolas Capens47dc8672017-04-25 12:54:39 -04004657 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4658 }
4659
4660 source0 += pitch;
4661 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004662 }
John Bauman89401822014-05-06 15:04:28 -04004663 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004664 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004665 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004666 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004667 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004668 for(int x = 0; x < width; x += 2)
4669 {
4670 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4671 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4672 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4673 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004674
Nicolas Capens47dc8672017-04-25 12:54:39 -04004675 c0 = _mm_avg_epu16(c0, c1);
4676 c2 = _mm_avg_epu16(c2, c3);
4677 c0 = _mm_avg_epu16(c0, c2);
John Bauman89401822014-05-06 15:04:28 -04004678
Nicolas Capens47dc8672017-04-25 12:54:39 -04004679 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4680 }
4681
4682 source0 += pitch;
4683 source1 += pitch;
4684 source2 += pitch;
4685 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004686 }
John Bauman89401822014-05-06 15:04:28 -04004687 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004688 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004689 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004690 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004691 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004692 for(int x = 0; x < width; x += 2)
4693 {
4694 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4695 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4696 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4697 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4698 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4699 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4700 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4701 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004702
Nicolas Capens47dc8672017-04-25 12:54:39 -04004703 c0 = _mm_avg_epu16(c0, c1);
4704 c2 = _mm_avg_epu16(c2, c3);
4705 c4 = _mm_avg_epu16(c4, c5);
4706 c6 = _mm_avg_epu16(c6, c7);
4707 c0 = _mm_avg_epu16(c0, c2);
4708 c4 = _mm_avg_epu16(c4, c6);
4709 c0 = _mm_avg_epu16(c0, c4);
John Bauman89401822014-05-06 15:04:28 -04004710
Nicolas Capens47dc8672017-04-25 12:54:39 -04004711 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4712 }
4713
4714 source0 += pitch;
4715 source1 += pitch;
4716 source2 += pitch;
4717 source3 += pitch;
4718 source4 += pitch;
4719 source5 += pitch;
4720 source6 += pitch;
4721 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004722 }
John Bauman89401822014-05-06 15:04:28 -04004723 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004724 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004725 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004726 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004727 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004728 for(int x = 0; x < width; x += 2)
4729 {
4730 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 8 * x));
4731 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 8 * x));
4732 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 8 * x));
4733 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 8 * x));
4734 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 8 * x));
4735 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 8 * x));
4736 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 8 * x));
4737 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 8 * x));
4738 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 8 * x));
4739 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 8 * x));
4740 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 8 * x));
4741 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 8 * x));
4742 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 8 * x));
4743 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 8 * x));
4744 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 8 * x));
4745 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04004746
Nicolas Capens47dc8672017-04-25 12:54:39 -04004747 c0 = _mm_avg_epu16(c0, c1);
4748 c2 = _mm_avg_epu16(c2, c3);
4749 c4 = _mm_avg_epu16(c4, c5);
4750 c6 = _mm_avg_epu16(c6, c7);
4751 c8 = _mm_avg_epu16(c8, c9);
4752 cA = _mm_avg_epu16(cA, cB);
4753 cC = _mm_avg_epu16(cC, cD);
4754 cE = _mm_avg_epu16(cE, cF);
4755 c0 = _mm_avg_epu16(c0, c2);
4756 c4 = _mm_avg_epu16(c4, c6);
4757 c8 = _mm_avg_epu16(c8, cA);
4758 cC = _mm_avg_epu16(cC, cE);
4759 c0 = _mm_avg_epu16(c0, c4);
4760 c8 = _mm_avg_epu16(c8, cC);
4761 c0 = _mm_avg_epu16(c0, c8);
John Bauman89401822014-05-06 15:04:28 -04004762
Nicolas Capens47dc8672017-04-25 12:54:39 -04004763 _mm_store_si128((__m128i*)(source0 + 8 * x), c0);
4764 }
4765
4766 source0 += pitch;
4767 source1 += pitch;
4768 source2 += pitch;
4769 source3 += pitch;
4770 source4 += pitch;
4771 source5 += pitch;
4772 source6 += pitch;
4773 source7 += pitch;
4774 source8 += pitch;
4775 source9 += pitch;
4776 sourceA += pitch;
4777 sourceB += pitch;
4778 sourceC += pitch;
4779 sourceD += pitch;
4780 sourceE += pitch;
4781 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04004782 }
John Bauman89401822014-05-06 15:04:28 -04004783 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004784 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04004785 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04004786 else
4787 #endif
John Bauman89401822014-05-06 15:04:28 -04004788 {
4789 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7FFF7FFF) + (((x) ^ (y)) & 0x00010001))
4790
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004791 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004792 {
4793 for(int y = 0; y < height; y++)
4794 {
4795 for(int x = 0; x < 2 * width; x++)
4796 {
4797 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4798 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4799
4800 c0 = AVERAGE(c0, c1);
4801
4802 *(unsigned int*)(source0 + 4 * x) = c0;
4803 }
4804
4805 source0 += pitch;
4806 source1 += pitch;
4807 }
4808 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004809 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004810 {
4811 for(int y = 0; y < height; y++)
4812 {
4813 for(int x = 0; x < 2 * width; x++)
4814 {
4815 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4816 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4817 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4818 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4819
4820 c0 = AVERAGE(c0, c1);
4821 c2 = AVERAGE(c2, c3);
4822 c0 = AVERAGE(c0, c2);
4823
4824 *(unsigned int*)(source0 + 4 * x) = c0;
4825 }
4826
4827 source0 += pitch;
4828 source1 += pitch;
4829 source2 += pitch;
4830 source3 += pitch;
4831 }
4832 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004833 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004834 {
4835 for(int y = 0; y < height; y++)
4836 {
4837 for(int x = 0; x < 2 * width; x++)
4838 {
4839 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4840 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4841 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4842 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4843 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4844 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4845 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4846 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4847
4848 c0 = AVERAGE(c0, c1);
4849 c2 = AVERAGE(c2, c3);
4850 c4 = AVERAGE(c4, c5);
4851 c6 = AVERAGE(c6, c7);
4852 c0 = AVERAGE(c0, c2);
4853 c4 = AVERAGE(c4, c6);
4854 c0 = AVERAGE(c0, c4);
4855
4856 *(unsigned int*)(source0 + 4 * x) = c0;
4857 }
4858
4859 source0 += pitch;
4860 source1 += pitch;
4861 source2 += pitch;
4862 source3 += pitch;
4863 source4 += pitch;
4864 source5 += pitch;
4865 source6 += pitch;
4866 source7 += pitch;
4867 }
4868 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004869 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04004870 {
4871 for(int y = 0; y < height; y++)
4872 {
4873 for(int x = 0; x < 2 * width; x++)
4874 {
4875 unsigned int c0 = *(unsigned int*)(source0 + 4 * x);
4876 unsigned int c1 = *(unsigned int*)(source1 + 4 * x);
4877 unsigned int c2 = *(unsigned int*)(source2 + 4 * x);
4878 unsigned int c3 = *(unsigned int*)(source3 + 4 * x);
4879 unsigned int c4 = *(unsigned int*)(source4 + 4 * x);
4880 unsigned int c5 = *(unsigned int*)(source5 + 4 * x);
4881 unsigned int c6 = *(unsigned int*)(source6 + 4 * x);
4882 unsigned int c7 = *(unsigned int*)(source7 + 4 * x);
4883 unsigned int c8 = *(unsigned int*)(source8 + 4 * x);
4884 unsigned int c9 = *(unsigned int*)(source9 + 4 * x);
4885 unsigned int cA = *(unsigned int*)(sourceA + 4 * x);
4886 unsigned int cB = *(unsigned int*)(sourceB + 4 * x);
4887 unsigned int cC = *(unsigned int*)(sourceC + 4 * x);
4888 unsigned int cD = *(unsigned int*)(sourceD + 4 * x);
4889 unsigned int cE = *(unsigned int*)(sourceE + 4 * x);
4890 unsigned int cF = *(unsigned int*)(sourceF + 4 * x);
4891
4892 c0 = AVERAGE(c0, c1);
4893 c2 = AVERAGE(c2, c3);
4894 c4 = AVERAGE(c4, c5);
4895 c6 = AVERAGE(c6, c7);
4896 c8 = AVERAGE(c8, c9);
4897 cA = AVERAGE(cA, cB);
4898 cC = AVERAGE(cC, cD);
4899 cE = AVERAGE(cE, cF);
4900 c0 = AVERAGE(c0, c2);
4901 c4 = AVERAGE(c4, c6);
4902 c8 = AVERAGE(c8, cA);
4903 cC = AVERAGE(cC, cE);
4904 c0 = AVERAGE(c0, c4);
4905 c8 = AVERAGE(c8, cC);
4906 c0 = AVERAGE(c0, c8);
4907
4908 *(unsigned int*)(source0 + 4 * x) = c0;
4909 }
4910
4911 source0 += pitch;
4912 source1 += pitch;
4913 source2 += pitch;
4914 source3 += pitch;
4915 source4 += pitch;
4916 source5 += pitch;
4917 source6 += pitch;
4918 source7 += pitch;
4919 source8 += pitch;
4920 source9 += pitch;
4921 sourceA += pitch;
4922 sourceB += pitch;
4923 sourceC += pitch;
4924 sourceD += pitch;
4925 sourceE += pitch;
4926 sourceF += pitch;
4927 }
4928 }
4929 else ASSERT(false);
4930
4931 #undef AVERAGE
4932 }
4933 }
4934 else if(internal.format == FORMAT_R32F)
4935 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004936 #if defined(__i386__) || defined(__x86_64__)
4937 if(CPUID::supportsSSE() && (width % 4) == 0)
John Bauman89401822014-05-06 15:04:28 -04004938 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004939 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04004940 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004941 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004942 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004943 for(int x = 0; x < width; x += 4)
4944 {
4945 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4946 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004947
Nicolas Capens47dc8672017-04-25 12:54:39 -04004948 c0 = _mm_add_ps(c0, c1);
4949 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04004950
Nicolas Capens47dc8672017-04-25 12:54:39 -04004951 _mm_store_ps((float*)(source0 + 4 * x), c0);
4952 }
4953
4954 source0 += pitch;
4955 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004956 }
John Bauman89401822014-05-06 15:04:28 -04004957 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004958 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04004959 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004960 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004961 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004962 for(int x = 0; x < width; x += 4)
4963 {
4964 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4965 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4966 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4967 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004968
Nicolas Capens47dc8672017-04-25 12:54:39 -04004969 c0 = _mm_add_ps(c0, c1);
4970 c2 = _mm_add_ps(c2, c3);
4971 c0 = _mm_add_ps(c0, c2);
4972 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04004973
Nicolas Capens47dc8672017-04-25 12:54:39 -04004974 _mm_store_ps((float*)(source0 + 4 * x), c0);
4975 }
4976
4977 source0 += pitch;
4978 source1 += pitch;
4979 source2 += pitch;
4980 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04004981 }
John Bauman89401822014-05-06 15:04:28 -04004982 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05004983 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04004984 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004985 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04004986 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04004987 for(int x = 0; x < width; x += 4)
4988 {
4989 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
4990 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
4991 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
4992 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
4993 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
4994 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
4995 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
4996 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04004997
Nicolas Capens47dc8672017-04-25 12:54:39 -04004998 c0 = _mm_add_ps(c0, c1);
4999 c2 = _mm_add_ps(c2, c3);
5000 c4 = _mm_add_ps(c4, c5);
5001 c6 = _mm_add_ps(c6, c7);
5002 c0 = _mm_add_ps(c0, c2);
5003 c4 = _mm_add_ps(c4, c6);
5004 c0 = _mm_add_ps(c0, c4);
5005 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005006
Nicolas Capens47dc8672017-04-25 12:54:39 -04005007 _mm_store_ps((float*)(source0 + 4 * x), c0);
5008 }
5009
5010 source0 += pitch;
5011 source1 += pitch;
5012 source2 += pitch;
5013 source3 += pitch;
5014 source4 += pitch;
5015 source5 += pitch;
5016 source6 += pitch;
5017 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005018 }
John Bauman89401822014-05-06 15:04:28 -04005019 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005020 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005021 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005022 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005023 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005024 for(int x = 0; x < width; x += 4)
5025 {
5026 __m128 c0 = _mm_load_ps((float*)(source0 + 4 * x));
5027 __m128 c1 = _mm_load_ps((float*)(source1 + 4 * x));
5028 __m128 c2 = _mm_load_ps((float*)(source2 + 4 * x));
5029 __m128 c3 = _mm_load_ps((float*)(source3 + 4 * x));
5030 __m128 c4 = _mm_load_ps((float*)(source4 + 4 * x));
5031 __m128 c5 = _mm_load_ps((float*)(source5 + 4 * x));
5032 __m128 c6 = _mm_load_ps((float*)(source6 + 4 * x));
5033 __m128 c7 = _mm_load_ps((float*)(source7 + 4 * x));
5034 __m128 c8 = _mm_load_ps((float*)(source8 + 4 * x));
5035 __m128 c9 = _mm_load_ps((float*)(source9 + 4 * x));
5036 __m128 cA = _mm_load_ps((float*)(sourceA + 4 * x));
5037 __m128 cB = _mm_load_ps((float*)(sourceB + 4 * x));
5038 __m128 cC = _mm_load_ps((float*)(sourceC + 4 * x));
5039 __m128 cD = _mm_load_ps((float*)(sourceD + 4 * x));
5040 __m128 cE = _mm_load_ps((float*)(sourceE + 4 * x));
5041 __m128 cF = _mm_load_ps((float*)(sourceF + 4 * x));
John Bauman89401822014-05-06 15:04:28 -04005042
Nicolas Capens47dc8672017-04-25 12:54:39 -04005043 c0 = _mm_add_ps(c0, c1);
5044 c2 = _mm_add_ps(c2, c3);
5045 c4 = _mm_add_ps(c4, c5);
5046 c6 = _mm_add_ps(c6, c7);
5047 c8 = _mm_add_ps(c8, c9);
5048 cA = _mm_add_ps(cA, cB);
5049 cC = _mm_add_ps(cC, cD);
5050 cE = _mm_add_ps(cE, cF);
5051 c0 = _mm_add_ps(c0, c2);
5052 c4 = _mm_add_ps(c4, c6);
5053 c8 = _mm_add_ps(c8, cA);
5054 cC = _mm_add_ps(cC, cE);
5055 c0 = _mm_add_ps(c0, c4);
5056 c8 = _mm_add_ps(c8, cC);
5057 c0 = _mm_add_ps(c0, c8);
5058 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005059
Nicolas Capens47dc8672017-04-25 12:54:39 -04005060 _mm_store_ps((float*)(source0 + 4 * x), c0);
5061 }
5062
5063 source0 += pitch;
5064 source1 += pitch;
5065 source2 += pitch;
5066 source3 += pitch;
5067 source4 += pitch;
5068 source5 += pitch;
5069 source6 += pitch;
5070 source7 += pitch;
5071 source8 += pitch;
5072 source9 += pitch;
5073 sourceA += pitch;
5074 sourceB += pitch;
5075 sourceC += pitch;
5076 sourceD += pitch;
5077 sourceE += pitch;
5078 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005079 }
John Bauman89401822014-05-06 15:04:28 -04005080 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005081 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005082 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005083 else
5084 #endif
John Bauman89401822014-05-06 15:04:28 -04005085 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005086 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005087 {
5088 for(int y = 0; y < height; y++)
5089 {
5090 for(int x = 0; x < width; x++)
5091 {
5092 float c0 = *(float*)(source0 + 4 * x);
5093 float c1 = *(float*)(source1 + 4 * x);
5094
5095 c0 = c0 + c1;
5096 c0 *= 1.0f / 2.0f;
5097
5098 *(float*)(source0 + 4 * x) = c0;
5099 }
5100
5101 source0 += pitch;
5102 source1 += pitch;
5103 }
5104 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005105 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005106 {
5107 for(int y = 0; y < height; y++)
5108 {
5109 for(int x = 0; x < width; x++)
5110 {
5111 float c0 = *(float*)(source0 + 4 * x);
5112 float c1 = *(float*)(source1 + 4 * x);
5113 float c2 = *(float*)(source2 + 4 * x);
5114 float c3 = *(float*)(source3 + 4 * x);
5115
5116 c0 = c0 + c1;
5117 c2 = c2 + c3;
5118 c0 = c0 + c2;
5119 c0 *= 1.0f / 4.0f;
5120
5121 *(float*)(source0 + 4 * x) = c0;
5122 }
5123
5124 source0 += pitch;
5125 source1 += pitch;
5126 source2 += pitch;
5127 source3 += pitch;
5128 }
5129 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005130 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005131 {
5132 for(int y = 0; y < height; y++)
5133 {
5134 for(int x = 0; x < width; x++)
5135 {
5136 float c0 = *(float*)(source0 + 4 * x);
5137 float c1 = *(float*)(source1 + 4 * x);
5138 float c2 = *(float*)(source2 + 4 * x);
5139 float c3 = *(float*)(source3 + 4 * x);
5140 float c4 = *(float*)(source4 + 4 * x);
5141 float c5 = *(float*)(source5 + 4 * x);
5142 float c6 = *(float*)(source6 + 4 * x);
5143 float c7 = *(float*)(source7 + 4 * x);
5144
5145 c0 = c0 + c1;
5146 c2 = c2 + c3;
5147 c4 = c4 + c5;
5148 c6 = c6 + c7;
5149 c0 = c0 + c2;
5150 c4 = c4 + c6;
5151 c0 = c0 + c4;
5152 c0 *= 1.0f / 8.0f;
5153
5154 *(float*)(source0 + 4 * x) = c0;
5155 }
5156
5157 source0 += pitch;
5158 source1 += pitch;
5159 source2 += pitch;
5160 source3 += pitch;
5161 source4 += pitch;
5162 source5 += pitch;
5163 source6 += pitch;
5164 source7 += pitch;
5165 }
5166 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005167 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005168 {
5169 for(int y = 0; y < height; y++)
5170 {
5171 for(int x = 0; x < width; x++)
5172 {
5173 float c0 = *(float*)(source0 + 4 * x);
5174 float c1 = *(float*)(source1 + 4 * x);
5175 float c2 = *(float*)(source2 + 4 * x);
5176 float c3 = *(float*)(source3 + 4 * x);
5177 float c4 = *(float*)(source4 + 4 * x);
5178 float c5 = *(float*)(source5 + 4 * x);
5179 float c6 = *(float*)(source6 + 4 * x);
5180 float c7 = *(float*)(source7 + 4 * x);
5181 float c8 = *(float*)(source8 + 4 * x);
5182 float c9 = *(float*)(source9 + 4 * x);
5183 float cA = *(float*)(sourceA + 4 * x);
5184 float cB = *(float*)(sourceB + 4 * x);
5185 float cC = *(float*)(sourceC + 4 * x);
5186 float cD = *(float*)(sourceD + 4 * x);
5187 float cE = *(float*)(sourceE + 4 * x);
5188 float cF = *(float*)(sourceF + 4 * x);
5189
5190 c0 = c0 + c1;
5191 c2 = c2 + c3;
5192 c4 = c4 + c5;
5193 c6 = c6 + c7;
5194 c8 = c8 + c9;
5195 cA = cA + cB;
5196 cC = cC + cD;
5197 cE = cE + cF;
5198 c0 = c0 + c2;
5199 c4 = c4 + c6;
5200 c8 = c8 + cA;
5201 cC = cC + cE;
5202 c0 = c0 + c4;
5203 c8 = c8 + cC;
5204 c0 = c0 + c8;
5205 c0 *= 1.0f / 16.0f;
5206
5207 *(float*)(source0 + 4 * x) = c0;
5208 }
5209
5210 source0 += pitch;
5211 source1 += pitch;
5212 source2 += pitch;
5213 source3 += pitch;
5214 source4 += pitch;
5215 source5 += pitch;
5216 source6 += pitch;
5217 source7 += pitch;
5218 source8 += pitch;
5219 source9 += pitch;
5220 sourceA += pitch;
5221 sourceB += pitch;
5222 sourceC += pitch;
5223 sourceD += pitch;
5224 sourceE += pitch;
5225 sourceF += pitch;
5226 }
5227 }
5228 else ASSERT(false);
5229 }
5230 }
5231 else if(internal.format == FORMAT_G32R32F)
5232 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005233 #if defined(__i386__) || defined(__x86_64__)
5234 if(CPUID::supportsSSE() && (width % 2) == 0)
John Bauman89401822014-05-06 15:04:28 -04005235 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005236 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005237 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005238 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005239 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005240 for(int x = 0; x < width; x += 2)
5241 {
5242 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5243 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005244
Nicolas Capens47dc8672017-04-25 12:54:39 -04005245 c0 = _mm_add_ps(c0, c1);
5246 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005247
Nicolas Capens47dc8672017-04-25 12:54:39 -04005248 _mm_store_ps((float*)(source0 + 8 * x), c0);
5249 }
5250
5251 source0 += pitch;
5252 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005253 }
John Bauman89401822014-05-06 15:04:28 -04005254 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005255 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005256 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005257 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005258 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005259 for(int x = 0; x < width; x += 2)
5260 {
5261 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5262 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5263 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5264 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005265
Nicolas Capens47dc8672017-04-25 12:54:39 -04005266 c0 = _mm_add_ps(c0, c1);
5267 c2 = _mm_add_ps(c2, c3);
5268 c0 = _mm_add_ps(c0, c2);
5269 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005270
Nicolas Capens47dc8672017-04-25 12:54:39 -04005271 _mm_store_ps((float*)(source0 + 8 * x), c0);
5272 }
5273
5274 source0 += pitch;
5275 source1 += pitch;
5276 source2 += pitch;
5277 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005278 }
John Bauman89401822014-05-06 15:04:28 -04005279 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005280 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005281 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005282 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005283 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005284 for(int x = 0; x < width; x += 2)
5285 {
5286 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5287 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5288 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5289 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5290 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5291 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5292 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5293 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005294
Nicolas Capens47dc8672017-04-25 12:54:39 -04005295 c0 = _mm_add_ps(c0, c1);
5296 c2 = _mm_add_ps(c2, c3);
5297 c4 = _mm_add_ps(c4, c5);
5298 c6 = _mm_add_ps(c6, c7);
5299 c0 = _mm_add_ps(c0, c2);
5300 c4 = _mm_add_ps(c4, c6);
5301 c0 = _mm_add_ps(c0, c4);
5302 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005303
Nicolas Capens47dc8672017-04-25 12:54:39 -04005304 _mm_store_ps((float*)(source0 + 8 * x), c0);
5305 }
5306
5307 source0 += pitch;
5308 source1 += pitch;
5309 source2 += pitch;
5310 source3 += pitch;
5311 source4 += pitch;
5312 source5 += pitch;
5313 source6 += pitch;
5314 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005315 }
John Bauman89401822014-05-06 15:04:28 -04005316 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005317 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005318 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005319 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005320 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005321 for(int x = 0; x < width; x += 2)
5322 {
5323 __m128 c0 = _mm_load_ps((float*)(source0 + 8 * x));
5324 __m128 c1 = _mm_load_ps((float*)(source1 + 8 * x));
5325 __m128 c2 = _mm_load_ps((float*)(source2 + 8 * x));
5326 __m128 c3 = _mm_load_ps((float*)(source3 + 8 * x));
5327 __m128 c4 = _mm_load_ps((float*)(source4 + 8 * x));
5328 __m128 c5 = _mm_load_ps((float*)(source5 + 8 * x));
5329 __m128 c6 = _mm_load_ps((float*)(source6 + 8 * x));
5330 __m128 c7 = _mm_load_ps((float*)(source7 + 8 * x));
5331 __m128 c8 = _mm_load_ps((float*)(source8 + 8 * x));
5332 __m128 c9 = _mm_load_ps((float*)(source9 + 8 * x));
5333 __m128 cA = _mm_load_ps((float*)(sourceA + 8 * x));
5334 __m128 cB = _mm_load_ps((float*)(sourceB + 8 * x));
5335 __m128 cC = _mm_load_ps((float*)(sourceC + 8 * x));
5336 __m128 cD = _mm_load_ps((float*)(sourceD + 8 * x));
5337 __m128 cE = _mm_load_ps((float*)(sourceE + 8 * x));
5338 __m128 cF = _mm_load_ps((float*)(sourceF + 8 * x));
John Bauman89401822014-05-06 15:04:28 -04005339
Nicolas Capens47dc8672017-04-25 12:54:39 -04005340 c0 = _mm_add_ps(c0, c1);
5341 c2 = _mm_add_ps(c2, c3);
5342 c4 = _mm_add_ps(c4, c5);
5343 c6 = _mm_add_ps(c6, c7);
5344 c8 = _mm_add_ps(c8, c9);
5345 cA = _mm_add_ps(cA, cB);
5346 cC = _mm_add_ps(cC, cD);
5347 cE = _mm_add_ps(cE, cF);
5348 c0 = _mm_add_ps(c0, c2);
5349 c4 = _mm_add_ps(c4, c6);
5350 c8 = _mm_add_ps(c8, cA);
5351 cC = _mm_add_ps(cC, cE);
5352 c0 = _mm_add_ps(c0, c4);
5353 c8 = _mm_add_ps(c8, cC);
5354 c0 = _mm_add_ps(c0, c8);
5355 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005356
Nicolas Capens47dc8672017-04-25 12:54:39 -04005357 _mm_store_ps((float*)(source0 + 8 * x), c0);
5358 }
5359
5360 source0 += pitch;
5361 source1 += pitch;
5362 source2 += pitch;
5363 source3 += pitch;
5364 source4 += pitch;
5365 source5 += pitch;
5366 source6 += pitch;
5367 source7 += pitch;
5368 source8 += pitch;
5369 source9 += pitch;
5370 sourceA += pitch;
5371 sourceB += pitch;
5372 sourceC += pitch;
5373 sourceD += pitch;
5374 sourceE += pitch;
5375 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005376 }
John Bauman89401822014-05-06 15:04:28 -04005377 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005378 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005379 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005380 else
5381 #endif
John Bauman89401822014-05-06 15:04:28 -04005382 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005383 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005384 {
5385 for(int y = 0; y < height; y++)
5386 {
5387 for(int x = 0; x < 2 * width; x++)
5388 {
5389 float c0 = *(float*)(source0 + 4 * x);
5390 float c1 = *(float*)(source1 + 4 * x);
5391
5392 c0 = c0 + c1;
5393 c0 *= 1.0f / 2.0f;
5394
5395 *(float*)(source0 + 4 * x) = c0;
5396 }
5397
5398 source0 += pitch;
5399 source1 += pitch;
5400 }
5401 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005402 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005403 {
5404 for(int y = 0; y < height; y++)
5405 {
5406 for(int x = 0; x < 2 * width; x++)
5407 {
5408 float c0 = *(float*)(source0 + 4 * x);
5409 float c1 = *(float*)(source1 + 4 * x);
5410 float c2 = *(float*)(source2 + 4 * x);
5411 float c3 = *(float*)(source3 + 4 * x);
5412
5413 c0 = c0 + c1;
5414 c2 = c2 + c3;
5415 c0 = c0 + c2;
5416 c0 *= 1.0f / 4.0f;
5417
5418 *(float*)(source0 + 4 * x) = c0;
5419 }
5420
5421 source0 += pitch;
5422 source1 += pitch;
5423 source2 += pitch;
5424 source3 += pitch;
5425 }
5426 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005427 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005428 {
5429 for(int y = 0; y < height; y++)
5430 {
5431 for(int x = 0; x < 2 * width; x++)
5432 {
5433 float c0 = *(float*)(source0 + 4 * x);
5434 float c1 = *(float*)(source1 + 4 * x);
5435 float c2 = *(float*)(source2 + 4 * x);
5436 float c3 = *(float*)(source3 + 4 * x);
5437 float c4 = *(float*)(source4 + 4 * x);
5438 float c5 = *(float*)(source5 + 4 * x);
5439 float c6 = *(float*)(source6 + 4 * x);
5440 float c7 = *(float*)(source7 + 4 * x);
5441
5442 c0 = c0 + c1;
5443 c2 = c2 + c3;
5444 c4 = c4 + c5;
5445 c6 = c6 + c7;
5446 c0 = c0 + c2;
5447 c4 = c4 + c6;
5448 c0 = c0 + c4;
5449 c0 *= 1.0f / 8.0f;
5450
5451 *(float*)(source0 + 4 * x) = c0;
5452 }
5453
5454 source0 += pitch;
5455 source1 += pitch;
5456 source2 += pitch;
5457 source3 += pitch;
5458 source4 += pitch;
5459 source5 += pitch;
5460 source6 += pitch;
5461 source7 += pitch;
5462 }
5463 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005464 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005465 {
5466 for(int y = 0; y < height; y++)
5467 {
5468 for(int x = 0; x < 2 * width; x++)
5469 {
5470 float c0 = *(float*)(source0 + 4 * x);
5471 float c1 = *(float*)(source1 + 4 * x);
5472 float c2 = *(float*)(source2 + 4 * x);
5473 float c3 = *(float*)(source3 + 4 * x);
5474 float c4 = *(float*)(source4 + 4 * x);
5475 float c5 = *(float*)(source5 + 4 * x);
5476 float c6 = *(float*)(source6 + 4 * x);
5477 float c7 = *(float*)(source7 + 4 * x);
5478 float c8 = *(float*)(source8 + 4 * x);
5479 float c9 = *(float*)(source9 + 4 * x);
5480 float cA = *(float*)(sourceA + 4 * x);
5481 float cB = *(float*)(sourceB + 4 * x);
5482 float cC = *(float*)(sourceC + 4 * x);
5483 float cD = *(float*)(sourceD + 4 * x);
5484 float cE = *(float*)(sourceE + 4 * x);
5485 float cF = *(float*)(sourceF + 4 * x);
5486
5487 c0 = c0 + c1;
5488 c2 = c2 + c3;
5489 c4 = c4 + c5;
5490 c6 = c6 + c7;
5491 c8 = c8 + c9;
5492 cA = cA + cB;
5493 cC = cC + cD;
5494 cE = cE + cF;
5495 c0 = c0 + c2;
5496 c4 = c4 + c6;
5497 c8 = c8 + cA;
5498 cC = cC + cE;
5499 c0 = c0 + c4;
5500 c8 = c8 + cC;
5501 c0 = c0 + c8;
5502 c0 *= 1.0f / 16.0f;
5503
5504 *(float*)(source0 + 4 * x) = c0;
5505 }
5506
5507 source0 += pitch;
5508 source1 += pitch;
5509 source2 += pitch;
5510 source3 += pitch;
5511 source4 += pitch;
5512 source5 += pitch;
5513 source6 += pitch;
5514 source7 += pitch;
5515 source8 += pitch;
5516 source9 += pitch;
5517 sourceA += pitch;
5518 sourceB += pitch;
5519 sourceC += pitch;
5520 sourceD += pitch;
5521 sourceE += pitch;
5522 sourceF += pitch;
5523 }
5524 }
5525 else ASSERT(false);
5526 }
5527 }
Nicolas Capens67fdd832017-12-21 11:20:54 -05005528 else if(internal.format == FORMAT_A32B32G32R32F ||
5529 internal.format == FORMAT_X32B32G32R32F ||
5530 internal.format == FORMAT_X32B32G32R32F_UNSIGNED)
John Bauman89401822014-05-06 15:04:28 -04005531 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005532 #if defined(__i386__) || defined(__x86_64__)
5533 if(CPUID::supportsSSE())
John Bauman89401822014-05-06 15:04:28 -04005534 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005535 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005536 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005537 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005538 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005539 for(int x = 0; x < width; x++)
5540 {
5541 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5542 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005543
Nicolas Capens47dc8672017-04-25 12:54:39 -04005544 c0 = _mm_add_ps(c0, c1);
5545 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 2.0f));
John Bauman89401822014-05-06 15:04:28 -04005546
Nicolas Capens47dc8672017-04-25 12:54:39 -04005547 _mm_store_ps((float*)(source0 + 16 * x), c0);
5548 }
5549
5550 source0 += pitch;
5551 source1 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005552 }
John Bauman89401822014-05-06 15:04:28 -04005553 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005554 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005555 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005556 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005557 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005558 for(int x = 0; x < width; x++)
5559 {
5560 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5561 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5562 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5563 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005564
Nicolas Capens47dc8672017-04-25 12:54:39 -04005565 c0 = _mm_add_ps(c0, c1);
5566 c2 = _mm_add_ps(c2, c3);
5567 c0 = _mm_add_ps(c0, c2);
5568 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 4.0f));
John Bauman89401822014-05-06 15:04:28 -04005569
Nicolas Capens47dc8672017-04-25 12:54:39 -04005570 _mm_store_ps((float*)(source0 + 16 * x), c0);
5571 }
5572
5573 source0 += pitch;
5574 source1 += pitch;
5575 source2 += pitch;
5576 source3 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005577 }
John Bauman89401822014-05-06 15:04:28 -04005578 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005579 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005580 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005581 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005582 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005583 for(int x = 0; x < width; x++)
5584 {
5585 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5586 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5587 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5588 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5589 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5590 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5591 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5592 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005593
Nicolas Capens47dc8672017-04-25 12:54:39 -04005594 c0 = _mm_add_ps(c0, c1);
5595 c2 = _mm_add_ps(c2, c3);
5596 c4 = _mm_add_ps(c4, c5);
5597 c6 = _mm_add_ps(c6, c7);
5598 c0 = _mm_add_ps(c0, c2);
5599 c4 = _mm_add_ps(c4, c6);
5600 c0 = _mm_add_ps(c0, c4);
5601 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 8.0f));
John Bauman89401822014-05-06 15:04:28 -04005602
Nicolas Capens47dc8672017-04-25 12:54:39 -04005603 _mm_store_ps((float*)(source0 + 16 * x), c0);
5604 }
5605
5606 source0 += pitch;
5607 source1 += pitch;
5608 source2 += pitch;
5609 source3 += pitch;
5610 source4 += pitch;
5611 source5 += pitch;
5612 source6 += pitch;
5613 source7 += pitch;
John Bauman89401822014-05-06 15:04:28 -04005614 }
John Bauman89401822014-05-06 15:04:28 -04005615 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005616 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005617 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005618 for(int y = 0; y < height; y++)
John Bauman89401822014-05-06 15:04:28 -04005619 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005620 for(int x = 0; x < width; x++)
5621 {
5622 __m128 c0 = _mm_load_ps((float*)(source0 + 16 * x));
5623 __m128 c1 = _mm_load_ps((float*)(source1 + 16 * x));
5624 __m128 c2 = _mm_load_ps((float*)(source2 + 16 * x));
5625 __m128 c3 = _mm_load_ps((float*)(source3 + 16 * x));
5626 __m128 c4 = _mm_load_ps((float*)(source4 + 16 * x));
5627 __m128 c5 = _mm_load_ps((float*)(source5 + 16 * x));
5628 __m128 c6 = _mm_load_ps((float*)(source6 + 16 * x));
5629 __m128 c7 = _mm_load_ps((float*)(source7 + 16 * x));
5630 __m128 c8 = _mm_load_ps((float*)(source8 + 16 * x));
5631 __m128 c9 = _mm_load_ps((float*)(source9 + 16 * x));
5632 __m128 cA = _mm_load_ps((float*)(sourceA + 16 * x));
5633 __m128 cB = _mm_load_ps((float*)(sourceB + 16 * x));
5634 __m128 cC = _mm_load_ps((float*)(sourceC + 16 * x));
5635 __m128 cD = _mm_load_ps((float*)(sourceD + 16 * x));
5636 __m128 cE = _mm_load_ps((float*)(sourceE + 16 * x));
5637 __m128 cF = _mm_load_ps((float*)(sourceF + 16 * x));
John Bauman89401822014-05-06 15:04:28 -04005638
Nicolas Capens47dc8672017-04-25 12:54:39 -04005639 c0 = _mm_add_ps(c0, c1);
5640 c2 = _mm_add_ps(c2, c3);
5641 c4 = _mm_add_ps(c4, c5);
5642 c6 = _mm_add_ps(c6, c7);
5643 c8 = _mm_add_ps(c8, c9);
5644 cA = _mm_add_ps(cA, cB);
5645 cC = _mm_add_ps(cC, cD);
5646 cE = _mm_add_ps(cE, cF);
5647 c0 = _mm_add_ps(c0, c2);
5648 c4 = _mm_add_ps(c4, c6);
5649 c8 = _mm_add_ps(c8, cA);
5650 cC = _mm_add_ps(cC, cE);
5651 c0 = _mm_add_ps(c0, c4);
5652 c8 = _mm_add_ps(c8, cC);
5653 c0 = _mm_add_ps(c0, c8);
5654 c0 = _mm_mul_ps(c0, _mm_set1_ps(1.0f / 16.0f));
John Bauman89401822014-05-06 15:04:28 -04005655
Nicolas Capens47dc8672017-04-25 12:54:39 -04005656 _mm_store_ps((float*)(source0 + 16 * x), c0);
5657 }
5658
5659 source0 += pitch;
5660 source1 += pitch;
5661 source2 += pitch;
5662 source3 += pitch;
5663 source4 += pitch;
5664 source5 += pitch;
5665 source6 += pitch;
5666 source7 += pitch;
5667 source8 += pitch;
5668 source9 += pitch;
5669 sourceA += pitch;
5670 sourceB += pitch;
5671 sourceC += pitch;
5672 sourceD += pitch;
5673 sourceE += pitch;
5674 sourceF += pitch;
John Bauman89401822014-05-06 15:04:28 -04005675 }
John Bauman89401822014-05-06 15:04:28 -04005676 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005677 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04005678 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04005679 else
5680 #endif
John Bauman89401822014-05-06 15:04:28 -04005681 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005682 if(internal.samples == 2)
John Bauman89401822014-05-06 15:04:28 -04005683 {
5684 for(int y = 0; y < height; y++)
5685 {
5686 for(int x = 0; x < 4 * width; x++)
5687 {
5688 float c0 = *(float*)(source0 + 4 * x);
5689 float c1 = *(float*)(source1 + 4 * x);
5690
5691 c0 = c0 + c1;
5692 c0 *= 1.0f / 2.0f;
5693
5694 *(float*)(source0 + 4 * x) = c0;
5695 }
5696
5697 source0 += pitch;
5698 source1 += pitch;
5699 }
5700 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005701 else if(internal.samples == 4)
John Bauman89401822014-05-06 15:04:28 -04005702 {
5703 for(int y = 0; y < height; y++)
5704 {
5705 for(int x = 0; x < 4 * width; x++)
5706 {
5707 float c0 = *(float*)(source0 + 4 * x);
5708 float c1 = *(float*)(source1 + 4 * x);
5709 float c2 = *(float*)(source2 + 4 * x);
5710 float c3 = *(float*)(source3 + 4 * x);
5711
5712 c0 = c0 + c1;
5713 c2 = c2 + c3;
5714 c0 = c0 + c2;
5715 c0 *= 1.0f / 4.0f;
5716
5717 *(float*)(source0 + 4 * x) = c0;
5718 }
5719
5720 source0 += pitch;
5721 source1 += pitch;
5722 source2 += pitch;
5723 source3 += pitch;
5724 }
5725 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005726 else if(internal.samples == 8)
John Bauman89401822014-05-06 15:04:28 -04005727 {
5728 for(int y = 0; y < height; y++)
5729 {
5730 for(int x = 0; x < 4 * width; x++)
5731 {
5732 float c0 = *(float*)(source0 + 4 * x);
5733 float c1 = *(float*)(source1 + 4 * x);
5734 float c2 = *(float*)(source2 + 4 * x);
5735 float c3 = *(float*)(source3 + 4 * x);
5736 float c4 = *(float*)(source4 + 4 * x);
5737 float c5 = *(float*)(source5 + 4 * x);
5738 float c6 = *(float*)(source6 + 4 * x);
5739 float c7 = *(float*)(source7 + 4 * x);
5740
5741 c0 = c0 + c1;
5742 c2 = c2 + c3;
5743 c4 = c4 + c5;
5744 c6 = c6 + c7;
5745 c0 = c0 + c2;
5746 c4 = c4 + c6;
5747 c0 = c0 + c4;
5748 c0 *= 1.0f / 8.0f;
5749
5750 *(float*)(source0 + 4 * x) = c0;
5751 }
5752
5753 source0 += pitch;
5754 source1 += pitch;
5755 source2 += pitch;
5756 source3 += pitch;
5757 source4 += pitch;
5758 source5 += pitch;
5759 source6 += pitch;
5760 source7 += pitch;
5761 }
5762 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005763 else if(internal.samples == 16)
John Bauman89401822014-05-06 15:04:28 -04005764 {
5765 for(int y = 0; y < height; y++)
5766 {
5767 for(int x = 0; x < 4 * width; x++)
5768 {
5769 float c0 = *(float*)(source0 + 4 * x);
5770 float c1 = *(float*)(source1 + 4 * x);
5771 float c2 = *(float*)(source2 + 4 * x);
5772 float c3 = *(float*)(source3 + 4 * x);
5773 float c4 = *(float*)(source4 + 4 * x);
5774 float c5 = *(float*)(source5 + 4 * x);
5775 float c6 = *(float*)(source6 + 4 * x);
5776 float c7 = *(float*)(source7 + 4 * x);
5777 float c8 = *(float*)(source8 + 4 * x);
5778 float c9 = *(float*)(source9 + 4 * x);
5779 float cA = *(float*)(sourceA + 4 * x);
5780 float cB = *(float*)(sourceB + 4 * x);
5781 float cC = *(float*)(sourceC + 4 * x);
5782 float cD = *(float*)(sourceD + 4 * x);
5783 float cE = *(float*)(sourceE + 4 * x);
5784 float cF = *(float*)(sourceF + 4 * x);
5785
5786 c0 = c0 + c1;
5787 c2 = c2 + c3;
5788 c4 = c4 + c5;
5789 c6 = c6 + c7;
5790 c8 = c8 + c9;
5791 cA = cA + cB;
5792 cC = cC + cD;
5793 cE = cE + cF;
5794 c0 = c0 + c2;
5795 c4 = c4 + c6;
5796 c8 = c8 + cA;
5797 cC = cC + cE;
5798 c0 = c0 + c4;
5799 c8 = c8 + cC;
5800 c0 = c0 + c8;
5801 c0 *= 1.0f / 16.0f;
5802
5803 *(float*)(source0 + 4 * x) = c0;
5804 }
5805
5806 source0 += pitch;
5807 source1 += pitch;
5808 source2 += pitch;
5809 source3 += pitch;
5810 source4 += pitch;
5811 source5 += pitch;
5812 source6 += pitch;
5813 source7 += pitch;
5814 source8 += pitch;
5815 source9 += pitch;
5816 sourceA += pitch;
5817 sourceB += pitch;
5818 sourceC += pitch;
5819 sourceD += pitch;
5820 sourceE += pitch;
5821 sourceF += pitch;
5822 }
5823 }
5824 else ASSERT(false);
5825 }
5826 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005827 else if(internal.format == FORMAT_R5G6B5)
5828 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005829 #if defined(__i386__) || defined(__x86_64__)
5830 if(CPUID::supportsSSE2() && (width % 8) == 0)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005831 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005832 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005833 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005834 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005835 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005836 for(int x = 0; x < width; x += 8)
5837 {
5838 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5839 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005840
Nicolas Capens47dc8672017-04-25 12:54:39 -04005841 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5842 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5843 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5844 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5845 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5846 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005847
Nicolas Capens47dc8672017-04-25 12:54:39 -04005848 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5849 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5850 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5851 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5852 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005853
Nicolas Capens47dc8672017-04-25 12:54:39 -04005854 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5855 }
5856
5857 source0 += pitch;
5858 source1 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005859 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005860 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005861 else if(internal.samples == 4)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005862 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005863 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005864 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005865 for(int x = 0; x < width; x += 8)
5866 {
5867 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5868 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5869 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5870 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005871
Nicolas Capens47dc8672017-04-25 12:54:39 -04005872 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5873 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5874 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5875 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5876 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5877 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5878 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5879 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5880 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5881 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005882
Nicolas Capens47dc8672017-04-25 12:54:39 -04005883 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5884 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5885 c0 = _mm_avg_epu8(c0, c2);
5886 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5887 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5888 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5889 c1 = _mm_avg_epu16(c1, c3);
5890 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5891 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005892
Nicolas Capens47dc8672017-04-25 12:54:39 -04005893 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5894 }
5895
5896 source0 += pitch;
5897 source1 += pitch;
5898 source2 += pitch;
5899 source3 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005900 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005901 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005902 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005903 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005904 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005905 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005906 for(int x = 0; x < width; x += 8)
5907 {
5908 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5909 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5910 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5911 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5912 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5913 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5914 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5915 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
Nicolas Capensc39901e2016-03-21 16:37:44 -04005916
Nicolas Capens47dc8672017-04-25 12:54:39 -04005917 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5918 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5919 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5920 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5921 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5922 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5923 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5924 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5925 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5926 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
5927 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
5928 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
5929 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
5930 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
5931 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
5932 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
5933 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
5934 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005935
Nicolas Capens47dc8672017-04-25 12:54:39 -04005936 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
5937 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
5938 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
5939 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
5940 c0 = _mm_avg_epu8(c0, c2);
5941 c4 = _mm_avg_epu8(c4, c6);
5942 c0 = _mm_avg_epu8(c0, c4);
5943 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5944 c1 = _mm_avg_epu16(c0__g_, c1__g_);
5945 c3 = _mm_avg_epu16(c2__g_, c3__g_);
5946 c5 = _mm_avg_epu16(c4__g_, c5__g_);
5947 c7 = _mm_avg_epu16(c6__g_, c7__g_);
5948 c1 = _mm_avg_epu16(c1, c3);
5949 c5 = _mm_avg_epu16(c5, c7);
5950 c1 = _mm_avg_epu16(c1, c5);
5951 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5952 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04005953
Nicolas Capens47dc8672017-04-25 12:54:39 -04005954 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
5955 }
5956
5957 source0 += pitch;
5958 source1 += pitch;
5959 source2 += pitch;
5960 source3 += pitch;
5961 source4 += pitch;
5962 source5 += pitch;
5963 source6 += pitch;
5964 source7 += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04005965 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04005966 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05005967 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005968 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005969 for(int y = 0; y < height; y++)
Nicolas Capens0e12a922015-09-04 09:18:15 -04005970 {
Nicolas Capens47dc8672017-04-25 12:54:39 -04005971 for(int x = 0; x < width; x += 8)
5972 {
5973 __m128i c0 = _mm_load_si128((__m128i*)(source0 + 2 * x));
5974 __m128i c1 = _mm_load_si128((__m128i*)(source1 + 2 * x));
5975 __m128i c2 = _mm_load_si128((__m128i*)(source2 + 2 * x));
5976 __m128i c3 = _mm_load_si128((__m128i*)(source3 + 2 * x));
5977 __m128i c4 = _mm_load_si128((__m128i*)(source4 + 2 * x));
5978 __m128i c5 = _mm_load_si128((__m128i*)(source5 + 2 * x));
5979 __m128i c6 = _mm_load_si128((__m128i*)(source6 + 2 * x));
5980 __m128i c7 = _mm_load_si128((__m128i*)(source7 + 2 * x));
5981 __m128i c8 = _mm_load_si128((__m128i*)(source8 + 2 * x));
5982 __m128i c9 = _mm_load_si128((__m128i*)(source9 + 2 * x));
5983 __m128i cA = _mm_load_si128((__m128i*)(sourceA + 2 * x));
5984 __m128i cB = _mm_load_si128((__m128i*)(sourceB + 2 * x));
5985 __m128i cC = _mm_load_si128((__m128i*)(sourceC + 2 * x));
5986 __m128i cD = _mm_load_si128((__m128i*)(sourceD + 2 * x));
5987 __m128i cE = _mm_load_si128((__m128i*)(sourceE + 2 * x));
5988 __m128i cF = _mm_load_si128((__m128i*)(sourceF + 2 * x));
Nicolas Capens0e12a922015-09-04 09:18:15 -04005989
Nicolas Capens47dc8672017-04-25 12:54:39 -04005990 static const ushort8 r_b = {0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F};
5991 static const ushort8 _g_ = {0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0};
5992 __m128i c0_r_b = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
5993 __m128i c0__g_ = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(_g_));
5994 __m128i c1_r_b = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(r_b));
5995 __m128i c1__g_ = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
5996 __m128i c2_r_b = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(r_b));
5997 __m128i c2__g_ = _mm_and_si128(c2, reinterpret_cast<const __m128i&>(_g_));
5998 __m128i c3_r_b = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(r_b));
5999 __m128i c3__g_ = _mm_and_si128(c3, reinterpret_cast<const __m128i&>(_g_));
6000 __m128i c4_r_b = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(r_b));
6001 __m128i c4__g_ = _mm_and_si128(c4, reinterpret_cast<const __m128i&>(_g_));
6002 __m128i c5_r_b = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(r_b));
6003 __m128i c5__g_ = _mm_and_si128(c5, reinterpret_cast<const __m128i&>(_g_));
6004 __m128i c6_r_b = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(r_b));
6005 __m128i c6__g_ = _mm_and_si128(c6, reinterpret_cast<const __m128i&>(_g_));
6006 __m128i c7_r_b = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(r_b));
6007 __m128i c7__g_ = _mm_and_si128(c7, reinterpret_cast<const __m128i&>(_g_));
6008 __m128i c8_r_b = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(r_b));
6009 __m128i c8__g_ = _mm_and_si128(c8, reinterpret_cast<const __m128i&>(_g_));
6010 __m128i c9_r_b = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(r_b));
6011 __m128i c9__g_ = _mm_and_si128(c9, reinterpret_cast<const __m128i&>(_g_));
6012 __m128i cA_r_b = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(r_b));
6013 __m128i cA__g_ = _mm_and_si128(cA, reinterpret_cast<const __m128i&>(_g_));
6014 __m128i cB_r_b = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(r_b));
6015 __m128i cB__g_ = _mm_and_si128(cB, reinterpret_cast<const __m128i&>(_g_));
6016 __m128i cC_r_b = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(r_b));
6017 __m128i cC__g_ = _mm_and_si128(cC, reinterpret_cast<const __m128i&>(_g_));
6018 __m128i cD_r_b = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(r_b));
6019 __m128i cD__g_ = _mm_and_si128(cD, reinterpret_cast<const __m128i&>(_g_));
6020 __m128i cE_r_b = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(r_b));
6021 __m128i cE__g_ = _mm_and_si128(cE, reinterpret_cast<const __m128i&>(_g_));
6022 __m128i cF_r_b = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(r_b));
6023 __m128i cF__g_ = _mm_and_si128(cF, reinterpret_cast<const __m128i&>(_g_));
Nicolas Capens0e12a922015-09-04 09:18:15 -04006024
Nicolas Capens47dc8672017-04-25 12:54:39 -04006025 c0 = _mm_avg_epu8(c0_r_b, c1_r_b);
6026 c2 = _mm_avg_epu8(c2_r_b, c3_r_b);
6027 c4 = _mm_avg_epu8(c4_r_b, c5_r_b);
6028 c6 = _mm_avg_epu8(c6_r_b, c7_r_b);
6029 c8 = _mm_avg_epu8(c8_r_b, c9_r_b);
6030 cA = _mm_avg_epu8(cA_r_b, cB_r_b);
6031 cC = _mm_avg_epu8(cC_r_b, cD_r_b);
6032 cE = _mm_avg_epu8(cE_r_b, cF_r_b);
6033 c0 = _mm_avg_epu8(c0, c2);
6034 c4 = _mm_avg_epu8(c4, c6);
6035 c8 = _mm_avg_epu8(c8, cA);
6036 cC = _mm_avg_epu8(cC, cE);
6037 c0 = _mm_avg_epu8(c0, c4);
6038 c8 = _mm_avg_epu8(c8, cC);
6039 c0 = _mm_avg_epu8(c0, c8);
6040 c0 = _mm_and_si128(c0, reinterpret_cast<const __m128i&>(r_b));
6041 c1 = _mm_avg_epu16(c0__g_, c1__g_);
6042 c3 = _mm_avg_epu16(c2__g_, c3__g_);
6043 c5 = _mm_avg_epu16(c4__g_, c5__g_);
6044 c7 = _mm_avg_epu16(c6__g_, c7__g_);
6045 c9 = _mm_avg_epu16(c8__g_, c9__g_);
6046 cB = _mm_avg_epu16(cA__g_, cB__g_);
6047 cD = _mm_avg_epu16(cC__g_, cD__g_);
6048 cF = _mm_avg_epu16(cE__g_, cF__g_);
6049 c1 = _mm_avg_epu8(c1, c3);
6050 c5 = _mm_avg_epu8(c5, c7);
6051 c9 = _mm_avg_epu8(c9, cB);
6052 cD = _mm_avg_epu8(cD, cF);
6053 c1 = _mm_avg_epu8(c1, c5);
6054 c9 = _mm_avg_epu8(c9, cD);
6055 c1 = _mm_avg_epu8(c1, c9);
6056 c1 = _mm_and_si128(c1, reinterpret_cast<const __m128i&>(_g_));
6057 c0 = _mm_or_si128(c0, c1);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006058
Nicolas Capens47dc8672017-04-25 12:54:39 -04006059 _mm_store_si128((__m128i*)(source0 + 2 * x), c0);
6060 }
6061
6062 source0 += pitch;
6063 source1 += pitch;
6064 source2 += pitch;
6065 source3 += pitch;
6066 source4 += pitch;
6067 source5 += pitch;
6068 source6 += pitch;
6069 source7 += pitch;
6070 source8 += pitch;
6071 source9 += pitch;
6072 sourceA += pitch;
6073 sourceB += pitch;
6074 sourceC += pitch;
6075 sourceD += pitch;
6076 sourceE += pitch;
6077 sourceF += pitch;
Nicolas Capens0e12a922015-09-04 09:18:15 -04006078 }
Nicolas Capens0e12a922015-09-04 09:18:15 -04006079 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006080 else ASSERT(false);
Nicolas Capens0e12a922015-09-04 09:18:15 -04006081 }
Nicolas Capens47dc8672017-04-25 12:54:39 -04006082 else
6083 #endif
Nicolas Capens0e12a922015-09-04 09:18:15 -04006084 {
6085 #define AVERAGE(x, y) (((x) & (y)) + ((((x) ^ (y)) >> 1) & 0x7BEF) + (((x) ^ (y)) & 0x0821))
6086
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006087 if(internal.samples == 2)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006088 {
6089 for(int y = 0; y < height; y++)
6090 {
6091 for(int x = 0; x < width; x++)
6092 {
6093 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6094 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6095
6096 c0 = AVERAGE(c0, c1);
6097
6098 *(unsigned short*)(source0 + 2 * x) = c0;
6099 }
6100
6101 source0 += pitch;
6102 source1 += pitch;
6103 }
6104 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006105 else if(internal.samples == 4)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006106 {
6107 for(int y = 0; y < height; y++)
6108 {
6109 for(int x = 0; x < width; x++)
6110 {
6111 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6112 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6113 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6114 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6115
6116 c0 = AVERAGE(c0, c1);
6117 c2 = AVERAGE(c2, c3);
6118 c0 = AVERAGE(c0, c2);
6119
6120 *(unsigned short*)(source0 + 2 * x) = c0;
6121 }
6122
6123 source0 += pitch;
6124 source1 += pitch;
6125 source2 += pitch;
6126 source3 += pitch;
6127 }
6128 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006129 else if(internal.samples == 8)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006130 {
6131 for(int y = 0; y < height; y++)
6132 {
6133 for(int x = 0; x < width; x++)
6134 {
6135 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6136 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6137 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6138 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6139 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6140 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6141 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6142 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6143
6144 c0 = AVERAGE(c0, c1);
6145 c2 = AVERAGE(c2, c3);
6146 c4 = AVERAGE(c4, c5);
6147 c6 = AVERAGE(c6, c7);
6148 c0 = AVERAGE(c0, c2);
6149 c4 = AVERAGE(c4, c6);
6150 c0 = AVERAGE(c0, c4);
6151
6152 *(unsigned short*)(source0 + 2 * x) = c0;
6153 }
6154
6155 source0 += pitch;
6156 source1 += pitch;
6157 source2 += pitch;
6158 source3 += pitch;
6159 source4 += pitch;
6160 source5 += pitch;
6161 source6 += pitch;
6162 source7 += pitch;
6163 }
6164 }
Nicolas Capensbfa23b32017-12-11 10:06:37 -05006165 else if(internal.samples == 16)
Nicolas Capens0e12a922015-09-04 09:18:15 -04006166 {
6167 for(int y = 0; y < height; y++)
6168 {
6169 for(int x = 0; x < width; x++)
6170 {
6171 unsigned short c0 = *(unsigned short*)(source0 + 2 * x);
6172 unsigned short c1 = *(unsigned short*)(source1 + 2 * x);
6173 unsigned short c2 = *(unsigned short*)(source2 + 2 * x);
6174 unsigned short c3 = *(unsigned short*)(source3 + 2 * x);
6175 unsigned short c4 = *(unsigned short*)(source4 + 2 * x);
6176 unsigned short c5 = *(unsigned short*)(source5 + 2 * x);
6177 unsigned short c6 = *(unsigned short*)(source6 + 2 * x);
6178 unsigned short c7 = *(unsigned short*)(source7 + 2 * x);
6179 unsigned short c8 = *(unsigned short*)(source8 + 2 * x);
6180 unsigned short c9 = *(unsigned short*)(source9 + 2 * x);
6181 unsigned short cA = *(unsigned short*)(sourceA + 2 * x);
6182 unsigned short cB = *(unsigned short*)(sourceB + 2 * x);
6183 unsigned short cC = *(unsigned short*)(sourceC + 2 * x);
6184 unsigned short cD = *(unsigned short*)(sourceD + 2 * x);
6185 unsigned short cE = *(unsigned short*)(sourceE + 2 * x);
6186 unsigned short cF = *(unsigned short*)(sourceF + 2 * x);
6187
6188 c0 = AVERAGE(c0, c1);
6189 c2 = AVERAGE(c2, c3);
6190 c4 = AVERAGE(c4, c5);
6191 c6 = AVERAGE(c6, c7);
6192 c8 = AVERAGE(c8, c9);
6193 cA = AVERAGE(cA, cB);
6194 cC = AVERAGE(cC, cD);
6195 cE = AVERAGE(cE, cF);
6196 c0 = AVERAGE(c0, c2);
6197 c4 = AVERAGE(c4, c6);
6198 c8 = AVERAGE(c8, cA);
6199 cC = AVERAGE(cC, cE);
6200 c0 = AVERAGE(c0, c4);
6201 c8 = AVERAGE(c8, cC);
6202 c0 = AVERAGE(c0, c8);
6203
6204 *(unsigned short*)(source0 + 2 * x) = c0;
6205 }
6206
6207 source0 += pitch;
6208 source1 += pitch;
6209 source2 += pitch;
6210 source3 += pitch;
6211 source4 += pitch;
6212 source5 += pitch;
6213 source6 += pitch;
6214 source7 += pitch;
6215 source8 += pitch;
6216 source9 += pitch;
6217 sourceA += pitch;
6218 sourceB += pitch;
6219 sourceC += pitch;
6220 sourceD += pitch;
6221 sourceE += pitch;
6222 sourceF += pitch;
6223 }
6224 }
6225 else ASSERT(false);
6226
6227 #undef AVERAGE
6228 }
6229 }
John Bauman89401822014-05-06 15:04:28 -04006230 else
6231 {
6232 // UNIMPLEMENTED();
6233 }
6234 }
6235}