• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief EGL image tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglImageTests.hpp"
25 
26 #include "teglImageUtil.hpp"
27 #include "teglAndroidUtil.hpp"
28 #include "teglImageFormatTests.hpp"
29 
30 #include "egluNativeDisplay.hpp"
31 #include "egluNativeWindow.hpp"
32 #include "egluNativePixmap.hpp"
33 #include "egluStrUtil.hpp"
34 #include "egluUnique.hpp"
35 #include "egluUtil.hpp"
36 #include "egluGLUtil.hpp"
37 
38 #include "eglwLibrary.hpp"
39 #include "eglwEnums.hpp"
40 
41 #include "gluDefs.hpp"
42 #include "gluCallLogWrapper.hpp"
43 #include "gluObjectWrapper.hpp"
44 #include "gluStrUtil.hpp"
45 
46 #include "glwDefs.hpp"
47 #include "glwEnums.hpp"
48 
49 #include "tcuTestLog.hpp"
50 #include "tcuCommandLine.hpp"
51 
52 #include "deUniquePtr.hpp"
53 
54 #include <algorithm>
55 #include <sstream>
56 #include <string>
57 #include <vector>
58 #include <set>
59 
60 using tcu::TestLog;
61 
62 using std::string;
63 using std::vector;
64 using std::set;
65 using std::ostringstream;
66 
67 using de::MovePtr;
68 using de::UniquePtr;
69 using glu::ApiType;
70 using glu::ContextType;
71 using glu::Texture;
72 using eglu::AttribMap;
73 using eglu::NativeWindow;
74 using eglu::NativePixmap;
75 using eglu::UniqueImage;
76 using eglu::UniqueSurface;
77 using eglu::ScopedCurrentContext;
78 
79 using namespace glw;
80 using namespace eglw;
81 
82 namespace deqp
83 {
84 namespace egl
85 {
86 
87 namespace Image
88 {
89 
90 #define CHECK_EXTENSION(DPY, EXTNAME) \
91 	TCU_CHECK_AND_THROW(NotSupportedError, eglu::hasExtension(m_eglTestCtx.getLibrary(), DPY, EXTNAME), (string("Unsupported extension: ") + (EXTNAME)).c_str())
92 
93 template <typename RetVal>
checkCallError(EglTestContext & eglTestCtx,const char * call,RetVal returnValue,EGLint expectError)94 RetVal checkCallError (EglTestContext& eglTestCtx, const char* call, RetVal returnValue, EGLint expectError)
95 {
96 	tcu::TestContext&	testCtx		= eglTestCtx.getTestContext();
97 	TestLog&			log			= testCtx.getLog();
98 	EGLint				error;
99 
100 	log << TestLog::Message << call << TestLog::EndMessage;
101 
102 	error = eglTestCtx.getLibrary().getError();
103 
104 	if (error != expectError)
105 	{
106 		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
107 		log << TestLog::Message << "  " << returnValue << " was returned" << TestLog::EndMessage;
108 
109 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
110 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
111 	}
112 
113 	return returnValue;
114 }
115 
116 template <typename RetVal>
checkCallReturn(EglTestContext & eglTestCtx,const char * call,RetVal returnValue,RetVal expectReturnValue,EGLint expectError)117 void checkCallReturn (EglTestContext& eglTestCtx, const char* call, RetVal returnValue, RetVal expectReturnValue, EGLint expectError)
118 {
119 	tcu::TestContext&	testCtx		= eglTestCtx.getTestContext();
120 	TestLog&			log			= testCtx.getLog();
121 	EGLint				error;
122 
123 	log << TestLog::Message << call << TestLog::EndMessage;
124 
125 	error = eglTestCtx.getLibrary().getError();
126 
127 	if (returnValue != expectReturnValue)
128 	{
129 		log << TestLog::Message << "  Fail: Return value mismatch! Expected " << expectReturnValue << ", got " << returnValue << TestLog::EndMessage;
130 
131 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
132 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value");
133 	}
134 
135 	if (error != expectError)
136 	{
137 		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
138 
139 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
140 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
141 	}
142 }
143 
144 // \note These macros expect "EglTestContext m_eglTestCtx" to be defined.
145 #define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR)	checkCallReturn(m_eglTestCtx, #CALL, CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR))
146 #define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR)						checkCallError(m_eglTestCtx, #CALL, CALL, (EXPECT_ERROR))
147 
148 class ImageTestCase : public TestCase, public glu::CallLogWrapper
149 {
150 public:
ImageTestCase(EglTestContext & eglTestCtx,ApiType api,const string & name,const string & desc)151 				ImageTestCase		(EglTestContext& eglTestCtx, ApiType api, const string& name, const string& desc)
152 					: TestCase				(eglTestCtx, name.c_str(), desc.c_str())
153 					, glu::CallLogWrapper	(m_gl, m_testCtx.getLog())
154 					, m_api					(api)
155 					, m_display				(EGL_NO_DISPLAY)
156 	{
157 	}
158 
init(void)159 	void		init				(void)
160 	{
161 		DE_ASSERT(m_display == EGL_NO_DISPLAY);
162 		m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
163 
164 		const char* extensions[] = { "GL_OES_EGL_image" };
165 		m_eglTestCtx.initGLFunctions(&m_gl, m_api, DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
166 	}
167 
deinit(void)168 	void		deinit				(void)
169 	{
170 		m_eglTestCtx.getLibrary().terminate(m_display);
171 		m_display = EGL_NO_DISPLAY;
172 	}
173 
isGLRedSupported(void)174 	bool		isGLRedSupported	(void)
175 	{
176 		return m_api.getMajorVersion() >= 3 || glu::hasExtension(m_gl, m_api, "GL_EXT_texture_rg");
177 	}
178 
179 protected:
180 	glw::Functions	m_gl;
181 	ApiType			m_api;
182 	EGLDisplay		m_display;
183 };
184 
185 class InvalidCreateImage : public ImageTestCase
186 {
187 public:
188 	typedef EGLImage    (Library::*createImage)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLAttrib *) const ;
189 	typedef EGLImageKHR (Library::*createImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) const ;
190 
InvalidCreateImage(EglTestContext & eglTestCtx)191 	InvalidCreateImage (EglTestContext& eglTestCtx)
192 		: ImageTestCase(eglTestCtx, ApiType::es(2, 0), "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
193 	{
194 	}
195 
196 	template <typename createImageFuncType, typename imageType>
197 	void checkCreate	(createImageFuncType createImageFunc,
198 						 string createImageName,
199 						 const char* msg,
200 						 EGLDisplay dpy,
201 						 const char* dpyStr,
202 						 EGLContext context,
203 						 const char* ctxStr,
204 						 EGLenum source,
205 						 const char* srcStr,
206 						 EGLint expectError,
207 						 imageType noImageVal);
208 
iterate(void)209 	IterateResult iterate (void)
210 	{
211 		const Library& egl = m_eglTestCtx.getLibrary();
212 
213 		if (eglu::getVersion(egl, m_display) < eglu::Version(1, 5) &&
214 			!eglu::hasExtension(egl, m_display, "EGL_KHR_image") &&
215 			!eglu::hasExtension(egl, m_display, "EGL_KHR_image_base"))
216 		{
217 			TCU_THROW(NotSupportedError, "EGLimages not supported");
218 		}
219 
220 		if (eglu::getVersion(egl, m_display) >= eglu::Version(1, 5))
221 		{
222 #define CHECK_CREATE(MSG, DPY, CONTEXT, SOURCE, ERR) \
223 			checkCreate<createImage, EGLImage>(&Library::createImage, "eglCreateImage", MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR, EGL_NO_IMAGE)
224 		CHECK_CREATE("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
225 		CHECK_CREATE("Testing bad context (-1)...", m_display, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
226 		CHECK_CREATE("Testing bad source (-1)...", m_display, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
227 #undef CHECK_CREATE
228 		}
229 
230 		if (eglu::hasExtension(egl, m_display, "EGL_KHR_image") &&
231 			eglu::hasExtension(egl, m_display, "EGL_KHR_image_base"))
232 		{
233 #define CHECK_CREATE_KHR(MSG, DPY, CONTEXT, SOURCE, ERR) \
234 			checkCreate<createImageKHR, EGLImageKHR>(&Library::createImageKHR, "eglCreateImageKHR", MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR, EGL_NO_IMAGE_KHR)
235 		CHECK_CREATE_KHR("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
236 		CHECK_CREATE_KHR("Testing bad context (-1)...", m_display, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
237 		CHECK_CREATE_KHR("Testing bad source (-1)...", m_display, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
238 #undef CHECK_CREATE_KHR
239 		}
240 
241 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
242 		return STOP;
243 	}
244 
245 };
246 
247 template <typename createImageFuncType, typename imageType>
checkCreate(createImageFuncType createImageFunc,string createImageName,const char * msg,EGLDisplay dpy,const char * dpyStr,EGLContext context,const char * ctxStr,EGLenum source,const char * srcStr,EGLint expectError,imageType noImageVal)248 void InvalidCreateImage::checkCreate (createImageFuncType createImageFunc,
249 									  string createImageName,
250 									  const char* msg,
251 									  EGLDisplay dpy,
252 									  const char* dpyStr,
253 									  EGLContext context,
254 									  const char* ctxStr,
255 									  EGLenum source,
256 									  const char* srcStr,
257 									  EGLint expectError,
258 									  imageType noImageVal)
259 {
260 	m_testCtx.getLog() << TestLog::Message << msg << TestLog::EndMessage;
261 	{
262 		const Library&		egl		= m_eglTestCtx.getLibrary();
263 		const imageType	    image	= (egl.*createImageFunc)(dpy, context, source, 0, DE_NULL);
264 		ostringstream		call;
265 
266 		call << createImageName << "(" << dpyStr << ", " << ctxStr << ", " << srcStr << ", 0, DE_NULL)";
267 		checkCallReturn(m_eglTestCtx, call.str().c_str(), image, noImageVal, expectError);
268 	}
269 }
270 
chooseConfig(const Library & egl,EGLDisplay display,ApiType apiType)271 EGLConfig chooseConfig (const Library& egl, EGLDisplay display, ApiType apiType)
272 {
273 	AttribMap				attribs;
274 	vector<EGLConfig>		configs;
275 	// Prefer configs in order: pbuffer, window, pixmap
276 	static const EGLenum	s_surfaceTypes[] = { EGL_PBUFFER_BIT, EGL_WINDOW_BIT, EGL_PIXMAP_BIT };
277 
278 	attribs[EGL_RENDERABLE_TYPE] = eglu::apiRenderableType(apiType);
279 
280 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_surfaceTypes); ++ndx)
281 	{
282 		attribs[EGL_SURFACE_TYPE] = s_surfaceTypes[ndx];
283 		configs = eglu::chooseConfigs(egl, display, attribs);
284 
285 		if (!configs.empty())
286 			return configs.front();
287 	}
288 
289 	TCU_THROW(NotSupportedError, "No compatible EGL configs found");
290 	return (EGLConfig)0;
291 }
292 
293 class Context
294 {
295 public:
Context(EglTestContext & eglTestCtx,EGLDisplay display,ContextType ctxType,int width,int height)296 								Context			(EglTestContext& eglTestCtx, EGLDisplay display, ContextType ctxType, int width, int height)
297 									: m_eglTestCtx	(eglTestCtx)
298 									, m_display		(display)
299 									, m_config		(chooseConfig(eglTestCtx.getLibrary(), display, ctxType.getAPI()))
300 									, m_context		(m_eglTestCtx.getLibrary(), m_display, eglu::createGLContext(eglTestCtx.getLibrary(), m_display, m_config, ctxType))
301 									, m_surface		(createSurface(eglTestCtx, m_display, m_config, width, height))
302 									, m_current		(eglTestCtx.getLibrary(), m_display, m_surface->get(), m_surface->get(), *m_context)
303 	{
304 		m_eglTestCtx.initGLFunctions(&m_gl, ctxType.getAPI());
305 	}
306 
getConfig(void) const307 	EGLConfig					getConfig		(void) const { return m_config; }
getEglDisplay(void) const308 	EGLDisplay					getEglDisplay	(void) const { return m_display; }
getEglContext(void) const309 	EGLContext					getEglContext	(void) const { return *m_context; }
gl(void) const310 	const glw::Functions&		gl				(void) const { return m_gl; }
311 
312 private:
313 	EglTestContext&				m_eglTestCtx;
314 	EGLDisplay					m_display;
315 	EGLConfig					m_config;
316 	eglu::UniqueContext			m_context;
317 	UniquePtr<ManagedSurface>	m_surface;
318 	ScopedCurrentContext		m_current;
319 	glw::Functions				m_gl;
320 
321 								Context			(const Context&);
322 	Context&					operator=		(const Context&);
323 };
324 
325 class CreateImageGLES2 : public ImageTestCase
326 {
327 public:
getTargetName(EGLint target)328 	static const char* getTargetName (EGLint target)
329 	{
330 		switch (target)
331 		{
332 			case EGL_GL_TEXTURE_2D_KHR:						return "tex2d";
333 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:	return "cubemap_pos_x";
334 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:	return "cubemap_neg_x";
335 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:	return "cubemap_pos_y";
336 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:	return "cubemap_neg_y";
337 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:	return "cubemap_pos_z";
338 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:	return "cubemap_neg_z";
339 			case EGL_GL_RENDERBUFFER_KHR:					return "renderbuffer";
340 			case EGL_NATIVE_BUFFER_ANDROID:					return "android_native";
341 			default:		DE_ASSERT(DE_FALSE);			return "";
342 		}
343 	}
344 
getStorageName(GLenum storage)345 	static const char* getStorageName (GLenum storage)
346 	{
347 		switch (storage)
348 		{
349 			case GL_RED:				return "red";
350 			case GL_RG:					return "rg";
351 			case GL_LUMINANCE:			return "luminance";
352 			case GL_LUMINANCE_ALPHA:	return "luminance_alpha";
353 			case GL_RGB:				return "rgb";
354 			case GL_RGBA:				return "rgba";
355 			case GL_RGBA16F:			return "rgba16f";
356 			case GL_DEPTH_COMPONENT16:	return "depth_component_16";
357 			case GL_DEPTH_COMPONENT24:	return "depth_component_24";
358 			case GL_DEPTH_COMPONENT32F:	return "depth_component_32f";
359 			case GL_DEPTH24_STENCIL8:	return "depth24_stencil8";
360 			case GL_DEPTH32F_STENCIL8:	return "depth32f_stencil8";
361 			case GL_RGB10_A2:			return "rgb10_a2";
362 			case GL_RGBA4:				return "rgba4";
363 			case GL_RGB5_A1:			return "rgb5_a1";
364 			case GL_RGB565:				return "rgb565";
365 			case GL_RGB8:				return "rgb8";
366 			case GL_RGBA8:				return "rgba8";
367 			case GL_STENCIL_INDEX8:		return "stencil_index8";
368 			default:
369 				DE_ASSERT(DE_FALSE);
370 				return "";
371 		}
372 	}
373 
getImageSource(EGLint target,GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0)374 	MovePtr<ImageSource> getImageSource (EGLint target, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
375 	{
376 		switch (target)
377 		{
378 			case EGL_GL_TEXTURE_2D_KHR:
379 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
380 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
381 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
382 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
383 			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
384 			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
385 				DE_ASSERT(format != 0u && type != 0u);
386 				return createTextureImageSource(target, internalFormat, format, type, useTexLevel0);
387 
388 			case EGL_GL_RENDERBUFFER_KHR:
389 				DE_ASSERT(format == 0u && type == 0u);
390 				return createRenderbufferImageSource(internalFormat);
391 
392 			case EGL_NATIVE_BUFFER_ANDROID:
393 				DE_ASSERT(format == 0u && type == 0u);
394 				return createAndroidNativeImageSource(internalFormat, 1u, false);
395 
396 			default:
397 				DE_FATAL("Impossible");
398 				return MovePtr<ImageSource>();
399 		}
400 	}
401 
CreateImageGLES2(EglTestContext & eglTestCtx,EGLint target,GLenum internalFormat,GLenum format,GLenum type,bool useTexLevel0=false)402 	CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0 = false)
403 		: ImageTestCase		(eglTestCtx, ApiType::es(2, 0), string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(internalFormat) + (useTexLevel0 ? "_level0_only" : ""), "Create EGLImage from GLES2 object")
404 		, m_source			(getImageSource(target, internalFormat, format, type, useTexLevel0))
405 		, m_internalFormat	(internalFormat)
406 	{
407 	}
408 
iterate(void)409 	IterateResult iterate (void)
410 	{
411 		const Library&			egl				= m_eglTestCtx.getLibrary();
412 		const EGLDisplay		dpy				= m_display;
413 
414 		if (eglu::getVersion(egl, dpy) < eglu::Version(1, 5))
415 			CHECK_EXTENSION(dpy, m_source->getRequiredExtension());
416 
417 		// Initialize result.
418 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
419 
420 		// Create GLES2 context
421 		TestLog&				log				= m_testCtx.getLog();
422 		const ContextType		contextType		(ApiType::es(2, 0));
423 		Context					context			(m_eglTestCtx, dpy, contextType, 64, 64);
424 		const EGLContext		eglContext		= context.getEglContext();
425 
426 		if ((m_internalFormat == GL_RED || m_internalFormat == GL_RG) && !isGLRedSupported())
427 			TCU_THROW(NotSupportedError, "Unsupported extension: GL_EXT_texture_rg");
428 
429 		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(egl, dpy, context.getConfig()) << TestLog::EndMessage;
430 
431 		UniquePtr<ClientBuffer>	clientBuffer	(m_source->createBuffer(egl, context.gl()));
432 		const EGLImageKHR		image			= m_source->createImage(egl, dpy, eglContext, clientBuffer->get());
433 
434 		if (image == EGL_NO_IMAGE_KHR)
435 		{
436 			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
437 
438 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
439 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
440 		}
441 
442 		// Destroy image
443 		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
444 
445 		return STOP;
446 	}
447 
448 private:
449 	const UniquePtr<ImageSource>	m_source;
450 	const GLenum					m_internalFormat;
451 };
452 
453 class ImageTargetGLES2 : public ImageTestCase
454 {
455 public:
getTargetName(GLenum target)456 	static const char* getTargetName (GLenum target)
457 	{
458 		switch (target)
459 		{
460 			case GL_TEXTURE_2D:		return "tex2d";
461 			case GL_RENDERBUFFER:	return "renderbuffer";
462 			default:
463 				DE_ASSERT(DE_FALSE);
464 				return "";
465 		}
466 	}
467 
ImageTargetGLES2(EglTestContext & eglTestCtx,GLenum target)468 	ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target)
469 		: ImageTestCase	(eglTestCtx, ApiType::es(2, 0), string("image_target_gles2_") + getTargetName(target), "Use EGLImage as GLES2 object")
470 		, m_target		(target)
471 	{
472 	}
473 
iterate(void)474 	IterateResult iterate (void)
475 	{
476 		const Library&	egl	= m_eglTestCtx.getLibrary();
477 		TestLog&		log	= m_testCtx.getLog();
478 
479 		// \todo [2011-07-21 pyry] Try all possible EGLImage sources
480 		CHECK_EXTENSION(m_display, "EGL_KHR_gl_texture_2D_image");
481 
482 		// Initialize result.
483 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
484 
485 		// Create GLES2 context
486 
487 		Context context(m_eglTestCtx, m_display, ContextType(ApiType::es(2, 0)), 64, 64);
488 		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(m_eglTestCtx.getLibrary(), context.getEglDisplay(), context.getConfig()) << TestLog::EndMessage;
489 
490 		// Check for OES_EGL_image
491 		{
492 			const char* glExt = (const char*)glGetString(GL_EXTENSIONS);
493 
494 			if (string(glExt).find("GL_OES_EGL_image") == string::npos)
495 				throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__);
496 
497 			TCU_CHECK(m_gl.eglImageTargetTexture2DOES);
498 			TCU_CHECK(m_gl.eglImageTargetRenderbufferStorageOES);
499 		}
500 
501 		// Create GL_TEXTURE_2D and EGLImage from it.
502 		log << TestLog::Message << "Creating EGLImage using GL_TEXTURE_2D with GL_RGBA storage" << TestLog::EndMessage;
503 
504 		deUint32 srcTex = 1;
505 		GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
506 		GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL));
507 		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
508 
509 		// Create EGL image
510 		EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
511 		EGLImageKHR	image		= CHECK_EXT_CALL_ERR(egl.createImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attribs), EGL_SUCCESS);
512 		if (image == EGL_NO_IMAGE_KHR)
513 		{
514 			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
515 
516 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
517 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
518 		}
519 
520 		// Create texture or renderbuffer
521 		if (m_target == GL_TEXTURE_2D)
522 		{
523 			log << TestLog::Message << "Creating GL_TEXTURE_2D from EGLimage" << TestLog::EndMessage;
524 
525 			deUint32 dstTex = 2;
526 			GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex));
527 			GLU_CHECK_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image));
528 			GLU_CHECK_CALL(glDeleteTextures(1, &dstTex));
529 		}
530 		else
531 		{
532 			DE_ASSERT(m_target == GL_RENDERBUFFER);
533 
534 			log << TestLog::Message << "Creating GL_RENDERBUFFER from EGLimage" << TestLog::EndMessage;
535 
536 			deUint32 dstRbo = 2;
537 			GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo));
538 			GLU_CHECK_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image));
539 			GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo));
540 		}
541 
542 		// Destroy image
543 		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
544 
545 		// Destroy source texture object
546 		GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
547 
548 		return STOP;
549 	}
550 
551 private:
552 	GLenum	m_target;
553 };
554 
555 class ApiTests : public TestCaseGroup
556 {
557 public:
ApiTests(EglTestContext & eglTestCtx,const string & name,const string & desc)558 	ApiTests (EglTestContext& eglTestCtx, const string& name, const string& desc) : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
559 
init(void)560 	void init (void)
561 	{
562 		addChild(new Image::InvalidCreateImage(m_eglTestCtx));
563 
564 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RED, GL_RED, GL_UNSIGNED_BYTE, false));
565 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RG, GL_RG, GL_UNSIGNED_BYTE, false));
566 
567 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE));
568 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE));
569 
570 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE));
571 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
572 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true));
573 
574 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE));
575 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
576 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true));
577 
578 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
579 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
580 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
581 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
582 		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
583 
584 		static const GLenum rboStorages[] =
585 		{
586 			GL_DEPTH_COMPONENT16,
587 			GL_RGBA4,
588 			GL_RGB5_A1,
589 			GL_RGB565,
590 			GL_STENCIL_INDEX8
591 		};
592 		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(rboStorages); storageNdx++)
593 			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_RENDERBUFFER_KHR, rboStorages[storageNdx], (GLenum)0, (GLenum)0));
594 
595 		static const GLenum androidFormats[] =
596 		{
597 			GL_RGB565,
598 			GL_RGB8,
599 			GL_RGBA8,
600 			GL_RGBA4,
601 			GL_RGB5_A1,
602 			GL_DEPTH_COMPONENT16,
603 			GL_DEPTH_COMPONENT24,
604 			GL_DEPTH24_STENCIL8,
605 			GL_DEPTH_COMPONENT32F,
606 			GL_DEPTH32F_STENCIL8,
607 			GL_RGB10_A2,
608 			GL_RGBA16F,
609 			GL_STENCIL_INDEX8
610 		};
611 
612 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(androidFormats); ++formatNdx)
613 			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_NATIVE_BUFFER_ANDROID, androidFormats[formatNdx], (GLenum)0, (GLenum)0));
614 
615 		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_TEXTURE_2D));
616 		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_RENDERBUFFER));
617 	}
618 };
619 
620 } // Image
621 
ImageTests(EglTestContext & eglTestCtx)622 ImageTests::ImageTests (EglTestContext& eglTestCtx)
623 	: TestCaseGroup(eglTestCtx, "image", "EGLImage Tests")
624 {
625 }
626 
~ImageTests(void)627 ImageTests::~ImageTests (void)
628 {
629 }
630 
init(void)631 void ImageTests::init (void)
632 {
633 	addChild(new Image::ApiTests(m_eglTestCtx, "api", "EGLImage API tests"));
634 	addChild(Image::createSimpleCreationTests(m_eglTestCtx, "create", "EGLImage creation tests"));
635 	addChild(Image::createModifyTests(m_eglTestCtx, "modify", "EGLImage modifying tests"));
636 	addChild(Image::createMultiContextRenderTests(m_eglTestCtx, "render_multiple_contexts", "EGLImage render tests on multiple contexts"));
637 }
638 
639 } // egl
640 } // deqp
641