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 "SKPSlide.h" | 11 #include "SKPSlide.h" |
12 #include "ImageSlide.h" | |
12 | 13 |
13 #include "SkCanvas.h" | 14 #include "SkCanvas.h" |
14 #include "SkCommonFlags.h" | 15 #include "SkCommonFlags.h" |
15 #include "SkOSFile.h" | 16 #include "SkOSFile.h" |
16 #include "SkRandom.h" | 17 #include "SkRandom.h" |
17 #include "SkStream.h" | 18 #include "SkStream.h" |
19 #include "SkMetaData.h" | |
msarett
2016/06/13 14:56:26
nit: alphabetical order
liyuqian
2016/06/13 16:10:40
Done.
| |
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 |
25 static void on_paint_handler(SkCanvas* canvas, void* userData) { | 27 static void on_paint_handler(SkCanvas* canvas, void* userData) { |
26 Viewer* vv = reinterpret_cast<Viewer*>(userData); | 28 Viewer* vv = reinterpret_cast<Viewer*>(userData); |
27 | 29 |
(...skipping 17 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) |
80 , fBackendType(sk_app::Window::kVulkan_BackendType) | 88 , fBackendType(sk_app::Window::kVulkan_BackendType) |
81 , fZoomCenterX(0.0f) | 89 , fZoomCenterX(0.0f) |
82 , fZoomCenterY(0.0f) | 90 , fZoomCenterY(0.0f) |
83 , fZoomLevel(0.0f) | 91 , fZoomLevel(0.0f) |
84 , fZoomScale(SK_Scalar1) | 92 , fZoomScale(SK_Scalar1) |
85 { | 93 { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 } | 225 } |
218 | 226 |
219 SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); | 227 SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); |
220 sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); | 228 sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); |
221 if (slide) { | 229 if (slide) { |
222 fSlides.push_back(slide); | 230 fSlides.push_back(slide); |
223 } | 231 } |
224 } | 232 } |
225 } | 233 } |
226 } | 234 } |
235 | |
236 // JPGs | |
237 for (int i = 0; i < FLAGS_jpgs.count(); i++) { | |
238 SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg"); | |
239 SkString skpName; | |
msarett
2016/06/13 14:56:26
nit: More appropriate variable name?
liyuqian
2016/06/13 16:10:40
Done.
| |
240 while (it.next(&skpName)) { | |
241 SkString path = SkOSPath::Join(FLAGS_jpgs[i], skpName.c_str()); | |
242 sk_sp<ImageSlide> slide(new ImageSlide(skpName, path)); | |
243 if (slide) { | |
244 fSlides.push_back(slide); | |
245 } | |
246 } | |
247 } | |
227 } | 248 } |
228 | 249 |
229 | 250 |
230 Viewer::~Viewer() { | 251 Viewer::~Viewer() { |
231 fWindow->detach(); | 252 fWindow->detach(); |
232 delete fWindow; | 253 delete fWindow; |
233 } | 254 } |
234 | 255 |
235 void Viewer::updateTitle() { | 256 void Viewer::updateTitle() { |
236 SkString title("Viewer: "); | 257 SkString title("Viewer: "); |
237 title.append(fSlides[fCurrentSlide]->getName()); | 258 title.append(fSlides[fCurrentSlide]->getName()); |
238 if (kSRGB_SkColorProfileType == fWindow->getDisplayParams().fProfileType) { | 259 if (kSRGB_SkColorProfileType == fWindow->getDisplayParams().fProfileType) { |
239 title.append(" sRGB"); | 260 title.append(" sRGB"); |
240 } | 261 } |
241 title.append(kBackendTypeStrings[fBackendType]); | 262 title.append(kBackendTypeStrings[fBackendType]); |
242 fWindow->setTitle(title.c_str()); | 263 fWindow->setTitle(title.c_str()); |
243 } | 264 } |
244 | 265 |
245 void Viewer::setupCurrentSlide(int previousSlide) { | 266 void Viewer::setupCurrentSlide(int previousSlide) { |
246 if (fCurrentSlide == previousSlide) { | 267 if (fCurrentSlide == previousSlide) { |
247 return; // no change; do nothing | 268 return; // no change; do nothing |
248 } | 269 } |
249 | 270 |
271 fSlides[fCurrentSlide]->load(); // prepare dimensions for image slides | |
272 | |
250 fGesture.reset(); | 273 fGesture.reset(); |
251 fDefaultMatrix.reset(); | 274 fDefaultMatrix.reset(); |
252 fDefaultMatrixInv.reset(); | 275 fDefaultMatrixInv.reset(); |
253 | 276 |
254 if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { | 277 if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { |
255 const SkRect contentRect = fWindow->getContentRect(); | 278 const SkRect contentRect = fWindow->getContentRect(); |
256 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); | 279 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
257 const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize. height()); | 280 const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize. height()); |
258 if (contentRect.width() > 0 && contentRect.height() > 0) { | 281 if (contentRect.width() > 0 && contentRect.height() > 0) { |
259 fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kSt art_ScaleToFit); | 282 fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kSt art_ScaleToFit); |
260 SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); | 283 SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); |
261 } | 284 } |
262 } | 285 } |
263 | 286 |
264 if (fWindow->supportsContentRect()) { | 287 if (fWindow->supportsContentRect()) { |
265 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); | 288 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
266 SkRect windowRect = fWindow->getContentRect(); | 289 SkRect windowRect = fWindow->getContentRect(); |
267 fDefaultMatrixInv.mapRect(&windowRect); | 290 fDefaultMatrixInv.mapRect(&windowRect); |
268 fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), | 291 fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), |
269 SkIntToScalar(slideSize.height())) , | 292 SkIntToScalar(slideSize.height())) , |
270 windowRect); | 293 windowRect); |
271 } | 294 } |
272 | 295 |
273 this->updateTitle(); | 296 this->updateTitle(); |
274 this->updateUIState(); | 297 this->updateUIState(); |
275 fSlides[fCurrentSlide]->load(); | |
276 if (previousSlide >= 0) { | 298 if (previousSlide >= 0) { |
277 fSlides[previousSlide]->unload(); | 299 fSlides[previousSlide]->unload(); |
278 } | 300 } |
279 fWindow->inval(); | 301 fWindow->inval(); |
280 } | 302 } |
281 | 303 |
282 #define MAX_ZOOM_LEVEL 8 | 304 #define MAX_ZOOM_LEVEL 8 |
283 #define MIN_ZOOM_LEVEL -8 | 305 #define MIN_ZOOM_LEVEL -8 |
284 | 306 |
285 void Viewer::changeZoomLevel(float delta) { | 307 void Viewer::changeZoomLevel(float delta) { |
(...skipping 24 matching lines...) Expand all Loading... | |
310 m.postScale(fZoomScale, fZoomScale); | 332 m.postScale(fZoomScale, fZoomScale); |
311 m.postTranslate(cx, cy); | 333 m.postTranslate(cx, cy); |
312 } | 334 } |
313 | 335 |
314 m.preConcat(fGesture.localM()); | 336 m.preConcat(fGesture.localM()); |
315 m.preConcat(fGesture.globalM()); | 337 m.preConcat(fGesture.globalM()); |
316 | 338 |
317 return m; | 339 return m; |
318 } | 340 } |
319 | 341 |
320 void Viewer::onPaint(SkCanvas* canvas) { | 342 void Viewer::drawSlide(SkCanvas* canvas, bool inSplitScreen) { |
343 SkASSERT(!inSplitScreen || fWindow->supportsContentRect()); | |
344 | |
321 int count = canvas->save(); | 345 int count = canvas->save(); |
322 | 346 |
323 if (fWindow->supportsContentRect()) { | 347 if (fWindow->supportsContentRect()) { |
324 SkRect contentRect = fWindow->getContentRect(); | 348 SkRect contentRect = fWindow->getContentRect(); |
349 contentRect.fLeft += inSplitScreen ? (contentRect.fRight - contentRect.f Left) * 0.5 : 0; | |
msarett
2016/06/13 14:56:26
What's going on here? Are we upscaling?
liyuqian
2016/06/13 16:10:40
We are translating the image half screen to the ri
msarett
2016/06/13 16:57:35
Can you add a comment here?
liyuqian
2016/06/13 19:02:29
Done.
| |
325 canvas->clipRect(contentRect); | 350 canvas->clipRect(contentRect); |
326 canvas->translate(contentRect.fLeft, contentRect.fTop); | 351 canvas->translate(contentRect.fLeft, contentRect.fTop); |
327 } | 352 } |
328 | 353 |
329 canvas->clear(SK_ColorWHITE); | 354 canvas->clear(SK_ColorWHITE); |
330 canvas->concat(fDefaultMatrix); | 355 canvas->concat(fDefaultMatrix); |
331 canvas->concat(computeMatrix()); | 356 canvas->concat(computeMatrix()); |
332 | 357 |
358 canvas->getMetaData().setBool(kImageColorXformMetaData, inSplitScreen); | |
333 fSlides[fCurrentSlide]->draw(canvas); | 359 fSlides[fCurrentSlide]->draw(canvas); |
334 canvas->restoreToCount(count); | 360 canvas->restoreToCount(count); |
361 } | |
362 | |
363 void Viewer::onPaint(SkCanvas* canvas) { | |
364 drawSlide(canvas); | |
365 if (fSplitScreen && fWindow->supportsContentRect()) { | |
366 drawSlide(canvas, true); | |
msarett
2016/06/13 14:56:26
Is it ok/intentional to call this twice?
liyuqian
2016/06/13 16:10:40
Yes, this is used to draw the same slide twice. Th
| |
367 } | |
335 | 368 |
336 if (fDisplayStats) { | 369 if (fDisplayStats) { |
337 drawStats(canvas); | 370 drawStats(canvas); |
338 } | 371 } |
339 fCommands.drawHelp(canvas); | 372 fCommands.drawHelp(canvas); |
340 } | 373 } |
341 | 374 |
342 bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) { | 375 bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) { |
343 void* castedOwner = reinterpret_cast<void*>(owner); | 376 void* castedOwner = reinterpret_cast<void*>(owner); |
344 SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); | 377 SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
454 | 487 |
455 // FPS state | 488 // FPS state |
456 Json::Value fpsState(Json::objectValue); | 489 Json::Value fpsState(Json::objectValue); |
457 fpsState[kName] = kFpsStateName; | 490 fpsState[kName] = kFpsStateName; |
458 double measurement = fMeasurements[ | 491 double measurement = fMeasurements[ |
459 (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount | 492 (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount |
460 ]; | 493 ]; |
461 fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str(); | 494 fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str(); |
462 fpsState[kOptions] = Json::Value(Json::arrayValue); | 495 fpsState[kOptions] = Json::Value(Json::arrayValue); |
463 | 496 |
497 // Split screen state | |
498 Json::Value splitScreenState(Json::objectValue); | |
499 splitScreenState[kName] = kSplitScreenStateName; | |
500 splitScreenState[kValue] = fSplitScreen ? kON : kOFF; | |
501 splitScreenState[kOptions] = Json::Value(Json::arrayValue); | |
502 splitScreenState[kOptions].append(kON); | |
503 splitScreenState[kOptions].append(kOFF); | |
504 | |
464 Json::Value state(Json::arrayValue); | 505 Json::Value state(Json::arrayValue); |
465 state.append(slideState); | 506 state.append(slideState); |
466 state.append(backendState); | 507 state.append(backendState); |
467 state.append(softkeyState); | 508 state.append(softkeyState); |
468 state.append(fpsState); | 509 state.append(fpsState); |
510 state.append(splitScreenState); | |
469 | 511 |
470 fWindow->setUIState(state); | 512 fWindow->setUIState(state); |
471 } | 513 } |
472 | 514 |
473 void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateVa lue) { | 515 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: | 516 // 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). | 517 // 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; | 518 // For example, after slide change, updateUIState is called inside setupCurr entSlide; |
477 // after backend change, updateUIState is called in this function. | 519 // after backend change, updateUIState is called in this function. |
478 if (stateName.equals(kSlideStateName)) { | 520 if (stateName.equals(kSlideStateName)) { |
(...skipping 22 matching lines...) Expand all Loading... | |
501 updateUIState(); | 543 updateUIState(); |
502 } | 544 } |
503 break; | 545 break; |
504 } | 546 } |
505 } | 547 } |
506 } else if (stateName.equals(kSoftkeyStateName)) { | 548 } else if (stateName.equals(kSoftkeyStateName)) { |
507 if (!stateValue.equals(kSoftkeyHint)) { | 549 if (!stateValue.equals(kSoftkeyHint)) { |
508 fCommands.onSoftkey(stateValue); | 550 fCommands.onSoftkey(stateValue); |
509 updateUIState(); // This is still needed to reset the value to kSoft keyHint | 551 updateUIState(); // This is still needed to reset the value to kSoft keyHint |
510 } | 552 } |
553 } else if (stateName.equals(kSplitScreenStateName)) { | |
554 bool newSplitScreen = stateValue.equals(kON); | |
555 if (newSplitScreen != fSplitScreen) { | |
556 fSplitScreen = newSplitScreen; | |
557 fWindow->inval(); | |
558 updateUIState(); | |
559 } | |
511 } else { | 560 } else { |
512 SkDebugf("Unknown stateName: %s", stateName.c_str()); | 561 SkDebugf("Unknown stateName: %s", stateName.c_str()); |
513 } | 562 } |
514 } | 563 } |
OLD | NEW |