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