blob: dfbde75dc7eea30813401f1e45ecde11893d48a8 [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
70 SkAutoTUnref<GrTexture> resultTex(
71 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
72 if (!resultTex) {
73 return nullptr;
74 }
75
76 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
77
78 return SkSpecialImage::MakeFromGpu(proxy,
79 SkIRect::MakeWH(resultTex->width(), resultTex->height()),
80 this->uniqueID(),
81 resultTex, at);
82#else
83 return nullptr;
84#endif
85}
86
robertphillipse8c34972016-02-16 12:09:36 -080087void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080088 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -080089}
90
robertphillipsc5035e72016-03-17 06:58:39 -070091bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
92 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -080093}
94
95GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -080096 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -080097}
98
robertphillips4418dba2016-03-07 12:45:14 -080099bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const {
100 return as_SIB(this)->testingOnlyOnGetROPixels(result);
101}
102
robertphillips37bd7c32016-03-17 14:31:39 -0700103sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
104 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800105}
106
robertphillipsb4bd11e2016-03-21 13:44:18 -0700107sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700108 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700109}
110
robertphillips37bd7c32016-03-17 14:31:39 -0700111sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
112 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700113}
114
robertphillipsb4bd11e2016-03-21 13:44:18 -0700115sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
116 return as_SIB(this)->onMakeTightSubset(subset);
117}
118
robertphillips3b087f42016-02-18 08:48:03 -0800119#if SK_SUPPORT_GPU
120#include "SkGr.h"
121#include "SkGrPixelRef.h"
122#endif
123
robertphillips37bd7c32016-03-17 14:31:39 -0700124sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
125 const SkBitmap& src) {
robertphillips3b087f42016-02-18 08:48:03 -0800126 // Need to test offset case! (see skbug.com/4967)
127 if (src.getTexture()) {
robertphillips37bd7c32016-03-17 14:31:39 -0700128 return SkSpecialImage::MakeFromGpu(proxy,
129 src.bounds(),
130 src.getGenerationID(),
131 src.getTexture());
robertphillips3b087f42016-02-18 08:48:03 -0800132 }
133
robertphillips37bd7c32016-03-17 14:31:39 -0700134 return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src);
robertphillips3b087f42016-02-18 08:48:03 -0800135}
136
137bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800138 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800139
140 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800141 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800142}
143
robertphillipsc5035e72016-03-17 06:58:39 -0700144SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -0800145 return fProxy;
146}
147
robertphillipsb6c65e92016-02-04 10:52:42 -0800148///////////////////////////////////////////////////////////////////////////////
149#include "SkImage.h"
150#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700151#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800152#include "SkGrPriv.h"
153#endif
154
155class SkSpecialImage_Image : public SkSpecialImage_Base {
156public:
robertphillips37bd7c32016-03-17 14:31:39 -0700157 SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
158 const SkIRect& subset,
159 sk_sp<SkImage> image)
robertphillips3b087f42016-02-18 08:48:03 -0800160 : INHERITED(proxy, subset, image->uniqueID())
robertphillips37bd7c32016-03-17 14:31:39 -0700161 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800162 }
163
164 ~SkSpecialImage_Image() override { }
robertphillips37bd7c32016-03-17 14:31:39 -0700165
robertphillips3b087f42016-02-18 08:48:03 -0800166 bool isOpaque() const override { return fImage->isOpaque(); }
167
168 size_t getSize() const override {
169#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800170 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
171 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800172 } else
173#endif
174 {
reed6ceeebd2016-03-09 14:26:26 -0800175 SkPixmap pm;
176 if (fImage->peekPixels(&pm)) {
177 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800178 }
179 }
180 return 0;
181 }
182
robertphillipse8c34972016-02-16 12:09:36 -0800183 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800184 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
185
robertphillips37bd7c32016-03-17 14:31:39 -0700186 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800187 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
188 }
189
robertphillipsc5035e72016-03-17 06:58:39 -0700190 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800191 return fImage->peekPixels(pixmap);
192 }
193
bsalomon84a4e5a2016-02-29 11:41:52 -0800194 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800195
robertphillipsab01ccd2016-03-08 10:45:32 -0800196 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800197#if SK_SUPPORT_GPU
198 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
199 const SkImageInfo info = GrMakeInfoFromTexture(texture,
200 fImage->width(), fImage->height(),
201 fImage->isOpaque());
202 if (!result->setInfo(info)) {
203 return false;
204 }
205
206 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
207 return true;
208 }
209#endif
210
211 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800212 }
213
robertphillips4418dba2016-03-07 12:45:14 -0800214 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800215 return fImage->asLegacyBitmap(result, SkImage::kRO_LegacyBitmapMode);
robertphillips4418dba2016-03-07 12:45:14 -0800216 }
217
robertphillips37bd7c32016-03-17 14:31:39 -0700218 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800219#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800220 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800221 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700222 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800223 desc.fFlags = kRenderTarget_GrSurfaceFlag;
224
robertphillips37bd7c32016-03-17 14:31:39 -0700225 return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800226 }
227#endif
robertphillips37bd7c32016-03-17 14:31:39 -0700228 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800229 }
230
robertphillips37bd7c32016-03-17 14:31:39 -0700231 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
232 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700233 if (!subsetImg) {
234 return nullptr;
235 }
236
robertphillips37bd7c32016-03-17 14:31:39 -0700237 return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
238 SkIRect::MakeWH(subset.width(), subset.height()),
239 subsetImg);
robertphillipsc5035e72016-03-17 06:58:39 -0700240 }
241
robertphillipsb4bd11e2016-03-21 13:44:18 -0700242 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
243 return fImage->makeSubset(subset);
244 }
245
reede8f30622016-03-23 18:59:25 -0700246 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700247#if SK_SUPPORT_GPU
248 GrTexture* texture = as_IB(fImage.get())->peekTexture();
249 if (texture) {
reede8f30622016-03-23 18:59:25 -0700250 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700251 }
252#endif
reede8f30622016-03-23 18:59:25 -0700253 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700254 }
255
robertphillipsb6c65e92016-02-04 10:52:42 -0800256private:
robertphillips37bd7c32016-03-17 14:31:39 -0700257 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800258
259 typedef SkSpecialImage_Base INHERITED;
260};
261
262#ifdef SK_DEBUG
263static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800264 if (0 == width && 0 == height) {
265 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
266 return true;
267 }
268
robertphillipsb6c65e92016-02-04 10:52:42 -0800269 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
270 rect.fRight >= 0 && rect.fRight <= width &&
271 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
272 rect.fBottom >= 0 && rect.fBottom <= height;
273}
274#endif
275
robertphillips37bd7c32016-03-17 14:31:39 -0700276sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
277 const SkIRect& subset,
278 sk_sp<SkImage> image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800279 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700280
281 return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800282}
283
284///////////////////////////////////////////////////////////////////////////////
285#include "SkBitmap.h"
286#include "SkImageInfo.h"
287#include "SkPixelRef.h"
288
289class SkSpecialImage_Raster : public SkSpecialImage_Base {
290public:
robertphillips3b087f42016-02-18 08:48:03 -0800291 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
292 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800293 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800294 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800295 // we only preemptively lock if there is no chance of triggering something expensive
296 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
297 fBitmap.lockPixels();
298 }
299 }
300
robertphillipsc5035e72016-03-17 06:58:39 -0700301 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
302 const SkIRect& subset,
303 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700304 RasterReleaseProc releaseProc,
305 ReleaseContext context)
robertphillipsc5035e72016-03-17 06:58:39 -0700306 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
307 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
308 pixmap.rowBytes(), pixmap.ctable(),
309 releaseProc, context);
310 }
311
robertphillipsb6c65e92016-02-04 10:52:42 -0800312 ~SkSpecialImage_Raster() override { }
313
robertphillips3b087f42016-02-18 08:48:03 -0800314 bool isOpaque() const override { return fBitmap.isOpaque(); }
315
316 size_t getSize() const override { return fBitmap.getSize(); }
317
robertphillipse8c34972016-02-16 12:09:36 -0800318 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800319 SkRect dst = SkRect::MakeXYWH(x, y,
320 this->subset().width(), this->subset().height());
321
322 canvas->drawBitmapRect(fBitmap, this->subset(),
323 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
324 }
325
robertphillipsc5035e72016-03-17 06:58:39 -0700326 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800327 const SkImageInfo info = fBitmap.info();
328 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
329 return false;
330 }
robertphillipsc5035e72016-03-17 06:58:39 -0700331
332 return fBitmap.peekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800333 }
334
robertphillipsab01ccd2016-03-08 10:45:32 -0800335 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800336 *result = fBitmap;
337 return true;
338 }
339
robertphillips4418dba2016-03-07 12:45:14 -0800340 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
341 *result = fBitmap;
342 return true;
343 }
344
robertphillips37bd7c32016-03-17 14:31:39 -0700345 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
346 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800347 }
348
robertphillips37bd7c32016-03-17 14:31:39 -0700349 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700350 SkBitmap subsetBM;
351
352 if (!fBitmap.extractSubset(&subsetBM, subset)) {
353 return nullptr;
354 }
355
robertphillips37bd7c32016-03-17 14:31:39 -0700356 return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
357 SkIRect::MakeWH(subset.width(), subset.height()),
358 subsetBM);
robertphillipsc5035e72016-03-17 06:58:39 -0700359 }
360
robertphillipsb4bd11e2016-03-21 13:44:18 -0700361 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
362 SkBitmap subsetBM;
363
364 if (!fBitmap.extractSubset(&subsetBM, subset)) {
365 return nullptr;
366 }
367
368 return SkImage::MakeFromBitmap(subsetBM);
369 }
370
reede8f30622016-03-23 18:59:25 -0700371 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
372 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700373 }
374
robertphillipsb6c65e92016-02-04 10:52:42 -0800375private:
376 SkBitmap fBitmap;
377
378 typedef SkSpecialImage_Base INHERITED;
379};
380
robertphillips37bd7c32016-03-17 14:31:39 -0700381sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
382 const SkIRect& subset,
383 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800384 SkASSERT(nullptr == bm.getTexture());
385 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700386
387 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800388}
389
robertphillips37bd7c32016-03-17 14:31:39 -0700390sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
391 const SkIRect& subset,
392 const SkPixmap& src,
393 RasterReleaseProc releaseProc,
394 ReleaseContext context) {
395 if (!src.addr()) {
396 return nullptr;
397 }
398
399 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context);
robertphillipsc5035e72016-03-17 06:58:39 -0700400}
401
402
robertphillipsb6c65e92016-02-04 10:52:42 -0800403#if SK_SUPPORT_GPU
404///////////////////////////////////////////////////////////////////////////////
405#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700406#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800407
408class SkSpecialImage_Gpu : public SkSpecialImage_Base {
robertphillips3b087f42016-02-18 08:48:03 -0800409public:
410 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
411 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
412 : INHERITED(proxy, subset, uniqueID)
413 , fTexture(SkRef(tex))
414 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800415 }
416
417 ~SkSpecialImage_Gpu() override { }
418
robertphillips3b087f42016-02-18 08:48:03 -0800419 bool isOpaque() const override {
420 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
421 }
422
423 size_t getSize() const override { return fTexture->gpuMemorySize(); }
424
robertphillipse8c34972016-02-16 12:09:36 -0800425 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800426 SkRect dst = SkRect::MakeXYWH(x, y,
427 this->subset().width(), this->subset().height());
428
429 SkBitmap bm;
430
robertphillipsb6c65e92016-02-04 10:52:42 -0800431 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800432 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800433
434 canvas->drawBitmapRect(bm, this->subset(),
435 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
436 }
437
438 GrTexture* onPeekTexture() const override { return fTexture; }
439
robertphillipsab01ccd2016-03-08 10:45:32 -0800440 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800441 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
442 this->width(), this->height(),
443 this->isOpaque());
444 if (!result->setInfo(info)) {
445 return false;
446 }
447
robertphillipsc5035e72016-03-17 06:58:39 -0700448 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
449
450 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
451 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800452 return true;
453 }
454
robertphillips4418dba2016-03-07 12:45:14 -0800455 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
456
457 const SkImageInfo info = SkImageInfo::MakeN32(this->width(),
458 this->height(),
459 this->isOpaque() ? kOpaque_SkAlphaType
460 : kPremul_SkAlphaType);
461 if (!result->tryAllocPixels(info)) {
462 return false;
463 }
464
465 if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig,
466 result->getPixels(), result->rowBytes())) {
467 return false;
468 }
469
470 result->pixelRef()->setImmutable();
471 return true;
472 }
473
robertphillips37bd7c32016-03-17 14:31:39 -0700474 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
brianosmana6359362016-03-21 06:55:37 -0700475 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800476 desc.fFlags = kRenderTarget_GrSurfaceFlag;
477
robertphillips37bd7c32016-03-17 14:31:39 -0700478 return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800479 }
480
robertphillips37bd7c32016-03-17 14:31:39 -0700481 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
482 return SkSpecialImage::MakeFromGpu(this->internal_getProxy(),
483 subset,
484 this->uniqueID(),
485 fTexture,
486 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700487 }
488
robertphillipsb4bd11e2016-03-21 13:44:18 -0700489 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
490 if (0 == subset.fLeft && 0 == subset.fTop &&
491 fTexture->width() == subset.width() &&
492 fTexture->height() == subset.height()) {
493 // The existing GrTexture is already tight so reuse it in the SkImage
494 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
495 kNeedNewImageUniqueID,
496 fAlphaType, fTexture, SkBudgeted::kYes);
497 }
498
499 GrContext* ctx = fTexture->getContext();
500 GrSurfaceDesc desc = fTexture->desc();
501 desc.fWidth = subset.width();
502 desc.fHeight = subset.height();
503
robertphillipsd25d06b2016-03-22 09:56:58 -0700504 SkAutoTUnref<GrTexture> subTx(ctx->textureProvider()->createTexture(desc,
505 SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700506 if (!subTx) {
507 return nullptr;
508 }
509 ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
510 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
511 fAlphaType, subTx, SkBudgeted::kYes);
512 }
513
reede8f30622016-03-23 18:59:25 -0700514 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
515 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700516 }
517
robertphillipsb6c65e92016-02-04 10:52:42 -0800518private:
519 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800520 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800521
522 typedef SkSpecialImage_Base INHERITED;
523};
524
robertphillips37bd7c32016-03-17 14:31:39 -0700525sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
526 const SkIRect& subset,
527 uint32_t uniqueID,
528 GrTexture* tex,
529 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800530 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700531 return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800532}
533
534#else
535
robertphillips37bd7c32016-03-17 14:31:39 -0700536sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
537 const SkIRect& subset,
538 uint32_t uniqueID,
539 GrTexture* tex,
540 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800541 return nullptr;
542}
543
544#endif