ImageProcessingActivityJB.java revision 31f4588d26e258c61543e90e796c4c9a8c2a1482
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.imagejb;
18
19import android.app.Activity;
20import android.content.Intent;
21import android.os.Bundle;
22import android.os.Handler;
23import android.os.Message;
24import android.graphics.BitmapFactory;
25import android.graphics.Bitmap;
26import android.graphics.Canvas;
27import android.view.SurfaceView;
28import android.widget.AdapterView;
29import android.widget.ArrayAdapter;
30import android.widget.ImageView;
31import android.widget.SeekBar;
32import android.widget.Spinner;
33import android.widget.TextView;
34import android.view.View;
35import android.view.TextureView;
36import android.view.Surface;
37import android.graphics.SurfaceTexture;
38import android.util.Log;
39import android.renderscript.ScriptC;
40import android.renderscript.RenderScript;
41import android.renderscript.Type;
42import android.renderscript.Allocation;
43import android.renderscript.Element;
44import android.renderscript.Script;
45
46import android.os.Environment;
47import java.io.BufferedWriter;
48import java.io.File;
49import java.io.FileWriter;
50import java.io.IOException;
51
52public class ImageProcessingActivityJB extends Activity
53                                       implements SeekBar.OnSeekBarChangeListener,
54                                                  TextureView.SurfaceTextureListener {
55    private final String TAG = "Img";
56    public final String RESULT_FILE = "image_processing_result.csv";
57
58    Bitmap mBitmapIn;
59    Bitmap mBitmapIn2;
60
61    private Spinner mSpinner;
62    private SeekBar mBar1;
63    private SeekBar mBar2;
64    private SeekBar mBar3;
65    private SeekBar mBar4;
66    private SeekBar mBar5;
67    private TextView mText1;
68    private TextView mText2;
69    private TextView mText3;
70    private TextView mText4;
71    private TextView mText5;
72    private TextureView mDisplayView;
73
74    private int mTestList[];
75    private float mTestResults[];
76
77    private boolean mToggleIO;
78    private boolean mToggleDVFS;
79    private boolean mToggleLong;
80    private boolean mTogglePause;
81
82
83    /////////////////////////////////////////////////////////////////////////
84
85    class Processor extends Thread {
86        RenderScript mRS;
87        Allocation mInPixelsAllocation;
88        Allocation mInPixelsAllocation2;
89        Allocation mOutDisplayAllocation;
90        Allocation mOutPixelsAllocation;
91
92        private Surface mOutSurface;
93        private float mLastResult;
94        private boolean mRun = true;
95        private int mOp = 0;
96        private boolean mDoingBenchmark;
97        private TestBase mTest;
98        private TextureView mDisplayView;
99
100        private boolean mBenchmarkMode;
101
102
103        Processor(RenderScript rs, TextureView v, boolean benchmarkMode) {
104            mRS = rs;
105            mDisplayView = v;
106            mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
107            mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
108            mOutDisplayAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType(),
109                                                               Allocation.MipmapControl.MIPMAP_NONE,
110                                                               Allocation.USAGE_SCRIPT |
111                                                               Allocation.USAGE_IO_OUTPUT);
112            mOutPixelsAllocation = mOutDisplayAllocation;
113
114            if (!mToggleIO) {
115                // Not using USAGE_IO for the script so create a non-io kernel to copy from
116                mOutPixelsAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType(),
117                                                              Allocation.MipmapControl.MIPMAP_NONE,
118                                                              Allocation.USAGE_SCRIPT);
119            }
120
121            mBenchmarkMode = benchmarkMode;
122            start();
123        }
124
125        private float getBenchmark() {
126            mDoingBenchmark = true;
127
128            mTest.setupBenchmark();
129            long result = 0;
130            long runtime = 1000;
131            if (mToggleLong) {
132                runtime = 10000;
133            }
134
135            if (mToggleDVFS) {
136                mDvfsWar.go();
137            }
138
139            Log.v("rs", "Warming");
140            long t = java.lang.System.currentTimeMillis() + 250;
141            do {
142                mTest.runTest();
143                mTest.finish();
144            } while (t > java.lang.System.currentTimeMillis());
145            //mHandler.sendMessage(Message.obtain());
146
147            Log.v("rs", "Benchmarking");
148            int ct = 0;
149            t = java.lang.System.currentTimeMillis();
150            do {
151                mTest.runTest();
152                mTest.finish();
153                ct++;
154            } while ((t + runtime) > java.lang.System.currentTimeMillis());
155            t = java.lang.System.currentTimeMillis() - t;
156            float ft = (float)t;
157            ft /= ct;
158
159            mTest.exitBenchmark();
160            mDoingBenchmark = false;
161
162            android.util.Log.v("rs", "bench " + ft);
163            return ft;
164        }
165
166        private Handler mHandler = new Handler() {
167            // Allow the filter to complete without blocking the UI
168            // thread.  When the message arrives that the op is complete
169            // we will either mark completion or start a new filter if
170            // more work is ready.  Either way, display the result.
171            @Override
172            public void handleMessage(Message msg) {
173                synchronized(this) {
174                    if (mRS == null || mOutPixelsAllocation == null) {
175                        return;
176                    }
177                    if (mOutDisplayAllocation != mOutPixelsAllocation) {
178                        mOutDisplayAllocation.copyFrom(mOutPixelsAllocation);
179                    }
180                    mOutDisplayAllocation.ioSend();
181                    mDisplayView.invalidate();
182                    //mTest.runTestSendMessage();
183                }
184            }
185        };
186
187        public void run() {
188            Surface lastSurface = null;
189            while (mRun) {
190                synchronized(this) {
191                    try {
192                        this.wait();
193                    } catch(InterruptedException e) {
194                    }
195                    if (!mRun) return;
196
197                    if ((mOutSurface == null) || (mOutPixelsAllocation == null)) {
198                        continue;
199                    }
200
201                    if (lastSurface != mOutSurface) {
202                        mOutDisplayAllocation.setSurface(mOutSurface);
203                        lastSurface = mOutSurface;
204                    }
205                }
206
207                if (mBenchmarkMode) {
208                    for (int ct=0; ct < mTestList.length; ct++) {
209                        mRS.finish();
210
211                        try {
212                            sleep(1000);
213                        } catch(InterruptedException e) {
214                        }
215
216                        if (mTest != null) {
217                            mTest.destroy();
218                        }
219
220                        mTest = changeTest(mTestList[ct]);
221                        if (mTogglePause) {
222                            try {
223                                sleep(10000);
224                            } catch(InterruptedException e) {
225                            }
226                        }
227
228                        mTestResults[ct] = getBenchmark();
229                        mHandler.sendMessage(Message.obtain());
230                    }
231                    onBenchmarkFinish();
232                }
233            }
234
235        }
236
237        public void update() {
238            synchronized(this) {
239                if (mOp == 0) {
240                    mOp = 2;
241                }
242                notifyAll();
243            }
244        }
245
246        public void setSurface(Surface s) {
247            synchronized(this) {
248                mOutSurface = s;
249                notifyAll();
250            }
251            //update();
252        }
253
254        public void exit() {
255            mRun = false;
256
257            synchronized(this) {
258                notifyAll();
259            }
260
261            try {
262                this.join();
263            } catch(InterruptedException e) {
264            }
265
266            mInPixelsAllocation.destroy();
267            mInPixelsAllocation2.destroy();
268            if (mOutPixelsAllocation != mOutDisplayAllocation) {
269                mOutPixelsAllocation.destroy();
270            }
271            mOutDisplayAllocation.destroy();
272            mRS.destroy();
273
274            mInPixelsAllocation = null;
275            mInPixelsAllocation2 = null;
276            mOutPixelsAllocation = null;
277            mOutDisplayAllocation = null;
278            mRS = null;
279        }
280    }
281
282    ///////////////////////////////////////////////////////////////////////////////////////
283
284    static class DVFSWorkaround {
285        static class spinner extends Thread {
286            boolean mRun = true;
287            long mNextSleep;
288
289            spinner() {
290                setPriority(MIN_PRIORITY);
291                start();
292            }
293
294            public void run() {
295                while (mRun) {
296                    Thread.yield();
297                    synchronized(this) {
298                        long t = java.lang.System.currentTimeMillis();
299                        if (t > mNextSleep) {
300                            try {
301                                this.wait();
302                            } catch(InterruptedException e) {
303                            }
304                        }
305                    }
306                }
307            }
308
309            public void go(long t) {
310                synchronized(this) {
311                    mNextSleep = t;
312                    notifyAll();
313                }
314            }
315        }
316
317        spinner s1;
318        DVFSWorkaround() {
319            s1 = new spinner();
320        }
321
322        void go() {
323            long t = java.lang.System.currentTimeMillis() + 2000;
324            s1.go(t);
325        }
326
327        void destroy() {
328            synchronized(this) {
329                s1.mRun = false;
330                notifyAll();
331            }
332        }
333    }
334    DVFSWorkaround mDvfsWar = new DVFSWorkaround();
335
336    ///////////////////////////////////////////////////////////
337
338
339    private boolean mDoingBenchmark;
340    public Processor mProcessor;
341
342
343    private Handler mHandler = new Handler() {
344        @Override
345        public void handleMessage(Message msg) {
346            mDisplayView.invalidate();
347        }
348    };
349
350    public void updateDisplay() {
351        mHandler.sendMessage(Message.obtain());
352        //mProcessor.update();
353    }
354
355    TestBase changeTest(int id) {
356        IPTestListJB.TestName t = IPTestListJB.TestName.values()[id];
357        TestBase tb = IPTestListJB.newTest(t);
358        tb.createBaseTest(this);
359        //setupBars(tb);
360        return tb;
361    }
362
363    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
364        if (fromUser) {
365            if (seekBar == mBar1) {
366                mProcessor.mTest.onBar1Changed(progress);
367            } else if (seekBar == mBar2) {
368                mProcessor.mTest.onBar2Changed(progress);
369            } else if (seekBar == mBar3) {
370                mProcessor.mTest.onBar3Changed(progress);
371            } else if (seekBar == mBar4) {
372                mProcessor.mTest.onBar4Changed(progress);
373            } else if (seekBar == mBar5) {
374                mProcessor.mTest.onBar5Changed(progress);
375            }
376            mProcessor.update();
377        }
378    }
379
380    public void onStartTrackingTouch(SeekBar seekBar) {
381    }
382
383    public void onStopTrackingTouch(SeekBar seekBar) {
384    }
385
386    void setupBars(TestBase t) {
387        mSpinner.setVisibility(View.VISIBLE);
388        t.onSpinner1Setup(mSpinner);
389
390        mBar1.setVisibility(View.VISIBLE);
391        mText1.setVisibility(View.VISIBLE);
392        t.onBar1Setup(mBar1, mText1);
393
394        mBar2.setVisibility(View.VISIBLE);
395        mText2.setVisibility(View.VISIBLE);
396        t.onBar2Setup(mBar2, mText2);
397
398        mBar3.setVisibility(View.VISIBLE);
399        mText3.setVisibility(View.VISIBLE);
400        t.onBar3Setup(mBar3, mText3);
401
402        mBar4.setVisibility(View.VISIBLE);
403        mText4.setVisibility(View.VISIBLE);
404        t.onBar4Setup(mBar4, mText4);
405
406        mBar5.setVisibility(View.VISIBLE);
407        mText5.setVisibility(View.VISIBLE);
408        t.onBar5Setup(mBar5, mText5);
409    }
410
411
412    void cleanup() {
413        synchronized(this) {
414            mProcessor.exit();
415        }
416
417        mBitmapIn = null;
418        mBitmapIn2 = null;
419    }
420
421    @Override
422    protected void onCreate(Bundle savedInstanceState) {
423        super.onCreate(savedInstanceState);
424        setContentView(R.layout.main);
425
426        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
427        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
428
429        mDisplayView = (TextureView) findViewById(R.id.display);
430
431        mSpinner = (Spinner) findViewById(R.id.spinner1);
432
433        mBar1 = (SeekBar) findViewById(R.id.slider1);
434        mBar2 = (SeekBar) findViewById(R.id.slider2);
435        mBar3 = (SeekBar) findViewById(R.id.slider3);
436        mBar4 = (SeekBar) findViewById(R.id.slider4);
437        mBar5 = (SeekBar) findViewById(R.id.slider5);
438
439        mBar1.setOnSeekBarChangeListener(this);
440        mBar2.setOnSeekBarChangeListener(this);
441        mBar3.setOnSeekBarChangeListener(this);
442        mBar4.setOnSeekBarChangeListener(this);
443        mBar5.setOnSeekBarChangeListener(this);
444
445        mText1 = (TextView) findViewById(R.id.slider1Text);
446        mText2 = (TextView) findViewById(R.id.slider2Text);
447        mText3 = (TextView) findViewById(R.id.slider3Text);
448        mText4 = (TextView) findViewById(R.id.slider4Text);
449        mText5 = (TextView) findViewById(R.id.slider5Text);
450    }
451
452    @Override
453    protected void onPause() {
454        super.onPause();
455
456        cleanup();
457    }
458
459    public void onBenchmarkFinish() {
460        Intent intent = new Intent();
461        intent.putExtra("tests", mTestList);
462        intent.putExtra("results", mTestResults);
463        setResult(RESULT_OK, intent);
464        finish();
465    }
466
467    @Override
468    protected void onResume() {
469        super.onResume();
470        Intent i = getIntent();
471        mTestList = i.getIntArrayExtra("tests");
472
473        mToggleIO = i.getBooleanExtra("enable io", true);
474        mToggleDVFS = i.getBooleanExtra("enable dvfs", true);
475        mToggleLong = i.getBooleanExtra("enable long", false);
476        mTogglePause = i.getBooleanExtra("enable pause", false);
477
478        mTestResults = new float[mTestList.length];
479
480        mProcessor = new Processor(RenderScript.create(this), mDisplayView, true);
481        mDisplayView.setSurfaceTextureListener(this);
482    }
483
484    protected void onDestroy() {
485        super.onDestroy();
486    }
487
488    private Bitmap loadBitmap(int resource) {
489        final BitmapFactory.Options options = new BitmapFactory.Options();
490        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
491        return BitmapFactory.decodeResource(getResources(), resource, options);
492    }
493
494
495
496    @Override
497    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
498        mProcessor.setSurface(new Surface(surface));
499    }
500
501    @Override
502    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
503        mProcessor.setSurface(new Surface(surface));
504    }
505
506    @Override
507    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
508        mProcessor.setSurface(null);
509        return true;
510    }
511
512    @Override
513    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
514    }
515}
516