1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// 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
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// 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.
14
15#include "Sampler.hpp"
16
17#include "Context.hpp"
18#include "Surface.hpp"
19#include "Shader/PixelRoutine.hpp"
20#include "Common/Debug.hpp"
21
22#include <memory.h>
23#include <string.h>
24
25namespace sw
26{
27 FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
28 MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
29
30 Sampler::State::State()
31 {
32 memset(this, 0, sizeof(State));
33 }
34
35 Sampler::Sampler()
36 {
37 // FIXME: Mipmap::init
38 static const unsigned int zero = 0x00FF00FF;
39
40 for(int level = 0; level < MIPMAP_LEVELS; level++)
41 {
42 Mipmap &mipmap = texture.mipmap[level];
43
44 memset(&mipmap, 0, sizeof(Mipmap));
45
46 for(int face = 0; face < 6; face++)
47 {
48 mipmap.buffer[face] = &zero;
49 }
50 }
51
52 externalTextureFormat = FORMAT_NULL;
53 internalTextureFormat = FORMAT_NULL;
54 textureType = TEXTURE_NULL;
55
56 textureFilter = FILTER_LINEAR;
57 addressingModeU = ADDRESSING_WRAP;
58 addressingModeV = ADDRESSING_WRAP;
59 addressingModeW = ADDRESSING_WRAP;
60 mipmapFilterState = MIPMAP_NONE;
61 sRGB = false;
62 gather = false;
63 highPrecisionFiltering = false;
64 border = 0;
65
66 swizzleR = SWIZZLE_RED;
67 swizzleG = SWIZZLE_GREEN;
68 swizzleB = SWIZZLE_BLUE;
69 swizzleA = SWIZZLE_ALPHA;
70
71 compare = COMPARE_BYPASS;
72
73 texture.LOD = 0.0f;
74 exp2LOD = 1.0f;
75
76 texture.baseLevel = 0;
77 texture.maxLevel = 1000;
78 texture.maxLod = MAX_TEXTURE_LOD;
79 texture.minLod = 0;
80 }
81
82 Sampler::~Sampler()
83 {
84 }
85
86 Sampler::State Sampler::samplerState() const
87 {
88 State state;
89
90 if(textureType != TEXTURE_NULL)
91 {
92 state.textureType = textureType;
93 state.textureFormat = internalTextureFormat;
94 state.textureFilter = getTextureFilter();
95 state.addressingModeU = getAddressingModeU();
96 state.addressingModeV = getAddressingModeV();
97 state.addressingModeW = getAddressingModeW();
98 state.mipmapFilter = mipmapFilter();
99 state.sRGB = (sRGB && Surface::isSRGBreadable(externalTextureFormat)) || Surface::isSRGBformat(internalTextureFormat);
100 state.swizzleR = swizzleR;
101 state.swizzleG = swizzleG;
102 state.swizzleB = swizzleB;
103 state.swizzleA = swizzleA;
104 state.highPrecisionFiltering = highPrecisionFiltering;
105 state.compare = getCompareFunc();
106
107 #if PERF_PROFILE
108 state.compressedFormat = Surface::isCompressed(externalTextureFormat);
109 #endif
110 }
111
112 return state;
113 }
114
115 void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type)
116 {
117 if(surface)
118 {
119 Mipmap &mipmap = texture.mipmap[level];
120
121 border = surface->getBorder();
122 mipmap.buffer[face] = surface->lockInternal(-border, -border, 0, LOCK_UNLOCKED, PRIVATE);
123
124 if(face == 0)
125 {
126 externalTextureFormat = surface->getExternalFormat();
127 internalTextureFormat = surface->getInternalFormat();
128
129 int width = surface->getWidth();
130 int height = surface->getHeight();
131 int depth = surface->getDepth();
132 int pitchP = surface->getInternalPitchP();
133 int sliceP = surface->getInternalSliceP();
134
135 if(level == 0)
136 {
137 texture.widthHeightLOD[0] = width * exp2LOD;
138 texture.widthHeightLOD[1] = width * exp2LOD;
139 texture.widthHeightLOD[2] = height * exp2LOD;
140 texture.widthHeightLOD[3] = height * exp2LOD;
141
142 texture.widthLOD[0] = width * exp2LOD;
143 texture.widthLOD[1] = width * exp2LOD;
144 texture.widthLOD[2] = width * exp2LOD;
145 texture.widthLOD[3] = width * exp2LOD;
146
147 texture.heightLOD[0] = height * exp2LOD;
148 texture.heightLOD[1] = height * exp2LOD;
149 texture.heightLOD[2] = height * exp2LOD;
150 texture.heightLOD[3] = height * exp2LOD;
151
152 texture.depthLOD[0] = depth * exp2LOD;
153 texture.depthLOD[1] = depth * exp2LOD;
154 texture.depthLOD[2] = depth * exp2LOD;
155 texture.depthLOD[3] = depth * exp2LOD;
156 }
157
158 if(Surface::isFloatFormat(internalTextureFormat))
159 {
160 mipmap.fWidth[0] = (float)width / 65536.0f;
161 mipmap.fWidth[1] = (float)width / 65536.0f;
162 mipmap.fWidth[2] = (float)width / 65536.0f;
163 mipmap.fWidth[3] = (float)width / 65536.0f;
164
165 mipmap.fHeight[0] = (float)height / 65536.0f;
166 mipmap.fHeight[1] = (float)height / 65536.0f;
167 mipmap.fHeight[2] = (float)height / 65536.0f;
168 mipmap.fHeight[3] = (float)height / 65536.0f;
169
170 mipmap.fDepth[0] = (float)depth / 65536.0f;
171 mipmap.fDepth[1] = (float)depth / 65536.0f;
172 mipmap.fDepth[2] = (float)depth / 65536.0f;
173 mipmap.fDepth[3] = (float)depth / 65536.0f;
174 }
175
176 short halfTexelU = 0x8000 / width;
177 short halfTexelV = 0x8000 / height;
178 short halfTexelW = 0x8000 / depth;
179
180 mipmap.uHalf[0] = halfTexelU;
181 mipmap.uHalf[1] = halfTexelU;
182 mipmap.uHalf[2] = halfTexelU;
183 mipmap.uHalf[3] = halfTexelU;
184
185 mipmap.vHalf[0] = halfTexelV;
186 mipmap.vHalf[1] = halfTexelV;
187 mipmap.vHalf[2] = halfTexelV;
188 mipmap.vHalf[3] = halfTexelV;
189
190 mipmap.wHalf[0] = halfTexelW;
191 mipmap.wHalf[1] = halfTexelW;
192 mipmap.wHalf[2] = halfTexelW;
193 mipmap.wHalf[3] = halfTexelW;
194
195 mipmap.width[0] = width;
196 mipmap.width[1] = width;
197 mipmap.width[2] = width;
198 mipmap.width[3] = width;
199
200 mipmap.height[0] = height;
201 mipmap.height[1] = height;
202 mipmap.height[2] = height;
203 mipmap.height[3] = height;
204
205 mipmap.depth[0] = depth;
206 mipmap.depth[1] = depth;
207 mipmap.depth[2] = depth;
208 mipmap.depth[3] = depth;
209
210 mipmap.onePitchP[0] = 1;
211 mipmap.onePitchP[1] = pitchP;
212 mipmap.onePitchP[2] = 1;
213 mipmap.onePitchP[3] = pitchP;
214
215 mipmap.pitchP[0] = pitchP;
216 mipmap.pitchP[1] = pitchP;
217 mipmap.pitchP[2] = pitchP;
218 mipmap.pitchP[3] = pitchP;
219
220 mipmap.sliceP[0] = sliceP;
221 mipmap.sliceP[1] = sliceP;
222 mipmap.sliceP[2] = sliceP;
223 mipmap.sliceP[3] = sliceP;
224
225 if(internalTextureFormat == FORMAT_YV12_BT601 ||
226 internalTextureFormat == FORMAT_YV12_BT709 ||
227 internalTextureFormat == FORMAT_YV12_JFIF)
228 {
229 unsigned int YStride = pitchP;
230 unsigned int YSize = YStride * height;
231 unsigned int CStride = align<16>(YStride / 2);
232 unsigned int CSize = CStride * height / 2;
233
234 mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize;
235 mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize;
236
237 texture.mipmap[1].width[0] = width / 2;
238 texture.mipmap[1].width[1] = width / 2;
239 texture.mipmap[1].width[2] = width / 2;
240 texture.mipmap[1].width[3] = width / 2;
241 texture.mipmap[1].height[0] = height / 2;
242 texture.mipmap[1].height[1] = height / 2;
243 texture.mipmap[1].height[2] = height / 2;
244 texture.mipmap[1].height[3] = height / 2;
245 texture.mipmap[1].onePitchP[0] = 1;
246 texture.mipmap[1].onePitchP[1] = CStride;
247 texture.mipmap[1].onePitchP[2] = 1;
248 texture.mipmap[1].onePitchP[3] = CStride;
249 }
250 }
251 }
252
253 textureType = type;
254 }
255
256 void Sampler::setTextureFilter(FilterType textureFilter)
257 {
258 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
259 }
260
261 void Sampler::setMipmapFilter(MipmapType mipmapFilter)
262 {
263 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
264 }
265
266 void Sampler::setGatherEnable(bool enable)
267 {
268 gather = enable;
269 }
270
271 void Sampler::setAddressingModeU(AddressingMode addressingMode)
272 {
273 addressingModeU = addressingMode;
274 }
275
276 void Sampler::setAddressingModeV(AddressingMode addressingMode)
277 {
278 addressingModeV = addressingMode;
279 }
280
281 void Sampler::setAddressingModeW(AddressingMode addressingMode)
282 {
283 addressingModeW = addressingMode;
284 }
285
286 void Sampler::setReadSRGB(bool sRGB)
287 {
288 this->sRGB = sRGB;
289 }
290
291 void Sampler::setBorderColor(const Color<float> &borderColor)
292 {
293 // FIXME: Compact into generic function // FIXME: Clamp
294 short r = iround(0xFFFF * borderColor.r);
295 short g = iround(0xFFFF * borderColor.g);
296 short b = iround(0xFFFF * borderColor.b);
297 short a = iround(0xFFFF * borderColor.a);
298
299 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r;
300 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g;
301 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b;
302 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a;
303
304 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r;
305 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g;
306 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b;
307 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a;
308 }
309
310 void Sampler::setMaxAnisotropy(float maxAnisotropy)
311 {
312 texture.maxAnisotropy = maxAnisotropy;
313 }
314
315 void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering)
316 {
317 this->highPrecisionFiltering = highPrecisionFiltering;
318 }
319
320 void Sampler::setSwizzleR(SwizzleType swizzleR)
321 {
322 this->swizzleR = swizzleR;
323 }
324
325 void Sampler::setSwizzleG(SwizzleType swizzleG)
326 {
327 this->swizzleG = swizzleG;
328 }
329
330 void Sampler::setSwizzleB(SwizzleType swizzleB)
331 {
332 this->swizzleB = swizzleB;
333 }
334
335 void Sampler::setSwizzleA(SwizzleType swizzleA)
336 {
337 this->swizzleA = swizzleA;
338 }
339
340 void Sampler::setCompareFunc(CompareFunc compare)
341 {
342 this->compare = compare;
343 }
344
345 void Sampler::setBaseLevel(int baseLevel)
346 {
347 texture.baseLevel = baseLevel;
348 }
349
350 void Sampler::setMaxLevel(int maxLevel)
351 {
352 texture.maxLevel = maxLevel;
353 }
354
355 void Sampler::setMinLod(float minLod)
356 {
357 texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD));
358 }
359
360 void Sampler::setMaxLod(float maxLod)
361 {
362 texture.maxLod = clamp(maxLod, 0.0f, (float)(MAX_TEXTURE_LOD));
363 }
364
365 void Sampler::setFilterQuality(FilterType maximumFilterQuality)
366 {
367 Sampler::maximumTextureFilterQuality = maximumFilterQuality;
368 }
369
370 void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
371 {
372 Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
373 }
374
375 void Sampler::setMipmapLOD(float LOD)
376 {
377 texture.LOD = LOD;
378 exp2LOD = exp2(LOD);
379 }
380
381 bool Sampler::hasTexture() const
382 {
383 return textureType != TEXTURE_NULL;
384 }
385
386 bool Sampler::hasUnsignedTexture() const
387 {
388 return Surface::isUnsignedComponent(internalTextureFormat, 0) &&
389 Surface::isUnsignedComponent(internalTextureFormat, 1) &&
390 Surface::isUnsignedComponent(internalTextureFormat, 2) &&
391 Surface::isUnsignedComponent(internalTextureFormat, 3);
392 }
393
394 bool Sampler::hasCubeTexture() const
395 {
396 return textureType == TEXTURE_CUBE;
397 }
398
399 bool Sampler::hasVolumeTexture() const
400 {
401 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
402 }
403
404 void Sampler::setSyncRequired(bool isSyncRequired)
405 {
406 syncRequired = isSyncRequired;
407 }
408
409 bool Sampler::requiresSync() const
410 {
411 return syncRequired;
412 }
413
414 const Texture &Sampler::getTextureData()
415 {
416 return texture;
417 }
418
419 MipmapType Sampler::mipmapFilter() const
420 {
421 if(mipmapFilterState != MIPMAP_NONE)
422 {
423 for(int i = 1; i < MIPMAP_LEVELS; i++)
424 {
425 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
426 {
427 return mipmapFilterState;
428 }
429 }
430 }
431
432 // Only one mipmap level
433 return MIPMAP_NONE;
434 }
435
436 TextureType Sampler::getTextureType() const
437 {
438 return textureType;
439 }
440
441 FilterType Sampler::getTextureFilter() const
442 {
443 // Don't filter 1x1 textures.
444 if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1)
445 {
446 if(mipmapFilter() == MIPMAP_NONE)
447 {
448 return FILTER_POINT;
449 }
450 }
451
452 FilterType filter = textureFilter;
453
454 if(gather && Surface::componentCount(internalTextureFormat) == 1)
455 {
456 filter = FILTER_GATHER;
457 }
458
459 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
460 {
461 return (FilterType)min(filter, FILTER_LINEAR);
462 }
463
464 return filter;
465 }
466
467 AddressingMode Sampler::getAddressingModeU() const
468 {
469 if(textureType == TEXTURE_CUBE)
470 {
471 return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
472 }
473
474 return addressingModeU;
475 }
476
477 AddressingMode Sampler::getAddressingModeV() const
478 {
479 if(textureType == TEXTURE_CUBE)
480 {
481 return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
482 }
483
484 return addressingModeV;
485 }
486
487 AddressingMode Sampler::getAddressingModeW() const
488 {
489 if(textureType == TEXTURE_2D_ARRAY ||
490 textureType == TEXTURE_2D ||
491 textureType == TEXTURE_CUBE ||
492 textureType == TEXTURE_RECTANGLE)
493 {
494 return ADDRESSING_LAYER;
495 }
496
497 return addressingModeW;
498 }
499
500 CompareFunc Sampler::getCompareFunc() const
501 {
502 if(getTextureFilter() == FILTER_GATHER)
503 {
504 return COMPARE_BYPASS;
505 }
506
507 if(internalTextureFormat == FORMAT_D32FS8_SHADOW)
508 {
509 return COMPARE_LESSEQUAL;
510 }
511
512 return compare;
513 }
514}
515