1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Texture.h: Defines the abstract Texture class and its concrete derived 16 // classes Texture2D and TextureCubeMap. Implements GL texture objects and 17 // related functionality. [OpenGL ES 2.0.24] section 3.7 page 63. 18 19 #ifndef LIBGLESV2_TEXTURE_H_ 20 #define LIBGLESV2_TEXTURE_H_ 21 22 #include "Renderbuffer.h" 23 #include "common/Object.hpp" 24 #include "utilities.h" 25 #include "libEGL/Texture.hpp" 26 #include "common/debug.h" 27 28 #include <GLES2/gl2.h> 29 30 #include <vector> 31 32 namespace gl { class Surface; } 33 34 namespace es2 35 { 36 class Sampler; 37 38 enum 39 { 40 IMPLEMENTATION_MAX_TEXTURE_LEVELS = sw::MIPMAP_LEVELS, 41 IMPLEMENTATION_MAX_TEXTURE_SIZE = 1 << (IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1), 42 IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = IMPLEMENTATION_MAX_TEXTURE_SIZE, 43 IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = IMPLEMENTATION_MAX_TEXTURE_SIZE, 44 IMPLEMENTATION_MAX_ARRAY_TEXTURE_LAYERS = IMPLEMENTATION_MAX_TEXTURE_SIZE, 45 IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = sw::OUTLINE_RESOLUTION, 46 }; 47 48 class ImageLevels 49 { 50 public: 51 inline const egl::Image* operator[](size_t index) const 52 { 53 return (index < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? image[index] : nullptr; 54 } 55 56 inline egl::Image*& operator[](size_t index) 57 { 58 if(index < IMPLEMENTATION_MAX_TEXTURE_LEVELS) 59 { 60 return image[index]; 61 } 62 63 return getNullImage(); 64 } 65 release()66 inline void release() 67 { 68 for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 69 { 70 if(image[i]) 71 { 72 image[i]->release(); 73 image[i] = nullptr; 74 } 75 } 76 } 77 unbind(const egl::Texture * texture)78 inline void unbind(const egl::Texture* texture) 79 { 80 for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 81 { 82 if(image[i]) 83 { 84 image[i]->unbind(texture); 85 image[i] = nullptr; 86 } 87 } 88 } 89 90 private: 91 egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS] = {}; 92 static egl::Image*& getNullImage(); 93 }; 94 95 class Texture : public egl::Texture 96 { 97 public: 98 explicit Texture(GLuint name); 99 100 sw::Resource *getResource() const override; 101 102 virtual void addProxyRef(const Renderbuffer *proxy) = 0; 103 virtual void releaseProxy(const Renderbuffer *proxy) = 0; 104 105 virtual GLenum getTarget() const = 0; 106 107 bool setMinFilter(GLenum filter); 108 bool setMagFilter(GLenum filter); 109 bool setWrapS(GLenum wrap); 110 bool setWrapT(GLenum wrap); 111 bool setWrapR(GLenum wrap); 112 bool setMaxAnisotropy(GLfloat textureMaxAnisotropy); 113 bool setBaseLevel(GLint baseLevel); 114 bool setCompareFunc(GLenum compareFunc); 115 bool setCompareMode(GLenum compareMode); 116 void makeImmutable(GLsizei levels); 117 bool setMaxLevel(GLint maxLevel); 118 bool setMaxLOD(GLfloat maxLOD); 119 bool setMinLOD(GLfloat minLOD); 120 bool setSwizzleR(GLenum swizzleR); 121 bool setSwizzleG(GLenum swizzleG); 122 bool setSwizzleB(GLenum swizzleB); 123 bool setSwizzleA(GLenum swizzleA); 124 getMinFilter()125 GLenum getMinFilter() const { return mMinFilter; } getMagFilter()126 GLenum getMagFilter() const { return mMagFilter; } getWrapS()127 GLenum getWrapS() const { return mWrapS; } getWrapT()128 GLenum getWrapT() const { return mWrapT; } getWrapR()129 GLenum getWrapR() const { return mWrapR; } getMaxAnisotropy()130 GLfloat getMaxAnisotropy() const { return mMaxAnisotropy; } getBaseLevel()131 GLint getBaseLevel() const { return mBaseLevel; } getCompareFunc()132 GLenum getCompareFunc() const { return mCompareFunc; } getCompareMode()133 GLenum getCompareMode() const { return mCompareMode; } getImmutableFormat()134 GLboolean getImmutableFormat() const { return mImmutableFormat; } getImmutableLevels()135 GLsizei getImmutableLevels() const { return mImmutableLevels; } getMaxLevel()136 GLint getMaxLevel() const { return mMaxLevel; } getMaxLOD()137 GLfloat getMaxLOD() const { return mMaxLOD; } getMinLOD()138 GLfloat getMinLOD() const { return mMinLOD; } getSwizzleR()139 GLenum getSwizzleR() const { return mSwizzleR; } getSwizzleG()140 GLenum getSwizzleG() const { return mSwizzleG; } getSwizzleB()141 GLenum getSwizzleB() const { return mSwizzleB; } getSwizzleA()142 GLenum getSwizzleA() const { return mSwizzleA; } 143 144 virtual GLsizei getWidth(GLenum target, GLint level) const = 0; 145 virtual GLsizei getHeight(GLenum target, GLint level) const = 0; 146 virtual GLsizei getDepth(GLenum target, GLint level) const; 147 virtual GLint getFormat(GLenum target, GLint level) const = 0; 148 virtual int getTopLevel() const = 0; 149 virtual bool hasNonBaseLevels() const = 0; 150 virtual bool requiresSync() const = 0; 151 152 virtual bool isBaseLevelDefined() const = 0; 153 virtual bool isSamplerComplete(Sampler *sampler) const = 0; 154 virtual bool isCompressed(GLenum target, GLint level) const = 0; 155 virtual bool isDepth(GLenum target, GLint level) const = 0; 156 157 virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level) = 0; 158 virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0; 159 egl::Image *createSharedImage(GLenum target, unsigned int level); 160 virtual bool isShared(GLenum target, unsigned int level) const = 0; 161 162 virtual void generateMipmaps() = 0; 163 virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source) = 0; 164 165 protected: 166 ~Texture() override; 167 168 void setImage(GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels, egl::Image *image); 169 void subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels, egl::Image *image); 170 void setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image); 171 void subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image); 172 173 bool copy(egl::Image *source, const sw::SliceRect &sourceRect, GLint xoffset, GLint yoffset, GLint zoffset, egl::Image *dest); 174 175 bool isMipmapFiltered(Sampler *sampler) const; 176 177 GLenum mMinFilter; 178 GLenum mMagFilter; 179 GLenum mWrapS; 180 GLenum mWrapT; 181 GLenum mWrapR; 182 GLfloat mMaxAnisotropy; 183 GLint mBaseLevel; 184 GLenum mCompareFunc; 185 GLenum mCompareMode; 186 GLboolean mImmutableFormat; 187 GLsizei mImmutableLevels; 188 GLint mMaxLevel; 189 GLfloat mMaxLOD; 190 GLfloat mMinLOD; 191 GLenum mSwizzleR; 192 GLenum mSwizzleG; 193 GLenum mSwizzleB; 194 GLenum mSwizzleA; 195 196 sw::Resource *resource; 197 }; 198 199 class Texture2D : public Texture 200 { 201 public: 202 explicit Texture2D(GLuint name); 203 204 void addProxyRef(const Renderbuffer *proxy) override; 205 void releaseProxy(const Renderbuffer *proxy) override; 206 void sweep() override; 207 208 GLenum getTarget() const override; 209 210 GLsizei getWidth(GLenum target, GLint level) const override; 211 GLsizei getHeight(GLenum target, GLint level) const override; 212 GLint getFormat(GLenum target, GLint level) const override; 213 int getTopLevel() const override; 214 bool hasNonBaseLevels() const override; 215 bool requiresSync() const override; 216 217 void setImage(GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 218 void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); 219 void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 220 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); 221 void copyImage(GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source); 222 void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source) override; 223 224 void setSharedImage(egl::Image *image); 225 226 bool isBaseLevelDefined() const override; 227 bool isSamplerComplete(Sampler *sampler) const override; 228 bool isCompressed(GLenum target, GLint level) const override; 229 bool isDepth(GLenum target, GLint level) const override; 230 231 void bindTexImage(gl::Surface *surface); 232 void releaseTexImage() override; 233 234 void generateMipmaps() override; 235 236 Renderbuffer *getRenderbuffer(GLenum target, GLint level) override; 237 egl::Image *getRenderTarget(GLenum target, unsigned int level) override; 238 bool isShared(GLenum target, unsigned int level) const override; 239 240 egl::Image *getImage(unsigned int level); 241 242 protected: 243 ~Texture2D() override; 244 245 bool isMipmapComplete() const; 246 247 ImageLevels image; 248 249 gl::Surface *mSurface; 250 251 // A specific internal reference count is kept for colorbuffer proxy references, 252 // because, as the renderbuffer acting as proxy will maintain a binding pointer 253 // back to this texture, there would be a circular reference if we used a binding 254 // pointer here. This reference count will cause the pointer to be set to null if 255 // the count drops to zero, but will not cause deletion of the Renderbuffer. 256 Renderbuffer *mColorbufferProxy; 257 unsigned int mProxyRefs; 258 }; 259 260 class Texture2DRect : public Texture2D 261 { 262 public: 263 explicit Texture2DRect(GLuint name); 264 265 GLenum getTarget() const override; 266 267 Renderbuffer *getRenderbuffer(GLenum target, GLint level) override; 268 }; 269 270 class TextureCubeMap : public Texture 271 { 272 public: 273 explicit TextureCubeMap(GLuint name); 274 275 void addProxyRef(const Renderbuffer *proxy) override; 276 void releaseProxy(const Renderbuffer *proxy) override; 277 void sweep() override; 278 279 GLenum getTarget() const override; 280 281 GLsizei getWidth(GLenum target, GLint level) const override; 282 GLsizei getHeight(GLenum target, GLint level) const override; 283 GLint getFormat(GLenum target, GLint level) const override; 284 int getTopLevel() const override; 285 bool hasNonBaseLevels() const override; 286 bool requiresSync() const override; 287 288 void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 289 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); 290 291 void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 292 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); 293 void copyImage(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source); 294 void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source) override; 295 296 bool isBaseLevelDefined() const override; 297 bool isSamplerComplete(Sampler *sampler) const override; 298 bool isCompressed(GLenum target, GLint level) const override; 299 bool isDepth(GLenum target, GLint level) const override; 300 void releaseTexImage() override; 301 302 void generateMipmaps() override; 303 void updateBorders(int level); 304 305 Renderbuffer *getRenderbuffer(GLenum target, GLint level) override; 306 egl::Image *getRenderTarget(GLenum target, unsigned int level) override; 307 bool isShared(GLenum target, unsigned int level) const override; 308 309 egl::Image *getImage(int face, unsigned int level); 310 311 bool isCubeComplete() const; 312 313 protected: 314 ~TextureCubeMap() override; 315 316 private: 317 bool isMipmapCubeComplete() const; 318 319 // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. Returns nullptr on failure. 320 egl::Image *getImage(GLenum face, unsigned int level); 321 322 ImageLevels image[6]; 323 324 // A specific internal reference count is kept for colorbuffer proxy references, 325 // because, as the renderbuffer acting as proxy will maintain a binding pointer 326 // back to this texture, there would be a circular reference if we used a binding 327 // pointer here. This reference count will cause the pointer to be set to null if 328 // the count drops to zero, but will not cause deletion of the Renderbuffer. 329 Renderbuffer *mFaceProxies[6]; 330 unsigned int mFaceProxyRefs[6]; 331 }; 332 333 class Texture3D : public Texture 334 { 335 public: 336 explicit Texture3D(GLuint name); 337 338 void addProxyRef(const Renderbuffer *proxy) override; 339 void releaseProxy(const Renderbuffer *proxy) override; 340 void sweep() override; 341 342 GLenum getTarget() const override; 343 344 GLsizei getWidth(GLenum target, GLint level) const override; 345 GLsizei getHeight(GLenum target, GLint level) const override; 346 GLsizei getDepth(GLenum target, GLint level) const override; 347 GLint getFormat(GLenum target, GLint level) const override; 348 int getTopLevel() const override; 349 bool hasNonBaseLevels() const override; 350 bool requiresSync() const override; 351 352 void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 353 void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); 354 void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels); 355 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); 356 void copyImage(GLint level, GLenum internalformat, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, GLsizei depth, Renderbuffer *source); 357 void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source) override; 358 359 void setSharedImage(egl::Image *image); 360 361 bool isBaseLevelDefined() const override; 362 bool isSamplerComplete(Sampler *sampler) const override; 363 bool isCompressed(GLenum target, GLint level) const override; 364 bool isDepth(GLenum target, GLint level) const override; 365 void releaseTexImage() override; 366 367 void generateMipmaps() override; 368 369 Renderbuffer *getRenderbuffer(GLenum target, GLint level) override; 370 egl::Image *getRenderTarget(GLenum target, unsigned int level) override; 371 bool isShared(GLenum target, unsigned int level) const override; 372 373 egl::Image *getImage(unsigned int level); 374 375 protected: 376 ~Texture3D() override; 377 378 bool isMipmapComplete() const; 379 380 ImageLevels image; 381 382 gl::Surface *mSurface; 383 384 // A specific internal reference count is kept for colorbuffer proxy references, 385 // because, as the renderbuffer acting as proxy will maintain a binding pointer 386 // back to this texture, there would be a circular reference if we used a binding 387 // pointer here. This reference count will cause the pointer to be set to null if 388 // the count drops to zero, but will not cause deletion of the Renderbuffer. 389 Renderbuffer *mColorbufferProxy; 390 unsigned int mProxyRefs; 391 }; 392 393 class Texture2DArray : public Texture3D 394 { 395 public: 396 explicit Texture2DArray(GLuint name); 397 398 GLenum getTarget() const override; 399 void generateMipmaps() override; 400 401 protected: 402 ~Texture2DArray() override; 403 }; 404 405 class TextureExternal : public Texture2D 406 { 407 public: 408 explicit TextureExternal(GLuint name); 409 410 GLenum getTarget() const override; 411 412 protected: 413 ~TextureExternal() override; 414 }; 415 } 416 417 #endif // LIBGLESV2_TEXTURE_H_ 418