Coverage Report

Created: 2024-05-20 07:14

/src/skia/src/image/SkImage_Raster.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2012 Google Inc.
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
#include "src/image/SkImage_Raster.h"
8
9
#include "include/core/SkBitmap.h"
10
#include "include/core/SkColorSpace.h"
11
#include "include/core/SkData.h"
12
#include "include/core/SkImage.h"
13
#include "include/core/SkImageInfo.h"
14
#include "include/core/SkPixelRef.h"
15
#include "include/core/SkPixmap.h"
16
#include "include/core/SkPoint.h"
17
#include "include/core/SkRect.h"
18
#include "include/core/SkRefCnt.h"
19
#include "include/core/SkSize.h"
20
#include "include/core/SkTypes.h"
21
#include "src/base/SkRectMemcpy.h"
22
#include "src/core/SkImageInfoPriv.h"
23
#include "src/core/SkImagePriv.h"
24
#include "src/image/SkImage_Base.h"
25
26
#include <cstddef>
27
#include <cstdint>
28
#include <utility>
29
30
class GrDirectContext;
31
32
// fixes https://bug.skia.org/5096
33
110k
static bool is_not_subset(const SkBitmap& bm) {
34
110k
    SkASSERT(bm.pixelRef());
35
110k
    SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
36
110k
    SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
37
110k
    return dim == bm.dimensions();
38
110k
}
39
40
61.0k
static void release_data(void* addr, void* context) {
41
61.0k
    SkData* data = static_cast<SkData*>(context);
42
61.0k
    data->unref();
43
61.0k
}
44
45
SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
46
                               uint32_t id)
47
61.0k
        : SkImage_Base(info, id) {
48
61.0k
    void* addr = const_cast<void*>(data->data());
49
50
61.0k
    fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
51
61.0k
    fBitmap.setImmutable();
52
61.0k
}
53
54
SkImage_Raster::SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable)
55
        : SkImage_Base(bm.info(),
56
                    is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
57
110k
        , fBitmap(bm) {
58
110k
    SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
59
110k
}
60
61
171k
SkImage_Raster::~SkImage_Raster() {}
62
63
bool SkImage_Raster::onReadPixels(GrDirectContext*,
64
                                  const SkImageInfo& dstInfo,
65
                                  void* dstPixels,
66
                                  size_t dstRowBytes,
67
                                  int srcX,
68
                                  int srcY,
69
24
                                  CachingHint) const {
70
24
    SkBitmap shallowCopy(fBitmap);
71
24
    return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
72
24
}
73
74
2.72k
bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
75
2.72k
    return fBitmap.peekPixels(pm);
76
2.72k
}
77
78
156k
bool SkImage_Raster::getROPixels(GrDirectContext*, SkBitmap* dst, CachingHint) const {
79
156k
    *dst = fBitmap;
80
156k
    return true;
81
156k
}
82
83
10.0k
static SkBitmap copy_bitmap_subset(const SkBitmap& orig, const SkIRect& subset) {
84
10.0k
    SkImageInfo info = orig.info().makeDimensions(subset.size());
85
10.0k
    SkBitmap bitmap;
86
10.0k
    if (!bitmap.tryAllocPixels(info)) {
87
0
        return {};
88
0
    }
89
90
10.0k
    void* dst = bitmap.getPixels();
91
10.0k
    void* src = orig.getAddr(subset.x(), subset.y());
92
10.0k
    if (!dst || !src) {
93
0
        SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
94
0
        return {};
95
0
    }
96
97
10.0k
    SkRectMemcpy(dst, bitmap.rowBytes(), src, orig.rowBytes(), bitmap.rowBytes(),
98
10.0k
                 subset.height());
99
100
10.0k
    bitmap.setImmutable();
101
10.0k
    return bitmap;
102
10.0k
}
SkImage_Raster.cpp:copy_bitmap_subset(SkBitmap const&, SkIRect const&)
Line
Count
Source
83
10.0k
static SkBitmap copy_bitmap_subset(const SkBitmap& orig, const SkIRect& subset) {
84
10.0k
    SkImageInfo info = orig.info().makeDimensions(subset.size());
85
10.0k
    SkBitmap bitmap;
86
10.0k
    if (!bitmap.tryAllocPixels(info)) {
87
0
        return {};
88
0
    }
89
90
10.0k
    void* dst = bitmap.getPixels();
91
10.0k
    void* src = orig.getAddr(subset.x(), subset.y());
92
10.0k
    if (!dst || !src) {
93
0
        SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
94
0
        return {};
95
0
    }
96
97
10.0k
    SkRectMemcpy(dst, bitmap.rowBytes(), src, orig.rowBytes(), bitmap.rowBytes(),
98
10.0k
                 subset.height());
99
100
10.0k
    bitmap.setImmutable();
101
10.0k
    return bitmap;
102
10.0k
}
Unexecuted instantiation: SkImage_Raster.cpp:copy_bitmap_subset(SkBitmap const&, SkIRect const&)
103
104
10.0k
sk_sp<SkImage> SkImage_Raster::onMakeSubset(GrDirectContext*, const SkIRect& subset) const {
105
10.0k
    SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
106
10.0k
    if (copy.isNull()) {
107
0
        return nullptr;
108
10.0k
    } else {
109
10.0k
        return copy.asImage();
110
10.0k
    }
111
10.0k
}
112
113
0
static sk_sp<SkMipmap> copy_mipmaps(const SkBitmap& src, SkMipmap* srcMips) {
114
0
    if (!srcMips) {
115
0
        return nullptr;
116
0
    }
117
118
0
    sk_sp<SkMipmap> dst;
119
0
    dst.reset(SkMipmap::Build(src.pixmap(),
120
0
                              /* factoryProc= */ nullptr,
121
0
                              /* computeContents= */ false));
122
0
    if (!dst) {
123
0
        return nullptr;
124
0
    }
125
0
    for (int i = 0; i < dst->countLevels(); ++i) {
126
0
        SkMipmap::Level srcLevel, dstLevel;
127
0
        srcMips->getLevel(i, &srcLevel);
128
0
        dst->getLevel(i, &dstLevel);
129
0
        srcLevel.fPixmap.readPixels(dstLevel.fPixmap);
130
0
    }
131
132
0
    return dst;
133
0
}
134
135
sk_sp<SkImage> SkImage_Raster::onMakeSubset(skgpu::graphite::Recorder*,
136
                                            const SkIRect& subset,
137
0
                                            RequiredProperties requiredProperties) const {
138
0
    sk_sp<SkImage> img;
139
140
0
    if (requiredProperties.fMipmapped) {
141
0
        bool fullCopy = subset == SkIRect::MakeSize(fBitmap.dimensions());
142
143
0
        sk_sp<SkMipmap> mips = fullCopy ? copy_mipmaps(fBitmap, fBitmap.fMips.get()) : nullptr;
144
145
        // SkImage::withMipmaps will always make a copy for us so we can temporarily share
146
        // the pixel ref with fBitmap
147
0
        SkBitmap tmpSubset;
148
0
        if (!fBitmap.extractSubset(&tmpSubset, subset)) {
149
0
            return nullptr;
150
0
        }
151
152
0
        sk_sp<SkImage> tmp(new SkImage_Raster(tmpSubset, /* bitmapMayBeMutable= */ true));
153
154
        // withMipmaps will auto generate the mipmaps if a nullptr is passed in
155
0
        SkASSERT(!mips || mips->validForRootLevel(tmp->imageInfo()));
156
0
        img = tmp->withMipmaps(std::move(mips));
157
0
    } else {
158
0
        SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
159
0
        if (!copy.isNull()) {
160
0
            img = copy.asImage();
161
0
        }
162
0
    }
163
164
0
    return img;
165
0
}
Unexecuted instantiation: SkImage_Raster::onMakeSubset(skgpu::graphite::Recorder*, SkIRect const&, SkImage::RequiredProperties) const
Unexecuted instantiation: SkImage_Raster::onMakeSubset(skgpu::graphite::Recorder*, SkIRect const&, SkImage::RequiredProperties) const
166
167
///////////////////////////////////////////////////////////////////////////////
168
169
sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
170
153k
                                               uint32_t idForCopy) {
171
153k
    if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
172
42.3k
        SkPixmap pmap;
173
42.3k
        if (bm.peekPixels(&pmap)) {
174
42.3k
            return MakeRasterCopyPriv(pmap, idForCopy);
175
42.3k
        } else {
176
0
            return sk_sp<SkImage>();
177
0
        }
178
42.3k
    }
179
110k
    return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
180
153k
}
181
182
153k
sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
183
153k
    if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
184
38
        return nullptr;
185
38
    }
186
187
153k
    return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
188
153k
}
189
190
0
const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
191
0
    return ((const SkImage_Raster*)image)->getPixelRef();
192
0
}
193
194
0
bool SkImage_Raster::onAsLegacyBitmap(GrDirectContext*, SkBitmap* bitmap) const {
195
    // When we're a snapshot from a surface, our bitmap may not be marked immutable
196
    // even though logically always we are, but in that case we can't physically share our
197
    // pixelref since the caller might call setImmutable() themselves
198
    // (thus changing our state).
199
0
    if (fBitmap.isImmutable()) {
200
0
        SkIPoint origin = fBitmap.pixelRefOrigin();
201
0
        bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
202
0
        bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
203
0
        return true;
204
0
    }
205
0
    return this->SkImage_Base::onAsLegacyBitmap(nullptr, bitmap);
206
0
}
207
208
///////////////////////////////////////////////////////////////////////////////
209
210
sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType targetCT,
211
                                                            sk_sp<SkColorSpace> targetCS,
212
0
                                                            GrDirectContext*) const {
213
0
    SkPixmap src;
214
0
    SkAssertResult(fBitmap.peekPixels(&src));
215
216
0
    SkBitmap dst;
217
0
    if (!dst.tryAllocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS))) {
218
0
        return nullptr;
219
0
    }
220
221
0
    SkAssertResult(dst.writePixels(src));
222
0
    dst.setImmutable();
223
0
    return dst.asImage();
224
0
}
Unexecuted instantiation: SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>, GrDirectContext*) const
Unexecuted instantiation: SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>, GrDirectContext*) const
225
226
0
sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
227
    // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
228
    // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
229
    // gen ID from the bitmap, which gets it from the pixelRef.
230
0
    SkPixmap pixmap = fBitmap.pixmap();
231
0
    pixmap.setColorSpace(std::move(newCS));
232
0
    return SkImages::RasterFromPixmapCopy(pixmap);
233
0
}