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.image2;
18
19import android.app.Activity;
20
21import android.content.Intent;
22import android.os.Bundle;
23import android.graphics.BitmapFactory;
24import android.graphics.Bitmap;
25import android.graphics.Canvas;
26import android.support.v8.renderscript.*;
27import android.os.Handler;
28import android.os.Message;
29import android.widget.AdapterView;
30import android.widget.ArrayAdapter;
31import android.widget.ImageView;
32import android.widget.SeekBar;
33import android.widget.Spinner;
34import android.widget.TextView;
35import android.view.View;
36import android.view.TextureView;
37import android.view.Surface;
38import android.graphics.SurfaceTexture;
39import android.graphics.Point;
40
41import android.util.Log;
42
43
44public class ImageProcessingActivity2 extends Activity
45                                       implements SeekBar.OnSeekBarChangeListener,
46                                                  TextureView.SurfaceTextureListener {
47    private final String TAG = "Img";
48
49    private Spinner mSpinner;
50    private SeekBar mBar1;
51    private SeekBar mBar2;
52    private SeekBar mBar3;
53    private SeekBar mBar4;
54    private SeekBar mBar5;
55
56    private int mBars[] = new int[5];
57    private int mBarsOld[] = new int[5];
58
59    private TextView mText1;
60    private TextView mText2;
61    private TextView mText3;
62    private TextView mText4;
63    private TextView mText5;
64    private ImageView mDisplayView;
65    private SizedTV mDisplayViewIO;
66
67    private int mTestList[];
68    private float mTestResults[];
69
70    private boolean mToggleLong;
71    private boolean mTogglePause;
72    private boolean mToggleAnimate;
73    private boolean mToggleDisplay;
74    private boolean mToggleIO;
75    private int mBitmapWidth;
76    private int mBitmapHeight;
77    private boolean mDemoMode;
78
79    // Updates pending is a counter of how many kernels have been
80    // sent to RS for processing and are not yet started.
81    private int mUpdatesPending;
82
83    // This is used to count updates in the pipeline.  It's
84    // incremented when work is submitted to RS and decremented when we
85    // receive the callback the kernel has finished.
86    private int mShowsPending;
87
88    private boolean mTestNameChanged = true;
89    private String mTestName;
90
91    static public class SizedTV extends TextureView {
92        int mWidth;
93        int mHeight;
94
95        public SizedTV(android.content.Context c) {
96            super(c);
97            mWidth = 800;
98            mHeight = 450;
99        }
100
101        public SizedTV(android.content.Context c, android.util.AttributeSet attrs) {
102            super(c, attrs);
103            mWidth = 800;
104            mHeight = 450;
105        }
106
107        public SizedTV(android.content.Context c, android.util.AttributeSet attrs, int f) {
108            super(c, attrs, f);
109            mWidth = 800;
110            mHeight = 450;
111        }
112
113        protected void onMeasure(int w, int h) {
114            setMeasuredDimension(mWidth, mHeight);
115        }
116    }
117
118
119    /////////////////////////////////////////////////////////////////////////
120
121    // Message processor to handle notifications for when kernel completes
122    private class MessageProcessor extends RenderScript.RSMessageHandler {
123        MessageProcessor() {
124        }
125
126        public void run() {
127            synchronized(mProcessor) {
128                // Decrement the pending displays and notify the
129                // UI processor it can now enqueue more work if additional updates
130                // are blocked by a full pipeline.
131                if (mShowsPending > 0) {
132                    mShowsPending --;
133                    mProcessor.notifyAll();
134                    if (mToggleDisplay) {
135                        mProcessor.mHandler.sendMessage(Message.obtain());
136                    }
137                }
138            }
139        }
140    }
141
142
143    /////////////////////////////////////////////////////////////////////////
144    // Processor is a helper thread for running the work without
145    // blocking the UI thread.
146    class Processor extends Thread {
147        RenderScript mRS;
148        ScriptC_util mScriptUtils;
149        Allocation mInPixelsAllocation;
150        Allocation mInPixelsAllocation2;
151        Allocation mOutDisplayAllocation1;
152        Allocation mOutDisplayAllocation2;
153        Bitmap mBitmapOut1;
154        Bitmap mBitmapOut2;
155        int mActiveBitmap;
156
157        private float mLastResult;
158        private boolean mRun = true;
159        private boolean mDoingBenchmark;
160        private TestBase mTest;
161
162        private boolean mBenchmarkMode;
163
164        Allocation mOutDisplayAllocationIO;
165        Allocation mOutPixelsAllocationIO;
166        private TextureView mDisplayViewIO;
167        private Surface mOutSurface;
168        // We don't want to call the "changed" methods excessively as this
169        // can cause extra work for drivers.  Before running a test update
170        // any bars which have changed.
171        //
172        // These are UI elements which can be used to control the operation of
173        // a filter.  For example, blur radius or white level.
174        void runTest() {
175            if (mBars[0] != mBarsOld[0]) {
176                mTest.onBar1Changed(mBars[0]);
177                mBarsOld[0] = mBars[0];
178            }
179            if (mBars[1] != mBarsOld[1]) {
180                mTest.onBar2Changed(mBars[1]);
181                mBarsOld[1] = mBars[1];
182            }
183            if (mBars[2] != mBarsOld[2]) {
184                mTest.onBar3Changed(mBars[2]);
185                mBarsOld[2] = mBars[2];
186            }
187            if (mBars[3] != mBarsOld[3]) {
188                mTest.onBar4Changed(mBars[3]);
189                mBarsOld[3] = mBars[3];
190            }
191            if (mBars[4] != mBarsOld[4]) {
192                mTest.onBar5Changed(mBars[4]);
193                mBarsOld[4] = mBars[4];
194            }
195            mTest.runTest();
196        }
197
198        Processor(RenderScript rs, boolean benchmarkMode) {
199            mRS = rs;
200            mRS.setMessageHandler(new MessageProcessor());
201            mScriptUtils = new ScriptC_util(mRS);
202
203            switch(mBitmapWidth) {
204            case 1920:
205                mInPixelsAllocation = Allocation.createFromBitmapResource(
206                        mRS, getResources(), R.drawable.img1920x1080a);
207                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
208                        mRS, getResources(), R.drawable.img1920x1080b);
209                mBitmapOut1 = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
210                mBitmapOut2 = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
211                break;
212            case 1280:
213                mInPixelsAllocation = Allocation.createFromBitmapResource(
214                        mRS, getResources(), R.drawable.img1280x720a);
215                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
216                        mRS, getResources(), R.drawable.img1280x720b);
217                mBitmapOut1 = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
218                mBitmapOut2 = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
219                break;
220            case 800:
221                mInPixelsAllocation = Allocation.createFromBitmapResource(
222                        mRS, getResources(), R.drawable.img800x450a);
223                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
224                        mRS, getResources(), R.drawable.img800x450b);
225                mBitmapOut1 = Bitmap.createBitmap(800, 450, Bitmap.Config.ARGB_8888);
226                mBitmapOut2 = Bitmap.createBitmap(800, 450, Bitmap.Config.ARGB_8888);
227                break;
228            default:
229                throw new RuntimeException("unhandled bitmap width.");
230            }
231
232            mBitmapOut1.setHasAlpha(false);
233            mBitmapOut2.setHasAlpha(false);
234            mOutDisplayAllocation1 = Allocation.createFromBitmap(mRS, mBitmapOut1);
235            mOutDisplayAllocation2 = Allocation.createFromBitmap(mRS, mBitmapOut2);
236            mBenchmarkMode = benchmarkMode;
237            start();
238        }
239
240        Processor(RenderScript rs, TextureView v, boolean benchmarkMode) {
241            mRS = rs;
242            mRS.setMessageHandler(new MessageProcessor());
243            mScriptUtils = new ScriptC_util(mRS);
244            mDisplayViewIO = v;
245
246            switch(mBitmapWidth) {
247            case 1920:
248                mInPixelsAllocation = Allocation.createFromBitmapResource(
249                        mRS, getResources(), R.drawable.img1920x1080a);
250                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
251                        mRS, getResources(), R.drawable.img1920x1080b);
252                break;
253            case 1280:
254                mInPixelsAllocation = Allocation.createFromBitmapResource(
255                        mRS, getResources(), R.drawable.img1280x720a);
256                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
257                        mRS, getResources(), R.drawable.img1280x720b);
258                break;
259            case 800:
260                mInPixelsAllocation = Allocation.createFromBitmapResource(
261                        mRS, getResources(), R.drawable.img800x450a);
262                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
263                        mRS, getResources(), R.drawable.img800x450b);
264                break;
265            }
266
267            mOutDisplayAllocationIO = Allocation.createTyped(mRS, mInPixelsAllocation.getType(),
268                                                               Allocation.MipmapControl.MIPMAP_NONE,
269                                                               Allocation.USAGE_SCRIPT |
270                                                               Allocation.USAGE_IO_OUTPUT);
271            mOutPixelsAllocationIO = mOutDisplayAllocationIO;
272
273            mBenchmarkMode = benchmarkMode;
274            start();
275        }
276
277        class Result {
278            float totalTime;
279            int iterations;
280        }
281
282        // Run one loop of kernels for at least the specified minimum time.
283        // The function returns the average time in ms for the test run
284        private Result runBenchmarkLoop(float minTime) {
285            mUpdatesPending = 0;
286            Result r = new Result();
287
288            long t = java.lang.System.currentTimeMillis();
289            do {
290                synchronized(this) {
291                    // Shows pending is used to track the number of kernels in the RS pipeline
292                    // We throttle it to 2.  This provide some buffering to allow a kernel to be started
293                    // before we are nofitied the previous finished.  However, larger numbers are uncommon
294                    // in interactive apps as they introduce 'lag' between user input and display.
295                    mShowsPending++;
296                    if (mShowsPending > 2) {
297                        try {
298                            this.wait();
299                        } catch(InterruptedException e) {
300                        }
301                    }
302                }
303
304                // If animations are enabled update the test state.
305                if (mToggleAnimate) {
306                    mTest.animateBars(r.totalTime);
307                }
308
309                // Run the kernel
310                if (!mToggleIO) {
311                    if (mActiveBitmap == 0) {
312                        mTest.mOutPixelsAllocation = mOutDisplayAllocation1;
313                    } else {
314                        mTest.mOutPixelsAllocation = mOutDisplayAllocation2;
315                    }
316                } else {
317                    mTest.mOutPixelsAllocation = mOutDisplayAllocationIO;
318                }
319
320                mTest.runTest();
321                r.iterations ++;
322
323                if (!mToggleIO) {
324                    if (mToggleDisplay) {
325                        if (mActiveBitmap == 0) {
326                            mOutDisplayAllocation1.copyTo(mBitmapOut1);
327                        } else {
328                            mOutDisplayAllocation2.copyTo(mBitmapOut2);
329                        }
330                    }
331
332                }
333                // Send our RS message handler a message so we know when this work has completed
334                mScriptUtils.invoke_utilSendMessage(mActiveBitmap);
335                mActiveBitmap ^= 1;
336
337                long t2 = java.lang.System.currentTimeMillis();
338                r.totalTime = (t2 - t) / 1000.f;
339            } while (r.totalTime < minTime);
340
341            mRS.finish();
342            long t2 = java.lang.System.currentTimeMillis();
343            r.totalTime = (t2 - t) / 1000.f;
344
345            // Even if we are not displaying as we go, show the final output
346            if (!mToggleIO) {
347                mOutDisplayAllocation1.copyTo(mBitmapOut1);
348                mOutDisplayAllocation2.copyTo(mBitmapOut2);
349            }
350            return r;
351        }
352
353
354        // Get a benchmark result for a specific test
355        private float getBenchmark() {
356            mDoingBenchmark = true;
357            mUpdatesPending = 0;
358
359            long result = 0;
360            float runtime = 1.f;
361            if (mToggleLong) {
362                runtime = 10.f;
363            }
364
365            // We run a short bit of work before starting the actual test
366            // this is to let any power management do its job and respond
367            runBenchmarkLoop(0.3f);
368
369            // Run the actual benchmark
370            Result r = runBenchmarkLoop(runtime);
371
372            Log.v("rs", "Test: time=" + r.totalTime +"s,  frames=" + r.iterations +
373                  ", avg=" + r.totalTime / r.iterations * 1000.f);
374
375            mDoingBenchmark = false;
376            return r.totalTime / r.iterations * 1000.f;
377        }
378
379        private int mDisplayedBitmap;
380        private Handler mHandler = new Handler() {
381            @Override
382            public void handleMessage(Message msg) {
383                if (mTestNameChanged) {
384                    getActionBar().setTitle("IP-Compat test: " + mTestName);
385                }
386
387                if (!mToggleIO) {
388                    if (mDisplayedBitmap == 0) {
389                        mDisplayView.setImageBitmap(mBitmapOut1);
390                    } else {
391                        mDisplayView.setImageBitmap(mBitmapOut2);
392                    }
393                    mDisplayedBitmap ^= 1;
394                    mDisplayView.invalidate();
395                } else {
396                    synchronized(this) {
397                        if (mRS == null || mOutPixelsAllocationIO == null) {
398                            return;
399                        }
400                        if (mOutDisplayAllocationIO != mOutPixelsAllocationIO) {
401                            mOutDisplayAllocationIO.copyFrom(mOutPixelsAllocationIO);
402                        }
403                        mOutDisplayAllocationIO.ioSend();
404                    }
405                }
406            }
407        };
408
409        public void run() {
410            Surface lastSurface = null;
411            while (mRun) {
412                // Our loop for launching tests or benchmarks
413                synchronized(this) {
414                    // If we have no work to do, or we have displays pending, wait
415                    if ((mUpdatesPending == 0) || (mShowsPending != 0)) {
416                        try {
417                            this.wait();
418                        } catch(InterruptedException e) {
419                        }
420                    }
421                    if (mToggleIO) {
422                        if ((mOutSurface == null) || (mOutPixelsAllocationIO == null)) {
423                            continue;
424                        }
425                        if (lastSurface != mOutSurface) {
426                            mOutDisplayAllocationIO.setSurface(mOutSurface);
427                            lastSurface = mOutSurface;
428                        }
429                    }
430                    // We may have been asked to exit while waiting
431                    if (!mRun) return;
432
433                }
434
435                if (mBenchmarkMode) {
436                    // Loop over the tests we want to benchmark
437                    for (int ct=0; (ct < mTestList.length) && mRun; ct++) {
438
439                        // For reproducibility we wait a short time for any sporadic work
440                        // created by the user touching the screen to launch the test to pass.
441                        // Also allows for things to settle after the test changes.
442                        mRS.finish();
443                        try {
444                            sleep(250);
445                        } catch(InterruptedException e) {
446                        }
447
448                        // If we just ran a test, we destroy it here to relieve some memory pressure
449                        if (mTest != null) {
450                            mTest.destroy();
451                        }
452
453                        // Select the next test
454                        mTest = changeTest(mTestList[ct], false);
455
456                        // If the user selected the "long pause" option, wait
457                        if (mTogglePause) {
458                            for (int i=0; (i < 100) && mRun; i++) {
459                                try {
460                                    sleep(100);
461                                } catch(InterruptedException e) {
462                                }
463                            }
464                        }
465
466                        // Run the test
467                        mTestResults[ct] = getBenchmark();
468                    }
469                    onBenchmarkFinish(mRun);
470                    return;
471                } else {
472                    boolean update = false;
473                    synchronized(this) {
474                        // If we have updates to process and are not blocked by pending shows,
475                        // start the next kernel
476                        if ((mUpdatesPending > 0) && (mShowsPending == 0)) {
477                            mUpdatesPending = 0;
478                            update = true;
479                            mShowsPending++;
480                        }
481                    }
482
483                    if (update) {
484                        // Run the kernel
485                        if (mActiveBitmap == 0) {
486                            mTest.mOutPixelsAllocation = mOutDisplayAllocation1;
487                        } else {
488                            mTest.mOutPixelsAllocation = mOutDisplayAllocation2;
489                        }
490                        if (mToggleIO) {
491                            mTest.mOutPixelsAllocation = mOutDisplayAllocationIO;
492                        }
493                        runTest();
494
495                        if (mToggleDisplay && !mToggleIO) {
496                            if (mActiveBitmap == 0) {
497                                mOutDisplayAllocation1.copyTo(mBitmapOut1);
498                            } else {
499                                mOutDisplayAllocation2.copyTo(mBitmapOut2);
500                            }
501                        }
502
503                        // Send our RS message handler a message so we know when this work has completed
504                        mScriptUtils.invoke_utilSendMessage(mActiveBitmap);
505                        mActiveBitmap ^= 1;
506                    }
507                }
508            }
509
510        }
511
512        public void update() {
513            // Something UI related has changed, enqueue an update if one is not
514            // already pending.  Wake the worker if needed.
515            synchronized(this) {
516                if (mUpdatesPending < 2) {
517                    mUpdatesPending++;
518                    notifyAll();
519                }
520            }
521        }
522
523        public void setSurface(Surface s) {
524            synchronized(this) {
525                mOutSurface = s;
526                notifyAll();
527            }
528            //update();
529        }
530
531        public void exit() {
532            mRun = false;
533
534            synchronized(this) {
535                notifyAll();
536            }
537
538            try {
539                this.join();
540            } catch(InterruptedException e) {
541            }
542
543            mInPixelsAllocation.destroy();
544            mInPixelsAllocation2.destroy();
545
546            if (mTest != null) {
547                mTest.destroy();
548                mTest = null;
549            }
550
551            if(!mToggleIO) {
552                mOutDisplayAllocation1.destroy();
553                mOutDisplayAllocation2.destroy();
554            } else {
555                if (mOutPixelsAllocationIO != mOutDisplayAllocationIO) {
556                    mOutPixelsAllocationIO.destroy();
557                }
558                mOutDisplayAllocationIO.destroy();
559            }
560            mRS.destroy();
561
562            mInPixelsAllocation = null;
563            mInPixelsAllocation2 = null;
564            mOutDisplayAllocation1 = null;
565            mOutDisplayAllocation2 = null;
566            mOutDisplayAllocationIO = null;
567            mOutPixelsAllocationIO = null;
568            mRS = null;
569        }
570    }
571
572    ///////////////////////////////////////////////////////////////////////////////////////
573
574    private boolean mDoingBenchmark;
575    public Processor mProcessor;
576
577    TestBase changeTest(IPTestList.TestName t, boolean setupUI) {
578        TestBase tb = IPTestList.newTest(t);
579
580        mTestNameChanged = true;
581        mTestName = t.toString();
582        mProcessor.mHandler.sendMessage(Message.obtain());
583
584        tb.createBaseTest(this);
585        if (setupUI) {
586            setupBars(tb);
587        }
588        return tb;
589    }
590
591    TestBase changeTest(int id, boolean setupUI) {
592        IPTestList.TestName t = IPTestList.TestName.values()[id];
593        return changeTest(t, setupUI);
594    }
595
596    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
597        if (fromUser) {
598            if (seekBar == mBar1) {
599                mBars[0] = progress;
600            } else if (seekBar == mBar2) {
601                mBars[1] = progress;
602            } else if (seekBar == mBar3) {
603                mBars[2] = progress;
604            } else if (seekBar == mBar4) {
605                mBars[3] = progress;
606            } else if (seekBar == mBar5) {
607                mBars[4] = progress;
608            }
609            mProcessor.update();
610        }
611    }
612
613    public void onStartTrackingTouch(SeekBar seekBar) {
614    }
615
616    public void onStopTrackingTouch(SeekBar seekBar) {
617    }
618
619    void setupBars(TestBase t) {
620        mSpinner.setVisibility(View.VISIBLE);
621        t.onSpinner1Setup(mSpinner);
622
623        mBar1.setVisibility(View.VISIBLE);
624        mText1.setVisibility(View.VISIBLE);
625        t.onBar1Setup(mBar1, mText1);
626
627        mBar2.setVisibility(View.VISIBLE);
628        mText2.setVisibility(View.VISIBLE);
629        t.onBar2Setup(mBar2, mText2);
630
631        mBar3.setVisibility(View.VISIBLE);
632        mText3.setVisibility(View.VISIBLE);
633        t.onBar3Setup(mBar3, mText3);
634
635        mBar4.setVisibility(View.VISIBLE);
636        mText4.setVisibility(View.VISIBLE);
637        t.onBar4Setup(mBar4, mText4);
638
639        mBar5.setVisibility(View.VISIBLE);
640        mText5.setVisibility(View.VISIBLE);
641        t.onBar5Setup(mBar5, mText5);
642    }
643
644    void hideBars() {
645        mSpinner.setVisibility(View.INVISIBLE);
646
647        mBar1.setVisibility(View.INVISIBLE);
648        mText1.setVisibility(View.INVISIBLE);
649
650        mBar2.setVisibility(View.INVISIBLE);
651        mText2.setVisibility(View.INVISIBLE);
652
653        mBar3.setVisibility(View.INVISIBLE);
654        mText3.setVisibility(View.INVISIBLE);
655
656        mBar4.setVisibility(View.INVISIBLE);
657        mText4.setVisibility(View.INVISIBLE);
658
659        mBar5.setVisibility(View.INVISIBLE);
660        mText5.setVisibility(View.INVISIBLE);
661    }
662
663    @Override
664    protected void onCreate(Bundle savedInstanceState) {
665        super.onCreate(savedInstanceState);
666        setContentView(R.layout.main);
667
668        mDisplayView = (ImageView) findViewById(R.id.display);
669        mDisplayViewIO = (SizedTV) findViewById(R.id.display2);
670        //mDisplayView.setImageBitmap(mBitmapOut);
671
672        mSpinner = (Spinner) findViewById(R.id.spinner1);
673
674        mBar1 = (SeekBar) findViewById(R.id.slider1);
675        mBar2 = (SeekBar) findViewById(R.id.slider2);
676        mBar3 = (SeekBar) findViewById(R.id.slider3);
677        mBar4 = (SeekBar) findViewById(R.id.slider4);
678        mBar5 = (SeekBar) findViewById(R.id.slider5);
679
680        mBar1.setOnSeekBarChangeListener(this);
681        mBar2.setOnSeekBarChangeListener(this);
682        mBar3.setOnSeekBarChangeListener(this);
683        mBar4.setOnSeekBarChangeListener(this);
684        mBar5.setOnSeekBarChangeListener(this);
685
686        mText1 = (TextView) findViewById(R.id.slider1Text);
687        mText2 = (TextView) findViewById(R.id.slider2Text);
688        mText3 = (TextView) findViewById(R.id.slider3Text);
689        mText4 = (TextView) findViewById(R.id.slider4Text);
690        mText5 = (TextView) findViewById(R.id.slider5Text);
691    }
692
693    @Override
694    protected void onPause() {
695        super.onPause();
696        mProcessor.exit();
697    }
698
699    public void onBenchmarkFinish(boolean ok) {
700        if (ok) {
701            Intent intent = new Intent();
702            intent.putExtra("tests", mTestList);
703            intent.putExtra("results", mTestResults);
704            setResult(RESULT_OK, intent);
705        } else {
706            setResult(RESULT_CANCELED);
707        }
708        finish();
709    }
710
711
712    void startProcessor() {
713        if (!mDemoMode) {
714            hideBars();
715        }
716
717        Point size = new Point();
718        getWindowManager().getDefaultDisplay().getSize(size);
719
720        int mScreenWidth = size.x;
721        int mScreenHeight = size.y;
722
723        int tw = mBitmapWidth;
724        int th = mBitmapHeight;
725
726        if (tw > mScreenWidth || th > mScreenHeight) {
727            float s1 = (float)tw / (float)mScreenWidth;
728            float s2 = (float)th / (float)mScreenHeight;
729
730            if (s1 > s2) {
731                tw /= s1;
732                th /= s1;
733            } else {
734                tw /= s2;
735                th /= s2;
736            }
737        }
738
739        android.util.Log.v("rs", "TV sizes " + tw + ", " + th);
740        if (mToggleIO) {
741            mDisplayViewIO.mWidth = tw;
742            mDisplayViewIO.mHeight = th;
743
744            mProcessor = new Processor(RenderScript.create(this), mDisplayViewIO, !mDemoMode);
745            mDisplayViewIO.setSurfaceTextureListener(this);
746        } else {
747            mProcessor = new Processor(RenderScript.create(this), !mDemoMode);
748        }
749        if (mDemoMode) {
750            mProcessor.mTest = changeTest(mTestList[0], true);
751        }
752        mProcessor.update();
753    }
754
755    @Override
756    protected void onResume() {
757        super.onResume();
758        Intent i = getIntent();
759        mTestList = i.getIntArrayExtra("tests");
760        mToggleIO = i.getBooleanExtra("enable io", false);
761        mToggleLong = i.getBooleanExtra("enable long", false);
762        mTogglePause = i.getBooleanExtra("enable pause", false);
763        mToggleAnimate = i.getBooleanExtra("enable animate", false);
764        mToggleDisplay = i.getBooleanExtra("enable display", false);
765        mBitmapWidth = i.getIntExtra("resolution X", 0);
766        mBitmapHeight = i.getIntExtra("resolution Y", 0);
767        mDemoMode = i.getBooleanExtra("demo", false);
768        mTestResults = new float[mTestList.length];
769
770        startProcessor();
771    }
772
773    protected void onDestroy() {
774        super.onDestroy();
775    }
776    @Override
777    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
778        mProcessor.setSurface(new Surface(surface));
779    }
780
781    @Override
782    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
783        mProcessor.setSurface(new Surface(surface));
784    }
785
786    @Override
787    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
788        mProcessor.setSurface(null);
789        return true;
790    }
791
792    @Override
793    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
794    }
795
796}
797