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