blob: 93b3731b4960e330a25a1a22d07347647ffd0e1c [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 "Sampler.hpp"
16
John Bauman89401822014-05-06 15:04:28 -040017#include "Context.hpp"
18#include "Surface.hpp"
19#include "CPUID.hpp"
20#include "PixelRoutine.hpp"
21#include "Debug.hpp"
22
23#include <memory.h>
24#include <string.h>
25
26namespace sw
27{
28 FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
29 MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
30
31 Sampler::State::State()
32 {
33 memset(this, 0, sizeof(State));
34 }
35
36 Sampler::Sampler()
37 {
38 // FIXME: Mipmap::init
Nicolas Capens8e8a7e82015-09-01 14:39:57 -040039 static const unsigned int zero = 0x00FF00FF;
John Bauman89401822014-05-06 15:04:28 -040040
41 for(int level = 0; level < MIPMAP_LEVELS; level++)
42 {
43 Mipmap &mipmap = texture.mipmap[level];
44
45 memset(&mipmap, 0, sizeof(Mipmap));
46
Nicolas Capens7bb62682016-02-08 11:30:56 -050047 for(int face = 0; face < 6; face++)
John Bauman89401822014-05-06 15:04:28 -040048 {
49 mipmap.buffer[face] = &zero;
50 }
John Bauman89401822014-05-06 15:04:28 -040051 }
52
53 externalTextureFormat = FORMAT_NULL;
54 internalTextureFormat = FORMAT_NULL;
55 textureType = TEXTURE_NULL;
56
57 textureFilter = FILTER_LINEAR;
58 addressingModeU = ADDRESSING_WRAP;
59 addressingModeV = ADDRESSING_WRAP;
60 addressingModeW = ADDRESSING_WRAP;
61 mipmapFilterState = MIPMAP_NONE;
62 sRGB = false;
63 gather = false;
64
Alexis Hetu43da5682015-10-21 15:36:50 -040065 swizzleR = SWIZZLE_RED;
66 swizzleG = SWIZZLE_GREEN;
67 swizzleB = SWIZZLE_BLUE;
68 swizzleA = SWIZZLE_ALPHA;
69
John Bauman89401822014-05-06 15:04:28 -040070 texture.LOD = 0.0f;
71 exp2LOD = 1.0f;
Alexis Hetu112d81f2016-06-07 12:36:35 -040072
73 texture.baseLevel = 0;
74 texture.maxLevel = 1000;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -040075 texture.maxLod = MIPMAP_LEVELS - 2; // Trilinear accesses lod+1
76 texture.minLod = 0;
John Bauman89401822014-05-06 15:04:28 -040077 }
78
79 Sampler::~Sampler()
80 {
81 }
82
83 Sampler::State Sampler::samplerState() const
84 {
85 State state;
86
87 if(textureType != TEXTURE_NULL)
88 {
89 state.textureType = textureType;
90 state.textureFormat = internalTextureFormat;
91 state.textureFilter = getTextureFilter();
92 state.addressingModeU = getAddressingModeU();
93 state.addressingModeV = getAddressingModeV();
94 state.addressingModeW = getAddressingModeW();
95 state.mipmapFilter = mipmapFilter();
John Bauman89401822014-05-06 15:04:28 -040096 state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat);
Alexis Hetu1d01aa32015-09-29 11:50:05 -040097 state.swizzleR = swizzleR;
98 state.swizzleG = swizzleG;
99 state.swizzleB = swizzleB;
100 state.swizzleA = swizzleA;
John Bauman89401822014-05-06 15:04:28 -0400101
102 #if PERF_PROFILE
103 state.compressedFormat = Surface::isCompressed(externalTextureFormat);
104 #endif
105 }
106
107 return state;
108 }
109
110 void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type)
111 {
112 if(surface)
113 {
114 Mipmap &mipmap = texture.mipmap[level];
115
116 mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE);
117
118 if(face == 0)
119 {
120 externalTextureFormat = surface->getExternalFormat();
121 internalTextureFormat = surface->getInternalFormat();
122
Nicolas Capens3779ea92015-06-10 13:43:52 -0400123 int width = surface->getWidth();
124 int height = surface->getHeight();
125 int depth = surface->getDepth();
John Bauman89401822014-05-06 15:04:28 -0400126 int pitchP = surface->getInternalPitchP();
127 int sliceP = surface->getInternalSliceP();
128
129 int logWidth = log2(width);
130 int logHeight = log2(height);
131 int logDepth = log2(depth);
132
133 if(level == 0)
134 {
135 texture.widthHeightLOD[0] = width * exp2LOD;
136 texture.widthHeightLOD[1] = width * exp2LOD;
137 texture.widthHeightLOD[2] = height * exp2LOD;
138 texture.widthHeightLOD[3] = height * exp2LOD;
139
140 texture.widthLOD[0] = width * exp2LOD;
141 texture.widthLOD[1] = width * exp2LOD;
142 texture.widthLOD[2] = width * exp2LOD;
143 texture.widthLOD[3] = width * exp2LOD;
144
145 texture.heightLOD[0] = height * exp2LOD;
146 texture.heightLOD[1] = height * exp2LOD;
147 texture.heightLOD[2] = height * exp2LOD;
148 texture.heightLOD[3] = height * exp2LOD;
149
150 texture.depthLOD[0] = depth * exp2LOD;
151 texture.depthLOD[1] = depth * exp2LOD;
152 texture.depthLOD[2] = depth * exp2LOD;
153 texture.depthLOD[3] = depth * exp2LOD;
154 }
155
Nicolas Capens77980512016-12-02 14:22:32 -0500156 if(Surface::isFloatFormat(internalTextureFormat))
John Bauman89401822014-05-06 15:04:28 -0400157 {
158 mipmap.fWidth[0] = (float)width / 65536.0f;
159 mipmap.fWidth[1] = (float)width / 65536.0f;
160 mipmap.fWidth[2] = (float)width / 65536.0f;
161 mipmap.fWidth[3] = (float)width / 65536.0f;
162
163 mipmap.fHeight[0] = (float)height / 65536.0f;
164 mipmap.fHeight[1] = (float)height / 65536.0f;
165 mipmap.fHeight[2] = (float)height / 65536.0f;
166 mipmap.fHeight[3] = (float)height / 65536.0f;
167
168 mipmap.fDepth[0] = (float)depth / 65536.0f;
169 mipmap.fDepth[1] = (float)depth / 65536.0f;
170 mipmap.fDepth[2] = (float)depth / 65536.0f;
171 mipmap.fDepth[3] = (float)depth / 65536.0f;
172 }
173
Nicolas Capensadb305a2016-04-21 13:59:20 -0400174 short halfTexelU = 0x8000 / width;
175 short halfTexelV = 0x8000 / height;
176 short halfTexelW = 0x8000 / depth;
John Bauman89401822014-05-06 15:04:28 -0400177
178 mipmap.uHalf[0] = halfTexelU;
179 mipmap.uHalf[1] = halfTexelU;
180 mipmap.uHalf[2] = halfTexelU;
181 mipmap.uHalf[3] = halfTexelU;
182
183 mipmap.vHalf[0] = halfTexelV;
184 mipmap.vHalf[1] = halfTexelV;
185 mipmap.vHalf[2] = halfTexelV;
186 mipmap.vHalf[3] = halfTexelV;
187
188 mipmap.wHalf[0] = halfTexelW;
189 mipmap.wHalf[1] = halfTexelW;
190 mipmap.wHalf[2] = halfTexelW;
191 mipmap.wHalf[3] = halfTexelW;
192
193 mipmap.width[0] = width;
194 mipmap.width[1] = width;
195 mipmap.width[2] = width;
196 mipmap.width[3] = width;
197
198 mipmap.height[0] = height;
199 mipmap.height[1] = height;
200 mipmap.height[2] = height;
201 mipmap.height[3] = height;
202
203 mipmap.depth[0] = depth;
204 mipmap.depth[1] = depth;
205 mipmap.depth[2] = depth;
206 mipmap.depth[3] = depth;
207
208 mipmap.onePitchP[0] = 1;
209 mipmap.onePitchP[1] = pitchP;
210 mipmap.onePitchP[2] = 1;
211 mipmap.onePitchP[3] = pitchP;
212
213 mipmap.sliceP[0] = sliceP;
214 mipmap.sliceP[1] = sliceP;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -0400215
216 if(internalTextureFormat == FORMAT_YV12_BT601 ||
217 internalTextureFormat == FORMAT_YV12_BT709 ||
218 internalTextureFormat == FORMAT_YV12_JFIF)
219 {
Nicolas Capens6ee16a12015-11-19 22:58:29 -0500220 unsigned int YStride = pitchP;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -0400221 unsigned int YSize = YStride * height;
222 unsigned int CStride = align(YStride / 2, 16);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400223 unsigned int CSize = CStride * height / 2;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -0400224
225 mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize;
226 mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize;
227
Nicolas Capens8e8a7e82015-09-01 14:39:57 -0400228 texture.mipmap[1].width[0] = width / 2;
229 texture.mipmap[1].width[1] = width / 2;
230 texture.mipmap[1].width[2] = width / 2;
231 texture.mipmap[1].width[3] = width / 2;
232 texture.mipmap[1].height[0] = height / 2;
233 texture.mipmap[1].height[1] = height / 2;
234 texture.mipmap[1].height[2] = height / 2;
235 texture.mipmap[1].height[3] = height / 2;
236 texture.mipmap[1].onePitchP[0] = 1;
237 texture.mipmap[1].onePitchP[1] = CStride;
238 texture.mipmap[1].onePitchP[2] = 1;
239 texture.mipmap[1].onePitchP[3] = CStride;
240 }
John Bauman89401822014-05-06 15:04:28 -0400241 }
242 }
243
244 textureType = type;
245 }
246
247 void Sampler::setTextureFilter(FilterType textureFilter)
248 {
249 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
250 }
251
252 void Sampler::setMipmapFilter(MipmapType mipmapFilter)
253 {
254 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
255 }
256
257 void Sampler::setGatherEnable(bool enable)
258 {
259 gather = enable;
260 }
261
262 void Sampler::setAddressingModeU(AddressingMode addressingMode)
263 {
264 addressingModeU = addressingMode;
265 }
266
267 void Sampler::setAddressingModeV(AddressingMode addressingMode)
268 {
269 addressingModeV = addressingMode;
270 }
271
272 void Sampler::setAddressingModeW(AddressingMode addressingMode)
273 {
274 addressingModeW = addressingMode;
275 }
276
277 void Sampler::setReadSRGB(bool sRGB)
278 {
279 this->sRGB = sRGB;
280 }
281
282 void Sampler::setBorderColor(const Color<float> &borderColor)
283 {
284 // FIXME: Compact into generic function // FIXME: Clamp
285 short r = iround(0xFFFF * borderColor.r);
286 short g = iround(0xFFFF * borderColor.g);
287 short b = iround(0xFFFF * borderColor.b);
288 short a = iround(0xFFFF * borderColor.a);
289
290 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r;
291 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g;
292 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b;
293 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a;
294
295 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r;
296 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g;
297 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b;
298 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a;
299 }
300
Alexis Hetu617a5d52014-11-13 10:56:20 -0500301 void Sampler::setMaxAnisotropy(float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -0400302 {
Alexis Hetu617a5d52014-11-13 10:56:20 -0500303 texture.maxAnisotropy = maxAnisotropy;
John Bauman89401822014-05-06 15:04:28 -0400304 }
305
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400306 void Sampler::setSwizzleR(SwizzleType swizzleR)
307 {
308 this->swizzleR = swizzleR;
309 }
Nicolas Capens7bb62682016-02-08 11:30:56 -0500310
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400311 void Sampler::setSwizzleG(SwizzleType swizzleG)
312 {
313 this->swizzleG = swizzleG;
314 }
315
316 void Sampler::setSwizzleB(SwizzleType swizzleB)
317 {
318 this->swizzleB = swizzleB;
319 }
320
321 void Sampler::setSwizzleA(SwizzleType swizzleA)
322 {
323 this->swizzleA = swizzleA;
324 }
325
Alexis Hetu95ac1872016-06-06 13:26:52 -0400326 void Sampler::setBaseLevel(int baseLevel)
327 {
328 texture.baseLevel = baseLevel;
329 }
330
331 void Sampler::setMaxLevel(int maxLevel)
332 {
333 texture.maxLevel = maxLevel;
334 }
335
Alexis Hetu112d81f2016-06-07 12:36:35 -0400336 void Sampler::setMinLod(float minLod)
337 {
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400338 texture.minLod = clamp(minLod, 0.0f, (float)(MIPMAP_LEVELS - 2));
Alexis Hetu112d81f2016-06-07 12:36:35 -0400339 }
340
341 void Sampler::setMaxLod(float maxLod)
342 {
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400343 texture.maxLod = clamp(maxLod, 0.0f, (float)(MIPMAP_LEVELS - 2));
Alexis Hetu112d81f2016-06-07 12:36:35 -0400344 }
345
John Bauman89401822014-05-06 15:04:28 -0400346 void Sampler::setFilterQuality(FilterType maximumFilterQuality)
347 {
348 Sampler::maximumTextureFilterQuality = maximumFilterQuality;
349 }
350
351 void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
352 {
353 Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
354 }
355
356 void Sampler::setMipmapLOD(float LOD)
357 {
358 texture.LOD = LOD;
359 exp2LOD = exp2(LOD);
360 }
361
362 bool Sampler::hasTexture() const
363 {
364 return textureType != TEXTURE_NULL;
365 }
366
367 bool Sampler::hasUnsignedTexture() const
368 {
369 return Surface::isUnsignedComponent(internalTextureFormat, 0) &&
370 Surface::isUnsignedComponent(internalTextureFormat, 1) &&
Nicolas Capens0bac2852016-05-07 06:09:58 -0400371 Surface::isUnsignedComponent(internalTextureFormat, 2) &&
372 Surface::isUnsignedComponent(internalTextureFormat, 3);
John Bauman89401822014-05-06 15:04:28 -0400373 }
374
375 bool Sampler::hasCubeTexture() const
376 {
377 return textureType == TEXTURE_CUBE;
378 }
379
380 bool Sampler::hasVolumeTexture() const
381 {
Alexis Hetuf15e8942015-12-01 15:13:23 -0500382 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
John Bauman89401822014-05-06 15:04:28 -0400383 }
384
385 const Texture &Sampler::getTextureData()
386 {
387 return texture;
388 }
389
390 MipmapType Sampler::mipmapFilter() const
391 {
392 if(mipmapFilterState != MIPMAP_NONE)
393 {
394 for(int i = 1; i < MIPMAP_LEVELS; i++)
395 {
396 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
397 {
398 return mipmapFilterState;
399 }
400 }
401 }
402
403 // Only one mipmap level
404 return MIPMAP_NONE;
405 }
406
John Bauman89401822014-05-06 15:04:28 -0400407 TextureType Sampler::getTextureType() const
408 {
409 return textureType;
410 }
411
412 FilterType Sampler::getTextureFilter() const
413 {
414 FilterType filter = textureFilter;
415
416 if(gather && Surface::componentCount(internalTextureFormat) == 1)
417 {
418 filter = FILTER_GATHER;
419 }
420
421 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
422 {
423 return (FilterType)min(filter, FILTER_LINEAR);
424 }
425
426 return filter;
427 }
428
429 AddressingMode Sampler::getAddressingModeU() const
430 {
431 if(hasCubeTexture())
432 {
433 return ADDRESSING_CLAMP;
434 }
435
436 return addressingModeU;
437 }
438
439 AddressingMode Sampler::getAddressingModeV() const
440 {
441 if(hasCubeTexture())
442 {
443 return ADDRESSING_CLAMP;
444 }
445
446 return addressingModeV;
447 }
448
449 AddressingMode Sampler::getAddressingModeW() const
450 {
451 if(hasCubeTexture())
452 {
453 return ADDRESSING_CLAMP;
454 }
455
Nicolas Capens7bb62682016-02-08 11:30:56 -0500456 if(textureType == TEXTURE_2D_ARRAY || textureType == TEXTURE_2D)
457 {
458 return ADDRESSING_LAYER;
459 }
460
John Bauman89401822014-05-06 15:04:28 -0400461 return addressingModeW;
462 }
463}