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(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 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 getTextureData()404 const Texture &Sampler::getTextureData() 405 { 406 return texture; 407 } 408 mipmapFilter() const409 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 getTextureType() const426 TextureType Sampler::getTextureType() const 427 { 428 return textureType; 429 } 430 getTextureFilter() const431 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 getAddressingModeU() const457 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 getAddressingModeV() const467 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 getAddressingModeW() const477 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 getCompareFunc() const489 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