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