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