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 gles2 sharing tests
22 *//*--------------------------------------------------------------------*/
23
24#include "teglGLES2SharingTests.hpp"
25
26#include "teglGLES2SharingThreadedTests.hpp"
27
28#include "egluNativeWindow.hpp"
29#include "egluUtil.hpp"
30
31#include "tcuCommandLine.hpp"
32#include "tcuImageCompare.hpp"
33#include "tcuSurface.hpp"
34#include "tcuTestLog.hpp"
35#include "tcuTexture.hpp"
36#include "tcuTextureUtil.hpp"
37
38#include "deUniquePtr.hpp"
39#include "deRandom.hpp"
40
41#include "deMath.h"
42#include "deMemory.h"
43#include "deString.h"
44
45#include "gluDefs.hpp"
46
47#include <GLES2/gl2.h>
48
49#include <memory>
50#include <sstream>
51#include <vector>
52
53using std::vector;
54
55namespace deqp
56{
57namespace egl
58{
59
60namespace
61{
62
63// \todo [2013-04-09 pyry] Use glu::Program
64class Program
65{
66public:
67	Program (const char* vertexSource, const char* fragmentSource)
68		: m_program			(0)
69		, m_vertexShader	(0)
70		, m_fragmentShader	(0)
71		, m_isOk			(false)
72	{
73		m_program			= glCreateProgram();
74		m_vertexShader		= glCreateShader(GL_VERTEX_SHADER);
75		m_fragmentShader	= glCreateShader(GL_FRAGMENT_SHADER);
76
77		try
78		{
79			bool	vertexCompileOk		= false;
80			bool	fragmentCompileOk	= false;
81			bool	linkOk				= false;
82
83			for (int ndx = 0; ndx < 2; ndx++)
84			{
85				const char*		source			= ndx ? fragmentSource		: vertexSource;
86				const deUint32	shader			= ndx ? m_fragmentShader	: m_vertexShader;
87				int				compileStatus	= 0;
88				bool&			compileOk		= ndx ? fragmentCompileOk	: vertexCompileOk;
89
90				glShaderSource(shader, 1, &source, DE_NULL);
91				glCompileShader(shader);
92				glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
93
94				compileOk = (compileStatus == GL_TRUE);
95			}
96
97			if (vertexCompileOk && fragmentCompileOk)
98			{
99				int linkStatus = 0;
100
101				glAttachShader(m_program, m_vertexShader);
102				glAttachShader(m_program, m_fragmentShader);
103				glLinkProgram(m_program);
104				glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);
105
106				linkOk = (linkStatus == GL_TRUE);
107			}
108
109			m_isOk = linkOk;
110		}
111		catch (const std::exception&)
112		{
113			glDeleteShader(m_vertexShader);
114			glDeleteShader(m_fragmentShader);
115			glDeleteProgram(m_program);
116			throw;
117		}
118	}
119
120	~Program (void)
121	{
122		glDeleteShader(m_vertexShader);
123		glDeleteShader(m_fragmentShader);
124		glDeleteProgram(m_program);
125	}
126
127	bool			isOk			(void) const { return m_isOk;	}
128	deUint32		getProgram		(void) const {return m_program;	}
129
130private:
131	deUint32		m_program;
132	deUint32		m_vertexShader;
133	deUint32		m_fragmentShader;
134	bool			m_isOk;
135};
136
137} // anonymous
138
139class GLES2SharingTest : public TestCase
140{
141public:
142	enum ResourceType
143	{
144		BUFFER = 0,
145		TEXTURE,
146		RENDERBUFFER,
147		SHADER_PROGRAM
148	};
149
150	struct TestSpec
151	{
152		ResourceType	type;
153		bool			destroyContextBFirst;
154		bool			useResource;
155		bool			destroyOnContexB;
156		bool			initializeData;
157		bool			renderOnContexA;
158		bool			renderOnContexB;
159		bool			verifyOnContexA;
160		bool			verifyOnContexB;
161	};
162
163					GLES2SharingTest	(EglTestContext& eglTestCtx, const char* name , const char* desc, const TestSpec& spec);
164	IterateResult	iterate				(void);
165
166private:
167	TestSpec		m_spec;
168
169	EGLContext		createContext		(EGLDisplay display, EGLContext share, EGLConfig config);
170	void			destroyContext		(EGLDisplay display, EGLContext context);
171	void			makeCurrent			(EGLDisplay display, EGLContext context, EGLSurface surafec);
172
173protected:
174	de::Random		m_random;
175	tcu::TestLog&	m_log;
176	virtual void	createResource		(void)  { DE_ASSERT(false); }
177	virtual void 	destroyResource		(void)	{ DE_ASSERT(false); }
178	virtual void	renderResource		(tcu::Surface* screen, tcu::Surface* reference) { DE_UNREF(screen); DE_UNREF(reference); DE_ASSERT(false); }
179};
180
181GLES2SharingTest::GLES2SharingTest (EglTestContext& eglTestCtx, const char* name , const char* desc, const TestSpec& spec)
182	: TestCase	(eglTestCtx, name, desc)
183	, m_spec	(spec)
184	, m_random	(deStringHash(name))
185	, m_log		(eglTestCtx.getTestContext().getLog())
186{
187}
188
189EGLContext GLES2SharingTest::createContext (EGLDisplay display, EGLContext share, EGLConfig config)
190{
191	EGLContext context = EGL_NO_CONTEXT;
192	EGLint attriblist[] =
193	{
194		EGL_CONTEXT_CLIENT_VERSION, 2,
195		EGL_NONE
196	};
197
198	EGLint configId = -1;
199	eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &configId);
200
201	TCU_CHECK_EGL_CALL(eglBindAPI(EGL_OPENGL_ES_API));
202
203	context = eglCreateContext(display, config, share, attriblist);
204	TCU_CHECK_EGL_MSG("Failed to create GLES2 context");
205	TCU_CHECK(context != EGL_NO_CONTEXT);
206
207	return context;
208}
209
210void GLES2SharingTest::destroyContext (EGLDisplay display, EGLContext context)
211{
212	TCU_CHECK_EGL_CALL(eglDestroyContext(display, context));
213}
214
215void GLES2SharingTest::makeCurrent (EGLDisplay display, EGLContext context, EGLSurface surface)
216{
217	TCU_CHECK_EGL_CALL(eglMakeCurrent(display, surface, surface, context));
218}
219
220TestCase::IterateResult GLES2SharingTest::iterate (void)
221{
222	tcu::TestLog&		log		= m_testCtx.getLog();
223	vector<EGLConfig>	configs;
224
225	EGLint attribList[] =
226	{
227		EGL_RENDERABLE_TYPE, 	EGL_OPENGL_ES2_BIT,
228		EGL_SURFACE_TYPE,	 	EGL_WINDOW_BIT,
229		EGL_ALPHA_SIZE,			1,
230		EGL_NONE
231	};
232
233	tcu::egl::Display& display = m_eglTestCtx.getDisplay();
234	display.chooseConfig(attribList, configs);
235	EGLConfig config = configs[0];
236
237	de::UniquePtr<eglu::NativeWindow>	window	(m_eglTestCtx.createNativeWindow(display.getEGLDisplay(), config, DE_NULL, 480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
238	tcu::egl::WindowSurface				surface	(display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display.getEGLDisplay(), config, DE_NULL));
239
240	m_log << tcu::TestLog::Message << "Create context A" << tcu::TestLog::EndMessage;
241	EGLContext		contextA	= createContext(display.getEGLDisplay(), EGL_NO_CONTEXT, config);
242	m_log << tcu::TestLog::Message << "Create context B" << tcu::TestLog::EndMessage;
243	EGLContext		contextB	= createContext(display.getEGLDisplay(), contextA, config);
244	bool			isOk		= true;
245
246	if (m_spec.useResource)
247	{
248		m_log << tcu::TestLog::Message << "Make current context A" << tcu::TestLog::EndMessage;
249		makeCurrent(display.getEGLDisplay(), contextA, surface.getEGLSurface());
250		m_log << tcu::TestLog::Message << "Creating resource" << tcu::TestLog::EndMessage;
251		createResource();
252
253		int		width	= 240;
254		int		height	= 240;
255
256		if (m_spec.renderOnContexA)
257		{
258			m_log << tcu::TestLog::Message << "Render resource" << tcu::TestLog::EndMessage;
259			if (m_spec.verifyOnContexA)
260			{
261				tcu::Surface screen	(width, height);
262				tcu::Surface ref	(width, height);
263				renderResource(&screen, &ref);
264
265				if (!fuzzyCompare(log, "Rendered image", "Rendering result comparision", ref, screen, 0.05f, tcu::COMPARE_LOG_RESULT))
266					isOk = false;
267			}
268			else
269			{
270				renderResource(NULL, NULL);
271			}
272		}
273
274		if (m_spec.renderOnContexB)
275		{
276			m_log << tcu::TestLog::Message << "Make current context B" << tcu::TestLog::EndMessage;
277			makeCurrent(display.getEGLDisplay(), contextB, surface.getEGLSurface());
278			m_log << tcu::TestLog::Message << "Render resource" << tcu::TestLog::EndMessage;
279			if (m_spec.verifyOnContexB)
280			{
281				tcu::Surface screen	(width, height);
282				tcu::Surface ref	(width, height);
283				renderResource(&screen, &ref);
284
285				if (!fuzzyCompare(log, "Rendered image", "Rendering result comparision", ref, screen, 0.05f, tcu::COMPARE_LOG_RESULT))
286					isOk = false;
287			}
288			else
289			{
290				renderResource(NULL, NULL);
291			}
292		}
293
294		if (m_spec.destroyOnContexB)
295		{
296			m_log << tcu::TestLog::Message << "Make current context B" << tcu::TestLog::EndMessage;
297			makeCurrent(display.getEGLDisplay(), contextB, surface.getEGLSurface());
298			m_log << tcu::TestLog::Message << "Destroy resource" << tcu::TestLog::EndMessage;
299			destroyResource();
300		}
301		else
302		{
303			m_log << tcu::TestLog::Message << "Make current context A" << tcu::TestLog::EndMessage;
304			makeCurrent(display.getEGLDisplay(), contextA, surface.getEGLSurface());
305			m_log << tcu::TestLog::Message << "Destroy resource" << tcu::TestLog::EndMessage;
306			destroyResource();
307		}
308	}
309
310	if (m_spec.destroyContextBFirst)
311	{
312		m_log << tcu::TestLog::Message << "Destroy context B" << tcu::TestLog::EndMessage;
313		destroyContext(display.getEGLDisplay(), contextB);
314		m_log << tcu::TestLog::Message << "Destroy context A" << tcu::TestLog::EndMessage;
315		destroyContext(display.getEGLDisplay(), contextA);
316	}
317	else
318	{
319		m_log << tcu::TestLog::Message << "Destroy context A" << tcu::TestLog::EndMessage;
320		destroyContext(display.getEGLDisplay(), contextA);
321		m_log << tcu::TestLog::Message << "Destroy context B" << tcu::TestLog::EndMessage;
322		destroyContext(display.getEGLDisplay(), contextB);
323	}
324
325	if (isOk)
326		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
327	else
328		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
329
330	return STOP;
331}
332
333class GLES2BufferSharingTest : public GLES2SharingTest
334{
335public:
336							GLES2BufferSharingTest	(EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec);
337
338private:
339	GLuint					m_glBuffer;
340	std::vector<GLubyte>	m_buffer;
341
342	virtual void	createResource		(void);
343	virtual void 	destroyResource		(void);
344	virtual void	renderResource		(tcu::Surface* screen, tcu::Surface* reference);
345
346};
347
348GLES2BufferSharingTest::GLES2BufferSharingTest (EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec)
349	: GLES2SharingTest	(eglTestCtx, name, desc, spec)
350	, m_glBuffer		(0)
351{
352}
353
354void GLES2BufferSharingTest::createResource (void)
355{
356	int						size	= 16*16*4;
357
358	m_buffer.reserve(size);
359
360	for (int i = 0; i < size; i++)
361		m_buffer.push_back((GLubyte)m_random.getInt(0, 255));
362
363	GLU_CHECK_CALL(glGenBuffers(1, &m_glBuffer));
364	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_glBuffer));
365	GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, (GLsizei)(m_buffer.size() * sizeof(GLubyte)), &(m_buffer[0]), GL_DYNAMIC_DRAW));
366	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
367}
368
369void GLES2BufferSharingTest::destroyResource (void)
370{
371	GLU_CHECK_CALL(glDeleteBuffers(1, &m_glBuffer));
372	m_buffer.clear();
373}
374
375void GLES2BufferSharingTest::renderResource (tcu::Surface* screen, tcu::Surface* reference)
376{
377	DE_ASSERT((screen && reference) || (!screen && !reference));
378
379	const char* vertexShader = ""
380	"attribute mediump vec2 a_pos;\n"
381	"attribute mediump float a_color;\n"
382	"varying mediump float v_color;\n"
383	"void main(void)\n"
384	"{\n"
385	"\tv_color = a_color;\n"
386	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
387	"}\n";
388
389	const char* fragmentShader = ""
390	"varying mediump float v_color;\n"
391	"void main(void)\n"
392	"{\n"
393	"\tgl_FragColor = vec4(v_color, v_color, v_color, 1.0);\n"
394	"}\n";
395
396	Program program(vertexShader, fragmentShader);
397
398	if (!program.isOk())
399		TCU_FAIL("Failed to compile shader program");
400
401	std::vector<deUint16>	indices;
402	std::vector<float>		coords;
403
404	DE_ASSERT(m_buffer.size() % 4 == 0);
405
406	for (int i = 0; i < (int)m_buffer.size() / 4; i++)
407	{
408		indices.push_back(i*4);
409		indices.push_back(i*4 + 1);
410		indices.push_back(i*4 + 2);
411		indices.push_back(i*4 + 2);
412		indices.push_back(i*4 + 3);
413		indices.push_back(i*4);
414
415		coords.push_back(0.125f * (i % 16) - 1.0f);
416		coords.push_back(0.125f * ((int)(i / 16.0f)) - 1.0f);
417
418		coords.push_back(0.125f * (i % 16) - 1.0f);
419		coords.push_back(0.125f * ((int)(i / 16.0f) + 1) - 1.0f);
420
421		coords.push_back(0.125f * ((i % 16) + 1) - 1.0f);
422		coords.push_back(0.125f * ((int)(i / 16.0f) + 1) - 1.0f);
423
424		coords.push_back(0.125f * ((i % 16) + 1) - 1.0f);
425		coords.push_back(0.125f * ((int)(i / 16.0f)) - 1.0f);
426	}
427
428	int width = 240;
429	int height = 240;
430
431	if (screen)
432	{
433		width = screen->getWidth();
434		height = screen->getHeight();
435	}
436
437	GLU_CHECK_CALL(glViewport(0, 0, width, height));
438
439	GLU_CHECK_CALL(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
440	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
441
442	GLU_CHECK_CALL(glUseProgram(program.getProgram()));
443
444	GLuint gridLocation = glGetAttribLocation(program.getProgram(), "a_pos");
445	GLU_CHECK_MSG("glGetAttribLocation()");
446	TCU_CHECK(gridLocation != (GLuint)-1);
447
448	GLuint colorLocation = glGetAttribLocation(program.getProgram(), "a_color");
449	GLU_CHECK_MSG("glGetAttribLocation()");
450	TCU_CHECK(colorLocation != (GLuint)-1);
451
452	GLU_CHECK_CALL(glEnableVertexAttribArray(colorLocation));
453	GLU_CHECK_CALL(glEnableVertexAttribArray(gridLocation));
454
455	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_glBuffer));
456	GLU_CHECK_CALL(glVertexAttribPointer(colorLocation, 1, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL));
457	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
458
459	GLU_CHECK_CALL(glVertexAttribPointer(gridLocation, 2, GL_FLOAT, GL_FALSE, 0, &(coords[0])));
460
461	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_SHORT, &(indices[0])));
462	GLU_CHECK_CALL(glDisableVertexAttribArray(colorLocation));
463	GLU_CHECK_CALL(glDisableVertexAttribArray(gridLocation));
464
465	GLU_CHECK_CALL(glUseProgram(0));
466
467	if (screen)
468	{
469		tcu::clear(reference->getAccess(), tcu::IVec4(0xff, 0, 0, 0xff));
470		glReadPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
471		for (int i = 0; i < (int)m_buffer.size() / 4; i++)
472		{
473			float fx1 = 0.125f * (i % 16) - 1.0f;
474			float fy1 = 0.125f * ((int)(i / 16.0f)) - 1.0f;
475			float fx2 = 0.125f * ((i % 16) + 1) - 1.0f;
476			float fy2 = 0.125f * ((int)((i / 16.0f) + 1)) - 1.0f;
477
478			int ox = deRoundFloatToInt32(width		/ 2.0f);
479			int oy = deRoundFloatToInt32(height		/ 2.0f);
480			int x1 = deRoundFloatToInt32((width		 * fx1 / 2.0f) + ox);
481			int y1 = deRoundFloatToInt32((height	 * fy1 / 2.0f) + oy);
482			int x2 = deRoundFloatToInt32((width		 * fx2 / 2.0f) + ox);
483			int y2 = deRoundFloatToInt32((height	 * fy2 / 2.0f) + oy);
484
485			for (int x = x1; x < x2; x++)
486			{
487				for (int y = y1; y < y2; y++)
488				{
489					float		xf		= ((float)(x-x1) + 0.5f) / (float)(x2 - x1);
490					float		yf		= ((float)(y-y1) + 0.5f) / (float)(y2 - y1);
491					bool		tri		= yf >= xf;
492					deUint8		a		= m_buffer[i*4 + (tri ? 1 : 3)];
493					deUint8		b		= m_buffer[i*4 + (tri ? 2 : 0)];
494					deUint8		c		= m_buffer[i*4 + (tri ? 0 : 2)];
495					float		s		= tri ? xf : 1.0f-xf;
496					float		t		= tri ? 1.0f-yf : yf;
497					float		val		= (float)a + (float)(b-a)*s + (float)(c-a)*t;
498
499					reference->setPixel(x, y, tcu::RGBA((deUint8)val, (deUint8)val, (deUint8)val, 255));
500				}
501			}
502		}
503	}
504}
505
506class GLES2TextureSharingTest : public GLES2SharingTest
507{
508public:
509							GLES2TextureSharingTest	(EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec);
510
511private:
512	GLuint					m_glTexture;
513	tcu::Texture2D			m_texture;
514
515	virtual void	createResource		(void);
516	virtual void 	destroyResource		(void);
517	virtual void	renderResource		(tcu::Surface* screen, tcu::Surface* reference);
518
519};
520
521GLES2TextureSharingTest::GLES2TextureSharingTest (EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec)
522	: GLES2SharingTest	(eglTestCtx, name, desc, spec)
523	, m_glTexture		(0)
524	, m_texture			(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
525{
526}
527
528void GLES2TextureSharingTest::createResource (void)
529{
530	int width	= 128;
531	int	height	= 128;
532	m_texture = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height);
533	m_texture.allocLevel(0);
534
535	tcu::fillWithComponentGradients(m_texture.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
536	GLU_CHECK_CALL(glGenTextures(1, &m_glTexture));
537	GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, m_glTexture));
538	GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
539	GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
540	GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
541	GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
542	GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture.getLevel(0).getDataPtr()));
543	GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, 0));
544}
545
546void GLES2TextureSharingTest::destroyResource (void)
547{
548	GLU_CHECK_CALL(glDeleteTextures(1, &m_glTexture));
549}
550
551void GLES2TextureSharingTest::renderResource (tcu::Surface* screen, tcu::Surface* reference)
552{
553	DE_ASSERT((screen && reference) || (!screen && !reference));
554
555	const char* vertexShader = ""
556	"attribute mediump vec2 a_pos;\n"
557	"attribute mediump vec2 a_texCorod;\n"
558	"varying mediump vec2 v_texCoord;\n"
559	"void main(void)\n"
560	"{\n"
561	"\tv_texCoord = a_texCorod;\n"
562	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
563	"}\n";
564
565	const char* fragmentShader = ""
566	"varying mediump vec2 v_texCoord;\n"
567	"uniform sampler2D u_sampler;\n"
568	"void main(void)\n"
569	"{\n"
570	"\tgl_FragColor = texture2D(u_sampler, v_texCoord);\n"
571	"}\n";
572
573	Program program(vertexShader, fragmentShader);
574
575	if (!program.isOk())
576		TCU_FAIL("Failed to compile shader program");
577
578	int width = 240;
579	int height = 240;
580
581	if (screen)
582	{
583		width = screen->getWidth();
584		height = screen->getHeight();
585	}
586
587	static const GLfloat coords[] = {
588		-1.0f, -1.0f,
589		 1.0f, -1.0f,
590		 1.0f,  1.0f,
591		-1.0f,  1.0f
592	};
593
594	static const GLfloat texCoords[] = {
595		0.0f, 0.0f,
596		1.0f, 0.0f,
597		1.0f, 1.0f,
598		0.0f, 1.0f
599	};
600
601	static const GLushort indices[] = {
602		0, 1, 2,
603		2, 3, 0
604	};
605
606	GLU_CHECK_CALL(glViewport(0, 0, width, height));
607
608	GLU_CHECK_CALL(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
609	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
610
611	GLU_CHECK_CALL(glUseProgram(program.getProgram()));
612
613	GLuint coordLocation = glGetAttribLocation(program.getProgram(), "a_pos");
614	GLU_CHECK_MSG("glGetAttribLocation()");
615	TCU_CHECK(coordLocation != (GLuint)-1);
616
617	GLuint texCoordLocation = glGetAttribLocation(program.getProgram(), "a_texCorod");
618	GLU_CHECK_MSG("glGetAttribLocation()");
619	TCU_CHECK(texCoordLocation != (GLuint)-1);
620
621
622	GLuint samplerLocation = glGetUniformLocation(program.getProgram(), "u_sampler");
623	GLU_CHECK_MSG("glGetUniformLocation()");
624	TCU_CHECK(samplerLocation != (GLuint)-1);
625
626	GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0));
627	GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, m_glTexture));
628
629	GLU_CHECK_CALL(glUniform1i(samplerLocation, 0));
630
631	GLU_CHECK_CALL(glEnableVertexAttribArray(texCoordLocation));
632	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLocation));
633
634	GLU_CHECK_CALL(glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords));
635	GLU_CHECK_CALL(glVertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, coords));
636
637	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices));
638	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLocation));
639	GLU_CHECK_CALL(glDisableVertexAttribArray(texCoordLocation));
640
641	GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, 0));
642	GLU_CHECK_CALL(glUseProgram(0));
643
644	if (screen)
645	{
646		glReadPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
647
648		for (int x = 0; x < width; x++)
649		{
650			for (int y = 0; y < height; y++)
651			{
652				float t = ((float)x / (width - 1.0f));
653				float s = ((float)y / (height - 1.0f));
654				float lod = 0.0f;
655
656				tcu::Vec4 color = m_texture.sample(tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR), t, s, lod);
657
658				int r = deClamp32((int)(255.0f * color.x()), 0, 255);
659				int g = deClamp32((int)(255.0f * color.y()), 0, 255);
660				int b = deClamp32((int)(255.0f * color.z()), 0, 255);
661				int a = deClamp32((int)(255.0f * color.w()), 0, 255);
662
663				reference->setPixel(x, y, tcu::RGBA(r, g, b, a));
664			}
665		}
666	}
667}
668
669class GLES2ProgramSharingTest : public GLES2SharingTest
670{
671public:
672					GLES2ProgramSharingTest	(EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec);
673
674private:
675	Program*		m_program;
676
677	virtual void	createResource		(void);
678	virtual void 	destroyResource		(void);
679	virtual void	renderResource		(tcu::Surface* screen, tcu::Surface* reference);
680
681};
682
683GLES2ProgramSharingTest::GLES2ProgramSharingTest (EglTestContext& eglTestCtx, const char* name, const char* desc, const GLES2SharingTest::TestSpec& spec)
684	: GLES2SharingTest	(eglTestCtx, name, desc, spec)
685	, m_program			(NULL)
686{
687}
688
689void GLES2ProgramSharingTest::createResource (void)
690{
691	const char* vertexShader = ""
692	"attribute mediump vec2 a_pos;\n"
693	"attribute mediump vec4 a_color;\n"
694	"varying mediump vec4 v_color;\n"
695	"void main(void)\n"
696	"{\n"
697	"\tv_color = a_color;\n"
698	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
699	"}\n";
700
701	const char* fragmentShader = ""
702	"varying mediump vec4 v_color;\n"
703	"void main(void)\n"
704	"{\n"
705	"\tgl_FragColor = v_color;\n"
706	"}\n";
707
708	m_program = new Program(vertexShader, fragmentShader);
709
710	if (!m_program->isOk())
711		TCU_FAIL("Failed to compile shader program");
712}
713
714void GLES2ProgramSharingTest::destroyResource (void)
715{
716	delete m_program;
717}
718
719void GLES2ProgramSharingTest::renderResource (tcu::Surface* screen, tcu::Surface* reference)
720{
721	DE_ASSERT((screen && reference) || (!screen && !reference));
722
723	int width = 240;
724	int height = 240;
725
726	if (screen)
727	{
728		width = screen->getWidth();
729		height = screen->getHeight();
730	}
731
732	static const GLfloat coords[] = {
733		-0.9f, -0.9f,
734		 0.9f, -0.9f,
735		 0.9f,  0.9f,
736		-0.9f,  0.9f
737	};
738
739	static const GLfloat colors [] = {
740		0.0f, 0.0f, 0.0f, 1.0f,
741		1.0f, 0.0f, 0.0f, 1.0f,
742		0.0f, 1.0f, 0.0f, 1.0f,
743		0.0f, 0.0f, 1.0f, 1.0f
744	};
745
746	static const GLushort indices[] = {
747		0, 1, 2,
748		2, 3, 0
749	};
750
751	GLU_CHECK_CALL(glViewport(0, 0, width, height));
752
753	GLU_CHECK_CALL(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
754	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
755
756	GLU_CHECK_CALL(glUseProgram(m_program->getProgram()));
757
758	GLuint coordLocation = glGetAttribLocation(m_program->getProgram(), "a_pos");
759	GLU_CHECK_MSG("glGetAttribLocation()");
760	TCU_CHECK(coordLocation != (GLuint)-1);
761
762	GLuint colorLocation = glGetAttribLocation(m_program->getProgram(), "a_color");
763	GLU_CHECK_MSG("glGetAttribLocation()");
764	TCU_CHECK(colorLocation != (GLuint)-1);
765
766	GLU_CHECK_CALL(glEnableVertexAttribArray(colorLocation));
767	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLocation));
768
769	GLU_CHECK_CALL(glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, colors));
770	GLU_CHECK_CALL(glVertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, coords));
771
772	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices));
773	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLocation));
774	GLU_CHECK_CALL(glDisableVertexAttribArray(colorLocation));
775	GLU_CHECK_CALL(glUseProgram(0));
776
777	if (screen)
778	{
779		glReadPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
780
781		tcu::clear(reference->getAccess(), tcu::IVec4(0xff, 0, 0, 0xff));
782
783		int x1 = (int)((width/2.0f) * (-0.9f) + (width/2.0f));
784		int x2 = (int)((width/2.0f) * 0.9f + (width/2.0f));
785		int y1 = (int)((height/2.0f) * (-0.9f) + (height/2.0f));
786		int y2 = (int)((height/2.0f) * 0.9f + (height/2.0f));
787
788		for (int x = x1; x <= x2; x++)
789		{
790			for (int y = y1; y <= y2; y++)
791			{
792				float t = ((float)(x-x1) / (x2 - x1));
793				float s = ((float)(y-y1) / (y2-y1));
794				bool isUpper = t > s;
795
796				tcu::Vec4 a(colors[0],		colors[1],		colors[2],		colors[3]);
797				tcu::Vec4 b(colors[4 + 0],	colors[4 + 1],	colors[4 + 2],	colors[4 + 3]);
798				tcu::Vec4 c(colors[8 + 0],	colors[8 + 1],	colors[8 + 2],	colors[8 + 3]);
799				tcu::Vec4 d(colors[12 + 0],	colors[12 + 1],	colors[12 + 2],	colors[12 + 3]);
800
801
802				tcu::Vec4 color;
803
804				if (isUpper)
805					color = a * (1.0f - t)  + b * (t - s) + s * c;
806				else
807					color = a * (1.0f - s)  + d * (s - t) + t * c;
808
809				int red		= deClamp32((int)(255.0f * color.x()), 0, 255);
810				int green	= deClamp32((int)(255.0f * color.y()), 0, 255);
811				int blue	= deClamp32((int)(255.0f * color.z()), 0, 255);
812				int alpha	= deClamp32((int)(255.0f * color.w()), 0, 255);
813
814				reference->setPixel(x, y, tcu::RGBA(red, green, blue, alpha));
815			}
816		}
817	}
818}
819
820class GLES2ShaderSharingTest : public GLES2SharingTest
821{
822public:
823					GLES2ShaderSharingTest	(EglTestContext& eglTestCtx, const char* name, const char* desc, GLenum shaderType, const GLES2SharingTest::TestSpec& spec);
824
825private:
826	GLuint			m_shader;
827	GLenum			m_shaderType;
828
829	virtual void	createResource		(void);
830	virtual void 	destroyResource		(void);
831	virtual void	renderResource		(tcu::Surface* screen, tcu::Surface* reference);
832
833};
834
835GLES2ShaderSharingTest::GLES2ShaderSharingTest (EglTestContext& eglTestCtx, const char* name, const char* desc, GLenum shaderType, const GLES2SharingTest::TestSpec& spec)
836	: GLES2SharingTest	(eglTestCtx, name, desc, spec)
837	, m_shader			(0)
838	, m_shaderType		(shaderType)
839{
840}
841
842void GLES2ShaderSharingTest::createResource (void)
843{
844	const char* vertexShader = ""
845	"attribute mediump vec2 a_pos;\n"
846	"attribute mediump vec4 a_color;\n"
847	"varying mediump vec4 v_color;\n"
848	"void main(void)\n"
849	"{\n"
850	"\tv_color = a_color;\n"
851	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
852	"}\n";
853
854	const char* fragmentShader = ""
855	"varying mediump vec4 v_color;\n"
856	"void main(void)\n"
857	"{\n"
858	"\tgl_FragColor = v_color;\n"
859	"}\n";
860
861
862	m_shader = glCreateShader(m_shaderType);
863	GLU_CHECK_MSG("glCreateShader()");
864
865	switch (m_shaderType)
866	{
867		case GL_VERTEX_SHADER:
868			GLU_CHECK_CALL(glShaderSource(m_shader, 1, &vertexShader, NULL));
869			break;
870
871		case GL_FRAGMENT_SHADER:
872			GLU_CHECK_CALL(glShaderSource(m_shader, 1, &fragmentShader, NULL));
873			break;
874
875		default:
876			DE_ASSERT(false);
877	}
878
879	GLU_CHECK_CALL(glCompileShader(m_shader));
880
881	GLint status = 0;
882	GLU_CHECK_CALL(glGetShaderiv(m_shader, GL_COMPILE_STATUS, &status));
883
884	if (!status)
885	{
886		char buffer[256];
887		GLU_CHECK_CALL(glGetShaderInfoLog(m_shader, 256, NULL, buffer));
888
889		m_log << tcu::TestLog::Message << "Failed to compile shader" << tcu::TestLog::EndMessage;
890
891		switch (m_shaderType)
892		{
893			case GL_VERTEX_SHADER:
894				m_log << tcu::TestLog::Message << vertexShader << tcu::TestLog::EndMessage;
895				break;
896
897			case GL_FRAGMENT_SHADER:
898				m_log << tcu::TestLog::Message << fragmentShader << tcu::TestLog::EndMessage;
899				break;
900
901			default:
902				DE_ASSERT(false);
903		}
904
905		m_log << tcu::TestLog::Message << buffer << tcu::TestLog::EndMessage;
906		TCU_FAIL("Failed to compile shader");
907	}
908}
909
910void GLES2ShaderSharingTest::destroyResource (void)
911{
912	GLU_CHECK_CALL(glDeleteShader(m_shader));
913}
914
915void GLES2ShaderSharingTest::renderResource (tcu::Surface* screen, tcu::Surface* reference)
916{
917	DE_ASSERT((screen && reference) || (!screen && !reference));
918
919	int width = 240;
920	int height = 240;
921
922	const char* vertexShader = ""
923	"attribute mediump vec2 a_pos;\n"
924	"attribute mediump vec4 a_color;\n"
925	"varying mediump vec4 v_color;\n"
926	"void main(void)\n"
927	"{\n"
928	"\tv_color = a_color;\n"
929	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
930	"}\n";
931
932	const char* fragmentShader = ""
933	"varying mediump vec4 v_color;\n"
934	"void main(void)\n"
935	"{\n"
936	"\tgl_FragColor = v_color;\n"
937	"}\n";
938
939
940	GLuint otherShader = (GLuint)-1;
941
942	switch (m_shaderType)
943	{
944		case GL_VERTEX_SHADER:
945			otherShader = glCreateShader(GL_FRAGMENT_SHADER);
946			GLU_CHECK_MSG("glCreateShader()");
947			GLU_CHECK_CALL(glShaderSource(otherShader, 1, &fragmentShader, NULL));
948			break;
949
950		case GL_FRAGMENT_SHADER:
951			otherShader = glCreateShader(GL_VERTEX_SHADER);
952			GLU_CHECK_MSG("glCreateShader()");
953			GLU_CHECK_CALL(glShaderSource(otherShader, 1, &vertexShader, NULL));
954			break;
955
956		default:
957			DE_ASSERT(false);
958	}
959
960	GLU_CHECK_CALL(glCompileShader(otherShader));
961
962	GLint status = 0;
963	GLU_CHECK_CALL(glGetShaderiv(otherShader, GL_COMPILE_STATUS, &status));
964
965	if (!status)
966	{
967		char buffer[256];
968		GLU_CHECK_CALL(glGetShaderInfoLog(otherShader, 256, NULL, buffer));
969
970		m_log << tcu::TestLog::Message << "Failed to compile shader" << tcu::TestLog::EndMessage;
971
972		switch (m_shaderType)
973		{
974			case GL_FRAGMENT_SHADER:
975				m_log << tcu::TestLog::Message << vertexShader << tcu::TestLog::EndMessage;
976				break;
977
978			case GL_VERTEX_SHADER:
979				m_log << tcu::TestLog::Message << fragmentShader << tcu::TestLog::EndMessage;
980				break;
981
982			default:
983				DE_ASSERT(false);
984		}
985
986		m_log << tcu::TestLog::Message << buffer << tcu::TestLog::EndMessage;
987		TCU_FAIL("Failed to compile shader");
988	}
989
990	GLuint program = glCreateProgram();
991	GLU_CHECK_MSG("glCreateProgram()");
992
993	GLU_CHECK_CALL(glAttachShader(program, m_shader));
994	GLU_CHECK_CALL(glAttachShader(program, otherShader));
995
996	GLU_CHECK_CALL(glLinkProgram(program));
997	GLU_CHECK_CALL(glDeleteShader(otherShader));
998
999	status = 0;
1000	GLU_CHECK_CALL(glGetProgramiv(program, GL_LINK_STATUS, &status));
1001
1002	if (!status)
1003	{
1004		char buffer[256];
1005		GLU_CHECK_CALL(glGetProgramInfoLog(program, 256, NULL, buffer));
1006
1007		m_log << tcu::TestLog::Message << "Failed to link program" << tcu::TestLog::EndMessage;
1008
1009		m_log << tcu::TestLog::Message << vertexShader << tcu::TestLog::EndMessage;
1010		m_log << tcu::TestLog::Message << fragmentShader << tcu::TestLog::EndMessage;
1011		m_log << tcu::TestLog::Message << buffer << tcu::TestLog::EndMessage;
1012		TCU_FAIL("Failed to link program");
1013	}
1014
1015	if (screen)
1016	{
1017		width = screen->getWidth();
1018		height = screen->getHeight();
1019	}
1020
1021	static const GLfloat coords[] = {
1022		-0.9f, -0.9f,
1023		 0.9f, -0.9f,
1024		 0.9f,  0.9f,
1025		-0.9f,  0.9f
1026	};
1027
1028	static const GLfloat colors [] = {
1029		0.0f, 0.0f, 0.0f, 1.0f,
1030		1.0f, 0.0f, 0.0f, 1.0f,
1031		0.0f, 1.0f, 0.0f, 1.0f,
1032		0.0f, 0.0f, 1.0f, 1.0f
1033	};
1034
1035	static const GLushort indices[] = {
1036		0, 1, 2,
1037		2, 3, 0
1038	};
1039
1040	GLU_CHECK_CALL(glViewport(0, 0, width, height));
1041
1042	GLU_CHECK_CALL(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
1043	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1044
1045	GLU_CHECK_CALL(glUseProgram(program));
1046
1047	GLuint coordLocation = glGetAttribLocation(program, "a_pos");
1048	GLU_CHECK_MSG("glGetAttribLocation()");
1049	TCU_CHECK(coordLocation != (GLuint)-1);
1050
1051	GLuint colorLocation = glGetAttribLocation(program, "a_color");
1052	GLU_CHECK_MSG("glGetAttribLocation()");
1053	TCU_CHECK(colorLocation != (GLuint)-1);
1054
1055	GLU_CHECK_CALL(glEnableVertexAttribArray(colorLocation));
1056	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLocation));
1057
1058	GLU_CHECK_CALL(glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, colors));
1059	GLU_CHECK_CALL(glVertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, coords));
1060
1061	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices));
1062	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLocation));
1063	GLU_CHECK_CALL(glDisableVertexAttribArray(colorLocation));
1064	GLU_CHECK_CALL(glUseProgram(0));
1065
1066	if (screen)
1067	{
1068		glReadPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
1069
1070		tcu::clear(reference->getAccess(), tcu::IVec4(0xff, 0, 0, 0xff));
1071
1072		int x1 = (int)((width/2.0f) * (-0.9f) + (width/2.0f));
1073		int x2 = (int)((width/2.0f) * 0.9f + (width/2.0f));
1074		int y1 = (int)((height/2.0f) * (-0.9f) + (height/2.0f));
1075		int y2 = (int)((height/2.0f) * 0.9f + (height/2.0f));
1076
1077		for (int x = x1; x <= x2; x++)
1078		{
1079			for (int y = y1; y <= y2; y++)
1080			{
1081				float t = ((float)(x-x1) / (x2 - x1));
1082				float s = ((float)(y-y1) / (y2-y1));
1083				bool isUpper = t > s;
1084
1085				tcu::Vec4 a(colors[0],		colors[1],		colors[2],		colors[3]);
1086				tcu::Vec4 b(colors[4 + 0],	colors[4 + 1],	colors[4 + 2],	colors[4 + 3]);
1087				tcu::Vec4 c(colors[8 + 0],	colors[8 + 1],	colors[8 + 2],	colors[8 + 3]);
1088				tcu::Vec4 d(colors[12 + 0],	colors[12 + 1],	colors[12 + 2],	colors[12 + 3]);
1089
1090
1091				tcu::Vec4 color;
1092
1093				if (isUpper)
1094					color = a * (1.0f - t)  + b * (t - s) + s * c;
1095				else
1096					color = a * (1.0f - s)  + d * (s - t) + t * c;
1097
1098				int red		= deClamp32((int)(255.0f * color.x()), 0, 255);
1099				int green	= deClamp32((int)(255.0f * color.y()), 0, 255);
1100				int blue	= deClamp32((int)(255.0f * color.z()), 0, 255);
1101				int alpha	= deClamp32((int)(255.0f * color.w()), 0, 255);
1102
1103				reference->setPixel(x, y, tcu::RGBA(red, green, blue, alpha));
1104			}
1105		}
1106	}
1107}
1108
1109SharingTests::SharingTests (EglTestContext& eglTestCtx)
1110	: TestCaseGroup	(eglTestCtx, "sharing", "Sharing test cases")
1111{
1112}
1113
1114void SharingTests::init (void)
1115{
1116	TestCaseGroup* gles2 = new TestCaseGroup(m_eglTestCtx, "gles2", "OpenGL ES 2 sharing test");
1117
1118	TestCaseGroup* context = new TestCaseGroup(m_eglTestCtx, "context", "Context creation and destruction tests");
1119
1120	{
1121		GLES2SharingTest::TestSpec spec;
1122		spec.destroyContextBFirst	= false;
1123		spec.useResource			= false;
1124		spec.destroyOnContexB		= false;
1125		spec.initializeData			= true;
1126		spec.renderOnContexA		= true;
1127		spec.renderOnContexB		= true;
1128		spec.verifyOnContexA		= true;
1129		spec.verifyOnContexB		= true;
1130
1131		context->addChild(new GLES2SharingTest(m_eglTestCtx, "create_destroy", "Simple context creation and destruction", spec));
1132	}
1133	{
1134		GLES2SharingTest::TestSpec spec;
1135		spec.destroyContextBFirst	= true;
1136		spec.useResource			= false;
1137		spec.destroyOnContexB		= false;
1138		spec.initializeData			= false;
1139		spec.renderOnContexA		= false;
1140		spec.renderOnContexB		= false;
1141		spec.verifyOnContexA		= false;
1142		spec.verifyOnContexB		= false;
1143
1144		context->addChild(new GLES2SharingTest(m_eglTestCtx, "create_destroy_mixed", "Simple context creation and destruction test with different destruction order", spec));
1145	}
1146
1147	gles2->addChild(context);
1148
1149	TestCaseGroup* buffer = new TestCaseGroup(m_eglTestCtx, "buffer", "Buffer creation, destruction and rendering test");
1150
1151	{
1152		GLES2SharingTest::TestSpec spec;
1153		spec.destroyContextBFirst	= false;
1154		spec.useResource			= true;
1155		spec.destroyOnContexB		= false;
1156		spec.initializeData			= true;
1157		spec.renderOnContexA		= false;
1158		spec.renderOnContexB		= false;
1159		spec.verifyOnContexA		= false;
1160		spec.verifyOnContexB		= false;
1161
1162		buffer->addChild(new GLES2BufferSharingTest(m_eglTestCtx, "create_delete", "Create and delete on shared context", spec));
1163	}
1164	{
1165		GLES2SharingTest::TestSpec spec;
1166		spec.destroyContextBFirst	= false;
1167		spec.useResource			= true;
1168		spec.destroyOnContexB		= true;
1169		spec.initializeData			= true;
1170		spec.renderOnContexA		= false;
1171		spec.renderOnContexB		= false;
1172		spec.verifyOnContexA		= false;
1173		spec.verifyOnContexB		= false;
1174
1175		buffer->addChild(new GLES2BufferSharingTest(m_eglTestCtx, "create_delete_mixed", "Create and delet on different contexts", spec));
1176	}
1177	{
1178		GLES2SharingTest::TestSpec spec;
1179		spec.destroyContextBFirst	= false;
1180		spec.useResource			= true;
1181		spec.destroyOnContexB		= false;
1182		spec.initializeData			= true;
1183		spec.renderOnContexA		= true;
1184		spec.renderOnContexB		= true;
1185		spec.verifyOnContexA		= true;
1186		spec.verifyOnContexB		= true;
1187
1188		buffer->addChild(new GLES2BufferSharingTest(m_eglTestCtx, "render", "Create, rendering on two different contexts and delete", spec));
1189	}
1190
1191	gles2->addChild(buffer);
1192
1193	TestCaseGroup* texture = new TestCaseGroup(m_eglTestCtx, "texture", "Texture creation, destruction and rendering tests");
1194
1195	{
1196		GLES2SharingTest::TestSpec spec;
1197		spec.destroyContextBFirst	= false;
1198		spec.useResource			= true;
1199		spec.destroyOnContexB		= false;
1200		spec.initializeData			= true;
1201		spec.renderOnContexA		= false;
1202		spec.renderOnContexB		= false;
1203		spec.verifyOnContexA		= false;
1204		spec.verifyOnContexB		= false;
1205
1206		texture->addChild(new GLES2TextureSharingTest(m_eglTestCtx, "create_delete", "Create and delete on shared context", spec));
1207	}
1208	{
1209		GLES2SharingTest::TestSpec spec;
1210		spec.destroyContextBFirst	= false;
1211		spec.useResource			= true;
1212		spec.destroyOnContexB		= true;
1213		spec.initializeData			= true;
1214		spec.renderOnContexA		= false;
1215		spec.renderOnContexB		= false;
1216		spec.verifyOnContexA		= false;
1217		spec.verifyOnContexB		= false;
1218
1219		texture->addChild(new GLES2TextureSharingTest(m_eglTestCtx, "create_delete_mixed", "Create and delete on different contexts", spec));
1220	}
1221	{
1222		GLES2SharingTest::TestSpec spec;
1223		spec.destroyContextBFirst	= false;
1224		spec.useResource			= true;
1225		spec.destroyOnContexB		= false;
1226		spec.initializeData			= true;
1227		spec.renderOnContexA		= true;
1228		spec.renderOnContexB		= true;
1229		spec.verifyOnContexA		= true;
1230		spec.verifyOnContexB		= true;
1231
1232		texture->addChild(new GLES2TextureSharingTest(m_eglTestCtx, "render", "Create, render in two contexts and delete", spec));
1233	}
1234
1235	gles2->addChild(texture);
1236
1237	TestCaseGroup* program = new TestCaseGroup(m_eglTestCtx, "program", "Program creation, destruction and rendering test");
1238
1239	{
1240		GLES2SharingTest::TestSpec spec;
1241		spec.destroyContextBFirst	= false;
1242		spec.useResource			= true;
1243		spec.destroyOnContexB		= false;
1244		spec.initializeData			= true;
1245		spec.renderOnContexA		= false;
1246		spec.renderOnContexB		= false;
1247		spec.verifyOnContexA		= false;
1248		spec.verifyOnContexB		= false;
1249
1250		program->addChild(new GLES2ProgramSharingTest(m_eglTestCtx, "create_delete", "Create and delete on shared context", spec));
1251	}
1252	{
1253		GLES2SharingTest::TestSpec spec;
1254		spec.destroyContextBFirst	= false;
1255		spec.useResource			= true;
1256		spec.destroyOnContexB		= true;
1257		spec.initializeData			= true;
1258		spec.renderOnContexA		= false;
1259		spec.renderOnContexB		= false;
1260		spec.verifyOnContexA		= false;
1261		spec.verifyOnContexB		= false;
1262
1263		program->addChild(new GLES2ProgramSharingTest(m_eglTestCtx, "create_delete_mixed", "Create and delete on different contexts", spec));
1264	}
1265	{
1266		GLES2SharingTest::TestSpec spec;
1267		spec.destroyContextBFirst	= false;
1268		spec.useResource			= true;
1269		spec.destroyOnContexB		= false;
1270		spec.initializeData			= true;
1271		spec.renderOnContexA		= true;
1272		spec.renderOnContexB		= true;
1273		spec.verifyOnContexA		= true;
1274		spec.verifyOnContexB		= true;
1275
1276		program->addChild(new GLES2ProgramSharingTest(m_eglTestCtx, "render", "Create, render in two contexts and delete", spec));
1277	}
1278
1279	gles2->addChild(program);
1280
1281	TestCaseGroup* shader = new TestCaseGroup(m_eglTestCtx, "shader", "Shader creation, destruction and rendering test");
1282
1283	{
1284		GLES2SharingTest::TestSpec spec;
1285		spec.destroyContextBFirst	= false;
1286		spec.useResource			= true;
1287		spec.destroyOnContexB		= false;
1288		spec.initializeData			= true;
1289		spec.renderOnContexA		= false;
1290		spec.renderOnContexB		= false;
1291		spec.verifyOnContexA		= false;
1292		spec.verifyOnContexB		= false;
1293
1294		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "create_delete_vert", "Create and delete on shared context", GL_VERTEX_SHADER, spec));
1295	}
1296	{
1297		GLES2SharingTest::TestSpec spec;
1298		spec.destroyContextBFirst	= false;
1299		spec.useResource			= true;
1300		spec.destroyOnContexB		= true;
1301		spec.initializeData			= true;
1302		spec.renderOnContexA		= false;
1303		spec.renderOnContexB		= false;
1304		spec.verifyOnContexA		= false;
1305		spec.verifyOnContexB		= false;
1306
1307		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "create_delete_mixed_vert", "Create and delete on different contexts", GL_VERTEX_SHADER, spec));
1308	}
1309	{
1310		GLES2SharingTest::TestSpec spec;
1311		spec.destroyContextBFirst	= false;
1312		spec.useResource			= true;
1313		spec.destroyOnContexB		= false;
1314		spec.initializeData			= true;
1315		spec.renderOnContexA		= true;
1316		spec.renderOnContexB		= true;
1317		spec.verifyOnContexA		= true;
1318		spec.verifyOnContexB		= true;
1319
1320		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "render_vert", "Create, render on two contexts and delete", GL_VERTEX_SHADER, spec));
1321	}
1322	{
1323		GLES2SharingTest::TestSpec spec;
1324		spec.destroyContextBFirst	= false;
1325		spec.useResource			= true;
1326		spec.destroyOnContexB		= false;
1327		spec.initializeData			= true;
1328		spec.renderOnContexA		= false;
1329		spec.renderOnContexB		= false;
1330		spec.verifyOnContexA		= false;
1331		spec.verifyOnContexB		= false;
1332
1333		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "create_delete_frag", "Create and delete on shared context", GL_FRAGMENT_SHADER, spec));
1334	}
1335	{
1336		GLES2SharingTest::TestSpec spec;
1337		spec.destroyContextBFirst	= false;
1338		spec.useResource			= true;
1339		spec.destroyOnContexB		= true;
1340		spec.initializeData			= true;
1341		spec.renderOnContexA		= false;
1342		spec.renderOnContexB		= false;
1343		spec.verifyOnContexA		= false;
1344		spec.verifyOnContexB		= false;
1345
1346		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "create_delete_mixed_frag", "Create and delete on different contexts", GL_FRAGMENT_SHADER, spec));
1347	}
1348	{
1349		GLES2SharingTest::TestSpec spec;
1350		spec.destroyContextBFirst	= false;
1351		spec.useResource			= true;
1352		spec.destroyOnContexB		= false;
1353		spec.initializeData			= true;
1354		spec.renderOnContexA		= true;
1355		spec.renderOnContexB		= true;
1356		spec.verifyOnContexA		= true;
1357		spec.verifyOnContexB		= true;
1358
1359		shader->addChild(new GLES2ShaderSharingTest(m_eglTestCtx, "render_frag", "Create, render on two contexts and delete", GL_FRAGMENT_SHADER, spec));
1360	}
1361
1362
1363	gles2->addChild(shader);
1364
1365
1366	gles2->addChild(new GLES2SharingThreadedTests(m_eglTestCtx));
1367
1368	addChild(gles2);
1369}
1370
1371} // egl
1372} // deqp
1373