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 
17 package 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  **/
29 public 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;
Value(int id)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 
Sampler(long id, RenderScript rs)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      */
getMinification()60     public Value getMinification() {
61         return mMin;
62     }
63 
64     /**
65      * @return magnification setting for the sampler
66      */
getMagnification()67     public Value getMagnification() {
68         return mMag;
69     }
70 
71     /**
72      * @return S wrapping mode for the sampler
73      */
getWrapS()74     public Value getWrapS() {
75         return mWrapS;
76     }
77 
78     /**
79      * @return T wrapping mode for the sampler
80      */
getWrapT()81     public Value getWrapT() {
82         return mWrapT;
83     }
84 
85     /**
86      * @return anisotropy setting for the sampler
87      */
getAnisotropy()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      */
CLAMP_NEAREST(RenderScript rs)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      */
CLAMP_LINEAR(RenderScript rs)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      */
CLAMP_LINEAR_MIP_LINEAR(RenderScript rs)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      */
WRAP_NEAREST(RenderScript rs)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      */
WRAP_LINEAR(RenderScript rs)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      */
WRAP_LINEAR_MIP_LINEAR(RenderScript rs)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      */
MIRRORED_REPEAT_NEAREST(RenderScript rs)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      */
MIRRORED_REPEAT_LINEAR(RenderScript rs)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      */
MIRRORED_REPEAT_LINEAR_MIP_LINEAR(RenderScript rs)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 
Builder(RenderScript rs)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 
setMinification(Value v)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 
setMagnification(Value v)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 
setWrapS(Value v)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 
setWrapT(Value v)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 
setAnisotropy(float v)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 
create()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