blob: b17d5d4147d998d85016a1f2d50c6bbb63ac91e7 [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 */
7
8#include "SkCanvas.h"
bsalomon84a4e5a2016-02-29 11:41:52 -08009#include "SkImage_Base.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080010#include "SkSpecialImage.h"
11#include "SkSpecialSurface.h"
12
13///////////////////////////////////////////////////////////////////////////////
14class SkSpecialImage_Base : public SkSpecialImage {
15public:
robertphillips3b087f42016-02-18 08:48:03 -080016 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
17 : INHERITED(proxy, subset, uniqueID) {
18 }
robertphillipsb6c65e92016-02-04 10:52:42 -080019 virtual ~SkSpecialImage_Base() { }
20
robertphillipse8c34972016-02-16 12:09:36 -080021 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080022
robertphillipsc5035e72016-03-17 06:58:39 -070023 virtual bool onPeekPixels(SkPixmap*) const { return false; }
robertphillipsb6c65e92016-02-04 10:52:42 -080024
25 virtual GrTexture* onPeekTexture() const { return nullptr; }
26
robertphillips4418dba2016-03-07 12:45:14 -080027 virtual bool testingOnlyOnGetROPixels(SkBitmap*) const = 0;
28
robertphillips3b087f42016-02-18 08:48:03 -080029 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080030 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080031
robertphillipsc5035e72016-03-17 06:58:39 -070032 virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const = 0;
33
34 virtual SkSpecialImage* onExtractSubset(const SkIRect& subset) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080035
36private:
37 typedef SkSpecialImage INHERITED;
38};
39
40///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080041static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080042 return static_cast<const SkSpecialImage_Base*>(image);
43}
44
robertphillipse8c34972016-02-16 12:09:36 -080045void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080046 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -080047}
48
robertphillipsc5035e72016-03-17 06:58:39 -070049bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
50 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -080051}
52
53GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -080054 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -080055}
56
robertphillips4418dba2016-03-07 12:45:14 -080057bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const {
58 return as_SIB(this)->testingOnlyOnGetROPixels(result);
59}
60
robertphillipsb6c65e92016-02-04 10:52:42 -080061SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080062 return as_SIB(this)->onNewSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -080063}
64
robertphillipsc5035e72016-03-17 06:58:39 -070065SkSpecialImage* SkSpecialImage::extractSubset(const SkIRect& subset) const {
66 return as_SIB(this)->onExtractSubset(subset);
67}
68
robertphillips3b087f42016-02-18 08:48:03 -080069#if SK_SUPPORT_GPU
70#include "SkGr.h"
71#include "SkGrPixelRef.h"
72#endif
73
74SkSpecialImage* SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
75 const SkBitmap& src) {
76 // Need to test offset case! (see skbug.com/4967)
77 if (src.getTexture()) {
78 return SkSpecialImage::NewFromGpu(proxy,
79 src.bounds(),
80 src.getGenerationID(),
81 src.getTexture());
82 }
83
84 return SkSpecialImage::NewFromRaster(proxy, src.bounds(), src);
85}
86
87bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -080088 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -080089
90 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -080091 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -080092}
93
robertphillipsc5035e72016-03-17 06:58:39 -070094SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -080095 return fProxy;
96}
97
robertphillipsb6c65e92016-02-04 10:52:42 -080098///////////////////////////////////////////////////////////////////////////////
99#include "SkImage.h"
100#if SK_SUPPORT_GPU
robertphillipsb6c65e92016-02-04 10:52:42 -0800101#include "SkGrPriv.h"
102#endif
103
104class SkSpecialImage_Image : public SkSpecialImage_Base {
105public:
robertphillips3b087f42016-02-18 08:48:03 -0800106 SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image)
107 : INHERITED(proxy, subset, image->uniqueID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800108 , fImage(SkRef(image)) {
109 }
110
111 ~SkSpecialImage_Image() override { }
112
robertphillips3b087f42016-02-18 08:48:03 -0800113 bool isOpaque() const override { return fImage->isOpaque(); }
114
115 size_t getSize() const override {
116#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800117 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
118 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800119 } else
120#endif
121 {
reed6ceeebd2016-03-09 14:26:26 -0800122 SkPixmap pm;
123 if (fImage->peekPixels(&pm)) {
124 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800125 }
126 }
127 return 0;
128 }
129
robertphillipse8c34972016-02-16 12:09:36 -0800130 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800131 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
132
133 canvas->drawImageRect(fImage, this->subset(),
134 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
135 }
136
robertphillipsc5035e72016-03-17 06:58:39 -0700137 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800138 return fImage->peekPixels(pixmap);
139 }
140
bsalomon84a4e5a2016-02-29 11:41:52 -0800141 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800142
robertphillipsab01ccd2016-03-08 10:45:32 -0800143 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800144#if SK_SUPPORT_GPU
145 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
146 const SkImageInfo info = GrMakeInfoFromTexture(texture,
147 fImage->width(), fImage->height(),
148 fImage->isOpaque());
149 if (!result->setInfo(info)) {
150 return false;
151 }
152
153 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
154 return true;
155 }
156#endif
157
158 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800159 }
160
robertphillips4418dba2016-03-07 12:45:14 -0800161 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800162 return fImage->asLegacyBitmap(result, SkImage::kRO_LegacyBitmapMode);
robertphillips4418dba2016-03-07 12:45:14 -0800163 }
164
robertphillipsb6c65e92016-02-04 10:52:42 -0800165 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
166#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800167 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800168 if (texture) {
169 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
170 desc.fFlags = kRenderTarget_GrSurfaceFlag;
171
robertphillips3b087f42016-02-18 08:48:03 -0800172 return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800173 }
174#endif
robertphillips3b087f42016-02-18 08:48:03 -0800175 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800176 }
177
robertphillipsc5035e72016-03-17 06:58:39 -0700178 SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
179 SkAutoTUnref<SkImage> subsetImg(fImage->newSubset(subset));
180 if (!subsetImg) {
181 return nullptr;
182 }
183
184 return SkSpecialImage::NewFromImage(this->internal_getProxy(),
185 SkIRect::MakeWH(subset.width(), subset.height()),
186 subsetImg);
187 }
188
robertphillipsb6c65e92016-02-04 10:52:42 -0800189private:
190 SkAutoTUnref<const SkImage> fImage;
191
192 typedef SkSpecialImage_Base INHERITED;
193};
194
195#ifdef SK_DEBUG
196static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800197 if (0 == width && 0 == height) {
198 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
199 return true;
200 }
201
robertphillipsb6c65e92016-02-04 10:52:42 -0800202 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
203 rect.fRight >= 0 && rect.fRight <= width &&
204 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
205 rect.fBottom >= 0 && rect.fBottom <= height;
206}
207#endif
208
robertphillips6ac97b72016-03-09 05:17:10 -0800209SkSpecialImage* SkSpecialImage::NewFromImage(SkImageFilter::Proxy* proxy,
210 const SkIRect& subset,
211 const SkImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800212 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips6ac97b72016-03-09 05:17:10 -0800213 return new SkSpecialImage_Image(proxy, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800214}
215
216///////////////////////////////////////////////////////////////////////////////
217#include "SkBitmap.h"
218#include "SkImageInfo.h"
219#include "SkPixelRef.h"
220
221class SkSpecialImage_Raster : public SkSpecialImage_Base {
222public:
robertphillips3b087f42016-02-18 08:48:03 -0800223 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
224 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800225 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800226 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800227 // we only preemptively lock if there is no chance of triggering something expensive
228 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
229 fBitmap.lockPixels();
230 }
231 }
232
robertphillipsc5035e72016-03-17 06:58:39 -0700233 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
234 const SkIRect& subset,
235 const SkPixmap& pixmap,
236 void (*releaseProc)(void* addr, void* context),
237 void* context)
238 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
239 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
240 pixmap.rowBytes(), pixmap.ctable(),
241 releaseProc, context);
242 }
243
robertphillipsb6c65e92016-02-04 10:52:42 -0800244 ~SkSpecialImage_Raster() override { }
245
robertphillips3b087f42016-02-18 08:48:03 -0800246 bool isOpaque() const override { return fBitmap.isOpaque(); }
247
248 size_t getSize() const override { return fBitmap.getSize(); }
249
robertphillipse8c34972016-02-16 12:09:36 -0800250 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800251 SkRect dst = SkRect::MakeXYWH(x, y,
252 this->subset().width(), this->subset().height());
253
254 canvas->drawBitmapRect(fBitmap, this->subset(),
255 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
256 }
257
robertphillipsc5035e72016-03-17 06:58:39 -0700258 bool onPeekPixels(SkPixmap* pixmap) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800259 const SkImageInfo info = fBitmap.info();
260 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
261 return false;
262 }
robertphillipsc5035e72016-03-17 06:58:39 -0700263
264 return fBitmap.peekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -0800265 }
266
robertphillipsab01ccd2016-03-08 10:45:32 -0800267 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800268 *result = fBitmap;
269 return true;
270 }
271
robertphillips4418dba2016-03-07 12:45:14 -0800272 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
273 *result = fBitmap;
274 return true;
275 }
276
robertphillipsb6c65e92016-02-04 10:52:42 -0800277 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800278 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800279 }
280
robertphillipsc5035e72016-03-17 06:58:39 -0700281 SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
282 SkBitmap subsetBM;
283
284 if (!fBitmap.extractSubset(&subsetBM, subset)) {
285 return nullptr;
286 }
287
288 return SkSpecialImage::NewFromRaster(this->internal_getProxy(),
289 SkIRect::MakeWH(subset.width(), subset.height()),
290 subsetBM);
291 }
292
robertphillipsb6c65e92016-02-04 10:52:42 -0800293private:
294 SkBitmap fBitmap;
295
296 typedef SkSpecialImage_Base INHERITED;
297};
298
robertphillips3b087f42016-02-18 08:48:03 -0800299SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy,
300 const SkIRect& subset,
301 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800302 SkASSERT(nullptr == bm.getTexture());
303 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips3b087f42016-02-18 08:48:03 -0800304 return new SkSpecialImage_Raster(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800305}
306
robertphillipsc5035e72016-03-17 06:58:39 -0700307SkSpecialImage* SkSpecialImage::NewFromPixmap(SkImageFilter::Proxy* proxy,
308 const SkIRect& subset,
309 const SkPixmap& src,
310 void (*releaseProc)(void* addr, void* context),
311 void* context) {
312 return new SkSpecialImage_Raster(proxy, subset, src, releaseProc, context);
313}
314
315
robertphillipsb6c65e92016-02-04 10:52:42 -0800316#if SK_SUPPORT_GPU
317///////////////////////////////////////////////////////////////////////////////
318#include "GrTexture.h"
319
320class SkSpecialImage_Gpu : public SkSpecialImage_Base {
robertphillips3b087f42016-02-18 08:48:03 -0800321public:
322 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
323 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
324 : INHERITED(proxy, subset, uniqueID)
325 , fTexture(SkRef(tex))
326 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800327 }
328
329 ~SkSpecialImage_Gpu() override { }
330
robertphillips3b087f42016-02-18 08:48:03 -0800331 bool isOpaque() const override {
332 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
333 }
334
335 size_t getSize() const override { return fTexture->gpuMemorySize(); }
336
robertphillipse8c34972016-02-16 12:09:36 -0800337 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800338 SkRect dst = SkRect::MakeXYWH(x, y,
339 this->subset().width(), this->subset().height());
340
341 SkBitmap bm;
342
robertphillipsb6c65e92016-02-04 10:52:42 -0800343 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800344 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800345
346 canvas->drawBitmapRect(bm, this->subset(),
347 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
348 }
349
350 GrTexture* onPeekTexture() const override { return fTexture; }
351
robertphillipsab01ccd2016-03-08 10:45:32 -0800352 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800353 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
354 this->width(), this->height(),
355 this->isOpaque());
356 if (!result->setInfo(info)) {
357 return false;
358 }
359
robertphillipsc5035e72016-03-17 06:58:39 -0700360 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
361
362 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
363 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800364 return true;
365 }
366
robertphillips4418dba2016-03-07 12:45:14 -0800367 bool testingOnlyOnGetROPixels(SkBitmap* result) const override {
368
369 const SkImageInfo info = SkImageInfo::MakeN32(this->width(),
370 this->height(),
371 this->isOpaque() ? kOpaque_SkAlphaType
372 : kPremul_SkAlphaType);
373 if (!result->tryAllocPixels(info)) {
374 return false;
375 }
376
377 if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig,
378 result->getPixels(), result->rowBytes())) {
379 return false;
380 }
381
382 result->pixelRef()->setImmutable();
383 return true;
384 }
385
robertphillipsb6c65e92016-02-04 10:52:42 -0800386 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
387 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
388 desc.fFlags = kRenderTarget_GrSurfaceFlag;
389
robertphillips3b087f42016-02-18 08:48:03 -0800390 return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800391 }
392
robertphillipsc5035e72016-03-17 06:58:39 -0700393 SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
394 return SkSpecialImage::NewFromGpu(this->internal_getProxy(),
395 subset,
396 this->uniqueID(),
397 fTexture,
398 fAlphaType);
399 }
400
robertphillipsb6c65e92016-02-04 10:52:42 -0800401private:
402 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800403 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800404
405 typedef SkSpecialImage_Base INHERITED;
406};
407
robertphillips3b087f42016-02-18 08:48:03 -0800408SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
409 const SkIRect& subset,
410 uint32_t uniqueID,
411 GrTexture* tex,
412 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800413 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips3b087f42016-02-18 08:48:03 -0800414 return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800415}
416
417#else
418
robertphillips3b087f42016-02-18 08:48:03 -0800419SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
420 const SkIRect& subset,
421 uint32_t uniqueID,
422 GrTexture* tex,
423 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800424 return nullptr;
425}
426
427#endif