blob: 681c224ad841ec1d64cada400780f97dffcc43d2 [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"
18
19///////////////////////////////////////////////////////////////////////////////
20class SkSpecialImage_Base : public SkSpecialImage {
21public:
robertphillips3b087f42016-02-18 08:48:03 -080022 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
23 : INHERITED(proxy, subset, uniqueID) {
24 }
robertphillipsb6c65e92016-02-04 10:52:42 -080025 virtual ~SkSpecialImage_Base() { }
26
robertphillipse8c34972016-02-16 12:09:36 -080027 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080028
robertphillipsc5035e72016-03-17 06:58:39 -070029 virtual bool onPeekPixels(SkPixmap*) const { return false; }
robertphillipsb6c65e92016-02-04 10:52:42 -080030
31 virtual GrTexture* onPeekTexture() const { return nullptr; }
32
robertphillips4418dba2016-03-07 12:45:14 -080033 virtual bool testingOnlyOnGetROPixels(SkBitmap*) const = 0;
34
robertphillips3b087f42016-02-18 08:48:03 -080035 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080036 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080037
robertphillipsb4bd11e2016-03-21 13:44:18 -070038 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
39
robertphillips37bd7c32016-03-17 14:31:39 -070040 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070041
robertphillipsb4bd11e2016-03-21 13:44:18 -070042 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
43
reede8f30622016-03-23 18:59:25 -070044 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080045
46private:
47 typedef SkSpecialImage INHERITED;
48};
49
50///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080051static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080052 return static_cast<const SkSpecialImage_Base*>(image);
53}
54
robertphillips83c17fa2016-03-18 08:14:27 -070055sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy,
56 GrContext* context) {
57#if SK_SUPPORT_GPU
58 if (!context) {
59 return nullptr;
60 }
61 if (GrTexture* peek = as_SIB(this)->peekTexture()) {
62 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
63 }
64
65 SkBitmap bmp;
66 if (!this->internal_getBM(&bmp)) {
67 return nullptr;
68 }
69
robertphillips83f2e5a2016-03-24 06:31:25 -070070 if (bmp.empty()) {
71 return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp);
72 }
73
robertphillips83c17fa2016-03-18 08:14:27 -070074 SkAutoTUnref<GrTexture> resultTex(
75 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
76 if (!resultTex) {
77 return nullptr;
78 }
79
80 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
81
82 return SkSpecialImage::MakeFromGpu(proxy,
83 SkIRect::MakeWH(resultTex->width(), resultTex->height()),
84 this->uniqueID(),
85 resultTex, at);
86#else
87 return nullptr;
88#endif
89}
90
robertphillipse8c34972016-02-16 12:09:36 -080091void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080092 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -080093}
94
robertphillipsc5035e72016-03-17 06:58:39 -070095bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
96 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -080097}
98
99GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800100 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800101}
102
robertphillips4418dba2016-03-07 12:45:14 -0800103bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const {
104 return as_SIB(this)->testingOnlyOnGetROPixels(result);
105}
106
robertphillips37bd7c32016-03-17 14:31:39 -0700107sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
108 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800109}
110
robertphillipsb4bd11e2016-03-21 13:44:18 -0700111sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700112 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700113}
114
robertphillips37bd7c32016-03-17 14:31:39 -0700115sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
116 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700117}
118
robertphillipsb4bd11e2016-03-21 13:44:18 -0700119sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
120 return as_SIB(this)->onMakeTightSubset(subset);
121}
122
robertphillips3b087f42016-02-18 08:48:03 -0800123#if SK_SUPPORT_GPU
124#include "SkGr.h"
125#include "SkGrPixelRef.h"
126#endif
127
robertphillips37bd7c32016-03-17 14:31:39 -0700128sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
129 const SkBitmap& src) {
robertphillips3b087f42016-02-18 08:48:03 -0800130 // Need to test offset case! (see skbug.com/4967)
131 if (src.getTexture()) {
robertphillips37bd7c32016-03-17 14:31:39 -0700132 return SkSpecialImage::MakeFromGpu(proxy,
133 src.bounds(),
134 src.getGenerationID(),
135 src.getTexture());
robertphillips3b087f42016-02-18 08:48:03 -0800136 }
137
robertphillips37bd7c32016-03-17 14:31:39 -0700138 return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src);
robertphillips3b087f42016-02-18 08:48:03 -0800139}
140
141bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800142 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800143
144 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800145 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800146}
147
robertphillipsc5035e72016-03-17 06:58:39 -0700148SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -0800149 return fProxy;
150}
151
robertphillipsb6c65e92016-02-04 10:52:42 -0800152///////////////////////////////////////////////////////////////////////////////
153#include "SkImage.h"
154#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700155#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800156#include "SkGrPriv.h"
157#endif
158
159class SkSpecialImage_Image : public SkSpecialImage_Base {
160public:
robertphillips37bd7c32016-03-17 14:31:39 -0700161 SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
162 const SkIRect& subset,
163 sk_sp<SkImage> image)
robertphillips3b087f42016-02-18 08:48:03 -0800164 : INHERITED(proxy, subset, image->uniqueID())
robertphillips37bd7c32016-03-17 14:31:39 -0700165 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800166 }
167
168 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700169
robertphillips3b087f42016-02-18 08:48:03 -0800170 bool isOpaque() const override { return fImage->isOpaque(); }
171
172 size_t getSize() const override {
173#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800174 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
175 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800176 } else
177#endif
178 {
reed6ceeebd2016-03-09 14:26:26 -0800179 SkPixmap pm;
180 if (fImage->peekPixels(&pm)) {
181 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800182 }
183 }
184 return 0;
185 }
186
robertphillipse8c34972016-02-16 12:09:36 -0800187 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800188 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
189
robertphillips37bd7c32016-03-17 14:31:39 -0700190 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800191 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
192 }
193
robertphillipsc5035e72016-03-17 06:58:39 -0700194 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800195 return fImage->peekPixels(pixmap);
196 }
197
bsalomon84a4e5a2016-02-29 11:41:52 -0800198 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800199
robertphillipsab01ccd2016-03-08 10:45:32 -0800200 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800201#if SK_SUPPORT_GPU
202 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700203 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800204 fImage->width(), fImage->height(),
205 fImage->isOpaque());
206 if (!result->setInfo(info)) {
207 return false;
208 }
209
210 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
211 return true;
212 }
213#endif
214
215 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800216 }
217
robertphillips4418dba2016-03-07 12:45:14 -0800218 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800219 return fImage->asLegacyBitmap(result, SkImage::kRO_LegacyBitmapMode);
robertphillips4418dba2016-03-07 12:45:14 -0800220 }
221
robertphillips37bd7c32016-03-17 14:31:39 -0700222 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800223#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800224 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800225 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700226 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800227 desc.fFlags = kRenderTarget_GrSurfaceFlag;
228
robertphillips37bd7c32016-03-17 14:31:39 -0700229 return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800230 }
231#endif
robertphillips37bd7c32016-03-17 14:31:39 -0700232 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800233 }
234
robertphillips37bd7c32016-03-17 14:31:39 -0700235 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
236 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700237 if (!subsetImg) {
238 return nullptr;
239 }
240
robertphillips37bd7c32016-03-17 14:31:39 -0700241 return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
242 SkIRect::MakeWH(subset.width(), subset.height()),
243 subsetImg);
robertphillipsc5035e72016-03-17 06:58:39 -0700244 }
245
robertphillipsb4bd11e2016-03-21 13:44:18 -0700246 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
247 return fImage->makeSubset(subset);
248 }
249
reede8f30622016-03-23 18:59:25 -0700250 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700251#if SK_SUPPORT_GPU
252 GrTexture* texture = as_IB(fImage.get())->peekTexture();
253 if (texture) {
reede8f30622016-03-23 18:59:25 -0700254 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700255 }
256#endif
reede8f30622016-03-23 18:59:25 -0700257 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700258 }
259
robertphillipsb6c65e92016-02-04 10:52:42 -0800260private:
robertphillips37bd7c32016-03-17 14:31:39 -0700261 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800262
263 typedef SkSpecialImage_Base INHERITED;
264};
265
266#ifdef SK_DEBUG
267static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800268 if (0 == width && 0 == height) {
269 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
270 return true;
271 }
272
robertphillipsb6c65e92016-02-04 10:52:42 -0800273 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
274 rect.fRight >= 0 && rect.fRight <= width &&
275 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
276 rect.fBottom >= 0 && rect.fBottom <= height;
277}
278#endif
279
robertphillips37bd7c32016-03-17 14:31:39 -0700280sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
281 const SkIRect& subset,
282 sk_sp<SkImage> image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800283 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700284
285 return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800286}
287
288///////////////////////////////////////////////////////////////////////////////
289#include "SkBitmap.h"
290#include "SkImageInfo.h"
291#include "SkPixelRef.h"
292
293class SkSpecialImage_Raster : public SkSpecialImage_Base {
294public:
robertphillips3b087f42016-02-18 08:48:03 -0800295 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
296 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800297 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800298 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800299 // we only preemptively lock if there is no chance of triggering something expensive
300 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
301 fBitmap.lockPixels();
302 }
303 }
304
robertphillipsc5035e72016-03-17 06:58:39 -0700305 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
306 const SkIRect& subset,
307 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700308 RasterReleaseProc releaseProc,
309 ReleaseContext context)
robertphillipsc5035e72016-03-17 06:58:39 -0700310 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
311 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
312 pixmap.rowBytes(), pixmap.ctable(),
313 releaseProc, context);
314 }
315
robertphillipsb6c65e92016-02-04 10:52:42 -0800316 ~SkSpecialImage_Raster() override { }
317
robertphillips3b087f42016-02-18 08:48:03 -0800318 bool isOpaque() const override { return fBitmap.isOpaque(); }
319
320 size_t getSize() const override { return fBitmap.getSize(); }
321
robertphillipse8c34972016-02-16 12:09:36 -0800322 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800323 SkRect dst = SkRect::MakeXYWH(x, y,
324 this->subset().width(), this->subset().height());
325
326 canvas->drawBitmapRect(fBitmap, this->subset(),
327 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
328 }
329
robertphillipsc5035e72016-03-17 06:58:39 -0700330 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800331 const SkImageInfo info = fBitmap.info();
robertphillips1579e3c2016-03-24 05:01:23 -0700332
333 if (kUnknown_SkColorType == info.colorType()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800334 return false;
335 }
robertphillipsc5035e72016-03-17 06:58:39 -0700336
robertphillips1579e3c2016-03-24 05:01:23 -0700337 if (!fBitmap.peekPixels(pixmap)) {
338 fBitmap.lockPixels();
339 }
340
robertphillipsc5035e72016-03-17 06:58:39 -0700341 return fBitmap.peekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800342 }
343
robertphillipsab01ccd2016-03-08 10:45:32 -0800344 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800345 *result = fBitmap;
346 return true;
347 }
348
robertphillips4418dba2016-03-07 12:45:14 -0800349 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
350 *result = fBitmap;
351 return true;
352 }
353
robertphillips37bd7c32016-03-17 14:31:39 -0700354 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
355 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800356 }
357
robertphillips37bd7c32016-03-17 14:31:39 -0700358 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700359 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700360
robertphillipsc5035e72016-03-17 06:58:39 -0700361 if (!fBitmap.extractSubset(&subsetBM, subset)) {
362 return nullptr;
363 }
364
robertphillips37bd7c32016-03-17 14:31:39 -0700365 return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
366 SkIRect::MakeWH(subset.width(), subset.height()),
367 subsetBM);
robertphillipsc5035e72016-03-17 06:58:39 -0700368 }
369
robertphillipsb4bd11e2016-03-21 13:44:18 -0700370 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
371 SkBitmap subsetBM;
372
373 if (!fBitmap.extractSubset(&subsetBM, subset)) {
374 return nullptr;
375 }
376
377 return SkImage::MakeFromBitmap(subsetBM);
378 }
379
reede8f30622016-03-23 18:59:25 -0700380 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
381 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700382 }
383
robertphillipsb6c65e92016-02-04 10:52:42 -0800384private:
385 SkBitmap fBitmap;
386
387 typedef SkSpecialImage_Base INHERITED;
388};
389
robertphillips37bd7c32016-03-17 14:31:39 -0700390sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
391 const SkIRect& subset,
392 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800393 SkASSERT(nullptr == bm.getTexture());
394 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700395
396 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800397}
398
robertphillips37bd7c32016-03-17 14:31:39 -0700399sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
400 const SkIRect& subset,
401 const SkPixmap& src,
402 RasterReleaseProc releaseProc,
403 ReleaseContext context) {
404 if (!src.addr()) {
405 return nullptr;
406 }
407
408 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context);
robertphillipsc5035e72016-03-17 06:58:39 -0700409}
410
411
robertphillipsb6c65e92016-02-04 10:52:42 -0800412#if SK_SUPPORT_GPU
413///////////////////////////////////////////////////////////////////////////////
414#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700415#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800416
417class SkSpecialImage_Gpu : public SkSpecialImage_Base {
halcanary9d524f22016-03-29 09:03:52 -0700418public:
robertphillips3b087f42016-02-18 08:48:03 -0800419 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
420 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
421 : INHERITED(proxy, subset, uniqueID)
422 , fTexture(SkRef(tex))
423 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800424 }
425
426 ~SkSpecialImage_Gpu() override { }
427
robertphillips3b087f42016-02-18 08:48:03 -0800428 bool isOpaque() const override {
429 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
430 }
431
432 size_t getSize() const override { return fTexture->gpuMemorySize(); }
433
robertphillipse8c34972016-02-16 12:09:36 -0800434 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800435 SkRect dst = SkRect::MakeXYWH(x, y,
436 this->subset().width(), this->subset().height());
437
438 SkBitmap bm;
439
robertphillipsb6c65e92016-02-04 10:52:42 -0800440 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800441 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800442
443 canvas->drawBitmapRect(bm, this->subset(),
444 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
445 }
446
447 GrTexture* onPeekTexture() const override { return fTexture; }
448
robertphillipsab01ccd2016-03-08 10:45:32 -0800449 bool getBitmapDeprecated(SkBitmap* result) const override {
halcanary9d524f22016-03-29 09:03:52 -0700450 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800451 this->width(), this->height(),
452 this->isOpaque());
453 if (!result->setInfo(info)) {
454 return false;
455 }
456
robertphillipsc5035e72016-03-17 06:58:39 -0700457 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
458
459 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
460 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800461 return true;
462 }
463
robertphillips4418dba2016-03-07 12:45:14 -0800464 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
465
halcanary9d524f22016-03-29 09:03:52 -0700466 const SkImageInfo info = SkImageInfo::MakeN32(this->width(),
robertphillips4418dba2016-03-07 12:45:14 -0800467 this->height(),
468 this->isOpaque() ? kOpaque_SkAlphaType
469 : kPremul_SkAlphaType);
470 if (!result->tryAllocPixels(info)) {
471 return false;
472 }
473
474 if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig,
475 result->getPixels(), result->rowBytes())) {
476 return false;
477 }
478
479 result->pixelRef()->setImmutable();
480 return true;
481 }
482
robertphillips37bd7c32016-03-17 14:31:39 -0700483 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips090b7622016-03-28 11:07:43 -0700484 if (!fTexture->getContext()) {
485 return nullptr;
486 }
487
brianosmana6359362016-03-21 06:55:37 -0700488 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800489 desc.fFlags = kRenderTarget_GrSurfaceFlag;
490
robertphillips37bd7c32016-03-17 14:31:39 -0700491 return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800492 }
493
robertphillips37bd7c32016-03-17 14:31:39 -0700494 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
495 return SkSpecialImage::MakeFromGpu(this->internal_getProxy(),
496 subset,
497 this->uniqueID(),
halcanary9d524f22016-03-29 09:03:52 -0700498 fTexture,
robertphillips37bd7c32016-03-17 14:31:39 -0700499 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700500 }
501
robertphillipsb4bd11e2016-03-21 13:44:18 -0700502 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
503 if (0 == subset.fLeft && 0 == subset.fTop &&
504 fTexture->width() == subset.width() &&
505 fTexture->height() == subset.height()) {
506 // The existing GrTexture is already tight so reuse it in the SkImage
507 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
508 kNeedNewImageUniqueID,
509 fAlphaType, fTexture, SkBudgeted::kYes);
510 }
511
512 GrContext* ctx = fTexture->getContext();
513 GrSurfaceDesc desc = fTexture->desc();
514 desc.fWidth = subset.width();
515 desc.fHeight = subset.height();
516
robertphillipsd25d06b2016-03-22 09:56:58 -0700517 SkAutoTUnref<GrTexture> subTx(ctx->textureProvider()->createTexture(desc,
518 SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700519 if (!subTx) {
520 return nullptr;
521 }
522 ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
523 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
524 fAlphaType, subTx, SkBudgeted::kYes);
525 }
526
reede8f30622016-03-23 18:59:25 -0700527 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
528 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700529 }
530
robertphillipsb6c65e92016-02-04 10:52:42 -0800531private:
532 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800533 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800534
535 typedef SkSpecialImage_Base INHERITED;
536};
537
robertphillips37bd7c32016-03-17 14:31:39 -0700538sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
halcanary9d524f22016-03-29 09:03:52 -0700539 const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700540 uint32_t uniqueID,
541 GrTexture* tex,
542 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800543 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700544 return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800545}
546
547#else
548
robertphillips37bd7c32016-03-17 14:31:39 -0700549sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
550 const SkIRect& subset,
551 uint32_t uniqueID,
552 GrTexture* tex,
553 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800554 return nullptr;
555}
556
557#endif