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