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 "PixelRoutine.hpp" 20 #include "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 65 swizzleR = SWIZZLE_RED; 66 swizzleG = SWIZZLE_GREEN; 67 swizzleB = SWIZZLE_BLUE; 68 swizzleA = SWIZZLE_ALPHA; 69 70 texture.LOD = 0.0f; 71 exp2LOD = 1.0f; 72 73 texture.baseLevel = 0; 74 texture.maxLevel = 1000; 75 texture.maxLod = MIPMAP_LEVELS - 2; // Trilinear accesses lod+1 76 texture.minLod = 0; 77 } 78 ~Sampler()79 Sampler::~Sampler() 80 { 81 } 82 samplerState() const83 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(); 96 state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat); 97 state.swizzleR = swizzleR; 98 state.swizzleG = swizzleG; 99 state.swizzleB = swizzleB; 100 state.swizzleA = swizzleA; 101 state.highPrecisionFiltering = highPrecisionFiltering; 102 103 #if PERF_PROFILE 104 state.compressedFormat = Surface::isCompressed(externalTextureFormat); 105 #endif 106 } 107 108 return state; 109 } 110 setTextureLevel(int face,int level,Surface * surface,TextureType type)111 void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type) 112 { 113 if(surface) 114 { 115 Mipmap &mipmap = texture.mipmap[level]; 116 117 mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE); 118 119 if(face == 0) 120 { 121 externalTextureFormat = surface->getExternalFormat(); 122 internalTextureFormat = surface->getInternalFormat(); 123 124 int width = surface->getWidth(); 125 int height = surface->getHeight(); 126 int depth = surface->getDepth(); 127 int pitchP = surface->getInternalPitchP(); 128 int sliceP = surface->getInternalSliceP(); 129 130 if(level == 0) 131 { 132 texture.widthHeightLOD[0] = width * exp2LOD; 133 texture.widthHeightLOD[1] = width * exp2LOD; 134 texture.widthHeightLOD[2] = height * exp2LOD; 135 texture.widthHeightLOD[3] = height * exp2LOD; 136 137 texture.widthLOD[0] = width * exp2LOD; 138 texture.widthLOD[1] = width * exp2LOD; 139 texture.widthLOD[2] = width * exp2LOD; 140 texture.widthLOD[3] = width * exp2LOD; 141 142 texture.heightLOD[0] = height * exp2LOD; 143 texture.heightLOD[1] = height * exp2LOD; 144 texture.heightLOD[2] = height * exp2LOD; 145 texture.heightLOD[3] = height * exp2LOD; 146 147 texture.depthLOD[0] = depth * exp2LOD; 148 texture.depthLOD[1] = depth * exp2LOD; 149 texture.depthLOD[2] = depth * exp2LOD; 150 texture.depthLOD[3] = depth * exp2LOD; 151 } 152 153 if(Surface::isFloatFormat(internalTextureFormat)) 154 { 155 mipmap.fWidth[0] = (float)width / 65536.0f; 156 mipmap.fWidth[1] = (float)width / 65536.0f; 157 mipmap.fWidth[2] = (float)width / 65536.0f; 158 mipmap.fWidth[3] = (float)width / 65536.0f; 159 160 mipmap.fHeight[0] = (float)height / 65536.0f; 161 mipmap.fHeight[1] = (float)height / 65536.0f; 162 mipmap.fHeight[2] = (float)height / 65536.0f; 163 mipmap.fHeight[3] = (float)height / 65536.0f; 164 165 mipmap.fDepth[0] = (float)depth / 65536.0f; 166 mipmap.fDepth[1] = (float)depth / 65536.0f; 167 mipmap.fDepth[2] = (float)depth / 65536.0f; 168 mipmap.fDepth[3] = (float)depth / 65536.0f; 169 } 170 171 short halfTexelU = 0x8000 / width; 172 short halfTexelV = 0x8000 / height; 173 short halfTexelW = 0x8000 / depth; 174 175 mipmap.uHalf[0] = halfTexelU; 176 mipmap.uHalf[1] = halfTexelU; 177 mipmap.uHalf[2] = halfTexelU; 178 mipmap.uHalf[3] = halfTexelU; 179 180 mipmap.vHalf[0] = halfTexelV; 181 mipmap.vHalf[1] = halfTexelV; 182 mipmap.vHalf[2] = halfTexelV; 183 mipmap.vHalf[3] = halfTexelV; 184 185 mipmap.wHalf[0] = halfTexelW; 186 mipmap.wHalf[1] = halfTexelW; 187 mipmap.wHalf[2] = halfTexelW; 188 mipmap.wHalf[3] = halfTexelW; 189 190 mipmap.width[0] = width; 191 mipmap.width[1] = width; 192 mipmap.width[2] = width; 193 mipmap.width[3] = width; 194 195 mipmap.height[0] = height; 196 mipmap.height[1] = height; 197 mipmap.height[2] = height; 198 mipmap.height[3] = height; 199 200 mipmap.depth[0] = depth; 201 mipmap.depth[1] = depth; 202 mipmap.depth[2] = depth; 203 mipmap.depth[3] = depth; 204 205 mipmap.onePitchP[0] = 1; 206 mipmap.onePitchP[1] = pitchP; 207 mipmap.onePitchP[2] = 1; 208 mipmap.onePitchP[3] = pitchP; 209 210 mipmap.pitchP[0] = pitchP; 211 mipmap.pitchP[1] = pitchP; 212 mipmap.pitchP[2] = pitchP; 213 mipmap.pitchP[3] = pitchP; 214 215 mipmap.sliceP[0] = sliceP; 216 mipmap.sliceP[1] = sliceP; 217 mipmap.sliceP[2] = sliceP; 218 mipmap.sliceP[3] = sliceP; 219 220 if(internalTextureFormat == FORMAT_YV12_BT601 || 221 internalTextureFormat == FORMAT_YV12_BT709 || 222 internalTextureFormat == FORMAT_YV12_JFIF) 223 { 224 unsigned int YStride = pitchP; 225 unsigned int YSize = YStride * height; 226 unsigned int CStride = align(YStride / 2, 16); 227 unsigned int CSize = CStride * height / 2; 228 229 mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize; 230 mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize; 231 232 texture.mipmap[1].width[0] = width / 2; 233 texture.mipmap[1].width[1] = width / 2; 234 texture.mipmap[1].width[2] = width / 2; 235 texture.mipmap[1].width[3] = width / 2; 236 texture.mipmap[1].height[0] = height / 2; 237 texture.mipmap[1].height[1] = height / 2; 238 texture.mipmap[1].height[2] = height / 2; 239 texture.mipmap[1].height[3] = height / 2; 240 texture.mipmap[1].onePitchP[0] = 1; 241 texture.mipmap[1].onePitchP[1] = CStride; 242 texture.mipmap[1].onePitchP[2] = 1; 243 texture.mipmap[1].onePitchP[3] = CStride; 244 } 245 } 246 } 247 248 textureType = type; 249 } 250 setTextureFilter(FilterType textureFilter)251 void Sampler::setTextureFilter(FilterType textureFilter) 252 { 253 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality); 254 } 255 setMipmapFilter(MipmapType mipmapFilter)256 void Sampler::setMipmapFilter(MipmapType mipmapFilter) 257 { 258 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality); 259 } 260 setGatherEnable(bool enable)261 void Sampler::setGatherEnable(bool enable) 262 { 263 gather = enable; 264 } 265 setAddressingModeU(AddressingMode addressingMode)266 void Sampler::setAddressingModeU(AddressingMode addressingMode) 267 { 268 addressingModeU = addressingMode; 269 } 270 setAddressingModeV(AddressingMode addressingMode)271 void Sampler::setAddressingModeV(AddressingMode addressingMode) 272 { 273 addressingModeV = addressingMode; 274 } 275 setAddressingModeW(AddressingMode addressingMode)276 void Sampler::setAddressingModeW(AddressingMode addressingMode) 277 { 278 addressingModeW = addressingMode; 279 } 280 setReadSRGB(bool sRGB)281 void Sampler::setReadSRGB(bool sRGB) 282 { 283 this->sRGB = sRGB; 284 } 285 setBorderColor(const Color<float> & borderColor)286 void Sampler::setBorderColor(const Color<float> &borderColor) 287 { 288 // FIXME: Compact into generic function // FIXME: Clamp 289 short r = iround(0xFFFF * borderColor.r); 290 short g = iround(0xFFFF * borderColor.g); 291 short b = iround(0xFFFF * borderColor.b); 292 short a = iround(0xFFFF * borderColor.a); 293 294 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r; 295 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g; 296 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b; 297 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a; 298 299 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r; 300 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g; 301 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b; 302 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a; 303 } 304 setMaxAnisotropy(float maxAnisotropy)305 void Sampler::setMaxAnisotropy(float maxAnisotropy) 306 { 307 texture.maxAnisotropy = maxAnisotropy; 308 } 309 setHighPrecisionFiltering(bool highPrecisionFiltering)310 void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering) 311 { 312 this->highPrecisionFiltering = highPrecisionFiltering; 313 } 314 setSwizzleR(SwizzleType swizzleR)315 void Sampler::setSwizzleR(SwizzleType swizzleR) 316 { 317 this->swizzleR = swizzleR; 318 } 319 setSwizzleG(SwizzleType swizzleG)320 void Sampler::setSwizzleG(SwizzleType swizzleG) 321 { 322 this->swizzleG = swizzleG; 323 } 324 setSwizzleB(SwizzleType swizzleB)325 void Sampler::setSwizzleB(SwizzleType swizzleB) 326 { 327 this->swizzleB = swizzleB; 328 } 329 setSwizzleA(SwizzleType swizzleA)330 void Sampler::setSwizzleA(SwizzleType swizzleA) 331 { 332 this->swizzleA = swizzleA; 333 } 334 setBaseLevel(int baseLevel)335 void Sampler::setBaseLevel(int baseLevel) 336 { 337 texture.baseLevel = baseLevel; 338 } 339 setMaxLevel(int maxLevel)340 void Sampler::setMaxLevel(int maxLevel) 341 { 342 texture.maxLevel = maxLevel; 343 } 344 setMinLod(float minLod)345 void Sampler::setMinLod(float minLod) 346 { 347 texture.minLod = clamp(minLod, 0.0f, (float)(MIPMAP_LEVELS - 2)); 348 } 349 setMaxLod(float maxLod)350 void Sampler::setMaxLod(float maxLod) 351 { 352 texture.maxLod = clamp(maxLod, 0.0f, (float)(MIPMAP_LEVELS - 2)); 353 } 354 setFilterQuality(FilterType maximumFilterQuality)355 void Sampler::setFilterQuality(FilterType maximumFilterQuality) 356 { 357 Sampler::maximumTextureFilterQuality = maximumFilterQuality; 358 } 359 setMipmapQuality(MipmapType maximumFilterQuality)360 void Sampler::setMipmapQuality(MipmapType maximumFilterQuality) 361 { 362 Sampler::maximumMipmapFilterQuality = maximumFilterQuality; 363 } 364 setMipmapLOD(float LOD)365 void Sampler::setMipmapLOD(float LOD) 366 { 367 texture.LOD = LOD; 368 exp2LOD = exp2(LOD); 369 } 370 hasTexture() const371 bool Sampler::hasTexture() const 372 { 373 return textureType != TEXTURE_NULL; 374 } 375 hasUnsignedTexture() const376 bool Sampler::hasUnsignedTexture() const 377 { 378 return Surface::isUnsignedComponent(internalTextureFormat, 0) && 379 Surface::isUnsignedComponent(internalTextureFormat, 1) && 380 Surface::isUnsignedComponent(internalTextureFormat, 2) && 381 Surface::isUnsignedComponent(internalTextureFormat, 3); 382 } 383 hasCubeTexture() const384 bool Sampler::hasCubeTexture() const 385 { 386 return textureType == TEXTURE_CUBE; 387 } 388 hasVolumeTexture() const389 bool Sampler::hasVolumeTexture() const 390 { 391 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY; 392 } 393 getTextureData()394 const Texture &Sampler::getTextureData() 395 { 396 return texture; 397 } 398 mipmapFilter() const399 MipmapType Sampler::mipmapFilter() const 400 { 401 if(mipmapFilterState != MIPMAP_NONE) 402 { 403 for(int i = 1; i < MIPMAP_LEVELS; i++) 404 { 405 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0]) 406 { 407 return mipmapFilterState; 408 } 409 } 410 } 411 412 // Only one mipmap level 413 return MIPMAP_NONE; 414 } 415 getTextureType() const416 TextureType Sampler::getTextureType() const 417 { 418 return textureType; 419 } 420 getTextureFilter() const421 FilterType Sampler::getTextureFilter() const 422 { 423 // Don't filter 1x1 textures. 424 if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1) 425 { 426 if(mipmapFilter() == MIPMAP_NONE) 427 { 428 return FILTER_POINT; 429 } 430 } 431 432 FilterType filter = textureFilter; 433 434 if(gather && Surface::componentCount(internalTextureFormat) == 1) 435 { 436 filter = FILTER_GATHER; 437 } 438 439 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f) 440 { 441 return (FilterType)min(filter, FILTER_LINEAR); 442 } 443 444 return filter; 445 } 446 getAddressingModeU() const447 AddressingMode Sampler::getAddressingModeU() const 448 { 449 if(hasCubeTexture()) 450 { 451 return ADDRESSING_CLAMP; 452 } 453 454 return addressingModeU; 455 } 456 getAddressingModeV() const457 AddressingMode Sampler::getAddressingModeV() const 458 { 459 if(hasCubeTexture()) 460 { 461 return ADDRESSING_CLAMP; 462 } 463 464 return addressingModeV; 465 } 466 getAddressingModeW() const467 AddressingMode Sampler::getAddressingModeW() const 468 { 469 if(hasCubeTexture()) 470 { 471 return ADDRESSING_CLAMP; 472 } 473 474 if(textureType == TEXTURE_2D_ARRAY || textureType == TEXTURE_2D) 475 { 476 return ADDRESSING_LAYER; 477 } 478 479 return addressingModeW; 480 } 481 } 482