ImageProcessingActivity.java revision 05b269323e6f28f244d74b00cd63d81d9f8a1db4
1/*
2 * Copyright (C) 2012 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.rs.image;
18
19import android.app.Activity;
20import android.os.Bundle;
21import android.os.Handler;
22import android.os.Message;
23import android.graphics.BitmapFactory;
24import android.graphics.Bitmap;
25import android.graphics.Canvas;
26import android.view.SurfaceView;
27import android.widget.AdapterView;
28import android.widget.ArrayAdapter;
29import android.widget.ImageView;
30import android.widget.SeekBar;
31import android.widget.Spinner;
32import android.widget.TextView;
33import android.view.View;
34import android.util.Log;
35import android.renderscript.ScriptC;
36import android.renderscript.RenderScript;
37import android.renderscript.Type;
38import android.renderscript.Allocation;
39import android.renderscript.Element;
40import android.renderscript.Script;
41
42import android.os.Environment;
43import java.io.BufferedWriter;
44import java.io.File;
45import java.io.FileWriter;
46import java.io.IOException;
47
48public class ImageProcessingActivity extends Activity
49                                       implements SeekBar.OnSeekBarChangeListener {
50    private final String TAG = "Img";
51    public final String RESULT_FILE = "image_processing_result.csv";
52
53    RenderScript mRS;
54    Allocation mInPixelsAllocation;
55    Allocation mInPixelsAllocation2;
56    Allocation mOutPixelsAllocation;
57
58    static class DVFSWorkaround {
59        static class spinner extends Thread {
60            boolean mRun = true;
61            long mNextSleep;
62
63            spinner() {
64                setPriority(MIN_PRIORITY);
65                start();
66            }
67
68            public void run() {
69                while (mRun) {
70                    Thread.yield();
71                    synchronized(this) {
72                        long t = java.lang.System.currentTimeMillis();
73                        if (t > mNextSleep) {
74                            try {
75                                this.wait();
76                            } catch(InterruptedException e) {
77                            }
78                        }
79                    }
80                }
81            }
82
83            public void go(long t) {
84                synchronized(this) {
85                    mNextSleep = t;
86                    notifyAll();
87                }
88            }
89        }
90
91        spinner s1;
92        DVFSWorkaround() {
93            s1 = new spinner();
94        }
95
96        void go() {
97            long t = java.lang.System.currentTimeMillis() + 2000;
98            s1.go(t);
99        }
100
101        void destroy() {
102            synchronized(this) {
103                s1.mRun = false;
104                notifyAll();
105            }
106        }
107    }
108    DVFSWorkaround mDvfsWar = new DVFSWorkaround();
109
110
111    /**
112     * Define enum type for test names
113     */
114    public enum TestName {
115        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
116        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
117        LEVELS_VEC3_FULL ("Levels Vec3 Full"),
118        LEVELS_VEC4_FULL ("Levels Vec4 Full"),
119        BLUR_RADIUS_25 ("Blur radius 25"),
120        INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
121        GREYSCALE ("Greyscale"),
122        GRAIN ("Grain"),
123        FISHEYE_FULL ("Fisheye Full"),
124        FISHEYE_RELAXED ("Fisheye Relaxed"),
125        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
126        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
127        VIGNETTE_FULL ("Vignette Full"),
128        VIGNETTE_RELAXED ("Vignette Relaxed"),
129        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
130        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
131        GROUP_TEST_EMULATED ("Group Test (emulated)"),
132        GROUP_TEST_NATIVE ("Group Test (native)"),
133        CONVOLVE_3X3 ("Convolve 3x3"),
134        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
135        COLOR_MATRIX ("ColorMatrix"),
136        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
137        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
138        COPY ("Copy"),
139        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
140        CONVOLVE_5X5 ("Convolve 5x5"),
141        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
142        MANDELBROT_FLOAT ("Mandelbrot fp32"),
143        INTRINSICS_BLEND ("Intrinsics Blend"),
144        INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"),
145        VIBRANCE ("Vibrance"),
146        BW_FILTER ("BW Filter"),
147        SHADOWS ("Shadows"),
148        CONTRAST ("Contrast"),
149        EXPOSURE ("Exposure"),
150        WHITE_BALANCE ("White Balance"),
151        COLOR_CUBE ("Color Cube"),
152        COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)"),
153        USAGE_IO ("Usage io"),
154        ARTISTIC_1("Artistic 1"),
155        HISTOGRAM ("Histogram"),
156        MANDELBROT_DOUBLE ("Mandelbrot fp64");
157
158
159        private final String name;
160
161        private TestName(String s) {
162            name = s;
163        }
164
165        // return quoted string as displayed test name
166        public String toString() {
167            return name;
168        }
169    }
170
171    Bitmap mBitmapOut;
172
173    private Spinner mSpinner;
174    private SeekBar mBar1;
175    private SeekBar mBar2;
176    private SeekBar mBar3;
177    private SeekBar mBar4;
178    private SeekBar mBar5;
179    private TextView mText1;
180    private TextView mText2;
181    private TextView mText3;
182    private TextView mText4;
183    private TextView mText5;
184
185    private TextView mBenchmarkResult;
186    private Spinner mTestSpinner;
187
188    private ImageView mDisplayView;
189
190    private boolean mDoingBenchmark;
191
192    private TestBase mTest;
193    private int mRunCount;
194
195    public void updateDisplay() {
196        mHandler.sendMessage(Message.obtain());
197    }
198
199    private Handler mHandler = new Handler() {
200        // Allow the filter to complete without blocking the UI
201        // thread.  When the message arrives that the op is complete
202        // we will either mark completion or start a new filter if
203        // more work is ready.  Either way, display the result.
204        @Override
205        public void handleMessage(Message msg) {
206            boolean doTest = false;
207            synchronized(this) {
208                if (mRS == null) {
209                    return;
210                }
211                mTest.updateBitmap(mBitmapOut);
212                mDisplayView.invalidate();
213                if (mRunCount > 0) {
214                    mRunCount--;
215                    if (mRunCount > 0) {
216                        doTest = true;
217                    }
218                }
219
220                if (doTest) {
221                    mTest.runTestSendMessage();
222                }
223            }
224        }
225
226    };
227
228    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
229        if (fromUser) {
230
231            if (seekBar == mBar1) {
232                mTest.onBar1Changed(progress);
233            } else if (seekBar == mBar2) {
234                mTest.onBar2Changed(progress);
235            } else if (seekBar == mBar3) {
236                mTest.onBar3Changed(progress);
237            } else if (seekBar == mBar4) {
238                mTest.onBar4Changed(progress);
239            } else if (seekBar == mBar5) {
240                mTest.onBar5Changed(progress);
241            }
242
243            boolean doTest = false;
244            synchronized(this) {
245                if (mRunCount == 0) {
246                    doTest = true;
247                    mRunCount = 1;
248                } else {
249                    mRunCount = 2;
250                }
251            }
252            if (doTest) {
253                mTest.runTestSendMessage();
254            }
255        }
256    }
257
258    public void onStartTrackingTouch(SeekBar seekBar) {
259    }
260
261    public void onStopTrackingTouch(SeekBar seekBar) {
262    }
263
264    void setupBars() {
265        mSpinner.setVisibility(View.VISIBLE);
266        mTest.onSpinner1Setup(mSpinner);
267
268        mBar1.setVisibility(View.VISIBLE);
269        mText1.setVisibility(View.VISIBLE);
270        mTest.onBar1Setup(mBar1, mText1);
271
272        mBar2.setVisibility(View.VISIBLE);
273        mText2.setVisibility(View.VISIBLE);
274        mTest.onBar2Setup(mBar2, mText2);
275
276        mBar3.setVisibility(View.VISIBLE);
277        mText3.setVisibility(View.VISIBLE);
278        mTest.onBar3Setup(mBar3, mText3);
279
280        mBar4.setVisibility(View.VISIBLE);
281        mText4.setVisibility(View.VISIBLE);
282        mTest.onBar4Setup(mBar4, mText4);
283
284        mBar5.setVisibility(View.VISIBLE);
285        mText5.setVisibility(View.VISIBLE);
286        mTest.onBar5Setup(mBar5, mText5);
287    }
288
289
290    void changeTest(TestName testName) {
291        if (mTest != null) {
292            mTest.destroy();
293        }
294        switch(testName) {
295        case LEVELS_VEC3_RELAXED:
296            mTest = new LevelsV4(false, false);
297            break;
298        case LEVELS_VEC4_RELAXED:
299            mTest = new LevelsV4(false, true);
300            break;
301        case LEVELS_VEC3_FULL:
302            mTest = new LevelsV4(true, false);
303            break;
304        case LEVELS_VEC4_FULL:
305            mTest = new LevelsV4(true, true);
306            break;
307        case BLUR_RADIUS_25:
308            mTest = new Blur25(false);
309            break;
310        case INTRINSIC_BLUE_RADIUS_25:
311            mTest = new Blur25(true);
312            break;
313        case GREYSCALE:
314            mTest = new Greyscale();
315            break;
316        case GRAIN:
317            mTest = new Grain();
318            break;
319        case FISHEYE_FULL:
320            mTest = new Fisheye(false, false);
321            break;
322        case FISHEYE_RELAXED:
323            mTest = new Fisheye(false, true);
324            break;
325        case FISHEYE_APPROXIMATE_FULL:
326            mTest = new Fisheye(true, false);
327            break;
328        case FISHEYE_APPROXIMATE_RELAXED:
329            mTest = new Fisheye(true, true);
330            break;
331        case VIGNETTE_FULL:
332            mTest = new Vignette(false, false);
333            break;
334        case VIGNETTE_RELAXED:
335            mTest = new Vignette(false, true);
336            break;
337        case VIGNETTE_APPROXIMATE_FULL:
338            mTest = new Vignette(true, false);
339            break;
340        case VIGNETTE_APPROXIMATE_RELAXED:
341            mTest = new Vignette(true, true);
342            break;
343        case GROUP_TEST_EMULATED:
344            mTest = new GroupTest(false);
345            break;
346        case GROUP_TEST_NATIVE:
347            mTest = new GroupTest(true);
348            break;
349        case CONVOLVE_3X3:
350            mTest = new Convolve3x3(false);
351            break;
352        case INTRINSICS_CONVOLVE_3X3:
353            mTest = new Convolve3x3(true);
354            break;
355        case COLOR_MATRIX:
356            mTest = new ColorMatrix(false, false);
357            break;
358        case INTRINSICS_COLOR_MATRIX:
359            mTest = new ColorMatrix(true, false);
360            break;
361        case INTRINSICS_COLOR_MATRIX_GREY:
362            mTest = new ColorMatrix(true, true);
363            break;
364        case COPY:
365            mTest = new Copy();
366            break;
367        case CROSS_PROCESS_USING_LUT:
368            mTest = new CrossProcess();
369            break;
370        case CONVOLVE_5X5:
371            mTest = new Convolve5x5(false);
372            break;
373        case INTRINSICS_CONVOLVE_5X5:
374            mTest = new Convolve5x5(true);
375            break;
376        case MANDELBROT_FLOAT:
377            mTest = new Mandelbrot(false);
378            break;
379        case INTRINSICS_BLEND:
380            mTest = new Blend();
381            break;
382        case INTRINSICS_BLUR_25G:
383            mTest = new Blur25G();
384            break;
385        case VIBRANCE:
386            mTest = new Vibrance();
387            break;
388        case BW_FILTER:
389            mTest = new BWFilter();
390            break;
391        case SHADOWS:
392            mTest = new Shadows();
393            break;
394        case CONTRAST:
395            mTest = new Contrast();
396            break;
397        case EXPOSURE:
398            mTest = new Exposure();
399            break;
400        case WHITE_BALANCE:
401            mTest = new WhiteBalance();
402            break;
403        case COLOR_CUBE:
404            mTest = new ColorCube(false);
405            break;
406        case COLOR_CUBE_3D_INTRINSIC:
407            mTest = new ColorCube(true);
408            break;
409        case USAGE_IO:
410            mTest = new UsageIO();
411            break;
412        case ARTISTIC_1:
413            mTest = new Artistic1();
414            break;
415        case HISTOGRAM:
416            mTest = new Histogram();
417            break;
418        case MANDELBROT_DOUBLE:
419            mTest = new Mandelbrot(true);
420            break;
421        }
422
423        mTest.createBaseTest(this);
424        setupBars();
425
426        mTest.runTest();
427        updateDisplay();
428        mBenchmarkResult.setText("Result: not run");
429    }
430
431    void setupTests() {
432        mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
433            this, R.layout.spinner_layout, TestName.values()));
434    }
435
436    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
437            new AdapterView.OnItemSelectedListener() {
438                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
439                    changeTest(TestName.values()[pos]);
440                }
441
442                public void onNothingSelected(AdapterView parent) {
443
444                }
445            };
446
447    void init() {
448        mRS = RenderScript.create(this);
449        mInPixelsAllocation = Allocation.createFromBitmapResource(
450                mRS, getResources(), R.drawable.img1600x1067);
451        mInPixelsAllocation2 = Allocation.createFromBitmapResource(
452                mRS, getResources(), R.drawable.img1600x1067b);
453        mBitmapOut = Bitmap.createBitmap(mInPixelsAllocation.getType().getX(),
454                                         mInPixelsAllocation.getType().getY(),
455                                         Bitmap.Config.ARGB_8888);
456        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
457
458        mDisplayView = (ImageView) findViewById(R.id.display);
459        mDisplayView.setImageBitmap(mBitmapOut);
460
461        mSpinner = (Spinner) findViewById(R.id.spinner1);
462
463        mBar1 = (SeekBar) findViewById(R.id.slider1);
464        mBar2 = (SeekBar) findViewById(R.id.slider2);
465        mBar3 = (SeekBar) findViewById(R.id.slider3);
466        mBar4 = (SeekBar) findViewById(R.id.slider4);
467        mBar5 = (SeekBar) findViewById(R.id.slider5);
468
469        mBar1.setOnSeekBarChangeListener(this);
470        mBar2.setOnSeekBarChangeListener(this);
471        mBar3.setOnSeekBarChangeListener(this);
472        mBar4.setOnSeekBarChangeListener(this);
473        mBar5.setOnSeekBarChangeListener(this);
474
475        mText1 = (TextView) findViewById(R.id.slider1Text);
476        mText2 = (TextView) findViewById(R.id.slider2Text);
477        mText3 = (TextView) findViewById(R.id.slider3Text);
478        mText4 = (TextView) findViewById(R.id.slider4Text);
479        mText5 = (TextView) findViewById(R.id.slider5Text);
480
481        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
482        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
483
484        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
485        mBenchmarkResult.setText("Result: not run");
486
487        setupTests();
488        changeTest(TestName.LEVELS_VEC3_RELAXED);
489    }
490
491    void cleanup() {
492        synchronized(this) {
493            RenderScript rs = mRS;
494            mRS = null;
495            while(mDoingBenchmark) {
496                try {
497                    Thread.sleep(1, 0);
498                } catch(InterruptedException e) {
499                }
500
501            }
502            rs.destroy();
503        }
504
505        mInPixelsAllocation = null;
506        mInPixelsAllocation2 = null;
507        mOutPixelsAllocation = null;
508        mBitmapOut = null;
509    }
510
511    @Override
512    protected void onCreate(Bundle savedInstanceState) {
513        super.onCreate(savedInstanceState);
514        setContentView(R.layout.main);
515
516        init();
517    }
518
519    @Override
520    protected void onPause() {
521        super.onPause();
522
523        cleanup();
524    }
525
526
527    @Override
528    protected void onResume() {
529        super.onResume();
530
531        if (null == mRS) {
532            init();
533        }
534    }
535
536    // button hook
537    public void benchmark(View v) {
538        float t = getBenchmark();
539        //long javaTime = javaFilter();
540        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
541        mBenchmarkResult.setText("Result: " + t + " ms");
542        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
543    }
544
545    public void benchmark_all(View v) {
546        // write result into a file
547        File externalStorage = Environment.getExternalStorageDirectory();
548        if (!externalStorage.canWrite()) {
549            Log.v(TAG, "sdcard is not writable");
550            return;
551        }
552        File resultFile = new File(externalStorage, RESULT_FILE);
553        resultFile.setWritable(true, false);
554        try {
555            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
556            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
557            for (TestName tn: TestName.values()) {
558                changeTest(tn);
559                float t = getBenchmark();
560                String s = new String("" + tn.toString() + ", " + t);
561                rsWriter.write(s + "\n");
562                Log.v(TAG, "Test " + s + "ms\n");
563            }
564            rsWriter.close();
565        } catch (IOException e) {
566            Log.v(TAG, "Unable to write result file " + e.getMessage());
567        }
568        changeTest(TestName.LEVELS_VEC3_RELAXED);
569    }
570
571
572
573    // For benchmark test
574    public float getBenchmark() {
575        if (mRS == null) {
576            return 0;
577        }
578        mDoingBenchmark = true;
579
580        mDvfsWar.go();
581        mTest.setupBenchmark();
582        long result = 0;
583
584        //Log.v(TAG, "Warming");
585        long t = java.lang.System.currentTimeMillis() + 250;
586        do {
587            mTest.runTest();
588            mTest.finish();
589        } while (t > java.lang.System.currentTimeMillis());
590
591        //Log.v(TAG, "Benchmarking");
592        int ct = 0;
593        t = java.lang.System.currentTimeMillis();
594        do {
595            mTest.runTest();
596            mTest.finish();
597            ct++;
598        } while ((t+1000) > java.lang.System.currentTimeMillis());
599        t = java.lang.System.currentTimeMillis() - t;
600        float ft = (float)t;
601        ft /= ct;
602
603        mTest.exitBenchmark();
604        mDoingBenchmark = false;
605
606        return ft;
607    }
608}
609