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