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