1/*
2* Copyright (C) 2016 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#include <memory>
18
19#include <jni.h>
20#include <RenderScript.h>
21
22#include "ScriptC_allocs.h"
23
24sp<RS> mRS;
25
26sp<Allocation> mBoolAllocation;  // boolean
27
28sp<Allocation> mCharAllocation;  // char
29sp<Allocation> mChar2Allocation;   // char2
30sp<Allocation> mChar3Allocation;   // char3
31sp<Allocation> mChar4Allocation;   // char4
32
33sp<Allocation> mUCharAllocation;   // uchar
34sp<Allocation> mUChar2Allocation;  // uchar2
35sp<Allocation> mUChar3Allocation;  // uchar3
36sp<Allocation> mUChar4Allocation;  // uchar4
37
38sp<Allocation> mShortAllocation;   // short
39sp<Allocation> mShort2Allocation;  // short2
40sp<Allocation> mShort3Allocation;  // short3
41sp<Allocation> mShort4Allocation;  // short4
42
43sp<Allocation> mUShortAllocation;  // ushort
44sp<Allocation> mUShort2Allocation; // ushort2
45sp<Allocation> mUShort3Allocation; // ushort3
46sp<Allocation> mUShort4Allocation; // ushort4
47
48sp<Allocation> mIntAllocation;   // int
49sp<Allocation> mInt2Allocation;  // int2
50sp<Allocation> mInt3Allocation;  // int3
51sp<Allocation> mInt4Allocation;  // int4
52
53sp<Allocation> mUIntAllocation;  // uint
54sp<Allocation> mUInt2Allocation;   // uint2
55sp<Allocation> mUInt3Allocation;   // uint3
56sp<Allocation> mUInt4Allocation;   // uint4
57
58sp<Allocation> mLongAllocation;  // long
59sp<Allocation> mLong2Allocation;   // long2
60sp<Allocation> mLong3Allocation;   // long3
61sp<Allocation> mLong4Allocation;   // long4
62
63sp<Allocation> mULongAllocation;   // ulong
64sp<Allocation> mULong2Allocation;  // ulong2
65sp<Allocation> mULong3Allocation;  // ulong3
66sp<Allocation> mULong4Allocation;  // ulong4
67
68sp<Allocation> mHalfAllocation;  // half
69sp<Allocation> mHalf2Allocation;   // half2
70sp<Allocation> mHalf3Allocation;   // half3
71sp<Allocation> mHalf4Allocation;   // half4
72
73sp<Allocation> mFloatAllocation;   // float
74sp<Allocation> mFloat2Allocation;  // float2
75sp<Allocation> mFloat3Allocation;  // float3
76sp<Allocation> mFloat4Allocation;  // float4
77
78sp<Allocation> mDoubleAllocation;  // double
79sp<Allocation> mDouble2Allocation; // double2
80sp<Allocation> mDouble3Allocation; // double3
81sp<Allocation> mDouble4Allocation; // double4
82
83const int mAllocSize = 24; // Needs to be < CHAR_MAX and divisible by 4.
84const int mBitmapSize = 64;
85
86void createSignedAllocations() {
87    Type::Builder typeI8Builder(mRS, Element::I8(mRS));
88    typeI8Builder.setX(1); // One element here to test 16 byte memory alignment
89    typeI8Builder.setY(3);
90    typeI8Builder.setZ(8);
91
92    mCharAllocation = Allocation::createTyped(mRS, typeI8Builder.create());
93    mChar2Allocation = Allocation::createSized(mRS, Element::I8_2(mRS), mAllocSize / 2);
94    mChar3Allocation = Allocation::createSized(mRS, Element::I8_3(mRS), mAllocSize / 4);
95    mChar4Allocation = Allocation::createSized(mRS, Element::I8_4(mRS), mAllocSize / 4);
96
97    Type::Builder typeI16_2Builder(mRS, Element::I16_2(mRS));
98    typeI16_2Builder.setX(6);
99    typeI16_2Builder.setY(1);
100    typeI16_2Builder.setZ(2);
101
102    mShortAllocation = Allocation::createSized(mRS, Element::I16(mRS), mAllocSize);
103    mShort2Allocation = Allocation::createTyped(mRS, typeI16_2Builder.create());
104    mShort3Allocation = Allocation::createSized(mRS, Element::I16_3(mRS), mAllocSize / 4);
105    mShort4Allocation = Allocation::createSized(mRS, Element::I16_4(mRS), mAllocSize / 4);
106
107    Type::Builder typeI32_3Builder(mRS, Element::I32_3(mRS));
108    typeI32_3Builder.setX(3);
109    typeI32_3Builder.setY(2);
110
111    mIntAllocation = Allocation::createSized(mRS, Element::I32(mRS), mAllocSize);
112    mInt2Allocation = Allocation::createSized(mRS, Element::I32_2(mRS), mAllocSize / 2);
113    mInt3Allocation = Allocation::createTyped(mRS, typeI32_3Builder.create());
114    mInt4Allocation = Allocation::createSized(mRS, Element::I32_4(mRS), mAllocSize / 4);
115
116    Type::Builder typeI64_4Builder(mRS, Element::I64_4(mRS));
117    typeI64_4Builder.setX(1);
118    typeI64_4Builder.setY(6);
119
120    mLongAllocation = Allocation::createSized(mRS, Element::I64(mRS), mAllocSize);
121    mLong2Allocation = Allocation::createSized(mRS, Element::I64_2(mRS), mAllocSize / 2);
122    mLong3Allocation = Allocation::createSized(mRS, Element::I64_3(mRS), mAllocSize / 4);
123    mLong4Allocation = Allocation::createTyped(mRS, typeI64_4Builder.create());
124
125    mBoolAllocation = Allocation::createSized(mRS, Element::BOOLEAN(mRS), mAllocSize);
126}
127
128void initSignedAllocations() {
129    char *buffer_char = new char[mAllocSize];
130    short *buffer_short = new short[mAllocSize];
131    int *buffer_int = new int[mAllocSize];
132    int64_t *buffer_long = new int64_t[mAllocSize];
133    char *buffer_bool = new char[mAllocSize];
134
135    for(int i = 0; i < mAllocSize; ++i) {
136        buffer_char[i] = (char) i;
137        buffer_short[i] = (short) i;
138        buffer_int[i] = (int) i;
139        buffer_long[i] = (int64_t) i;
140        buffer_bool[i] =  (char) (0x01 & i);
141    }
142
143    mCharAllocation->copy3DRangeFrom(0, 0, 0, 1, 3, 8, buffer_char);
144    mChar2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_char);
145    mChar3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_char);
146    mChar4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_char);
147
148    delete [] buffer_char;
149
150    mShortAllocation->copy1DRangeFrom(0, mAllocSize, buffer_short);
151    mShort2Allocation->copy3DRangeFrom(0, 0, 0, 6, 1, 2, buffer_short);
152    mShort3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_short);
153    mShort4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_short);
154
155    delete [] buffer_short;
156
157    mIntAllocation->copy1DRangeFrom(0, mAllocSize, buffer_int);
158    mInt2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_int);
159    mInt3Allocation->copy2DRangeFrom(0, 0, 3, 2, buffer_int);
160    mInt4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_int);
161
162    delete [] buffer_int;
163
164    mLongAllocation->copy1DRangeFrom(0, mAllocSize, buffer_long);
165    mLong2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_long);
166    mLong3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_long);
167    mLong4Allocation->copy2DRangeFrom(0, 0, 1, 6, buffer_long);
168
169    delete [] buffer_long;
170
171    mBoolAllocation->copy1DRangeFrom(0, mAllocSize, buffer_bool);
172
173    delete [] buffer_bool;
174}
175
176void createUnsignedAllocations() {
177    Type::Builder typeU8_2Builder(mRS, Element::U8_2(mRS));
178    typeU8_2Builder.setX(2);
179    typeU8_2Builder.setY(6);
180
181    mUCharAllocation = Allocation::createSized(mRS, Element::U8(mRS), mAllocSize);
182    mUChar2Allocation = Allocation::createTyped(mRS, typeU8_2Builder.create());
183    mUChar3Allocation = Allocation::createSized(mRS, Element::U8_3(mRS), mAllocSize / 4);
184    mUChar4Allocation = Allocation::createSized(mRS, Element::U8_4(mRS), mAllocSize / 4);
185
186    Type::Builder typeU16_3Builder(mRS, Element::U16_3(mRS));
187    typeU16_3Builder.setX(1);
188    typeU16_3Builder.setY(6);
189
190    mUShortAllocation = Allocation::createSized(mRS, Element::U16(mRS), mAllocSize);
191    mUShort2Allocation = Allocation::createSized(mRS, Element::U16_2(mRS), mAllocSize / 2);
192    mUShort3Allocation = Allocation::createTyped(mRS, typeU16_3Builder.create());
193    mUShort4Allocation = Allocation::createSized(mRS, Element::U16_4(mRS), mAllocSize / 4);
194
195    Type::Builder typeU32_4Builder(mRS, Element::U32_4(mRS));
196    typeU32_4Builder.setX(1);
197    typeU32_4Builder.setY(1);
198    typeU32_4Builder.setZ(6);
199
200    mUIntAllocation = Allocation::createSized(mRS, Element::U32(mRS), mAllocSize);
201    mUInt2Allocation = Allocation::createSized(mRS, Element::U32_2(mRS), mAllocSize / 2);
202    mUInt3Allocation = Allocation::createSized(mRS, Element::U32_3(mRS), mAllocSize / 4);
203    mUInt4Allocation = Allocation::createTyped(mRS, typeU32_4Builder.create());
204
205    Type::Builder typeU64Builder(mRS, Element::U64(mRS));
206    typeU64Builder.setX(4);
207    typeU64Builder.setY(3);
208    typeU64Builder.setZ(2);
209
210    mULongAllocation = Allocation::createTyped(mRS, typeU64Builder.create());
211    mULong2Allocation = Allocation::createSized(mRS, Element::U64_2(mRS), mAllocSize / 2);
212    mULong3Allocation = Allocation::createSized(mRS, Element::U64_3(mRS), mAllocSize / 4);
213    mULong4Allocation = Allocation::createSized(mRS, Element::U64_4(mRS), mAllocSize / 4);
214}
215
216void initUnsignedAllocations() {
217    char *buffer_char = new char[mAllocSize];
218    short *buffer_short = new short[mAllocSize];
219    int *buffer_int = new int[mAllocSize];
220    uint64_t *buffer_long = new uint64_t[mAllocSize];
221
222    for(int i = 0; i < mAllocSize; ++i) {
223        buffer_char[i] = (char) i;
224        buffer_short[i] = (short) i;
225        buffer_int[i] = (int) i;
226        buffer_long[i] = (uint64_t) i;
227    }
228
229    mUCharAllocation->copy1DRangeFrom(0, mAllocSize, buffer_char);
230    mUChar2Allocation->copy2DRangeFrom(0, 0, 2, 6, buffer_char);
231    mUChar3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_char);
232    mUChar4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_char);
233
234    delete [] buffer_char;
235
236    mUShortAllocation->copy1DRangeFrom(0, mAllocSize, buffer_short);
237    mUShort2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_short);
238    mUShort3Allocation->copy2DRangeFrom(0, 0, 1, 6, buffer_short);
239    mUShort4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_short);
240
241    delete [] buffer_short;
242
243    mUIntAllocation->copy1DRangeFrom(0, mAllocSize, buffer_int);
244    mUInt2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_int);
245    mUInt3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_int);
246    mUInt4Allocation->copy3DRangeFrom(0, 0, 0, 1, 1, 6, buffer_int);
247
248    delete [] buffer_int;
249
250    mULongAllocation->copy3DRangeFrom(0, 0, 0, 4, 3, 2, buffer_long);
251    mULong2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_long);
252    mULong3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_long);
253    mULong4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_long);
254
255    delete [] buffer_long;
256}
257
258void createFloatAllocations() {
259    Type::Builder typeF16_3Builder(mRS, Element::F16_3(mRS));
260    typeF16_3Builder.setX(1);
261    typeF16_3Builder.setY(6);
262
263    mHalfAllocation = Allocation::createSized(mRS, Element::F16(mRS), mAllocSize);
264    mHalf2Allocation = Allocation::createSized(mRS, Element::F16_2(mRS), mAllocSize / 2);
265    mHalf3Allocation = Allocation::createTyped(mRS, typeF16_3Builder.create());
266    mHalf4Allocation = Allocation::createSized(mRS, Element::F16_4(mRS), mAllocSize / 4);
267
268    Type::Builder typeF32_4Builder(mRS, Element::F32_4(mRS));
269    typeF32_4Builder.setX(3);
270    typeF32_4Builder.setY(2);
271
272    mFloatAllocation = Allocation::createSized(mRS, Element::F32(mRS), mAllocSize);
273    mFloat2Allocation = Allocation::createSized(mRS, Element::F32_2(mRS), mAllocSize / 2);
274    mFloat3Allocation = Allocation::createSized(mRS, Element::F32_3(mRS), mAllocSize / 4);
275    mFloat4Allocation = Allocation::createTyped(mRS, typeF32_4Builder.create());
276
277    Type::Builder typeF64_2Builder(mRS, Element::F64_2(mRS));
278    typeF64_2Builder.setX(4);
279    typeF64_2Builder.setY(1);
280    typeF64_2Builder.setZ(3);
281
282    mDoubleAllocation = Allocation::createSized(mRS, Element::F64(mRS), mAllocSize);
283    mDouble2Allocation = Allocation::createTyped(mRS, typeF64_2Builder.create());
284
285    Type::Builder typeF64_3Builder(mRS, Element::F64_3(mRS));
286    typeF64_3Builder.setX(1);
287    typeF64_3Builder.setY(2);
288    typeF64_3Builder.setZ(3);
289
290    Type::Builder typeF64_4Builder(mRS, Element::F64_4(mRS));
291    typeF64_4Builder.setX(1);
292    typeF64_4Builder.setY(2);
293    typeF64_4Builder.setZ(3);
294
295    mDouble3Allocation = Allocation::createTyped(mRS, typeF64_3Builder.create());
296    mDouble4Allocation = Allocation::createTyped(mRS, typeF64_4Builder.create());
297}
298
299void initFloatAllocations() {
300    __fp16 *buffer_half = new __fp16[mAllocSize];
301    float *buffer_float = new float[mAllocSize];
302    double *buffer_double = new double[mAllocSize];
303
304    for(int i = 0; i < mAllocSize; ++i) {
305        buffer_half[i] = (__fp16) 1 / i;
306        buffer_float[i] = (float) 1 / i;
307        buffer_double[i] = (double) 1 / i;
308    }
309
310    mHalfAllocation->copy1DRangeFrom(0, mAllocSize, buffer_half);
311    mHalf2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_half);
312    mHalf3Allocation->copy2DRangeFrom(0, 0, 1, 6, buffer_half);
313    mHalf4Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_half);
314
315    delete [] buffer_half;
316
317    mFloatAllocation->copy1DRangeFrom(0, mAllocSize, buffer_float);
318    mFloat2Allocation->copy1DRangeFrom(0, mAllocSize/2, buffer_float);
319    mFloat3Allocation->copy1DRangeFrom(0, mAllocSize/4, buffer_float);
320    mFloat4Allocation->copy2DRangeFrom(0, 0, 3, 2, buffer_float);
321
322    delete [] buffer_float;
323
324    mDoubleAllocation->copy1DRangeFrom(0, mAllocSize, buffer_double);
325    mDouble2Allocation->copy3DRangeFrom(0, 0, 0, 4, 1, 3, buffer_double);
326    mDouble3Allocation->copy3DRangeFrom(0, 0, 0, 1, 2, 3, buffer_double);
327    mDouble4Allocation->copy3DRangeFrom(0, 0, 0, 1, 2, 3, buffer_double);
328
329    delete [] buffer_double;
330}
331
332extern "C" void JNICALL
333Java_com_android_rs_jniallocations_MainActivity_nativeRS(
334	JNIEnv * env,
335	jclass,
336	jstring pathObj)
337{
338    mRS = new RS();
339
340    const char * path = env->GetStringUTFChars(pathObj, nullptr);
341    mRS->init(path, RS_INIT_LOW_LATENCY | RS_INIT_WAIT_FOR_ATTACH);
342    env->ReleaseStringUTFChars(pathObj, path);
343
344    sp<ScriptC_allocs> mScript = new ScriptC_allocs(mRS);
345
346    Type::Builder typeRGBA_888Builder(mRS, Element::RGBA_8888(mRS));
347    typeRGBA_888Builder.setX(mBitmapSize);
348    typeRGBA_888Builder.setY(mBitmapSize);
349
350    sp<Allocation> mInAllocation = Allocation::createTyped(mRS, typeRGBA_888Builder.create());
351
352    const int image_area = mBitmapSize*mBitmapSize;
353    const int image_size = image_area*sizeof(int);
354
355    char *zero_buffer = new char[image_size];
356    memset(zero_buffer, 0, image_size);
357    mInAllocation->copy1DRangeFrom(0, image_area, zero_buffer);
358    delete [] zero_buffer;
359
360    sp<Allocation> mOutAllocation = Allocation::createTyped(mRS, typeRGBA_888Builder.create());
361    createSignedAllocations();
362    initSignedAllocations();
363
364    mRS->finish();
365    mScript->forEach_swizzle_kernel(mInAllocation, mOutAllocation);
366    mRS->finish();
367
368    mCharAllocation.clear();
369    mChar2Allocation.clear();
370    mChar3Allocation.clear();
371    mChar4Allocation.clear();
372
373    mShort2Allocation.clear();
374    mShort3Allocation.clear();
375    mShort4Allocation.clear();
376
377    mIntAllocation.clear();
378    mInt2Allocation.clear();
379    mInt3Allocation.clear();
380    mInt4Allocation.clear();
381
382    mLongAllocation.clear();
383    mLong2Allocation.clear();
384    mLong3Allocation.clear();
385    mLong4Allocation.clear();
386
387    mBoolAllocation.clear();
388
389    createUnsignedAllocations();
390    initUnsignedAllocations();
391
392    mInAllocation = mUShortAllocation; // Host side assignment
393
394    mRS->finish();
395    mScript->forEach_square_kernel(mInAllocation, mUIntAllocation);
396    mRS->finish();
397
398    mUCharAllocation.clear();
399    mUChar2Allocation.clear();
400    mUChar3Allocation.clear();
401    mUChar4Allocation.clear();
402
403    mUShortAllocation.clear();
404    mUShort2Allocation.clear();
405    mUShort3Allocation.clear();
406    mUShort4Allocation.clear();
407
408    mUInt2Allocation.clear();
409    mUInt3Allocation.clear();
410    mUInt4Allocation.clear();
411
412    mULongAllocation.clear();
413    mULong2Allocation.clear();
414    mULong3Allocation.clear();
415    mULong4Allocation.clear();
416
417    createFloatAllocations();
418    initFloatAllocations();
419
420    mRS->finish();
421    mScript->forEach_add_half_kernel(mDouble4Allocation, mDouble3Allocation);
422    mRS->finish();
423}
424
425