blob: 991e16351586674ad01272215071f043c72d8408 [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
robertphillips37bd7c32016-03-17 14:31:39 -070038 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070039
robertphillips37bd7c32016-03-17 14:31:39 -070040 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080041
42private:
43 typedef SkSpecialImage INHERITED;
44};
45
46///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080047static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080048 return static_cast<const SkSpecialImage_Base*>(image);
49}
50
robertphillips83c17fa2016-03-18 08:14:27 -070051sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy,
52 GrContext* context) {
53#if SK_SUPPORT_GPU
54 if (!context) {
55 return nullptr;
56 }
57 if (GrTexture* peek = as_SIB(this)->peekTexture()) {
58 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
59 }
60
61 SkBitmap bmp;
62 if (!this->internal_getBM(&bmp)) {
63 return nullptr;
64 }
65
66 SkAutoTUnref<GrTexture> resultTex(
67 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
68 if (!resultTex) {
69 return nullptr;
70 }
71
72 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
73
74 return SkSpecialImage::MakeFromGpu(proxy,
75 SkIRect::MakeWH(resultTex->width(), resultTex->height()),
76 this->uniqueID(),
77 resultTex, at);
78#else
79 return nullptr;
80#endif
81}
82
robertphillipse8c34972016-02-16 12:09:36 -080083void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080084 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -080085}
86
robertphillipsc5035e72016-03-17 06:58:39 -070087bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
88 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -080089}
90
91GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -080092 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -080093}
94
robertphillips4418dba2016-03-07 12:45:14 -080095bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const {
96 return as_SIB(this)->testingOnlyOnGetROPixels(result);
97}
98
robertphillips37bd7c32016-03-17 14:31:39 -070099sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
100 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800101}
102
robertphillips37bd7c32016-03-17 14:31:39 -0700103sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
104 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700105}
106
robertphillips3b087f42016-02-18 08:48:03 -0800107#if SK_SUPPORT_GPU
108#include "SkGr.h"
109#include "SkGrPixelRef.h"
110#endif
111
robertphillips37bd7c32016-03-17 14:31:39 -0700112sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
113 const SkBitmap& src) {
robertphillips3b087f42016-02-18 08:48:03 -0800114 // Need to test offset case! (see skbug.com/4967)
115 if (src.getTexture()) {
robertphillips37bd7c32016-03-17 14:31:39 -0700116 return SkSpecialImage::MakeFromGpu(proxy,
117 src.bounds(),
118 src.getGenerationID(),
119 src.getTexture());
robertphillips3b087f42016-02-18 08:48:03 -0800120 }
121
robertphillips37bd7c32016-03-17 14:31:39 -0700122 return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src);
robertphillips3b087f42016-02-18 08:48:03 -0800123}
124
125bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800126 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800127
128 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800129 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800130}
131
robertphillipsc5035e72016-03-17 06:58:39 -0700132SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -0800133 return fProxy;
134}
135
robertphillipsb6c65e92016-02-04 10:52:42 -0800136///////////////////////////////////////////////////////////////////////////////
137#include "SkImage.h"
138#if SK_SUPPORT_GPU
robertphillipsb6c65e92016-02-04 10:52:42 -0800139#include "SkGrPriv.h"
140#endif
141
142class SkSpecialImage_Image : public SkSpecialImage_Base {
143public:
robertphillips37bd7c32016-03-17 14:31:39 -0700144 SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
145 const SkIRect& subset,
146 sk_sp<SkImage> image)
robertphillips3b087f42016-02-18 08:48:03 -0800147 : INHERITED(proxy, subset, image->uniqueID())
robertphillips37bd7c32016-03-17 14:31:39 -0700148 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800149 }
150
151 ~SkSpecialImage_Image() override { }
robertphillips37bd7c32016-03-17 14:31:39 -0700152
robertphillips3b087f42016-02-18 08:48:03 -0800153 bool isOpaque() const override { return fImage->isOpaque(); }
154
155 size_t getSize() const override {
156#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800157 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
158 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800159 } else
160#endif
161 {
reed6ceeebd2016-03-09 14:26:26 -0800162 SkPixmap pm;
163 if (fImage->peekPixels(&pm)) {
164 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800165 }
166 }
167 return 0;
168 }
169
robertphillipse8c34972016-02-16 12:09:36 -0800170 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800171 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
172
robertphillips37bd7c32016-03-17 14:31:39 -0700173 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800174 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
175 }
176
robertphillipsc5035e72016-03-17 06:58:39 -0700177 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800178 return fImage->peekPixels(pixmap);
179 }
180
bsalomon84a4e5a2016-02-29 11:41:52 -0800181 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800182
robertphillipsab01ccd2016-03-08 10:45:32 -0800183 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800184#if SK_SUPPORT_GPU
185 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
186 const SkImageInfo info = GrMakeInfoFromTexture(texture,
187 fImage->width(), fImage->height(),
188 fImage->isOpaque());
189 if (!result->setInfo(info)) {
190 return false;
191 }
192
193 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
194 return true;
195 }
196#endif
197
198 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800199 }
200
robertphillips4418dba2016-03-07 12:45:14 -0800201 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800202 return fImage->asLegacyBitmap(result, SkImage::kRO_LegacyBitmapMode);
robertphillips4418dba2016-03-07 12:45:14 -0800203 }
204
robertphillips37bd7c32016-03-17 14:31:39 -0700205 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800206#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800207 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800208 if (texture) {
brianosmanc571c002016-03-17 13:01:26 -0700209 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800210 desc.fFlags = kRenderTarget_GrSurfaceFlag;
211
robertphillips37bd7c32016-03-17 14:31:39 -0700212 return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800213 }
214#endif
robertphillips37bd7c32016-03-17 14:31:39 -0700215 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800216 }
217
robertphillips37bd7c32016-03-17 14:31:39 -0700218 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
219 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700220 if (!subsetImg) {
221 return nullptr;
222 }
223
robertphillips37bd7c32016-03-17 14:31:39 -0700224 return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
225 SkIRect::MakeWH(subset.width(), subset.height()),
226 subsetImg);
robertphillipsc5035e72016-03-17 06:58:39 -0700227 }
228
robertphillipsb6c65e92016-02-04 10:52:42 -0800229private:
robertphillips37bd7c32016-03-17 14:31:39 -0700230 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800231
232 typedef SkSpecialImage_Base INHERITED;
233};
234
235#ifdef SK_DEBUG
236static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800237 if (0 == width && 0 == height) {
238 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
239 return true;
240 }
241
robertphillipsb6c65e92016-02-04 10:52:42 -0800242 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
243 rect.fRight >= 0 && rect.fRight <= width &&
244 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
245 rect.fBottom >= 0 && rect.fBottom <= height;
246}
247#endif
248
robertphillips37bd7c32016-03-17 14:31:39 -0700249sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
250 const SkIRect& subset,
251 sk_sp<SkImage> image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800252 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700253
254 return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800255}
256
257///////////////////////////////////////////////////////////////////////////////
258#include "SkBitmap.h"
259#include "SkImageInfo.h"
260#include "SkPixelRef.h"
261
262class SkSpecialImage_Raster : public SkSpecialImage_Base {
263public:
robertphillips3b087f42016-02-18 08:48:03 -0800264 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
265 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800266 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800267 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800268 // we only preemptively lock if there is no chance of triggering something expensive
269 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
270 fBitmap.lockPixels();
271 }
272 }
273
robertphillipsc5035e72016-03-17 06:58:39 -0700274 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
275 const SkIRect& subset,
276 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700277 RasterReleaseProc releaseProc,
278 ReleaseContext context)
robertphillipsc5035e72016-03-17 06:58:39 -0700279 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
280 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
281 pixmap.rowBytes(), pixmap.ctable(),
282 releaseProc, context);
283 }
284
robertphillipsb6c65e92016-02-04 10:52:42 -0800285 ~SkSpecialImage_Raster() override { }
286
robertphillips3b087f42016-02-18 08:48:03 -0800287 bool isOpaque() const override { return fBitmap.isOpaque(); }
288
289 size_t getSize() const override { return fBitmap.getSize(); }
290
robertphillipse8c34972016-02-16 12:09:36 -0800291 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800292 SkRect dst = SkRect::MakeXYWH(x, y,
293 this->subset().width(), this->subset().height());
294
295 canvas->drawBitmapRect(fBitmap, this->subset(),
296 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
297 }
298
robertphillipsc5035e72016-03-17 06:58:39 -0700299 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800300 const SkImageInfo info = fBitmap.info();
301 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
302 return false;
303 }
robertphillipsc5035e72016-03-17 06:58:39 -0700304
305 return fBitmap.peekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800306 }
307
robertphillipsab01ccd2016-03-08 10:45:32 -0800308 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800309 *result = fBitmap;
310 return true;
311 }
312
robertphillips4418dba2016-03-07 12:45:14 -0800313 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
314 *result = fBitmap;
315 return true;
316 }
317
robertphillips37bd7c32016-03-17 14:31:39 -0700318 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
319 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800320 }
321
robertphillips37bd7c32016-03-17 14:31:39 -0700322 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700323 SkBitmap subsetBM;
324
325 if (!fBitmap.extractSubset(&subsetBM, subset)) {
326 return nullptr;
327 }
328
robertphillips37bd7c32016-03-17 14:31:39 -0700329 return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
330 SkIRect::MakeWH(subset.width(), subset.height()),
331 subsetBM);
robertphillipsc5035e72016-03-17 06:58:39 -0700332 }
333
robertphillipsb6c65e92016-02-04 10:52:42 -0800334private:
335 SkBitmap fBitmap;
336
337 typedef SkSpecialImage_Base INHERITED;
338};
339
robertphillips37bd7c32016-03-17 14:31:39 -0700340sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
341 const SkIRect& subset,
342 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800343 SkASSERT(nullptr == bm.getTexture());
344 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700345
346 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800347}
348
robertphillips37bd7c32016-03-17 14:31:39 -0700349sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
350 const SkIRect& subset,
351 const SkPixmap& src,
352 RasterReleaseProc releaseProc,
353 ReleaseContext context) {
354 if (!src.addr()) {
355 return nullptr;
356 }
357
358 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context);
robertphillipsc5035e72016-03-17 06:58:39 -0700359}
360
361
robertphillipsb6c65e92016-02-04 10:52:42 -0800362#if SK_SUPPORT_GPU
363///////////////////////////////////////////////////////////////////////////////
364#include "GrTexture.h"
365
366class SkSpecialImage_Gpu : public SkSpecialImage_Base {
robertphillips3b087f42016-02-18 08:48:03 -0800367public:
368 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
369 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
370 : INHERITED(proxy, subset, uniqueID)
371 , fTexture(SkRef(tex))
372 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800373 }
374
375 ~SkSpecialImage_Gpu() override { }
376
robertphillips3b087f42016-02-18 08:48:03 -0800377 bool isOpaque() const override {
378 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
379 }
380
381 size_t getSize() const override { return fTexture->gpuMemorySize(); }
382
robertphillipse8c34972016-02-16 12:09:36 -0800383 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800384 SkRect dst = SkRect::MakeXYWH(x, y,
385 this->subset().width(), this->subset().height());
386
387 SkBitmap bm;
388
robertphillipsb6c65e92016-02-04 10:52:42 -0800389 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800390 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800391
392 canvas->drawBitmapRect(bm, this->subset(),
393 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
394 }
395
396 GrTexture* onPeekTexture() const override { return fTexture; }
397
robertphillipsab01ccd2016-03-08 10:45:32 -0800398 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800399 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
400 this->width(), this->height(),
401 this->isOpaque());
402 if (!result->setInfo(info)) {
403 return false;
404 }
405
robertphillipsc5035e72016-03-17 06:58:39 -0700406 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
407
408 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
409 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800410 return true;
411 }
412
robertphillips4418dba2016-03-07 12:45:14 -0800413 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
414
415 const SkImageInfo info = SkImageInfo::MakeN32(this->width(),
416 this->height(),
417 this->isOpaque() ? kOpaque_SkAlphaType
418 : kPremul_SkAlphaType);
419 if (!result->tryAllocPixels(info)) {
420 return false;
421 }
422
423 if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig,
424 result->getPixels(), result->rowBytes())) {
425 return false;
426 }
427
428 result->pixelRef()->setImmutable();
429 return true;
430 }
431
robertphillips37bd7c32016-03-17 14:31:39 -0700432 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
brianosmanc571c002016-03-17 13:01:26 -0700433 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800434 desc.fFlags = kRenderTarget_GrSurfaceFlag;
435
robertphillips37bd7c32016-03-17 14:31:39 -0700436 return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800437 }
438
robertphillips37bd7c32016-03-17 14:31:39 -0700439 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
440 return SkSpecialImage::MakeFromGpu(this->internal_getProxy(),
441 subset,
442 this->uniqueID(),
443 fTexture,
444 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700445 }
446
robertphillipsb6c65e92016-02-04 10:52:42 -0800447private:
448 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800449 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800450
451 typedef SkSpecialImage_Base INHERITED;
452};
453
robertphillips37bd7c32016-03-17 14:31:39 -0700454sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
455 const SkIRect& subset,
456 uint32_t uniqueID,
457 GrTexture* tex,
458 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800459 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700460 return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800461}
462
463#else
464
robertphillips37bd7c32016-03-17 14:31:39 -0700465sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
466 const SkIRect& subset,
467 uint32_t uniqueID,
468 GrTexture* tex,
469 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800470 return nullptr;
471}
472
473#endif