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 "teglImageTests.hpp"
     25 
     26 #include "teglImageFormatTests.hpp"
     27 
     28 #include "egluNativeDisplay.hpp"
     29 #include "egluNativeWindow.hpp"
     30 #include "egluNativePixmap.hpp"
     31 #include "egluStrUtil.hpp"
     32 #include "egluUtil.hpp"
     33 
     34 #include "gluDefs.hpp"
     35 #include "gluStrUtil.hpp"
     36 
     37 #include "tcuTestLog.hpp"
     38 #include "tcuCommandLine.hpp"
     39 
     40 
     41 #include <algorithm>
     42 #include <sstream>
     43 #include <string>
     44 #include <vector>
     45 #include <set>
     46 
     47 #include <EGL/eglext.h>
     48 
     49 #include <GLES2/gl2.h>
     50 #include <GLES2/gl2ext.h>
     51 
     52 using tcu::TestLog;
     53 
     54 using std::string;
     55 using std::vector;
     56 using std::set;
     57 
     58 namespace deqp
     59 {
     60 namespace egl
     61 {
     62 
     63 namespace Image
     64 {
     65 
     66 bool checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last, vector<const char*>& unsupported)
     67 {
     68 	vector<string> extensions;
     69 	dpy.getExtensions(extensions);
     70 
     71 	set<string> extSet(extensions.begin(), extensions.end());
     72 
     73 	unsupported.clear();
     74 
     75 	for (const char** extIter = first; extIter != last; extIter++)
     76 	{
     77 		const char* ext = *extIter;
     78 
     79 		if (extSet.find(ext) == extSet.end())
     80 			unsupported.push_back(ext);
     81 	}
     82 
     83 	return unsupported.size() == 0;
     84 }
     85 
     86 string join (const vector<const char*>& parts, const char* separator)
     87 {
     88 	std::ostringstream str;
     89 	for (std::vector<const char*>::const_iterator i = parts.begin(); i != parts.end(); i++)
     90 	{
     91 		if (i != parts.begin())
     92 			str << separator;
     93 		str << *i;
     94 	}
     95 	return str.str();
     96 }
     97 
     98 void checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last)
     99 {
    100 	vector<const char*> unsupported;
    101 	if (!checkExtensions(dpy, first, last, unsupported))
    102 		throw tcu::NotSupportedError("Extension not supported", join(unsupported, " ").c_str(), __FILE__, __LINE__);
    103 }
    104 
    105 template <size_t N>
    106 void checkExtensions (const tcu::egl::Display& dpy, const char* (&extensions)[N])
    107 {
    108 	checkExtensions(dpy, &extensions[0], &extensions[N]);
    109 }
    110 
    111 #define CHECK_EXTENSIONS(EXTENSIONS) do { static const char* ext[] = EXTENSIONS; checkExtensions(m_eglTestCtx.getDisplay(), ext); } while (deGetFalse())
    112 
    113 template <typename RetVal>
    114 RetVal checkCallError (tcu::TestContext& testCtx, const char* call, RetVal returnValue, EGLint expectError)
    115 {
    116 	TestLog& log = testCtx.getLog();
    117 	log << TestLog::Message << call << TestLog::EndMessage;
    118 
    119 	EGLint error = eglGetError();
    120 
    121 	if (error != expectError)
    122 	{
    123 		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
    124 		log << TestLog::Message << "  " << returnValue << " was returned" << TestLog::EndMessage;
    125 
    126 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    127 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
    128 	}
    129 
    130 	return returnValue;
    131 }
    132 
    133 template <typename RetVal>
    134 void checkCallReturn (tcu::TestContext& testCtx, const char* call, RetVal returnValue, RetVal expectReturnValue, EGLint expectError)
    135 {
    136 	TestLog& log = testCtx.getLog();
    137 	log << TestLog::Message << call << TestLog::EndMessage;
    138 
    139 	EGLint error = eglGetError();
    140 
    141 	if (returnValue != expectReturnValue)
    142 	{
    143 		log << TestLog::Message << "  Fail: Return value mismatch! Expected " << expectReturnValue << ", got " << returnValue << TestLog::EndMessage;
    144 
    145 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    146 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value");
    147 	}
    148 
    149 	if (error != expectError)
    150 	{
    151 		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
    152 
    153 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    154 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
    155 	}
    156 }
    157 
    158 void checkGLCall (tcu::TestContext& testCtx, const char* call, GLenum expectError)
    159 {
    160 	TestLog& log = testCtx.getLog();
    161 	log << TestLog::Message << call << TestLog::EndMessage;
    162 
    163 	GLenum error = glGetError();
    164 
    165 	if (error != expectError)
    166 	{
    167 		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << glu::getErrorStr(expectError) << ", got " << glu::getErrorStr(error) << TestLog::EndMessage;
    168 
    169 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    170 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
    171 	}
    172 }
    173 
    174 // \note These macros expect "TestContext m_testCtx" and "ExtFuncTable efTable" variables to be defined.
    175 #define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR)	checkCallReturn(m_testCtx, #CALL, efTable.CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR))
    176 #define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR)						checkCallError(m_testCtx, #CALL, efTable.CALL, (EXPECT_ERROR))
    177 #define CHECK_GL_EXT_CALL(CALL, EXPECT_ERROR)						do { efTable.CALL; checkGLCall(m_testCtx, #CALL, (EXPECT_ERROR)); } while (deGetFalse())
    178 
    179 class ExtFuncTable
    180 {
    181 public:
    182 	PFNEGLCREATEIMAGEKHRPROC						eglCreateImageKHR;
    183 	PFNEGLDESTROYIMAGEKHRPROC						eglDestroyImageKHR;
    184 
    185 	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC				glEGLImageTargetTexture2DOES;
    186 	PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC	glEGLImageTargetRenderbufferStorageOES;
    187 
    188 	ExtFuncTable (void)
    189 	{
    190 		// EGL_KHR_image_base
    191 		eglCreateImageKHR						= (PFNEGLCREATEIMAGEKHRPROC)						eglGetProcAddress("eglCreateImageKHR");
    192 		eglDestroyImageKHR						= (PFNEGLDESTROYIMAGEKHRPROC)						eglGetProcAddress("eglDestroyImageKHR");
    193 
    194 		// OES_EGL_image
    195 		glEGLImageTargetTexture2DOES			= (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)				eglGetProcAddress("glEGLImageTargetTexture2DOES");
    196 		glEGLImageTargetRenderbufferStorageOES	= (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)	eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
    197 	}
    198 };
    199 
    200 class InvalidCreateImage : public TestCase
    201 {
    202 public:
    203 	InvalidCreateImage (EglTestContext& eglTestCtx)
    204 		: TestCase(eglTestCtx, "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
    205 	{
    206 	}
    207 
    208 	IterateResult iterate (void)
    209 	{
    210 		EGLDisplay		dpy = m_eglTestCtx.getDisplay().getEGLDisplay();
    211 		TestLog&		log	= m_testCtx.getLog();
    212 		ExtFuncTable	efTable;
    213 
    214 		CHECK_EXTENSIONS({ "EGL_KHR_image_base" });
    215 
    216 		// Initialize result to pass.
    217 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    218 
    219 		log << TestLog::Message << "Testing bad display (-1)..." << TestLog::EndMessage;
    220 		CHECK_EXT_CALL_RET(eglCreateImageKHR((EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, 0, DE_NULL),
    221 						   EGL_NO_IMAGE_KHR, EGL_BAD_DISPLAY);
    222 
    223 		log << TestLog::Message << "Testing bad context (-1)..." << TestLog::EndMessage;
    224 		CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, (EGLContext)-1, EGL_NONE, 0, DE_NULL),
    225 						   EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT);
    226 
    227 		log << TestLog::Message << "Testing bad parameter (-1).." << TestLog::EndMessage;
    228 		CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, EGL_NO_CONTEXT, (EGLenum)-1, 0, DE_NULL),
    229 						   EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER);
    230 
    231 		return STOP;
    232 	}
    233 };
    234 
    235 class GLES2Context
    236 {
    237 public:
    238 	GLES2Context (EglTestContext& eglTestCtx, EGLint configId, int width, int height)
    239 		: m_eglTestCtx	(eglTestCtx)
    240 		, m_config		(getConfigById(eglTestCtx.getDisplay(), configId))
    241 		, m_context		(eglTestCtx.getDisplay(), m_config, m_ctxAttrs, EGL_OPENGL_ES_API)
    242 		, m_window		(DE_NULL)
    243 		, m_pixmap		(DE_NULL)
    244 		, m_surface		(DE_NULL)
    245 	{
    246 		tcu::egl::Display&	dpy				= eglTestCtx.getDisplay();
    247 		EGLint				surfaceTypeBits	= dpy.getConfigAttrib(m_config, EGL_SURFACE_TYPE);
    248 
    249 		if (surfaceTypeBits & EGL_PBUFFER_BIT)
    250 		{
    251 			EGLint pbufferAttrs[] =
    252 			{
    253 				EGL_WIDTH,		width,
    254 				EGL_HEIGHT,		height,
    255 				EGL_NONE
    256 			};
    257 
    258 			m_surface = new tcu::egl::PbufferSurface(dpy, m_config, pbufferAttrs);
    259 		}
    260 		else if (surfaceTypeBits & EGL_WINDOW_BIT)
    261 		{
    262 			m_window	= eglTestCtx.createNativeWindow(dpy.getEGLDisplay(), m_config, DE_NULL, width, height, eglu::parseWindowVisibility(eglTestCtx.getTestContext().getCommandLine()));
    263 			m_surface	= new tcu::egl::WindowSurface(dpy, eglu::createWindowSurface(eglTestCtx.getNativeDisplay(), *m_window, dpy.getEGLDisplay(), m_config, DE_NULL));
    264 		}
    265 		else if (surfaceTypeBits & EGL_PIXMAP_BIT)
    266 		{
    267 			m_pixmap	= eglTestCtx.createNativePixmap(dpy.getEGLDisplay(), m_config, DE_NULL, width, height);
    268 			m_surface	= new tcu::egl::PixmapSurface(dpy, eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *m_pixmap, dpy.getEGLDisplay(), m_config, DE_NULL));
    269 		}
    270 		else
    271 			TCU_FAIL("No valid surface types supported in config");
    272 
    273 		m_context.makeCurrent(*m_surface, *m_surface);
    274 	}
    275 
    276 	~GLES2Context (void)
    277 	{
    278 		eglMakeCurrent(m_eglTestCtx.getDisplay().getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    279 
    280 		delete m_window;
    281 		delete m_pixmap;
    282 		delete m_surface;
    283 	}
    284 
    285 	EGLDisplay getEglDisplay (void)
    286 	{
    287 		return m_eglTestCtx.getDisplay().getEGLDisplay();
    288 	}
    289 
    290 	EGLContext getEglContext (void)
    291 	{
    292 		return m_context.getEGLContext();
    293 	}
    294 
    295 	// Helper for selecting config.
    296 	static EGLint getConfigIdForApi (const vector<eglu::ConfigInfo>& configInfos, EGLint apiBits)
    297 	{
    298 		EGLint	windowCfg	= 0;
    299 		EGLint	pixmapCfg	= 0;
    300 		EGLint	pbufferCfg	= 0;
    301 
    302 		for (vector<eglu::ConfigInfo>::const_iterator cfgIter = configInfos.begin(); cfgIter != configInfos.end(); cfgIter++)
    303 		{
    304 			if ((cfgIter->renderableType & apiBits) == 0)
    305 				continue;
    306 
    307 			if (windowCfg == 0 && (cfgIter->surfaceType & EGL_WINDOW_BIT) != 0)
    308 				windowCfg = cfgIter->configId;
    309 
    310 			if (pixmapCfg == 0 && (cfgIter->surfaceType & EGL_PIXMAP_BIT) != 0)
    311 				pixmapCfg = cfgIter->configId;
    312 
    313 			if (pbufferCfg == 0 && (cfgIter->surfaceType & EGL_PBUFFER_BIT) != 0)
    314 				pbufferCfg = cfgIter->configId;
    315 
    316 			if (windowCfg && pixmapCfg && pbufferCfg)
    317 				break;
    318 		}
    319 
    320 		// Prefer configs in order: pbuffer, window, pixmap
    321 		if (pbufferCfg)
    322 			return pbufferCfg;
    323 		else if (windowCfg)
    324 			return windowCfg;
    325 		else if (pixmapCfg)
    326 			return pixmapCfg;
    327 		else
    328 			throw tcu::NotSupportedError("No compatible EGL configs found", "", __FILE__, __LINE__);
    329 	}
    330 
    331 private:
    332 	static EGLConfig getConfigById (const tcu::egl::Display& dpy, EGLint configId)
    333 	{
    334 		EGLint attributes[] = { EGL_CONFIG_ID, configId, EGL_NONE };
    335 		vector<EGLConfig> configs;
    336 		dpy.chooseConfig(attributes, configs);
    337 		TCU_CHECK(configs.size() == 1);
    338 		return configs[0];
    339 	}
    340 
    341 	static const EGLint			m_ctxAttrs[];
    342 
    343 	EglTestContext&				m_eglTestCtx;
    344 	EGLConfig					m_config;
    345 	tcu::egl::Context			m_context;
    346 	eglu::NativeWindow*			m_window;
    347 	eglu::NativePixmap*			m_pixmap;
    348 	tcu::egl::Surface*			m_surface;
    349 
    350 								GLES2Context	(const GLES2Context&);
    351 	GLES2Context&				operator=		(const GLES2Context&);
    352 };
    353 
    354 const EGLint GLES2Context::m_ctxAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    355 
    356 class CreateImageGLES2 : public TestCase
    357 {
    358 public:
    359 	static const char* getTargetName (EGLint target)
    360 	{
    361 		switch (target)
    362 		{
    363 			case EGL_GL_TEXTURE_2D_KHR:						return "tex2d";
    364 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:	return "cubemap_pos_x";
    365 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:	return "cubemap_neg_x";
    366 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:	return "cubemap_pos_y";
    367 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:	return "cubemap_neg_y";
    368 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:	return "cubemap_pos_z";
    369 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:	return "cubemap_neg_z";
    370 			case EGL_GL_RENDERBUFFER_KHR:					return "renderbuffer";
    371 			default:		DE_ASSERT(DE_FALSE);			return "";
    372 		}
    373 	}
    374 
    375 	static const char* getStorageName (GLenum storage)
    376 	{
    377 		switch (storage)
    378 		{
    379 			case GL_RGB:				return "rgb";
    380 			case GL_RGBA:				return "rgba";
    381 			case GL_DEPTH_COMPONENT16:	return "depth_component_16";
    382 			case GL_RGBA4:				return "rgba4";
    383 			case GL_RGB5_A1:			return "rgb5_a1";
    384 			case GL_RGB565:				return "rgb565";
    385 			case GL_STENCIL_INDEX8:		return "stencil_index8";
    386 			default:
    387 				DE_ASSERT(DE_FALSE);
    388 				return "";
    389 		}
    390 	}
    391 
    392 	CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum storage, bool useTexLevel0 = false)
    393 		: TestCase			(eglTestCtx, (string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(storage) + (useTexLevel0 ? "_level0_only" : "")).c_str(), "Create EGLImage from GLES2 object")
    394 		, m_target			(target)
    395 		, m_storage			(storage)
    396 		, m_useTexLevel0	(useTexLevel0)
    397 	{
    398 	}
    399 
    400 	IterateResult iterate (void)
    401 	{
    402 		TestLog&		log	= m_testCtx.getLog();
    403 		ExtFuncTable	efTable;
    404 
    405 		if (m_target == EGL_GL_TEXTURE_2D_KHR)
    406 			CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"});
    407 		else if (m_target == EGL_GL_RENDERBUFFER_KHR)
    408 			CHECK_EXTENSIONS({"EGL_KHR_gl_renderbuffer_image"});
    409 		else
    410 			CHECK_EXTENSIONS({"EGL_KHR_gl_texture_cubemap_image"});
    411 
    412 		// Initialize result.
    413 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    414 
    415 		// Create GLES2 context
    416 		EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT);
    417 		log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage;
    418 
    419 		GLES2Context context(m_eglTestCtx, configId, 64, 64);
    420 
    421 		switch (m_target)
    422 		{
    423 			case EGL_GL_TEXTURE_2D_KHR:
    424 			{
    425 				deUint32 tex = 1;
    426 				GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, tex));
    427 
    428 				// Specify mipmap level 0
    429 				GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL));
    430 
    431 				if (!m_useTexLevel0)
    432 				{
    433 					// Set minification filter to linear. This makes the texture complete.
    434 					GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    435 				}
    436 				// Else spec allows using incomplete texture when miplevel 0 is only used and specified.
    437 
    438 				// Create EGL image
    439 				EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
    440 				EGLImageKHR	image		= CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS);
    441 				if (image == EGL_NO_IMAGE_KHR)
    442 				{
    443 					log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
    444 
    445 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    446 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
    447 				}
    448 
    449 				// Destroy image
    450 				CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
    451 
    452 				// Destroy texture object
    453 				GLU_CHECK_CALL(glDeleteTextures(1, &tex));
    454 
    455 				break;
    456 			}
    457 
    458 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
    459 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
    460 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
    461 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
    462 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
    463 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
    464 			{
    465 				deUint32 tex = 1;
    466 				GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, tex));
    467 
    468 				// Specify mipmap level 0 for all faces
    469 				GLenum faces[] =
    470 				{
    471 					GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    472 					GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    473 					GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    474 					GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    475 					GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    476 					GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    477 				};
    478 				for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
    479 					GLU_CHECK_CALL(glTexImage2D(faces[faceNdx], 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL));
    480 
    481 				if (!m_useTexLevel0)
    482 				{
    483 					// Set minification filter to linear.
    484 					GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    485 				}
    486 
    487 				// Create EGL image
    488 				EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
    489 				EGLImageKHR	image		= CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), m_target, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS);
    490 				if (image == EGL_NO_IMAGE_KHR)
    491 				{
    492 					log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
    493 
    494 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    495 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
    496 				}
    497 
    498 				// Destroy image
    499 				CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
    500 
    501 				// Destroy texture object
    502 				GLU_CHECK_CALL(glDeleteTextures(1, &tex));
    503 
    504 				break;
    505 			}
    506 
    507 			case EGL_GL_RENDERBUFFER_KHR:
    508 			{
    509 				// Create renderbuffer.
    510 				deUint32 rbo = 1;
    511 				GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, rbo));
    512 
    513 				// Specify storage.
    514 				GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, m_storage, 64, 64));
    515 
    516 				// Create EGL image
    517 				EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_RENDERBUFFER_KHR, (EGLClientBuffer)(deUintptr)rbo, DE_NULL), EGL_SUCCESS);
    518 				if (image == EGL_NO_IMAGE_KHR)
    519 				{
    520 					log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
    521 
    522 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    523 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
    524 				}
    525 
    526 				// Destroy image
    527 				CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
    528 
    529 				// Destroy texture object
    530 				GLU_CHECK_CALL(glDeleteRenderbuffers(1, &rbo));
    531 
    532 				break;
    533 			}
    534 
    535 			default:
    536 				DE_ASSERT(DE_FALSE);
    537 				break;
    538 		}
    539 
    540 		return STOP;
    541 	}
    542 
    543 private:
    544 	EGLint	m_target;
    545 	GLenum	m_storage;
    546 	bool	m_useTexLevel0;
    547 };
    548 
    549 class ImageTargetGLES2 : public TestCase
    550 {
    551 public:
    552 	static const char* getTargetName (GLenum target)
    553 	{
    554 		switch (target)
    555 		{
    556 			case GL_TEXTURE_2D:		return "tex2d";
    557 			case GL_RENDERBUFFER:	return "renderbuffer";
    558 			default:
    559 				DE_ASSERT(DE_FALSE);
    560 				return "";
    561 		}
    562 	}
    563 
    564 	ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target)
    565 		: TestCase	(eglTestCtx, (string("image_target_gles2_") + getTargetName(target)).c_str(), "Use EGLImage as GLES2 object")
    566 		, m_target	(target)
    567 	{
    568 	}
    569 
    570 	IterateResult iterate (void)
    571 	{
    572 		TestLog&		log	= m_testCtx.getLog();
    573 		ExtFuncTable	efTable;
    574 
    575 		// \todo [2011-07-21 pyry] Try all possible EGLImage sources
    576 		CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"});
    577 
    578 		// Initialize result.
    579 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    580 
    581 		// Create GLES2 context
    582 		EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT);
    583 		log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage;
    584 
    585 		GLES2Context context(m_eglTestCtx, configId, 64, 64);
    586 
    587 		// Check for OES_EGL_image
    588 		{
    589 			const char* glExt = (const char*)glGetString(GL_EXTENSIONS);
    590 
    591 			if (string(glExt).find("GL_OES_EGL_image") == string::npos)
    592 				throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__);
    593 
    594 			TCU_CHECK(efTable.glEGLImageTargetTexture2DOES);
    595 			TCU_CHECK(efTable.glEGLImageTargetRenderbufferStorageOES);
    596 		}
    597 
    598 		// Create GL_TEXTURE_2D and EGLImage from it.
    599 		log << TestLog::Message << "Creating EGLImage using GL_TEXTURE_2D with GL_RGBA storage" << TestLog::EndMessage;
    600 
    601 		deUint32 srcTex = 1;
    602 		GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
    603 		GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL));
    604 		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    605 
    606 		// Create EGL image
    607 		EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
    608 		EGLImageKHR	image		= CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attribs), EGL_SUCCESS);
    609 		if (image == EGL_NO_IMAGE_KHR)
    610 		{
    611 			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
    612 
    613 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    614 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
    615 		}
    616 
    617 		// Create texture or renderbuffer
    618 		if (m_target == GL_TEXTURE_2D)
    619 		{
    620 			log << TestLog::Message << "Creating GL_TEXTURE_2D from EGLimage" << TestLog::EndMessage;
    621 
    622 			deUint32 dstTex = 2;
    623 			GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex));
    624 			CHECK_GL_EXT_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image), GL_NO_ERROR);
    625 			GLU_CHECK_CALL(glDeleteTextures(1, &dstTex));
    626 		}
    627 		else
    628 		{
    629 			DE_ASSERT(m_target == GL_RENDERBUFFER);
    630 
    631 			log << TestLog::Message << "Creating GL_RENDERBUFFER from EGLimage" << TestLog::EndMessage;
    632 
    633 			deUint32 dstRbo = 2;
    634 			GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo));
    635 			CHECK_GL_EXT_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image), GL_NO_ERROR);
    636 			GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo));
    637 		}
    638 
    639 		// Destroy image
    640 		CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
    641 
    642 		// Destroy source texture object
    643 		GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
    644 
    645 		return STOP;
    646 	}
    647 
    648 private:
    649 	GLenum	m_target;
    650 };
    651 
    652 class ApiTests : public TestCaseGroup
    653 {
    654 public:
    655 	ApiTests (EglTestContext& eglTestCtx)
    656 		: TestCaseGroup(eglTestCtx, "api", "EGLImage API tests")
    657 	{
    658 	}
    659 
    660 	void init (void)
    661 	{
    662 		addChild(new Image::InvalidCreateImage(m_eglTestCtx));
    663 
    664 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGB));
    665 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA));
    666 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, true));
    667 
    668 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGB));
    669 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA));
    670 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, true));
    671 
    672 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, GL_RGBA));
    673 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, GL_RGBA));
    674 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, GL_RGBA));
    675 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, GL_RGBA));
    676 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, GL_RGBA));
    677 
    678 		static const GLenum rboStorages[] =
    679 		{
    680 			GL_DEPTH_COMPONENT16,
    681 			GL_RGBA4,
    682 			GL_RGB5_A1,
    683 			GL_RGB565,
    684 			GL_STENCIL_INDEX8
    685 		};
    686 		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(rboStorages); storageNdx++)
    687 			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_RENDERBUFFER_KHR, rboStorages[storageNdx]));
    688 
    689 		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_TEXTURE_2D));
    690 		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_RENDERBUFFER));
    691 	}
    692 };
    693 
    694 } // Image
    695 
    696 ImageTests::ImageTests (EglTestContext& eglTestCtx)
    697 	: TestCaseGroup(eglTestCtx, "image", "EGLImage Tests")
    698 {
    699 }
    700 
    701 ImageTests::~ImageTests (void)
    702 {
    703 }
    704 
    705 void ImageTests::init (void)
    706 {
    707 	addChild(new Image::ApiTests(m_eglTestCtx));
    708 	addChild(new Image::SimpleCreationTests(m_eglTestCtx));
    709 	addChild(new Image::ModifyTests(m_eglTestCtx));
    710 	addChild(new Image::MultiContextRenderTests(m_eglTestCtx));
    711 }
    712 
    713 } // egl
    714 } // deqp
    715