blob: abac9471cd1d6b2eb018bad41942160150cd0560 [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
2 * Copyright 2016 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 */
robertphillips83c17fa2016-03-18 08:14:27 -07007#include "SkSpecialImage.h"
8
9#if SK_SUPPORT_GPU
10#include "GrTexture.h"
11#include "GrTextureParams.h"
12#include "SkGr.h"
13#endif
robertphillipsb6c65e92016-02-04 10:52:42 -080014
15#include "SkCanvas.h"
bsalomon84a4e5a2016-02-29 11:41:52 -080016#include "SkImage_Base.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080017#include "SkSpecialSurface.h"
brianosman898235c2016-04-06 07:38:23 -070018#include "SkSurfacePriv.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080019
20///////////////////////////////////////////////////////////////////////////////
21class SkSpecialImage_Base : public SkSpecialImage {
22public:
brianosman898235c2016-04-06 07:38:23 -070023 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID,
24 const SkSurfaceProps* props)
25 : INHERITED(proxy, subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080026 }
robertphillipsb6c65e92016-02-04 10:52:42 -080027 virtual ~SkSpecialImage_Base() { }
28
robertphillipse8c34972016-02-16 12:09:36 -080029 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080030
robertphillipsc5035e72016-03-17 06:58:39 -070031 virtual bool onPeekPixels(SkPixmap*) const { return false; }
robertphillipsb6c65e92016-02-04 10:52:42 -080032
33 virtual GrTexture* onPeekTexture() const { return nullptr; }
34
robertphillips4418dba2016-03-07 12:45:14 -080035 virtual bool testingOnlyOnGetROPixels(SkBitmap*) const = 0;
36
robertphillips3b087f42016-02-18 08:48:03 -080037 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080038 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080039
robertphillipsb4bd11e2016-03-21 13:44:18 -070040 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
41
robertphillips37bd7c32016-03-17 14:31:39 -070042 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070043
robertphillipsb4bd11e2016-03-21 13:44:18 -070044 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
45
reede8f30622016-03-23 18:59:25 -070046 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080047
48private:
49 typedef SkSpecialImage INHERITED;
50};
51
52///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080053static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080054 return static_cast<const SkSpecialImage_Base*>(image);
55}
56
brianosman898235c2016-04-06 07:38:23 -070057SkSpecialImage::SkSpecialImage(SkImageFilter::Proxy* proxy,
58 const SkIRect& subset,
59 uint32_t uniqueID,
60 const SkSurfaceProps* props)
61 : fProps(SkSurfacePropsCopyOrDefault(props))
62 , fSubset(subset)
63 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID)
64 , fProxy(proxy) {
65}
66
robertphillips83c17fa2016-03-18 08:14:27 -070067sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy,
68 GrContext* context) {
69#if SK_SUPPORT_GPU
70 if (!context) {
71 return nullptr;
72 }
73 if (GrTexture* peek = as_SIB(this)->peekTexture()) {
74 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
75 }
76
77 SkBitmap bmp;
78 if (!this->internal_getBM(&bmp)) {
79 return nullptr;
80 }
81
robertphillips83f2e5a2016-03-24 06:31:25 -070082 if (bmp.empty()) {
brianosman898235c2016-04-06 07:38:23 -070083 return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070084 }
85
robertphillips83c17fa2016-03-18 08:14:27 -070086 SkAutoTUnref<GrTexture> resultTex(
87 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
88 if (!resultTex) {
89 return nullptr;
90 }
91
92 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
93
94 return SkSpecialImage::MakeFromGpu(proxy,
95 SkIRect::MakeWH(resultTex->width(), resultTex->height()),
96 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -070097 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -070098#else
99 return nullptr;
100#endif
101}
102
robertphillipse8c34972016-02-16 12:09:36 -0800103void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800104 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800105}
106
robertphillipsc5035e72016-03-17 06:58:39 -0700107bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
108 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800109}
110
111GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800112 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800113}
114
robertphillips4418dba2016-03-07 12:45:14 -0800115bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const {
116 return as_SIB(this)->testingOnlyOnGetROPixels(result);
117}
118
robertphillips37bd7c32016-03-17 14:31:39 -0700119sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
120 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800121}
122
robertphillipsb4bd11e2016-03-21 13:44:18 -0700123sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700124 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700125}
126
robertphillips37bd7c32016-03-17 14:31:39 -0700127sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
128 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700129}
130
robertphillipsb4bd11e2016-03-21 13:44:18 -0700131sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
132 return as_SIB(this)->onMakeTightSubset(subset);
133}
134
robertphillips3b087f42016-02-18 08:48:03 -0800135#if SK_SUPPORT_GPU
136#include "SkGr.h"
137#include "SkGrPixelRef.h"
138#endif
139
robertphillips37bd7c32016-03-17 14:31:39 -0700140sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
brianosman898235c2016-04-06 07:38:23 -0700141 const SkBitmap& src,
142 const SkSurfaceProps* props) {
robertphillips3b087f42016-02-18 08:48:03 -0800143 // Need to test offset case! (see skbug.com/4967)
144 if (src.getTexture()) {
robertphillips37bd7c32016-03-17 14:31:39 -0700145 return SkSpecialImage::MakeFromGpu(proxy,
146 src.bounds(),
147 src.getGenerationID(),
brianosman898235c2016-04-06 07:38:23 -0700148 src.getTexture(),
149 props);
robertphillips3b087f42016-02-18 08:48:03 -0800150 }
151
brianosman898235c2016-04-06 07:38:23 -0700152 return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src, props);
robertphillips3b087f42016-02-18 08:48:03 -0800153}
154
155bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800156 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800157
158 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800159 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800160}
161
robertphillipsc5035e72016-03-17 06:58:39 -0700162SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -0800163 return fProxy;
164}
165
robertphillipsb6c65e92016-02-04 10:52:42 -0800166///////////////////////////////////////////////////////////////////////////////
167#include "SkImage.h"
168#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700169#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800170#include "SkGrPriv.h"
171#endif
172
173class SkSpecialImage_Image : public SkSpecialImage_Base {
174public:
robertphillips37bd7c32016-03-17 14:31:39 -0700175 SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
176 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700177 sk_sp<SkImage> image,
178 const SkSurfaceProps* props)
179 : INHERITED(proxy, subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700180 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800181 }
182
183 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700184
robertphillips3b087f42016-02-18 08:48:03 -0800185 bool isOpaque() const override { return fImage->isOpaque(); }
186
187 size_t getSize() const override {
188#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800189 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
190 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800191 } else
192#endif
193 {
reed6ceeebd2016-03-09 14:26:26 -0800194 SkPixmap pm;
195 if (fImage->peekPixels(&pm)) {
196 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800197 }
198 }
199 return 0;
200 }
201
robertphillipse8c34972016-02-16 12:09:36 -0800202 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800203 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
204
robertphillips37bd7c32016-03-17 14:31:39 -0700205 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800206 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
207 }
208
robertphillipsc5035e72016-03-17 06:58:39 -0700209 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800210 return fImage->peekPixels(pixmap);
211 }
212
bsalomon84a4e5a2016-02-29 11:41:52 -0800213 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800214
robertphillipsab01ccd2016-03-08 10:45:32 -0800215 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800216#if SK_SUPPORT_GPU
217 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700218 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800219 fImage->width(), fImage->height(),
220 fImage->isOpaque());
221 if (!result->setInfo(info)) {
222 return false;
223 }
224
225 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
226 return true;
227 }
228#endif
229
230 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800231 }
232
robertphillips4418dba2016-03-07 12:45:14 -0800233 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800234 return fImage->asLegacyBitmap(result, SkImage::kRO_LegacyBitmapMode);
robertphillips4418dba2016-03-07 12:45:14 -0800235 }
236
robertphillips37bd7c32016-03-17 14:31:39 -0700237 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800238#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800239 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800240 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700241 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800242 desc.fFlags = kRenderTarget_GrSurfaceFlag;
243
robertphillips37bd7c32016-03-17 14:31:39 -0700244 return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800245 }
246#endif
robertphillips37bd7c32016-03-17 14:31:39 -0700247 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800248 }
249
robertphillips37bd7c32016-03-17 14:31:39 -0700250 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
251 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700252 if (!subsetImg) {
253 return nullptr;
254 }
255
robertphillips37bd7c32016-03-17 14:31:39 -0700256 return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
257 SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700258 subsetImg,
259 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700260 }
261
robertphillipsb4bd11e2016-03-21 13:44:18 -0700262 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
263 return fImage->makeSubset(subset);
264 }
265
reede8f30622016-03-23 18:59:25 -0700266 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700267#if SK_SUPPORT_GPU
268 GrTexture* texture = as_IB(fImage.get())->peekTexture();
269 if (texture) {
reede8f30622016-03-23 18:59:25 -0700270 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700271 }
272#endif
reede8f30622016-03-23 18:59:25 -0700273 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700274 }
275
robertphillipsb6c65e92016-02-04 10:52:42 -0800276private:
robertphillips37bd7c32016-03-17 14:31:39 -0700277 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800278
279 typedef SkSpecialImage_Base INHERITED;
280};
281
282#ifdef SK_DEBUG
283static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800284 if (0 == width && 0 == height) {
285 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
286 return true;
287 }
288
robertphillipsb6c65e92016-02-04 10:52:42 -0800289 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
290 rect.fRight >= 0 && rect.fRight <= width &&
291 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
292 rect.fBottom >= 0 && rect.fBottom <= height;
293}
294#endif
295
robertphillips37bd7c32016-03-17 14:31:39 -0700296sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
297 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700298 sk_sp<SkImage> image,
299 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800300 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700301
brianosman898235c2016-04-06 07:38:23 -0700302 return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800303}
304
305///////////////////////////////////////////////////////////////////////////////
306#include "SkBitmap.h"
307#include "SkImageInfo.h"
308#include "SkPixelRef.h"
309
310class SkSpecialImage_Raster : public SkSpecialImage_Base {
311public:
brianosman898235c2016-04-06 07:38:23 -0700312 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm,
313 const SkSurfaceProps* props)
314 : INHERITED(proxy, subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800315 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800316 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800317 // we only preemptively lock if there is no chance of triggering something expensive
318 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
319 fBitmap.lockPixels();
320 }
321 }
322
robertphillipsc5035e72016-03-17 06:58:39 -0700323 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
324 const SkIRect& subset,
325 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700326 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700327 ReleaseContext context,
328 const SkSurfaceProps* props)
329 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage, props) {
robertphillipsc5035e72016-03-17 06:58:39 -0700330 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
331 pixmap.rowBytes(), pixmap.ctable(),
332 releaseProc, context);
333 }
334
robertphillipsb6c65e92016-02-04 10:52:42 -0800335 ~SkSpecialImage_Raster() override { }
336
robertphillips3b087f42016-02-18 08:48:03 -0800337 bool isOpaque() const override { return fBitmap.isOpaque(); }
338
339 size_t getSize() const override { return fBitmap.getSize(); }
340
robertphillipse8c34972016-02-16 12:09:36 -0800341 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800342 SkRect dst = SkRect::MakeXYWH(x, y,
343 this->subset().width(), this->subset().height());
344
345 canvas->drawBitmapRect(fBitmap, this->subset(),
346 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
347 }
348
robertphillipsc5035e72016-03-17 06:58:39 -0700349 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800350 const SkImageInfo info = fBitmap.info();
robertphillips1579e3c2016-03-24 05:01:23 -0700351
352 if (kUnknown_SkColorType == info.colorType()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800353 return false;
354 }
robertphillipsc5035e72016-03-17 06:58:39 -0700355
robertphillips1579e3c2016-03-24 05:01:23 -0700356 if (!fBitmap.peekPixels(pixmap)) {
357 fBitmap.lockPixels();
358 }
359
robertphillipsc5035e72016-03-17 06:58:39 -0700360 return fBitmap.peekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800361 }
362
robertphillipsab01ccd2016-03-08 10:45:32 -0800363 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800364 *result = fBitmap;
365 return true;
366 }
367
robertphillips4418dba2016-03-07 12:45:14 -0800368 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
369 *result = fBitmap;
370 return true;
371 }
372
robertphillips37bd7c32016-03-17 14:31:39 -0700373 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
374 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800375 }
376
robertphillips37bd7c32016-03-17 14:31:39 -0700377 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700378 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700379
robertphillipsc5035e72016-03-17 06:58:39 -0700380 if (!fBitmap.extractSubset(&subsetBM, subset)) {
381 return nullptr;
382 }
383
robertphillips37bd7c32016-03-17 14:31:39 -0700384 return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
385 SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700386 subsetBM,
387 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700388 }
389
robertphillipsb4bd11e2016-03-21 13:44:18 -0700390 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
391 SkBitmap subsetBM;
392
393 if (!fBitmap.extractSubset(&subsetBM, subset)) {
394 return nullptr;
395 }
396
397 return SkImage::MakeFromBitmap(subsetBM);
398 }
399
reede8f30622016-03-23 18:59:25 -0700400 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
401 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700402 }
403
robertphillipsb6c65e92016-02-04 10:52:42 -0800404private:
405 SkBitmap fBitmap;
406
407 typedef SkSpecialImage_Base INHERITED;
408};
409
robertphillips37bd7c32016-03-17 14:31:39 -0700410sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
411 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700412 const SkBitmap& bm,
413 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800414 SkASSERT(nullptr == bm.getTexture());
415 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700416
brianosman898235c2016-04-06 07:38:23 -0700417 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800418}
419
robertphillips37bd7c32016-03-17 14:31:39 -0700420sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
421 const SkIRect& subset,
422 const SkPixmap& src,
423 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700424 ReleaseContext context,
425 const SkSurfaceProps* props) {
robertphillips37bd7c32016-03-17 14:31:39 -0700426 if (!src.addr()) {
427 return nullptr;
428 }
429
brianosman898235c2016-04-06 07:38:23 -0700430 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context, props);
robertphillipsc5035e72016-03-17 06:58:39 -0700431}
432
433
robertphillipsb6c65e92016-02-04 10:52:42 -0800434#if SK_SUPPORT_GPU
435///////////////////////////////////////////////////////////////////////////////
436#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700437#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800438
439class SkSpecialImage_Gpu : public SkSpecialImage_Base {
halcanary9d524f22016-03-29 09:03:52 -0700440public:
robertphillips3b087f42016-02-18 08:48:03 -0800441 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700442 uint32_t uniqueID, GrTexture* tex, SkAlphaType at,
443 const SkSurfaceProps* props)
444 : INHERITED(proxy, subset, uniqueID, props)
robertphillips3b087f42016-02-18 08:48:03 -0800445 , fTexture(SkRef(tex))
446 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800447 }
448
449 ~SkSpecialImage_Gpu() override { }
450
robertphillips3b087f42016-02-18 08:48:03 -0800451 bool isOpaque() const override {
452 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
453 }
454
455 size_t getSize() const override { return fTexture->gpuMemorySize(); }
456
robertphillipse8c34972016-02-16 12:09:36 -0800457 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800458 SkRect dst = SkRect::MakeXYWH(x, y,
459 this->subset().width(), this->subset().height());
460
461 SkBitmap bm;
462
robertphillipsb6c65e92016-02-04 10:52:42 -0800463 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800464 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800465
466 canvas->drawBitmapRect(bm, this->subset(),
467 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
468 }
469
470 GrTexture* onPeekTexture() const override { return fTexture; }
471
robertphillipsab01ccd2016-03-08 10:45:32 -0800472 bool getBitmapDeprecated(SkBitmap* result) const override {
halcanary9d524f22016-03-29 09:03:52 -0700473 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800474 this->width(), this->height(),
475 this->isOpaque());
476 if (!result->setInfo(info)) {
477 return false;
478 }
479
robertphillipsc5035e72016-03-17 06:58:39 -0700480 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
481
482 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
483 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800484 return true;
485 }
486
robertphillips4418dba2016-03-07 12:45:14 -0800487 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
488
halcanary9d524f22016-03-29 09:03:52 -0700489 const SkImageInfo info = SkImageInfo::MakeN32(this->width(),
robertphillips4418dba2016-03-07 12:45:14 -0800490 this->height(),
491 this->isOpaque() ? kOpaque_SkAlphaType
492 : kPremul_SkAlphaType);
493 if (!result->tryAllocPixels(info)) {
494 return false;
495 }
496
497 if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig,
498 result->getPixels(), result->rowBytes())) {
499 return false;
500 }
501
502 result->pixelRef()->setImmutable();
503 return true;
504 }
505
robertphillips37bd7c32016-03-17 14:31:39 -0700506 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips090b7622016-03-28 11:07:43 -0700507 if (!fTexture->getContext()) {
508 return nullptr;
509 }
510
brianosmana6359362016-03-21 06:55:37 -0700511 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800512 desc.fFlags = kRenderTarget_GrSurfaceFlag;
513
robertphillips37bd7c32016-03-17 14:31:39 -0700514 return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800515 }
516
robertphillips37bd7c32016-03-17 14:31:39 -0700517 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
518 return SkSpecialImage::MakeFromGpu(this->internal_getProxy(),
519 subset,
520 this->uniqueID(),
halcanary9d524f22016-03-29 09:03:52 -0700521 fTexture,
brianosman898235c2016-04-06 07:38:23 -0700522 &this->props(),
robertphillips37bd7c32016-03-17 14:31:39 -0700523 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700524 }
525
robertphillipsb4bd11e2016-03-21 13:44:18 -0700526 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
527 if (0 == subset.fLeft && 0 == subset.fTop &&
528 fTexture->width() == subset.width() &&
529 fTexture->height() == subset.height()) {
530 // The existing GrTexture is already tight so reuse it in the SkImage
531 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
532 kNeedNewImageUniqueID,
533 fAlphaType, fTexture, SkBudgeted::kYes);
534 }
535
536 GrContext* ctx = fTexture->getContext();
537 GrSurfaceDesc desc = fTexture->desc();
538 desc.fWidth = subset.width();
539 desc.fHeight = subset.height();
540
robertphillipsd25d06b2016-03-22 09:56:58 -0700541 SkAutoTUnref<GrTexture> subTx(ctx->textureProvider()->createTexture(desc,
542 SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700543 if (!subTx) {
544 return nullptr;
545 }
546 ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
547 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
548 fAlphaType, subTx, SkBudgeted::kYes);
549 }
550
reede8f30622016-03-23 18:59:25 -0700551 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
552 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700553 }
554
robertphillipsb6c65e92016-02-04 10:52:42 -0800555private:
556 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800557 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800558
559 typedef SkSpecialImage_Base INHERITED;
560};
561
robertphillips37bd7c32016-03-17 14:31:39 -0700562sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
halcanary9d524f22016-03-29 09:03:52 -0700563 const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700564 uint32_t uniqueID,
565 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700566 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700567 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800568 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosman898235c2016-04-06 07:38:23 -0700569 return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800570}
571
572#else
573
robertphillips37bd7c32016-03-17 14:31:39 -0700574sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
575 const SkIRect& subset,
576 uint32_t uniqueID,
577 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700578 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700579 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800580 return nullptr;
581}
582
583#endif