• 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_VG
134 		//API_GLES1
135 
136 		API_LAST
137 	};
138 
139 	struct Operation
140 	{
Operationdeqp::egl::Image::TestSpec::Operation141 		Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {}
142 		int				apiIndex;
143 		const Action*	action;
144 	};
145 
146 	vector<ApiContext>	contexts;
147 	vector<Operation>	operations;
148 
149 };
150 
151 class ImageApi
152 {
153 public:
154 					ImageApi		(const Library& egl, int contextId, EGLDisplay display, EGLSurface surface);
~ImageApi(void)155 	virtual 		~ImageApi		(void) {}
156 
157 protected:
158 	const Library&	m_egl;
159 	int				m_contextId;
160 	EGLDisplay		m_display;
161 	EGLSurface		m_surface;
162 };
163 
ImageApi(const Library & egl,int contextId,EGLDisplay display,EGLSurface surface)164 ImageApi::ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface)
165 	: m_egl				(egl)
166 	, m_contextId		(contextId)
167 	, m_display			(display)
168 	, m_surface			(surface)
169 {
170 }
171 
172 class GLES2ImageApi : public ImageApi, private glu::CallLogWrapper
173 {
174 public:
175 	class GLES2Action : public Action
176 	{
177 	public:
178 		bool				invoke					(ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
179 		virtual bool		invokeGLES2				(GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0;
180 	};
181 
182 	class Create : public GLES2Action
183 	{
184 	public:
Create(MovePtr<ImageSource> imgSource)185 								Create					(MovePtr<ImageSource> imgSource) : m_imgSource(imgSource) {}
getRequiredExtension(void) const186 		string					getRequiredExtension	(void) const { return m_imgSource->getRequiredExtension(); }
187 		bool					invokeGLES2				(GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
getEffectiveFormat(void) const188 		glw::GLenum				getEffectiveFormat		(void) const { return m_imgSource->getEffectiveFormat(); }
189 
190 	private:
191 		UniquePtr<ImageSource>	m_imgSource;
192 	};
193 
194 	class Render : public GLES2Action
195 	{
196 	public:
getRequiredExtension(void) const197 		string				getRequiredExtension	(void) const { return "GL_OES_EGL_image"; }
198 	};
199 
200 	class RenderTexture2D				: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
201 	class RenderTextureCubemap			: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
202 	class RenderReadPixelsRenderbuffer	: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
203 	class RenderDepthbuffer				: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
204 	class RenderStencilbuffer			: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
205 	class RenderTryAll					: public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
206 
207 	class Modify : public GLES2Action
208 	{
209 	public:
getRequiredExtension(void) const210 		string				getRequiredExtension	(void) const { return "GL_OES_EGL_image"; }
211 	};
212 
213 	class ModifyTexSubImage : public Modify
214 	{
215 	public:
ModifyTexSubImage(GLenum format,GLenum type)216 							ModifyTexSubImage		(GLenum format, GLenum type) : m_format(format), m_type(type) {}
217 		bool				invokeGLES2				(GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
getFormat(void) const218 		GLenum				getFormat				(void) const { return m_format; }
getType(void) const219 		GLenum				getType					(void) const { return m_type; }
220 
221 	private:
222 		GLenum				m_format;
223 		GLenum				m_type;
224 	};
225 
226 	class ModifyRenderbuffer : public Modify
227 	{
228 	public:
229 		bool				invokeGLES2				(GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
230 
231 	protected:
232 		virtual void		initializeRbo			(GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0;
233 	};
234 
235 	class ModifyRenderbufferClearColor : public ModifyRenderbuffer
236 	{
237 	public:
ModifyRenderbufferClearColor(tcu::Vec4 color)238 					ModifyRenderbufferClearColor	(tcu::Vec4 color) : m_color(color) {}
239 
240 	protected:
241 		void		initializeRbo					(GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
242 
243 		tcu::Vec4	m_color;
244 	};
245 
246 	class ModifyRenderbufferClearDepth : public ModifyRenderbuffer
247 	{
248 	public:
ModifyRenderbufferClearDepth(GLfloat depth)249 					ModifyRenderbufferClearDepth	(GLfloat depth) : m_depth(depth) {}
250 
251 	protected:
252 		void		initializeRbo					(GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
253 
254 		GLfloat		m_depth;
255 	};
256 
257 	class ModifyRenderbufferClearStencil : public ModifyRenderbuffer
258 	{
259 	public:
ModifyRenderbufferClearStencil(GLint stencil)260 					ModifyRenderbufferClearStencil	(GLint stencil) : m_stencil(stencil) {}
261 
262 	protected:
263 		void		initializeRbo					(GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
264 
265 		GLint		m_stencil;
266 	};
267 
268 					GLES2ImageApi					(const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config);
269 					~GLES2ImageApi					(void);
270 
271 private:
272 	EGLContext					m_context;
273 	const glw::Functions&		m_gl;
274 
275 	MovePtr<UniqueImage>		createImage			(const ImageSource& source, const ClientBuffer& buffer) const;
276 };
277 
GLES2ImageApi(const Library & egl,const glw::Functions & gl,int contextId,tcu::TestLog & log,EGLDisplay display,EGLSurface surface,EGLConfig config)278 GLES2ImageApi::GLES2ImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config)
279 	: ImageApi				(egl, contextId, display, surface)
280 	, glu::CallLogWrapper	(gl, log)
281 	, m_context				(DE_NULL)
282 	, m_gl					(gl)
283 {
284 	const EGLint attriblist[] =
285 	{
286 		EGL_CONTEXT_CLIENT_VERSION, 2,
287 		EGL_NONE
288 	};
289 
290 	EGLint configId = -1;
291 	EGLU_CHECK_CALL(m_egl, getConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId));
292 	getLog() << tcu::TestLog::Message << "Creating gles2 context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
293 	egl.bindAPI(EGL_OPENGL_ES_API);
294 	m_context = m_egl.createContext(m_display, config, EGL_NO_CONTEXT, attriblist);
295 	EGLU_CHECK_MSG(m_egl, "Failed to create GLES2 context");
296 
297 	egl.makeCurrent(display, m_surface, m_surface, m_context);
298 	EGLU_CHECK_MSG(m_egl, "Failed to make context current");
299 }
300 
~GLES2ImageApi(void)301 GLES2ImageApi::~GLES2ImageApi (void)
302 {
303 	m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
304 	m_egl.destroyContext(m_display, m_context);
305 }
306 
invoke(ImageApi & api,MovePtr<UniqueImage> & image,tcu::Texture2D & ref) const307 bool GLES2ImageApi::GLES2Action::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
308 {
309 	GLES2ImageApi& gles2Api = dynamic_cast<GLES2ImageApi&>(api);
310 
311 	gles2Api.m_egl.makeCurrent(gles2Api.m_display, gles2Api.m_surface, gles2Api.m_surface, gles2Api.m_context);
312 	return invokeGLES2(gles2Api, image, ref);
313 }
314 
315 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & image,tcu::Texture2D & ref) const316 bool GLES2ImageApi::Create::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
317 {
318 	de::UniquePtr<ClientBuffer>	buffer	(m_imgSource->createBuffer(api.m_gl, &ref));
319 	image = api.createImage(*m_imgSource, *buffer);
320 	return true;
321 }
322 
createImage(const ImageSource & source,const ClientBuffer & buffer) const323 MovePtr<UniqueImage> GLES2ImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const
324 {
325 	const EGLImageKHR image = source.createImage(m_egl, m_display, m_context, buffer.get());
326 	return MovePtr<UniqueImage>(new UniqueImage(m_egl, m_display, image));
327 }
328 
imageTargetTexture2D(const Library & egl,const glw::Functions & gl,GLeglImageOES img)329 static void imageTargetTexture2D (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
330 {
331 	gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img);
332 	{
333 		const GLenum error = gl.getError();
334 
335 		if (error == GL_INVALID_OPERATION)
336 			TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported");
337 
338 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
339 		EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()");
340 	}
341 }
342 
imageTargetRenderbuffer(const Library & egl,const glw::Functions & gl,GLeglImageOES img)343 static void imageTargetRenderbuffer (const Library& egl, const glw::Functions& gl, GLeglImageOES img)
344 {
345 	gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img);
346 	{
347 		const GLenum error = gl.getError();
348 
349 		if (error == GL_INVALID_OPERATION)
350 			TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported");
351 
352 		GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()");
353 		EGLU_CHECK_MSG(egl, "glEGLImageTargetRenderbufferStorageOES()");
354 	}
355 }
356 
framebufferRenderbuffer(const glw::Functions & gl,GLenum attachment,GLuint rbo)357 static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo)
358 {
359 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo));
360 	TCU_CHECK_AND_THROW(NotSupportedError,
361 						gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
362 						("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str());
363 }
364 
365 static const float squareTriangleCoords[] =
366 {
367 	-1.0, -1.0,
368 	1.0, -1.0,
369 	1.0,  1.0,
370 
371 	1.0,  1.0,
372 	-1.0,  1.0,
373 	-1.0, -1.0
374 };
375 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const376 bool GLES2ImageApi::RenderTexture2D::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
377 {
378 	const glw::Functions&	gl		= api.m_gl;
379 	tcu::TestLog&			log		= api.getLog();
380 	Texture					srcTex	(gl);
381 
382 	// Branch only taken in TryAll case
383 	if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
384 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures
385 	if (reference.getFormat().order == tcu::TextureFormat::S)
386 		throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures
387 
388 	gl.clearColor(0.0, 0.0, 0.0, 0.0);
389 	gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
390 	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
391 	gl.disable(GL_DEPTH_TEST);
392 
393 	log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage;
394 	TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
395 
396 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
397 	imageTargetTexture2D(api.m_egl, gl, **img);
398 
399 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
400 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
401 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
402 	GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
403 
404 	const char* const vertexShader =
405 		"attribute highp vec2 a_coord;\n"
406 		"varying mediump vec2 v_texCoord;\n"
407 		"void main(void) {\n"
408 		"\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n"
409 		"\tgl_Position = vec4(a_coord, -0.1, 1.0);\n"
410 		"}\n";
411 
412 	const char* const fragmentShader =
413 		"varying mediump vec2 v_texCoord;\n"
414 		"uniform sampler2D u_sampler;\n"
415 		"void main(void) {\n"
416 		"\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n"
417 		"\tgl_FragColor = vec4(texColor);\n"
418 		"}";
419 
420 	Program program(gl, vertexShader, fragmentShader);
421 	TCU_CHECK(program.isOk());
422 
423 	GLuint glProgram = program.getProgram();
424 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
425 
426 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
427 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
428 
429 	GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
430 	TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
431 
432 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
433 	GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
434 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
435 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
436 
437 	GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
438 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
439 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
440 
441 	tcu::Surface refSurface	(reference.getWidth(), reference.getHeight());
442 	tcu::Surface screen		(reference.getWidth(), reference.getHeight());
443 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
444 
445 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
446 
447 	float	threshold	= 0.05f;
448 	bool	match		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
449 
450 	return match;
451 }
452 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const453 bool GLES2ImageApi::RenderDepthbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
454 {
455 	const glw::Functions&	gl					= api.m_gl;
456 	tcu::TestLog&			log					= api.getLog();
457 	Framebuffer				framebuffer			(gl);
458 	Renderbuffer			renderbufferColor	(gl);
459 	Renderbuffer			renderbufferDepth	(gl);
460 	const tcu::RGBA			compareThreshold	(32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
461 
462 	// Branch only taken in TryAll case
463 	if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::D)
464 		throw IllegalRendererException(); // Skip, interpreting non-depth data as depth data is not meaningful
465 
466 	log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
467 
468 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
469 
470 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
471 	GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
472 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
473 
474 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth));
475 	imageTargetRenderbuffer(api.m_egl, gl, **img);
476 	framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth);
477 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
478 
479 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
480 
481 	// Render
482 	const char* vertexShader =
483 		"attribute highp vec2 a_coord;\n"
484 		"uniform highp float u_depth;\n"
485 		"void main(void) {\n"
486 		"\tgl_Position = vec4(a_coord, u_depth, 1.0);\n"
487 		"}\n";
488 
489 	const char* fragmentShader =
490 		"uniform mediump vec4 u_color;\n"
491 		"void main(void) {\n"
492 		"\tgl_FragColor = u_color;\n"
493 		"}";
494 
495 	Program program(gl, vertexShader, fragmentShader);
496 	TCU_CHECK(program.isOk());
497 
498 	GLuint glProgram = program.getProgram();
499 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
500 
501 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
502 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
503 
504 	GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
505 	TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
506 
507 	GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth");
508 	TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth");
509 
510 	GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
511 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
512 
513 	tcu::Vec4 depthLevelColors[] = {
514 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
515 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
516 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
517 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
518 		tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
519 
520 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
521 		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
522 		tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
523 		tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
524 		tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
525 	};
526 
527 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
528 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
529 
530 	GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST));
531 	GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS));
532 	GLU_CHECK_GLW_CALL(gl, depthMask(GL_FALSE));
533 
534 	for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
535 	{
536 		const tcu::Vec4	color		= depthLevelColors[level];
537 		const float		clipDepth	= ((float)(level + 1) * 0.1f) * 2.0f - 1.0f; // depth in clip coords
538 
539 		GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
540 		GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, clipDepth));
541 		GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
542 	}
543 
544 	GLU_CHECK_GLW_CALL(gl, depthMask(GL_TRUE));
545 	GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST));
546 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
547 
548 	const ConstPixelBufferAccess&	refAccess		= reference.getLevel(0);
549 	tcu::Surface					screen			(reference.getWidth(), reference.getHeight());
550 	tcu::Surface					referenceScreen	(reference.getWidth(), reference.getHeight());
551 
552 	gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
553 
554 	for (int y = 0; y < reference.getHeight(); y++)
555 	{
556 		for (int x = 0; x < reference.getWidth(); x++)
557 		{
558 			tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
559 
560 			for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
561 			{
562 				if ((float)(level + 1) * 0.1f < refAccess.getPixDepth(x, y))
563 					result = depthLevelColors[level];
564 			}
565 
566 			referenceScreen.getAccess().setPixel(result, x, y);
567 		}
568 	}
569 
570 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
571 	GLU_CHECK_GLW_CALL(gl, finish());
572 
573 	return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
574 }
575 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const576 bool GLES2ImageApi::RenderStencilbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
577 {
578 	// Branch only taken in TryAll case
579 	if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::S)
580 		throw IllegalRendererException(); // Skip, interpreting non-stencil data as stencil data is not meaningful
581 
582 	const glw::Functions&	gl					= api.m_gl;
583 	tcu::TestLog&			log					= api.getLog();
584 	Framebuffer				framebuffer			(gl);
585 	Renderbuffer			renderbufferColor	(gl);
586 	Renderbuffer			renderbufferStencil (gl);
587 	const tcu::RGBA			compareThreshold	(32, 32, 32, 32); // layer colors are far apart, large thresholds are ok
588 	const deUint32			numStencilBits		= tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(reference.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
589 	const deUint32			maxStencil			= deBitMask32(0, numStencilBits);
590 
591 	log << tcu::TestLog::Message << "Rendering with stencil buffer" << tcu::TestLog::EndMessage;
592 
593 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
594 
595 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
596 	GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
597 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
598 
599 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferStencil));
600 	imageTargetRenderbuffer(api.m_egl, gl, **img);
601 	framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, *renderbufferStencil);
602 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
603 
604 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
605 
606 	// Render
607 	const char* vertexShader =
608 		"attribute highp vec2 a_coord;\n"
609 		"void main(void) {\n"
610 		"\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
611 		"}\n";
612 
613 	const char* fragmentShader =
614 		"uniform mediump vec4 u_color;\n"
615 		"void main(void) {\n"
616 		"\tgl_FragColor = u_color;\n"
617 		"}";
618 
619 	Program program(gl, vertexShader, fragmentShader);
620 	TCU_CHECK(program.isOk());
621 
622 	GLuint glProgram = program.getProgram();
623 	GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
624 
625 	GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
626 	TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
627 
628 	GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
629 	TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
630 
631 	GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f));
632 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
633 
634 	tcu::Vec4 stencilLevelColors[] = {
635 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
636 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
637 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
638 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
639 		tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
640 
641 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
642 		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
643 		tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),
644 		tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f),
645 		tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
646 	};
647 
648 	GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
649 	GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
650 
651 	GLU_CHECK_GLW_CALL(gl, enable(GL_STENCIL_TEST));
652 	GLU_CHECK_GLW_CALL(gl, stencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
653 
654 	for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
655 	{
656 		const tcu::Vec4	color	= stencilLevelColors[level];
657 		const int		stencil	= (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
658 
659 		GLU_CHECK_GLW_CALL(gl, stencilFunc(GL_LESS, stencil, 0xFFFFFFFFu));
660 		GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
661 		GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6));
662 	}
663 
664 	GLU_CHECK_GLW_CALL(gl, disable(GL_STENCIL_TEST));
665 	GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
666 
667 	const ConstPixelBufferAccess&	refAccess		= reference.getLevel(0);
668 	tcu::Surface					screen			(reference.getWidth(), reference.getHeight());
669 	tcu::Surface					referenceScreen	(reference.getWidth(), reference.getHeight());
670 
671 	gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
672 
673 	for (int y = 0; y < reference.getHeight(); y++)
674 	for (int x = 0; x < reference.getWidth(); x++)
675 	{
676 		tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
677 
678 		for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++)
679 		{
680 			const int levelStencil = (int)(((float)(level + 1) * 0.1f) * (float)maxStencil);
681 			if (levelStencil < refAccess.getPixStencil(x, y))
682 				result = stencilLevelColors[level];
683 		}
684 
685 		referenceScreen.getAccess().setPixel(result, x, y);
686 	}
687 
688 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
689 	GLU_CHECK_GLW_CALL(gl, finish());
690 
691 	return tcu::pixelThresholdCompare(log, "StencilResult", "Result from rendering with stencil buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT);
692 }
693 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const694 bool GLES2ImageApi::RenderReadPixelsRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
695 {
696 	const glw::Functions&	gl				= api.m_gl;
697 	const tcu::IVec4		bitDepth		= tcu::getTextureFormatMantissaBitDepth(reference.getFormat());
698 	const tcu::IVec4		threshold		(2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth)));
699 	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)));
700 	tcu::TestLog&			log				= api.getLog();
701 	Framebuffer				framebuffer		(gl);
702 	Renderbuffer			renderbuffer	(gl);
703 	tcu::Surface			screen			(reference.getWidth(), reference.getHeight());
704 	tcu::Surface			refSurface		(reference.getWidth(), reference.getHeight());
705 
706 	// Branch only taken in TryAll case
707 	if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D)
708 		throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for depth attachments
709 	if (reference.getFormat().order == tcu::TextureFormat::S)
710 		throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for stencil attachments
711 
712 	log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
713 
714 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
715 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
716 	imageTargetRenderbuffer(api.m_egl, gl, **img);
717 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
718 
719 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
720 
721 	gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
722 
723 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
724 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
725 	GLU_CHECK_GLW_CALL(gl, finish());
726 
727 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
728 
729 	return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
730 
731 }
732 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const733 bool GLES2ImageApi::RenderTryAll::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
734 {
735 	bool										foundSupported			= false;
736 	tcu::TestLog&								log						= api.getLog();
737 	GLES2ImageApi::RenderTexture2D				renderTex2D;
738 	GLES2ImageApi::RenderReadPixelsRenderbuffer	renderReadPixels;
739 	GLES2ImageApi::RenderDepthbuffer			renderDepth;
740 	GLES2ImageApi::RenderStencilbuffer			renderStencil;
741 	Action*										actions[] 				= { &renderTex2D, &renderReadPixels, &renderDepth, &renderStencil };
742 
743 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
744 	{
745 		try
746 		{
747 			if (!actions[ndx]->invoke(api, img, reference))
748 				return false;
749 
750 			foundSupported = true;
751 		}
752 		catch (const tcu::NotSupportedError& error)
753 		{
754 			log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
755 		}
756 		catch (const IllegalRendererException&)
757 		{
758 			// not valid renderer
759 		}
760 	}
761 
762 	if (!foundSupported)
763 		throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
764 
765 	return true;
766 }
767 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const768 bool GLES2ImageApi::ModifyTexSubImage::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
769 {
770 	const glw::Functions&	gl		= api.m_gl;
771 	tcu::TestLog&			log		= api.getLog();
772 	glu::Texture			srcTex	(gl);
773 	const int				xOffset	= 8;
774 	const int				yOffset	= 16;
775 	const int				xSize	= de::clamp(16, 0, reference.getWidth() - xOffset);
776 	const int				ySize	= de::clamp(16, 0, reference.getHeight() - yOffset);
777 	tcu::Texture2D			src		(glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
778 
779 	log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
780 
781 	src.allocLevel(0);
782 	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));
783 
784 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
785 	imageTargetTexture2D(api.m_egl, gl, **img);
786 	GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
787 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
788 	GLU_CHECK_GLW_CALL(gl, finish());
789 
790 	tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
791 
792 	return true;
793 }
794 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const795 bool GLES2ImageApi::ModifyRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
796 {
797 	const glw::Functions&	gl				= api.m_gl;
798 	tcu::TestLog&			log				= api.getLog();
799 	glu::Framebuffer		framebuffer		(gl);
800 	glu::Renderbuffer		renderbuffer	(gl);
801 
802 	log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
803 
804 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
805 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
806 
807 	imageTargetRenderbuffer(api.m_egl, gl, **img);
808 
809 	initializeRbo(api, *renderbuffer, reference);
810 
811 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
812 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
813 
814 	GLU_CHECK_GLW_CALL(gl, finish());
815 
816 	return true;
817 }
818 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const819 void GLES2ImageApi::ModifyRenderbufferClearColor::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
820 {
821 	const glw::Functions&	gl		= api.m_gl;
822 
823 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
824 
825 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
826 	GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w()));
827 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
828 
829 	tcu::clear(reference.getLevel(0), m_color);
830 }
831 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const832 void GLES2ImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
833 {
834 	const glw::Functions&	gl		= api.m_gl;
835 
836 	framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
837 
838 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
839 	GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth));
840 	GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
841 
842 	tcu::clearDepth(reference.getLevel(0), m_depth);
843 }
844 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const845 void GLES2ImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
846 {
847 	const glw::Functions&	gl		= api.m_gl;
848 
849 	framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
850 
851 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
852 	GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil));
853 	GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
854 
855 	tcu::clearStencil(reference.getLevel(0), m_stencil);
856 }
857 
858 class ImageFormatCase : public TestCase, private glu::CallLogWrapper
859 {
860 public:
861 						ImageFormatCase		(EglTestContext& eglTestCtx, const TestSpec& spec);
862 						~ImageFormatCase	(void);
863 
864 	void				init				(void);
865 	void				deinit				(void);
866 	IterateResult		iterate				(void);
867 	void				checkExtensions		(void);
868 
869 private:
870 	EGLConfig			getConfig			(void);
871 
872 	const TestSpec		m_spec;
873 
874 	vector<ImageApi*>	m_apiContexts;
875 
876 	EGLDisplay			m_display;
877 	eglu::NativeWindow*	m_window;
878 	EGLSurface			m_surface;
879 	EGLConfig			m_config;
880 	int					m_curIter;
881 	MovePtr<UniqueImage>m_img;
882 	tcu::Texture2D		m_refImg;
883 	glw::Functions		m_gl;
884 };
885 
getConfig(void)886 EGLConfig ImageFormatCase::getConfig (void)
887 {
888 	const EGLint attribList[] =
889 	{
890 		EGL_RENDERABLE_TYPE, 	EGL_OPENGL_ES2_BIT,
891 		EGL_SURFACE_TYPE,	 	EGL_WINDOW_BIT,
892 		EGL_RED_SIZE,			8,
893 		EGL_BLUE_SIZE,			8,
894 		EGL_GREEN_SIZE,			8,
895 		EGL_ALPHA_SIZE,			8,
896 		EGL_DEPTH_SIZE,			8,
897 		EGL_NONE
898 	};
899 
900 	return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList);
901 }
902 
ImageFormatCase(EglTestContext & eglTestCtx,const TestSpec & spec)903 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
904 	: TestCase				(eglTestCtx, spec.name.c_str(), spec.desc.c_str())
905 	, glu::CallLogWrapper	(m_gl, eglTestCtx.getTestContext().getLog())
906 	, m_spec				(spec)
907 	, m_display				(EGL_NO_DISPLAY)
908 	, m_window				(DE_NULL)
909 	, m_surface				(EGL_NO_SURFACE)
910 	, m_config				(0)
911 	, m_curIter				(0)
912 	, m_refImg				(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
913 {
914 }
915 
~ImageFormatCase(void)916 ImageFormatCase::~ImageFormatCase (void)
917 {
918 	deinit();
919 }
920 
checkExtensions(void)921 void ImageFormatCase::checkExtensions (void)
922 {
923 	const Library&			egl		= m_eglTestCtx.getLibrary();
924 	const EGLDisplay		dpy		= m_display;
925 	set<string>				exts;
926 	const vector<string>	glExts	= de::splitString((const char*) m_gl.getString(GL_EXTENSIONS));
927 	const vector<string>	eglExts	= eglu::getDisplayExtensions(egl, dpy);
928 
929 	exts.insert(glExts.begin(), glExts.end());
930 	exts.insert(eglExts.begin(), eglExts.end());
931 
932 	if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5))
933 	{
934 		// EGL 1.5 has built-in support for EGLImage and GL sources
935 		exts.insert("EGL_KHR_image_base");
936 		exts.insert("EGL_KHR_gl_texture_2D_image");
937 		exts.insert("EGL_KHR_gl_texture_cubemap_image");
938 		exts.insert("EGL_KHR_gl_renderbuffer_image");
939 	}
940 
941 	if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
942 	{
943 		getLog() << tcu::TestLog::Message
944 				 << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
945 				 << "One should be supported."
946 				 << tcu::TestLog::EndMessage;
947 		TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
948 	}
949 
950 	for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
951 	{
952 		const TestSpec::Operation&	op	= m_spec.operations[operationNdx];
953 		const string				ext	= op.action->getRequiredExtension();
954 
955 		if (!de::contains(exts, ext))
956 			TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
957 	}
958 }
959 
init(void)960 void ImageFormatCase::init (void)
961 {
962 	const Library&						egl				= m_eglTestCtx.getLibrary();
963 	const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
964 
965 	try
966 	{
967 		m_display	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
968 		m_config	= getConfig();
969 		m_window	= windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
970 		m_surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL);
971 
972 		{
973 			const char* extensions[] = { "GL_OES_EGL_image" };
974 			m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
975 		}
976 
977 		for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
978 		{
979 			ImageApi* api = DE_NULL;
980 			switch (m_spec.contexts[contextNdx])
981 			{
982 				case TestSpec::API_GLES2:
983 				{
984 					api = new GLES2ImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config);
985 					break;
986 				}
987 
988 				default:
989 					DE_ASSERT(false);
990 					break;
991 			}
992 			m_apiContexts.push_back(api);
993 		}
994 		checkExtensions();
995 	}
996 	catch (...)
997 	{
998 		deinit();
999 		throw;
1000 	}
1001 }
1002 
deinit(void)1003 void ImageFormatCase::deinit (void)
1004 {
1005 	const Library& egl = m_eglTestCtx.getLibrary();
1006 
1007 	for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++)
1008 		delete m_apiContexts[contexNdx];
1009 
1010 	m_apiContexts.clear();
1011 
1012 	if (m_surface != EGL_NO_SURFACE)
1013 	{
1014 		egl.destroySurface(m_display, m_surface);
1015 		m_surface = EGL_NO_SURFACE;
1016 	}
1017 
1018 	delete m_window;
1019 	m_window = DE_NULL;
1020 
1021 	if (m_display != EGL_NO_DISPLAY)
1022 	{
1023 		egl.terminate(m_display);
1024 		m_display = EGL_NO_DISPLAY;
1025 	}
1026 }
1027 
iterate(void)1028 TestCase::IterateResult ImageFormatCase::iterate (void)
1029 {
1030 	const TestSpec::Operation&	op		= m_spec.operations[m_curIter++];
1031 	ImageApi&					api		= *m_apiContexts[op.apiIndex];
1032 	const bool					isOk	= op.action->invoke(api, m_img, m_refImg);
1033 
1034 	if (isOk && m_curIter < (int)m_spec.operations.size())
1035 		return CONTINUE;
1036 	else if (isOk)
1037 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1038 	else
1039 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1040 
1041 	return STOP;
1042 }
1043 
1044 struct LabeledAction
1045 {
1046 	string			label;
1047 	MovePtr<Action>	action;
1048 };
1049 
1050 // A simple vector mockup that we need because MovePtr isn't copy-constructible.
1051 struct LabeledActions
1052 {
LabeledActionsdeqp::egl::Image::LabeledActions1053 					LabeledActions	(void) : m_numActions(0){}
operator []deqp::egl::Image::LabeledActions1054 	LabeledAction&	operator[]		(int ndx)				{ DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
1055 	void			add				(const string& label, MovePtr<Action> action);
sizedeqp::egl::Image::LabeledActions1056 	int				size			(void) const			{ return m_numActions; }
1057 private:
1058 	LabeledAction	m_actions[32];
1059 	int				m_numActions;
1060 };
1061 
add(const string & label,MovePtr<Action> action)1062 void LabeledActions::add (const string& label, MovePtr<Action> action)
1063 {
1064 	DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
1065 	m_actions[m_numActions].label = label;
1066 	m_actions[m_numActions].action = action;
1067 	++m_numActions;
1068 }
1069 
1070 class ImageTests : public TestCaseGroup
1071 {
1072 protected:
ImageTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1073 					ImageTests						(EglTestContext& eglTestCtx, const string& name, const string& desc)
1074 						: TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
1075 
1076 	void			addCreateTexture				(const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type);
1077 	void			addCreateRenderbuffer			(const string& name, GLenum format);
1078 	void			addCreateAndroidNative			(const string& name, GLenum format);
1079 	void			addCreateTexture2DActions		(const string& prefix);
1080 	void			addCreateTextureCubemapActions	(const string& suffix, GLenum internalFormat, GLenum format, GLenum type);
1081 	void			addCreateRenderbufferActions	(void);
1082 	void			addCreateAndroidNativeActions	(void);
1083 
1084 	LabeledActions	m_createActions;
1085 };
1086 
addCreateTexture(const string & name,EGLenum source,GLenum internalFormat,GLenum format,GLenum type)1087 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type)
1088 {
1089 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createTextureImageSource(source, internalFormat, format, type))));
1090 }
1091 
addCreateRenderbuffer(const string & name,GLenum format)1092 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
1093 {
1094 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createRenderbufferImageSource(format))));
1095 }
1096 
addCreateAndroidNative(const string & name,GLenum format)1097 void ImageTests::addCreateAndroidNative (const string& name, GLenum format)
1098 {
1099 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createAndroidNativeImageSource(format))));
1100 }
1101 
addCreateTexture2DActions(const string & prefix)1102 void ImageTests::addCreateTexture2DActions (const string& prefix)
1103 {
1104 	addCreateTexture(prefix + "rgb8", 		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_BYTE);
1105 	addCreateTexture(prefix + "rgb565",		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_SHORT_5_6_5);
1106 	addCreateTexture(prefix + "rgba8",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_BYTE);
1107 	addCreateTexture(prefix + "rgb5_a1",	EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1);
1108 	addCreateTexture(prefix + "rgba4",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4);
1109 }
1110 
addCreateTextureCubemapActions(const string & suffix,GLenum internalFormat,GLenum format,GLenum type)1111 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum internalFormat, GLenum format, GLenum type)
1112 {
1113 	addCreateTexture("cubemap_positive_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, internalFormat,	format,	type);
1114 	addCreateTexture("cubemap_positive_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, internalFormat,	format,	type);
1115 	addCreateTexture("cubemap_positive_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, internalFormat,	format,	type);
1116 	addCreateTexture("cubemap_negative_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, internalFormat,	format,	type);
1117 	addCreateTexture("cubemap_negative_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, internalFormat,	format,	type);
1118 	addCreateTexture("cubemap_negative_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, internalFormat,	format,	type);
1119 }
1120 
addCreateRenderbufferActions(void)1121 void ImageTests::addCreateRenderbufferActions (void)
1122 {
1123 	addCreateRenderbuffer("renderbuffer_rgba4",		GL_RGBA4);
1124 	addCreateRenderbuffer("renderbuffer_rgb5_a1",	GL_RGB5_A1);
1125 	addCreateRenderbuffer("renderbuffer_rgb565",	GL_RGB565);
1126 	addCreateRenderbuffer("renderbuffer_depth16",	GL_DEPTH_COMPONENT16);
1127 	addCreateRenderbuffer("renderbuffer_stencil",	GL_STENCIL_INDEX8);
1128 }
1129 
addCreateAndroidNativeActions(void)1130 void ImageTests::addCreateAndroidNativeActions (void)
1131 {
1132 	addCreateAndroidNative("android_native_rgb565",		GL_RGB565);
1133 	addCreateAndroidNative("android_native_rgb8",		GL_RGB8);
1134 	addCreateAndroidNative("android_native_rgba4",		GL_RGBA4);
1135 	addCreateAndroidNative("android_native_rgb5_a1",	GL_RGB5_A1);
1136 	addCreateAndroidNative("android_native_rgba8",		GL_RGBA8);
1137 }
1138 
1139 class RenderTests : public ImageTests
1140 {
1141 protected:
RenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1142 											RenderTests				(EglTestContext& eglTestCtx, const string& name, const string& desc)
1143 												: ImageTests			(eglTestCtx, name, desc) {}
1144 
1145 	void									addRenderActions		(void);
1146 	LabeledActions							m_renderActions;
1147 };
1148 
addRenderActions(void)1149 void RenderTests::addRenderActions (void)
1150 {
1151 	m_renderActions.add("texture",			MovePtr<Action>(new GLES2ImageApi::RenderTexture2D()));
1152 	m_renderActions.add("read_pixels",		MovePtr<Action>(new GLES2ImageApi::RenderReadPixelsRenderbuffer()));
1153 	m_renderActions.add("depth_buffer",		MovePtr<Action>(new GLES2ImageApi::RenderDepthbuffer()));
1154 	m_renderActions.add("stencil_buffer",	MovePtr<Action>(new GLES2ImageApi::RenderStencilbuffer()));
1155 }
1156 
1157 class SimpleCreationTests : public RenderTests
1158 {
1159 public:
SimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1160 			SimpleCreationTests		(EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
1161 	void	init					(void);
1162 };
1163 
isDepthFormat(GLenum format)1164 bool isDepthFormat (GLenum format)
1165 {
1166 	switch (format)
1167 	{
1168 		case GL_RGB:
1169 		case GL_RGB8:
1170 		case GL_RGB565:
1171 		case GL_RGBA:
1172 		case GL_RGBA4:
1173 		case GL_RGBA8:
1174 		case GL_RGB5_A1:
1175 			return false;
1176 
1177 		case GL_DEPTH_COMPONENT16:
1178 			return true;
1179 
1180 		case GL_STENCIL_INDEX8:
1181 			return false;
1182 
1183 		default:
1184 			DE_ASSERT(false);
1185 			return false;
1186 	}
1187 }
1188 
isStencilFormat(GLenum format)1189 bool isStencilFormat (GLenum format)
1190 {
1191 	switch (format)
1192 	{
1193 		case GL_RGB:
1194 		case GL_RGB8:
1195 		case GL_RGB565:
1196 		case GL_RGBA:
1197 		case GL_RGBA4:
1198 		case GL_RGBA8:
1199 		case GL_RGB5_A1:
1200 			return false;
1201 
1202 		case GL_DEPTH_COMPONENT16:
1203 			return false;
1204 
1205 		case GL_STENCIL_INDEX8:
1206 			return true;
1207 
1208 		default:
1209 			DE_ASSERT(false);
1210 			return false;
1211 	}
1212 }
1213 
isCompatibleCreateAndRenderActions(const Action & create,const Action & render)1214 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render)
1215 {
1216 	if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1217 	{
1218 		const GLenum createFormat = gles2Create->getEffectiveFormat();
1219 
1220 		if (dynamic_cast<const GLES2ImageApi::RenderTexture2D*>(&render))
1221 		{
1222 			// GLES2 does not have depth or stencil textures
1223 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1224 				return false;
1225 		}
1226 
1227 		if (dynamic_cast<const GLES2ImageApi::RenderReadPixelsRenderbuffer*>(&render))
1228 		{
1229 			// GLES2 does not support readPixels for depth or stencil
1230 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1231 				return false;
1232 		}
1233 
1234 		if (dynamic_cast<const GLES2ImageApi::RenderDepthbuffer*>(&render))
1235 		{
1236 			// Copying non-depth data to depth renderbuffer and expecting meaningful
1237 			// results just doesn't make any sense.
1238 			if (!isDepthFormat(createFormat))
1239 				return false;
1240 		}
1241 
1242 		if (dynamic_cast<const GLES2ImageApi::RenderStencilbuffer*>(&render))
1243 		{
1244 			// Copying non-stencil data to stencil renderbuffer and expecting meaningful
1245 			// results just doesn't make any sense.
1246 			if (!isStencilFormat(createFormat))
1247 				return false;
1248 		}
1249 
1250 		return true;
1251 	}
1252 	else
1253 		DE_ASSERT(false);
1254 
1255 	return false;
1256 }
1257 
init(void)1258 void SimpleCreationTests::init (void)
1259 {
1260 	addCreateTexture2DActions("texture_");
1261 	addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1262 	addCreateTextureCubemapActions("_rgb", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1263 	addCreateRenderbufferActions();
1264 	addCreateAndroidNativeActions();
1265 	addRenderActions();
1266 
1267 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1268 	{
1269 		const LabeledAction& createAction = m_createActions[createNdx];
1270 
1271 		for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1272 		{
1273 			const LabeledAction&	renderAction	= m_renderActions[renderNdx];
1274 			TestSpec				spec;
1275 
1276 			if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1277 				continue;
1278 
1279 			spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1280 			spec.desc = spec.name;
1281 			spec.contexts.push_back(TestSpec::API_GLES2);
1282 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1283 			spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1284 
1285 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
1286 		}
1287 	}
1288 }
1289 
createSimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1290 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1291 {
1292 	return new SimpleCreationTests(eglTestCtx, name, desc);
1293 }
1294 
isCompatibleFormats(GLenum createFormat,GLenum modifyFormat,GLenum modifyType)1295 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat, GLenum modifyType)
1296 {
1297 	switch (modifyFormat)
1298 	{
1299 		case GL_RGB:
1300 			switch (modifyType)
1301 			{
1302 				case GL_UNSIGNED_BYTE:
1303 					return createFormat == GL_RGB
1304 							|| createFormat == GL_RGB8
1305 							|| createFormat == GL_RGB565
1306 							|| createFormat == GL_SRGB8;
1307 
1308 				case GL_BYTE:
1309 					return createFormat == GL_RGB8_SNORM;
1310 
1311 				case GL_UNSIGNED_SHORT_5_6_5:
1312 					return createFormat == GL_RGB
1313 							|| createFormat == GL_RGB565;
1314 
1315 				case GL_UNSIGNED_INT_10F_11F_11F_REV:
1316 					return createFormat == GL_R11F_G11F_B10F;
1317 
1318 				case GL_UNSIGNED_INT_5_9_9_9_REV:
1319 					return createFormat == GL_RGB9_E5;
1320 
1321 				case GL_HALF_FLOAT:
1322 					return createFormat == GL_RGB16F
1323 							|| createFormat == GL_R11F_G11F_B10F
1324 							|| createFormat == GL_RGB9_E5;
1325 
1326 				case GL_FLOAT:
1327 					return createFormat == GL_RGB16F
1328 							|| createFormat == GL_RGB32F
1329 							|| createFormat == GL_R11F_G11F_B10F
1330 							|| createFormat == GL_RGB9_E5;
1331 
1332 				default:
1333 					DE_FATAL("Unknown modify type");
1334 					return false;
1335 			}
1336 
1337 		case GL_RGBA:
1338 			switch (modifyType)
1339 			{
1340 				case GL_UNSIGNED_BYTE:
1341 					return createFormat == GL_RGBA8
1342 						|| createFormat == GL_RGB5_A1
1343 						|| createFormat == GL_RGBA4
1344 						|| createFormat == GL_SRGB8_ALPHA8
1345 						|| createFormat == GL_RGBA;
1346 
1347 				case GL_UNSIGNED_SHORT_4_4_4_4:
1348 					return createFormat == GL_RGBA4
1349 						|| createFormat == GL_RGBA;
1350 
1351 				case GL_UNSIGNED_SHORT_5_5_5_1:
1352 					return createFormat == GL_RGB5_A1
1353 						|| createFormat == GL_RGBA;
1354 
1355 				case GL_UNSIGNED_INT_2_10_10_10_REV:
1356 					return createFormat == GL_RGB10_A2
1357 						|| createFormat == GL_RGB5_A1;
1358 
1359 				case GL_HALF_FLOAT:
1360 					return createFormat == GL_RGBA16F;
1361 
1362 				case GL_FLOAT:
1363 					return createFormat == GL_RGBA16F
1364 						|| createFormat == GL_RGBA32F;
1365 
1366 				default:
1367 					DE_FATAL("Unknown modify type");
1368 					return false;
1369 			};
1370 
1371 		default:
1372 			DE_FATAL("Unknown modify format");
1373 			return false;
1374 	}
1375 }
1376 
isCompatibleCreateAndModifyActions(const Action & create,const Action & modify)1377 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify)
1378 {
1379 	if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1380 	{
1381 		const GLenum createFormat = gles2Create->getEffectiveFormat();
1382 
1383 		if (const GLES2ImageApi::ModifyTexSubImage* gles2TexSubImageModify = dynamic_cast<const GLES2ImageApi::ModifyTexSubImage*>(&modify))
1384 		{
1385 			const GLenum modifyFormat 	= gles2TexSubImageModify->getFormat();
1386 			const GLenum modifyType		= gles2TexSubImageModify->getType();
1387 
1388 			return isCompatibleFormats(createFormat, modifyFormat, modifyType);
1389 		}
1390 
1391 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearColor*>(&modify))
1392 		{
1393 			// reintepreting color as non-color is not meaningful
1394 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1395 				return false;
1396 		}
1397 
1398 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearDepth*>(&modify))
1399 		{
1400 			// reintepreting depth as non-depth is not meaningful
1401 			if (!isDepthFormat(createFormat))
1402 				return false;
1403 		}
1404 
1405 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearStencil*>(&modify))
1406 		{
1407 			// reintepreting stencil as non-stencil is not meaningful
1408 			if (!isStencilFormat(createFormat))
1409 				return false;
1410 		}
1411 
1412 		return true;
1413 	}
1414 	else
1415 		DE_ASSERT(false);
1416 
1417 	return false;
1418 }
1419 
1420 class MultiContextRenderTests : public RenderTests
1421 {
1422 public:
1423 					MultiContextRenderTests		(EglTestContext& eglTestCtx, const string& name, const string& desc);
1424 	void			init						(void);
1425 	void			addClearActions				(void);
1426 private:
1427 	LabeledActions	m_clearActions;
1428 };
1429 
MultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1430 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1431 	: RenderTests	(eglTestCtx, name, desc)
1432 {
1433 }
1434 
addClearActions(void)1435 void MultiContextRenderTests::addClearActions (void)
1436 {
1437 	m_clearActions.add("renderbuffer_clear_color",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f))));
1438 	m_clearActions.add("renderbuffer_clear_depth",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.75f)));
1439 	m_clearActions.add("renderbuffer_clear_stencil",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(97)));
1440 }
1441 
init(void)1442 void MultiContextRenderTests::init (void)
1443 {
1444 	addCreateTexture2DActions("texture_");
1445 	addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1446 	addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1447 	addCreateRenderbufferActions();
1448 	addCreateAndroidNativeActions();
1449 	addRenderActions();
1450 	addClearActions();
1451 
1452 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1453 	for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1454 	for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++)
1455 	{
1456 		const LabeledAction&	createAction	= m_createActions[createNdx];
1457 		const LabeledAction&	renderAction	= m_renderActions[renderNdx];
1458 		const LabeledAction&	clearAction		= m_clearActions[clearNdx];
1459 		TestSpec				spec;
1460 
1461 		if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1462 			continue;
1463 		if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action))
1464 			continue;
1465 
1466 		spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1467 		spec.desc = spec.name;
1468 
1469 		spec.contexts.push_back(TestSpec::API_GLES2);
1470 		spec.contexts.push_back(TestSpec::API_GLES2);
1471 
1472 		spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1473 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1474 		spec.operations.push_back(TestSpec::Operation(0, *clearAction.action));
1475 		spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
1476 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1477 		spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
1478 
1479 		addChild(new ImageFormatCase(m_eglTestCtx, spec));
1480 	}
1481 }
1482 
createMultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1483 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1484 {
1485 	return new MultiContextRenderTests(eglTestCtx, name, desc);
1486 }
1487 
1488 class ModifyTests : public ImageTests
1489 {
1490 public:
ModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1491 								ModifyTests		(EglTestContext& eglTestCtx, const string& name, const string& desc)
1492 									: ImageTests(eglTestCtx, name, desc) {}
1493 
1494 	void						init			(void);
1495 
1496 protected:
1497 	void						addModifyActions(void);
1498 
1499 	LabeledActions				m_modifyActions;
1500 	GLES2ImageApi::RenderTryAll	m_renderAction;
1501 };
1502 
addModifyActions(void)1503 void ModifyTests::addModifyActions (void)
1504 {
1505 	m_modifyActions.add("tex_subimage_rgb8",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,	GL_UNSIGNED_BYTE)));
1506 	m_modifyActions.add("tex_subimage_rgb565",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB, 	GL_UNSIGNED_SHORT_5_6_5)));
1507 	m_modifyActions.add("tex_subimage_rgba8",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_BYTE)));
1508 	m_modifyActions.add("tex_subimage_rgb5_a1",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1)));
1509 	m_modifyActions.add("tex_subimage_rgba4",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4)));
1510 
1511 	m_modifyActions.add("renderbuffer_clear_color",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
1512 	m_modifyActions.add("renderbuffer_clear_depth",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.7f)));
1513 	m_modifyActions.add("renderbuffer_clear_stencil",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(78)));
1514 }
1515 
init(void)1516 void ModifyTests::init (void)
1517 {
1518 	addCreateTexture2DActions("tex_");
1519 	addCreateRenderbufferActions();
1520 	addCreateAndroidNativeActions();
1521 	addModifyActions();
1522 
1523 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1524 	{
1525 		LabeledAction& createAction = m_createActions[createNdx];
1526 
1527 		for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
1528 		{
1529 			LabeledAction& modifyAction = m_modifyActions[modifyNdx];
1530 
1531 			if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action))
1532 				continue;
1533 
1534 			TestSpec spec;
1535 			spec.name = createAction.label + "_" + modifyAction.label;
1536 			spec.desc = "gles2_tex_sub_image";
1537 
1538 			spec.contexts.push_back(TestSpec::API_GLES2);
1539 
1540 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1541 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1542 			spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
1543 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1544 
1545 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
1546 		}
1547 	}
1548 }
1549 
createModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1550 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1551 {
1552 	return new ModifyTests(eglTestCtx, name, desc);
1553 }
1554 
1555 } // Image
1556 } // egl
1557 } // deqp
1558