1/*
2 * Copyright (C) 2008 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
17package android.renderscript;
18
19/**
20 * Sampler object that defines how Allocations can be read as textures within a
21 * kernel. Samplers are used in conjunction with the {@code rsSample} runtime
22 * function to return values from normalized coordinates.
23 *
24 * Any Allocation used with a Sampler must have been created with {@link
25 * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE}; using a Sampler on
26 * an {@link android.renderscript.Allocation} that was not created with {@link
27 * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE} is undefined.
28 **/
29public class Sampler extends BaseObj {
30    public enum Value {
31        NEAREST (0),
32        LINEAR (1),
33        LINEAR_MIP_LINEAR (2),
34        LINEAR_MIP_NEAREST (5),
35        WRAP (3),
36        CLAMP (4),
37        MIRRORED_REPEAT (6);
38
39        int mID;
40        Value(int id) {
41            mID = id;
42        }
43    }
44
45    Value mMin;
46    Value mMag;
47    Value mWrapS;
48    Value mWrapT;
49    Value mWrapR;
50    float mAniso;
51
52    Sampler(long id, RenderScript rs) {
53        super(id, rs);
54        guard.open("destroy");
55    }
56
57    /**
58     * @return minification setting for the sampler
59     */
60    public Value getMinification() {
61        return mMin;
62    }
63
64    /**
65     * @return magnification setting for the sampler
66     */
67    public Value getMagnification() {
68        return mMag;
69    }
70
71    /**
72     * @return S wrapping mode for the sampler
73     */
74    public Value getWrapS() {
75        return mWrapS;
76    }
77
78    /**
79     * @return T wrapping mode for the sampler
80     */
81    public Value getWrapT() {
82        return mWrapT;
83    }
84
85    /**
86     * @return anisotropy setting for the sampler
87     */
88    public float getAnisotropy() {
89        return mAniso;
90    }
91
92    /**
93     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
94     * clamp.
95     *
96     * @param rs Context to which the sampler will belong.
97     *
98     * @return Sampler
99     */
100    public static Sampler CLAMP_NEAREST(RenderScript rs) {
101        if (rs.mSampler_CLAMP_NEAREST == null) {
102            synchronized (rs) {
103                if (rs.mSampler_CLAMP_NEAREST == null) {
104                    Builder b = new Builder(rs);
105                    b.setMinification(Value.NEAREST);
106                    b.setMagnification(Value.NEAREST);
107                    b.setWrapS(Value.CLAMP);
108                    b.setWrapT(Value.CLAMP);
109                    rs.mSampler_CLAMP_NEAREST = b.create();
110                }
111            }
112        }
113        return rs.mSampler_CLAMP_NEAREST;
114    }
115
116    /**
117     * Retrieve a sampler with min and mag set to linear and wrap modes set to
118     * clamp.
119     *
120     * @param rs Context to which the sampler will belong.
121     *
122     * @return Sampler
123     */
124    public static Sampler CLAMP_LINEAR(RenderScript rs) {
125        if (rs.mSampler_CLAMP_LINEAR == null) {
126            synchronized (rs) {
127                if (rs.mSampler_CLAMP_LINEAR == null) {
128                    Builder b = new Builder(rs);
129                    b.setMinification(Value.LINEAR);
130                    b.setMagnification(Value.LINEAR);
131                    b.setWrapS(Value.CLAMP);
132                    b.setWrapT(Value.CLAMP);
133                    rs.mSampler_CLAMP_LINEAR = b.create();
134                }
135            }
136        }
137        return rs.mSampler_CLAMP_LINEAR;
138    }
139
140    /**
141     * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
142     * wrap modes set to clamp.
143     *
144     * @param rs Context to which the sampler will belong.
145     *
146     * @return Sampler
147     */
148    public static Sampler CLAMP_LINEAR_MIP_LINEAR(RenderScript rs) {
149        if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
150            synchronized (rs) {
151                if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
152                    Builder b = new Builder(rs);
153                    b.setMinification(Value.LINEAR_MIP_LINEAR);
154                    b.setMagnification(Value.LINEAR);
155                    b.setWrapS(Value.CLAMP);
156                    b.setWrapT(Value.CLAMP);
157                    rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
158                }
159            }
160        }
161        return rs.mSampler_CLAMP_LINEAR_MIP_LINEAR;
162    }
163
164    /**
165     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
166     * wrap.
167     *
168     * @param rs Context to which the sampler will belong.
169     *
170     * @return Sampler
171     */
172    public static Sampler WRAP_NEAREST(RenderScript rs) {
173        if (rs.mSampler_WRAP_NEAREST == null) {
174            synchronized (rs) {
175                if (rs.mSampler_WRAP_NEAREST == null) {
176                    Builder b = new Builder(rs);
177                    b.setMinification(Value.NEAREST);
178                    b.setMagnification(Value.NEAREST);
179                    b.setWrapS(Value.WRAP);
180                    b.setWrapT(Value.WRAP);
181                    rs.mSampler_WRAP_NEAREST = b.create();
182                }
183            }
184        }
185        return rs.mSampler_WRAP_NEAREST;
186    }
187
188    /**
189     * Retrieve a sampler with min and mag set to linear and wrap modes set to
190     * wrap.
191     *
192     * @param rs Context to which the sampler will belong.
193     *
194     * @return Sampler
195     */
196    public static Sampler WRAP_LINEAR(RenderScript rs) {
197        if (rs.mSampler_WRAP_LINEAR == null) {
198            synchronized (rs) {
199                if (rs.mSampler_WRAP_LINEAR == null) {
200                    Builder b = new Builder(rs);
201                    b.setMinification(Value.LINEAR);
202                    b.setMagnification(Value.LINEAR);
203                    b.setWrapS(Value.WRAP);
204                    b.setWrapT(Value.WRAP);
205                    rs.mSampler_WRAP_LINEAR = b.create();
206                }
207            }
208        }
209        return rs.mSampler_WRAP_LINEAR;
210    }
211
212    /**
213     * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
214     * wrap modes set to wrap.
215     *
216     * @param rs Context to which the sampler will belong.
217     *
218     * @return Sampler
219     */
220    public static Sampler WRAP_LINEAR_MIP_LINEAR(RenderScript rs) {
221        if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
222            synchronized (rs) {
223                if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
224                    Builder b = new Builder(rs);
225                    b.setMinification(Value.LINEAR_MIP_LINEAR);
226                    b.setMagnification(Value.LINEAR);
227                    b.setWrapS(Value.WRAP);
228                    b.setWrapT(Value.WRAP);
229                    rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
230                }
231            }
232        }
233        return rs.mSampler_WRAP_LINEAR_MIP_LINEAR;
234    }
235
236    /**
237     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
238     * mirrored repeat.
239     *
240     * @param rs Context to which the sampler will belong.
241     *
242     * @return Sampler
243     */
244    public static Sampler MIRRORED_REPEAT_NEAREST(RenderScript rs) {
245        if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
246            synchronized (rs) {
247                if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
248                    Builder b = new Builder(rs);
249                    b.setMinification(Value.NEAREST);
250                    b.setMagnification(Value.NEAREST);
251                    b.setWrapS(Value.MIRRORED_REPEAT);
252                    b.setWrapT(Value.MIRRORED_REPEAT);
253                    rs.mSampler_MIRRORED_REPEAT_NEAREST = b.create();
254                }
255            }
256        }
257        return rs.mSampler_MIRRORED_REPEAT_NEAREST;
258    }
259
260    /**
261     * Retrieve a sampler with min and mag set to linear and wrap modes set to
262     * mirrored repeat.
263     *
264     * @param rs Context to which the sampler will belong.
265     *
266     * @return Sampler
267     */
268    public static Sampler MIRRORED_REPEAT_LINEAR(RenderScript rs) {
269        if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
270            synchronized (rs) {
271                if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
272                    Builder b = new Builder(rs);
273                    b.setMinification(Value.LINEAR);
274                    b.setMagnification(Value.LINEAR);
275                    b.setWrapS(Value.MIRRORED_REPEAT);
276                    b.setWrapT(Value.MIRRORED_REPEAT);
277                    rs.mSampler_MIRRORED_REPEAT_LINEAR = b.create();
278                }
279            }
280        }
281        return rs.mSampler_MIRRORED_REPEAT_LINEAR;
282    }
283
284    /**
285     * Retrieve a sampler with min and mag set to linear and wrap modes set to
286     * mirrored repeat.
287     *
288     * @param rs Context to which the sampler will belong.
289     *
290     * @return Sampler
291     */
292    public static Sampler MIRRORED_REPEAT_LINEAR_MIP_LINEAR(RenderScript rs) {
293        if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
294            synchronized (rs) {
295                if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
296                    Builder b = new Builder(rs);
297                    b.setMinification(Value.LINEAR_MIP_LINEAR);
298                    b.setMagnification(Value.LINEAR);
299                    b.setWrapS(Value.MIRRORED_REPEAT);
300                    b.setWrapT(Value.MIRRORED_REPEAT);
301                    rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR = b.create();
302                }
303            }
304        }
305        return rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
306    }
307
308    /**
309     * Builder for creating non-standard samplers.  This is only necessary if
310     * a Sampler with different min and mag modes is desired.
311     */
312    public static class Builder {
313        RenderScript mRS;
314        Value mMin;
315        Value mMag;
316        Value mWrapS;
317        Value mWrapT;
318        Value mWrapR;
319        float mAniso;
320
321        public Builder(RenderScript rs) {
322            mRS = rs;
323            mMin = Value.NEAREST;
324            mMag = Value.NEAREST;
325            mWrapS = Value.WRAP;
326            mWrapT = Value.WRAP;
327            mWrapR = Value.WRAP;
328            mAniso = 1.0f;
329        }
330
331        public void setMinification(Value v) {
332            if (v == Value.NEAREST ||
333                v == Value.LINEAR ||
334                v == Value.LINEAR_MIP_LINEAR ||
335                v == Value.LINEAR_MIP_NEAREST) {
336                mMin = v;
337            } else {
338                throw new IllegalArgumentException("Invalid value");
339            }
340        }
341
342        public void setMagnification(Value v) {
343            if (v == Value.NEAREST || v == Value.LINEAR) {
344                mMag = v;
345            } else {
346                throw new IllegalArgumentException("Invalid value");
347            }
348        }
349
350        public void setWrapS(Value v) {
351            if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
352                mWrapS = v;
353            } else {
354                throw new IllegalArgumentException("Invalid value");
355            }
356        }
357
358        public void setWrapT(Value v) {
359            if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
360                mWrapT = v;
361            } else {
362                throw new IllegalArgumentException("Invalid value");
363            }
364        }
365
366        public void setAnisotropy(float v) {
367            if(v >= 0.0f) {
368                mAniso = v;
369            } else {
370                throw new IllegalArgumentException("Invalid value");
371            }
372        }
373
374        public Sampler create() {
375            mRS.validate();
376            long id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
377                                        mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso);
378            Sampler sampler = new Sampler(id, mRS);
379            sampler.mMin = mMin;
380            sampler.mMag = mMag;
381            sampler.mWrapS = mWrapS;
382            sampler.mWrapT = mWrapT;
383            sampler.mWrapR = mWrapR;
384            sampler.mAniso = mAniso;
385            return sampler;
386        }
387    }
388
389}
390
391