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