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 |