rsdSampler.cpp revision fe3697bf62d0812209d9355eee082914eaf05689
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18#include "rsdCore.h" 19#include "rsdSampler.h" 20 21#include "rsContext.h" 22#include "rsSampler.h" 23 24#ifndef RS_COMPATIBILITY_LIB 25#include "rsProgramVertex.h" 26#include "rsProgramFragment.h" 27 28#include <GLES/gl.h> 29#include <GLES/glext.h> 30#endif 31 32using namespace android; 33using namespace android::renderscript; 34 35#if 0 36 37typedef float float2 __attribute__((ext_vector_type(2))); 38typedef float float3 __attribute__((ext_vector_type(3))); 39typedef float float4 __attribute__((ext_vector_type(4))); 40typedef uint8_t uchar4 __attribute__((ext_vector_type(4))); 41 42 43#if defined(ARCH_ARM_HAVE_VFP) 44 #define LOCAL_CALL __attribute__((pcs("aapcs-vfp"))) 45#else 46 #define LOCAL_CALL 47#endif 48 49extern "C" { 50 typedef float4 Sampler2DFn(const uint8_t *p, size_t stride, 51 int lx, int ly, int nx, int ny, 52 float w0, float w1, float w2, float w3) LOCAL_CALL; 53 54 Sampler2DFn rsdCpuGetSample2D_L_k; 55 Sampler2DFn rsdCpuGetSample2D_A_k; 56 Sampler2DFn rsdCpuGetSample2D_LA_k; 57 Sampler2DFn rsdCpuGetSample2D_RGB_k; 58 Sampler2DFn rsdCpuGetSample2D_RGBA_k; 59} 60 61// 565 Conversion bits taken from SkBitmap 62#define SK_R16_BITS 5 63#define SK_G16_BITS 6 64#define SK_B16_BITS 5 65 66#define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) 67#define SK_G16_SHIFT (SK_B16_BITS) 68#define SK_B16_SHIFT 0 69 70#define SK_R16_MASK ((1 << SK_R16_BITS) - 1) 71#define SK_G16_MASK ((1 << SK_G16_BITS) - 1) 72#define SK_B16_MASK ((1 << SK_B16_BITS) - 1) 73 74static inline unsigned SkR16ToR32(unsigned r) { 75 return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); 76} 77 78static inline unsigned SkG16ToG32(unsigned g) { 79 return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); 80} 81 82static inline unsigned SkB16ToB32(unsigned b) { 83 return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8)); 84} 85 86#define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c)) 87#define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c)) 88#define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c)) 89 90#define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK) 91#define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK) 92#define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK) 93 94static float3 getFrom565(uint16_t color) { 95 float3 result; 96 result.x = (float)SkPacked16ToR32(color); 97 result.y = (float)SkPacked16ToG32(color); 98 result.z = (float)SkPacked16ToB32(color); 99 return result; 100} 101 102 103 104/** 105* Allocation sampling 106*/ 107static inline float getElementAt1(const uint8_t *p, int32_t x) { 108 float r = p[x]; 109 return r; 110} 111 112static inline float2 getElementAt2(const uint8_t *p, int32_t x) { 113 x *= 2; 114 float2 r = {p[x], p[x+1]}; 115 return r; 116} 117 118static inline float3 getElementAt3(const uint8_t *p, int32_t x) { 119 x *= 4; 120 float3 r = {p[x], p[x+1], p[x+2]}; 121 return r; 122} 123 124static inline float4 getElementAt4(const uint8_t *p, int32_t x) { 125 x *= 4; 126 float4 r = {p[x], p[x+1], p[x+2], p[x+3]}; 127 return r; 128} 129 130static inline float3 getElementAt565(const uint8_t *p, int32_t x) { 131 x *= 2; 132 float3 r = getFrom565(((const uint16_t *)p)[0]); 133 return r; 134} 135 136static inline float getElementAt1(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 137 p += y * stride; 138 float r = p[x]; 139 return r; 140} 141 142static inline float2 getElementAt2(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 143 p += y * stride; 144 x *= 2; 145 float2 r = {p[x], p[x+1]}; 146 return r; 147} 148 149static inline float3 getElementAt3(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 150 p += y * stride; 151 x *= 4; 152 float3 r = {p[x], p[x+1], p[x+2]}; 153 return r; 154} 155 156static inline float4 getElementAt4(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 157 p += y * stride; 158 x *= 4; 159 float4 r = {p[x], p[x+1], p[x+2], p[x+3]}; 160 return r; 161} 162 163static inline float3 getElementAt565(const uint8_t *p, size_t stride, int32_t x, int32_t y) { 164 p += y * stride; 165 x *= 2; 166 float3 r = getFrom565(((const uint16_t *)p)[0]); 167 return r; 168} 169 170 171 172 173 174static float4 LOCAL_CALL 175 getSample1D_A(const uint8_t *p, int32_t iPixel, 176 int32_t next, float w0, float w1) { 177 float p0 = getElementAt1(p, iPixel); 178 float p1 = getElementAt1(p, next); 179 float r = p0 * w0 + p1 * w1; 180 r *= (1.f / 255.f); 181 float4 ret = {0.f, 0.f, 0.f, r}; 182 return ret; 183} 184static float4 LOCAL_CALL 185 getSample1D_L(const uint8_t *p, int32_t iPixel, 186 int32_t next, float w0, float w1) { 187 float p0 = getElementAt1(p, iPixel); 188 float p1 = getElementAt1(p, next); 189 float r = p0 * w0 + p1 * w1; 190 r *= (1.f / 255.f); 191 float4 ret = {r, r, r, 1.f}; 192 return ret; 193} 194static float4 LOCAL_CALL 195 getSample1D_LA(const uint8_t *p, int32_t iPixel, 196 int32_t next, float w0, float w1) { 197 float2 p0 = getElementAt2(p, iPixel); 198 float2 p1 = getElementAt2(p, next); 199 float2 r = p0 * w0 + p1 * w1; 200 r *= (1.f / 255.f); 201 float4 ret = {r.x, r.x, r.x, r.y}; 202 return ret; 203} 204static float4 LOCAL_CALL 205 getSample1D_RGB(const uint8_t *p, int32_t iPixel, 206 int32_t next, float w0, float w1) { 207 float3 p0 = getElementAt3(p, iPixel); 208 float3 p1 = getElementAt3(p, next); 209 float3 r = p0 * w0 + p1 * w1; 210 r *= (1.f / 255.f); 211 float4 ret = {r.x, r.x, r.z, 1.f}; 212 return ret; 213} 214static float4 LOCAL_CALL 215 getSample1D_565(const uint8_t *p, int32_t iPixel, 216 int32_t next, float w0, float w1) { 217 float3 p0 = getElementAt565(p, iPixel); 218 float3 p1 = getElementAt565(p, next); 219 float3 r = p0 * w0 + p1 * w1; 220 r *= (1.f / 255.f); 221 float4 ret = {r.x, r.x, r.z, 1.f}; 222 return ret; 223} 224static float4 LOCAL_CALL 225 getSample1D_RGBA(const uint8_t *p, int32_t iPixel, 226 int32_t next, float w0, float w1) { 227 float4 p0 = getElementAt4(p, iPixel); 228 float4 p1 = getElementAt4(p, next); 229 float4 r = p0 * w0 + p1 * w1; 230 r *= (1.f / 255.f); 231 return r; 232} 233 234 235#if 1 236static float4 LOCAL_CALL 237 getSample2D_A(const uint8_t *p, size_t stride, 238 int locX, int locY, int nextX, int nextY, 239 float w0, float w1, float w2, float w3) { 240 float p0 = getElementAt1(p, stride, locX, locY); 241 float p1 = getElementAt1(p, stride, nextX, locY); 242 float p2 = getElementAt1(p, stride, locX, nextY); 243 float p3 = getElementAt1(p, stride, nextX, nextY); 244 float r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 245 r *= (1.f / 255.f); 246 float4 ret = {0.f, 0.f, 0.f, r}; 247 return ret; 248} 249static float4 LOCAL_CALL 250 getSample2D_L(const uint8_t *p, size_t stride, 251 int locX, int locY, int nextX, int nextY, 252 float w0, float w1, float w2, float w3) { 253 float p0 = getElementAt1(p, stride, locX, locY); 254 float p1 = getElementAt1(p, stride, nextX, locY); 255 float p2 = getElementAt1(p, stride, locX, nextY); 256 float p3 = getElementAt1(p, stride, nextX, nextY); 257 float r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 258 r *= (1.f / 255.f); 259 float4 ret = {r, r, r, 1.f}; 260 return ret; 261} 262static float4 LOCAL_CALL 263 getSample2D_LA(const uint8_t *p, size_t stride, 264 int locX, int locY, int nextX, int nextY, 265 float w0, float w1, float w2, float w3) { 266 float2 p0 = getElementAt2(p, stride, locX, locY); 267 float2 p1 = getElementAt2(p, stride, nextX, locY); 268 float2 p2 = getElementAt2(p, stride, locX, nextY); 269 float2 p3 = getElementAt2(p, stride, nextX, nextY); 270 float2 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 271 r *= (1.f / 255.f); 272 float4 ret = {r.x, r.x, r.x, r.y}; 273 return ret; 274} 275static float4 LOCAL_CALL 276 getSample2D_RGB(const uint8_t *p, size_t stride, 277 int locX, int locY, int nextX, int nextY, 278 float w0, float w1, float w2, float w3) { 279 float4 p0 = getElementAt4(p, stride, locX, locY); 280 float4 p1 = getElementAt4(p, stride, nextX, locY); 281 float4 p2 = getElementAt4(p, stride, locX, nextY); 282 float4 p3 = getElementAt4(p, stride, nextX, nextY); 283 float4 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 284 r *= (1.f / 255.f); 285 float4 ret = {r.x, r.y, r.z, 1.f}; 286 return ret; 287} 288static float4 LOCAL_CALL 289 getSample2D_RGBA(const uint8_t *p, size_t stride, 290 int locX, int locY, int nextX, int nextY, 291 float w0, float w1, float w2, float w3) { 292 float4 p0 = getElementAt4(p, stride, locX, locY); 293 float4 p1 = getElementAt4(p, stride, nextX, locY); 294 float4 p2 = getElementAt4(p, stride, locX, nextY); 295 float4 p3 = getElementAt4(p, stride, nextX, nextY); 296 float4 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 297 r *= (1.f / 255.f); 298 return r; 299} 300#endif 301static float4 getSample2D_565(const uint8_t *p, size_t stride, 302 int locX, int locY, int nextX, int nextY, 303 float w0, float w1, float w2, float w3) { 304 float3 p0 = getElementAt565(p, stride, locX, locY); 305 float3 p1 = getElementAt565(p, stride, nextX, locY); 306 float3 p2 = getElementAt565(p, stride, locX, nextY); 307 float3 p3 = getElementAt565(p, stride, nextX, nextY); 308 float3 r = p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3; 309 r *= (1.f / 255.f); 310 float4 ret = {r.x, r.y, r.z, 1.f}; 311 return ret; 312} 313 314 315#if 0 316static Sampler2DFn* GetBilinearSampleTable2D[] = { 317 0, 0, 0, 0, 0, 0, 0, 318 0,//rsdCpuGetSample2D_L_k, 319 0,//rsdCpuGetSample2D_A_k, 320 0,//rsdCpuGetSample2D_LA_k, 321 0,//rsdCpuGetSample2D_RGB_k, 322 rsdCpuGetSample2D_RGBA_k 323}; 324 325#else 326static Sampler2DFn* GetBilinearSampleTable2D[] = { 327 0, 0, 0, 0, 0, 0, 0, 328 &getSample2D_L, 329 &getSample2D_A, 330 &getSample2D_LA, 331 &getSample2D_RGB, 332 &getSample2D_RGBA, 333}; 334#endif 335 336 337static int applyWrapMode(RsSamplerValue mode, int coord, int size) { 338 switch (mode) { 339 case RS_SAMPLER_WRAP: 340 coord = coord % size; 341 if (coord < 0) { 342 coord += size; 343 } 344 break; 345 346 case RS_SAMPLER_CLAMP: 347 coord = rsMax(0, rsMin(coord, size - 1)); 348 break; 349 350 case RS_SAMPLER_MIRRORED_REPEAT: 351 coord = coord % (size * 2); 352 if (coord < 0) { 353 coord = (size * 2) + coord; 354 } 355 if (coord >= size) { 356 coord = (size * 2) - coord; 357 } 358 break; 359 360 default: 361 coord = 0; 362 rsAssert(0); 363 } 364 return coord; 365} 366 367static float4 368 sample_LOD_LinearPixel(Allocation *a, const Type *type, 369 RsDataKind dk, RsDataType dt, 370 Sampler *s, 371 float uv, int32_t lod) { 372 RsSamplerValue wrapS = s->mHal.state.wrapS; 373 int32_t sourceW = type->mHal.state.lodDimX[lod]; 374 float pixelUV = uv * (float)(sourceW); 375 int32_t iPixel = (int32_t)(pixelUV); 376 float frac = pixelUV - (float)iPixel; 377 378 if (frac < 0.5f) { 379 iPixel -= 1; 380 frac += 0.5f; 381 } else { 382 frac -= 0.5f; 383 } 384 385 float oneMinusFrac = 1.0f - frac; 386 387 int32_t next = applyWrapMode(wrapS, iPixel + 1, sourceW); 388 int32_t loc = applyWrapMode(wrapS, iPixel, sourceW); 389 390 const uint8_t *ptr = (const uint8_t *)a->mHal.drvState.lod[lod].mallocPtr; 391 392 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 393 return getSample1D_565(ptr, loc, next, next, frac); 394 } 395 396 switch(dk) { 397 case RS_KIND_PIXEL_L: 398 return getSample1D_L(ptr, loc, next, next, frac); 399 case RS_KIND_PIXEL_A: 400 return getSample1D_A(ptr, loc, next, next, frac); 401 case RS_KIND_PIXEL_LA: 402 return getSample1D_LA(ptr, loc, next, next, frac); 403 case RS_KIND_PIXEL_RGB: 404 return getSample1D_RGB(ptr, loc, next, next, frac); 405 case RS_KIND_PIXEL_RGBA: 406 return getSample1D_RGBA(ptr, loc, next, next, frac); 407 408 case RS_KIND_PIXEL_YUV: 409 case RS_KIND_USER: 410 case RS_KIND_INVALID: 411 case RS_KIND_PIXEL_DEPTH: 412 rsAssert(0); 413 break; 414 } 415 416 return 0.f; 417} 418 419static float4 420 sample_LOD_NearestPixel(Allocation *a, const Type *type, 421 RsDataKind dk, RsDataType dt, 422 Sampler *s, float uv, int32_t lod) { 423 RsSamplerValue wrapS = s->mHal.state.wrapS; 424 int32_t sourceW = type->mHal.state.lodDimX[lod]; 425 int32_t iPixel = (int32_t)(uv * (float)(sourceW)); 426 int32_t location = applyWrapMode(wrapS, iPixel, sourceW); 427 428 429 const uint8_t *ptr = (const uint8_t *)a->mHal.drvState.lod[lod].mallocPtr; 430 431 float4 result = {0.f, 0.f, 0.f, 1.f}; 432 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 433 result.xyz = getElementAt565(ptr, iPixel); 434 return result; 435 } 436 437 switch(dk) { 438 case RS_KIND_PIXEL_L: 439 { 440 float t = getElementAt1(ptr, iPixel); 441 result.xyz = t; 442 } 443 break; 444 case RS_KIND_PIXEL_A: 445 result.w = getElementAt1(ptr, iPixel); 446 break; 447 case RS_KIND_PIXEL_LA: 448 { 449 float2 t = getElementAt2(ptr, iPixel); 450 result.xyz = t.x; 451 result.w = t.y; 452 } 453 break; 454 case RS_KIND_PIXEL_RGB: 455 result.xyz = getElementAt3(ptr, iPixel); 456 break; 457 case RS_KIND_PIXEL_RGBA: 458 result = getElementAt4(ptr, iPixel); 459 break; 460 461 case RS_KIND_PIXEL_YUV: 462 case RS_KIND_USER: 463 case RS_KIND_INVALID: 464 case RS_KIND_PIXEL_DEPTH: 465 rsAssert(0); 466 break; 467 } 468 469 return result * (1.f / 255.f); 470} 471 472 473static float4 474 sample_LOD_LinearPixel(Allocation *a, const Type *type, 475 RsDataKind dk, RsDataType dt, 476 Sampler *s, float u, float v, int32_t lod) { 477 const RsSamplerValue wrapS = s->mHal.state.wrapS; 478 const RsSamplerValue wrapT = s->mHal.state.wrapT; 479 const int sourceW = type->mHal.state.lodDimX[lod]; 480 const int sourceH = type->mHal.state.lodDimY[lod]; 481 482 float pixelU = u * (float)sourceW; 483 float pixelV = v * (float)sourceH; 484 int iPixelU = (int)pixelU; 485 int iPixelV = (int)pixelV; 486 487 float fracU = pixelU - iPixelU; 488 float fracV = pixelV - iPixelV; 489 490 if (fracU < 0.5f) { 491 iPixelU -= 1; 492 fracU += 0.5f; 493 } else { 494 fracU -= 0.5f; 495 } 496 if (fracV < 0.5f) { 497 iPixelV -= 1; 498 fracV += 0.5f; 499 } else { 500 fracV -= 0.5f; 501 } 502 float oneMinusFracU = 1.0f - fracU; 503 float oneMinusFracV = 1.0f - fracV; 504 505 float w1 = oneMinusFracU * oneMinusFracV; 506 float w2 = fracU * oneMinusFracV; 507 float w3 = oneMinusFracU * fracV; 508 float w4 = fracU * fracV; 509 510 int nextX = applyWrapMode(wrapS, iPixelU + 1, sourceW); 511 int nextY = applyWrapMode(wrapT, iPixelV + 1, sourceH); 512 int locX = applyWrapMode(wrapS, iPixelU, sourceW); 513 int locY = applyWrapMode(wrapT, iPixelV, sourceH); 514 515 const uint8_t *ptr = (const uint8_t *)a->mHal.drvState.lod[lod].mallocPtr; 516 size_t stride = a->mHal.drvState.lod[lod].stride; 517 518 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 519 return getSample2D_565(ptr, stride, locX, locY, nextX, nextY, w1, w2, w3, w4); 520 } 521 522 return GetBilinearSampleTable2D[dk](ptr, stride, locX, locY, nextX, nextY, w1, w2, w3, w4); 523} 524 525static float4 526 sample_LOD_LinearPixel_Clamp(Allocation *a, const Type *type, 527 RsDataKind dk, RsDataType dt, 528 Sampler *s, float u, float v, int32_t lod) { 529 const RsSamplerValue wrapS = s->mHal.state.wrapS; 530 const RsSamplerValue wrapT = s->mHal.state.wrapT; 531 const int sourceW = type->mHal.state.lodDimX[lod]; 532 const int sourceH = type->mHal.state.lodDimY[lod]; 533 534 float pixelU = u * (float)sourceW; 535 float pixelV = v * (float)sourceH; 536 int iPixelU = (int)pixelU; 537 int iPixelV = (int)pixelV; 538 539 float fracU = pixelU - iPixelU; 540 float fracV = pixelV - iPixelV; 541 542 if (fracU < 0.5f) { 543 iPixelU -= 1; 544 fracU += 0.5f; 545 } else { 546 fracU -= 0.5f; 547 } 548 if (fracV < 0.5f) { 549 iPixelV -= 1; 550 fracV += 0.5f; 551 } else { 552 fracV -= 0.5f; 553 } 554 float oneMinusFracU = 1.0f - fracU; 555 float oneMinusFracV = 1.0f - fracV; 556 557 float w1 = oneMinusFracU * oneMinusFracV; 558 float w2 = fracU * oneMinusFracV; 559 float w3 = oneMinusFracU * fracV; 560 float w4 = fracU * fracV; 561 562 int nextX = rsMax(0, rsMin(iPixelU + 1, sourceW - 1)); 563 int nextY = rsMax(0, rsMin(iPixelV + 1, sourceH - 1)); 564 int locX = rsMax(0, rsMin(iPixelU, sourceW - 1)); 565 int locY = rsMax(0, rsMin(iPixelV, sourceH - 1)); 566 567 const uint8_t *ptr = (const uint8_t *)a->mHal.drvState.lod[lod].mallocPtr; 568 size_t stride = a->mHal.drvState.lod[lod].stride; 569 570 return GetBilinearSampleTable2D[dk](ptr, stride, locX, locY, nextX, nextY, w1, w2, w3, w4); 571} 572 573static float4 574 sample_LOD_NearestPixel(Allocation *a, const Type *type, 575 RsDataKind dk, RsDataType dt, 576 Sampler *s, 577 float u, float v, int32_t lod) { 578 RsSamplerValue wrapS = s->mHal.state.wrapS; 579 RsSamplerValue wrapT = s->mHal.state.wrapT; 580 581 int32_t sourceW = type->mHal.state.lodDimX[lod]; 582 int32_t sourceH = type->mHal.state.lodDimY[lod]; 583 584 int locX = applyWrapMode(wrapS, u * sourceW, sourceW); 585 int locY = applyWrapMode(wrapT, v * sourceH, sourceH); 586 587 588 const uint8_t *ptr = (const uint8_t *)a->mHal.drvState.lod[lod].mallocPtr; 589 size_t stride = a->mHal.drvState.lod[lod].stride; 590 591 float4 result = {0.f, 0.f, 0.f, 1.f}; 592 if (dt == RS_TYPE_UNSIGNED_5_6_5) { 593 result.xyz = getElementAt565(ptr, stride, locX, locY); 594 return result; 595 } 596 597 switch(dk) { 598 case RS_KIND_PIXEL_L: 599 { 600 float t = getElementAt1(ptr, stride, locX, locY); 601 result.xyz = t; 602 } 603 break; 604 case RS_KIND_PIXEL_A: 605 result.w = getElementAt1(ptr, stride, locX, locY); 606 break; 607 case RS_KIND_PIXEL_LA: 608 { 609 float2 t = getElementAt2(ptr, stride, locX, locY); 610 result.xyz = t.x; 611 result.w = t.y; 612 } 613 break; 614 case RS_KIND_PIXEL_RGB: 615 result.xyz = getElementAt3(ptr, stride, locX, locY); 616 break; 617 case RS_KIND_PIXEL_RGBA: 618 result = getElementAt4(ptr, stride, locX, locY); 619 break; 620 621 622 case RS_KIND_PIXEL_YUV: 623 case RS_KIND_USER: 624 case RS_KIND_INVALID: 625 case RS_KIND_PIXEL_DEPTH: 626 rsAssert(0); 627 break; 628 } 629 630 return result * (1.f / 255.f); 631} 632 633 634 635static float4 GenericSample1D(Allocation *a, Sampler *s, float u, float lod) { 636 const Type *type = a->getType(); 637 const Element *elem = type->getElement(); 638 const RsDataKind dk = elem->getKind(); 639 const RsDataType dt = elem->getType(); 640 641 if (dk == RS_KIND_USER || (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5)) { 642 return 0.f; 643 } 644 645 if (!(a->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)) { 646 const Context *rsc = RsdCpuReference::getTlsContext(); 647 rsc->setError(RS_ERROR_BAD_VALUE, "Sampling from texture witout USAGE_GRAPHICS_TEXTURE."); 648 return 0.f; 649 } 650 651 if (lod <= 0.0f) { 652 if (s->mHal.state.magFilter == RS_SAMPLER_NEAREST) { 653 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, 0); 654 } 655 return sample_LOD_LinearPixel(a, type, dk, dt, s, u, 0); 656 } 657 658 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_NEAREST) { 659 int32_t maxLOD = type->mHal.state.lodCount - 1; 660 lod = rsMin(lod, (float)maxLOD); 661 int32_t nearestLOD = (int32_t)round(lod); 662 return sample_LOD_LinearPixel(a, type, dk, dt, s, u, nearestLOD); 663 } 664 665 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_LINEAR) { 666 int32_t lod0 = (int32_t)floor(lod); 667 int32_t lod1 = (int32_t)ceil(lod); 668 int32_t maxLOD = type->mHal.state.lodCount - 1; 669 lod0 = rsMin(lod0, maxLOD); 670 lod1 = rsMin(lod1, maxLOD); 671 float4 sample0 = sample_LOD_LinearPixel(a, type, dk, dt, s, u, lod0); 672 float4 sample1 = sample_LOD_LinearPixel(a, type, dk, dt, s, u, lod1); 673 float frac = lod - (float)lod0; 674 return sample0 * (1.0f - frac) + sample1 * frac; 675 } 676 677 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, 0); 678} 679 680static float4 GenericSample2D(Allocation *a, Sampler *s, float u, float v, float lod) { 681 const Type *type = a->getType(); 682 const Element *elem = type->getElement(); 683 const RsDataKind dk = elem->getKind(); 684 const RsDataType dt = elem->getType(); 685 686 if (dk == RS_KIND_USER || (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5)) { 687 return 0.f; 688 } 689 690 if (!(a->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)) { 691 const Context *rsc = RsdCpuReference::getTlsContext(); 692 rsc->setError(RS_ERROR_BAD_VALUE, "Sampling from texture witout USAGE_GRAPHICS_TEXTURE."); 693 return 0.f; 694 } 695 696 if (lod <= 0.0f) { 697 if (s->mHal.state.magFilter == RS_SAMPLER_NEAREST) { 698 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, v, 0); 699 } 700 return sample_LOD_LinearPixel(a, type, dk, dt, s, u, v, 0); 701 } 702 703 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_NEAREST) { 704 int32_t maxLOD = type->mHal.state.lodCount - 1; 705 lod = rsMin(lod, (float)maxLOD); 706 int32_t nearestLOD = (int32_t)round(lod); 707 return sample_LOD_LinearPixel(a, type, dk, dt, s, u, v, nearestLOD); 708 } 709 710 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_LINEAR) { 711 int32_t lod0 = (int32_t)floor(lod); 712 int32_t lod1 = (int32_t)ceil(lod); 713 int32_t maxLOD = type->mHal.state.lodCount - 1; 714 lod0 = rsMin(lod0, maxLOD); 715 lod1 = rsMin(lod1, maxLOD); 716 float4 sample0 = sample_LOD_LinearPixel(a, type, dk, dt, s, u, v, lod0); 717 float4 sample1 = sample_LOD_LinearPixel(a, type, dk, dt, s, u, v, lod1); 718 float frac = lod - (float)lod0; 719 return sample0 * (1.0f - frac) + sample1 * frac; 720 } 721 722 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, v, 0); 723} 724 725 726static float4 GenericSample2D_Clamp(Allocation *a, Sampler *s, float u, float v, float lod) { 727 const Type *type = a->getType(); 728 const Element *elem = type->getElement(); 729 const RsDataKind dk = elem->getKind(); 730 const RsDataType dt = elem->getType(); 731 732 if (!(a->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)) { 733 const Context *rsc = RsdCpuReference::getTlsContext(); 734 rsc->setError(RS_ERROR_BAD_VALUE, "Sampling from texture witout USAGE_GRAPHICS_TEXTURE."); 735 return 0.f; 736 } 737 738 if (lod <= 0.0f) { 739 if (s->mHal.state.magFilter == RS_SAMPLER_NEAREST) { 740 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, v, 0); 741 } 742 return sample_LOD_LinearPixel_Clamp(a, type, dk, dt, s, u, v, 0); 743 } 744 745 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_NEAREST) { 746 int32_t maxLOD = type->mHal.state.lodCount - 1; 747 lod = rsMin(lod, (float)maxLOD); 748 int32_t nearestLOD = (int32_t)round(lod); 749 return sample_LOD_LinearPixel_Clamp(a, type, dk, dt, s, u, v, nearestLOD); 750 } 751 752 if (s->mHal.state.minFilter == RS_SAMPLER_LINEAR_MIP_LINEAR) { 753 int32_t lod0 = (int32_t)floor(lod); 754 int32_t lod1 = (int32_t)ceil(lod); 755 int32_t maxLOD = type->mHal.state.lodCount - 1; 756 lod0 = rsMin(lod0, maxLOD); 757 lod1 = rsMin(lod1, maxLOD); 758 float4 sample0 = sample_LOD_LinearPixel_Clamp(a, type, dk, dt, s, u, v, lod0); 759 float4 sample1 = sample_LOD_LinearPixel_Clamp(a, type, dk, dt, s, u, v, lod1); 760 float frac = lod - (float)lod0; 761 return sample0 * (1.0f - frac) + sample1 * frac; 762 } 763 764 return sample_LOD_NearestPixel(a, type, dk, dt, s, u, v, 0); 765} 766 767 768 769// Must match pixel kind in rsDefines.h 770static void * NearestWrap[] = { 771 (void *) GenericSample1D, // L, 772 (void *) GenericSample1D, // A, 773 (void *) GenericSample1D, // LA, 774 (void *) GenericSample1D, // RGB, 775 (void *) GenericSample1D, // RGBA, 776 0, 777 (void *) GenericSample1D, // YUV 778 779 (void *) GenericSample2D, // L, 780 (void *) GenericSample2D, // A, 781 (void *) GenericSample2D, // LA, 782 (void *) GenericSample2D, // RGB, 783 (void *) GenericSample2D, // RGBA, 784 0, 785 (void *) GenericSample2D, // YUV 786}; 787 788static void * NearestClamp[] = { 789 (void *) GenericSample1D, // L, 790 (void *) GenericSample1D, // A, 791 (void *) GenericSample1D, // LA, 792 (void *) GenericSample1D, // RGB, 793 (void *) GenericSample1D, // RGBA, 794 0, 795 (void *) GenericSample1D, // YUV 796 797 (void *) GenericSample2D, // L, 798 (void *) GenericSample2D, // A, 799 (void *) GenericSample2D, // LA, 800 (void *) GenericSample2D, // RGB, 801 (void *) GenericSample2D, // RGBA, 802 0, 803 (void *) GenericSample2D, // YUV 804}; 805 806static void * NearestMirroredRepeat[] = { 807 (void *) GenericSample1D, // L, 808 (void *) GenericSample1D, // A, 809 (void *) GenericSample1D, // LA, 810 (void *) GenericSample1D, // RGB, 811 (void *) GenericSample1D, // RGBA, 812 0, 813 (void *) GenericSample1D, // YUV 814 815 (void *) GenericSample2D, // L, 816 (void *) GenericSample2D, // A, 817 (void *) GenericSample2D, // LA, 818 (void *) GenericSample2D, // RGB, 819 (void *) GenericSample2D, // RGBA, 820 0, 821 (void *) GenericSample2D, // YUV 822}; 823 824// Must match pixel kind in rsDefines.h 825static void * LinearWrap[] = { 826 (void *) GenericSample1D, // L, 827 (void *) GenericSample1D, // A, 828 (void *) GenericSample1D, // LA, 829 (void *) GenericSample1D, // RGB, 830 (void *) GenericSample1D, // RGBA, 831 0, 832 (void *) GenericSample1D, // YUV 833 834 (void *) GenericSample2D, // L, 835 (void *) GenericSample2D, // A, 836 (void *) GenericSample2D, // LA, 837 (void *) GenericSample2D, // RGB, 838 (void *) GenericSample2D, // RGBA, 839 0, 840 (void *) GenericSample2D, // YUV 841}; 842 843// Must match pixel kind in rsDefines.h 844static void * LinearClamp[] = { 845 (void *) GenericSample1D, // L, 846 (void *) GenericSample1D, // A, 847 (void *) GenericSample1D, // LA, 848 (void *) GenericSample1D, // RGB, 849 (void *) GenericSample1D, // RGBA, 850 0, 851 (void *) GenericSample1D, // YUV 852 853 (void *) GenericSample2D_Clamp, // L, 854 (void *) GenericSample2D_Clamp, // A, 855 (void *) GenericSample2D_Clamp, // LA, 856 (void *) GenericSample2D, // RGB, 857 (void *) GenericSample2D_Clamp, // RGBA, 858 0, 859 (void *) GenericSample2D, // YUV 860}; 861 862// Must match pixel kind in rsDefines.h 863static void * LinearMirroredRepeat[] = { 864 (void *) GenericSample1D, // L, 865 (void *) GenericSample1D, // A, 866 (void *) GenericSample1D, // LA, 867 (void *) GenericSample1D, // RGB, 868 (void *) GenericSample1D, // RGBA, 869 0, 870 (void *) GenericSample1D, // YUV 871 872 (void *) GenericSample2D, // L, 873 (void *) GenericSample2D, // A, 874 (void *) GenericSample2D, // LA, 875 (void *) GenericSample2D, // RGB, 876 (void *) GenericSample2D, // RGBA, 877 0, 878 (void *) GenericSample2D, // YUV 879}; 880 881// Must match pixel kind in rsDefines.h 882static void * Generic[] = { 883 (void *) GenericSample1D, // L, 884 (void *) GenericSample1D, // A, 885 (void *) GenericSample1D, // LA, 886 (void *) GenericSample1D, // RGB, 887 (void *) GenericSample1D, // RGBA, 888 0, 889 (void *) GenericSample1D, // YUV 890 891 (void *) GenericSample2D, // L, 892 (void *) GenericSample2D, // A, 893 (void *) GenericSample2D, // LA, 894 (void *) GenericSample2D, // RGB, 895 (void *) GenericSample2D, // RGBA, 896 0, 897 (void *) GenericSample2D, // YUV 898}; 899#endif 900 901bool rsdSamplerInit(const Context *, const Sampler *s) { 902#if 0 903 s->mHal.drv = Generic; 904 905 if ((s->mHal.state.minFilter == s->mHal.state.magFilter) && 906 (s->mHal.state.wrapS == s->mHal.state.wrapT)) { 907 // We have fast paths for these. 908 909 switch(s->mHal.state.minFilter) { 910 case RS_SAMPLER_NEAREST: 911 switch(s->mHal.state.wrapS) { 912 case RS_SAMPLER_WRAP: 913 s->mHal.drv = NearestWrap; 914 break; 915 case RS_SAMPLER_CLAMP: 916 s->mHal.drv = NearestClamp; 917 break; 918 case RS_SAMPLER_MIRRORED_REPEAT: 919 s->mHal.drv = NearestMirroredRepeat; 920 break; 921 default: 922 break; 923 } 924 break; 925 case RS_SAMPLER_LINEAR: 926 switch(s->mHal.state.wrapS) { 927 case RS_SAMPLER_WRAP: 928 s->mHal.drv = LinearWrap; 929 break; 930 case RS_SAMPLER_CLAMP: 931 s->mHal.drv = LinearClamp; 932 break; 933 case RS_SAMPLER_MIRRORED_REPEAT: 934 s->mHal.drv = LinearMirroredRepeat; 935 break; 936 default: 937 break; 938 } 939 break; 940 case RS_SAMPLER_LINEAR_MIP_LINEAR: 941 switch(s->mHal.state.wrapS) { 942 case RS_SAMPLER_WRAP: 943 s->mHal.drv = LinearWrap; 944 break; 945 case RS_SAMPLER_CLAMP: 946 s->mHal.drv = LinearClamp; 947 break; 948 case RS_SAMPLER_MIRRORED_REPEAT: 949 s->mHal.drv = LinearMirroredRepeat; 950 break; 951 default: 952 break; 953 } 954 break; 955 default: 956 rsAssert(0); 957 break; 958 } 959 960 } 961#endif 962 return true; 963} 964 965void rsdSamplerDestroy(const android::renderscript::Context *rsc, 966 const android::renderscript::Sampler *s) { 967} 968