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
60using tcu::TestLog;
61
62using std::string;
63using std::vector;
64using std::set;
65using std::ostringstream;
66
67using de::MovePtr;
68using de::UniquePtr;
69using glu::ApiType;
70using glu::ContextType;
71using glu::Texture;
72using eglu::AttribMap;
73using eglu::NativeWindow;
74using eglu::NativePixmap;
75using eglu::UniqueImage;
76using eglu::UniqueSurface;
77using eglu::ScopedCurrentContext;
78
79using namespace glw;
80using namespace eglw;
81
82namespace deqp
83{
84namespace egl
85{
86
87namespace 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
93template <typename RetVal>
94RetVal 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
116template <typename RetVal>
117void 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
148class ImageTestCase : public TestCase, public glu::CallLogWrapper
149{
150public:
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
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
168	void		deinit				(void)
169	{
170		m_eglTestCtx.getLibrary().terminate(m_display);
171		m_display = EGL_NO_DISPLAY;
172	}
173
174protected:
175	glw::Functions	m_gl;
176	ApiType			m_api;
177	EGLDisplay		m_display;
178};
179
180class InvalidCreateImage : public ImageTestCase
181{
182public:
183	InvalidCreateImage (EglTestContext& eglTestCtx)
184		: ImageTestCase(eglTestCtx, ApiType::es(2, 0), "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
185	{
186	}
187
188	void checkCreate (const char* desc, EGLDisplay dpy, const char* dpyStr, EGLContext context, const char* ctxStr, EGLenum source, const char* srcStr, EGLint expectError);
189
190	IterateResult iterate (void)
191	{
192#define CHECK_CREATE(MSG, DPY, CONTEXT, SOURCE, ERR) checkCreate(MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR)
193		CHECK_CREATE("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
194		CHECK_CREATE("Testing bad context (-1)...", m_display, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
195		CHECK_CREATE("Testing bad source (-1)...", m_display, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
196#undef CHECK_CREATE
197
198		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
199		return STOP;
200	}
201
202};
203
204void InvalidCreateImage::checkCreate (const char* msg, EGLDisplay dpy, const char* dpyStr, EGLContext context, const char* ctxStr, EGLenum source, const char* srcStr, EGLint expectError)
205{
206	m_testCtx.getLog() << TestLog::Message << msg << TestLog::EndMessage;
207	{
208		const Library&		egl		= m_eglTestCtx.getLibrary();
209		const EGLImageKHR	image	= egl.createImageKHR(dpy, context, source, 0, DE_NULL);
210		ostringstream		call;
211
212		call << "eglCreateImage(" << dpyStr << ", " << ctxStr << ", " << srcStr << ", 0, DE_NULL)";
213		checkCallReturn(m_eglTestCtx, call.str().c_str(), image, EGL_NO_IMAGE_KHR, expectError);
214	}
215}
216
217EGLConfig chooseConfig (const Library& egl, EGLDisplay display, ApiType apiType)
218{
219	AttribMap				attribs;
220	vector<EGLConfig>		configs;
221	// Prefer configs in order: pbuffer, window, pixmap
222	static const EGLenum	s_surfaceTypes[] = { EGL_PBUFFER_BIT, EGL_WINDOW_BIT, EGL_PIXMAP_BIT };
223
224	attribs[EGL_RENDERABLE_TYPE] = eglu::apiRenderableType(apiType);
225
226	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_surfaceTypes); ++ndx)
227	{
228		attribs[EGL_SURFACE_TYPE] = s_surfaceTypes[ndx];
229		configs = eglu::chooseConfigs(egl, display, attribs);
230
231		if (!configs.empty())
232			return configs.front();
233	}
234
235	TCU_THROW(NotSupportedError, "No compatible EGL configs found");
236	return (EGLConfig)0;
237}
238
239class Context
240{
241public:
242								Context			(EglTestContext& eglTestCtx, EGLDisplay display, ContextType ctxType, int width, int height)
243									: m_eglTestCtx	(eglTestCtx)
244									, m_display		(display)
245									, m_config		(chooseConfig(eglTestCtx.getLibrary(), display, ctxType.getAPI()))
246									, m_context		(m_eglTestCtx.getLibrary(), m_display, eglu::createGLContext(eglTestCtx.getLibrary(), m_display, m_config, ctxType))
247									, m_surface		(createSurface(eglTestCtx, m_display, m_config, width, height))
248									, m_current		(eglTestCtx.getLibrary(), m_display, m_surface->get(), m_surface->get(), *m_context)
249	{
250		m_eglTestCtx.initGLFunctions(&m_gl, ctxType.getAPI());
251	}
252
253	EGLConfig					getConfig		(void) const { return m_config; }
254	EGLDisplay 					getEglDisplay	(void) const { return m_display; }
255	EGLContext 					getEglContext	(void) const { return *m_context; }
256	const glw::Functions&		gl				(void) const { return m_gl; }
257
258private:
259	EglTestContext&				m_eglTestCtx;
260	EGLDisplay					m_display;
261	EGLConfig					m_config;
262	eglu::UniqueContext			m_context;
263	UniquePtr<ManagedSurface>	m_surface;
264	ScopedCurrentContext		m_current;
265	glw::Functions				m_gl;
266
267								Context			(const Context&);
268	Context&					operator=		(const Context&);
269};
270
271class CreateImageGLES2 : public ImageTestCase
272{
273public:
274	static const char* getTargetName (EGLint target)
275	{
276		switch (target)
277		{
278			case EGL_GL_TEXTURE_2D_KHR:						return "tex2d";
279			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:	return "cubemap_pos_x";
280			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:	return "cubemap_neg_x";
281			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:	return "cubemap_pos_y";
282			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:	return "cubemap_neg_y";
283			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:	return "cubemap_pos_z";
284			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:	return "cubemap_neg_z";
285			case EGL_GL_RENDERBUFFER_KHR:					return "renderbuffer";
286			case EGL_NATIVE_BUFFER_ANDROID:					return "android_native";
287			default:		DE_ASSERT(DE_FALSE);			return "";
288		}
289	}
290
291	static const char* getStorageName (GLenum storage)
292	{
293		switch (storage)
294		{
295			case GL_RGB:				return "rgb";
296			case GL_RGBA:				return "rgba";
297			case GL_DEPTH_COMPONENT16:	return "depth_component_16";
298			case GL_RGBA4:				return "rgba4";
299			case GL_RGB5_A1:			return "rgb5_a1";
300			case GL_RGB565:				return "rgb565";
301			case GL_RGB8:				return "rgb8";
302			case GL_RGBA8:				return "rgba8";
303			case GL_STENCIL_INDEX8:		return "stencil_index8";
304			default:
305				DE_ASSERT(DE_FALSE);
306				return "";
307		}
308	}
309
310	MovePtr<ImageSource> getImageSource (EGLint target, GLenum format, bool useTexLevel0)
311	{
312		switch (target)
313		{
314			case EGL_GL_TEXTURE_2D_KHR:
315			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
316			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
317			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
318			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
319			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
320			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
321				return createTextureImageSource(target, format, GL_UNSIGNED_BYTE, useTexLevel0);
322			case EGL_GL_RENDERBUFFER_KHR:
323				return createRenderbufferImageSource(format);
324			case EGL_NATIVE_BUFFER_ANDROID:
325				return createAndroidNativeImageSource(format);
326			default:
327				DE_ASSERT(!"Impossible");
328				return MovePtr<ImageSource>();
329		}
330	}
331
332	CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum storage, bool useTexLevel0 = false)
333		: ImageTestCase		(eglTestCtx, ApiType::es(2, 0), string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(storage) + (useTexLevel0 ? "_level0_only" : ""), "Create EGLImage from GLES2 object")
334		, m_source			(getImageSource(target, storage, useTexLevel0))
335	{
336	}
337
338	IterateResult iterate (void)
339	{
340		const Library&			egl				= m_eglTestCtx.getLibrary();
341		const EGLDisplay		dpy				= m_display;
342
343		if (eglu::getVersion(egl, dpy) < eglu::Version(1, 5))
344			CHECK_EXTENSION(dpy, m_source->getRequiredExtension());
345
346		// Initialize result.
347		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
348
349		// Create GLES2 context
350		TestLog&				log				= m_testCtx.getLog();
351		const ContextType		contextType		(ApiType::es(2, 0));
352		Context					context			(m_eglTestCtx, dpy, contextType, 64, 64);
353		const EGLContext		eglContext		= context.getEglContext();
354
355		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(egl, dpy, context.getConfig()) << TestLog::EndMessage;
356
357		UniquePtr<ClientBuffer>	clientBuffer	(m_source->createBuffer(context.gl()));
358		const EGLImageKHR		image			= m_source->createImage(egl, dpy, eglContext, clientBuffer->get());
359
360		if (image == EGL_NO_IMAGE_KHR)
361		{
362			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
363
364			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
365				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
366		}
367
368		// Destroy image
369		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
370
371		return STOP;
372	}
373
374private:
375	UniquePtr<ImageSource>	m_source;
376};
377
378class ImageTargetGLES2 : public ImageTestCase
379{
380public:
381	static const char* getTargetName (GLenum target)
382	{
383		switch (target)
384		{
385			case GL_TEXTURE_2D:		return "tex2d";
386			case GL_RENDERBUFFER:	return "renderbuffer";
387			default:
388				DE_ASSERT(DE_FALSE);
389				return "";
390		}
391	}
392
393	ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target)
394		: ImageTestCase	(eglTestCtx, ApiType::es(2, 0), string("image_target_gles2_") + getTargetName(target), "Use EGLImage as GLES2 object")
395		, m_target		(target)
396	{
397	}
398
399	IterateResult iterate (void)
400	{
401		const Library&	egl	= m_eglTestCtx.getLibrary();
402		TestLog&		log	= m_testCtx.getLog();
403
404		// \todo [2011-07-21 pyry] Try all possible EGLImage sources
405		CHECK_EXTENSION(m_display, "EGL_KHR_gl_texture_2D_image");
406
407		// Initialize result.
408		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
409
410		// Create GLES2 context
411
412		Context context(m_eglTestCtx, m_display, ContextType(ApiType::es(2, 0)), 64, 64);
413		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(m_eglTestCtx.getLibrary(), context.getEglDisplay(), context.getConfig()) << TestLog::EndMessage;
414
415		// Check for OES_EGL_image
416		{
417			const char* glExt = (const char*)glGetString(GL_EXTENSIONS);
418
419			if (string(glExt).find("GL_OES_EGL_image") == string::npos)
420				throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__);
421
422			TCU_CHECK(m_gl.eglImageTargetTexture2DOES);
423			TCU_CHECK(m_gl.eglImageTargetRenderbufferStorageOES);
424		}
425
426		// Create GL_TEXTURE_2D and EGLImage from it.
427		log << TestLog::Message << "Creating EGLImage using GL_TEXTURE_2D with GL_RGBA storage" << TestLog::EndMessage;
428
429		deUint32 srcTex = 1;
430		GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
431		GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL));
432		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
433
434		// Create EGL image
435		EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
436		EGLImageKHR	image		= CHECK_EXT_CALL_ERR(egl.createImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attribs), EGL_SUCCESS);
437		if (image == EGL_NO_IMAGE_KHR)
438		{
439			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
440
441			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
442				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
443		}
444
445		// Create texture or renderbuffer
446		if (m_target == GL_TEXTURE_2D)
447		{
448			log << TestLog::Message << "Creating GL_TEXTURE_2D from EGLimage" << TestLog::EndMessage;
449
450			deUint32 dstTex = 2;
451			GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex));
452			GLU_CHECK_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image));
453			GLU_CHECK_CALL(glDeleteTextures(1, &dstTex));
454		}
455		else
456		{
457			DE_ASSERT(m_target == GL_RENDERBUFFER);
458
459			log << TestLog::Message << "Creating GL_RENDERBUFFER from EGLimage" << TestLog::EndMessage;
460
461			deUint32 dstRbo = 2;
462			GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo));
463			GLU_CHECK_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image));
464			GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo));
465		}
466
467		// Destroy image
468		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
469
470		// Destroy source texture object
471		GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
472
473		return STOP;
474	}
475
476private:
477	GLenum	m_target;
478};
479
480class ApiTests : public TestCaseGroup
481{
482public:
483	ApiTests (EglTestContext& eglTestCtx, const string& name, const string& desc) : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
484
485	void init (void)
486	{
487		addChild(new Image::InvalidCreateImage(m_eglTestCtx));
488
489		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGB));
490		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA));
491		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, true));
492
493		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGB));
494		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA));
495		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, true));
496
497		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, GL_RGBA));
498		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, GL_RGBA));
499		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, GL_RGBA));
500		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, GL_RGBA));
501		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, GL_RGBA));
502
503		static const GLenum rboStorages[] =
504		{
505			GL_DEPTH_COMPONENT16,
506			GL_RGBA4,
507			GL_RGB5_A1,
508			GL_RGB565,
509			GL_STENCIL_INDEX8
510		};
511		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(rboStorages); storageNdx++)
512			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_RENDERBUFFER_KHR, rboStorages[storageNdx]));
513
514		static const GLenum androidFormats[] =
515		{
516			GL_RGB565,
517			GL_RGB8,
518			GL_RGBA4,
519			GL_RGB5_A1,
520			GL_RGBA8,
521		};
522
523		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(androidFormats); ++formatNdx)
524			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_NATIVE_BUFFER_ANDROID, androidFormats[formatNdx]));
525
526		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_TEXTURE_2D));
527		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_RENDERBUFFER));
528	}
529};
530
531} // Image
532
533ImageTests::ImageTests (EglTestContext& eglTestCtx)
534	: TestCaseGroup(eglTestCtx, "image", "EGLImage Tests")
535{
536}
537
538ImageTests::~ImageTests (void)
539{
540}
541
542void ImageTests::init (void)
543{
544	addChild(new Image::ApiTests(m_eglTestCtx, "api", "EGLImage API tests"));
545	addChild(Image::createSimpleCreationTests(m_eglTestCtx, "create", "EGLImage creation tests"));
546	addChild(Image::createModifyTests(m_eglTestCtx, "modify", "EGLImage modifying tests"));
547	addChild(Image::createMultiContextRenderTests(m_eglTestCtx, "render_multiple_contexts", "EGLImage render tests on multiple contexts"));
548}
549
550} // egl
551} // deqp
552