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