| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "Viewer.h" | 8 #include "Viewer.h" |
| 9 | 9 |
| 10 #include "GMSlide.h" | 10 #include "GMSlide.h" |
| 11 #include "ImageSlide.h" |
| 11 #include "SKPSlide.h" | 12 #include "SKPSlide.h" |
| 12 | 13 |
| 13 #include "SkCanvas.h" | 14 #include "SkCanvas.h" |
| 14 #include "SkCommonFlags.h" | 15 #include "SkCommonFlags.h" |
| 16 #include "SkMetaData.h" |
| 15 #include "SkOSFile.h" | 17 #include "SkOSFile.h" |
| 16 #include "SkRandom.h" | 18 #include "SkRandom.h" |
| 17 #include "SkStream.h" | 19 #include "SkStream.h" |
| 18 | 20 |
| 19 using namespace sk_app; | 21 using namespace sk_app; |
| 20 | 22 |
| 21 Application* Application::Create(int argc, char** argv, void* platformData) { | 23 Application* Application::Create(int argc, char** argv, void* platformData) { |
| 22 return new Viewer(argc, argv, platformData); | 24 return new Viewer(argc, argv, platformData); |
| 23 } | 25 } |
| 24 | 26 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 45 DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON identifyi
ng this builder."); | 47 DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON identifyi
ng this builder."); |
| 46 DEFINE_string2(match, m, nullptr, | 48 DEFINE_string2(match, m, nullptr, |
| 47 "[~][^]substring[$] [...] of bench name to run.\n" | 49 "[~][^]substring[$] [...] of bench name to run.\n" |
| 48 "Multiple matches may be separated by spaces.\n" | 50 "Multiple matches may be separated by spaces.\n" |
| 49 "~ causes a matching bench to always be skipped\n" | 51 "~ causes a matching bench to always be skipped\n" |
| 50 "^ requires the start of the bench to match\n" | 52 "^ requires the start of the bench to match\n" |
| 51 "$ requires the end of the bench to match\n" | 53 "$ requires the end of the bench to match\n" |
| 52 "^ and $ requires an exact match\n" | 54 "^ and $ requires an exact match\n" |
| 53 "If a bench does not match any list entry,\n" | 55 "If a bench does not match any list entry,\n" |
| 54 "it is skipped unless some list entry starts with ~"); | 56 "it is skipped unless some list entry starts with ~"); |
| 55 DEFINE_string(skps, "skps", "Directory to read skps from."); | |
| 56 #ifdef SK_BUILD_FOR_ANDROID | 57 #ifdef SK_BUILD_FOR_ANDROID |
| 58 DEFINE_string(skps, "/data/local/tmp/skia", "Directory to read skps from."); |
| 59 DEFINE_string(jpgs, "/data/local/tmp/skia", "Directory to read jpgs from."); |
| 57 DEFINE_bool(vulkan, false, "Run with Vulkan."); | 60 DEFINE_bool(vulkan, false, "Run with Vulkan."); |
| 58 #else | 61 #else |
| 62 DEFINE_string(skps, "skps", "Directory to read skps from."); |
| 63 DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from."); |
| 59 DEFINE_bool(vulkan, true, "Run with Vulkan."); | 64 DEFINE_bool(vulkan, true, "Run with Vulkan."); |
| 60 #endif | 65 #endif |
| 61 | 66 |
| 62 const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = { | 67 const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = { |
| 63 " [OpenGL]", | 68 " [OpenGL]", |
| 64 " [Vulkan]", | 69 " [Vulkan]", |
| 65 " [Raster]" | 70 " [Raster]" |
| 66 }; | 71 }; |
| 67 | 72 |
| 68 const char* kName = "name"; | 73 const char* kName = "name"; |
| 69 const char* kValue = "value"; | 74 const char* kValue = "value"; |
| 70 const char* kOptions = "options"; | 75 const char* kOptions = "options"; |
| 71 const char* kSlideStateName = "Slide"; | 76 const char* kSlideStateName = "Slide"; |
| 72 const char* kBackendStateName = "Backend"; | 77 const char* kBackendStateName = "Backend"; |
| 73 const char* kSoftkeyStateName = "Softkey"; | 78 const char* kSoftkeyStateName = "Softkey"; |
| 74 const char* kSoftkeyHint = "Please select a softkey"; | 79 const char* kSoftkeyHint = "Please select a softkey"; |
| 75 const char* kFpsStateName = "FPS"; | 80 const char* kFpsStateName = "FPS"; |
| 81 const char* kSplitScreenStateName = "Split screen"; |
| 82 const char* kON = "ON"; |
| 83 const char* kOFF = "OFF"; |
| 76 | 84 |
| 77 Viewer::Viewer(int argc, char** argv, void* platformData) | 85 Viewer::Viewer(int argc, char** argv, void* platformData) |
| 78 : fCurrentMeasurement(0) | 86 : fCurrentMeasurement(0) |
| 79 , fDisplayStats(false) | 87 , fDisplayStats(false) |
| 88 , fSplitScreen(false) |
| 80 , fBackendType(sk_app::Window::kVulkan_BackendType) | 89 , fBackendType(sk_app::Window::kVulkan_BackendType) |
| 81 , fZoomCenterX(0.0f) | 90 , fZoomCenterX(0.0f) |
| 82 , fZoomCenterY(0.0f) | 91 , fZoomCenterY(0.0f) |
| 83 , fZoomLevel(0.0f) | 92 , fZoomLevel(0.0f) |
| 84 , fZoomScale(SK_Scalar1) | 93 , fZoomScale(SK_Scalar1) |
| 85 { | 94 { |
| 86 memset(fMeasurements, 0, sizeof(fMeasurements)); | 95 memset(fMeasurements, 0, sizeof(fMeasurements)); |
| 87 | 96 |
| 88 SkDebugf("Command line arguments: "); | 97 SkDebugf("Command line arguments: "); |
| 89 for (int i = 1; i < argc; ++i) { | 98 for (int i = 1; i < argc; ++i) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 } | 226 } |
| 218 | 227 |
| 219 SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); | 228 SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); |
| 220 sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); | 229 sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); |
| 221 if (slide) { | 230 if (slide) { |
| 222 fSlides.push_back(slide); | 231 fSlides.push_back(slide); |
| 223 } | 232 } |
| 224 } | 233 } |
| 225 } | 234 } |
| 226 } | 235 } |
| 236 |
| 237 // JPGs |
| 238 for (int i = 0; i < FLAGS_jpgs.count(); i++) { |
| 239 SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg"); |
| 240 SkString jpgName; |
| 241 while (it.next(&jpgName)) { |
| 242 SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str()); |
| 243 sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path)); |
| 244 if (slide) { |
| 245 fSlides.push_back(slide); |
| 246 } |
| 247 } |
| 248 } |
| 227 } | 249 } |
| 228 | 250 |
| 229 | 251 |
| 230 Viewer::~Viewer() { | 252 Viewer::~Viewer() { |
| 231 fWindow->detach(); | 253 fWindow->detach(); |
| 232 delete fWindow; | 254 delete fWindow; |
| 233 } | 255 } |
| 234 | 256 |
| 235 void Viewer::updateTitle() { | 257 void Viewer::updateTitle() { |
| 236 SkString title("Viewer: "); | 258 SkString title("Viewer: "); |
| 237 title.append(fSlides[fCurrentSlide]->getName()); | 259 title.append(fSlides[fCurrentSlide]->getName()); |
| 238 if (kSRGB_SkColorProfileType == fWindow->getDisplayParams().fProfileType) { | 260 if (kSRGB_SkColorProfileType == fWindow->getDisplayParams().fProfileType) { |
| 239 title.append(" sRGB"); | 261 title.append(" sRGB"); |
| 240 } | 262 } |
| 241 title.append(kBackendTypeStrings[fBackendType]); | 263 title.append(kBackendTypeStrings[fBackendType]); |
| 242 fWindow->setTitle(title.c_str()); | 264 fWindow->setTitle(title.c_str()); |
| 243 } | 265 } |
| 244 | 266 |
| 245 void Viewer::setupCurrentSlide(int previousSlide) { | 267 void Viewer::setupCurrentSlide(int previousSlide) { |
| 246 if (fCurrentSlide == previousSlide) { | 268 if (fCurrentSlide == previousSlide) { |
| 247 return; // no change; do nothing | 269 return; // no change; do nothing |
| 248 } | 270 } |
| 249 | 271 |
| 272 // prepare dimensions for image slides |
| 273 fSlides[fCurrentSlide]->load(); |
| 274 |
| 250 fGesture.reset(); | 275 fGesture.reset(); |
| 251 fDefaultMatrix.reset(); | 276 fDefaultMatrix.reset(); |
| 252 fDefaultMatrixInv.reset(); | 277 fDefaultMatrixInv.reset(); |
| 253 | 278 |
| 254 if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { | 279 if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { |
| 255 const SkRect contentRect = fWindow->getContentRect(); | 280 const SkRect contentRect = fWindow->getContentRect(); |
| 256 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); | 281 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 257 const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.
height()); | 282 const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.
height()); |
| 258 if (contentRect.width() > 0 && contentRect.height() > 0) { | 283 if (contentRect.width() > 0 && contentRect.height() > 0) { |
| 259 fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kSt
art_ScaleToFit); | 284 fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kSt
art_ScaleToFit); |
| 260 SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); | 285 SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); |
| 261 } | 286 } |
| 262 } | 287 } |
| 263 | 288 |
| 264 if (fWindow->supportsContentRect()) { | 289 if (fWindow->supportsContentRect()) { |
| 265 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); | 290 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 266 SkRect windowRect = fWindow->getContentRect(); | 291 SkRect windowRect = fWindow->getContentRect(); |
| 267 fDefaultMatrixInv.mapRect(&windowRect); | 292 fDefaultMatrixInv.mapRect(&windowRect); |
| 268 fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), | 293 fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), |
| 269 SkIntToScalar(slideSize.height()))
, | 294 SkIntToScalar(slideSize.height()))
, |
| 270 windowRect); | 295 windowRect); |
| 271 } | 296 } |
| 272 | 297 |
| 273 this->updateTitle(); | 298 this->updateTitle(); |
| 274 this->updateUIState(); | 299 this->updateUIState(); |
| 275 fSlides[fCurrentSlide]->load(); | |
| 276 if (previousSlide >= 0) { | 300 if (previousSlide >= 0) { |
| 277 fSlides[previousSlide]->unload(); | 301 fSlides[previousSlide]->unload(); |
| 278 } | 302 } |
| 279 fWindow->inval(); | 303 fWindow->inval(); |
| 280 } | 304 } |
| 281 | 305 |
| 282 #define MAX_ZOOM_LEVEL 8 | 306 #define MAX_ZOOM_LEVEL 8 |
| 283 #define MIN_ZOOM_LEVEL -8 | 307 #define MIN_ZOOM_LEVEL -8 |
| 284 | 308 |
| 285 void Viewer::changeZoomLevel(float delta) { | 309 void Viewer::changeZoomLevel(float delta) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 310 m.postScale(fZoomScale, fZoomScale); | 334 m.postScale(fZoomScale, fZoomScale); |
| 311 m.postTranslate(cx, cy); | 335 m.postTranslate(cx, cy); |
| 312 } | 336 } |
| 313 | 337 |
| 314 m.preConcat(fGesture.localM()); | 338 m.preConcat(fGesture.localM()); |
| 315 m.preConcat(fGesture.globalM()); | 339 m.preConcat(fGesture.globalM()); |
| 316 | 340 |
| 317 return m; | 341 return m; |
| 318 } | 342 } |
| 319 | 343 |
| 320 void Viewer::onPaint(SkCanvas* canvas) { | 344 void Viewer::drawSlide(SkCanvas* canvas, bool inSplitScreen) { |
| 345 SkASSERT(!inSplitScreen || fWindow->supportsContentRect()); |
| 346 |
| 321 int count = canvas->save(); | 347 int count = canvas->save(); |
| 322 | 348 |
| 323 if (fWindow->supportsContentRect()) { | 349 if (fWindow->supportsContentRect()) { |
| 324 SkRect contentRect = fWindow->getContentRect(); | 350 SkRect contentRect = fWindow->getContentRect(); |
| 351 // If inSplitScreen, translate the image half screen to the right. |
| 352 // Thus we have two copies of the image on each half of the screen. |
| 353 contentRect.fLeft += inSplitScreen ? (contentRect.fRight - contentRect.f
Left) * 0.5 : 0; |
| 325 canvas->clipRect(contentRect); | 354 canvas->clipRect(contentRect); |
| 326 canvas->translate(contentRect.fLeft, contentRect.fTop); | 355 canvas->translate(contentRect.fLeft, contentRect.fTop); |
| 327 } | 356 } |
| 328 | 357 |
| 329 canvas->clear(SK_ColorWHITE); | 358 canvas->clear(SK_ColorWHITE); |
| 330 canvas->concat(fDefaultMatrix); | 359 canvas->concat(fDefaultMatrix); |
| 331 canvas->concat(computeMatrix()); | 360 canvas->concat(computeMatrix()); |
| 332 | 361 |
| 362 canvas->getMetaData().setBool(kImageColorXformMetaData, inSplitScreen); |
| 333 fSlides[fCurrentSlide]->draw(canvas); | 363 fSlides[fCurrentSlide]->draw(canvas); |
| 334 canvas->restoreToCount(count); | 364 canvas->restoreToCount(count); |
| 365 } |
| 366 |
| 367 void Viewer::onPaint(SkCanvas* canvas) { |
| 368 drawSlide(canvas, false); |
| 369 if (fSplitScreen && fWindow->supportsContentRect()) { |
| 370 drawSlide(canvas, true); |
| 371 } |
| 335 | 372 |
| 336 if (fDisplayStats) { | 373 if (fDisplayStats) { |
| 337 drawStats(canvas); | 374 drawStats(canvas); |
| 338 } | 375 } |
| 339 fCommands.drawHelp(canvas); | 376 fCommands.drawHelp(canvas); |
| 340 } | 377 } |
| 341 | 378 |
| 342 bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y)
{ | 379 bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y)
{ |
| 343 void* castedOwner = reinterpret_cast<void*>(owner); | 380 void* castedOwner = reinterpret_cast<void*>(owner); |
| 344 SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); | 381 SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 | 491 |
| 455 // FPS state | 492 // FPS state |
| 456 Json::Value fpsState(Json::objectValue); | 493 Json::Value fpsState(Json::objectValue); |
| 457 fpsState[kName] = kFpsStateName; | 494 fpsState[kName] = kFpsStateName; |
| 458 double measurement = fMeasurements[ | 495 double measurement = fMeasurements[ |
| 459 (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount | 496 (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount |
| 460 ]; | 497 ]; |
| 461 fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str(); | 498 fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str(); |
| 462 fpsState[kOptions] = Json::Value(Json::arrayValue); | 499 fpsState[kOptions] = Json::Value(Json::arrayValue); |
| 463 | 500 |
| 501 // Split screen state |
| 502 Json::Value splitScreenState(Json::objectValue); |
| 503 splitScreenState[kName] = kSplitScreenStateName; |
| 504 splitScreenState[kValue] = fSplitScreen ? kON : kOFF; |
| 505 splitScreenState[kOptions] = Json::Value(Json::arrayValue); |
| 506 splitScreenState[kOptions].append(kON); |
| 507 splitScreenState[kOptions].append(kOFF); |
| 508 |
| 464 Json::Value state(Json::arrayValue); | 509 Json::Value state(Json::arrayValue); |
| 465 state.append(slideState); | 510 state.append(slideState); |
| 466 state.append(backendState); | 511 state.append(backendState); |
| 467 state.append(softkeyState); | 512 state.append(softkeyState); |
| 468 state.append(fpsState); | 513 state.append(fpsState); |
| 514 state.append(splitScreenState); |
| 469 | 515 |
| 470 fWindow->setUIState(state); | 516 fWindow->setUIState(state); |
| 471 } | 517 } |
| 472 | 518 |
| 473 void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateVa
lue) { | 519 void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateVa
lue) { |
| 474 // For those who will add more features to handle the state change in this f
unction: | 520 // For those who will add more features to handle the state change in this f
unction: |
| 475 // After the change, please call updateUIState no notify the frontend (e.g.,
Android app). | 521 // After the change, please call updateUIState no notify the frontend (e.g.,
Android app). |
| 476 // For example, after slide change, updateUIState is called inside setupCurr
entSlide; | 522 // For example, after slide change, updateUIState is called inside setupCurr
entSlide; |
| 477 // after backend change, updateUIState is called in this function. | 523 // after backend change, updateUIState is called in this function. |
| 478 if (stateName.equals(kSlideStateName)) { | 524 if (stateName.equals(kSlideStateName)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 501 updateUIState(); | 547 updateUIState(); |
| 502 } | 548 } |
| 503 break; | 549 break; |
| 504 } | 550 } |
| 505 } | 551 } |
| 506 } else if (stateName.equals(kSoftkeyStateName)) { | 552 } else if (stateName.equals(kSoftkeyStateName)) { |
| 507 if (!stateValue.equals(kSoftkeyHint)) { | 553 if (!stateValue.equals(kSoftkeyHint)) { |
| 508 fCommands.onSoftkey(stateValue); | 554 fCommands.onSoftkey(stateValue); |
| 509 updateUIState(); // This is still needed to reset the value to kSoft
keyHint | 555 updateUIState(); // This is still needed to reset the value to kSoft
keyHint |
| 510 } | 556 } |
| 557 } else if (stateName.equals(kSplitScreenStateName)) { |
| 558 bool newSplitScreen = stateValue.equals(kON); |
| 559 if (newSplitScreen != fSplitScreen) { |
| 560 fSplitScreen = newSplitScreen; |
| 561 fWindow->inval(); |
| 562 updateUIState(); |
| 563 } |
| 511 } else { | 564 } else { |
| 512 SkDebugf("Unknown stateName: %s", stateName.c_str()); | 565 SkDebugf("Unknown stateName: %s", stateName.c_str()); |
| 513 } | 566 } |
| 514 } | 567 } |
| OLD | NEW |