rs_sample.c 22 KB

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