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