1 /*
2  * Copyright (C) 2010 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 
17 #ifndef ANDROID_HWUI_TEXTURE_H
18 #define ANDROID_HWUI_TEXTURE_H
19 
20 #include "GpuMemoryTracker.h"
21 #include "hwui/Bitmap.h"
22 #include "utils/Color.h"
23 
24 #include <memory>
25 
26 #include <math/mat3.h>
27 
28 #include <ui/ColorSpace.h>
29 
30 #include <EGL/egl.h>
31 #include <EGL/eglext.h>
32 #include <GLES2/gl2.h>
33 #include <GLES3/gl3.h>
34 #include <SkBitmap.h>
35 
36 namespace android {
37 
38 class GraphicBuffer;
39 
40 namespace uirenderer {
41 
42 class Caches;
43 class UvMapper;
44 class Layer;
45 
46 /**
47  * Represents an OpenGL texture.
48  */
49 class Texture : public GpuMemoryTracker {
50 public:
51     static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
52                                 sk_sp<SkColorSpace> sRGB);
53     static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending);
54     static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
55                                            bool needSRGB, GLint* outInternalFormat,
56                                            GLint* outFormat, GLint* outType);
57 
Texture(Caches & caches)58     explicit Texture(Caches& caches) : GpuMemoryTracker(GpuObjectType::Texture), mCaches(caches) {}
59 
~Texture()60     virtual ~Texture() {}
61 
62     inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
63         setWrapST(wrap, wrap, bindTexture, force);
64     }
65 
66     virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
67                            bool force = false);
68 
69     inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
70         setFilterMinMag(filter, filter, bindTexture, force);
71     }
72 
73     virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
74                                  bool force = false);
75 
76     /**
77      * Convenience method to call glDeleteTextures() on this texture's id.
78      */
79     void deleteTexture();
80 
81     /**
82      * Sets the width, height, and format of the texture along with allocating
83      * the texture ID. Does nothing if the width, height, and format are already
84      * the requested values.
85      *
86      * The image data is undefined after calling this.
87      */
resize(uint32_t width,uint32_t height,GLint internalFormat,GLint format)88     void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
89         upload(internalFormat, width, height, format,
90                internalFormat == GL_RGBA16F ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE, nullptr);
91     }
92 
93     /**
94      * Updates this Texture with the contents of the provided Bitmap,
95      * also setting the appropriate width, height, and format. It is not necessary
96      * to call resize() prior to this.
97      *
98      * Note this does not set the generation from the Bitmap.
99      */
100     void upload(Bitmap& source);
101 
102     /**
103      * Basically glTexImage2D/glTexSubImage2D.
104      */
105     void upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format, GLenum type,
106                 const void* pixels);
107 
108     /**
109      * Wraps an existing texture.
110      */
111     void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
112               GLenum target);
113 
id()114     GLuint id() const { return mId; }
115 
width()116     uint32_t width() const { return mWidth; }
117 
height()118     uint32_t height() const { return mHeight; }
119 
format()120     GLint format() const { return mFormat; }
121 
internalFormat()122     GLint internalFormat() const { return mInternalFormat; }
123 
target()124     GLenum target() const { return mTarget; }
125 
126     /**
127      * Returns nullptr if this texture does not require color space conversion
128      * to sRGB, or a valid pointer to a ColorSpaceConnector if a conversion
129      * is required.
130      */
getColorSpaceConnector()131     constexpr const ColorSpaceConnector* getColorSpaceConnector() const { return mConnector.get(); }
132 
hasColorSpaceConversion()133     constexpr bool hasColorSpaceConversion() const { return mConnector.get() != nullptr; }
134 
135     TransferFunctionType getTransferFunctionType() const;
136 
137     /**
138      * Returns true if this texture uses a linear encoding format.
139      */
isLinear()140     constexpr bool isLinear() const { return mIsLinear; }
141 
142     /**
143      * Generation of the backing bitmap,
144      */
145     uint32_t generation = 0;
146     /**
147      * Indicates whether the texture requires blending.
148      */
149     bool blend = false;
150     /**
151      * Indicates whether this texture should be cleaned up after use.
152      */
153     bool cleanup = false;
154     /**
155      * Optional, size of the original bitmap.
156      */
157     uint32_t bitmapSize = 0;
158     /**
159      * Indicates whether this texture will use trilinear filtering.
160      */
161     bool mipMap = false;
162 
163     /**
164      * Optional, pointer to a texture coordinates mapper.
165      */
166     const UvMapper* uvMapper = nullptr;
167 
168     /**
169      * Whether or not the Texture is marked in use and thus not evictable for
170      * the current frame. This is reset at the start of a new frame.
171      */
172     void* isInUse = nullptr;
173 
174 private:
175     // TODO: Temporarily grant private access to GlLayer, remove once
176     // GlLayer can be de-tangled from being a dual-purpose render target
177     // and external texture wrapper
178     friend class GlLayer;
179 
180     // Returns true if the texture layout (size, format, etc.) changed, false if it was the same
181     bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
182                       GLenum target);
183     void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
184     void resetCachedParams();
185 
186     GLuint mId = 0;
187     uint32_t mWidth = 0;
188     uint32_t mHeight = 0;
189     GLint mFormat = 0;
190     GLint mInternalFormat = 0;
191     GLenum mTarget = GL_NONE;
192     EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;
193 
194     /* See GLES spec section 3.8.14
195      * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
196      * NEAREST_MIPMAP_LINEAR and the value for TEXTURE_MAG_FILTER is LINEAR.
197      * s, t, and r wrap modes are all set to REPEAT."
198      */
199     GLenum mWrapS = GL_REPEAT;
200     GLenum mWrapT = GL_REPEAT;
201     GLenum mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
202     GLenum mMagFilter = GL_LINEAR;
203 
204     // Indicates whether the content of the texture is in linear space
205     bool mIsLinear = false;
206 
207     Caches& mCaches;
208 
209     std::unique_ptr<ColorSpaceConnector> mConnector;
210 };  // struct Texture
211 
212 class AutoTexture {
213 public:
AutoTexture(Texture * texture)214     explicit AutoTexture(Texture* texture) : texture(texture) {}
~AutoTexture()215     ~AutoTexture() {
216         if (texture && texture->cleanup) {
217             texture->deleteTexture();
218             delete texture;
219         }
220     }
221 
222     Texture* const texture;
223 };  // class AutoTexture
224 
225 };  // namespace uirenderer
226 };  // namespace android
227 
228 #endif  // ANDROID_HWUI_TEXTURE_H
229