make SkiaHelper::dump() available also in non-dbgutil builds
[LibreOffice.git] / vcl / inc / skia / utils.hxx
blob0a17ee81bc4dfe3f86fffe53d7860b787aafb03c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_VCL_INC_SKIA_UTILS_H
21 #define INCLUDED_VCL_INC_SKIA_UTILS_H
23 #include <vcl/skia/SkiaHelper.hxx>
25 #include <tools/gen.hxx>
26 #include <driverblocklist.hxx>
27 #include <vcl/bitmap.hxx>
28 #include <vcl/salgtype.hxx>
30 #include <premac.h>
31 #include <SkRegion.h>
32 #include <SkSurface.h>
33 #include <tools/sk_app/WindowContext.h>
34 #include <postmac.h>
36 #include <string_view>
38 namespace SkiaHelper
40 // Get the one shared GrDirectContext instance.
41 GrDirectContext* getSharedGrDirectContext();
43 void disableRenderMethod(RenderMethod method);
45 // Create SkSurface, GPU-backed if possible.
46 VCL_DLLPUBLIC sk_sp<SkSurface> createSkSurface(int width, int height,
47 SkColorType type = kN32_SkColorType,
48 SkAlphaType alpha = kPremul_SkAlphaType);
50 inline sk_sp<SkSurface> createSkSurface(const Size& size, SkColorType type = kN32_SkColorType,
51 SkAlphaType alpha = kPremul_SkAlphaType)
53 return createSkSurface(size.Width(), size.Height(), type, alpha);
56 inline sk_sp<SkSurface> createSkSurface(int width, int height, SkAlphaType alpha)
58 return createSkSurface(width, height, kN32_SkColorType, alpha);
61 inline sk_sp<SkSurface> createSkSurface(const Size& size, SkAlphaType alpha)
63 return createSkSurface(size.Width(), size.Height(), kN32_SkColorType, alpha);
66 // Create SkImage, GPU-backed if possible.
67 VCL_DLLPUBLIC sk_sp<SkImage> createSkImage(const SkBitmap& bitmap);
69 // Call surface->makeImageSnapshot() and abort on failure.
70 VCL_DLLPUBLIC sk_sp<SkImage> makeCheckedImageSnapshot(sk_sp<SkSurface> surface);
71 VCL_DLLPUBLIC sk_sp<SkImage> makeCheckedImageSnapshot(sk_sp<SkSurface> surface,
72 const SkIRect& bounds);
74 inline Size imageSize(const sk_sp<SkImage>& image) { return Size(image->width(), image->height()); }
76 // Do 'paint->setBlendMode(SkBlendMode::kDifference)' (workaround for buggy drivers).
77 void setBlendModeDifference(SkPaint* paint);
79 // Must be called in any VCL backend before any Skia functionality is used.
80 // If not set, Skia will be disabled.
81 VCL_DLLPUBLIC void
82 prepareSkia(std::unique_ptr<sk_app::WindowContext> (*createGpuWindowContext)(bool));
84 // Shared cache of images.
85 void addCachedImage(const OString& key, sk_sp<SkImage> image);
86 sk_sp<SkImage> findCachedImage(const OString& key);
87 void removeCachedImage(sk_sp<SkImage> image);
88 tools::Long maxImageCacheSize();
90 // SkSurfaceProps to be used by all Skia surfaces.
91 VCL_DLLPUBLIC const SkSurfaceProps* surfaceProps();
92 // Set pixel geometry to be used by SkSurfaceProps.
93 VCL_DLLPUBLIC void setPixelGeometry(SkPixelGeometry pixelGeometry);
95 inline bool isUnitTestRunning(const char* name = nullptr)
97 if (name == nullptr)
99 static const char* const testname = getenv("LO_TESTNAME");
100 return testname != nullptr;
102 const char* const testname = getenv("LO_TESTNAME");
103 return testname != nullptr && std::string_view(name) == testname;
106 // Normal scaling algorithms have a poor quality when downscaling a lot.
107 // https://bugs.chromium.org/p/skia/issues/detail?id=11810 suggests to use mipmaps
108 // in such a case, which is annoying to do explicitly instead of Skia deciding which
109 // algorithm would be the best, but now with Skia removing SkFilterQuality and requiring
110 // explicitly being told what algorithm to use this appears to be the best we can do.
111 // Anything scaled down at least this ratio will use linear+mipmaps.
112 constexpr int downscaleRatioThreshold = 4;
114 inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, SkMatrix matrix,
115 int scalingFactor)
117 switch (scalingType)
119 case BmpScaleFlag::BestQuality:
120 if (scalingFactor != 1)
121 matrix.postScale(scalingFactor, scalingFactor);
122 if (matrix.getScaleX() <= 1.0 / downscaleRatioThreshold
123 || matrix.getScaleY() <= 1.0 / downscaleRatioThreshold)
124 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
125 return SkSamplingOptions(SkCubicResampler::Mitchell());
126 case BmpScaleFlag::Default:
127 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
128 case BmpScaleFlag::Fast:
129 case BmpScaleFlag::NearestNeighbor:
130 return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
131 default:
132 assert(false);
133 return SkSamplingOptions();
137 inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, const Size& srcSize,
138 Size destSize, int scalingFactor)
140 switch (scalingType)
142 case BmpScaleFlag::BestQuality:
143 if (scalingFactor != 1)
144 destSize *= scalingFactor;
145 if (srcSize.Width() / destSize.Width() >= downscaleRatioThreshold
146 || srcSize.Height() / destSize.Height() >= downscaleRatioThreshold)
147 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
148 return SkSamplingOptions(SkCubicResampler::Mitchell());
149 case BmpScaleFlag::Default:
150 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
151 case BmpScaleFlag::Fast:
152 case BmpScaleFlag::NearestNeighbor:
153 return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
154 default:
155 assert(false);
156 return SkSamplingOptions();
160 inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor,
161 int srcScalingFactor = 1)
163 // If there will be scaling, make it smooth, but not in unittests, as those often
164 // require exact color values and would be confused by this.
165 if (isUnitTestRunning())
166 return SkSamplingOptions(); // none
167 Size srcSize(rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
168 Size destSize(rPosAry.mnDestWidth, rPosAry.mnDestHeight);
169 if (scalingFactor != 1)
170 destSize *= scalingFactor;
171 if (srcScalingFactor != 1)
172 srcSize *= srcScalingFactor;
173 if (srcSize != destSize)
175 if (srcSize.Width() / destSize.Width() >= downscaleRatioThreshold
176 || srcSize.Height() / destSize.Height() >= downscaleRatioThreshold)
177 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
178 return SkSamplingOptions(SkCubicResampler::Mitchell()); // best
180 return SkSamplingOptions(); // none
183 inline SkRect scaleRect(const SkRect& rect, int scaling)
185 return SkRect::MakeXYWH(rect.x() * scaling, rect.y() * scaling, rect.width() * scaling,
186 rect.height() * scaling);
189 inline SkIRect scaleRect(const SkIRect& rect, int scaling)
191 return SkIRect::MakeXYWH(rect.x() * scaling, rect.y() * scaling, rect.width() * scaling,
192 rect.height() * scaling);
195 #ifdef DBG_UTIL
196 void prefillSurface(const sk_sp<SkSurface>& surface);
197 #endif
199 VCL_DLLPUBLIC void dump(const SkBitmap& bitmap, const char* file);
200 VCL_DLLPUBLIC void dump(const sk_sp<SkImage>& image, const char* file);
201 VCL_DLLPUBLIC void dump(const sk_sp<SkSurface>& surface, const char* file);
203 VCL_DLLPUBLIC extern uint32_t vendorId;
205 inline DriverBlocklist::DeviceVendor getVendor()
207 return DriverBlocklist::GetVendorFromId(vendorId);
210 } // namespace SkiaHelper
212 // For unittests.
213 namespace SkiaTests
215 VCL_DLLPUBLIC bool matrixNeedsHighQuality(const SkMatrix& matrix);
218 template <typename charT, typename traits>
219 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
220 const SkRect& rectangle)
222 if (rectangle.isEmpty())
223 return stream << "EMPTY";
224 else
225 return stream << rectangle.width() << 'x' << rectangle.height() << "@(" << rectangle.x()
226 << ',' << rectangle.y() << ")";
229 template <typename charT, typename traits>
230 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
231 const SkIRect& rectangle)
233 if (rectangle.isEmpty())
234 return stream << "EMPTY";
235 else
236 return stream << rectangle.width() << 'x' << rectangle.height() << "@(" << rectangle.x()
237 << ',' << rectangle.y() << ")";
240 template <typename charT, typename traits>
241 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
242 const SkRegion& region)
244 if (region.isEmpty())
245 return stream << "EMPTY";
246 stream << "(";
247 SkRegion::Iterator it(region);
248 for (int i = 0; !it.done(); it.next(), ++i)
249 stream << "[" << i << "] " << it.rect();
250 stream << ")";
251 return stream;
254 template <typename charT, typename traits>
255 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
256 const SkMatrix& matrix)
258 return stream << "[" << matrix[0] << " " << matrix[1] << " " << matrix[2] << "]"
259 << "[" << matrix[3] << " " << matrix[4] << " " << matrix[5] << "]"
260 << "[" << matrix[6] << " " << matrix[7] << " " << matrix[8] << "]";
263 template <typename charT, typename traits>
264 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
265 const SkImage& image)
267 // G - on GPU
268 return stream << static_cast<const void*>(&image) << " " << Size(image.width(), image.height())
269 << "/" << (SkColorTypeBytesPerPixel(image.imageInfo().colorType()) * 8)
270 << (image.isTextureBacked() ? "G" : "");
272 template <typename charT, typename traits>
273 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream,
274 const sk_sp<SkImage>& image)
276 if (image == nullptr)
277 return stream << "(null)";
278 return stream << *image;
281 #endif // INCLUDED_VCL_INC_SKIA_UTILS_H
283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */