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
32namespace gl { class Surface; }
33
34namespace es2
35{
36class Sampler;
37
38enum
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
48class ImageLevels
49{
50public:
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
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
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
90private:
91 egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS] = {};
92 static egl::Image*& getNullImage();
93};
94
95class Texture : public egl::Texture
96{
97public:
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
125 GLenum getMinFilter() const { return mMinFilter; }
126 GLenum getMagFilter() const { return mMagFilter; }
127 GLenum getWrapS() const { return mWrapS; }
128 GLenum getWrapT() const { return mWrapT; }
129 GLenum getWrapR() const { return mWrapR; }
130 GLfloat getMaxAnisotropy() const { return mMaxAnisotropy; }
131 GLint getBaseLevel() const { return mBaseLevel; }
132 GLenum getCompareFunc() const { return mCompareFunc; }
133 GLenum getCompareMode() const { return mCompareMode; }
134 GLboolean getImmutableFormat() const { return mImmutableFormat; }
135 GLsizei getImmutableLevels() const { return mImmutableLevels; }
136 GLint getMaxLevel() const { return mMaxLevel; }
137 GLfloat getMaxLOD() const { return mMaxLOD; }
138 GLfloat getMinLOD() const { return mMinLOD; }
139 GLenum getSwizzleR() const { return mSwizzleR; }
140 GLenum getSwizzleG() const { return mSwizzleG; }
141 GLenum getSwizzleB() const { return mSwizzleB; }
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
165protected:
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
199class Texture2D : public Texture
200{
201public:
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
242protected:
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
260class Texture2DRect : public Texture2D
261{
262public:
263 explicit Texture2DRect(GLuint name);
264
265 GLenum getTarget() const override;
266
267 Renderbuffer *getRenderbuffer(GLenum target, GLint level) override;
268};
269
270class TextureCubeMap : public Texture
271{
272public:
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
313protected:
314 ~TextureCubeMap() override;
315
316private:
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
333class Texture3D : public Texture
334{
335public:
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
375protected:
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
393class Texture2DArray : public Texture3D
394{
395public:
396 explicit Texture2DArray(GLuint name);
397
398 GLenum getTarget() const override;
399 void generateMipmaps() override;
400
401protected:
402 ~Texture2DArray() override;
403};
404
405class TextureExternal : public Texture2D
406{
407public:
408 explicit TextureExternal(GLuint name);
409
410 GLenum getTarget() const override;
411
412protected:
413 ~TextureExternal() override;
414};
415}
416
417#endif // LIBGLESV2_TEXTURE_H_
418