• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 namespace sw
26 {
27 	FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
28 	MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
29 
State()30 	Sampler::State::State()
31 	{
32 		memset(this, 0, sizeof(State));
33 	}
34 
Sampler()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 
~Sampler()82 	Sampler::~Sampler()
83 	{
84 	}
85 
samplerState() const86 	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 
setTextureLevel(int face,int level,Surface * surface,TextureType type)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 
setTextureFilter(FilterType textureFilter)256 	void Sampler::setTextureFilter(FilterType textureFilter)
257 	{
258 		this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
259 	}
260 
setMipmapFilter(MipmapType mipmapFilter)261 	void Sampler::setMipmapFilter(MipmapType mipmapFilter)
262 	{
263 		mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
264 	}
265 
setGatherEnable(bool enable)266 	void Sampler::setGatherEnable(bool enable)
267 	{
268 		gather = enable;
269 	}
270 
setAddressingModeU(AddressingMode addressingMode)271 	void Sampler::setAddressingModeU(AddressingMode addressingMode)
272 	{
273 		addressingModeU = addressingMode;
274 	}
275 
setAddressingModeV(AddressingMode addressingMode)276 	void Sampler::setAddressingModeV(AddressingMode addressingMode)
277 	{
278 		addressingModeV = addressingMode;
279 	}
280 
setAddressingModeW(AddressingMode addressingMode)281 	void Sampler::setAddressingModeW(AddressingMode addressingMode)
282 	{
283 		addressingModeW = addressingMode;
284 	}
285 
setReadSRGB(bool sRGB)286 	void Sampler::setReadSRGB(bool sRGB)
287 	{
288 		this->sRGB = sRGB;
289 	}
290 
setBorderColor(const Color<float> & borderColor)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 
setMaxAnisotropy(float maxAnisotropy)310 	void Sampler::setMaxAnisotropy(float maxAnisotropy)
311 	{
312 		texture.maxAnisotropy = maxAnisotropy;
313 	}
314 
setHighPrecisionFiltering(bool highPrecisionFiltering)315 	void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering)
316 	{
317 		this->highPrecisionFiltering = highPrecisionFiltering;
318 	}
319 
setSwizzleR(SwizzleType swizzleR)320 	void Sampler::setSwizzleR(SwizzleType swizzleR)
321 	{
322 		this->swizzleR = swizzleR;
323 	}
324 
setSwizzleG(SwizzleType swizzleG)325 	void Sampler::setSwizzleG(SwizzleType swizzleG)
326 	{
327 		this->swizzleG = swizzleG;
328 	}
329 
setSwizzleB(SwizzleType swizzleB)330 	void Sampler::setSwizzleB(SwizzleType swizzleB)
331 	{
332 		this->swizzleB = swizzleB;
333 	}
334 
setSwizzleA(SwizzleType swizzleA)335 	void Sampler::setSwizzleA(SwizzleType swizzleA)
336 	{
337 		this->swizzleA = swizzleA;
338 	}
339 
setCompareFunc(CompareFunc compare)340 	void Sampler::setCompareFunc(CompareFunc compare)
341 	{
342 		this->compare = compare;
343 	}
344 
setBaseLevel(int baseLevel)345 	void Sampler::setBaseLevel(int baseLevel)
346 	{
347 		texture.baseLevel = baseLevel;
348 	}
349 
setMaxLevel(int maxLevel)350 	void Sampler::setMaxLevel(int maxLevel)
351 	{
352 		texture.maxLevel = maxLevel;
353 	}
354 
setMinLod(float minLod)355 	void Sampler::setMinLod(float minLod)
356 	{
357 		texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD));
358 	}
359 
setMaxLod(float maxLod)360 	void Sampler::setMaxLod(float maxLod)
361 	{
362 		texture.maxLod = clamp(maxLod, 0.0f, (float)(MAX_TEXTURE_LOD));
363 	}
364 
setFilterQuality(FilterType maximumFilterQuality)365 	void Sampler::setFilterQuality(FilterType maximumFilterQuality)
366 	{
367 		Sampler::maximumTextureFilterQuality = maximumFilterQuality;
368 	}
369 
setMipmapQuality(MipmapType maximumFilterQuality)370 	void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
371 	{
372 		Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
373 	}
374 
setMipmapLOD(float LOD)375 	void Sampler::setMipmapLOD(float LOD)
376 	{
377 		texture.LOD = LOD;
378 		exp2LOD = exp2(LOD);
379 	}
380 
hasTexture() const381 	bool Sampler::hasTexture() const
382 	{
383 		return textureType != TEXTURE_NULL;
384 	}
385 
hasUnsignedTexture() const386 	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 
hasCubeTexture() const394 	bool Sampler::hasCubeTexture() const
395 	{
396 		return textureType == TEXTURE_CUBE;
397 	}
398 
hasVolumeTexture() const399 	bool Sampler::hasVolumeTexture() const
400 	{
401 		return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
402 	}
403 
setSyncRequired(bool isSyncRequired)404 	void Sampler::setSyncRequired(bool isSyncRequired)
405 	{
406 		syncRequired = isSyncRequired;
407 	}
408 
requiresSync() const409 	bool Sampler::requiresSync() const
410 	{
411 		return syncRequired;
412 	}
413 
getTextureData()414 	const Texture &Sampler::getTextureData()
415 	{
416 		return texture;
417 	}
418 
mipmapFilter() const419 	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 
getTextureType() const436 	TextureType Sampler::getTextureType() const
437 	{
438 		return textureType;
439 	}
440 
getTextureFilter() const441 	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 
getAddressingModeU() const467 	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 
getAddressingModeV() const477 	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 
getAddressingModeW() const487 	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 
getCompareFunc() const500 	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