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