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 "CPUID.hpp" 20 #include "PixelRoutine.hpp" 21 #include "Debug.hpp" 22 23 #include <memory.h> 24 #include <string.h> 25 26 namespace sw 27 { 28 FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR; 29 MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT; 30 State()31 Sampler::State::State() 32 { 33 memset(this, 0, sizeof(State)); 34 } 35 Sampler()36 Sampler::Sampler() 37 { 38 // FIXME: Mipmap::init 39 static const unsigned int zero = 0x00FF00FF; 40 41 for(int level = 0; level < MIPMAP_LEVELS; level++) 42 { 43 Mipmap &mipmap = texture.mipmap[level]; 44 45 memset(&mipmap, 0, sizeof(Mipmap)); 46 47 for(int face = 0; face < 6; face++) 48 { 49 mipmap.buffer[face] = &zero; 50 } 51 52 mipmap.uFrac = 16; 53 mipmap.vFrac = 16; 54 mipmap.wFrac = 16; 55 } 56 57 externalTextureFormat = FORMAT_NULL; 58 internalTextureFormat = FORMAT_NULL; 59 textureType = TEXTURE_NULL; 60 61 textureFilter = FILTER_LINEAR; 62 addressingModeU = ADDRESSING_WRAP; 63 addressingModeV = ADDRESSING_WRAP; 64 addressingModeW = ADDRESSING_WRAP; 65 mipmapFilterState = MIPMAP_NONE; 66 sRGB = false; 67 gather = false; 68 69 swizzleR = SWIZZLE_RED; 70 swizzleG = SWIZZLE_GREEN; 71 swizzleB = SWIZZLE_BLUE; 72 swizzleA = SWIZZLE_ALPHA; 73 74 texture.LOD = 0.0f; 75 exp2LOD = 1.0f; 76 } 77 ~Sampler()78 Sampler::~Sampler() 79 { 80 } 81 samplerState() const82 Sampler::State Sampler::samplerState() const 83 { 84 State state; 85 86 if(textureType != TEXTURE_NULL) 87 { 88 state.textureType = textureType; 89 state.textureFormat = internalTextureFormat; 90 state.textureFilter = getTextureFilter(); 91 state.addressingModeU = getAddressingModeU(); 92 state.addressingModeV = getAddressingModeV(); 93 state.addressingModeW = getAddressingModeW(); 94 state.mipmapFilter = mipmapFilter(); 95 state.hasNPOTTexture = hasNPOTTexture(); 96 state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat); 97 state.swizzleR = swizzleR; 98 state.swizzleG = swizzleG; 99 state.swizzleB = swizzleB; 100 state.swizzleA = swizzleA; 101 102 #if PERF_PROFILE 103 state.compressedFormat = Surface::isCompressed(externalTextureFormat); 104 #endif 105 } 106 107 return state; 108 } 109 setTextureLevel(int face,int level,Surface * surface,TextureType type)110 void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type) 111 { 112 if(surface) 113 { 114 Mipmap &mipmap = texture.mipmap[level]; 115 116 mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE); 117 118 if(face == 0) 119 { 120 externalTextureFormat = surface->getExternalFormat(); 121 internalTextureFormat = surface->getInternalFormat(); 122 123 int width = surface->getWidth(); 124 int height = surface->getHeight(); 125 int depth = surface->getDepth(); 126 int pitchP = surface->getInternalPitchP(); 127 int sliceP = surface->getInternalSliceP(); 128 129 int logWidth = log2(width); 130 int logHeight = log2(height); 131 int logDepth = log2(depth); 132 133 if(level == 0) 134 { 135 texture.widthHeightLOD[0] = width * exp2LOD; 136 texture.widthHeightLOD[1] = width * exp2LOD; 137 texture.widthHeightLOD[2] = height * exp2LOD; 138 texture.widthHeightLOD[3] = height * exp2LOD; 139 140 texture.widthLOD[0] = width * exp2LOD; 141 texture.widthLOD[1] = width * exp2LOD; 142 texture.widthLOD[2] = width * exp2LOD; 143 texture.widthLOD[3] = width * exp2LOD; 144 145 texture.heightLOD[0] = height * exp2LOD; 146 texture.heightLOD[1] = height * exp2LOD; 147 texture.heightLOD[2] = height * exp2LOD; 148 texture.heightLOD[3] = height * exp2LOD; 149 150 texture.depthLOD[0] = depth * exp2LOD; 151 texture.depthLOD[1] = depth * exp2LOD; 152 texture.depthLOD[2] = depth * exp2LOD; 153 texture.depthLOD[3] = depth * exp2LOD; 154 } 155 156 if(!Surface::isFloatFormat(internalTextureFormat)) 157 { 158 mipmap.uInt = logWidth; 159 mipmap.vInt = logHeight; 160 mipmap.wInt = logDepth; 161 mipmap.uFrac = 16 - logWidth; 162 mipmap.vFrac = 16 - logHeight; 163 mipmap.wFrac = 16 - logDepth; 164 } 165 else 166 { 167 mipmap.fWidth[0] = (float)width / 65536.0f; 168 mipmap.fWidth[1] = (float)width / 65536.0f; 169 mipmap.fWidth[2] = (float)width / 65536.0f; 170 mipmap.fWidth[3] = (float)width / 65536.0f; 171 172 mipmap.fHeight[0] = (float)height / 65536.0f; 173 mipmap.fHeight[1] = (float)height / 65536.0f; 174 mipmap.fHeight[2] = (float)height / 65536.0f; 175 mipmap.fHeight[3] = (float)height / 65536.0f; 176 177 mipmap.fDepth[0] = (float)depth / 65536.0f; 178 mipmap.fDepth[1] = (float)depth / 65536.0f; 179 mipmap.fDepth[2] = (float)depth / 65536.0f; 180 mipmap.fDepth[3] = (float)depth / 65536.0f; 181 } 182 183 short halfTexelU = 0x8000 / width; 184 short halfTexelV = 0x8000 / height; 185 short halfTexelW = 0x8000 / depth; 186 187 mipmap.uHalf[0] = halfTexelU; 188 mipmap.uHalf[1] = halfTexelU; 189 mipmap.uHalf[2] = halfTexelU; 190 mipmap.uHalf[3] = halfTexelU; 191 192 mipmap.vHalf[0] = halfTexelV; 193 mipmap.vHalf[1] = halfTexelV; 194 mipmap.vHalf[2] = halfTexelV; 195 mipmap.vHalf[3] = halfTexelV; 196 197 mipmap.wHalf[0] = halfTexelW; 198 mipmap.wHalf[1] = halfTexelW; 199 mipmap.wHalf[2] = halfTexelW; 200 mipmap.wHalf[3] = halfTexelW; 201 202 mipmap.width[0] = width; 203 mipmap.width[1] = width; 204 mipmap.width[2] = width; 205 mipmap.width[3] = width; 206 207 mipmap.height[0] = height; 208 mipmap.height[1] = height; 209 mipmap.height[2] = height; 210 mipmap.height[3] = height; 211 212 mipmap.depth[0] = depth; 213 mipmap.depth[1] = depth; 214 mipmap.depth[2] = depth; 215 mipmap.depth[3] = depth; 216 217 mipmap.onePitchP[0] = 1; 218 mipmap.onePitchP[1] = pitchP; 219 mipmap.onePitchP[2] = 1; 220 mipmap.onePitchP[3] = pitchP; 221 222 mipmap.sliceP[0] = sliceP; 223 mipmap.sliceP[1] = 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].uFrac = texture.mipmap[0].uFrac + 1; 238 texture.mipmap[1].vFrac = texture.mipmap[0].vFrac + 1; 239 texture.mipmap[1].width[0] = width / 2; 240 texture.mipmap[1].width[1] = width / 2; 241 texture.mipmap[1].width[2] = width / 2; 242 texture.mipmap[1].width[3] = width / 2; 243 texture.mipmap[1].height[0] = height / 2; 244 texture.mipmap[1].height[1] = height / 2; 245 texture.mipmap[1].height[2] = height / 2; 246 texture.mipmap[1].height[3] = height / 2; 247 texture.mipmap[1].onePitchP[0] = 1; 248 texture.mipmap[1].onePitchP[1] = CStride; 249 texture.mipmap[1].onePitchP[2] = 1; 250 texture.mipmap[1].onePitchP[3] = CStride; 251 } 252 } 253 } 254 255 textureType = type; 256 } 257 setTextureFilter(FilterType textureFilter)258 void Sampler::setTextureFilter(FilterType textureFilter) 259 { 260 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality); 261 } 262 setMipmapFilter(MipmapType mipmapFilter)263 void Sampler::setMipmapFilter(MipmapType mipmapFilter) 264 { 265 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality); 266 } 267 setGatherEnable(bool enable)268 void Sampler::setGatherEnable(bool enable) 269 { 270 gather = enable; 271 } 272 setAddressingModeU(AddressingMode addressingMode)273 void Sampler::setAddressingModeU(AddressingMode addressingMode) 274 { 275 addressingModeU = addressingMode; 276 } 277 setAddressingModeV(AddressingMode addressingMode)278 void Sampler::setAddressingModeV(AddressingMode addressingMode) 279 { 280 addressingModeV = addressingMode; 281 } 282 setAddressingModeW(AddressingMode addressingMode)283 void Sampler::setAddressingModeW(AddressingMode addressingMode) 284 { 285 addressingModeW = addressingMode; 286 } 287 setReadSRGB(bool sRGB)288 void Sampler::setReadSRGB(bool sRGB) 289 { 290 this->sRGB = sRGB; 291 } 292 setBorderColor(const Color<float> & borderColor)293 void Sampler::setBorderColor(const Color<float> &borderColor) 294 { 295 // FIXME: Compact into generic function // FIXME: Clamp 296 short r = iround(0xFFFF * borderColor.r); 297 short g = iround(0xFFFF * borderColor.g); 298 short b = iround(0xFFFF * borderColor.b); 299 short a = iround(0xFFFF * borderColor.a); 300 301 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r; 302 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g; 303 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b; 304 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a; 305 306 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r; 307 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g; 308 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b; 309 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a; 310 } 311 setMaxAnisotropy(float maxAnisotropy)312 void Sampler::setMaxAnisotropy(float maxAnisotropy) 313 { 314 texture.maxAnisotropy = maxAnisotropy; 315 } 316 setSwizzleR(SwizzleType swizzleR)317 void Sampler::setSwizzleR(SwizzleType swizzleR) 318 { 319 this->swizzleR = swizzleR; 320 } 321 setSwizzleG(SwizzleType swizzleG)322 void Sampler::setSwizzleG(SwizzleType swizzleG) 323 { 324 this->swizzleG = swizzleG; 325 } 326 setSwizzleB(SwizzleType swizzleB)327 void Sampler::setSwizzleB(SwizzleType swizzleB) 328 { 329 this->swizzleB = swizzleB; 330 } 331 setSwizzleA(SwizzleType swizzleA)332 void Sampler::setSwizzleA(SwizzleType swizzleA) 333 { 334 this->swizzleA = swizzleA; 335 } 336 setFilterQuality(FilterType maximumFilterQuality)337 void Sampler::setFilterQuality(FilterType maximumFilterQuality) 338 { 339 Sampler::maximumTextureFilterQuality = maximumFilterQuality; 340 } 341 setMipmapQuality(MipmapType maximumFilterQuality)342 void Sampler::setMipmapQuality(MipmapType maximumFilterQuality) 343 { 344 Sampler::maximumMipmapFilterQuality = maximumFilterQuality; 345 } 346 setMipmapLOD(float LOD)347 void Sampler::setMipmapLOD(float LOD) 348 { 349 texture.LOD = LOD; 350 exp2LOD = exp2(LOD); 351 } 352 hasTexture() const353 bool Sampler::hasTexture() const 354 { 355 return textureType != TEXTURE_NULL; 356 } 357 hasUnsignedTexture() const358 bool Sampler::hasUnsignedTexture() const 359 { 360 return Surface::isUnsignedComponent(internalTextureFormat, 0) && 361 Surface::isUnsignedComponent(internalTextureFormat, 1) && 362 Surface::isUnsignedComponent(internalTextureFormat, 2) && 363 Surface::isUnsignedComponent(internalTextureFormat, 3); 364 } 365 hasCubeTexture() const366 bool Sampler::hasCubeTexture() const 367 { 368 return textureType == TEXTURE_CUBE; 369 } 370 hasVolumeTexture() const371 bool Sampler::hasVolumeTexture() const 372 { 373 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY; 374 } 375 getTextureData()376 const Texture &Sampler::getTextureData() 377 { 378 return texture; 379 } 380 mipmapFilter() const381 MipmapType Sampler::mipmapFilter() const 382 { 383 if(mipmapFilterState != MIPMAP_NONE) 384 { 385 for(int i = 1; i < MIPMAP_LEVELS; i++) 386 { 387 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0]) 388 { 389 return mipmapFilterState; 390 } 391 } 392 } 393 394 // Only one mipmap level 395 return MIPMAP_NONE; 396 } 397 hasNPOTTexture() const398 bool Sampler::hasNPOTTexture() const 399 { 400 if(textureType == TEXTURE_NULL) 401 { 402 return false; 403 } 404 405 for(int i = 0; i < MIPMAP_LEVELS; i++) 406 { 407 if(texture.mipmap[i].width[0] != texture.mipmap[i].onePitchP[1]) 408 { 409 return true; // Shifting of the texture coordinates doesn't yield the correct address, so using multiply by pitch 410 } 411 } 412 413 return !isPow2(texture.mipmap[0].width[0]) || !isPow2(texture.mipmap[0].height[0]) || !isPow2(texture.mipmap[0].depth[0]); 414 } 415 getTextureType() const416 TextureType Sampler::getTextureType() const 417 { 418 return textureType; 419 } 420 getTextureFilter() const421 FilterType Sampler::getTextureFilter() const 422 { 423 FilterType filter = textureFilter; 424 425 if(gather && Surface::componentCount(internalTextureFormat) == 1) 426 { 427 filter = FILTER_GATHER; 428 } 429 430 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f) 431 { 432 return (FilterType)min(filter, FILTER_LINEAR); 433 } 434 435 return filter; 436 } 437 getAddressingModeU() const438 AddressingMode Sampler::getAddressingModeU() const 439 { 440 if(hasCubeTexture()) 441 { 442 return ADDRESSING_CLAMP; 443 } 444 445 return addressingModeU; 446 } 447 getAddressingModeV() const448 AddressingMode Sampler::getAddressingModeV() const 449 { 450 if(hasCubeTexture()) 451 { 452 return ADDRESSING_CLAMP; 453 } 454 455 return addressingModeV; 456 } 457 getAddressingModeW() const458 AddressingMode Sampler::getAddressingModeW() const 459 { 460 if(hasCubeTexture()) 461 { 462 return ADDRESSING_CLAMP; 463 } 464 465 if(textureType == TEXTURE_2D_ARRAY || textureType == TEXTURE_2D) 466 { 467 return ADDRESSING_LAYER; 468 } 469 470 return addressingModeW; 471 } 472 } 473