Home | History | Annotate | Download | only in Renderer
      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 
     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(YStride / 2, 16);
    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 	const Texture &Sampler::getTextureData()
    405 	{
    406 		return texture;
    407 	}
    408 
    409 	MipmapType Sampler::mipmapFilter() const
    410 	{
    411 		if(mipmapFilterState != MIPMAP_NONE)
    412 		{
    413 			for(int i = 1; i < MIPMAP_LEVELS; i++)
    414 			{
    415 				if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
    416 				{
    417 					return mipmapFilterState;
    418 				}
    419 			}
    420 		}
    421 
    422 		// Only one mipmap level
    423 		return MIPMAP_NONE;
    424 	}
    425 
    426 	TextureType Sampler::getTextureType() const
    427 	{
    428 		return textureType;
    429 	}
    430 
    431 	FilterType Sampler::getTextureFilter() const
    432 	{
    433 		// Don't filter 1x1 textures.
    434 		if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1)
    435 		{
    436 			if(mipmapFilter() == MIPMAP_NONE)
    437 			{
    438 				return FILTER_POINT;
    439 			}
    440 		}
    441 
    442 		FilterType filter = textureFilter;
    443 
    444 		if(gather && Surface::componentCount(internalTextureFormat) == 1)
    445 		{
    446 			filter = FILTER_GATHER;
    447 		}
    448 
    449 		if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
    450 		{
    451 			return (FilterType)min(filter, FILTER_LINEAR);
    452 		}
    453 
    454 		return filter;
    455 	}
    456 
    457 	AddressingMode Sampler::getAddressingModeU() const
    458 	{
    459 		if(textureType == TEXTURE_CUBE)
    460 		{
    461 			return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
    462 		}
    463 
    464 		return addressingModeU;
    465 	}
    466 
    467 	AddressingMode Sampler::getAddressingModeV() const
    468 	{
    469 		if(textureType == TEXTURE_CUBE)
    470 		{
    471 			return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
    472 		}
    473 
    474 		return addressingModeV;
    475 	}
    476 
    477 	AddressingMode Sampler::getAddressingModeW() const
    478 	{
    479 		if(textureType == TEXTURE_2D_ARRAY ||
    480 		   textureType == TEXTURE_2D ||
    481 		   textureType == TEXTURE_CUBE)
    482 		{
    483 			return ADDRESSING_LAYER;
    484 		}
    485 
    486 		return addressingModeW;
    487 	}
    488 
    489 	CompareFunc Sampler::getCompareFunc() const
    490 	{
    491 		if(getTextureFilter() == FILTER_GATHER)
    492 		{
    493 			return COMPARE_BYPASS;
    494 		}
    495 
    496 		if(internalTextureFormat == FORMAT_D32FS8_SHADOW)
    497 		{
    498 			return COMPARE_LESSEQUAL;
    499 		}
    500 
    501 		return compare;
    502 	}
    503 }
    504