• 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_egl, 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 	switch (glu::getInternalFormat(reference.getFormat()))
710 	{
711 		case GL_RGBA4:
712 		case GL_RGB5_A1:
713 		case GL_RGB565:
714 			break;
715 		default:
716 			// Skip, not in the list of allowed render buffer formats for GLES2.
717 			throw tcu::NotSupportedError("Image format not allowed for glReadPixels.");
718 			break;
719 	}
720 
721 	log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
722 
723 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
724 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
725 	imageTargetRenderbuffer(api.m_egl, gl, **img);
726 
727 	GLU_EXPECT_NO_ERROR(gl.getError(), "imageTargetRenderbuffer");
728 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
729 	GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferRenderbuffer");
730 
731 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
732 
733 	GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
734 
735 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
736 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
737 	GLU_CHECK_GLW_CALL(gl, finish());
738 
739 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
740 
741 	return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
742 
743 }
744 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const745 bool GLES2ImageApi::RenderTryAll::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
746 {
747 	bool										foundSupported			= false;
748 	tcu::TestLog&								log						= api.getLog();
749 	GLES2ImageApi::RenderTexture2D				renderTex2D;
750 	GLES2ImageApi::RenderReadPixelsRenderbuffer	renderReadPixels;
751 	GLES2ImageApi::RenderDepthbuffer			renderDepth;
752 	GLES2ImageApi::RenderStencilbuffer			renderStencil;
753 	Action*										actions[]				= { &renderTex2D, &renderReadPixels, &renderDepth, &renderStencil };
754 
755 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
756 	{
757 		try
758 		{
759 			if (!actions[ndx]->invoke(api, img, reference))
760 				return false;
761 
762 			foundSupported = true;
763 		}
764 		catch (const tcu::NotSupportedError& error)
765 		{
766 			log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
767 		}
768 		catch (const IllegalRendererException&)
769 		{
770 			// not valid renderer
771 		}
772 	}
773 
774 	if (!foundSupported)
775 		throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
776 
777 	return true;
778 }
779 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const780 bool GLES2ImageApi::ModifyTexSubImage::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
781 {
782 	const glw::Functions&	gl		= api.m_gl;
783 	tcu::TestLog&			log		= api.getLog();
784 	glu::Texture			srcTex	(gl);
785 	const int				xOffset	= 8;
786 	const int				yOffset	= 16;
787 	const int				xSize	= de::clamp(16, 0, reference.getWidth() - xOffset);
788 	const int				ySize	= de::clamp(16, 0, reference.getHeight() - yOffset);
789 	tcu::Texture2D			src		(glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
790 
791 	log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
792 
793 	src.allocLevel(0);
794 	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));
795 
796 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
797 	imageTargetTexture2D(api.m_egl, gl, **img);
798 	GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
799 	GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
800 	GLU_CHECK_GLW_CALL(gl, finish());
801 
802 	tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
803 
804 	return true;
805 }
806 
invokeGLES2(GLES2ImageApi & api,MovePtr<UniqueImage> & img,tcu::Texture2D & reference) const807 bool GLES2ImageApi::ModifyRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
808 {
809 	const glw::Functions&	gl				= api.m_gl;
810 	tcu::TestLog&			log				= api.getLog();
811 	glu::Framebuffer		framebuffer		(gl);
812 	glu::Renderbuffer		renderbuffer	(gl);
813 
814 	log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
815 
816 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
817 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
818 
819 	imageTargetRenderbuffer(api.m_egl, gl, **img);
820 
821 	initializeRbo(api, *renderbuffer, reference);
822 
823 	GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
824 	GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
825 
826 	GLU_CHECK_GLW_CALL(gl, finish());
827 
828 	return true;
829 }
830 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const831 void GLES2ImageApi::ModifyRenderbufferClearColor::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
832 {
833 	const glw::Functions&	gl		= api.m_gl;
834 
835 	framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
836 
837 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
838 	GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w()));
839 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
840 
841 	tcu::clear(reference.getLevel(0), m_color);
842 }
843 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const844 void GLES2ImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
845 {
846 	const glw::Functions&	gl		= api.m_gl;
847 
848 	framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
849 
850 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
851 	GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth));
852 	GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
853 
854 	tcu::clearDepth(reference.getLevel(0), m_depth);
855 }
856 
initializeRbo(GLES2ImageApi & api,GLuint renderbuffer,tcu::Texture2D & reference) const857 void GLES2ImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
858 {
859 	const glw::Functions&	gl		= api.m_gl;
860 
861 	framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
862 
863 	GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
864 	GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil));
865 	GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
866 
867 	tcu::clearStencil(reference.getLevel(0), m_stencil);
868 }
869 
870 class ImageFormatCase : public TestCase, private glu::CallLogWrapper
871 {
872 public:
873 						ImageFormatCase		(EglTestContext& eglTestCtx, const TestSpec& spec);
874 						~ImageFormatCase	(void);
875 
876 	void				init				(void);
877 	void				deinit				(void);
878 	IterateResult		iterate				(void);
879 	void				checkExtensions		(void);
880 
881 private:
882 	EGLConfig			getConfig			(void);
883 
884 	const TestSpec		m_spec;
885 
886 	vector<ImageApi*>	m_apiContexts;
887 
888 	EGLDisplay			m_display;
889 	eglu::NativeWindow*	m_window;
890 	EGLSurface			m_surface;
891 	EGLConfig			m_config;
892 	int					m_curIter;
893 	MovePtr<UniqueImage>m_img;
894 	tcu::Texture2D		m_refImg;
895 	glw::Functions		m_gl;
896 };
897 
getConfig(void)898 EGLConfig ImageFormatCase::getConfig (void)
899 {
900 	const EGLint attribList[] =
901 	{
902 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
903 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
904 		EGL_RED_SIZE,			8,
905 		EGL_BLUE_SIZE,			8,
906 		EGL_GREEN_SIZE,			8,
907 		EGL_ALPHA_SIZE,			8,
908 		EGL_DEPTH_SIZE,			8,
909 		EGL_NONE
910 	};
911 
912 	return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList);
913 }
914 
ImageFormatCase(EglTestContext & eglTestCtx,const TestSpec & spec)915 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
916 	: TestCase				(eglTestCtx, spec.name.c_str(), spec.desc.c_str())
917 	, glu::CallLogWrapper	(m_gl, eglTestCtx.getTestContext().getLog())
918 	, m_spec				(spec)
919 	, m_display				(EGL_NO_DISPLAY)
920 	, m_window				(DE_NULL)
921 	, m_surface				(EGL_NO_SURFACE)
922 	, m_config				(0)
923 	, m_curIter				(0)
924 	, m_refImg				(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
925 {
926 }
927 
~ImageFormatCase(void)928 ImageFormatCase::~ImageFormatCase (void)
929 {
930 	deinit();
931 }
932 
checkExtensions(void)933 void ImageFormatCase::checkExtensions (void)
934 {
935 	const Library&			egl		= m_eglTestCtx.getLibrary();
936 	const EGLDisplay		dpy		= m_display;
937 	set<string>				exts;
938 	const vector<string>	glExts	= de::splitString((const char*) m_gl.getString(GL_EXTENSIONS));
939 	const vector<string>	eglExts	= eglu::getDisplayExtensions(egl, dpy);
940 
941 	exts.insert(glExts.begin(), glExts.end());
942 	exts.insert(eglExts.begin(), eglExts.end());
943 
944 	if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5))
945 	{
946 		// EGL 1.5 has built-in support for EGLImage and GL sources
947 		exts.insert("EGL_KHR_image_base");
948 		exts.insert("EGL_KHR_gl_texture_2D_image");
949 		exts.insert("EGL_KHR_gl_texture_cubemap_image");
950 		exts.insert("EGL_KHR_gl_renderbuffer_image");
951 	}
952 
953 	if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
954 	{
955 		getLog() << tcu::TestLog::Message
956 				 << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
957 				 << "One should be supported."
958 				 << tcu::TestLog::EndMessage;
959 		TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
960 	}
961 
962 	for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
963 	{
964 		const TestSpec::Operation&	op	= m_spec.operations[operationNdx];
965 		const string				ext	= op.action->getRequiredExtension();
966 
967 		if (!de::contains(exts, ext))
968 			TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
969 	}
970 }
971 
init(void)972 void ImageFormatCase::init (void)
973 {
974 	const Library&						egl				= m_eglTestCtx.getLibrary();
975 	const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
976 
977 	try
978 	{
979 		m_display	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
980 		m_config	= getConfig();
981 		m_window	= windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
982 		m_surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL);
983 
984 		{
985 			const char* extensions[] = { "GL_OES_EGL_image" };
986 			m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
987 		}
988 
989 		for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
990 		{
991 			ImageApi* api = DE_NULL;
992 			switch (m_spec.contexts[contextNdx])
993 			{
994 				case TestSpec::API_GLES2:
995 				{
996 					api = new GLES2ImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config);
997 					break;
998 				}
999 
1000 				default:
1001 					DE_ASSERT(false);
1002 					break;
1003 			}
1004 			m_apiContexts.push_back(api);
1005 		}
1006 		checkExtensions();
1007 	}
1008 	catch (...)
1009 	{
1010 		deinit();
1011 		throw;
1012 	}
1013 }
1014 
deinit(void)1015 void ImageFormatCase::deinit (void)
1016 {
1017 	const Library& egl = m_eglTestCtx.getLibrary();
1018 
1019 	m_img.clear();
1020 
1021 	for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++)
1022 		delete m_apiContexts[contexNdx];
1023 
1024 	m_apiContexts.clear();
1025 
1026 	if (m_surface != EGL_NO_SURFACE)
1027 	{
1028 		egl.destroySurface(m_display, m_surface);
1029 		m_surface = EGL_NO_SURFACE;
1030 	}
1031 
1032 	delete m_window;
1033 	m_window = DE_NULL;
1034 
1035 	if (m_display != EGL_NO_DISPLAY)
1036 	{
1037 		egl.terminate(m_display);
1038 		m_display = EGL_NO_DISPLAY;
1039 	}
1040 }
1041 
iterate(void)1042 TestCase::IterateResult ImageFormatCase::iterate (void)
1043 {
1044 	const TestSpec::Operation&	op		= m_spec.operations[m_curIter++];
1045 	ImageApi&					api		= *m_apiContexts[op.apiIndex];
1046 	const bool					isOk	= op.action->invoke(api, m_img, m_refImg);
1047 
1048 	if (isOk && m_curIter < (int)m_spec.operations.size())
1049 		return CONTINUE;
1050 	else if (isOk)
1051 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1052 	else
1053 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1054 
1055 	return STOP;
1056 }
1057 
1058 struct LabeledAction
1059 {
1060 	string			label;
1061 	MovePtr<Action>	action;
1062 };
1063 
1064 // A simple vector mockup that we need because MovePtr isn't copy-constructible.
1065 struct LabeledActions
1066 {
LabeledActionsdeqp::egl::Image::LabeledActions1067 					LabeledActions	(void) : m_numActions(0){}
operator []deqp::egl::Image::LabeledActions1068 	LabeledAction&	operator[]		(int ndx)				{ DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
1069 	void			add				(const string& label, MovePtr<Action> action);
sizedeqp::egl::Image::LabeledActions1070 	int				size			(void) const			{ return m_numActions; }
1071 private:
1072 	LabeledAction	m_actions[64];
1073 	int				m_numActions;
1074 };
1075 
add(const string & label,MovePtr<Action> action)1076 void LabeledActions::add (const string& label, MovePtr<Action> action)
1077 {
1078 	DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
1079 	m_actions[m_numActions].label = label;
1080 	m_actions[m_numActions].action = action;
1081 	++m_numActions;
1082 }
1083 
1084 class ImageTests : public TestCaseGroup
1085 {
1086 protected:
ImageTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1087 					ImageTests						(EglTestContext& eglTestCtx, const string& name, const string& desc)
1088 						: TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
1089 
1090 	void			addCreateTexture				(const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type);
1091 	void			addCreateRenderbuffer			(const string& name, GLenum format);
1092 	void			addCreateAndroidNative			(const string& name, GLenum format);
1093 	void			addCreateTexture2DActions		(const string& prefix);
1094 	void			addCreateTextureCubemapActions	(const string& suffix, GLenum internalFormat, GLenum format, GLenum type);
1095 	void			addCreateRenderbufferActions	(void);
1096 	void			addCreateAndroidNativeActions	(void);
1097 
1098 	LabeledActions	m_createActions;
1099 };
1100 
addCreateTexture(const string & name,EGLenum source,GLenum internalFormat,GLenum format,GLenum type)1101 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum internalFormat, GLenum format, GLenum type)
1102 {
1103 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createTextureImageSource(source, internalFormat, format, type))));
1104 }
1105 
addCreateRenderbuffer(const string & name,GLenum format)1106 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
1107 {
1108 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createRenderbufferImageSource(format))));
1109 }
1110 
addCreateAndroidNative(const string & name,GLenum format)1111 void ImageTests::addCreateAndroidNative (const string& name, GLenum format)
1112 {
1113 	m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createAndroidNativeImageSource(format))));
1114 }
1115 
addCreateTexture2DActions(const string & prefix)1116 void ImageTests::addCreateTexture2DActions (const string& prefix)
1117 {
1118 	addCreateTexture(prefix + "rgb8",		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_BYTE);
1119 	addCreateTexture(prefix + "rgb565",		EGL_GL_TEXTURE_2D_KHR,	GL_RGB,		GL_RGB,		GL_UNSIGNED_SHORT_5_6_5);
1120 	addCreateTexture(prefix + "rgba8",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_BYTE);
1121 	addCreateTexture(prefix + "rgb5_a1",	EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1);
1122 	addCreateTexture(prefix + "rgba4",		EGL_GL_TEXTURE_2D_KHR,	GL_RGBA,	GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4);
1123 }
1124 
addCreateTextureCubemapActions(const string & suffix,GLenum internalFormat,GLenum format,GLenum type)1125 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum internalFormat, GLenum format, GLenum type)
1126 {
1127 	addCreateTexture("cubemap_positive_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, internalFormat,	format,	type);
1128 	addCreateTexture("cubemap_positive_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, internalFormat,	format,	type);
1129 	addCreateTexture("cubemap_positive_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, internalFormat,	format,	type);
1130 	addCreateTexture("cubemap_negative_x" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, internalFormat,	format,	type);
1131 	addCreateTexture("cubemap_negative_y" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, internalFormat,	format,	type);
1132 	addCreateTexture("cubemap_negative_z" + suffix,	EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, internalFormat,	format,	type);
1133 }
1134 
addCreateRenderbufferActions(void)1135 void ImageTests::addCreateRenderbufferActions (void)
1136 {
1137 	addCreateRenderbuffer("renderbuffer_rgba4",		GL_RGBA4);
1138 	addCreateRenderbuffer("renderbuffer_rgb5_a1",	GL_RGB5_A1);
1139 	addCreateRenderbuffer("renderbuffer_rgb565",	GL_RGB565);
1140 	addCreateRenderbuffer("renderbuffer_depth16",	GL_DEPTH_COMPONENT16);
1141 	addCreateRenderbuffer("renderbuffer_stencil",	GL_STENCIL_INDEX8);
1142 }
1143 
addCreateAndroidNativeActions(void)1144 void ImageTests::addCreateAndroidNativeActions (void)
1145 {
1146 	addCreateAndroidNative("android_native_rgba4",		GL_RGBA4);
1147 	addCreateAndroidNative("android_native_rgb5_a1",	GL_RGB5_A1);
1148 	addCreateAndroidNative("android_native_rgb565",		GL_RGB565);
1149 	addCreateAndroidNative("android_native_rgb8",		GL_RGB8);
1150 	addCreateAndroidNative("android_native_rgba8",		GL_RGBA8);
1151 	addCreateAndroidNative("android_native_d16",		GL_DEPTH_COMPONENT16);
1152 	addCreateAndroidNative("android_native_d24",		GL_DEPTH_COMPONENT24);
1153 	addCreateAndroidNative("android_native_d24s8",		GL_DEPTH24_STENCIL8);
1154 	addCreateAndroidNative("android_native_d32f",		GL_DEPTH_COMPONENT32F);
1155 	addCreateAndroidNative("android_native_d32fs8",		GL_DEPTH32F_STENCIL8);
1156 	addCreateAndroidNative("android_native_rgb10a2",	GL_RGB10_A2);
1157 	addCreateAndroidNative("android_native_rgba16f",	GL_RGBA16F);
1158 	addCreateAndroidNative("android_native_s8",			GL_STENCIL_INDEX8);
1159 }
1160 
1161 class RenderTests : public ImageTests
1162 {
1163 protected:
RenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1164 											RenderTests				(EglTestContext& eglTestCtx, const string& name, const string& desc)
1165 												: ImageTests			(eglTestCtx, name, desc) {}
1166 
1167 	void									addRenderActions		(void);
1168 	LabeledActions							m_renderActions;
1169 };
1170 
addRenderActions(void)1171 void RenderTests::addRenderActions (void)
1172 {
1173 	m_renderActions.add("texture",			MovePtr<Action>(new GLES2ImageApi::RenderTexture2D()));
1174 	m_renderActions.add("read_pixels",		MovePtr<Action>(new GLES2ImageApi::RenderReadPixelsRenderbuffer()));
1175 	m_renderActions.add("depth_buffer",		MovePtr<Action>(new GLES2ImageApi::RenderDepthbuffer()));
1176 	m_renderActions.add("stencil_buffer",	MovePtr<Action>(new GLES2ImageApi::RenderStencilbuffer()));
1177 }
1178 
1179 class SimpleCreationTests : public RenderTests
1180 {
1181 public:
SimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1182 			SimpleCreationTests		(EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
1183 	void	init					(void);
1184 };
1185 
isDepthFormat(GLenum format)1186 bool isDepthFormat (GLenum format)
1187 {
1188 	switch (format)
1189 	{
1190 		case GL_RGB:
1191 		case GL_RGB8:
1192 		case GL_RGB565:
1193 		case GL_RGBA:
1194 		case GL_RGBA4:
1195 		case GL_RGBA8:
1196 		case GL_RGB5_A1:
1197 		case GL_RGB10_A2:
1198 		case GL_RGBA16F:
1199 			return false;
1200 
1201 		case GL_DEPTH_COMPONENT16:
1202 		case GL_DEPTH_COMPONENT24:
1203 		case GL_DEPTH_COMPONENT32:
1204 		case GL_DEPTH_COMPONENT32F:
1205 		case GL_DEPTH24_STENCIL8:
1206 		case GL_DEPTH32F_STENCIL8:
1207 			return true;
1208 
1209 		case GL_STENCIL_INDEX8:
1210 			return false;
1211 
1212 		default:
1213 			DE_ASSERT(false);
1214 			return false;
1215 	}
1216 }
1217 
isStencilFormat(GLenum format)1218 bool isStencilFormat (GLenum format)
1219 {
1220 	switch (format)
1221 	{
1222 		case GL_RGB:
1223 		case GL_RGB8:
1224 		case GL_RGB565:
1225 		case GL_RGBA:
1226 		case GL_RGBA4:
1227 		case GL_RGBA8:
1228 		case GL_RGB5_A1:
1229 		case GL_RGB10_A2:
1230 		case GL_RGBA16F:
1231 			return false;
1232 
1233 		case GL_DEPTH_COMPONENT16:
1234 		case GL_DEPTH_COMPONENT24:
1235 		case GL_DEPTH_COMPONENT32:
1236 		case GL_DEPTH_COMPONENT32F:
1237 			return false;
1238 
1239 		case GL_STENCIL_INDEX8:
1240 		case GL_DEPTH24_STENCIL8:
1241 		case GL_DEPTH32F_STENCIL8:
1242 			return true;
1243 
1244 		default:
1245 			DE_ASSERT(false);
1246 			return false;
1247 	}
1248 }
1249 
isCompatibleCreateAndRenderActions(const Action & create,const Action & render)1250 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render)
1251 {
1252 	if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1253 	{
1254 		const GLenum createFormat = gles2Create->getEffectiveFormat();
1255 
1256 		if (dynamic_cast<const GLES2ImageApi::RenderTexture2D*>(&render))
1257 		{
1258 			// GLES2 does not have depth or stencil textures
1259 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1260 				return false;
1261 		}
1262 
1263 		if (dynamic_cast<const GLES2ImageApi::RenderReadPixelsRenderbuffer*>(&render))
1264 		{
1265 			// GLES2 does not support readPixels for depth or stencil
1266 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1267 				return false;
1268 		}
1269 
1270 		if (dynamic_cast<const GLES2ImageApi::RenderDepthbuffer*>(&render))
1271 		{
1272 			// Copying non-depth data to depth renderbuffer and expecting meaningful
1273 			// results just doesn't make any sense.
1274 			if (!isDepthFormat(createFormat))
1275 				return false;
1276 		}
1277 
1278 		if (dynamic_cast<const GLES2ImageApi::RenderStencilbuffer*>(&render))
1279 		{
1280 			// Copying non-stencil data to stencil renderbuffer and expecting meaningful
1281 			// results just doesn't make any sense.
1282 			if (!isStencilFormat(createFormat))
1283 				return false;
1284 		}
1285 
1286 		return true;
1287 	}
1288 	else
1289 		DE_ASSERT(false);
1290 
1291 	return false;
1292 }
1293 
init(void)1294 void SimpleCreationTests::init (void)
1295 {
1296 	addCreateTexture2DActions("texture_");
1297 	addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1298 	addCreateTextureCubemapActions("_rgb", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1299 	addCreateRenderbufferActions();
1300 	addCreateAndroidNativeActions();
1301 	addRenderActions();
1302 
1303 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1304 	{
1305 		const LabeledAction& createAction = m_createActions[createNdx];
1306 
1307 		for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1308 		{
1309 			const LabeledAction&	renderAction	= m_renderActions[renderNdx];
1310 			TestSpec				spec;
1311 
1312 			if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1313 				continue;
1314 
1315 			spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1316 			spec.desc = spec.name;
1317 			spec.contexts.push_back(TestSpec::API_GLES2);
1318 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1319 			spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1320 
1321 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
1322 		}
1323 	}
1324 }
1325 
createSimpleCreationTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1326 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1327 {
1328 	return new SimpleCreationTests(eglTestCtx, name, desc);
1329 }
1330 
isCompatibleFormats(GLenum createFormat,GLenum modifyFormat,GLenum modifyType)1331 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat, GLenum modifyType)
1332 {
1333 	switch (modifyFormat)
1334 	{
1335 		case GL_RGB:
1336 			switch (modifyType)
1337 			{
1338 				case GL_UNSIGNED_BYTE:
1339 					return createFormat == GL_RGB
1340 							|| createFormat == GL_RGB8
1341 							|| createFormat == GL_RGB565
1342 							|| createFormat == GL_SRGB8;
1343 
1344 				case GL_BYTE:
1345 					return createFormat == GL_RGB8_SNORM;
1346 
1347 				case GL_UNSIGNED_SHORT_5_6_5:
1348 					return createFormat == GL_RGB
1349 							|| createFormat == GL_RGB565;
1350 
1351 				case GL_UNSIGNED_INT_10F_11F_11F_REV:
1352 					return createFormat == GL_R11F_G11F_B10F;
1353 
1354 				case GL_UNSIGNED_INT_5_9_9_9_REV:
1355 					return createFormat == GL_RGB9_E5;
1356 
1357 				case GL_HALF_FLOAT:
1358 					return createFormat == GL_RGB16F
1359 							|| createFormat == GL_R11F_G11F_B10F
1360 							|| createFormat == GL_RGB9_E5;
1361 
1362 				case GL_FLOAT:
1363 					return createFormat == GL_RGB16F
1364 							|| createFormat == GL_RGB32F
1365 							|| createFormat == GL_R11F_G11F_B10F
1366 							|| createFormat == GL_RGB9_E5;
1367 
1368 				default:
1369 					DE_FATAL("Unknown modify type");
1370 					return false;
1371 			}
1372 
1373 		case GL_RGBA:
1374 			switch (modifyType)
1375 			{
1376 				case GL_UNSIGNED_BYTE:
1377 					return createFormat == GL_RGBA8
1378 						|| createFormat == GL_RGB5_A1
1379 						|| createFormat == GL_RGBA4
1380 						|| createFormat == GL_SRGB8_ALPHA8
1381 						|| createFormat == GL_RGBA;
1382 
1383 				case GL_UNSIGNED_SHORT_4_4_4_4:
1384 					return createFormat == GL_RGBA4
1385 						|| createFormat == GL_RGBA;
1386 
1387 				case GL_UNSIGNED_SHORT_5_5_5_1:
1388 					return createFormat == GL_RGB5_A1
1389 						|| createFormat == GL_RGBA;
1390 
1391 				case GL_UNSIGNED_INT_2_10_10_10_REV:
1392 					return createFormat == GL_RGB10_A2
1393 						|| createFormat == GL_RGB5_A1;
1394 
1395 				case GL_HALF_FLOAT:
1396 					return createFormat == GL_RGBA16F;
1397 
1398 				case GL_FLOAT:
1399 					return createFormat == GL_RGBA16F
1400 						|| createFormat == GL_RGBA32F;
1401 
1402 				default:
1403 					DE_FATAL("Unknown modify type");
1404 					return false;
1405 			};
1406 
1407 		default:
1408 			DE_FATAL("Unknown modify format");
1409 			return false;
1410 	}
1411 }
1412 
isCompatibleCreateAndModifyActions(const Action & create,const Action & modify)1413 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify)
1414 {
1415 	if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create))
1416 	{
1417 		const GLenum createFormat = gles2Create->getEffectiveFormat();
1418 
1419 		if (const GLES2ImageApi::ModifyTexSubImage* gles2TexSubImageModify = dynamic_cast<const GLES2ImageApi::ModifyTexSubImage*>(&modify))
1420 		{
1421 			const GLenum modifyFormat	= gles2TexSubImageModify->getFormat();
1422 			const GLenum modifyType		= gles2TexSubImageModify->getType();
1423 
1424 			return isCompatibleFormats(createFormat, modifyFormat, modifyType);
1425 		}
1426 
1427 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearColor*>(&modify))
1428 		{
1429 			// reintepreting color as non-color is not meaningful
1430 			if (isDepthFormat(createFormat) || isStencilFormat(createFormat))
1431 				return false;
1432 		}
1433 
1434 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearDepth*>(&modify))
1435 		{
1436 			// reintepreting depth as non-depth is not meaningful
1437 			if (!isDepthFormat(createFormat))
1438 				return false;
1439 		}
1440 
1441 		if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearStencil*>(&modify))
1442 		{
1443 			// reintepreting stencil as non-stencil is not meaningful
1444 			if (!isStencilFormat(createFormat))
1445 				return false;
1446 		}
1447 
1448 		return true;
1449 	}
1450 	else
1451 		DE_ASSERT(false);
1452 
1453 	return false;
1454 }
1455 
1456 class MultiContextRenderTests : public RenderTests
1457 {
1458 public:
1459 					MultiContextRenderTests		(EglTestContext& eglTestCtx, const string& name, const string& desc);
1460 	void			init						(void);
1461 	void			addClearActions				(void);
1462 private:
1463 	LabeledActions	m_clearActions;
1464 };
1465 
MultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1466 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1467 	: RenderTests	(eglTestCtx, name, desc)
1468 {
1469 }
1470 
addClearActions(void)1471 void MultiContextRenderTests::addClearActions (void)
1472 {
1473 	m_clearActions.add("clear_color",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f))));
1474 	m_clearActions.add("clear_depth",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.75f)));
1475 	m_clearActions.add("clear_stencil",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(97)));
1476 }
1477 
init(void)1478 void MultiContextRenderTests::init (void)
1479 {
1480 	addCreateTexture2DActions("texture_");
1481 	addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1482 	addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
1483 	addCreateRenderbufferActions();
1484 	addCreateAndroidNativeActions();
1485 	addRenderActions();
1486 	addClearActions();
1487 
1488 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1489 	for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
1490 	for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++)
1491 	{
1492 		const LabeledAction&	createAction	= m_createActions[createNdx];
1493 		const LabeledAction&	renderAction	= m_renderActions[renderNdx];
1494 		const LabeledAction&	clearAction		= m_clearActions[clearNdx];
1495 		TestSpec				spec;
1496 
1497 		if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action))
1498 			continue;
1499 		if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action))
1500 			continue;
1501 
1502 		spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
1503 
1504 		const GLenum createFormat = dynamic_cast<const GLES2ImageApi::Create*>(createAction.action.get())->getEffectiveFormat();
1505 		if (isDepthFormat(createFormat) && isStencilFormat(createFormat))
1506 		{
1507 			// Combined depth and stencil format. Add the clear action label to avoid test
1508 			// name clashes.
1509 			spec.name += std::string("_") + clearAction.label;
1510 		}
1511 
1512 		spec.desc = spec.name;
1513 
1514 		spec.contexts.push_back(TestSpec::API_GLES2);
1515 		spec.contexts.push_back(TestSpec::API_GLES2);
1516 
1517 		spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1518 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1519 		spec.operations.push_back(TestSpec::Operation(0, *clearAction.action));
1520 		spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
1521 		spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
1522 		spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
1523 
1524 		addChild(new ImageFormatCase(m_eglTestCtx, spec));
1525 	}
1526 }
1527 
createMultiContextRenderTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1528 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1529 {
1530 	return new MultiContextRenderTests(eglTestCtx, name, desc);
1531 }
1532 
1533 class ModifyTests : public ImageTests
1534 {
1535 public:
ModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1536 								ModifyTests		(EglTestContext& eglTestCtx, const string& name, const string& desc)
1537 									: ImageTests(eglTestCtx, name, desc) {}
1538 
1539 	void						init			(void);
1540 
1541 protected:
1542 	void						addModifyActions(void);
1543 
1544 	LabeledActions				m_modifyActions;
1545 	GLES2ImageApi::RenderTryAll	m_renderAction;
1546 };
1547 
addModifyActions(void)1548 void ModifyTests::addModifyActions (void)
1549 {
1550 	m_modifyActions.add("tex_subimage_rgb8",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,	GL_UNSIGNED_BYTE)));
1551 	m_modifyActions.add("tex_subimage_rgb565",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,	GL_UNSIGNED_SHORT_5_6_5)));
1552 	m_modifyActions.add("tex_subimage_rgba8",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_BYTE)));
1553 	m_modifyActions.add("tex_subimage_rgb5_a1",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1)));
1554 	m_modifyActions.add("tex_subimage_rgba4",			MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4)));
1555 
1556 	m_modifyActions.add("renderbuffer_clear_color",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
1557 	m_modifyActions.add("renderbuffer_clear_depth",		MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.7f)));
1558 	m_modifyActions.add("renderbuffer_clear_stencil",	MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(78)));
1559 }
1560 
init(void)1561 void ModifyTests::init (void)
1562 {
1563 	addCreateTexture2DActions("tex_");
1564 	addCreateRenderbufferActions();
1565 	addCreateAndroidNativeActions();
1566 	addModifyActions();
1567 
1568 	for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
1569 	{
1570 		LabeledAction& createAction = m_createActions[createNdx];
1571 
1572 		for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
1573 		{
1574 			LabeledAction& modifyAction = m_modifyActions[modifyNdx];
1575 
1576 			if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action))
1577 				continue;
1578 
1579 			TestSpec spec;
1580 			spec.name = createAction.label + "_" + modifyAction.label;
1581 			spec.desc = "gles2_tex_sub_image";
1582 
1583 			spec.contexts.push_back(TestSpec::API_GLES2);
1584 
1585 			spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
1586 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1587 			spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
1588 			spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
1589 
1590 			addChild(new ImageFormatCase(m_eglTestCtx, spec));
1591 		}
1592 	}
1593 }
1594 
createModifyTests(EglTestContext & eglTestCtx,const string & name,const string & desc)1595 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
1596 {
1597 	return new ModifyTests(eglTestCtx, name, desc);
1598 }
1599 
1600 } // Image
1601 } // egl
1602 } // deqp
1603