/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HWUI_TEXTURE_H #define ANDROID_HWUI_TEXTURE_H #include "GpuMemoryTracker.h" #include "hwui/Bitmap.h" #include "utils/Color.h" #include #include #include #include #include #include #include #include namespace android { class GraphicBuffer; namespace uirenderer { class Caches; class UvMapper; class Layer; /** * Represents an OpenGL texture. */ class Texture : public GpuMemoryTracker { public: static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending, sk_sp sRGB); static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending); static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType, bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType); explicit Texture(Caches& caches) : GpuMemoryTracker(GpuObjectType::Texture) , mCaches(caches) { } virtual ~Texture() { } inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) { setWrapST(wrap, wrap, bindTexture, force); } virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false); inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) { setFilterMinMag(filter, filter, bindTexture, force); } virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, bool force = false); /** * Convenience method to call glDeleteTextures() on this texture's id. */ void deleteTexture(); /** * Sets the width, height, and format of the texture along with allocating * the texture ID. Does nothing if the width, height, and format are already * the requested values. * * The image data is undefined after calling this. */ void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) { upload(internalFormat, width, height, format, GL_UNSIGNED_BYTE, nullptr); } /** * Updates this Texture with the contents of the provided Bitmap, * also setting the appropriate width, height, and format. It is not necessary * to call resize() prior to this. * * Note this does not set the generation from the Bitmap. */ void upload(Bitmap& source); /** * Basically glTexImage2D/glTexSubImage2D. */ void upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format, GLenum type, const void* pixels); /** * Wraps an existing texture. */ void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format, GLenum target); GLuint id() const { return mId; } uint32_t width() const { return mWidth; } uint32_t height() const { return mHeight; } GLint format() const { return mFormat; } GLint internalFormat() const { return mInternalFormat; } GLenum target() const { return mTarget; } /** * Returns nullptr if this texture does not require color space conversion * to sRGB, or a valid pointer to a ColorSpaceConnector if a conversion * is required. */ constexpr const ColorSpaceConnector* getColorSpaceConnector() const { return mConnector.get(); } constexpr bool hasColorSpaceConversion() const { return mConnector.get() != nullptr; } TransferFunctionType getTransferFunctionType() const; /** * Returns true if this texture uses a linear encoding format. */ constexpr bool isLinear() const { return mInternalFormat == GL_RGBA16F; } /** * Generation of the backing bitmap, */ uint32_t generation = 0; /** * Indicates whether the texture requires blending. */ bool blend = false; /** * Indicates whether this texture should be cleaned up after use. */ bool cleanup = false; /** * Optional, size of the original bitmap. */ uint32_t bitmapSize = 0; /** * Indicates whether this texture will use trilinear filtering. */ bool mipMap = false; /** * Optional, pointer to a texture coordinates mapper. */ const UvMapper* uvMapper = nullptr; /** * Whether or not the Texture is marked in use and thus not evictable for * the current frame. This is reset at the start of a new frame. */ void* isInUse = nullptr; private: // TODO: Temporarily grant private access to GlLayer, remove once // GlLayer can be de-tangled from being a dual-purpose render target // and external texture wrapper friend class GlLayer; // Returns true if the texture layout (size, format, etc.) changed, false if it was the same bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format, GLenum target); void uploadHardwareBitmapToTexture(GraphicBuffer* buffer); void resetCachedParams(); GLuint mId = 0; uint32_t mWidth = 0; uint32_t mHeight = 0; GLint mFormat = 0; GLint mInternalFormat = 0; GLenum mTarget = GL_NONE; EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR; /* See GLES spec section 3.8.14 * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is * NEAREST_MIPMAP_LINEAR and the value for TEXTURE_MAG_FILTER is LINEAR. * s, t, and r wrap modes are all set to REPEAT." */ GLenum mWrapS = GL_REPEAT; GLenum mWrapT = GL_REPEAT; GLenum mMinFilter = GL_NEAREST_MIPMAP_LINEAR; GLenum mMagFilter = GL_LINEAR; Caches& mCaches; std::unique_ptr mConnector; }; // struct Texture class AutoTexture { public: explicit AutoTexture(Texture* texture) : texture(texture) {} ~AutoTexture() { if (texture && texture->cleanup) { texture->deleteTexture(); delete texture; } } Texture* const texture; }; // class AutoTexture }; // namespace uirenderer }; // namespace android #endif // ANDROID_HWUI_TEXTURE_H