| /* |
| * Copyright 2020 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrPixmap_DEFINED |
| #define GrPixmap_DEFINED |
| |
| #include "include/core/SkData.h" |
| #include "include/core/SkPixmap.h" |
| #include "src/gpu/ganesh/GrImageInfo.h" |
| |
| template <typename T, typename DERIVED> class GrPixmapBase { |
| public: |
| const GrImageInfo& info() const { return fInfo; } |
| const GrColorInfo& colorInfo() const { return fInfo.colorInfo(); } |
| |
| T* addr() const { return fAddr; } |
| size_t rowBytes() const { return fRowBytes; } |
| |
| bool hasPixels() const { return SkToBool(fAddr); } |
| bool ownsPixels() const { return SkToBool(fPixelStorage); } |
| sk_sp<SkData> pixelStorage() const { return fPixelStorage; } |
| |
| int width() const { return fInfo.width(); } |
| int height() const { return fInfo.height(); } |
| SkISize dimensions() const { return fInfo.dimensions(); } |
| GrColorType colorType() const { return fInfo.colorType(); } |
| SkAlphaType alphaType() const { return fInfo.alphaType(); } |
| SkColorSpace* colorSpace() const { return fInfo.colorSpace(); } |
| sk_sp<SkColorSpace> refColorSpace() const { return fInfo.refColorSpace(); } |
| |
| /** |
| * Map this pixmap to a rect in a surface of indicated dimensions at offset surfacePt. Clip the |
| * logical rectangle to the bounds of the surface. If the rect does not intersect the surface |
| * bounds or is empty then return a default GrPixmap. Otherwise, surfacePt is updated to refer |
| * to the upper left of the clipped rectangle. The returned pixmap will refer to the portion |
| * of the original pixmap inside the surface bounds. |
| */ |
| DERIVED clip(SkISize surfaceDims, SkIPoint* surfacePt) { |
| auto bounds = SkIRect::MakeSize(surfaceDims); |
| auto rect = SkIRect::MakePtSize(*surfacePt, this->dimensions()); |
| if (!rect.intersect(bounds)) { |
| return {}; |
| } |
| T* addr = static_cast<sknonstd::copy_const_t<char, T>*>(fAddr) + |
| (rect.fTop - surfacePt->fY) * fRowBytes + |
| (rect.fLeft - surfacePt->fX) * fInfo.bpp(); |
| surfacePt->fX = rect.fLeft; |
| surfacePt->fY = rect.fTop; |
| return DERIVED{this->info().makeDimensions(rect.size()), addr, fRowBytes}; |
| } |
| |
| protected: |
| GrPixmapBase() = default; |
| GrPixmapBase(const GrPixmapBase& that) = default; |
| GrPixmapBase(GrPixmapBase&& that) = default; |
| GrPixmapBase& operator=(const GrPixmapBase& that) = default; |
| GrPixmapBase& operator=(GrPixmapBase&& that) = default; |
| |
| GrPixmapBase(GrImageInfo info, T* addr, size_t rowBytes) |
| : fAddr(addr), fRowBytes(rowBytes), fInfo(std::move(info)) { |
| if (fRowBytes < fInfo.minRowBytes() || !addr) { |
| *this = {}; |
| } |
| } |
| |
| GrPixmapBase(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) |
| : GrPixmapBase(std::move(info), const_cast<void*>(storage->data()), rowBytes) { |
| fPixelStorage = std::move(storage); |
| } |
| |
| private: |
| T* fAddr = nullptr; |
| size_t fRowBytes = 0; |
| GrImageInfo fInfo; |
| sk_sp<SkData> fPixelStorage; |
| }; |
| |
| /** A pixmap with mutable pixels. */ |
| class GrPixmap : public GrPixmapBase<void, GrPixmap> { |
| public: |
| GrPixmap() = default; |
| GrPixmap(const GrPixmap&) = default; |
| GrPixmap(GrPixmap&&) = default; |
| GrPixmap& operator=(const GrPixmap&) = default; |
| GrPixmap& operator=(GrPixmap&&) = default; |
| |
| GrPixmap(GrImageInfo info, void* addr, size_t rowBytes) |
| : GrPixmapBase(std::move(info), addr, rowBytes) {} |
| |
| /* implicit */ GrPixmap(const SkPixmap& pixmap) |
| : GrPixmapBase(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes()) {} |
| |
| /** |
| * Returns a GrPixmap that owns its backing store. Copies of the pixmap (as GrPixmap or |
| * GrCPixmap) will share ownership. |
| */ |
| static GrPixmap Allocate(const GrImageInfo& info) { |
| size_t rb = info.minRowBytes(); |
| size_t size = info.height()*rb; |
| if (!size) { |
| return {}; |
| } |
| return GrPixmap(info, SkData::MakeUninitialized(size), rb); |
| } |
| |
| private: |
| GrPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) |
| : GrPixmapBase(std::move(info), std::move(storage), rowBytes) {} |
| }; |
| |
| /** |
| * A pixmap with immutable pixels. Note that this pixmap need not be the unique owner of the pixels |
| * and thus it is context-dependent whether the pixels could be manipulated externally. |
| */ |
| class GrCPixmap : public GrPixmapBase<const void, GrCPixmap> { |
| public: |
| GrCPixmap() = default; |
| GrCPixmap(const GrCPixmap&) = default; |
| GrCPixmap(GrCPixmap&&) = default; |
| GrCPixmap& operator=(const GrCPixmap&) = default; |
| GrCPixmap& operator=(GrCPixmap&&) = default; |
| |
| /* implicit*/ GrCPixmap(const GrPixmap& pixmap) { |
| if (auto storage = pixmap.pixelStorage()) { |
| *this = GrCPixmap(pixmap.info(), std::move(storage), pixmap.rowBytes()); |
| } else { |
| *this = GrCPixmap(pixmap.info(), pixmap.addr(), pixmap.rowBytes()); |
| } |
| } |
| |
| /* implicit */ GrCPixmap(const SkPixmap& pixmap) |
| : GrPixmapBase(pixmap.info(), pixmap.addr(), pixmap.rowBytes()) {} |
| |
| GrCPixmap(GrImageInfo info, const void* addr, size_t rowBytes) |
| : GrPixmapBase(std::move(info), addr, rowBytes) {} |
| |
| private: |
| GrCPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) |
| : GrPixmapBase(std::move(info), std::move(storage), rowBytes) {} |
| }; |
| |
| #endif |