1 #include "rs_core.rsh" 2 #include "rs_graphics.rsh" 3 #include "rs_structs.h" 4 5 6 // 565 Conversion bits taken from SkBitmap 7 #define SK_R16_BITS 5 8 #define SK_G16_BITS 6 9 #define SK_B16_BITS 5 10 11 #define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) 12 #define SK_G16_SHIFT (SK_B16_BITS) 13 #define SK_B16_SHIFT 0 14 15 #define SK_R16_MASK ((1 << SK_R16_BITS) - 1) 16 #define SK_G16_MASK ((1 << SK_G16_BITS) - 1) 17 #define SK_B16_MASK ((1 << SK_B16_BITS) - 1) 18 19 #define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK) 20 #define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK) 21 #define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK) 22 23 static inline unsigned SkR16ToR32(unsigned r) { 24 return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); 25 } 26 27 static inline unsigned SkG16ToG32(unsigned g) { 28 return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); 29 } 30 31 static inline unsigned SkB16ToB32(unsigned b) { 32 return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8)); 33 } 34 35 #define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c)) 36 #define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c)) 37 #define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c)) 38 39 static float3 getFrom565(uint16_t color) { 40 float3 result; 41 result.x = (float)SkPacked16ToR32(color); 42 result.y = (float)SkPacked16ToG32(color); 43 result.z = (float)SkPacked16ToB32(color); 44 return result; 45 } 46 47 /** 48 * Allocation sampling 49 */ 50 static inline float __attribute__((overloadable)) 51 getElementAt1(const uint8_t *p, int32_t x) { 52 float r = p[x]; 53 return r; 54 } 55 56 static inline float2 __attribute__((overloadable)) 57 getElementAt2(const uint8_t *p, int32_t x) { 58 x *= 2; 59 float2 r = {p[x], p[x+1]}; 60 return r; 61 } 62 63 static inline float3 __attribute__((overloadable)) 64 getElementAt3(const uint8_t *p, int32_t x) { 65 x *= 4; 66 float3 r = {p[x], p[x+1], p[x+2]}; 67 return r; 68 } 69 70 static inline float4 __attribute__((overloadable)) 71 getElementAt4(const uint8_t *p, int32_t x) { 72 x *= 4; 73 const uchar4 *p2 = (const uchar4 *)&p[x]; 74 return convert_float4(p2[0]); 75 } 76 77 static inline float3 __attribute__((overloadable)) 78 getElementAt565(const uint8_t *p, int32_t x) { 79 x *= 2; 80 float3 r = getFrom565(((const uint16_t *)p)[0]); 81 return r; 82 } 83 84 static inline float __attribute__((overloadable)) 85 getElementAt1(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 86 p += y * stride; 87 float r = p[x]; 88 return r; 89 } 90 91 static inline float2 __attribute__((overloadable)) 92 getElementAt2(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 93 p += y * stride; 94 x *= 2; 95 float2 r = {p[x], p[x+1]}; 96 return r; 97 } 98 99 static inline float3 __attribute__((overloadable)) 100 getElementAt3(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 101 p += y * stride; 102 x *= 4; 103 float3 r = {p[x], p[x+1], p[x+2]}; 104 return r; 105 } 106 107 static inline float4 __attribute__((overloadable)) 108 getElementAt4(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 109 p += y * stride; 110 x *= 4; 111 float4 r = {p[x], p[x+1], p[x+2], p[x+3]}; 112 return r; 113 } 114 115 static inline float3 __attribute__((overloadable)) 116 getElementAt565(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 117 p += y * stride; 118 x *= 2; 119 float3 r = getFrom565(((const uint16_t *)p)[0]); 120 return r; 121 } 122 123 124 125 126 127 static float4 __attribute__((overloadable)) 128 getSample_A(const uint8_t *p, int32_t iPixel, 129 int32_t next, float w0, float w1) { 130 float p0 = getElementAt1(p, iPixel); 131 float p1 = getElementAt1(p, next); 132 float r = p0 * w0 + p1 * w1; 133 r *= (1.f / 255.f); 134 float4 ret = {0.f, 0.f, 0.f, r}; 135 return ret; 136 } 137 static float4 __attribute__((overloadable)) 138 getSample_L(const uint8_t *p, int32_t iPixel, 139 int32_t next, float w0, float w1) { 140 float p0 = getElementAt1(p, iPixel); 141 float p1 = getElementAt1(p, next); 142 float r = p0 * w0 + p1 * w1; 143 r *= (1.f / 255.f); 144 float4 ret = {r, r, r, 1.f}; 145 return ret; 146 } 147 static float4 __attribute__((overloadable)) 148 getSample_LA(const uint8_t *p, int32_t iPixel, 149 int32_t next, float w0, float w1) { 150 float2 p0 = getElementAt2(p, iPixel); 151 float2 p1 = getElementAt2(p, next); 152 float2 r = p0 * w0 + p1 * w1; 153 r *= (1.f / 255.f); 154 float4 ret = {r.x, r.x, r.x, r.y}; 155 return ret; 156 } 157 static float4 __attribute__((overloadable)) 158 getSample_RGB(const uint8_t *p, int32_t iPixel, 159 int32_t next, float w0, float w1) { 160 float3 p0 = getElementAt3(p, iPixel); 161 float3 p1 = getElementAt3(p, next); 162 float3 r = p0 * w0 + p1 * w1; 163 r *= (1.f / 255.f); 164 float4 ret = {r.x, r.x, r.z, 1.f}; 165 return ret; 166 } 167 static float4 __attribute__((overloadable)) 168 getSample_565(const uint8_t *p, int32_t iPixel, 169 int32_t next, float w0, float w1) { 170 float3 p0 = getElementAt565(p, iPixel); 171 float3 p1 = getElementAt565(p, next); 172 float3 r = p0 * w0 + p1 * w1; 173 r *= (1.f / 255.f); 174 float4 ret = {r.x, r.x, r.z, 1.f}; 175 return ret; 176 } 177 static float4 __attribute__((overloadable)) 178 getSample_RGBA(const uint8_t *p, int32_t iPixel, 179 int32_t next, float w0, float w1) { 180 float4 p0 = getElementAt4(p, iPixel); 181 float4 p1 = getElementAt4(p, next); 182 float4 r = p0 * w0 + p1 * w1; 183 r *= (1.f / 255.f); 184 return r; 185 } 186 187 188 static float4 __attribute__((overloadable)) 189 getSample_A(const uint8_t *p, size_t stride, 190 int locX, int locY, int nextX, int nextY, 191 float w0, float w1, float w2, float w3) { 192 float p0 = getElementAt1(p, stride, locX, locY); 193 float p1 = getElementAt1(p, stride, nextX, locY); 194 float p2 = getElementAt1(p, stride, locX, nextY); 195 float p3 = getElementAt1(p, stride, nextX, nextY); 196 float r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 197 r *= (1.f / 255.f); 198 float4 ret = {0.f, 0.f, 0.f, r}; 199 return ret; 200 } 201 static float4 __attribute__((overloadable)) 202 getSample_L(const uint8_t *p, size_t stride, 203 int locX, int locY, int nextX, int nextY, 204 float w0, float w1, float w2, float w3) { 205 float p0 = getElementAt1(p, stride, locX, locY); 206 float p1 = getElementAt1(p, stride, nextX, locY); 207 float p2 = getElementAt1(p, stride, locX, nextY); 208 float p3 = getElementAt1(p, stride, nextX, nextY); 209 float r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 210 r *= (1.f / 255.f); 211 float4 ret = {r, r, r, 1.f}; 212 return ret; 213 } 214 static float4 __attribute__((overloadable)) 215 getSample_LA(const uint8_t *p, size_t stride, 216 int locX, int locY, int nextX, int nextY, 217 float w0, float w1, float w2, float w3) { 218 float2 p0 = getElementAt2(p, stride, locX, locY); 219 float2 p1 = getElementAt2(p, stride, nextX, locY); 220 float2 p2 = getElementAt2(p, stride, locX, nextY); 221 float2 p3 = getElementAt2(p, stride, nextX, nextY); 222 float2 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 223 r *= (1.f / 255.f); 224 float4 ret = {r.x, r.x, r.x, r.y}; 225 return ret; 226 } 227 static float4 __attribute__((overloadable)) 228 getSample_RGB(const uint8_t *p, size_t stride, 229 int locX, int locY, int nextX, int nextY, 230 float w0, float w1, float w2, float w3) { 231 float4 p0 = getElementAt4(p, stride, locX, locY); 232 float4 p1 = getElementAt4(p, stride, nextX, locY); 233 float4 p2 = getElementAt4(p, stride, locX, nextY); 234 float4 p3 = getElementAt4(p, stride, nextX, nextY); 235 float4 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 236 r *= (1.f / 255.f); 237 float4 ret = {r.x, r.y, r.z, 1.f}; 238 return ret; 239 } 240 static float4 __attribute__((overloadable)) 241 getSample_RGBA(const uint8_t *p, size_t stride, 242 int locX, int locY, int nextX, int nextY, 243 float w0, float w1, float w2, float w3) { 244 float4 p0 = getElementAt4(p, stride, locX, locY); 245 float4 p1 = getElementAt4(p, stride, nextX, locY); 246 float4 p2 = getElementAt4(p, stride, locX, nextY); 247 float4 p3 = getElementAt4(p, stride, nextX, nextY); 248 float4 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 249 r *= (1.f / 255.f); 250 return r; 251 } 252 static float4 __attribute__((overloadable)) 253 getSample_565(const uint8_t *p, size_t stride, 254 int locX, int locY, int nextX, int nextY, 255 float w0, float w1, float w2, float w3) { 256 float3 p0 = getElementAt565(p, stride, locX, locY); 257 float3 p1 = getElementAt565(p, stride, nextX, locY); 258 float3 p2 = getElementAt565(p, stride, locX, nextY); 259 float3 p3 = getElementAt565(p, stride, nextX, nextY); 260 float3 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 261 r *= (1.f / 255.f); 262 float4 ret; 263 ret.rgb = r; 264 ret.w = 1.f; 265 return ret; 266 } 267 268 static float4 __attribute__((overloadable)) 269 getBilinearSample1D(const Allocation_t *alloc, float2 weights, 270 uint32_t iPixel, uint32_t next, 271 rs_data_kind dk, rs_data_type dt, uint32_t lod) { 272 273 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 274 275 switch(dk) { 276 case RS_KIND_PIXEL_RGBA: 277 return getSample_RGBA(p, iPixel, next, weights.x, weights.y); 278 case RS_KIND_PIXEL_A: 279 return getSample_A(p, iPixel, next, weights.x, weights.y); 280 case RS_KIND_PIXEL_RGB: 281 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 282 return getSample_565(p, iPixel, next, weights.x, weights.y); 283 } 284 return getSample_RGB(p, iPixel, next, weights.x, weights.y); 285 case RS_KIND_PIXEL_L: 286 return getSample_L(p, iPixel, next, weights.x, weights.y); 287 case RS_KIND_PIXEL_LA: 288 return getSample_LA(p, iPixel, next, weights.x, weights.y); 289 290 default: 291 //__builtin_unreachable(); 292 break; 293 } 294 295 //__builtin_unreachable(); 296 return 0.f; 297 } 298 299 static uint32_t wrapI(rs_sampler_value wrap, int32_t coord, int32_t size) { 300 if (wrap == RS_SAMPLER_WRAP) { 301 coord = coord % size; 302 if (coord < 0) { 303 coord += size; 304 } 305 } 306 if (wrap == RS_SAMPLER_MIRRORED_REPEAT) { 307 coord = coord % (size * 2); 308 if (coord < 0) { 309 coord = (size * 2) + coord; 310 } 311 if (coord >= size) { 312 coord = (size * 2) - coord; 313 } 314 } 315 return (uint32_t)max(0, min(coord, size - 1)); 316 } 317 318 static float4 __attribute__((overloadable)) 319 getBilinearSample2D(const Allocation_t *alloc, float w0, float w1, float w2, float w3, 320 int lx, int ly, int nx, int ny, 321 rs_data_kind dk, rs_data_type dt, uint32_t lod) { 322 323 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 324 size_t stride = alloc->mHal.drvState.lod[lod].stride; 325 326 switch(dk) { 327 case RS_KIND_PIXEL_RGBA: 328 return getSample_RGBA(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 329 case RS_KIND_PIXEL_A: 330 return getSample_A(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 331 case RS_KIND_PIXEL_LA: 332 return getSample_LA(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 333 case RS_KIND_PIXEL_RGB: 334 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 335 return getSample_565(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 336 } 337 return getSample_RGB(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 338 case RS_KIND_PIXEL_L: 339 return getSample_L(p, stride, lx, ly, nx, ny, w0, w1, w2, w3); 340 341 default: 342 //__builtin_unreachable(); 343 break; 344 } 345 346 //__builtin_unreachable(); 347 return 0.f; 348 } 349 350 static float4 __attribute__((overloadable)) 351 getNearestSample(const Allocation_t *alloc, uint32_t iPixel, rs_data_kind dk, 352 rs_data_type dt, uint32_t lod) { 353 354 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 355 356 float4 result = {0.f, 0.f, 0.f, 255.f}; 357 358 switch(dk) { 359 case RS_KIND_PIXEL_RGBA: 360 result = getElementAt4(p, iPixel); 361 break; 362 case RS_KIND_PIXEL_A: 363 result.w = getElementAt1(p, iPixel); 364 break; 365 case RS_KIND_PIXEL_LA: 366 result.zw = getElementAt2(p, iPixel); 367 result.xy = result.z; 368 break; 369 case RS_KIND_PIXEL_RGB: 370 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 371 result.xyz = getElementAt565(p, iPixel); 372 } else { 373 result.xyz = getElementAt3(p, iPixel); 374 } 375 break; 376 case RS_KIND_PIXEL_L: 377 result.xyz = getElementAt1(p, iPixel); 378 379 default: 380 //__builtin_unreachable(); 381 break; 382 } 383 384 return result * 0.003921569f; 385 } 386 387 static float4 __attribute__((overloadable)) 388 getNearestSample(const Allocation_t *alloc, uint2 iPixel, rs_data_kind dk, 389 rs_data_type dt, uint32_t lod) { 390 391 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 392 size_t stride = alloc->mHal.drvState.lod[lod].stride; 393 394 float4 result = {0.f, 0.f, 0.f, 255.f}; 395 396 switch(dk) { 397 case RS_KIND_PIXEL_RGBA: 398 result = getElementAt4(p, stride, iPixel.x, iPixel.y); 399 break; 400 case RS_KIND_PIXEL_A: 401 result.w = getElementAt1(p, stride, iPixel.x, iPixel.y); 402 break; 403 case RS_KIND_PIXEL_LA: 404 result.zw = getElementAt2(p, stride, iPixel.x, iPixel.y); 405 result.xy = result.z; 406 break; 407 case RS_KIND_PIXEL_RGB: 408 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 409 result.xyz = getElementAt565(p, stride, iPixel.x, iPixel.y); 410 } else { 411 result.xyz = getElementAt3(p, stride, iPixel.x, iPixel.y); 412 } 413 break; 414 415 default: 416 //__builtin_unreachable(); 417 break; 418 } 419 420 return result * 0.003921569f; 421 } 422 423 static float4 __attribute__((overloadable)) 424 sample_LOD_LinearPixel(const Allocation_t *alloc, const Type_t *type, 425 rs_data_kind dk, rs_data_type dt, 426 rs_sampler s, 427 float uv, uint32_t lod) { 428 429 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 430 431 rs_sampler_value wrapS = rsSamplerGetWrapS(s); 432 int32_t sourceW = alloc->mHal.drvState.lod[lod].dimX; 433 float pixelUV = uv * (float)(sourceW); 434 int32_t iPixel = (int32_t)(pixelUV); 435 float frac = pixelUV - (float)iPixel; 436 437 if (frac < 0.5f) { 438 iPixel -= 1; 439 frac += 0.5f; 440 } else { 441 frac -= 0.5f; 442 } 443 444 float oneMinusFrac = 1.0f - frac; 445 446 float2 weights; 447 weights.x = oneMinusFrac; 448 weights.y = frac; 449 450 uint32_t next = wrapI(wrapS, iPixel + 1, sourceW); 451 uint32_t location = wrapI(wrapS, iPixel, sourceW); 452 453 return getBilinearSample1D(alloc, weights, location, next, dk, dt, lod); 454 } 455 456 static float4 __attribute__((overloadable)) 457 sample_LOD_NearestPixel(const Allocation_t *alloc, 458 rs_data_kind dk, rs_data_type dt, 459 rs_sampler s, 460 float uv, uint32_t lod) { 461 462 rs_sampler_value wrapS = rsSamplerGetWrapS(s); 463 int32_t sourceW = alloc->mHal.drvState.lod[lod].dimX; 464 int32_t iPixel = (int32_t)(uv * (float)(sourceW)); 465 uint32_t location = wrapI(wrapS, iPixel, sourceW); 466 467 return getNearestSample(alloc, location, dk, dt, lod); 468 } 469 470 static float4 __attribute__((overloadable)) 471 sample_LOD_LinearPixel(const Allocation_t *alloc, 472 rs_data_kind dk, rs_data_type dt, 473 rs_sampler s, 474 float2 uv, uint32_t lod) { 475 476 const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr; 477 478 rs_sampler_value wrapS = rsSamplerGetWrapS(s); 479 rs_sampler_value wrapT = rsSamplerGetWrapT(s); 480 481 int sourceW = alloc->mHal.drvState.lod[lod].dimX; 482 int sourceH = alloc->mHal.drvState.lod[lod].dimY; 483 484 float pixelU = uv.x * sourceW; 485 float pixelV = uv.y * sourceH; 486 int iPixelU = pixelU; 487 int iPixelV = pixelV; 488 float fracU = pixelU - iPixelU; 489 float fracV = pixelV - iPixelV; 490 491 if (fracU < 0.5f) { 492 iPixelU -= 1; 493 fracU += 0.5f; 494 } else { 495 fracU -= 0.5f; 496 } 497 if (fracV < 0.5f) { 498 iPixelV -= 1; 499 fracV += 0.5f; 500 } else { 501 fracV -= 0.5f; 502 } 503 float oneMinusFracU = 1.0f - fracU; 504 float oneMinusFracV = 1.0f - fracV; 505 506 float w0 = oneMinusFracU * oneMinusFracV; 507 float w1 = fracU * oneMinusFracV; 508 float w2 = oneMinusFracU * fracV; 509 float w3 = fracU * fracV; 510 511 int nx = wrapI(wrapS, iPixelU + 1, sourceW); 512 int ny = wrapI(wrapT, iPixelV + 1, sourceH); 513 int lx = wrapI(wrapS, iPixelU, sourceW); 514 int ly = wrapI(wrapT, iPixelV, sourceH); 515 516 return getBilinearSample2D(alloc, w0, w1, w2, w3, lx, ly, nx, ny, dk, dt, lod); 517 518 } 519 520 static float4 __attribute__((overloadable)) 521 sample_LOD_NearestPixel(const Allocation_t *alloc, 522 rs_data_kind dk, rs_data_type dt, 523 rs_sampler s, 524 float2 uv, uint32_t lod) { 525 rs_sampler_value wrapS = rsSamplerGetWrapS(s); 526 rs_sampler_value wrapT = rsSamplerGetWrapT(s); 527 528 int sourceW = alloc->mHal.drvState.lod[lod].dimX; 529 int sourceH = alloc->mHal.drvState.lod[lod].dimY; 530 531 float2 dimF; 532 dimF.x = (float)(sourceW); 533 dimF.y = (float)(sourceH); 534 int2 iPixel = convert_int2(uv * dimF); 535 536 uint2 location; 537 location.x = wrapI(wrapS, iPixel.x, sourceW); 538 location.y = wrapI(wrapT, iPixel.y, sourceH); 539 return getNearestSample(alloc, location, dk, dt, lod); 540 } 541 542 extern const float4 __attribute__((overloadable)) 543 rsSample(rs_allocation a, rs_sampler s, float uv, float lod) { 544 rs_element elem = rsAllocationGetElement(a); 545 rs_data_kind dk = rsElementGetDataKind(elem); 546 rs_data_type dt = rsElementGetDataType(elem); 547 548 if (dk == RS_KIND_USER || (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5)) { 549 return 0.f; 550 } 551 552 const Allocation_t *alloc = (const Allocation_t *)a.p; 553 const Type_t *type = (const Type_t*)alloc->mHal.state.type; 554 555 rs_sampler_value sampleMin = rsSamplerGetMinification(s); 556 rs_sampler_value sampleMag = rsSamplerGetMagnification(s); 557 558 if (lod <= 0.0f) { 559 if (sampleMag == RS_SAMPLER_NEAREST) { 560 return sample_LOD_NearestPixel(alloc, dk, dt, s, uv, 0); 561 } 562 return sample_LOD_LinearPixel(alloc, dk, dt, s, uv, 0); 563 } 564 565 if (sampleMin == RS_SAMPLER_LINEAR_MIP_NEAREST) { 566 uint32_t maxLOD = type->mHal.state.lodCount - 1; 567 lod = min(lod, (float)maxLOD); 568 uint32_t nearestLOD = (uint32_t)round(lod); 569 return sample_LOD_LinearPixel(alloc, dk, dt, s, uv, nearestLOD); 570 } 571 572 if (sampleMin == RS_SAMPLER_LINEAR_MIP_LINEAR) { 573 uint32_t lod0 = (uint32_t)floor(lod); 574 uint32_t lod1 = (uint32_t)ceil(lod); 575 uint32_t maxLOD = type->mHal.state.lodCount - 1; 576 lod0 = min(lod0, maxLOD); 577 lod1 = min(lod1, maxLOD); 578 float4 sample0 = sample_LOD_LinearPixel(alloc, dk, dt, s, uv, lod0); 579 float4 sample1 = sample_LOD_LinearPixel(alloc, dk, dt, s, uv, lod1); 580 float frac = lod - (float)lod0; 581 return sample0 * (1.0f - frac) + sample1 * frac; 582 } 583 584 return sample_LOD_NearestPixel(alloc, dk, dt, s, uv, 0); 585 } 586 587 extern const float4 __attribute__((overloadable)) 588 rsSample(rs_allocation a, rs_sampler s, float location) { 589 return rsSample(a, s, location, 0); 590 } 591 592 593 extern const float4 __attribute__((overloadable)) 594 rsSample(rs_allocation a, rs_sampler s, float2 uv, float lod) { 595 596 const Allocation_t *alloc = (const Allocation_t *)a.p; 597 598 rs_element elem = rsAllocationGetElement(a); 599 rs_data_kind dk = rsElementGetDataKind(elem); 600 rs_data_type dt = rsElementGetDataType(elem); 601 602 if (dk == RS_KIND_USER || 603 (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5) || 604 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)) { 605 return 0.f; 606 } 607 608 rs_sampler_value sampleMin = rsSamplerGetMinification(s); 609 rs_sampler_value sampleMag = rsSamplerGetMagnification(s); 610 611 if (lod <= 0.0f) { 612 if (sampleMag == RS_SAMPLER_NEAREST) { 613 return sample_LOD_NearestPixel(alloc, dk, dt, s, uv, 0); 614 } 615 return sample_LOD_LinearPixel(alloc, dk, dt, s, uv, 0); 616 } 617 618 if (sampleMin == RS_SAMPLER_LINEAR_MIP_NEAREST) { 619 const Type_t *type = (const Type_t*)alloc->mHal.state.type; 620 uint32_t maxLOD = type->mHal.state.lodCount - 1; 621 lod = min(lod, (float)maxLOD); 622 uint32_t nearestLOD = (uint32_t)round(lod); 623 return sample_LOD_LinearPixel(alloc, dk, dt, s, uv, nearestLOD); 624 } 625 626 if (sampleMin == RS_SAMPLER_LINEAR_MIP_LINEAR) { 627 const Type_t *type = (const Type_t*)alloc->mHal.state.type; 628 uint32_t lod0 = (uint32_t)floor(lod); 629 uint32_t lod1 = (uint32_t)ceil(lod); 630 uint32_t maxLOD = type->mHal.state.lodCount - 1; 631 lod0 = min(lod0, maxLOD); 632 lod1 = min(lod1, maxLOD); 633 float4 sample0 = sample_LOD_LinearPixel(alloc, dk, dt, s, uv, lod0); 634 float4 sample1 = sample_LOD_LinearPixel(alloc, dk, dt, s, uv, lod1); 635 float frac = lod - (float)lod0; 636 return sample0 * (1.0f - frac) + sample1 * frac; 637 } 638 639 return sample_LOD_NearestPixel(alloc, dk, dt, s, uv, 0); 640 } 641 642 extern const float4 __attribute__((overloadable)) 643 rsSample(rs_allocation a, rs_sampler s, float2 uv) { 644 645 const Allocation_t *alloc = (const Allocation_t *)a.p; 646 647 rs_element elem = rsAllocationGetElement(a); 648 rs_data_kind dk = rsElementGetDataKind(elem); 649 rs_data_type dt = rsElementGetDataType(elem); 650 651 if (dk == RS_KIND_USER || 652 (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5) || 653 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)) { 654 return 0.f; 655 } 656 657 if (rsSamplerGetMagnification(s) == RS_SAMPLER_NEAREST) { 658 return sample_LOD_NearestPixel(alloc, dk, dt, s, uv, 0); 659 } 660 return sample_LOD_LinearPixel(alloc, dk, dt, s, uv, 0); 661 } 662 663