1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <SkBitmap.h> 19 #include <SkColorFilter.h> 20 #include <SkColorSpace.h> 21 #include <SkImage.h> 22 #include <SkImageInfo.h> 23 #include <SkPixelRef.h> 24 #include <SkRefCnt.h> 25 #include <cutils/compiler.h> 26 #include <utils/StrongPointer.h> 27 28 #include <mutex> 29 #include <optional> 30 31 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 32 #include <android/hardware_buffer.h> 33 #endif 34 35 class SkWStream; 36 37 namespace android { 38 39 enum class PixelStorageType { 40 WrappedPixelRef = 0, 41 Heap = 1, 42 Ashmem = 2, 43 Hardware = 3, 44 }; 45 46 // TODO: Find a better home for this. It's here because hwui/Bitmap is exported and CanvasTransform 47 // isn't, but cleanup should be done 48 enum class BitmapPalette { 49 Unknown, 50 Light, 51 Dark, 52 }; 53 54 namespace uirenderer { 55 class Gainmap; 56 namespace renderthread { 57 class RenderThread; 58 } 59 } 60 61 class PixelStorage; 62 63 typedef void (*FreeFunc)(void* addr, void* context); 64 65 class Bitmap : public SkPixelRef { 66 public: 67 /* The allocate factories not only construct the Bitmap object but also allocate the 68 * backing store whose type is determined by the specific method that is called. 69 * 70 * The factories that accept SkBitmap* as a param will modify those params by 71 * installing the returned bitmap as their SkPixelRef. 72 * 73 * The factories that accept const SkBitmap& as a param will copy the contents of the 74 * provided bitmap into the newly allocated buffer. 75 */ 76 static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap); 77 static sk_sp<Bitmap> allocateHardwareBitmap(const SkBitmap& bitmap); 78 static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap); 79 static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info); 80 static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& i, size_t rowBytes); 81 82 static std::string getAshmemId(const char* tag, uint64_t bitmapId, 83 int width, int height, size_t size); 84 85 /* The createFrom factories construct a new Bitmap object by wrapping the already allocated 86 * memory that is provided as an input param. 87 */ 88 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 89 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, 90 sk_sp<SkColorSpace> colorSpace, 91 BitmapPalette palette = BitmapPalette::Unknown); 92 93 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, 94 SkColorType colorType, 95 sk_sp<SkColorSpace> colorSpace, 96 SkAlphaType alphaType, 97 BitmapPalette palette); 98 #endif 99 static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr, 100 size_t size, bool readOnly); 101 static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&); 102 rowBytesAsPixels()103 int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); } 104 105 void reconfigure(const SkImageInfo& info, size_t rowBytes); 106 void reconfigure(const SkImageInfo& info); 107 void setColorSpace(sk_sp<SkColorSpace> colorSpace); 108 void setAlphaType(SkAlphaType alphaType); 109 getId()110 uint64_t getId() const { 111 return mId; 112 } 113 114 void getSkBitmap(SkBitmap* outBitmap); 115 getSkBitmap()116 SkBitmap getSkBitmap() { 117 SkBitmap ret; 118 getSkBitmap(&ret); 119 return ret; 120 } 121 122 int getAshmemFd() const; 123 size_t getAllocationByteCount() const; 124 125 void setHasHardwareMipMap(bool hasMipMap); 126 bool hasHardwareMipMap() const; 127 isOpaque()128 bool isOpaque() const { return mInfo.isOpaque(); } colorType()129 SkColorType colorType() const { return mInfo.colorType(); } info()130 const SkImageInfo& info() const { return mInfo; } 131 132 void getBounds(SkRect* bounds) const; 133 isHardware()134 bool isHardware() const { return mPixelStorageType == PixelStorageType::Hardware; } hasGainmap()135 bool hasGainmap() const { return mGainmap.get() != nullptr; } 136 137 sp<uirenderer::Gainmap> gainmap() const; 138 139 void setGainmap(sp<uirenderer::Gainmap>&& gainmap); 140 pixelStorageType()141 PixelStorageType pixelStorageType() const { return mPixelStorageType; } 142 143 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 144 AHardwareBuffer* hardwareBuffer(); 145 #endif 146 147 /** 148 * Creates or returns a cached SkImage and is safe to be invoked from either 149 * the UI or RenderThread. 150 * 151 */ 152 sk_sp<SkImage> makeImage(); 153 154 static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes); 155 computePalette(const SkBitmap & bitmap)156 static BitmapPalette computePalette(const SkBitmap& bitmap) { 157 return computePalette(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes()); 158 } 159 palette()160 BitmapPalette palette() { 161 if (!isHardware() && mPaletteGenerationId != getGenerationID()) { 162 mPalette = computePalette(info(), pixels(), rowBytes()); 163 mPaletteGenerationId = getGenerationID(); 164 } 165 return mPalette; 166 } 167 168 // returns true if rowBytes * height can be represented by a positive int32_t value 169 // and places that value in size. 170 static bool computeAllocationSize(size_t rowBytes, int height, size_t* size); 171 172 // These must match the int values of CompressFormat in Bitmap.java, as well as 173 // AndroidBitmapCompressFormat. 174 enum class JavaCompressFormat { 175 Jpeg = 0, 176 Png = 1, 177 Webp = 2, 178 WebpLossy = 3, 179 WebpLossless = 4, 180 }; 181 182 bool compress(JavaCompressFormat format, int32_t quality, SkWStream* stream); 183 184 static bool compress(const SkBitmap& bitmap, JavaCompressFormat format, 185 int32_t quality, SkWStream* stream); 186 private: 187 static constexpr uint64_t INVALID_BITMAP_ID = 0u; 188 189 static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes); 190 191 Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes); 192 Bitmap(SkPixelRef& pixelRef, const SkImageInfo& info); 193 Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes, 194 uint64_t id = INVALID_BITMAP_ID); 195 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 196 Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes, 197 BitmapPalette palette); 198 199 // Common code for the two public facing createFrom(AHardwareBuffer*, ...) 200 // methods. 201 // bufferDesc is only used to compute rowBytes. 202 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, const SkImageInfo& info, 203 const AHardwareBuffer_Desc& bufferDesc, BitmapPalette palette); 204 #endif 205 206 virtual ~Bitmap(); 207 208 SkImageInfo mInfo; 209 210 const PixelStorageType mPixelStorageType; 211 212 BitmapPalette mPalette = BitmapPalette::Unknown; 213 uint32_t mPaletteGenerationId = -1; 214 215 bool mHasHardwareMipMap = false; 216 217 sp<uirenderer::Gainmap> mGainmap; 218 219 union { 220 struct { 221 SkPixelRef* pixelRef; 222 } wrapped; 223 struct { 224 void* address; 225 int fd; 226 size_t size; 227 } ashmem; 228 struct { 229 void* address; 230 size_t size; 231 } heap; 232 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 233 struct { 234 AHardwareBuffer* buffer; 235 uint64_t size; 236 } hardware; 237 #endif 238 } mPixelStorage; 239 240 sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline. 241 242 uint64_t mId; // unique ID for this bitmap 243 static uint64_t getId(PixelStorageType type); 244 245 // for tracing total number and memory usage of bitmaps 246 static std::mutex mLock; 247 static size_t mTotalBitmapBytes; 248 static size_t mTotalBitmapCount; 249 void traceBitmapCreate(); 250 void traceBitmapDelete(); 251 }; 252 253 } // namespace android 254