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 com.android.perftest;
18
19import java.io.Writer;
20import java.io.BufferedWriter;
21import java.io.FileWriter;
22import java.io.IOException;
23import java.io.File;
24import java.io.FileOutputStream;
25import java.io.OutputStream;
26
27import android.os.Environment;
28import android.content.res.Resources;
29import android.graphics.Bitmap;
30import android.graphics.BitmapFactory;
31import android.renderscript.*;
32import android.renderscript.Element.DataKind;
33import android.renderscript.Element.DataType;
34import android.renderscript.Allocation.MipmapControl;
35import android.renderscript.Program.TextureType;
36import android.renderscript.ProgramStore.DepthFunc;
37import android.renderscript.ProgramStore.BlendSrcFunc;
38import android.renderscript.ProgramStore.BlendDstFunc;
39import android.renderscript.RenderScript.RSMessageHandler;
40import android.renderscript.Sampler.Value;
41import android.renderscript.Mesh.Primitive;
42import android.renderscript.Matrix4f;
43import android.renderscript.ProgramVertexFixedFunction;
44
45import android.util.Log;
46
47
48public class RsBenchRS {
49
50    private static final String TAG = "RsBenchRS";
51    private static final String SAMPLE_TEXT = "Bench Test";
52    private static final String LIST_TEXT =
53      "This is a sample list of text to show in the list view";
54    private static int PARTICLES_COUNT = 12000;
55    int mWidth;
56    int mHeight;
57    int mLoops;
58    int mCurrentLoop;
59
60    int mBenchmarkDimX;
61    int mBenchmarkDimY;
62
63    public RsBenchRS() {
64    }
65
66    public void init(RenderScriptGL rs, Resources res, int width, int height, int loops) {
67        mRS = rs;
68        mRes = res;
69        mWidth = width;
70        mHeight = height;
71        mOptionsARGB.inScaled = false;
72        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
73        mMode = 0;
74        mMaxModes = 0;
75        mLoops = loops;
76        mCurrentLoop = 0;
77        mBenchmarkDimX = 1280;
78        mBenchmarkDimY = 720;
79        initRS();
80    }
81
82    private boolean stopTest = false;
83
84    private Resources mRes;
85    private RenderScriptGL mRS;
86
87    private ProgramStore mProgStoreBlendNoneDepth;
88    private ProgramStore mProgStoreBlendNone;
89    private ProgramStore mProgStoreBlendAlpha;
90    private ProgramStore mProgStoreBlendAdd;
91
92    private ProgramFragment mProgFragmentTexture;
93    private ProgramFragment mProgFragmentColor;
94
95    private ProgramVertex mProgVertex;
96    private ProgramVertexFixedFunction.Constants mPVA;
97    private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
98
99    // Custom shaders
100    private ProgramVertex mProgVertexCustom;
101    private ProgramFragment mProgFragmentCustom;
102    private ProgramFragment mProgFragmentMultitex;
103    private ProgramVertex mProgVertexPixelLight;
104    private ProgramVertex mProgVertexPixelLightMove;
105    private ProgramFragment mProgFragmentPixelLight;
106    private ScriptField_VertexShaderConstants_s mVSConst;
107    private ScriptField_FragentShaderConstants_s mFSConst;
108    private ScriptField_VertexShaderConstants3_s mVSConstPixel;
109    private ScriptField_FragentShaderConstants3_s mFSConstPixel;
110
111
112    private Allocation mTexTorus;
113    private Allocation mTexOpaque;
114    private Allocation mTexTransparent;
115    private Allocation mTexChecker;
116    private Allocation mTexGlobe;
117
118    private Mesh m10by10Mesh;
119    private Mesh m100by100Mesh;
120    private Mesh mWbyHMesh;
121    private Mesh mTorus;
122    private Mesh mSingleMesh;
123    private Mesh mParticlesMesh;
124
125    Font mFontSans;
126    Font mFontSerif;
127    private Allocation mTextAlloc;
128
129    private ScriptField_ListAllocs_s mTextureAllocs;
130    private ScriptField_ListAllocs_s mSampleTextAllocs;
131    private ScriptField_ListAllocs_s mSampleListViewAllocs;
132    private ScriptField_VpConsts mPvStarAlloc;
133
134
135    private ScriptC_rsbench mScript;
136    private ScriptC_text_test mTextScript;
137    private ScriptC_torus_test mTorusScript;
138
139    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
140
141    int mMode;
142    int mMaxModes;
143
144    String[] mTestNames;
145    float[] mLocalTestResults;
146
147    public void onActionDown(int x, int y) {
148        mMode ++;
149        mMode = mMode % mMaxModes;
150        mScript.set_gDisplayMode(mMode);
151    }
152
153    private void saveTestResults() {
154        String state = Environment.getExternalStorageState();
155        if (!Environment.MEDIA_MOUNTED.equals(state)) {
156            Log.v(TAG, "sdcard is read only");
157            return;
158        }
159        File sdCard = Environment.getExternalStorageDirectory();
160        if (!sdCard.canWrite()) {
161            Log.v(TAG, "ssdcard is read only");
162            return;
163        }
164
165        File resultFile = new File(sdCard, "rsbench_result" + mCurrentLoop + ".csv");
166        resultFile.setWritable(true, false);
167
168        try {
169            BufferedWriter results = new BufferedWriter(new FileWriter(resultFile));
170            for (int i = 0; i < mLocalTestResults.length; i ++) {
171                results.write(mTestNames[i] + ", " + mLocalTestResults[i] + ",\n");
172            }
173            results.close();
174            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
175        } catch (IOException e) {
176            Log.v(TAG, "Unable to write result file " + e.getMessage());
177        }
178    }
179
180    /**
181     * Create a message handler to handle message sent from the script
182     */
183    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
184        public void run() {
185            if (mID == mScript.get_RS_MSG_RESULTS_READY()) {
186                for (int i = 0; i < mLocalTestResults.length; i ++) {
187                    mLocalTestResults[i] = Float.intBitsToFloat(mData[i]);
188                }
189                saveTestResults();
190                if (mLoops > 0) {
191                    mCurrentLoop ++;
192                    mCurrentLoop = mCurrentLoop % mLoops;
193                }
194                return;
195
196            } else if (mID == mScript.get_RS_MSG_TEST_DONE()) {
197                synchronized(this) {
198                    stopTest = true;
199                    this.notifyAll();
200                }
201                return;
202            } else {
203                Log.v(TAG, "Perf test got unexpected message");
204                return;
205            }
206        }
207    };
208
209    /**
210     * Wait for message from the script
211     */
212    public boolean testIsFinished() {
213        synchronized(this) {
214            while (true) {
215                if (stopTest) {
216                    return true;
217                } else {
218                    try {
219                        this.wait(60*1000);
220                    } catch (InterruptedException e) {
221                        e.printStackTrace();
222                    }
223                }
224            }
225        }
226    }
227
228    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
229        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
230        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
231        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
232        builder.setDitherEnabled(false);
233        builder.setDepthMaskEnabled(false);
234        return builder.create();
235    }
236
237    private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
238
239        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
240                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
241
242        for (int y = 0; y <= hResolution; y++) {
243            final float normalizedY = (float)y / hResolution;
244            final float yOffset = (normalizedY - 0.5f) * height;
245            for (int x = 0; x <= wResolution; x++) {
246                float normalizedX = (float)x / wResolution;
247                float xOffset = (normalizedX - 0.5f) * width;
248                tmb.setTexture((float)x % 2, (float)y % 2);
249                tmb.addVertex(xOffset, yOffset);
250             }
251        }
252
253        for (int y = 0; y < hResolution; y++) {
254            final int curY = y * (wResolution + 1);
255            final int belowY = (y + 1) * (wResolution + 1);
256            for (int x = 0; x < wResolution; x++) {
257                int curV = curY + x;
258                int belowV = belowY + x;
259                tmb.addTriangle(curV, belowV, curV + 1);
260                tmb.addTriangle(belowV, belowV + 1, curV + 1);
261            }
262        }
263
264        return tmb.create(true);
265    }
266
267    /**
268     * Create a mesh with a single quad for the given width and height.
269     */
270    private Mesh getSingleMesh(float width, float height) {
271        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
272                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
273        float xOffset = width/2;
274        float yOffset = height/2;
275        tmb.setTexture(0, 0);
276        tmb.addVertex(-1.0f * xOffset, -1.0f * yOffset);
277        tmb.setTexture(1, 0);
278        tmb.addVertex(xOffset, -1.0f * yOffset);
279        tmb.setTexture(1, 1);
280        tmb.addVertex(xOffset, yOffset);
281        tmb.setTexture(0, 1);
282        tmb.addVertex(-1.0f * xOffset, yOffset);
283        tmb.addTriangle(0, 3, 1);
284        tmb.addTriangle(1, 3, 2);
285        return tmb.create(true);
286    }
287
288    private void initProgramStore() {
289        // Use stock the stock program store object
290        mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
291        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
292
293        // Create a custom program store
294        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
295        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
296        builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
297                             ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
298        builder.setDitherEnabled(false);
299        builder.setDepthMaskEnabled(false);
300        mProgStoreBlendAlpha = builder.create();
301
302        mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
303
304        mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
305
306        mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
307        mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
308        mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
309
310        // For GALAXY
311        builder = new ProgramStore.Builder(mRS);
312        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
313        mRS.bindProgramStore(builder.create());
314
315        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
316        mScript.set_gPSLights(builder.create());
317
318    }
319
320    private void initProgramFragment() {
321
322        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
323        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
324                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
325        mProgFragmentTexture = texBuilder.create();
326        mProgFragmentTexture.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
327
328        ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
329        colBuilder.setVaryingColor(false);
330        mProgFragmentColor = colBuilder.create();
331
332        mScript.set_gProgFragmentColor(mProgFragmentColor);
333
334        mScript.set_gProgFragmentTexture(mProgFragmentTexture);
335
336
337
338        // For Galaxy live wallpaper drawing
339        ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
340        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
341                           ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
342        ProgramFragment pfb = builder.create();
343        pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
344        mScript.set_gPFBackground(pfb);
345
346        builder = new ProgramFragmentFixedFunction.Builder(mRS);
347        builder.setPointSpriteTexCoordinateReplacement(true);
348        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
349                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
350        builder.setVaryingColor(true);
351        ProgramFragment pfs = builder.create();
352        pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
353        mScript.set_gPFStars(pfs);
354
355    }
356
357    private Matrix4f getProjectionNormalized(int w, int h) {
358      // range -1,1 in the narrow axis at z = 0.
359      Matrix4f m1 = new Matrix4f();
360      Matrix4f m2 = new Matrix4f();
361
362      if(w > h) {
363          float aspect = ((float)w) / h;
364          m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
365      } else {
366          float aspect = ((float)h) / w;
367          m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
368      }
369
370      m2.loadRotate(180, 0, 1, 0);
371      m1.loadMultiply(m1, m2);
372
373      m2.loadScale(-2, 2, 1);
374      m1.loadMultiply(m1, m2);
375
376      m2.loadTranslate(0, 0, 2);
377      m1.loadMultiply(m1, m2);
378      return m1;
379  }
380
381    private void updateProjectionMatrices() {
382      Matrix4f projNorm = getProjectionNormalized(mBenchmarkDimX, mBenchmarkDimY);
383      ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
384      i.Proj = projNorm;
385      i.MVP = projNorm;
386      mPvStarAlloc.set(i, 0, true);
387      mPvProjectionAlloc.setProjection(projNorm);
388  }
389
390    private void initProgramVertex() {
391        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
392        mProgVertex = pvb.create();
393
394        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
395        ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA);
396        Matrix4f proj = new Matrix4f();
397        proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
398        mPVA.setProjection(proj);
399
400        mScript.set_gProgVertex(mProgVertex);
401
402
403        // For galaxy live wallpaper
404        mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
405        mScript.bind_vpConstants(mPvStarAlloc);
406        mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
407        updateProjectionMatrices();
408
409        pvb = new ProgramVertexFixedFunction.Builder(mRS);
410        ProgramVertex pvbp = pvb.create();
411        ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
412        mScript.set_gPVBkProj(pvbp);
413
414        ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
415        String t =  "varying vec4 varColor;\n" +
416                    "varying vec2 varTex0;\n" +
417                    "void main() {\n" +
418                    "  float dist = ATTRIB_position.y;\n" +
419                    "  float angle = ATTRIB_position.x;\n" +
420                    "  float x = dist * sin(angle);\n" +
421                    "  float y = dist * cos(angle) * 0.892;\n" +
422                    "  float p = dist * 5.5;\n" +
423                    "  float s = cos(p);\n" +
424                    "  float t = sin(p);\n" +
425                    "  vec4 pos;\n" +
426                    "  pos.x = t * x + s * y;\n" +
427                    "  pos.y = s * x - t * y;\n" +
428                    "  pos.z = ATTRIB_position.z;\n" +
429                    "  pos.w = 1.0;\n" +
430                    "  gl_Position = UNI_MVP * pos;\n" +
431                    "  gl_PointSize = ATTRIB_color.a * 10.0;\n" +
432                    "  varColor.rgb = ATTRIB_color.rgb;\n" +
433                    "  varColor.a = 1.0;\n" +
434                    "}\n";
435        sb.setShader(t);
436        sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
437        sb.addConstant(mPvStarAlloc.getType());
438        ProgramVertex pvs = sb.create();
439        pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
440        mScript.set_gPVStars(pvs);
441    }
442
443    private void initCustomShaders() {
444        mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
445        mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
446
447
448        mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
449        mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
450
451
452        // Initialize the shader builder
453        ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
454        // Specify the resource that contains the shader string
455        pvbCustom.setShader(mRes, R.raw.shaderv);
456        // Use a script field to specify the input layout
457        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
458        // Define the constant input layout
459        pvbCustom.addConstant(mVSConst.getAllocation().getType());
460        mProgVertexCustom = pvbCustom.create();
461        // Bind the source of constant data
462        mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
463
464        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
465        // Specify the resource that contains the shader string
466        pfbCustom.setShader(mRes, R.raw.shaderf);
467        // Tell the builder how many textures we have
468        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
469        // Define the constant input layout
470        pfbCustom.addConstant(mFSConst.getAllocation().getType());
471        mProgFragmentCustom = pfbCustom.create();
472        // Bind the source of constant data
473        mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
474
475        pvbCustom = new ProgramVertex.Builder(mRS);
476        pvbCustom.setShader(mRes, R.raw.shader2v);
477        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
478        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
479        mProgVertexPixelLight = pvbCustom.create();
480        mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
481
482        pvbCustom = new ProgramVertex.Builder(mRS);
483        pvbCustom.setShader(mRes, R.raw.shader2movev);
484        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
485        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
486        mProgVertexPixelLightMove = pvbCustom.create();
487        mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
488
489        pfbCustom = new ProgramFragment.Builder(mRS);
490        pfbCustom.setShader(mRes, R.raw.shader2f);
491        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
492        pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
493        mProgFragmentPixelLight = pfbCustom.create();
494        mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
495
496        pfbCustom = new ProgramFragment.Builder(mRS);
497        pfbCustom.setShader(mRes, R.raw.multitexf);
498        for (int texCount = 0; texCount < 3; texCount ++) {
499            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
500        }
501        mProgFragmentMultitex = pfbCustom.create();
502
503
504        mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
505    }
506
507    private Allocation loadTextureRGB(int id) {
508        return Allocation.createFromBitmapResource(mRS, mRes, id,
509                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
510                Allocation.USAGE_GRAPHICS_TEXTURE);
511    }
512
513    private Allocation loadTextureARGB(int id) {
514        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
515        return Allocation.createFromBitmap(mRS, b,
516                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
517                Allocation.USAGE_GRAPHICS_TEXTURE);
518    }
519
520    private void loadImages() {
521        mTexTorus = loadTextureRGB(R.drawable.torusmap);
522        mTexOpaque = loadTextureRGB(R.drawable.data);
523        mTexTransparent = loadTextureARGB(R.drawable.leaf);
524        mTexChecker = loadTextureRGB(R.drawable.checker);
525        mTexGlobe = loadTextureRGB(R.drawable.globe);
526
527        mScript.set_gTexTorus(mTexTorus);
528        mScript.set_gTexOpaque(mTexOpaque);
529        mScript.set_gTexTransparent(mTexTransparent);
530        mScript.set_gTexChecker(mTexChecker);
531        mScript.set_gTexGlobe(mTexGlobe);
532
533        // For Galaxy live wallpaper
534        mScript.set_gTSpace(loadTextureRGB(R.drawable.space));
535        mScript.set_gTLight1(loadTextureRGB(R.drawable.light1));
536        mScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
537    }
538
539    private void initFonts() {
540        // Sans font by family name
541        mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
542        mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8);
543        // Create fonts by family and style
544
545        mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
546
547        mScript.set_gFontSans(mFontSans);
548        mScript.set_gFontSerif(mFontSerif);
549    }
550
551    private void createParticlesMesh() {
552        ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
553
554        final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
555        meshBuilder.addVertexAllocation(p.getAllocation());
556        final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
557        meshBuilder.addIndexSetType(Primitive.POINT);
558        mParticlesMesh = meshBuilder.create();
559
560        mScript.set_gParticlesMesh(mParticlesMesh);
561        mScript.bind_Particles(p);
562    }
563
564    private void initMesh() {
565        m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10);
566        mScript.set_g10by10Mesh(m10by10Mesh);
567        m100by100Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 100, 100);
568        mScript.set_g100by100Mesh(m100by100Mesh);
569        mWbyHMesh= getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, mBenchmarkDimX/4, mBenchmarkDimY/4);
570        mScript.set_gWbyHMesh(mWbyHMesh);
571        mSingleMesh = getSingleMesh(1, 1);  // a unit size mesh
572        mScript.set_gSingleMesh(mSingleMesh);
573
574        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
575        FileA3D.IndexEntry entry = model.getIndexEntry(0);
576        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
577            Log.e("rs", "could not load model");
578        } else {
579            mTorus = (Mesh)entry.getObject();
580        }
581
582        createParticlesMesh();
583    }
584
585    private void initSamplers() {
586        mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
587        mScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
588        mScript.set_gMipLinearWrap(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS));
589        mScript.set_gNearestClamp(Sampler.CLAMP_NEAREST(mRS));
590    }
591
592    private void initProgramRaster() {
593        mScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
594        mScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
595        mScript.set_gCullNone(ProgramRaster.CULL_NONE(mRS));
596    }
597
598    private int strlen(byte[] array) {
599        int count = 0;
600        while(count < array.length && array[count] != 0) {
601            count ++;
602        }
603        return count;
604    }
605
606    private void prepareTestData() {
607        mTestNames = new String[mMaxModes];
608        mLocalTestResults = new float[mMaxModes];
609        int scratchSize = 1024;
610        Allocation scratch = Allocation.createSized(mRS, Element.U8(mRS), scratchSize);
611        byte[] tmp = new byte[scratchSize];
612        mScript.bind_gStringBuffer(scratch);
613        for (int i = 0; i < mMaxModes; i ++) {
614            mScript.invoke_getTestName(i);
615            scratch.copyTo(tmp);
616            int len = strlen(tmp);
617            mTestNames[i] = new String(tmp, 0, len);
618        }
619    }
620
621    public void setDebugMode(int num) {
622        mScript.invoke_setDebugMode(num);
623    }
624
625    public void setBenchmarkMode() {
626        mScript.invoke_setBenchmarkMode();
627    }
628
629    void initTextScript() {
630        mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
631        mTextScript.set_gFontSans(mFontSans);
632        mTextScript.set_gFontSerif(mFontSerif);
633    }
634
635    void initTorusScript() {
636        mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
637        mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
638        mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
639        mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
640        mTorusScript.set_gTorusMesh(mTorus);
641        mTorusScript.set_gTexTorus(mTexTorus);
642        mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
643        mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
644        mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
645        mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
646        mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
647        mTorusScript.bind_gVSConstPixel(mVSConstPixel);
648        mTorusScript.bind_gFSConstPixel(mFSConstPixel);
649        mTorusScript.bind_gVSConstants(mVSConst);
650        mTorusScript.bind_gFSConstants(mFSConst);
651        mTorusScript.set_gProgVertex(mProgVertex);
652        mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
653        mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
654        mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
655    }
656
657    private void initRS() {
658
659        mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
660
661
662        mRS.setMessageHandler(mRsMessage);
663
664        mMaxModes = mScript.get_gMaxModes();
665        mScript.set_gMaxLoops(mLoops);
666
667        prepareTestData();
668
669        initSamplers();
670        initMesh();
671        initProgramVertex();
672        initProgramStore();
673        initProgramFragment();
674        initFonts();
675        loadImages();
676        initProgramRaster();
677        initCustomShaders();
678
679        Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
680        b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
681        Allocation offscreen = Allocation.createTyped(mRS,
682                                                      b.create(),
683                                                      Allocation.USAGE_GRAPHICS_TEXTURE |
684                                                      Allocation.USAGE_GRAPHICS_RENDER_TARGET);
685        mScript.set_gRenderBufferColor(offscreen);
686
687        b = new Type.Builder(mRS,
688                             Element.createPixel(mRS, DataType.UNSIGNED_16,
689                             DataKind.PIXEL_DEPTH));
690        b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
691        offscreen = Allocation.createTyped(mRS,
692                                           b.create(),
693                                           Allocation.USAGE_GRAPHICS_RENDER_TARGET);
694        mScript.set_gRenderBufferDepth(offscreen);
695
696        mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
697        for (int i = 0; i < 100; i++) {
698            ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
699            texElem.item = loadTextureRGB(R.drawable.globe);
700            mTextureAllocs.set(texElem, i, false);
701        }
702        mTextureAllocs.copyAll();
703        mScript.bind_gTexList100(mTextureAllocs);
704
705        mSampleTextAllocs = new ScriptField_ListAllocs_s(mRS, 100);
706        for (int i = 0; i < 100; i++) {
707            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
708            textElem.item = Allocation.createFromString(mRS, SAMPLE_TEXT, Allocation.USAGE_SCRIPT);
709            mSampleTextAllocs.set(textElem, i, false);
710        }
711        mSampleTextAllocs.copyAll();
712        mScript.bind_gSampleTextList100(mSampleTextAllocs);
713
714        mSampleListViewAllocs = new ScriptField_ListAllocs_s(mRS, 1000);
715        for (int i = 0; i < 1000; i++) {
716            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
717            textElem.item = Allocation.createFromString(mRS, LIST_TEXT, Allocation.USAGE_SCRIPT);
718            mSampleListViewAllocs.set(textElem, i, false);
719        }
720        mSampleListViewAllocs.copyAll();
721        mScript.bind_gListViewText(mSampleListViewAllocs);
722
723        initTextScript();
724        initTorusScript();
725
726        mScript.set_gFontScript(mTextScript);
727        mScript.set_gTorusScript(mTorusScript);
728        mScript.set_gDummyAlloc(Allocation.createSized(mRS, Element.I32(mRS), 1));
729
730        mRS.bindRootScript(mScript);
731    }
732}
733