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