OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SampleApp.h" | 8 #include "SampleApp.h" |
9 | 9 |
10 #include "OverView.h" | 10 #include "OverView.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 # include "gl/GrGLUtil.h" | 42 # include "gl/GrGLUtil.h" |
43 # include "GrContext.h" | 43 # include "GrContext.h" |
44 # include "SkGr.h" | 44 # include "SkGr.h" |
45 # if SK_ANGLE | 45 # if SK_ANGLE |
46 # include "gl/angle/GLTestContext_angle.h" | 46 # include "gl/angle/GLTestContext_angle.h" |
47 # endif | 47 # endif |
48 #else | 48 #else |
49 class GrContext; | 49 class GrContext; |
50 #endif | 50 #endif |
51 | 51 |
| 52 enum OutputColorSpace { |
| 53 kLegacy_OutputColorSpace, |
| 54 kSRGB_OutputColorSpace, |
| 55 kMonitor_OutputColorSpace, |
| 56 }; |
| 57 |
52 const struct { | 58 const struct { |
53 SkColorType fColorType; | 59 SkColorType fColorType; |
54 bool fSRGB; | 60 OutputColorSpace fColorSpace; |
55 const char* fName; | 61 const char* fName; |
56 } gConfig[] = { | 62 } gConfig[] = { |
57 { kN32_SkColorType, false, "L32" }, | 63 { kN32_SkColorType, kLegacy_OutputColorSpace, "L32" }, |
58 { kN32_SkColorType, true, "S32" }, | 64 { kN32_SkColorType, kSRGB_OutputColorSpace, "S32" }, |
59 { kRGBA_F16_SkColorType, true, "F16" }, | 65 { kRGBA_F16_SkColorType, kSRGB_OutputColorSpace, "F16" }, |
| 66 { kRGBA_F16_SkColorType, kMonitor_OutputColorSpace, "F16 Device" }, |
60 }; | 67 }; |
61 | 68 |
62 static const char* find_config_name(const SkImageInfo& info) { | |
63 for (const auto& config : gConfig) { | |
64 if (config.fColorType == info.colorType() && | |
65 config.fSRGB == (info.colorSpace() != nullptr)) { | |
66 return config.fName; | |
67 } | |
68 } | |
69 return "???"; | |
70 } | |
71 | |
72 // Should be 3x + 1 | 69 // Should be 3x + 1 |
73 #define kMaxFatBitsScale 28 | 70 #define kMaxFatBitsScale 28 |
74 | 71 |
75 extern SampleView* CreateSamplePictFileView(const char filename[]); | 72 extern SampleView* CreateSamplePictFileView(const char filename[]); |
76 | 73 |
77 class PictFileFactory : public SkViewFactory { | 74 class PictFileFactory : public SkViewFactory { |
78 SkString fFilename; | 75 SkString fFilename; |
79 public: | 76 public: |
80 PictFileFactory(const SkString& filename) : fFilename(filename) {} | 77 PictFileFactory(const SkString& filename) : fFilename(filename) {} |
81 SkView* operator() () const override { | 78 SkView* operator() () const override { |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 return nullptr; | 312 return nullptr; |
316 } | 313 } |
317 | 314 |
318 void publishCanvas(SampleWindow::DeviceType dType, | 315 void publishCanvas(SampleWindow::DeviceType dType, |
319 SkCanvas* renderingCanvas, SampleWindow* win) override { | 316 SkCanvas* renderingCanvas, SampleWindow* win) override { |
320 #if SK_SUPPORT_GPU | 317 #if SK_SUPPORT_GPU |
321 if (!IsGpuDeviceType(dType) || | 318 if (!IsGpuDeviceType(dType) || |
322 kRGBA_F16_SkColorType == win->info().colorType() || | 319 kRGBA_F16_SkColorType == win->info().colorType() || |
323 fActualColorBits > 24) { | 320 fActualColorBits > 24) { |
324 // We made/have an off-screen surface. Get the contents as an SkImag
e: | 321 // We made/have an off-screen surface. Get the contents as an SkImag
e: |
| 322 SkImageInfo offscreenInfo = win->info(); |
| 323 if (kMonitor_OutputColorSpace == gConfig[win->getColorConfigIndex()]
.fColorSpace) { |
| 324 // This is a big hack. We want our final output to be color "cor
rect". If we snap |
| 325 // an image in the gamut of the monitor, and then render to FBO0
(which we've tagged |
| 326 // as sRGB), then we end up doing round-trip gamut conversion, a
nd still seeing the |
| 327 // same colors on-screen as if we weren't color managed at all. |
| 328 // Instead, we readPixels into a buffer that we claim is sRGB (r
eadPixels doesn't |
| 329 // do gamut conversion), so these pixels then get thrown directl
y at the monitor, |
| 330 // giving us the expected results (the output is adapted to the
monitor's gamut). |
| 331 auto srgb = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); |
| 332 offscreenInfo = offscreenInfo.makeColorSpace(srgb); |
| 333 } |
325 SkBitmap bm; | 334 SkBitmap bm; |
326 bm.allocPixels(win->info()); | 335 bm.allocPixels(offscreenInfo); |
327 renderingCanvas->readPixels(&bm, 0, 0); | 336 renderingCanvas->readPixels(&bm, 0, 0); |
328 SkPixmap pm; | 337 SkPixmap pm; |
329 bm.peekPixels(&pm); | 338 bm.peekPixels(&pm); |
330 sk_sp<SkImage> image(SkImage::MakeTextureFromPixmap(fCurContext, pm, | 339 sk_sp<SkImage> image(SkImage::MakeTextureFromPixmap(fCurContext, pm, |
331 SkBudgeted::kNo)
); | 340 SkBudgeted::kNo)
); |
332 | 341 |
333 SkCanvas* gpuCanvas = fGpuSurface->getCanvas(); | 342 SkCanvas* gpuCanvas = fGpuSurface->getCanvas(); |
334 | 343 |
335 // With ten-bit output, we need to manually apply the gamma of the o
utput device | 344 // With ten-bit output, we need to manually apply the gamma of the o
utput device |
336 // (unless we're in non-gamma correct mode, in which case our data i
s already | 345 // (unless we're in non-gamma correct mode, in which case our data i
s already |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 if (!FLAGS_slide.isEmpty()) { | 817 if (!FLAGS_slide.isEmpty()) { |
809 fCurrIndex = findByTitle(FLAGS_slide[0]); | 818 fCurrIndex = findByTitle(FLAGS_slide[0]); |
810 if (fCurrIndex < 0) { | 819 if (fCurrIndex < 0) { |
811 fprintf(stderr, "Unknown sample \"%s\"\n", FLAGS_slide[0]); | 820 fprintf(stderr, "Unknown sample \"%s\"\n", FLAGS_slide[0]); |
812 listTitles(); | 821 listTitles(); |
813 } | 822 } |
814 } | 823 } |
815 | 824 |
816 fMSAASampleCount = FLAGS_msaa; | 825 fMSAASampleCount = FLAGS_msaa; |
817 fDeepColor = FLAGS_deepColor; | 826 fDeepColor = FLAGS_deepColor; |
| 827 fColorConfigIndex = 0; |
818 | 828 |
819 if (FLAGS_list) { | 829 if (FLAGS_list) { |
820 listTitles(); | 830 listTitles(); |
821 } | 831 } |
822 | 832 |
823 if (fCurrIndex < 0) { | 833 if (fCurrIndex < 0) { |
824 SkString title; | 834 SkString title; |
825 if (readTitleFromPrefs(&title)) { | 835 if (readTitleFromPrefs(&title)) { |
826 fCurrIndex = findByTitle(title.c_str()); | 836 fCurrIndex = findByTitle(title.c_str()); |
827 } | 837 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 fPipeSerializer.setTypefaceSerializer(new SampleTFSerializer); | 895 fPipeSerializer.setTypefaceSerializer(new SampleTFSerializer); |
886 fPipeDeserializer.setTypefaceDeserializer(new SampleTFDeserializer); | 896 fPipeDeserializer.setTypefaceDeserializer(new SampleTFDeserializer); |
887 } | 897 } |
888 | 898 |
889 int sinkID = this->getSinkID(); | 899 int sinkID = this->getSinkID(); |
890 fAppMenu = new SkOSMenu; | 900 fAppMenu = new SkOSMenu; |
891 fAppMenu->setTitle("Global Settings"); | 901 fAppMenu->setTitle("Global Settings"); |
892 int itemID; | 902 int itemID; |
893 | 903 |
894 itemID = fAppMenu->appendList("ColorType", "ColorType", sinkID, 0, | 904 itemID = fAppMenu->appendList("ColorType", "ColorType", sinkID, 0, |
895 gConfig[0].fName, gConfig[1].fName, gConfig[2]
.fName, nullptr); | 905 gConfig[0].fName, |
| 906 gConfig[1].fName, |
| 907 gConfig[2].fName, |
| 908 gConfig[3].fName, |
| 909 nullptr); |
896 fAppMenu->assignKeyEquivalentToItem(itemID, 'C'); | 910 fAppMenu->assignKeyEquivalentToItem(itemID, 'C'); |
897 | 911 |
898 itemID = fAppMenu->appendList("Device Type", "Device Type", sinkID, 0, | 912 itemID = fAppMenu->appendList("Device Type", "Device Type", sinkID, 0, |
899 "Raster", | 913 "Raster", |
900 "OpenGL", | 914 "OpenGL", |
901 #if SK_ANGLE | 915 #if SK_ANGLE |
902 "ANGLE", | 916 "ANGLE", |
903 #endif | 917 #endif |
904 nullptr); | 918 nullptr); |
905 fAppMenu->assignKeyEquivalentToItem(itemID, 'd'); | 919 fAppMenu->assignKeyEquivalentToItem(itemID, 'd'); |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 void SampleWindow::showOverview() { | 1573 void SampleWindow::showOverview() { |
1560 this->loadView(create_overview(fSamples.count(), fSamples.begin())); | 1574 this->loadView(create_overview(fSamples.count(), fSamples.begin())); |
1561 } | 1575 } |
1562 | 1576 |
1563 void SampleWindow::postAnimatingEvent() { | 1577 void SampleWindow::postAnimatingEvent() { |
1564 if (fAnimating) { | 1578 if (fAnimating) { |
1565 (new SkEvent(ANIMATING_EVENTTYPE, this->getSinkID()))->postDelay(ANIMATI
NG_DELAY); | 1579 (new SkEvent(ANIMATING_EVENTTYPE, this->getSinkID()))->postDelay(ANIMATI
NG_DELAY); |
1566 } | 1580 } |
1567 } | 1581 } |
1568 | 1582 |
| 1583 static sk_sp<SkColorSpace> getMonitorColorSpace() { |
| 1584 #if defined(SK_BUILD_FOR_MAC) |
| 1585 CGColorSpaceRef cs = CGDisplayCopyColorSpace(CGMainDisplayID()); |
| 1586 CFDataRef dataRef = CGColorSpaceCopyICCProfile(cs); |
| 1587 const uint8_t* data = CFDataGetBytePtr(dataRef); |
| 1588 size_t size = CFDataGetLength(dataRef); |
| 1589 |
| 1590 sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewICC(data, size); |
| 1591 |
| 1592 CFRelease(cs); |
| 1593 CFRelease(dataRef); |
| 1594 return colorSpace; |
| 1595 #elif defined(SK_BUILD_FOR_WIN) |
| 1596 DISPLAY_DEVICE dd = { sizeof(DISPLAY_DEVICE) }; |
| 1597 |
| 1598 // Chrome's code for this currently just gets the primary monitor's profile.
This code iterates |
| 1599 // over all attached monitors, so it's "better" in that sense. Making intell
igent use of this |
| 1600 // information (via things like MonitorFromWindow or MonitorFromRect to pick
the correct |
| 1601 // profile for a particular window or region of a window), is an exercise le
ft to the reader. |
| 1602 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { |
| 1603 if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { |
| 1604 // There are other helpful things in dd at this point: |
| 1605 // dd.DeviceString has a longer name for the adapter |
| 1606 // dd.StateFlags indicates primary display, mirroring, etc... |
| 1607 HDC dc = CreateDC(NULL, dd.DeviceName, NULL, NULL); |
| 1608 if (dc) { |
| 1609 char icmPath[MAX_PATH + 1]; |
| 1610 DWORD pathLength = MAX_PATH; |
| 1611 BOOL success = GetICMProfile(dc, &pathLength, icmPath); |
| 1612 DeleteDC(dc); |
| 1613 if (success) { |
| 1614 sk_sp<SkData> iccData = SkData::MakeFromFileName(icmPath); |
| 1615 return SkColorSpace::NewICC(iccData->data(), iccData->size()
); |
| 1616 } |
| 1617 } |
| 1618 } |
| 1619 } |
| 1620 |
| 1621 return nullptr; |
| 1622 #else |
| 1623 return nullptr; |
| 1624 #endif |
| 1625 } |
| 1626 |
1569 bool SampleWindow::onEvent(const SkEvent& evt) { | 1627 bool SampleWindow::onEvent(const SkEvent& evt) { |
1570 if (evt.isType(gUpdateWindowTitleEvtName)) { | 1628 if (evt.isType(gUpdateWindowTitleEvtName)) { |
1571 this->updateTitle(); | 1629 this->updateTitle(); |
1572 return true; | 1630 return true; |
1573 } | 1631 } |
1574 if (evt.isType(ANIMATING_EVENTTYPE)) { | 1632 if (evt.isType(ANIMATING_EVENTTYPE)) { |
1575 if (fAnimating) { | 1633 if (fAnimating) { |
1576 this->nextSample(); | 1634 this->nextSample(); |
1577 this->postAnimatingEvent(); | 1635 this->postAnimatingEvent(); |
1578 } | 1636 } |
1579 return true; | 1637 return true; |
1580 } | 1638 } |
1581 if (evt.isType("set-curr-index")) { | 1639 if (evt.isType("set-curr-index")) { |
1582 this->goToSample(evt.getFast32()); | 1640 this->goToSample(evt.getFast32()); |
1583 return true; | 1641 return true; |
1584 } | 1642 } |
1585 if (isInvalEvent(evt)) { | 1643 if (isInvalEvent(evt)) { |
1586 this->inval(nullptr); | 1644 this->inval(nullptr); |
1587 return true; | 1645 return true; |
1588 } | 1646 } |
1589 int selected = -1; | 1647 int selected = -1; |
1590 if (SkOSMenu::FindListIndex(evt, "Device Type", &selected)) { | 1648 if (SkOSMenu::FindListIndex(evt, "Device Type", &selected)) { |
1591 this->setDeviceType((DeviceType)selected); | 1649 this->setDeviceType((DeviceType)selected); |
1592 return true; | 1650 return true; |
1593 } | 1651 } |
1594 if (SkOSMenu::FindListIndex(evt, "ColorType", &selected)) { | 1652 if (SkOSMenu::FindListIndex(evt, "ColorType", &selected)) { |
1595 auto colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); | 1653 fColorConfigIndex = selected; |
| 1654 sk_sp<SkColorSpace> colorSpace = nullptr; |
| 1655 switch (gConfig[selected].fColorSpace) { |
| 1656 case kSRGB_OutputColorSpace: |
| 1657 colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); |
| 1658 break; |
| 1659 case kMonitor_OutputColorSpace: |
| 1660 colorSpace = getMonitorColorSpace(); |
| 1661 if (!colorSpace) { |
| 1662 // Fallback for platforms / machines where we can't get a mo
nitor profile |
| 1663 colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Name
d); |
| 1664 } |
| 1665 break; |
| 1666 case kLegacy_OutputColorSpace: |
| 1667 default: |
| 1668 // Do nothing |
| 1669 break; |
| 1670 } |
1596 if (kRGBA_F16_SkColorType == gConfig[selected].fColorType) { | 1671 if (kRGBA_F16_SkColorType == gConfig[selected].fColorType) { |
| 1672 SkASSERT(colorSpace); |
1597 colorSpace = colorSpace->makeLinearGamma(); | 1673 colorSpace = colorSpace->makeLinearGamma(); |
1598 } | 1674 } |
1599 this->setDeviceColorType(gConfig[selected].fColorType, | 1675 this->setDeviceColorType(gConfig[selected].fColorType, colorSpace); |
1600 gConfig[selected].fSRGB ? colorSpace : nullptr)
; | |
1601 return true; | 1676 return true; |
1602 } | 1677 } |
1603 if (SkOSMenu::FindSwitchState(evt, "Slide Show", nullptr)) { | 1678 if (SkOSMenu::FindSwitchState(evt, "Slide Show", nullptr)) { |
1604 this->toggleSlideshow(); | 1679 this->toggleSlideshow(); |
1605 return true; | 1680 return true; |
1606 } | 1681 } |
1607 if (SkOSMenu::FindTriState(evt, "AA", &fAAState) || | 1682 if (SkOSMenu::FindTriState(evt, "AA", &fAAState) || |
1608 SkOSMenu::FindTriState(evt, "LCD", &fLCDState) || | 1683 SkOSMenu::FindTriState(evt, "LCD", &fLCDState) || |
1609 SkOSMenu::FindListIndex(evt, "FilterQuality", &fFilterQualityIndex) || | 1684 SkOSMenu::FindListIndex(evt, "FilterQuality", &fFilterQualityIndex) || |
1610 SkOSMenu::FindTriState(evt, "Subpixel", &fSubpixelState) || | 1685 SkOSMenu::FindTriState(evt, "Subpixel", &fSubpixelState) || |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2114 | 2189 |
2115 #if SK_SUPPORT_GPU | 2190 #if SK_SUPPORT_GPU |
2116 if (IsGpuDeviceType(fDeviceType) && | 2191 if (IsGpuDeviceType(fDeviceType) && |
2117 fDevManager && | 2192 fDevManager && |
2118 fDevManager->numColorSamples() > 0) { | 2193 fDevManager->numColorSamples() > 0) { |
2119 title.appendf(" [MSAA: %d]", | 2194 title.appendf(" [MSAA: %d]", |
2120 fDevManager->numColorSamples()); | 2195 fDevManager->numColorSamples()); |
2121 } | 2196 } |
2122 #endif | 2197 #endif |
2123 | 2198 |
2124 title.appendf(" %s", find_config_name(this->info())); | 2199 title.appendf(" %s", gConfig[fColorConfigIndex].fName); |
2125 | 2200 |
2126 if (fDevManager && fDevManager->getColorBits() > 24) { | 2201 if (fDevManager && fDevManager->getColorBits() > 24) { |
2127 title.appendf(" %d bpc", fDevManager->getColorBits()); | 2202 title.appendf(" %d bpc", fDevManager->getColorBits()); |
2128 } | 2203 } |
2129 | 2204 |
2130 this->setTitle(title.c_str()); | 2205 this->setTitle(title.c_str()); |
2131 } | 2206 } |
2132 | 2207 |
2133 void SampleWindow::onSizeChange() { | 2208 void SampleWindow::onSizeChange() { |
2134 this->INHERITED::onSizeChange(); | 2209 this->INHERITED::onSizeChange(); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 #ifdef SK_BUILD_FOR_MAC | 2383 #ifdef SK_BUILD_FOR_MAC |
2309 setenv("ANDROID_ROOT", "/android/device/data", 0); | 2384 setenv("ANDROID_ROOT", "/android/device/data", 0); |
2310 #endif | 2385 #endif |
2311 SkGraphics::Init(); | 2386 SkGraphics::Init(); |
2312 SkEvent::Init(); | 2387 SkEvent::Init(); |
2313 } | 2388 } |
2314 | 2389 |
2315 void application_term() { | 2390 void application_term() { |
2316 SkEvent::Term(); | 2391 SkEvent::Term(); |
2317 } | 2392 } |
OLD | NEW |