• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief EGL image tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglImageFormatTests.hpp"
25 
26 #include "deStringUtil.hpp"
27 #include "deSTLUtil.hpp"
28 
29 #include "tcuTestLog.hpp"
30 #include "tcuSurface.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuCommandLine.hpp"
35 
36 #include "egluNativeDisplay.hpp"
37 #include "egluNativeWindow.hpp"
38 #include "egluNativePixmap.hpp"
39 #include "egluConfigFilter.hpp"
40 #include "egluUnique.hpp"
41 #include "egluUtil.hpp"
42 
43 #include "eglwLibrary.hpp"
44 #include "eglwEnums.hpp"
45 
46 #include "gluCallLogWrapper.hpp"
47 #include "gluShaderProgram.hpp"
48 #include "gluStrUtil.hpp"
49 #include "gluTexture.hpp"
50 #include "gluPixelTransfer.hpp"
51 #include "gluObjectWrapper.hpp"
52 #include "gluTextureUtil.hpp"
53 
54 #include "glwEnums.hpp"
55 #include "glwFunctions.hpp"
56 
57 #include "teglImageUtil.hpp"
58 #include "teglAndroidUtil.hpp"
59 
60 #include <vector>
61 #include <string>
62 #include <set>
63 
64 using std::vector;
65 using std::set;
66 using std::string;
67 
68 using de::MovePtr;
69 using de::UniquePtr;
70 
71 using glu::Framebuffer;
72 using glu::Renderbuffer;
73 using glu::Texture;
74 
75 using eglu::UniqueImage;
76 
77 using tcu::ConstPixelBufferAccess;
78 
79 using namespace glw;
80 using namespace eglw;
81 
82 namespace deqp
83 {
84 namespace egl
85 {
86 
87 namespace
88 {
89 
programSources(const string & vertexSource,const string & fragmentSource)90 glu::ProgramSources programSources (const string& vertexSource, const string& fragmentSource)
91 {
92 	glu::ProgramSources sources;
93 
94 	sources << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource);
95 
96 	return sources;
97 }
98 
99 class Program : public glu::ShaderProgram
100 {
101 public:
Program(const glw::Functions & gl,const char * vertexSource,const char * fragmentSource)102 	Program (const glw::Functions& gl, const char* vertexSource, const char* fragmentSource)
103 		: glu::ShaderProgram(gl, programSources(vertexSource, fragmentSource)) {}
104 };
105 
106 } // anonymous
107 
108 namespace Image
109 {
110 
111 class ImageApi;
112 
113 class IllegalRendererException : public std::exception
114 {
115 };
116 
117 class Action
118 {
119 public:
~Action(void)120 	virtual			~Action					(void) {}
121 	virtual bool	invoke					(ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& refImg) const = 0;
122 	virtual string	getRequiredExtension	(void) const = 0;
123 };
124 
125 struct TestSpec
126 {
127 	std::string name;
128 	std::string desc;
129 
130 	enum ApiContext
131 	{
132 		API_GLES2 = 0,
133 		API_GLES3,
134 		//API_VG
135 		//API_GLES1
136 
137 		API_LAST
138 	};
139 
140 	struct Operation
141 	{
Operationdeqp::egl::Image::TestSpec::Operation142 		Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {}
143 		int				apiIndex;
144 		const Action*	action;
145 	};
146 
147 	vector<ApiContext>	contexts;
148 	vector<Operation>	operations;
149 
150 };
151 
152 class ImageApi
153 {
154 public:
155 					ImageApi		(const Library& egl, int contextId, EGLDisplay display, EGLSurface surface);
~ImageApi(void)156 	virtual			~ImageApi		(void) {}
157 
158 protected:
159 	const Library&	m_egl;
160 	int				m_contextId;
161 	EGLDisplay		m_display;
162 	EGLSurface		m_surface;
163 };
164 
ImageApi(const Library & egl,int contextId,EGLDisplay display,EGLSurface surface)165 ImageApi::ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface)
166 	: m_egl				(egl)
167 	, m_contextId		(contextId)
168 	, m_display			(display)
169 	, m_surface			(surface)
170 {
171 }
172 
173 class GLESImageApi : public ImageApi, private glu::CallLogWrapper
174 {
175 public:
176 	class GLESAction : public Action
177 	{
178 	public:
179 		bool				invoke					(ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
180 		virtual bool		invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0;
181 	};
182 
183 	class Create : public GLESAction
184 	{
185 	public:
Create(MovePtr<ImageSource> imgSource,deUint32 numLayers=1u)186 								Create					(MovePtr<ImageSource> imgSource, deUint32 numLayers = 1u) : m_imgSource(imgSource), m_numLayers(numLayers) {}
getRequiredExtension(void) const187 		string					getRequiredExtension	(void) const { return m_imgSource->getRequiredExtension(); }
188 		bool					invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
getNumLayers(void) const189 		deUint32				getNumLayers			(void) const { return m_numLayers; }
getEffectiveFormat(void) const190 		glw::GLenum				getEffectiveFormat		(void) const { return m_imgSource->getEffectiveFormat(); }
isYUVFormatImage(void) const191 		bool					isYUVFormatImage		(void) const { return m_imgSource->isYUVFormatImage(); }
192 	private:
193 		UniquePtr<ImageSource>	m_imgSource;
194 		deUint32				m_numLayers;
195 	};
196 
197 	class Render : public GLESAction
198 	{
199 	public:
getRequiredExtension(void) const200 		virtual string			getRequiredExtension	(void) const { return "GL_OES_EGL_image"; }
201 	};
202 
203 	class RenderTexture2D				: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
204 	class RenderTextureCubemap			: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
205 	class RenderReadPixelsRenderbuffer	: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
206 	class RenderDepthbuffer				: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
207 	class RenderStencilbuffer			: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
208 	class RenderTryAll					: public Render { public: bool invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override; };
209 
210 	class RenderTexture2DArray : public Render
211 	{
212 		public:
213 			bool	invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
getRequiredExtension(void) const214 			string	getRequiredExtension	(void) const override { return "GL_EXT_EGL_image_array"; }
215 	};
216 
217 	class RenderExternalTexture			: public Render
218 	{
219 		public:
220 			bool	invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
getRequiredExtension(void) const221 			string	getRequiredExtension	(void) const override { return "GL_OES_EGL_image_external"; }
222 	};
223 
224 	class RenderExternalTextureSamplerArray	: public Render
225 	{
226 		public:
227 			bool	invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
getRequiredExtension(void) const228 			string	getRequiredExtension	(void) const override { return "GL_OES_EGL_image_external"; }
229 	};
230 	class RenderYUVTexture			: public Render
231 	{
232 		public:
233 			bool	invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
getRequiredExtension(void) const234 			string	getRequiredExtension	(void) const override { return "GL_EXT_YUV_target"; }
235 	};
236 	class RenderSampleTexture2DArray			         : public RenderTexture2DArray
237 	{
238 		public:
239 			bool	invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const override;
getRequiredExtension(void) const240 			string	getRequiredExtension	(void) const override { return "GL_EXT_EGL_image_array"; }
241 	};
242 	class Modify : public GLESAction
243 	{
244 	public:
getRequiredExtension(void) const245 		string				getRequiredExtension	(void) const { return "GL_OES_EGL_image"; }
246 	};
247 
248 	class ModifyTexSubImage : public Modify
249 	{
250 	public:
ModifyTexSubImage(GLenum format,GLenum type)251 							ModifyTexSubImage		(GLenum format, GLenum type) : m_format(format), m_type(type) {}
252 		bool				invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
getFormat(void) const253 		GLenum				getFormat				(void) const { return m_format; }
getType(void) const254 		GLenum				getType					(void) const { return m_type; }
255 
256 	private:
257 		GLenum				m_format;
258 		GLenum				m_type;
259 	};
260 
261 	class ModifyRenderbuffer : public Modify
262 	{
263 	public:
264 		bool				invokeGLES				(GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
265 
266 	protected:
267 		virtual void		initializeRbo			(GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0;
268 	};
269 
270 	class ModifyRenderbufferClearColor : public ModifyRenderbuffer
271 	{
272 	public:
ModifyRenderbufferClearColor(tcu::Vec4 color)273 					ModifyRenderbufferClearColor	(tcu::Vec4 color) : m_color(color) {}
274 
275 	protected:
276 		void		initializeRbo					(GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
277 
278 		tcu::Vec4	m_color;
279 	};
280 
281 	class ModifyRenderbufferClearDepth : public ModifyRenderbuffer
282 	{
283 	public:
ModifyRenderbufferClearDepth(GLfloat depth)284 					ModifyRenderbufferClearDepth	(GLfloat depth) : m_depth(depth) {}
285 
286 	protected:
287 		void		initializeRbo					(GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
288 
289 		GLfloat		m_depth;
290 	};
291 
292 	class ModifyRenderbufferClearStencil : public ModifyRenderbuffer
293 	{
294 	public:
ModifyRenderbufferClearStencil(GLint stencil)295 					ModifyRenderbufferClearStencil	(GLint stencil) : m_stencil(stencil) {}
296 
297 	protected:
298 		void		initializeRbo					(GLESImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
299 
300 		GLint		m_stencil;
301 	};
302 
303 					GLESImageApi					(const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config, EGLint apiVersion);
304 					~GLESImageApi					(void);
305 
306 private:
307 	EGLContext					m_context;
308 	const glw::Functions&		m_gl;
309 
310 	MovePtr<UniqueImage>		createImage			(const ImageSource& source, const ClientBuffer& buffer) const;
311 };
312 
GLESImageApi(const Library & egl,const glw::Functions & gl,int contextId,tcu::TestLog & log,EGLDisplay display,EGLSurface surface,EGLConfig config,EGLint apiVersion)313 GLESImageApi::GLESImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config, EGLint apiVersion)
314 	: ImageApi				(egl, contextId, display, surface)
315 	, glu::CallLogWrapper	(gl, log)
316 	, m_context				(DE_NULL)
317 	, m_gl					(gl)
318 {
319 	const EGLint attriblist[] =
320 	{
321 		EGL_CONTEXT_CLIENT_VERSION, apiVersion,
322 		EGL_NONE
323 	};
324 
325 	EGLint configId = -1;
326 	EGLU_CHECK_CALL(m_egl, getConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId));
327 	getLog() << tcu::TestLog::Message << "Creating gles" << apiVersion << " context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
328 	egl.bindAPI(EGL_OPENGL_ES_API);
329 	m_context = m_egl.createContext(m_display, config, EGL_NO_CONTEXT, attriblist);
330 	EGLU_CHECK_MSG(m_egl, "Failed to create GLES context");
331 
332 	egl.makeCurrent(display, m_surface, m_surface, m_context);
333 	EGLU_CHECK_MSG(m_egl, "Failed to make context current");
334 }
335 
~GLESImageApi(void)336 GLESImageApi::~GLESImageApi (void)
337 {
338 	m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
339 	m_egl.destroyContext(m_display, m_context);
340 }
341 
invoke(ImageApi & api,MovePtr<UniqueImage> & image,tcu::Texture2D & ref) const342 bool GLESImageApi::GLESAction::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
343 {
344 	GLESImageApi& glesApi = dynamic_cast<GLESImageApi&>(api);
345 
346 	glesApi.m_egl.makeCurrent(glesApi.m_display, glesApi.m_surface, glesApi.m_surface, glesApi.m_context);
347 	return invokeGLES(glesApi, image, ref);
348 }
349 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & image,tcu::Texture2D & ref) const350 bool GLESImageApi::Create::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
351 {
352 	de::UniquePtr<ClientBuffer>	buffer	(m_imgSource->createBuffer(api.m_egl, api.m_gl, &ref));
353 
354 	GLU_CHECK_GLW_CALL(api.m_gl, finish());
355 
356 	image = api.createImage(*m_imgSource, *buffer);
357 	return true;
358 }
359 
createImage(const ImageSource & source,const ClientBuffer & buffer) const360 MovePtr<UniqueImage> GLESImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const
361 {
362 	const EGLImageKHR image = source.createImage(m_egl, m_display, m_context, buffer.get());
363 	return MovePtr<UniqueImage>(new UniqueImage(m_egl, m_display, image));
364 }
365 
imageTargetTexture2D(const Library & egl,const glw::Functions & gl,GLeglImageOES img)366 static void imageTargetTexture2D (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
367 {
368 	gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img);
369 	{
370 		const GLenum error = gl.getError();
371 
372 		if (error == GL_INVALID_OPERATION)
373 			TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported");
374 
375 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
376 		EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
377 	}
378 }
379 
imageTargetExternalTexture(const Library & egl,const glw::Functions & gl,GLeglImageOES img)380 static void imageTargetExternalTexture (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
381 {
382 	gl.eglImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, img);
383 	{
384 		const GLenum error = gl.getError();
385 
386 		if (error == GL_INVALID_OPERATION)
387 			TCU_THROW(NotSupportedError, "Creating external texture from EGLImage type not supported");
388 
389 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
390 		EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
391 	}
392 }
393 
imageTargetTexture2DArray(const Library & egl,const glw::Functions & gl,GLeglImageOES img)394 static void imageTargetTexture2DArray (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
395 {
396 	gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D_ARRAY, img);
397 	{
398 		const GLenum error = gl.getError();
399 
400 		if (error == GL_INVALID_OPERATION)
401 			TCU_THROW(NotSupportedError, "Creating texture2D array from EGLImage type not supported");
402 
403 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
404 		EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
405 	}
406 }
407 
imageTargetRenderbuffer(const Library & egl,const glw::Functions & gl,GLeglImageOES img)408 static void imageTargetRenderbuffer (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
409 {
410 	gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img);
411 	{
412 		const GLenum error = gl.getError();
413 
414 		if (error == GL_INVALID_OPERATION)
415 			TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported");
416 
417 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()");
418 		EGLU_CHECK_MSG(egl, "glEGLImageTargetRenderbufferStorageOES()");
419 	}
420 }
421 
framebufferRenderbuffer(const glw::Functions & gl,GLenum attachment,GLuint rbo)422 static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo)
423 {
424 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo));
425 	TCU_CHECK_AND_THROW(NotSupportedError,
426 						gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
427 						("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str());
428 }
429 
getSupportedExtensions(tcu::TestLog & log,const Library & egl,const EGLDisplay dpy,const glw::Functions gl)430 static set<string> getSupportedExtensions (tcu::TestLog& log, const Library& egl, const EGLDisplay dpy, const glw::Functions gl)
431 {
432 	set<string>				exts;
433 	const vector<string>	glExts	= de::splitString((const char*) gl.getString(GL_EXTENSIONS));
434 	const vector<string>	eglExts	= eglu::getDisplayExtensions(egl, dpy);
435 
436 	exts.insert(glExts.begin(), glExts.end());
437 	exts.insert(eglExts.begin(), eglExts.end());
438 
439 	if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5))
440 	{
441 		// EGL 1.5 has built-in support for EGLImage and GL sources
442 		exts.insert("EGL_KHR_image_base");
443 		exts.insert("EGL_KHR_gl_texture_2D_image");
444 		exts.insert("EGL_KHR_gl_texture_cubemap_image");
445 		exts.insert("EGL_KHR_gl_renderbuffer_image");
446 	}
447 
448 	if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
449 	{
450 		log << tcu::TestLog::Message
451 			<< "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
452 			<< "One should be supported."
453 			<< tcu::TestLog::EndMessage;
454 		TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
455 	}
456 
457 	return exts;
458 }
459 
460 static const float squareTriangleCoords[] =
461 {
462 	-1.0, -1.0,
463 	1.0, -1.0,
464 	1.0,  1.0,
465 
466 	1.0,  1.0,
467 	-1.0,  1.0,
468 	-1.0, -1.0
469 };
470 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const471 bool GLESImageApi::RenderTexture2D::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
472 {
473 	const glw::Functions&	gl		= api.m_gl;
474 	tcu::TestLog&			log		= api.getLog();
475 	Texture					srcTex	(gl);
476 
477 	// Branch only taken in TryAll case
478 	if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
479 		throw IllegalRendererException(); // Skip, GLES does not support sampling depth textures
480 	if (reference.getFormat().order == tcu::TextureFormat::S)
481 		throw IllegalRendererException(); // Skip, GLES does not support sampling stencil textures
482 
483 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
484 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
485 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
486 	gl.disable(GL_DEPTH_TEST);
487 
488 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage;
489 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
490 
491 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
492 	imageTargetTexture2D(api.m_egl, gl, **img);
493 
494 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
495 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
496 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
497 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
498 
499 	const char* const vertexShader =
500 		"attribute highp vec2 a_coord;\n"
501 		"varying mediump vec2 v_texCoord;\n"
502 		"void main(void) {\n"
503 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
504 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
505 		"}\n";
506 
507 	const char* const fragmentShader =
508 		"varying mediump vec2 v_texCoord;\n"
509 		"uniform sampler2D u_sampler;\n"
510 		"void main(void) {\n"
511 		"\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
512 		"\tgl_FragColor = vec4(texColor);\n"
513 		"}";
514 
515 	Program program(gl, vertexShader, fragmentShader);
516 	TCU_CHECK(program.isOk());
517 
518 	GLuint glProgram = program.getProgram();
519 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
520 
521 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
522 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
523 
524 	GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
525 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
526 
527 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
528 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
529 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
530 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
531 
532 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
533 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
534 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
535 
536 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
537 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
538 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
539 
540 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
541 
542 	float	threshold	= 0.05f;
543 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
544 
545 	return match;
546 }
547 
548 // Renders using a single layer from a texture array.
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const549 bool GLESImageApi::RenderTexture2DArray::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
550 {
551 	const glw::Functions&	gl		= api.m_gl;
552 	tcu::TestLog&			log		= api.getLog();
553 	Texture					srcTex	(gl);
554 
555 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
556 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
557 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
558 	gl.disable(GL_DEPTH_TEST);
559 
560 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D_ARRAY in context: " << api.m_contextId << tcu::TestLog::EndMessage;
561 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
562 
563 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTex));
564 	imageTargetTexture2DArray(api.m_egl, gl, **img);
565 
566 	glu::TransferFormat transferFormat = glu::getTransferFormat(reference.getFormat());
567 	// Initializes layer 1.
568 	GLU_CHECK_GLW_CALL(gl, texSubImage3D(GL_TEXTURE_2D_ARRAY,
569 			0,										// Mipmap level
570             0,										// X offset
571 			0,										// Y offset
572 			1,										// Z offset (layer)
573 			reference.getWidth(),					// Width
574 			reference.getHeight(),					// Height
575 			1u,										// Depth
576 			transferFormat.format,					// Format
577 			transferFormat.dataType,				// Type
578 			reference.getLevel(0).getDataPtr()));	// Pixel data
579 
580 
581 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
582 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
583 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
584 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
585 
586 	const char* const vertexShader =
587 	"#version 320 es\n"
588 	"precision highp int;\n"
589 	"precision highp float;\n"
590 	"layout(location = 0) in vec2 pos_in;\n"
591 	"layout(location = 0) out vec2 texcoord_out;\n"
592 	"void main()\n"
593 	"{\n"
594 	"    gl_Position = vec4(pos_in, -0.1, 1.0);\n"
595 	"    texcoord_out = vec2((pos_in.x + 1.0) * 0.5, (pos_in.y + 1.0) * 0.5);\n"
596 	"}\n";
597 
598 	const char* const fragmentShader =
599 	"#version 320 es\n"
600 	"precision highp int;\n"
601 	"precision highp float;\n"
602 	"layout(location = 0) in vec2 texcoords_in;\n"
603 	"layout(location = 0) out vec4 color_out;\n"
604 	"uniform layout(binding=0) highp sampler2DArray tex_sampler;\n"
605 	"void main()\n"
606 	"{\n"
607 	// Samples layer 1.
608 	"    color_out = texture(tex_sampler, vec3(texcoords_in, 1));\n"
609 	"}\n";
610 
611 	Program program(gl, vertexShader, fragmentShader);
612 
613 	if (!program.isOk())
614 	{
615 		log << tcu::TestLog::Message << "Shader build failed.\n"
616 			<< "Vertex: " << program.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
617 			<< vertexShader << "\n"
618 			<< "Fragment: " << program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
619 			<< fragmentShader << "\n"
620 			<< "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
621 	}
622 
623 	TCU_CHECK(program.isOk());
624 
625 	GLuint glProgram = program.getProgram();
626 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
627 
628 	GLuint coordLoc = gl.getAttribLocation(glProgram, "pos_in");
629 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute pos_in");
630 
631 	GLuint samplerLoc = gl.getUniformLocation(glProgram, "tex_sampler");
632 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform tex_sampler");
633 
634 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTex));
635 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
636 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
637 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
638 
639 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
640 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
641 
642 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
643 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
644 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
645 
646 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
647 
648 	float	threshold	= 0.05f;
649 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
650 
651 	return match;
652 }
653 
654 //Texture2D array can be both rendered and sampled as a texture.
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const655 bool GLESImageApi::RenderSampleTexture2DArray::invokeGLES(GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
656 {
657 	const glw::Functions&	gl		= api.m_gl;
658 	tcu::TestLog&			log		= api.getLog();
659 	Texture					srcTex	(gl);
660 	Texture					srcTexArray	(gl);
661 
662 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
663 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
664 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
665 	gl.disable(GL_DEPTH_TEST);
666 
667 	log << tcu::TestLog::Message << "Rendering and sampling EGLImage as GL_TEXTURE_2D_ARRAY in context: " << api.m_contextId << tcu::TestLog::EndMessage;
668 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
669 
670 	glu::TransferFormat transferFormat = glu::getTransferFormat(reference.getFormat());
671 	deUint32 internalForat = glu::getInternalFormat(reference.getFormat());
672 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
673 	GLU_CHECK_GLW_CALL(gl, texImage2D(GL_TEXTURE_2D,
674 			0,										// Level
675 			internalForat,							// Internal format
676 			reference.getWidth(),					// Width
677 			reference.getHeight(),					// Height
678 			0,										// Border
679 			transferFormat.format,					// Format
680 			transferFormat.dataType,				// Type
681 			reference.getLevel(0).getDataPtr()));	// Pixel data
682 
683 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
684 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
685 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
686 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
687 
688 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTexArray));
689 	imageTargetTexture2DArray(api.m_egl, gl, **img);
690 
691 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
692 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
693 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
694 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
695 
696 	/* Create FBO and attach source texture layer 0 */
697 	glu::Framebuffer		fbo(gl);
698 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *fbo));
699 	GLU_CHECK_GLW_CALL(gl, framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *srcTexArray, 0, 0));
700 
701 	const char* const vertexShader0 =
702 		"attribute highp vec2 a_coord;\n"
703 		"varying mediump vec2 v_texCoord;\n"
704 		"void main(void) {\n"
705 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
706 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
707 		"}\n";
708 
709 	const char* const fragmentShader0 =
710 		"varying mediump vec2 v_texCoord;\n"
711 		"uniform sampler2D u_sampler;\n"
712 		"void main(void) {\n"
713 		"\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
714 		"\tgl_FragColor = vec4(texColor);\n"
715 		"}";
716 
717 	Program program0(gl, vertexShader0, fragmentShader0);
718 	if (!program0.isOk())
719 	{
720 		log << tcu::TestLog::Message << "Shader build failed.\n"
721 			<< "Vertex: " << program0.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
722 			<< vertexShader0 << "\n"
723 			<< "Fragment: " << program0.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
724 			<< fragmentShader0 << "\n"
725 			<< "Program: " << program0.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
726 	}
727 
728 	TCU_CHECK(program0.isOk());
729 
730 	GLuint glProgram0 = program0.getProgram();
731 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram0));
732 
733 	GLuint coordLoc = gl.getAttribLocation(glProgram0, "a_coord");
734 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
735 	GLuint samplerLoc = gl.getUniformLocation(glProgram0, "u_sampler");
736 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
737 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
738 
739 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
740 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
741 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
742 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
743 
744 	tcu::Surface refSurface0	(reference.getWidth(), reference.getHeight());
745 	tcu::Surface screen0		(reference.getWidth(), reference.getHeight());
746 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen0.getWidth(), screen0.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen0.getAccess().getDataPtr()));
747 
748 	tcu::copy(refSurface0.getAccess(), reference.getLevel(0));
749 
750 	float	threshold	= 0.01f;
751 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface0, screen0, threshold, tcu::COMPARE_LOG_RESULT);
752 
753 	if (match == false)
754 		return match;
755 
756 	/* Bind texture to FBO. */
757 	GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *srcTex, 0));
758 
759 	const char* const vertexShader =
760 		"#version 320 es\n"
761 		"precision highp int;\n"
762 		"precision highp float;\n"
763 		"layout(location = 0) in vec2 pos_in;\n"
764 		"layout(location = 0) out vec2 texcoord_out;\n"
765 		"void main()\n"
766 		"{\n"
767 		"    gl_Position = vec4(pos_in, -0.1, 1.0);\n"
768 		"    texcoord_out = vec2((pos_in.x + 1.0) * 0.5, (pos_in.y + 1.0) * 0.5);\n"
769 		"}\n";
770 
771 	const char* const fragmentShader =
772 		"#version 320 es\n"
773 		"precision highp int;\n"
774 		"precision highp float;\n"
775 		"layout(location = 0) in vec2 texcoords_in;\n"
776 		"layout(location = 0) out vec4 color_out;\n"
777 		"uniform layout(binding=0) highp sampler2DArray tex_sampler;\n"
778 		"void main()\n"
779 		"{\n"
780 		// Samples layer 0.
781 		"    color_out = texture(tex_sampler, vec3(texcoords_in, 0));\n"
782 		"}\n";
783 
784 	Program program(gl, vertexShader, fragmentShader);
785 
786 	if (!program.isOk())
787 	{
788 		log << tcu::TestLog::Message << "Shader build failed.\n"
789 			<< "Vertex: " << program.getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog << "\n"
790 			<< vertexShader << "\n"
791 			<< "Fragment: " << program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog << "\n"
792 			<< fragmentShader << "\n"
793 			<< "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
794 	}
795 
796 	TCU_CHECK(program.isOk());
797 
798 	GLuint glProgram = program.getProgram();
799 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
800 
801 	coordLoc = gl.getAttribLocation(glProgram, "pos_in");
802 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute pos_in");
803 
804 	samplerLoc = gl.getUniformLocation(glProgram, "tex_sampler");
805 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform tex_sampler");
806 
807 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D_ARRAY, *srcTexArray));
808 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
809 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
810 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
811 
812 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
813 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
814 	GLU_CHECK_GLW_CALL(gl, finish());
815 
816 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
817 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
818 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
819 
820 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
821 
822 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
823 
824 	threshold	= 0.01f;
825 	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
826 	return match;
827 }
828 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const829 bool GLESImageApi::RenderExternalTexture::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
830 {
831 	const glw::Functions&	gl		= api.m_gl;
832 	tcu::TestLog&			log		= api.getLog();
833 	Texture					srcTex	(gl);
834 
835 	// Branch only taken in TryAll case
836 	if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
837 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
838 	if (reference.getFormat().order == tcu::TextureFormat::S)
839 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
840 
841 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
842 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
843 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
844 	gl.disable(GL_DEPTH_TEST);
845 
846 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES in context: " << api.m_contextId << tcu::TestLog::EndMessage;
847 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
848 
849 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
850 	imageTargetExternalTexture(api.m_egl, gl, **img);
851 
852 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
853 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
854 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
855 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
856 
857 	const char* const vertexShader =
858 		"attribute highp vec2 a_coord;\n"
859 		"varying mediump vec2 v_texCoord;\n"
860 		"void main(void) {\n"
861 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
862 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
863 		"}\n";
864 
865 	const char* const fragmentShader =
866 		"#extension GL_OES_EGL_image_external : require\n"
867 		"varying mediump vec2 v_texCoord;\n"
868 		"uniform samplerExternalOES u_sampler;\n"
869 		"void main(void) {\n"
870 		"\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
871 		"\tgl_FragColor = vec4(texColor);\n"
872 		"}";
873 
874 	Program program(gl, vertexShader, fragmentShader);
875 	TCU_CHECK(program.isOk());
876 
877 	GLuint glProgram = program.getProgram();
878 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
879 
880 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
881 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
882 
883 	GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
884 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
885 
886 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
887 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
888 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
889 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
890 
891 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
892 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
893 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
894 
895 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
896 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
897 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
898 
899 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
900 
901 	float	threshold	= 0.05f;
902 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
903 
904 	return match;
905 }
906 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const907 bool GLESImageApi::RenderYUVTexture::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
908 {
909 	const glw::Functions&	gl		= api.m_gl;
910 	tcu::TestLog&			log		= api.getLog();
911 	Texture					srcTex	(gl);
912 
913 	DE_ASSERT(reference.isYUVTextureUsed());
914 
915 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
916 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
917 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
918 	gl.disable(GL_DEPTH_TEST);
919 
920 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES in context: " << api.m_contextId << tcu::TestLog::EndMessage;
921 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
922 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
923 	imageTargetExternalTexture(api.m_egl, gl, **img);
924 	{
925 		/* init YUV texture with glClear, clear color value in YUV color space */
926 		glu::Framebuffer		fbo(gl);
927 		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *fbo));
928 		GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,  GL_TEXTURE_EXTERNAL_OES,*srcTex, 0));
929 		const tcu::Vec4 colorValues[] =
930 		{
931 			tcu::Vec4(0.9f, 0.5f, 0.65f, 1.0f),
932 			tcu::Vec4(0.5f, 0.7f, 0.65f, 1.0f),
933 			tcu::Vec4(0.2f, 0.5f, 0.65f, 1.0f),
934 			tcu::Vec4(0.3f, 0.1f, 0.5f, 1.0f),
935 			tcu::Vec4(0.8f, 0.2f, 0.3f, 1.0f),
936 			tcu::Vec4(0.9f, 0.4f, 0.8f, 1.0f),
937 		};
938 		tcu::clear(reference.getLevel(0), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
939 		GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
940 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorValues); ++ndx)
941 		{
942 			const tcu::IVec2	size	= tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)reference.getWidth() / float(DE_LENGTH_OF_ARRAY(colorValues)))),
943 													(int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)reference.getHeight() / float(DE_LENGTH_OF_ARRAY(colorValues)))));
944 
945 			if (size.x() == 0 || size.y() == 0)
946 				break;
947 			GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
948 
949 			GLU_CHECK_GLW_CALL(gl, clearColor(colorValues[ndx].x(), colorValues[ndx].y(), colorValues[ndx].z(), colorValues[ndx].w()));
950 			GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
951 			GLU_CHECK_GLW_CALL(gl, finish());
952 			char tmp[4]={"0"};
953 			GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)tmp));
954 			tcu::clear(tcu::getSubregion(reference.getLevel(0), 0, 0, size.x(), size.y()), tcu::Vec4(tmp[0]/(255.0f), tmp[1]/(255.0f), tmp[2]/(255.0f), tmp[3]/(255.0f)));
955 		}
956 		GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
957 		GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, 0, 0));
958 		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
959 		GLU_CHECK_GLW_CALL(gl, finish());
960 	}
961 
962 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
963 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
964 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
965 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
966 
967 	const char* const vertexShader =
968 		"attribute highp vec2 a_coord;\n"
969 		"varying mediump vec2 v_texCoord;\n"
970 		"void main(void) {\n"
971 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
972 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
973 		"}\n";
974 
975 	const char* const fragmentShader =
976 		"#extension GL_OES_EGL_image_external : require\n"
977 		"varying mediump vec2 v_texCoord;\n"
978 		"uniform samplerExternalOES u_sampler;\n"
979 		"void main(void) {\n"
980 		"\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
981 		"\tgl_FragColor = vec4(texColor);\n"
982 		"}";
983 
984 	Program program(gl, vertexShader, fragmentShader);
985 	TCU_CHECK(program.isOk());
986 
987 	GLuint glProgram = program.getProgram();
988 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
989 
990 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
991 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
992 
993 	GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
994 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
995 
996 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
997 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
998 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
999 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1000 
1001 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1002 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1003 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1004 
1005 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
1006 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
1007 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1008 
1009 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1010 
1011 	float	threshold	= 0.05f;
1012 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
1013 
1014 	return match;
1015 }
1016 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1017 bool GLESImageApi::RenderExternalTextureSamplerArray::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1018 {
1019 	const glw::Functions&	gl		= api.m_gl;
1020 	tcu::TestLog&			log		= api.getLog();
1021 	Texture					srcTex	(gl);
1022 
1023 	// Branch only taken in TryAll case
1024 	if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
1025 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
1026 	if (reference.getFormat().order == tcu::TextureFormat::S)
1027 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
1028 
1029 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
1030 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
1031 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1032 	gl.disable(GL_DEPTH_TEST);
1033 
1034 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_EXTERNAL_OES using sampler array in context: " << api.m_contextId << tcu::TestLog::EndMessage;
1035 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
1036 
1037 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
1038 	imageTargetExternalTexture(api.m_egl, gl, **img);
1039 
1040 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1041 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1042 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1043 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1044 
1045 	// Texture not associated with an external texture will return (0, 0, 0, 1) when sampled.
1046 	GLuint	emptyTex;
1047 	gl.genTextures(1, &emptyTex);
1048 	gl.activeTexture(GL_TEXTURE1);
1049 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, emptyTex));
1050 
1051 	const char* const vertexShader =
1052 		"attribute highp vec2 a_coord;\n"
1053 		"varying mediump vec2 v_texCoord;\n"
1054 		"void main(void) {\n"
1055 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
1056 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
1057 		"}\n";
1058 
1059 	const char* const fragmentShader =
1060 		"#extension GL_OES_EGL_image_external : require\n"
1061 		"varying mediump vec2 v_texCoord;\n"
1062 		"uniform samplerExternalOES u_sampler[4];\n"
1063 		"void main(void) {\n"
1064 		"\tmediump vec4 texColor = texture2D(u_sampler[2], v_texCoord);\n"
1065 		"\t//These will sample (0, 0, 0, 1) and should not affect the results.\n"
1066 		"\ttexColor += texture2D(u_sampler[0], v_texCoord) - vec4(0, 0, 0, 1);\n"
1067 		"\ttexColor += texture2D(u_sampler[1], v_texCoord) - vec4(0, 0, 0, 1);\n"
1068 		"\ttexColor += texture2D(u_sampler[3], v_texCoord) - vec4(0, 0, 0, 1);\n"
1069 		"\tgl_FragColor = vec4(texColor);\n"
1070 		"}";
1071 
1072 	Program program(gl, vertexShader, fragmentShader);
1073 	TCU_CHECK(program.isOk());
1074 
1075 	GLuint glProgram = program.getProgram();
1076 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1077 
1078 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1079 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1080 
1081 	GLuint samplerLoc0 = gl.getUniformLocation(glProgram, "u_sampler[0]");
1082 	TCU_CHECK_MSG((int)samplerLoc0 != (int)-1, "Couldn't find uniform u_sampler[0]");
1083 	GLuint samplerLoc1 = gl.getUniformLocation(glProgram, "u_sampler[1]");
1084 	TCU_CHECK_MSG((int)samplerLoc1 != (int)-1, "Couldn't find uniform u_sampler[1]");
1085 	GLuint samplerLoc2 = gl.getUniformLocation(glProgram, "u_sampler[2]");
1086 	TCU_CHECK_MSG((int)samplerLoc2 != (int)-1, "Couldn't find uniform u_sampler[2]");
1087 	GLuint samplerLoc3 = gl.getUniformLocation(glProgram, "u_sampler[3]");
1088 	TCU_CHECK_MSG((int)samplerLoc3 != (int)-1, "Couldn't find uniform u_sampler[3]");
1089 
1090 	gl.activeTexture(GL_TEXTURE0);
1091 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, *srcTex));
1092 	// One sampler reads a gradient and others opaque black.
1093 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc0, 1));
1094 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc1, 1));
1095 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc2, 0));
1096 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc3, 1));
1097 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1098 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1099 
1100 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1101 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1102 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1103 	gl.activeTexture(GL_TEXTURE1);
1104 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_EXTERNAL_OES, 0));
1105 	gl.deleteTextures(1, &emptyTex);
1106 	gl.activeTexture(GL_TEXTURE0);
1107 
1108 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
1109 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
1110 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1111 
1112 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1113 
1114 	float	threshold	= 0.05f;
1115 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
1116 
1117 	return match;
1118 }
1119 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1120 bool GLESImageApi::RenderDepthbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1121 {
1122 	const glw::Functions&	gl					= api.m_gl;
1123 	tcu::TestLog&			log					= api.getLog();
1124 	Framebuffer				framebuffer			(gl);
1125 	Renderbuffer			renderbufferColor	(gl);
1126 	Renderbuffer			renderbufferDepth	(gl);
1127 	const tcu::RGBA			compareThreshold	(32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
1128 
1129 	// Branch only taken in TryAll case
1130 	if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::D)
1131 		throw IllegalRendererException(); // Skip, interpreting non-depth data as depth data is not meaningful
1132 
1133 	log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
1134 
1135 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1136 
1137 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
1138 	GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
1139 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
1140 
1141 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth));
1142 	imageTargetRenderbuffer(api.m_egl, gl, **img);
1143 	framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth);
1144 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1145 
1146 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1147 
1148 	// Render
1149 	const char* vertexShader =
1150 		"attribute highp vec2 a_coord;\n"
1151 		"uniform highp float u_depth;\n"
1152 		"void main(void) {\n"
1153 		"\tgl_Position = vec4(a_coord, u_depth, 1.0);\n"
1154 		"}\n";
1155 
1156 	const char* fragmentShader =
1157 		"uniform mediump vec4 u_color;\n"
1158 		"void main(void) {\n"
1159 		"\tgl_FragColor = u_color;\n"
1160 		"}";
1161 
1162 	Program program(gl, vertexShader, fragmentShader);
1163 	TCU_CHECK(program.isOk());
1164 
1165 	GLuint glProgram = program.getProgram();
1166 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1167 
1168 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1169 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1170 
1171 	GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
1172 	TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
1173 
1174 	GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth");
1175 	TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth");
1176 
1177 	GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
1178 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1179 
1180 	tcu::Vec4 depthLevelColors[] = {
1181 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1182 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1183 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1184 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1185 		tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1186 
1187 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1188 		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
1189 		tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
1190 		tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
1191 		tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
1192 	};
1193 
1194 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1195 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1196 
1197 	GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST));
1198 	GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS));
1199 	GLU_CHECK_GLW_CALL(gl, depthMask(GL_FALSE));
1200 
1201 	for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
1202 	{
1203 		const tcu::Vec4	color		= depthLevelColors[level];
1204 		const float		clipDepth	= ((float)(level + 1) * 0.1f) * 2.0f - 1.0f; // depth in clip coords
1205 
1206 		GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
1207 		GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, clipDepth));
1208 		GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1209 	}
1210 
1211 	GLU_CHECK_GLW_CALL(gl, depthMask(GL_TRUE));
1212 	GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST));
1213 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1214 
1215 	const ConstPixelBufferAccess&	refAccess		= reference.getLevel(0);
1216 	tcu::Surface					screen			(reference.getWidth(), reference.getHeight());
1217 	tcu::Surface					referenceScreen	(reference.getWidth(), reference.getHeight());
1218 
1219 	gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
1220 
1221 	for (int y = 0; y < reference.getHeight(); y++)
1222 	{
1223 		for (int x = 0; x < reference.getWidth(); x++)
1224 		{
1225 			tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
1226 
1227 			for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
1228 			{
1229 				if ((float)(level + 1) * 0.1f < refAccess.getPixDepth(x, y))
1230 					result = depthLevelColors[level];
1231 			}
1232 
1233 			referenceScreen.getAccess().setPixel(result, x, y);
1234 		}
1235 	}
1236 
1237 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1238 	GLU_CHECK_GLW_CALL(gl, finish());
1239 
1240 	return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
1241 }
1242 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1243 bool GLESImageApi::RenderStencilbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1244 {
1245 	// Branch only taken in TryAll case
1246 	if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::S)
1247 		throw IllegalRendererException(); // Skip, interpreting non-stencil data as stencil data is not meaningful
1248 
1249 	const glw::Functions&	gl					= api.m_gl;
1250 	tcu::TestLog&			log					= api.getLog();
1251 	Framebuffer				framebuffer			(gl);
1252 	Renderbuffer			renderbufferColor	(gl);
1253 	Renderbuffer			renderbufferStencil (gl);
1254 	const tcu::RGBA			compareThreshold	(32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
1255 	const deUint32			numStencilBits		= tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(reference.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
1256 	const deUint32			maxStencil			= deBitMask32(0, numStencilBits);
1257 
1258 	log << tcu::TestLog::Message << "Rendering with stencil buffer" << tcu::TestLog::EndMessage;
1259 
1260 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1261 
1262 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
1263 	GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
1264 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
1265 
1266 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferStencil));
1267 	imageTargetRenderbuffer(api.m_egl, gl, **img);
1268 	framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, *renderbufferStencil);
1269 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1270 
1271 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1272 
1273 	// Render
1274 	const char* vertexShader =
1275 		"attribute highp vec2 a_coord;\n"
1276 		"void main(void) {\n"
1277 		"\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
1278 		"}\n";
1279 
1280 	const char* fragmentShader =
1281 		"uniform mediump vec4 u_color;\n"
1282 		"void main(void) {\n"
1283 		"\tgl_FragColor = u_color;\n"
1284 		"}";
1285 
1286 	Program program(gl, vertexShader, fragmentShader);
1287 	TCU_CHECK(program.isOk());
1288 
1289 	GLuint glProgram = program.getProgram();
1290 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
1291 
1292 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
1293 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
1294 
1295 	GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
1296 	TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
1297 
1298 	GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
1299 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1300 
1301 	tcu::Vec4 stencilLevelColors[] = {
1302 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1303 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1304 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1305 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1306 		tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1307 
1308 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1309 		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
1310 		tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
1311 		tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
1312 		tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
1313 	};
1314 
1315 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
1316 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
1317 
1318 	GLU_CHECK_GLW_CALL(gl, enable(GL_STENCIL_TEST));
1319 	GLU_CHECK_GLW_CALL(gl, stencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1320 
1321 	for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
1322 	{
1323 		const tcu::Vec4	color	= stencilLevelColors[level];
1324 		const int		stencil	= (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
1325 
1326 		GLU_CHECK_GLW_CALL(gl, stencilFunc(GL_LESS, stencil, 0xFFFFFFFFu));
1327 		GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
1328 		GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
1329 	}
1330 
1331 	GLU_CHECK_GLW_CALL(gl, disable(GL_STENCIL_TEST));
1332 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
1333 
1334 	const ConstPixelBufferAccess&	refAccess		= reference.getLevel(0);
1335 	tcu::Surface					screen			(reference.getWidth(), reference.getHeight());
1336 	tcu::Surface					referenceScreen	(reference.getWidth(), reference.getHeight());
1337 
1338 	gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
1339 
1340 	for (int y = 0; y < reference.getHeight(); y++)
1341 	for (int x = 0; x < reference.getWidth(); x++)
1342 	{
1343 		tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
1344 
1345 		for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
1346 		{
1347 			const int levelStencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
1348 			if (levelStencil < refAccess.getPixStencil(x, y))
1349 				result = stencilLevelColors[level];
1350 		}
1351 
1352 		referenceScreen.getAccess().setPixel(result, x, y);
1353 	}
1354 
1355 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1356 	GLU_CHECK_GLW_CALL(gl, finish());
1357 
1358 	return tcu::pixelThresholdCompare(log, "StencilResult", "Result from rendering with stencil buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
1359 }
1360 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1361 bool GLESImageApi::RenderReadPixelsRenderbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1362 {
1363 	switch (glu::getInternalFormat(reference.getFormat()))
1364 	{
1365 		case GL_RGBA4:
1366 		case GL_RGB5_A1:
1367 		case GL_RGB565:
1368 			break;
1369 		default:
1370 			// Skip, not in the list of allowed render buffer formats for GLES.
1371 			throw tcu::NotSupportedError("Image format not allowed for glReadPixels.");
1372 	}
1373 
1374 	const glw::Functions&	gl				= api.m_gl;
1375 	const tcu::IVec4		bitDepth		= tcu::getTextureFormatMantissaBitDepth(reference.getFormat());
1376 	const tcu::IVec4		threshold		(2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth)));
1377 	const tcu::RGBA			threshold8		((deUint8)(de::clamp(threshold[0], 0, 255)), (deUint8)(de::clamp(threshold[1], 0, 255)), (deUint8)(de::clamp(threshold[2], 0, 255)), (deUint8)(de::clamp(threshold[3], 0, 255)));
1378 	tcu::TestLog&			log				= api.getLog();
1379 	Framebuffer				framebuffer		(gl);
1380 	Renderbuffer			renderbuffer	(gl);
1381 	tcu::Surface			screen			(reference.getWidth(), reference.getHeight());
1382 	tcu::Surface			refSurface		(reference.getWidth(), reference.getHeight());
1383 
1384 	log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
1385 
1386 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1387 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
1388 	imageTargetRenderbuffer(api.m_egl, gl, **img);
1389 
1390 	GLU_EXPECT_NO_ERROR(gl.getError(), "imageTargetRenderbuffer");
1391 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
1392 	GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferRenderbuffer");
1393 
1394 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1395 
1396 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
1397 
1398 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1399 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1400 	GLU_CHECK_GLW_CALL(gl, finish());
1401 
1402 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
1403 
1404 	return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
1405 
1406 }
1407 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1408 bool GLESImageApi::RenderTryAll::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1409 {
1410 	bool											foundSupported			= false;
1411 	tcu::TestLog&									log						= api.getLog();
1412 	GLESImageApi::RenderTexture2D					renderTex2D;
1413 	GLESImageApi::RenderExternalTexture				renderExternal;
1414 	GLESImageApi::RenderExternalTextureSamplerArray	renderExternalSamplerArray;
1415 	GLESImageApi::RenderReadPixelsRenderbuffer		renderReadPixels;
1416 	GLESImageApi::RenderDepthbuffer					renderDepth;
1417 	GLESImageApi::RenderStencilbuffer				renderStencil;
1418 	Action*											actions[]				= { &renderTex2D, &renderExternal, &renderExternalSamplerArray, &renderReadPixels, &renderDepth, &renderStencil };
1419 	set<string>										exts					= getSupportedExtensions(log, api.m_egl, api.m_display, api.m_gl);
1420 
1421 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
1422 	{
1423 		try
1424 		{
1425 			const string ext = actions[ndx]->getRequiredExtension();
1426 
1427 			if (!de::contains(exts, ext))
1428 				TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
1429 
1430 			if (!actions[ndx]->invoke(api, img, reference))
1431 				return false;
1432 
1433 			foundSupported = true;
1434 		}
1435 		catch (const tcu::NotSupportedError& error)
1436 		{
1437 			log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
1438 		}
1439 		catch (const IllegalRendererException&)
1440 		{
1441 			// not valid renderer
1442 		}
1443 	}
1444 
1445 	if (!foundSupported)
1446 		throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
1447 
1448 	return true;
1449 }
1450 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1451 bool GLESImageApi::ModifyTexSubImage::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1452 {
1453 	const glw::Functions&	gl		= api.m_gl;
1454 	tcu::TestLog&			log		= api.getLog();
1455 	glu::Texture			srcTex	(gl);
1456 	const int				xOffset	= 8;
1457 	const int				yOffset	= 16;
1458 	const int				xSize	= de::clamp(16, 0, reference.getWidth() - xOffset);
1459 	const int				ySize	= de::clamp(16, 0, reference.getHeight() - yOffset);
1460 	tcu::Texture2D			src		(glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
1461 
1462 	log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
1463 
1464 	src.allocLevel(0);
1465 	tcu::fillWithComponentGradients(src.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1466 
1467 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
1468 	imageTargetTexture2D(api.m_egl, gl, **img);
1469 	GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
1470 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
1471 	GLU_CHECK_GLW_CALL(gl, finish());
1472 
1473 	tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
1474 
1475 	return true;
1476 }
1477 
invokeGLES(GLESImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const1478 bool GLESImageApi::ModifyRenderbuffer::invokeGLES (GLESImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
1479 {
1480 	const glw::Functions&	gl				= api.m_gl;
1481 	tcu::TestLog&			log				= api.getLog();
1482 	glu::Framebuffer		framebuffer		(gl);
1483 	glu::Renderbuffer		renderbuffer	(gl);
1484 
1485 	log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
1486 
1487 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
1488 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
1489 
1490 	imageTargetRenderbuffer(api.m_egl, gl, **img);
1491 
1492 	initializeRbo(api, *renderbuffer, reference);
1493 
1494 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
1495 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
1496 
1497 	GLU_CHECK_GLW_CALL(gl, finish());
1498 
1499 	return true;
1500 }
1501 
initializeRbo(GLESImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const1502 void GLESImageApi::ModifyRenderbufferClearColor::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1503 {
1504 	const glw::Functions&	gl		= api.m_gl;
1505 
1506 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
1507 
1508 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1509 	GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w()));
1510 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
1511 
1512 	tcu::clear(reference.getLevel(0), m_color);
1513 }
1514 
initializeRbo(GLESImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const1515 void GLESImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1516 {
1517 	const glw::Functions&	gl		= api.m_gl;
1518 
1519 	framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
1520 
1521 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1522 	GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth));
1523 	GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
1524 
1525 	tcu::clearDepth(reference.getLevel(0), m_depth);
1526 }
1527 
initializeRbo(GLESImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const1528 void GLESImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLESImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
1529 {
1530 	const glw::Functions&	gl		= api.m_gl;
1531 
1532 	framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
1533 
1534 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
1535 	GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil));
1536 	GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
1537 
1538 	tcu::clearStencil(reference.getLevel(0), m_stencil);
1539 }
1540 
1541 class ImageFormatCase : public TestCase, private glu::CallLogWrapper
1542 {
1543 public:
1544 							ImageFormatCase		(EglTestContext& eglTestCtx, const TestSpec& spec);
1545 							~ImageFormatCase	(void);
1546 
1547 	void					init				(void);
1548 	void					deinit				(void);
1549 	IterateResult			iterate				(void);
1550 	void					checkExtensions		(void);
1551 
1552 private:
1553 	EGLConfig				getConfig			(void);
1554 
1555 	const TestSpec			m_spec;
1556 
1557 	vector<ImageApi*>		m_apiContexts;
1558 
1559 	EGLDisplay				m_display;
1560 	eglu::NativeWindow*		m_window;
1561 	EGLSurface				m_surface;
1562 	EGLConfig				m_config;
1563 	int						m_curIter;
1564 	MovePtr<UniqueImage>	m_img;
1565 	tcu::Texture2D			m_refImg;
1566 	glw::Functions			m_gl;
1567 };
1568 
getConfig(void)1569 EGLConfig ImageFormatCase::getConfig (void)
1570 {
1571 	const GLint		glesApi			= m_spec.contexts[0] == TestSpec::API_GLES3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
1572 	const EGLint	attribList[]	=
1573 	{
1574 		EGL_RENDERABLE_TYPE,	glesApi,
1575 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
1576 		EGL_RED_SIZE,			8,
1577 		EGL_BLUE_SIZE,			8,
1578 		EGL_GREEN_SIZE,			8,
1579 		EGL_ALPHA_SIZE,			8,
1580 		EGL_DEPTH_SIZE,			8,
1581 		EGL_NONE
1582 	};
1583 
1584 	return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList);
1585 }
1586 
ImageFormatCase(EglTestContext & eglTestCtx,const TestSpec & spec)1587 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
1588 	: TestCase				(eglTestCtx, spec.name.c_str(), spec.desc.c_str())
1589 	, glu::CallLogWrapper	(m_gl, eglTestCtx.getTestContext().getLog())
1590 	, m_spec				(spec)
1591 	, m_display				(EGL_NO_DISPLAY)
1592 	, m_window				(DE_NULL)
1593 	, m_surface				(EGL_NO_SURFACE)
1594 	, m_config				(0)
1595 	, m_curIter				(0)
1596 	, m_refImg				(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
1597 {
1598 }
1599 
~ImageFormatCase(void)1600 ImageFormatCase::~ImageFormatCase (void)
1601 {
1602 	deinit();
1603 }
1604 
checkExtensions(void)1605 void ImageFormatCase::checkExtensions (void)
1606 {
1607 	set<string> exts = getSupportedExtensions(getLog(), m_eglTestCtx.getLibrary(), m_display, m_gl);
1608 
1609 	for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
1610 	{
1611 		const TestSpec::Operation&	op	= m_spec.operations[operationNdx];
1612 		const string				ext	= op.action->getRequiredExtension();
1613 
1614 		if (!de::contains(exts, ext))
1615 			TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
1616 	}
1617 }
1618 
init(void)1619 void ImageFormatCase::init (void)
1620 {
1621 	const Library&						egl				= m_eglTestCtx.getLibrary();
1622 	const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
1623 
1624 	try
1625 	{
1626 		m_display	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
1627 
1628 		// GLES3 requires either EGL 1.5 or EGL_KHR_create_context extension.
1629 		if (m_spec.contexts[0] == TestSpec::API_GLES3 && eglu::getVersion(egl, m_display) < eglu::Version(1, 5))
1630 		{
1631 			set<string>				exts;
1632 			const vector<string>	eglExts	= eglu::getDisplayExtensions(egl, m_display);
1633 			exts.insert(eglExts.begin(), eglExts.end());
1634 
1635 			if (!de::contains(exts, "EGL_KHR_create_context"))
1636 			{
1637 				getLog() << tcu::TestLog::Message
1638 						 << "EGL version is under 1.5 and the test is using OpenGL ES 3.2."
1639 						 << "This requires EGL_KHR_create_context extension."
1640 						 << tcu::TestLog::EndMessage;
1641 				TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_create_context");
1642 			}
1643 		}
1644 
1645 		m_config	= getConfig();
1646 		m_window	= windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
1647 		m_surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL);
1648 
1649 		{
1650 			const char*	extensions[]	= { "GL_OES_EGL_image" };
1651 			int			major			= 2;
1652 			int			minor			= 0;
1653 
1654 			if (m_spec.contexts[0] == TestSpec::API_GLES3)
1655 			{
1656 				major = 3;
1657 				minor = 2;
1658 			}
1659 			m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(major, minor), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
1660 		}
1661 
1662 		for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
1663 		{
1664 			ImageApi* api = DE_NULL;
1665 			switch (m_spec.contexts[contextNdx])
1666 			{
1667 				case TestSpec::API_GLES2:
1668 				{
1669 					api = new GLESImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config, 2);
1670 					break;
1671 				}
1672 
1673 				case TestSpec::API_GLES3:
1674 				{
1675 					api = new GLESImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config, 3);
1676 					break;
1677 				}
1678 
1679 				default:
1680 					DE_ASSERT(false);
1681 					break;
1682 			}
1683 			m_apiContexts.push_back(api);
1684 		}
1685 		checkExtensions();
1686 	}
1687 	catch (...)
1688 	{
1689 		deinit();
1690 		throw;
1691 	}
1692 }
1693 
deinit(void)1694 void ImageFormatCase::deinit (void)
1695 {
1696 	const Library& egl = m_eglTestCtx.getLibrary();
1697 
1698 	m_img.clear();
1699 
1700 	for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++)
1701 		delete m_apiContexts[contexNdx];
1702 
1703 	m_apiContexts.clear();
1704 
1705 	if (m_surface != EGL_NO_SURFACE)
1706 	{
1707 		egl.destroySurface(m_display, m_surface);
1708 		m_surface = EGL_NO_SURFACE;
1709 	}
1710 
1711 	delete m_window;
1712 	m_window = DE_NULL;
1713 
1714 	if (m_display != EGL_NO_DISPLAY)
1715 	{
1716 		egl.terminate(m_display);
1717 		m_display = EGL_NO_DISPLAY;
1718 	}
1719 }
1720 
iterate(void)1721 TestCase::IterateResult ImageFormatCase::iterate (void)
1722 {
1723 	const TestSpec::Operation&	op		= m_spec.operations[m_curIter++];
1724 	ImageApi&					api		= *m_apiContexts[op.apiIndex];
1725 	const bool					isOk	= op.action->invoke(api, m_img, m_refImg);
1726 
1727 	if (isOk && m_curIter < (int)m_spec.operations.size())
1728 		return CONTINUE;
1729 	else if (isOk)
1730 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1731 	else
1732 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1733 
1734 	return STOP;
1735 }
1736 
1737 struct LabeledAction
1738 {
1739 	string			label;
1740 	MovePtr<Action>	action;
1741 };
1742 
1743 // A simple vector mockup that we need because MovePtr isn't copy-constructible.
1744 struct LabeledActions
1745 {
LabeledActionsdeqp::egl::Image::LabeledActions1746 					LabeledActions	(void) : m_numActions(0){}
operator []deqp::egl::Image::LabeledActions1747 	LabeledAction&	operator[]		(int ndx)				{ DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
1748 	void			add				(const string& label, MovePtr<Action> action);
sizedeqp::egl::Image::LabeledActions1749 	int				size			(void) const			{ return m_numActions; }
1750 private:
1751 	LabeledAction	m_actions[64];
1752 	int				m_numActions;
1753 };
1754 
add(const string & label,MovePtr<Action> action)1755 void LabeledActions::add (const string& label, MovePtr<Action> action)
1756 {
1757 	DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
1758 	m_actions[m_numActions].label = label;
1759 	m_actions[m_numActions].action = action;
1760 	++m_numActions;
1761 }
1762 
1763 class ImageTests : public TestCaseGroup
1764 {
1765 protected:
ImageTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1766 					ImageTests						(EglTestContext& eglTestCtx, const string& name, const string& desc)
1767 						: TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
1768 
1769 	void			addCreateTexture				(const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type);
1770 	void			addCreateRenderbuffer			(const string& name, GLenum format);
1771 	void			addCreateAndroidNative			(const string& name, GLenum format, bool isYUV);
1772 	void			addCreateAndroidNativeArray		(const string& name, GLenum format, deUint32 numLayers);
1773 	void			addCreateTexture2DActions		(const string& prefix);
1774 	void			addCreateTextureCubemapActions	(const string& suffix, GLenum internalFormat, GLenum format, GLenum type);
1775 	void			addCreateRenderbufferActions	(void);
1776 	void			addCreateAndroidNativeActions	(void);
1777 
1778 	LabeledActions	m_createActions;
1779 };
1780 
addCreateTexture(const string & name,EGLenum source,GLenum internalFormat,GLenum format,GLenum type)1781 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type)
1782 {
1783 	m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createTextureImageSource(source, internalFormat, format, type))));
1784 }
1785 
addCreateRenderbuffer(const string & name,GLenum format)1786 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
1787 {
1788 	m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createRenderbufferImageSource(format))));
1789 }
1790 
addCreateAndroidNative(const string & name,GLenum format,bool isYUV=false)1791 void ImageTests::addCreateAndroidNative (const string& name, GLenum format, bool isYUV = false)
1792 {
1793 	m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createAndroidNativeImageSource(format, 1u, isYUV))));
1794 }
1795 
addCreateAndroidNativeArray(const string & name,GLenum format,deUint32 numLayers)1796 void ImageTests::addCreateAndroidNativeArray (const string& name, GLenum format, deUint32 numLayers)
1797 {
1798 	m_createActions.add(name, MovePtr<Action>(new GLESImageApi::Create(createAndroidNativeImageSource(format, numLayers, false), numLayers)));
1799 }
1800 
addCreateTexture2DActions(const string & prefix)1801 void ImageTests::addCreateTexture2DActions (const string& prefix)
1802 {
1803 	addCreateTexture(prefix + "rgb8",		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_BYTE);
1804 	addCreateTexture(prefix + "rgb565",		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_SHORT_5_6_5);
1805 	addCreateTexture(prefix + "rgba8",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_BYTE);
1806 	addCreateTexture(prefix + "rgb5_a1",	EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1);
1807 	addCreateTexture(prefix + "rgba4",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4);
1808 }
1809 
addCreateTextureCubemapActions(const string & suffix,GLenum internalFormat,GLenum format,GLenum type)1810 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum internalFormat, GLenum format, GLenum type)
1811 {
1812 	addCreateTexture("cubemap_positive_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, internalFormat,	format,	type);
1813 	addCreateTexture("cubemap_positive_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, internalFormat,	format,	type);
1814 	addCreateTexture("cubemap_positive_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, internalFormat,	format,	type);
1815 	addCreateTexture("cubemap_negative_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, internalFormat,	format,	type);
1816 	addCreateTexture("cubemap_negative_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, internalFormat,	format,	type);
1817 	addCreateTexture("cubemap_negative_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, internalFormat,	format,	type);
1818 }
1819 
addCreateRenderbufferActions(void)1820 void ImageTests::addCreateRenderbufferActions (void)
1821 {
1822 	addCreateRenderbuffer("renderbuffer_rgba4",		GL_RGBA4);
1823 	addCreateRenderbuffer("renderbuffer_rgb5_a1",	GL_RGB5_A1);
1824 	addCreateRenderbuffer("renderbuffer_rgb565",	GL_RGB565);
1825 	addCreateRenderbuffer("renderbuffer_depth16",	GL_DEPTH_COMPONENT16);
1826 	addCreateRenderbuffer("renderbuffer_stencil",	GL_STENCIL_INDEX8);
1827 }
1828 
addCreateAndroidNativeActions(void)1829 void ImageTests::addCreateAndroidNativeActions (void)
1830 {
1831 	addCreateAndroidNative("android_native_rgba4",		GL_RGBA4);
1832 	addCreateAndroidNative("android_native_rgb5_a1",	GL_RGB5_A1);
1833 	addCreateAndroidNative("android_native_rgb565",		GL_RGB565);
1834 	addCreateAndroidNative("android_native_rgb8",		GL_RGB8);
1835 	addCreateAndroidNative("android_native_rgba8",		GL_RGBA8);
1836 	addCreateAndroidNative("android_native_d16",		GL_DEPTH_COMPONENT16);
1837 	addCreateAndroidNative("android_native_d24",		GL_DEPTH_COMPONENT24);
1838 	addCreateAndroidNative("android_native_d24s8",		GL_DEPTH24_STENCIL8);
1839 	addCreateAndroidNative("android_native_d32f",		GL_DEPTH_COMPONENT32F);
1840 	addCreateAndroidNative("android_native_d32fs8",		GL_DEPTH32F_STENCIL8);
1841 	addCreateAndroidNative("android_native_rgb10a2",	GL_RGB10_A2);
1842 	addCreateAndroidNative("android_native_rgba16f",	GL_RGBA16F);
1843 	addCreateAndroidNative("android_native_s8",			GL_STENCIL_INDEX8);
1844 	addCreateAndroidNative("android_native_yuv420",		GL_RGBA8, true);
1845 
1846 	addCreateAndroidNativeArray("android_native_array_rgba4",	GL_RGBA4,	4u);
1847 	addCreateAndroidNativeArray("android_native_array_rgb5_a1",	GL_RGB5_A1,	4u);
1848 	addCreateAndroidNativeArray("android_native_array_rgb565",	GL_RGB565,	4u);
1849 	addCreateAndroidNativeArray("android_native_array_rgb8",	GL_RGB8,	4u);
1850 	addCreateAndroidNativeArray("android_native_array_rgba8",	GL_RGBA8,	4u);
1851 }
1852 
1853 class RenderTests : public ImageTests
1854 {
1855 protected:
RenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1856 											RenderTests				(EglTestContext& eglTestCtx, const string& name, const string& desc)
1857 												: ImageTests			(eglTestCtx, name, desc) {}
1858 
1859 	void									addRenderActions		(void);
1860 	LabeledActions							m_renderActions;
1861 };
1862 
addRenderActions(void)1863 void RenderTests::addRenderActions (void)
1864 {
1865 	m_renderActions.add("texture",			MovePtr<Action>(new GLESImageApi::RenderTexture2D()));
1866 	m_renderActions.add("texture_array",	MovePtr<Action>(new GLESImageApi::RenderTexture2DArray()));
1867 	m_renderActions.add("read_pixels",		MovePtr<Action>(new GLESImageApi::RenderReadPixelsRenderbuffer()));
1868 	m_renderActions.add("depth_buffer",		MovePtr<Action>(new GLESImageApi::RenderDepthbuffer()));
1869 	m_renderActions.add("stencil_buffer",	MovePtr<Action>(new GLESImageApi::RenderStencilbuffer()));
1870 	m_renderActions.add("yuv_texture",		MovePtr<Action>(new GLESImageApi::RenderYUVTexture()));
1871 	m_renderActions.add("render_sample_texture_array",    MovePtr<Action>(new GLESImageApi::RenderSampleTexture2DArray()));
1872 }
1873 
1874 class SimpleCreationTests : public RenderTests
1875 {
1876 public:
SimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1877 			SimpleCreationTests		(EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
1878 	void	init					(void);
1879 };
1880 
isDepthFormat(GLenum format)1881 bool isDepthFormat (GLenum format)
1882 {
1883 	switch (format)
1884 	{
1885 		case GL_RGB:
1886 		case GL_RGB8:
1887 		case GL_RGB565:
1888 		case GL_RGBA:
1889 		case GL_RGBA4:
1890 		case GL_RGBA8:
1891 		case GL_RGB5_A1:
1892 		case GL_RGB10_A2:
1893 		case GL_RGBA16F:
1894 			return false;
1895 
1896 		case GL_DEPTH_COMPONENT16:
1897 		case GL_DEPTH_COMPONENT24:
1898 		case GL_DEPTH_COMPONENT32:
1899 		case GL_DEPTH_COMPONENT32F:
1900 		case GL_DEPTH24_STENCIL8:
1901 		case GL_DEPTH32F_STENCIL8:
1902 			return true;
1903 
1904 		case GL_STENCIL_INDEX8:
1905 			return false;
1906 
1907 		default:
1908 			DE_ASSERT(false);
1909 			return false;
1910 	}
1911 }
1912 
isStencilFormat(GLenum format)1913 bool isStencilFormat (GLenum format)
1914 {
1915 	switch (format)
1916 	{
1917 		case GL_RGB:
1918 		case GL_RGB8:
1919 		case GL_RGB565:
1920 		case GL_RGBA:
1921 		case GL_RGBA4:
1922 		case GL_RGBA8:
1923 		case GL_RGB5_A1:
1924 		case GL_RGB10_A2:
1925 		case GL_RGBA16F:
1926 			return false;
1927 
1928 		case GL_DEPTH_COMPONENT16:
1929 		case GL_DEPTH_COMPONENT24:
1930 		case GL_DEPTH_COMPONENT32:
1931 		case GL_DEPTH_COMPONENT32F:
1932 			return false;
1933 
1934 		case GL_STENCIL_INDEX8:
1935 		case GL_DEPTH24_STENCIL8:
1936 		case GL_DEPTH32F_STENCIL8:
1937 			return true;
1938 
1939 		default:
1940 			DE_ASSERT(false);
1941 			return false;
1942 	}
1943 }
1944 
isCompatibleCreateAndRenderActions(const Action & create,const Action & render)1945 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render)
1946 {
1947 	if (const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(&create))
1948 	{
1949 		bool  yuvFormatTest = glesCreate->isYUVFormatImage();
1950 		// this path only for none-yuv format tests
1951 		if(!yuvFormatTest)
1952 		{
1953 		    const GLenum createFormat = glesCreate->getEffectiveFormat();
1954 
1955 			if (dynamic_cast<const GLESImageApi::RenderTexture2DArray*>(&render))
1956 			{
1957 				// Makes sense only for texture arrays.
1958 				if (glesCreate->getNumLayers() <= 1u)
1959 					return false;
1960 			}
1961 			else if (glesCreate->getNumLayers() != 1u)
1962 			{
1963 				// Skip other render actions for texture arrays.
1964 				return false;
1965 			}
1966 
1967 			if (dynamic_cast<const GLESImageApi::RenderTexture2D*>(&render))
1968 			{
1969 				// GLES does not have depth or stencil textures
1970 				if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1971 					return false;
1972 			}
1973 
1974 			if (dynamic_cast<const GLESImageApi::RenderReadPixelsRenderbuffer*>(&render))
1975 			{
1976 				// GLES does not support readPixels for depth or stencil.
1977 				if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1978 					return false;
1979 			}
1980 
1981 			if (dynamic_cast<const GLESImageApi::RenderDepthbuffer*>(&render))
1982 			{
1983 				// Copying non-depth data to depth renderbuffer and expecting meaningful
1984 				// results just doesn't make any sense.
1985 				if (!isDepthFormat(createFormat))
1986 					return false;
1987 			}
1988 
1989 			if (dynamic_cast<const GLESImageApi::RenderStencilbuffer*>(&render))
1990 			{
1991 				// Copying non-stencil data to stencil renderbuffer and expecting meaningful
1992 				// results just doesn't make any sense.
1993 				if (!isStencilFormat(createFormat))
1994 					return false;
1995 			}
1996 
1997 			if (dynamic_cast<const GLESImageApi::RenderYUVTexture*>(&render))
1998 			{
1999 				// In yuv path rendering with non-yuv format native buffer and expecting meaningful
2000 				// results just doesn't make any sense
2001 				return false;
2002 			}
2003 
2004 			return true;
2005 		}
2006 		else if (dynamic_cast<const GLESImageApi::RenderYUVTexture*>(&render))
2007 		{
2008 			return true;
2009 		}
2010 	}
2011 	else
2012 		DE_ASSERT(false);
2013 
2014 	return false;
2015 }
2016 
init(void)2017 void SimpleCreationTests::init (void)
2018 {
2019 	addCreateTexture2DActions("texture_");
2020 	addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2021 	addCreateTextureCubemapActions("_rgb", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
2022 	addCreateRenderbufferActions();
2023 	addCreateAndroidNativeActions();
2024 	addRenderActions();
2025 
2026 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2027 	{
2028 		const LabeledAction& createAction = m_createActions[createNdx];
2029 
2030 		for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
2031 		{
2032 			const LabeledAction&	renderAction	= m_renderActions[renderNdx];
2033 			TestSpec				spec;
2034 
2035 			if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
2036 				continue;
2037 
2038 			if (dynamic_cast<const GLESImageApi::RenderTexture2DArray*>(renderAction.action.get()) ||
2039 				dynamic_cast<const GLESImageApi::RenderYUVTexture*>(renderAction.action.get()) ||
2040 				dynamic_cast<const GLESImageApi::RenderSampleTexture2DArray*>(renderAction.action.get()))
2041 			{
2042 				// Texture array tests require GLES3.
2043 				spec.name = std::string("gles3_") + createAction.label + "_" + renderAction.label;
2044 				spec.contexts.push_back(TestSpec::API_GLES3);
2045 			}
2046 			else
2047 			{
2048 				spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
2049 				spec.contexts.push_back(TestSpec::API_GLES2);
2050 			}
2051 
2052 			spec.desc = spec.name;
2053 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2054 			spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2055 
2056 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
2057 		}
2058 	}
2059 }
2060 
createSimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)2061 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2062 {
2063 	return new SimpleCreationTests(eglTestCtx, name, desc);
2064 }
2065 
isCompatibleFormats(GLenum createFormat,GLenum modifyFormat,GLenum modifyType)2066 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat, GLenum modifyType)
2067 {
2068 	switch (modifyFormat)
2069 	{
2070 		case GL_RGB:
2071 			switch (modifyType)
2072 			{
2073 				case GL_UNSIGNED_BYTE:
2074 					return createFormat == GL_RGB
2075 							|| createFormat == GL_RGB8
2076 							|| createFormat == GL_RGB565
2077 							|| createFormat == GL_SRGB8;
2078 
2079 				case GL_BYTE:
2080 					return createFormat == GL_RGB8_SNORM;
2081 
2082 				case GL_UNSIGNED_SHORT_5_6_5:
2083 					return createFormat == GL_RGB
2084 							|| createFormat == GL_RGB565;
2085 
2086 				case GL_UNSIGNED_INT_10F_11F_11F_REV:
2087 					return createFormat == GL_R11F_G11F_B10F;
2088 
2089 				case GL_UNSIGNED_INT_5_9_9_9_REV:
2090 					return createFormat == GL_RGB9_E5;
2091 
2092 				case GL_HALF_FLOAT:
2093 					return createFormat == GL_RGB16F
2094 							|| createFormat == GL_R11F_G11F_B10F
2095 							|| createFormat == GL_RGB9_E5;
2096 
2097 				case GL_FLOAT:
2098 					return createFormat == GL_RGB16F
2099 							|| createFormat == GL_RGB32F
2100 							|| createFormat == GL_R11F_G11F_B10F
2101 							|| createFormat == GL_RGB9_E5;
2102 
2103 				default:
2104 					DE_FATAL("Unknown modify type");
2105 					return false;
2106 			}
2107 
2108 		case GL_RGBA:
2109 			switch (modifyType)
2110 			{
2111 				case GL_UNSIGNED_BYTE:
2112 					return createFormat == GL_RGBA8
2113 						|| createFormat == GL_RGB5_A1
2114 						|| createFormat == GL_RGBA4
2115 						|| createFormat == GL_SRGB8_ALPHA8
2116 						|| createFormat == GL_RGBA;
2117 
2118 				case GL_UNSIGNED_SHORT_4_4_4_4:
2119 					return createFormat == GL_RGBA4
2120 						|| createFormat == GL_RGBA;
2121 
2122 				case GL_UNSIGNED_SHORT_5_5_5_1:
2123 					return createFormat == GL_RGB5_A1
2124 						|| createFormat == GL_RGBA;
2125 
2126 				case GL_UNSIGNED_INT_2_10_10_10_REV:
2127 					return createFormat == GL_RGB10_A2
2128 						|| createFormat == GL_RGB5_A1;
2129 
2130 				case GL_HALF_FLOAT:
2131 					return createFormat == GL_RGBA16F;
2132 
2133 				case GL_FLOAT:
2134 					return createFormat == GL_RGBA16F
2135 						|| createFormat == GL_RGBA32F;
2136 
2137 				default:
2138 					DE_FATAL("Unknown modify type");
2139 					return false;
2140 			}
2141 
2142 		default:
2143 			DE_FATAL("Unknown modify format");
2144 			return false;
2145 	}
2146 }
2147 
isCompatibleCreateAndModifyActions(const Action & create,const Action & modify)2148 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify)
2149 {
2150 	if (const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(&create))
2151 	{
2152 		// No modify tests for texture arrays.
2153 		if (glesCreate->getNumLayers() > 1u)
2154 			return false;
2155 		// No modify tests for yuv format image.
2156 		if (glesCreate->isYUVFormatImage())
2157 			return false;
2158 
2159 		const GLenum createFormat = glesCreate->getEffectiveFormat();
2160 
2161 		if (const GLESImageApi::ModifyTexSubImage* glesTexSubImageModify = dynamic_cast<const GLESImageApi::ModifyTexSubImage*>(&modify))
2162 		{
2163 			const GLenum modifyFormat	= glesTexSubImageModify->getFormat();
2164 			const GLenum modifyType		= glesTexSubImageModify->getType();
2165 
2166 			return isCompatibleFormats(createFormat, modifyFormat, modifyType);
2167 		}
2168 
2169 		if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearColor*>(&modify))
2170 		{
2171 			// reintepreting color as non-color is not meaningful
2172 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
2173 				return false;
2174 		}
2175 
2176 		if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearDepth*>(&modify))
2177 		{
2178 			// reintepreting depth as non-depth is not meaningful
2179 			if (!isDepthFormat(createFormat))
2180 				return false;
2181 		}
2182 
2183 		if (dynamic_cast<const GLESImageApi::ModifyRenderbufferClearStencil*>(&modify))
2184 		{
2185 			// reintepreting stencil as non-stencil is not meaningful
2186 			if (!isStencilFormat(createFormat))
2187 				return false;
2188 		}
2189 
2190 		return true;
2191 	}
2192 	else
2193 		DE_ASSERT(false);
2194 
2195 	return false;
2196 }
2197 
2198 class MultiContextRenderTests : public RenderTests
2199 {
2200 public:
2201 					MultiContextRenderTests		(EglTestContext& eglTestCtx, const string& name, const string& desc);
2202 	void			init						(void);
2203 	void			addClearActions				(void);
2204 private:
2205 	LabeledActions	m_clearActions;
2206 };
2207 
MultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)2208 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2209 	: RenderTests	(eglTestCtx, name, desc)
2210 {
2211 }
2212 
addClearActions(void)2213 void MultiContextRenderTests::addClearActions (void)
2214 {
2215 	m_clearActions.add("clear_color",	MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f))));
2216 	m_clearActions.add("clear_depth",	MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearDepth(0.75f)));
2217 	m_clearActions.add("clear_stencil",	MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearStencil(97)));
2218 }
2219 
init(void)2220 void MultiContextRenderTests::init (void)
2221 {
2222 	addCreateTexture2DActions("texture_");
2223 	addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2224 	addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
2225 	addCreateRenderbufferActions();
2226 	addCreateAndroidNativeActions();
2227 	addRenderActions();
2228 	addClearActions();
2229 
2230 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2231 	for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
2232 	for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++)
2233 	{
2234 		const LabeledAction&	createAction	= m_createActions[createNdx];
2235 		const LabeledAction&	renderAction	= m_renderActions[renderNdx];
2236 		const LabeledAction&	clearAction		= m_clearActions[clearNdx];
2237 		TestSpec				spec;
2238 
2239 		if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
2240 			continue;
2241 		if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action))
2242 			continue;
2243 
2244 		spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
2245 
2246 		const GLESImageApi::Create* glesCreate = dynamic_cast<const GLESImageApi::Create*>(createAction.action.get());
2247 
2248 		if (!glesCreate)
2249 			DE_FATAL("Dynamic casting to GLESImageApi::Create* failed");
2250 
2251 		const GLenum createFormat = glesCreate->getEffectiveFormat();
2252 
2253 		if (isDepthFormat(createFormat) && isStencilFormat(createFormat))
2254 		{
2255 			// Combined depth and stencil format. Add the clear action label to avoid test
2256 			// name clashes.
2257 			spec.name += std::string("_") + clearAction.label;
2258 		}
2259 
2260 		spec.desc = spec.name;
2261 
2262 		spec.contexts.push_back(TestSpec::API_GLES2);
2263 		spec.contexts.push_back(TestSpec::API_GLES2);
2264 
2265 		spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2266 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2267 		spec.operations.push_back(TestSpec::Operation(0, *clearAction.action));
2268 		spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
2269 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
2270 		spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
2271 
2272 		addChild(new ImageFormatCase(m_eglTestCtx, spec));
2273 	}
2274 }
2275 
createMultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)2276 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2277 {
2278 	return new MultiContextRenderTests(eglTestCtx, name, desc);
2279 }
2280 
2281 class ModifyTests : public ImageTests
2282 {
2283 public:
ModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)2284 								ModifyTests		(EglTestContext& eglTestCtx, const string& name, const string& desc)
2285 									: ImageTests(eglTestCtx, name, desc) {}
2286 
2287 	void						init			(void);
2288 
2289 protected:
2290 	void						addModifyActions(void);
2291 
2292 	LabeledActions				m_modifyActions;
2293 	GLESImageApi::RenderTryAll	m_renderAction;
2294 };
2295 
addModifyActions(void)2296 void ModifyTests::addModifyActions (void)
2297 {
2298 	m_modifyActions.add("tex_subimage_rgb8",			MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGB,		GL_UNSIGNED_BYTE)));
2299 	m_modifyActions.add("tex_subimage_rgb565",			MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGB,		GL_UNSIGNED_SHORT_5_6_5)));
2300 	m_modifyActions.add("tex_subimage_rgba8",			MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_BYTE)));
2301 	m_modifyActions.add("tex_subimage_rgb5_a1",			MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1)));
2302 	m_modifyActions.add("tex_subimage_rgba4",			MovePtr<Action>(new GLESImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4)));
2303 
2304 	m_modifyActions.add("renderbuffer_clear_color",		MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
2305 	m_modifyActions.add("renderbuffer_clear_depth",		MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearDepth(0.7f)));
2306 	m_modifyActions.add("renderbuffer_clear_stencil",	MovePtr<Action>(new GLESImageApi::ModifyRenderbufferClearStencil(78)));
2307 }
2308 
init(void)2309 void ModifyTests::init (void)
2310 {
2311 	addCreateTexture2DActions("tex_");
2312 	addCreateRenderbufferActions();
2313 	addCreateAndroidNativeActions();
2314 	addModifyActions();
2315 
2316 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
2317 	{
2318 		LabeledAction& createAction = m_createActions[createNdx];
2319 
2320 		for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
2321 		{
2322 			LabeledAction& modifyAction = m_modifyActions[modifyNdx];
2323 
2324 			if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action))
2325 				continue;
2326 
2327 			TestSpec spec;
2328 			spec.name = createAction.label + "_" + modifyAction.label;
2329 			spec.desc = "gles2_tex_sub_image";
2330 
2331 			spec.contexts.push_back(TestSpec::API_GLES2);
2332 
2333 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
2334 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
2335 			spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
2336 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
2337 
2338 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
2339 		}
2340 	}
2341 }
2342 
createModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)2343 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
2344 {
2345 	return new ModifyTests(eglTestCtx, name, desc);
2346 }
2347 
2348 } // Image
2349 } // egl
2350 } // deqp
2351