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