1 /* 2 * Copyright 2020 Google LLC 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 #ifndef GrPixmap_DEFINED 9 #define GrPixmap_DEFINED 10 11 #include "include/core/SkData.h" 12 #include "include/core/SkPixmap.h" 13 #include "src/gpu/ganesh/GrImageInfo.h" 14 15 template <typename T, typename DERIVED> class GrPixmapBase { 16 public: info()17 const GrImageInfo& info() const { return fInfo; } colorInfo()18 const GrColorInfo& colorInfo() const { return fInfo.colorInfo(); } 19 addr()20 T* addr() const { return fAddr; } rowBytes()21 size_t rowBytes() const { return fRowBytes; } 22 hasPixels()23 bool hasPixels() const { return SkToBool(fAddr); } ownsPixels()24 bool ownsPixels() const { return SkToBool(fPixelStorage); } pixelStorage()25 sk_sp<SkData> pixelStorage() const { return fPixelStorage; } 26 width()27 int width() const { return fInfo.width(); } height()28 int height() const { return fInfo.height(); } dimensions()29 SkISize dimensions() const { return fInfo.dimensions(); } colorType()30 GrColorType colorType() const { return fInfo.colorType(); } alphaType()31 SkAlphaType alphaType() const { return fInfo.alphaType(); } colorSpace()32 SkColorSpace* colorSpace() const { return fInfo.colorSpace(); } refColorSpace()33 sk_sp<SkColorSpace> refColorSpace() const { return fInfo.refColorSpace(); } 34 35 /** 36 * Map this pixmap to a rect in a surface of indicated dimensions at offset surfacePt. Clip the 37 * logical rectangle to the bounds of the surface. If the rect does not intersect the surface 38 * bounds or is empty then return a default GrPixmap. Otherwise, surfacePt is updated to refer 39 * to the upper left of the clipped rectangle. The returned pixmap will refer to the portion 40 * of the original pixmap inside the surface bounds. 41 */ clip(SkISize surfaceDims,SkIPoint * surfacePt)42 DERIVED clip(SkISize surfaceDims, SkIPoint* surfacePt) { 43 auto bounds = SkIRect::MakeSize(surfaceDims); 44 auto rect = SkIRect::MakePtSize(*surfacePt, this->dimensions()); 45 if (!rect.intersect(bounds)) { 46 return {}; 47 } 48 T* addr = static_cast<sknonstd::copy_const_t<char, T>*>(fAddr) + 49 (rect.fTop - surfacePt->fY) * fRowBytes + 50 (rect.fLeft - surfacePt->fX) * fInfo.bpp(); 51 surfacePt->fX = rect.fLeft; 52 surfacePt->fY = rect.fTop; 53 return DERIVED{this->info().makeDimensions(rect.size()), addr, fRowBytes}; 54 } 55 56 protected: 57 GrPixmapBase() = default; 58 GrPixmapBase(const GrPixmapBase& that) = default; 59 GrPixmapBase(GrPixmapBase&& that) = default; 60 GrPixmapBase& operator=(const GrPixmapBase& that) = default; 61 GrPixmapBase& operator=(GrPixmapBase&& that) = default; 62 GrPixmapBase(GrImageInfo info,T * addr,size_t rowBytes)63 GrPixmapBase(GrImageInfo info, T* addr, size_t rowBytes) 64 : fAddr(addr), fRowBytes(rowBytes), fInfo(std::move(info)) { 65 if (fRowBytes < fInfo.minRowBytes() || !addr) { 66 *this = {}; 67 } 68 } 69 GrPixmapBase(GrImageInfo info,sk_sp<SkData> storage,size_t rowBytes)70 GrPixmapBase(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) 71 : GrPixmapBase(std::move(info), const_cast<void*>(storage->data()), rowBytes) { 72 fPixelStorage = std::move(storage); 73 } 74 75 private: 76 T* fAddr = nullptr; 77 size_t fRowBytes = 0; 78 GrImageInfo fInfo; 79 sk_sp<SkData> fPixelStorage; 80 }; 81 82 /** A pixmap with mutable pixels. */ 83 class GrPixmap : public GrPixmapBase<void, GrPixmap> { 84 public: 85 GrPixmap() = default; 86 GrPixmap(const GrPixmap&) = default; 87 GrPixmap(GrPixmap&&) = default; 88 GrPixmap& operator=(const GrPixmap&) = default; 89 GrPixmap& operator=(GrPixmap&&) = default; 90 GrPixmap(GrImageInfo info,void * addr,size_t rowBytes)91 GrPixmap(GrImageInfo info, void* addr, size_t rowBytes) : GrPixmapBase(info, addr, rowBytes) {} 92 GrPixmap(const SkPixmap & pixmap)93 /* implicit */ GrPixmap(const SkPixmap& pixmap) 94 : GrPixmapBase(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes()) {} 95 96 /** 97 * Returns a GrPixmap that owns its backing store. Copies of the pixmap (as GrPixmap or 98 * GrCPixmap) will share ownership. 99 */ Allocate(const GrImageInfo & info)100 static GrPixmap Allocate(const GrImageInfo& info) { 101 size_t rb = info.minRowBytes(); 102 size_t size = info.height()*rb; 103 if (!size) { 104 return {}; 105 } 106 return GrPixmap(info, SkData::MakeUninitialized(size), rb); 107 } 108 109 private: GrPixmap(GrImageInfo info,sk_sp<SkData> storage,size_t rowBytes)110 GrPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) 111 : GrPixmapBase(std::move(info), std::move(storage), rowBytes) {} 112 }; 113 114 /** 115 * A pixmap with immutable pixels. Note that this pixmap need not be the unique owner of the pixels 116 * and thus it is context-dependent whether the pixels could be manipulated externally. 117 */ 118 class GrCPixmap : public GrPixmapBase<const void, GrCPixmap> { 119 public: 120 GrCPixmap() = default; 121 GrCPixmap(const GrCPixmap&) = default; 122 GrCPixmap(GrCPixmap&&) = default; 123 GrCPixmap& operator=(const GrCPixmap&) = default; 124 GrCPixmap& operator=(GrCPixmap&&) = default; 125 GrCPixmap(const GrPixmap & pixmap)126 /* implicit*/ GrCPixmap(const GrPixmap& pixmap) { 127 if (auto storage = pixmap.pixelStorage()) { 128 *this = GrCPixmap(pixmap.info(), std::move(storage), pixmap.rowBytes()); 129 } else { 130 *this = GrCPixmap(pixmap.info(), pixmap.addr(), pixmap.rowBytes()); 131 } 132 } 133 GrCPixmap(const SkPixmap & pixmap)134 /* implicit */ GrCPixmap(const SkPixmap& pixmap) 135 : GrPixmapBase(pixmap.info(), pixmap.addr(), pixmap.rowBytes()) {} 136 GrCPixmap(GrImageInfo info,const void * addr,size_t rowBytes)137 GrCPixmap(GrImageInfo info, const void* addr, size_t rowBytes) 138 : GrPixmapBase(info, addr, rowBytes) {} 139 140 private: GrCPixmap(GrImageInfo info,sk_sp<SkData> storage,size_t rowBytes)141 GrCPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) 142 : GrPixmapBase(info, std::move(storage), rowBytes) {} 143 }; 144 145 #endif 146