/src/skia/src/image/SkSurface_Base.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2023 Google LLC |
3 | | * |
4 | | * Use of this source code is governed by a BSD-style license that can be |
5 | | * found in the LICENSE file. |
6 | | */ |
7 | | |
8 | | #include "src/image/SkSurface_Base.h" |
9 | | |
10 | | #include "include/core/SkBitmap.h" |
11 | | #include "include/core/SkCanvas.h" |
12 | | #include "include/core/SkCapabilities.h" |
13 | | #include "include/core/SkColorSpace.h" // IWYU pragma: keep |
14 | | #include "include/core/SkImage.h" |
15 | | #include "include/core/SkImageInfo.h" |
16 | | #include "include/core/SkPixmap.h" |
17 | | #include "include/core/SkRect.h" |
18 | | #include "include/core/SkRefCnt.h" |
19 | | #include "include/core/SkScalar.h" |
20 | | #include "include/core/SkSize.h" |
21 | | #include "src/image/SkRescaleAndReadPixels.h" |
22 | | |
23 | | #include <atomic> |
24 | | #include <cstdint> |
25 | | #include <memory> |
26 | | |
27 | | class GrRecordingContext; |
28 | | class SkPaint; |
29 | | class SkSurfaceProps; |
30 | | namespace skgpu { namespace graphite { class Recorder; } } |
31 | | |
32 | | SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) |
33 | 48.7k | : SkSurface(width, height, props) {} |
34 | | |
35 | | SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) |
36 | 36 | : SkSurface(info, props) {} |
37 | | |
38 | 48.8k | SkSurface_Base::~SkSurface_Base() { |
39 | | // in case the canvas outsurvives us, we null the callback |
40 | 48.8k | if (fCachedCanvas) { |
41 | 47.8k | fCachedCanvas->setSurfaceBase(nullptr); |
42 | 47.8k | } |
43 | 48.8k | } |
44 | | |
45 | 0 | GrRecordingContext* SkSurface_Base::onGetRecordingContext() const { return nullptr; } |
46 | | |
47 | 0 | skgpu::graphite::Recorder* SkSurface_Base::onGetRecorder() const { return nullptr; } |
48 | | |
49 | | void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, |
50 | 0 | const SkSamplingOptions& sampling, const SkPaint* paint) { |
51 | 0 | auto image = this->makeImageSnapshot(); |
52 | 0 | if (image) { |
53 | 0 | canvas->drawImage(image.get(), x, y, sampling, paint); |
54 | 0 | } |
55 | 0 | } |
56 | | |
57 | | void SkSurface_Base::onAsyncRescaleAndReadPixels(const SkImageInfo& info, |
58 | | SkIRect origSrcRect, |
59 | | SkSurface::RescaleGamma rescaleGamma, |
60 | | RescaleMode rescaleMode, |
61 | | SkSurface::ReadPixelsCallback callback, |
62 | 0 | SkSurface::ReadPixelsContext context) { |
63 | 0 | SkBitmap src; |
64 | 0 | SkPixmap peek; |
65 | 0 | SkIRect srcRect; |
66 | 0 | if (this->peekPixels(&peek)) { |
67 | 0 | src.installPixels(peek); |
68 | 0 | srcRect = origSrcRect; |
69 | 0 | } else { |
70 | 0 | src.setInfo(this->imageInfo().makeDimensions(origSrcRect.size())); |
71 | 0 | src.allocPixels(); |
72 | 0 | if (!this->readPixels(src, origSrcRect.x(), origSrcRect.y())) { |
73 | 0 | callback(context, nullptr); |
74 | 0 | return; |
75 | 0 | } |
76 | 0 | srcRect = SkIRect::MakeSize(src.dimensions()); |
77 | 0 | } |
78 | 0 | return SkRescaleAndReadPixels(src, info, srcRect, rescaleGamma, rescaleMode, callback, |
79 | 0 | context); |
80 | 0 | } |
81 | | |
82 | | void SkSurface_Base::onAsyncRescaleAndReadPixelsYUV420( |
83 | | SkYUVColorSpace yuvColorSpace, bool readAlpha, sk_sp<SkColorSpace> dstColorSpace, |
84 | | SkIRect srcRect, SkISize dstSize, RescaleGamma rescaleGamma, RescaleMode, |
85 | 0 | ReadPixelsCallback callback, ReadPixelsContext context) { |
86 | | // TODO: Call non-YUV asyncRescaleAndReadPixels and then make our callback convert to YUV and |
87 | | // call client's callback. |
88 | 0 | callback(context, nullptr); |
89 | 0 | } |
90 | | |
91 | 56.1k | bool SkSurface_Base::outstandingImageSnapshot() const { |
92 | 56.1k | return fCachedImage && !fCachedImage->unique(); |
93 | 56.1k | } |
94 | | |
95 | 242k | bool SkSurface_Base::aboutToDraw(ContentChangeMode mode) { |
96 | 242k | this->dirtyGenerationID(); |
97 | | |
98 | 242k | SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); |
99 | | |
100 | 242k | if (fCachedImage) { |
101 | | // the surface may need to fork its backend, if its sharing it with |
102 | | // the cached image. Note: we only call if there is an outstanding owner |
103 | | // on the image (besides us). |
104 | 0 | bool unique = fCachedImage->unique(); |
105 | 0 | if (!unique) { |
106 | 0 | if (!this->onCopyOnWrite(mode)) { |
107 | 0 | return false; |
108 | 0 | } |
109 | 0 | } |
110 | | |
111 | | // regardless of copy-on-write, we must drop our cached image now, so |
112 | | // that the next request will get our new contents. |
113 | 0 | fCachedImage.reset(); |
114 | |
|
115 | 0 | if (unique) { |
116 | | // Our content isn't held by any image now, so we can consider that content mutable. |
117 | | // Raster surfaces need to be told it's safe to consider its pixels mutable again. |
118 | | // We make this call after the ->unref() so the subclass can assert there are no images. |
119 | 0 | this->onRestoreBackingMutability(); |
120 | 0 | } |
121 | 242k | } else if (kDiscard_ContentChangeMode == mode) { |
122 | 0 | this->onDiscard(); |
123 | 0 | } |
124 | 242k | return true; |
125 | 242k | } |
126 | | |
127 | 0 | uint32_t SkSurface_Base::newGenerationID() { |
128 | 0 | SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); |
129 | 0 | static std::atomic<uint32_t> nextID{1}; |
130 | 0 | return nextID.fetch_add(1, std::memory_order_relaxed); |
131 | 0 | } Unexecuted instantiation: SkSurface_Base::newGenerationID() Unexecuted instantiation: SkSurface_Base::newGenerationID() |
132 | | |
133 | 0 | sk_sp<const SkCapabilities> SkSurface_Base::onCapabilities() { |
134 | 0 | return SkCapabilities::RasterBackend(); |
135 | 0 | } |