1 /* 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" 9 #include "SkSpecialImage.h" 10 #include "SkSpecialSurface.h" 11 12 /////////////////////////////////////////////////////////////////////////////// 13 class SkSpecialImage_Base : public SkSpecialImage { 14 public: 15 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID) 16 : INHERITED(proxy, subset, uniqueID) { 17 } 18 virtual ~SkSpecialImage_Base() { } 19 20 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0; 21 22 virtual bool onPeekPixels(SkPixmap*) const { return false; } 23 24 virtual GrTexture* onPeekTexture() const { return nullptr; } 25 26 // Delete this entry point ASAP (see skbug.com/4965) 27 virtual bool getBitmap(SkBitmap* result) const = 0; 28 29 virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; } 30 31 private: 32 typedef SkSpecialImage INHERITED; 33 }; 34 35 /////////////////////////////////////////////////////////////////////////////// 36 static inline const SkSpecialImage_Base* as_IB(const SkSpecialImage* image) { 37 return static_cast<const SkSpecialImage_Base*>(image); 38 } 39 40 void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const { 41 return as_IB(this)->onDraw(canvas, x, y, paint); 42 } 43 44 bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const { 45 return as_IB(this)->onPeekPixels(pixmap); 46 } 47 48 GrTexture* SkSpecialImage::peekTexture() const { 49 return as_IB(this)->onPeekTexture(); 50 } 51 52 SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const { 53 return as_IB(this)->onNewSurface(info); 54 } 55 56 #if SK_SUPPORT_GPU 57 #include "SkGr.h" 58 #include "SkGrPixelRef.h" 59 #endif 60 61 SkSpecialImage* SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy, 62 const SkBitmap& src) { 63 // Need to test offset case! (see skbug.com/4967) 64 if (src.getTexture()) { 65 return SkSpecialImage::NewFromGpu(proxy, 66 src.bounds(), 67 src.getGenerationID(), 68 src.getTexture()); 69 } 70 71 return SkSpecialImage::NewFromRaster(proxy, src.bounds(), src); 72 } 73 74 bool SkSpecialImage::internal_getBM(SkBitmap* result) { 75 const SkSpecialImage_Base* ib = as_IB(this); 76 77 // TODO: need to test offset case! (see skbug.com/4967) 78 return ib->getBitmap(result); 79 } 80 81 SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() { 82 SkASSERT(fProxy); 83 return fProxy; 84 } 85 86 /////////////////////////////////////////////////////////////////////////////// 87 #include "SkImage.h" 88 #if SK_SUPPORT_GPU 89 #include "SkGrPriv.h" 90 #endif 91 92 class SkSpecialImage_Image : public SkSpecialImage_Base { 93 public: 94 SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image) 95 : INHERITED(proxy, subset, image->uniqueID()) 96 , fImage(SkRef(image)) { 97 } 98 99 ~SkSpecialImage_Image() override { } 100 101 bool isOpaque() const override { return fImage->isOpaque(); } 102 103 size_t getSize() const override { 104 #if SK_SUPPORT_GPU 105 if (fImage->getTexture()) { 106 return fImage->getTexture()->gpuMemorySize(); 107 } else 108 #endif 109 { 110 SkImageInfo info; 111 size_t rowBytes; 112 113 if (fImage->peekPixels(&info, &rowBytes)) { 114 return info.height() * rowBytes; 115 } 116 } 117 return 0; 118 } 119 120 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override { 121 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height()); 122 123 canvas->drawImageRect(fImage, this->subset(), 124 dst, paint, SkCanvas::kStrict_SrcRectConstraint); 125 } 126 127 bool onPeekPixels(SkPixmap* pixmap) const override { 128 return fImage->peekPixels(pixmap); 129 } 130 131 GrTexture* onPeekTexture() const override { return fImage->getTexture(); } 132 133 bool getBitmap(SkBitmap* result) const override { 134 return false; 135 } 136 137 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { 138 #if SK_SUPPORT_GPU 139 GrTexture* texture = fImage->getTexture(); 140 if (texture) { 141 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info); 142 desc.fFlags = kRenderTarget_GrSurfaceFlag; 143 144 return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc); 145 } 146 #endif 147 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr); 148 } 149 150 private: 151 SkAutoTUnref<const SkImage> fImage; 152 153 typedef SkSpecialImage_Base INHERITED; 154 }; 155 156 #ifdef SK_DEBUG 157 static bool rect_fits(const SkIRect& rect, int width, int height) { 158 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight && 159 rect.fRight >= 0 && rect.fRight <= width && 160 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom && 161 rect.fBottom >= 0 && rect.fBottom <= height; 162 } 163 #endif 164 165 SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) { 166 SkASSERT(rect_fits(subset, image->width(), image->height())); 167 return new SkSpecialImage_Image(nullptr, subset, image); 168 } 169 170 /////////////////////////////////////////////////////////////////////////////// 171 #include "SkBitmap.h" 172 #include "SkImageInfo.h" 173 #include "SkPixelRef.h" 174 175 class SkSpecialImage_Raster : public SkSpecialImage_Base { 176 public: 177 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm) 178 : INHERITED(proxy, subset, bm.getGenerationID()) 179 , fBitmap(bm) { 180 if (bm.pixelRef()->isPreLocked()) { 181 // we only preemptively lock if there is no chance of triggering something expensive 182 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already. 183 fBitmap.lockPixels(); 184 } 185 } 186 187 ~SkSpecialImage_Raster() override { } 188 189 bool isOpaque() const override { return fBitmap.isOpaque(); } 190 191 size_t getSize() const override { return fBitmap.getSize(); } 192 193 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override { 194 SkRect dst = SkRect::MakeXYWH(x, y, 195 this->subset().width(), this->subset().height()); 196 197 canvas->drawBitmapRect(fBitmap, this->subset(), 198 dst, paint, SkCanvas::kStrict_SrcRectConstraint); 199 } 200 201 bool onPeekPixels(SkPixmap* pixmap) const override { 202 const SkImageInfo info = fBitmap.info(); 203 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) { 204 return false; 205 } 206 const void* pixels = fBitmap.getPixels(); 207 if (pixels) { 208 if (pixmap) { 209 pixmap->reset(info, pixels, fBitmap.rowBytes()); 210 } 211 return true; 212 } 213 return false; 214 } 215 216 bool getBitmap(SkBitmap* result) const override { 217 *result = fBitmap; 218 return true; 219 } 220 221 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { 222 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr); 223 } 224 225 private: 226 SkBitmap fBitmap; 227 228 typedef SkSpecialImage_Base INHERITED; 229 }; 230 231 SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy, 232 const SkIRect& subset, 233 const SkBitmap& bm) { 234 SkASSERT(nullptr == bm.getTexture()); 235 SkASSERT(rect_fits(subset, bm.width(), bm.height())); 236 return new SkSpecialImage_Raster(proxy, subset, bm); 237 } 238 239 #if SK_SUPPORT_GPU 240 /////////////////////////////////////////////////////////////////////////////// 241 #include "GrTexture.h" 242 243 class SkSpecialImage_Gpu : public SkSpecialImage_Base { 244 public: 245 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset, 246 uint32_t uniqueID, GrTexture* tex, SkAlphaType at) 247 : INHERITED(proxy, subset, uniqueID) 248 , fTexture(SkRef(tex)) 249 , fAlphaType(at) { 250 } 251 252 ~SkSpecialImage_Gpu() override { } 253 254 bool isOpaque() const override { 255 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType; 256 } 257 258 size_t getSize() const override { return fTexture->gpuMemorySize(); } 259 260 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override { 261 SkRect dst = SkRect::MakeXYWH(x, y, 262 this->subset().width(), this->subset().height()); 263 264 SkBitmap bm; 265 266 GrWrapTextureInBitmap(fTexture, 267 fTexture->width(), fTexture->height(), this->isOpaque(), &bm); 268 269 canvas->drawBitmapRect(bm, this->subset(), 270 dst, paint, SkCanvas::kStrict_SrcRectConstraint); 271 } 272 273 GrTexture* onPeekTexture() const override { return fTexture; } 274 275 bool getBitmap(SkBitmap* result) const override { 276 const SkImageInfo info = GrMakeInfoFromTexture(fTexture, 277 this->width(), this->height(), 278 this->isOpaque()); 279 if (!result->setInfo(info)) { 280 return false; 281 } 282 283 result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref(); 284 return true; 285 } 286 287 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { 288 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info); 289 desc.fFlags = kRenderTarget_GrSurfaceFlag; 290 291 return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc); 292 } 293 294 private: 295 SkAutoTUnref<GrTexture> fTexture; 296 const SkAlphaType fAlphaType; 297 298 typedef SkSpecialImage_Base INHERITED; 299 }; 300 301 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy, 302 const SkIRect& subset, 303 uint32_t uniqueID, 304 GrTexture* tex, 305 SkAlphaType at) { 306 SkASSERT(rect_fits(subset, tex->width(), tex->height())); 307 return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at); 308 } 309 310 #else 311 312 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy, 313 const SkIRect& subset, 314 uint32_t uniqueID, 315 GrTexture* tex, 316 SkAlphaType at) { 317 return nullptr; 318 } 319 320 #endif 321