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 <optional> 29 30 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 31 #include <android/hardware_buffer.h> 32 #endif 33 34 class SkWStream; 35 36 namespace android { 37 38 enum class PixelStorageType { 39 WrappedPixelRef, 40 Heap, 41 Ashmem, 42 Hardware, 43 }; 44 45 // TODO: Find a better home for this. It's here because hwui/Bitmap is exported and CanvasTransform 46 // isn't, but cleanup should be done 47 enum class BitmapPalette { 48 Unknown, 49 Light, 50 Dark, 51 }; 52 53 namespace uirenderer { 54 class Gainmap; 55 namespace renderthread { 56 class RenderThread; 57 } 58 } 59 60 class PixelStorage; 61 62 typedef void (*FreeFunc)(void* addr, void* context); 63 64 class Bitmap : public SkPixelRef { 65 public: 66 /* The allocate factories not only construct the Bitmap object but also allocate the 67 * backing store whose type is determined by the specific method that is called. 68 * 69 * The factories that accept SkBitmap* as a param will modify those params by 70 * installing the returned bitmap as their SkPixelRef. 71 * 72 * The factories that accept const SkBitmap& as a param will copy the contents of the 73 * provided bitmap into the newly allocated buffer. 74 */ 75 static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap); 76 static sk_sp<Bitmap> allocateHardwareBitmap(const SkBitmap& bitmap); 77 static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap); 78 static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info); 79 static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& i, size_t rowBytes); 80 81 /* The createFrom factories construct a new Bitmap object by wrapping the already allocated 82 * memory that is provided as an input param. 83 */ 84 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 85 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, 86 sk_sp<SkColorSpace> colorSpace, 87 BitmapPalette palette = BitmapPalette::Unknown); 88 89 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, 90 SkColorType colorType, 91 sk_sp<SkColorSpace> colorSpace, 92 SkAlphaType alphaType, 93 BitmapPalette palette); 94 #endif 95 static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr, 96 size_t size, bool readOnly); 97 static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&); 98 rowBytesAsPixels()99 int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); } 100 101 void reconfigure(const SkImageInfo& info, size_t rowBytes); 102 void reconfigure(const SkImageInfo& info); 103 void setColorSpace(sk_sp<SkColorSpace> colorSpace); 104 void setAlphaType(SkAlphaType alphaType); 105 106 void getSkBitmap(SkBitmap* outBitmap); 107 getSkBitmap()108 SkBitmap getSkBitmap() { 109 SkBitmap ret; 110 getSkBitmap(&ret); 111 return ret; 112 } 113 114 int getAshmemFd() const; 115 size_t getAllocationByteCount() const; 116 117 void setHasHardwareMipMap(bool hasMipMap); 118 bool hasHardwareMipMap() const; 119 isOpaque()120 bool isOpaque() const { return mInfo.isOpaque(); } colorType()121 SkColorType colorType() const { return mInfo.colorType(); } info()122 const SkImageInfo& info() const { return mInfo; } 123 124 void getBounds(SkRect* bounds) const; 125 isHardware()126 bool isHardware() const { return mPixelStorageType == PixelStorageType::Hardware; } hasGainmap()127 bool hasGainmap() const { return mGainmap.get() != nullptr; } 128 129 sp<uirenderer::Gainmap> gainmap() const; 130 131 void setGainmap(sp<uirenderer::Gainmap>&& gainmap); 132 pixelStorageType()133 PixelStorageType pixelStorageType() const { return mPixelStorageType; } 134 135 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 136 AHardwareBuffer* hardwareBuffer(); 137 #endif 138 139 /** 140 * Creates or returns a cached SkImage and is safe to be invoked from either 141 * the UI or RenderThread. 142 * 143 */ 144 sk_sp<SkImage> makeImage(); 145 146 static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes); 147 computePalette(const SkBitmap & bitmap)148 static BitmapPalette computePalette(const SkBitmap& bitmap) { 149 return computePalette(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes()); 150 } 151 palette()152 BitmapPalette palette() { 153 if (!isHardware() && mPaletteGenerationId != getGenerationID()) { 154 mPalette = computePalette(info(), pixels(), rowBytes()); 155 mPaletteGenerationId = getGenerationID(); 156 } 157 return mPalette; 158 } 159 160 // returns true if rowBytes * height can be represented by a positive int32_t value 161 // and places that value in size. 162 static bool computeAllocationSize(size_t rowBytes, int height, size_t* size); 163 164 // These must match the int values of CompressFormat in Bitmap.java, as well as 165 // AndroidBitmapCompressFormat. 166 enum class JavaCompressFormat { 167 Jpeg = 0, 168 Png = 1, 169 Webp = 2, 170 WebpLossy = 3, 171 WebpLossless = 4, 172 }; 173 174 bool compress(JavaCompressFormat format, int32_t quality, SkWStream* stream); 175 176 static bool compress(const SkBitmap& bitmap, JavaCompressFormat format, 177 int32_t quality, SkWStream* stream); 178 private: 179 static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes); 180 181 Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes); 182 Bitmap(SkPixelRef& pixelRef, const SkImageInfo& info); 183 Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes); 184 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 185 Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes, 186 BitmapPalette palette); 187 188 // Common code for the two public facing createFrom(AHardwareBuffer*, ...) 189 // methods. 190 // bufferDesc is only used to compute rowBytes. 191 static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, const SkImageInfo& info, 192 const AHardwareBuffer_Desc& bufferDesc, BitmapPalette palette); 193 #endif 194 195 virtual ~Bitmap(); 196 197 SkImageInfo mInfo; 198 199 const PixelStorageType mPixelStorageType; 200 201 BitmapPalette mPalette = BitmapPalette::Unknown; 202 uint32_t mPaletteGenerationId = -1; 203 204 bool mHasHardwareMipMap = false; 205 206 sp<uirenderer::Gainmap> mGainmap; 207 208 union { 209 struct { 210 SkPixelRef* pixelRef; 211 } wrapped; 212 struct { 213 void* address; 214 int fd; 215 size_t size; 216 } ashmem; 217 struct { 218 void* address; 219 size_t size; 220 } heap; 221 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration 222 struct { 223 AHardwareBuffer* buffer; 224 uint64_t size; 225 } hardware; 226 #endif 227 } mPixelStorage; 228 229 sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline. 230 }; 231 232 } // namespace android 233