1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24/**
25 * \file  gl4cBufferStorageTests.cpp
26 * \brief Implements conformance tests for "Buffer storage" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29#include "gl4cBufferStorageTests.hpp"
30
31#include "gluContextInfo.hpp"
32#include "gluDefs.hpp"
33#include "gluStrUtil.hpp"
34#include "glwEnums.hpp"
35#include "glwFunctions.hpp"
36#include "tcuImageIO.hpp"
37#include "tcuTestLog.hpp"
38#include "tcuTexture.hpp"
39
40#include <iomanip>
41#include <string>
42
43using namespace glw;
44
45namespace gl4cts
46{
47namespace BufferStorage
48{
49/* Enums */
50
51/* Represents how functionality is supported */
52enum FUNCTIONALITY_SUPPORT
53{
54	FUNCTIONALITY_SUPPORT_NONE = 0,
55	FUNCTIONALITY_SUPPORT_EXTENSION,
56	FUNCTIONALITY_SUPPORT_CORE,
57	FUNCTIONALITY_SUPPORT_NOT_DETERMINED,
58};
59
60/* Prototypes of functions  */
61FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context& context);
62bool isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor);
63
64/* Classes */
65
66/** Represents buffer instance
67 * Provides basic buffer functionality
68 **/
69class Buffer
70{
71public:
72	// I don't quite understand how the old code *ever* worked...
73	// This is uglyish hack to make it actually compile on any sane
74	// compiler, and not crash.
75	struct MoveMapOwner
76	{
77		MoveMapOwner(Buffer* buffer_, glw::GLvoid* data_) : buffer(buffer_), data(data_)
78		{
79		}
80
81		Buffer*		 buffer;
82		glw::GLvoid* data;
83	};
84
85	/* Public classes */
86	class MapOwner
87	{
88		friend class Buffer;
89
90	public:
91		MapOwner(MapOwner& map_owner);
92		MapOwner(const MoveMapOwner& moveOwner);
93		~MapOwner();
94
95		glw::GLvoid* m_data;
96
97	private:
98		MapOwner(Buffer& buffer, glw::GLvoid* data);
99
100		Buffer* m_buffer;
101	};
102
103	/* Public methods */
104	/* Ctr & Dtr */
105	Buffer(deqp::Context& context);
106	~Buffer();
107
108	/* Init & Release */
109	void InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data);
110
111	void InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid* data);
112
113	void Release();
114
115	/* Functionality */
116	void Bind() const;
117	void BindBase(glw::GLuint index) const;
118
119	void BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const;
120
121	MoveMapOwner MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access);
122
123	void UnMap();
124
125	/* Public static routines */
126	/* Extensions */
127	static void LoadExtDirectStateAccess(deqp::Context& context);
128
129	/* Functionality */
130	static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
131
132	static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index);
133
134	static void BindRange(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
135						  glw::GLintptr offset, glw::GLsizeiptr size);
136
137	static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
138					 const glw::GLvoid* data);
139
140	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
141
142	static void GetNamedParameter(const glw::Functions& gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint* data);
143
144	static void GetParameter(const glw::Functions& gl, glw::GLenum target, glw::GLenum value, glw::GLint* data);
145
146	static void GetSubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
147						   glw::GLvoid* data);
148
149	static void* Map(const glw::Functions& gl, glw::GLenum target, glw::GLenum access);
150
151	static void* MapRange(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
152						  glw::GLenum access);
153
154	static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
155						const glw::GLvoid* data);
156
157	static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
158						glw::GLvoid* data);
159
160	static void UnMap(const glw::Functions& gl, glw::GLenum target);
161
162	/* Public fields */
163	glw::GLuint m_id;
164
165	/* Public constants */
166	static const glw::GLuint m_invalid_id;
167	static const glw::GLuint m_n_targets = 13;
168	static const glw::GLenum m_targets[m_n_targets];
169
170private:
171	/* Private enums */
172
173	/* Private fields */
174	deqp::Context& m_context;
175	glw::GLenum	m_target;
176};
177
178/** Represents framebuffer
179 * Provides basic functionality
180 **/
181class Framebuffer
182{
183public:
184	/* Public methods */
185	/* Ctr & Dtr */
186	Framebuffer(deqp::Context& context);
187	~Framebuffer();
188
189	/* Init & Release */
190	void Release();
191
192	/* Public static routines */
193	static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
194							  glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
195
196	static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id);
197
198	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
199
200	/* Public fields */
201	glw::GLuint m_id;
202
203	/* Public constants */
204	static const glw::GLuint m_invalid_id;
205
206private:
207	/* Private fields */
208	deqp::Context& m_context;
209};
210
211/** Represents shader instance.
212 * Provides basic functionality for shaders.
213 **/
214class Shader
215{
216public:
217	/* Public methods */
218	/* Ctr & Dtr */
219	Shader(deqp::Context& context);
220	~Shader();
221
222	/* Init & Realese */
223	void Init(glw::GLenum stage, const std::string& source);
224	void Release();
225
226	/* Public static routines */
227	/* Functionality */
228	static void Compile(const glw::Functions& gl, glw::GLuint id);
229
230	static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id);
231
232	static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source);
233
234	/* Public fields */
235	glw::GLuint m_id;
236
237	/* Public constants */
238	static const glw::GLuint m_invalid_id;
239
240private:
241	/* Private fields */
242	deqp::Context& m_context;
243};
244
245/** Represents program instance.
246 * Provides basic functionality
247 **/
248class Program
249{
250public:
251	/* Public methods */
252	/* Ctr & Dtr */
253	Program(deqp::Context& context);
254	~Program();
255
256	/* Init & Release */
257	void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader,
258			  const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader,
259			  const std::string& vertex_shader);
260
261	void Release();
262
263	/* Public static routines */
264	/* Functionality */
265	static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id);
266
267	static void Create(const glw::Functions& gl, glw::GLuint& out_id);
268
269	static void Link(const glw::Functions& gl, glw::GLuint id);
270
271	static void Use(const glw::Functions& gl, glw::GLuint id);
272
273	/* Public fields */
274	glw::GLuint m_id;
275
276	Shader m_compute;
277	Shader m_fragment;
278	Shader m_geometry;
279	Shader m_tess_ctrl;
280	Shader m_tess_eval;
281	Shader m_vertex;
282
283	/* Public constants */
284	static const glw::GLuint m_invalid_id;
285
286private:
287	/* Private fields */
288	deqp::Context& m_context;
289};
290
291/** Represents texture instance
292 **/
293class Texture
294{
295public:
296	/* Public types */
297	/* Public methods */
298	/* Ctr & Dtr */
299	Texture(deqp::Context& context);
300	~Texture();
301
302	/* Init & Release */
303	void Release();
304
305	/* Public static routines */
306	/* Extensions */
307	static void LoadExtDirectStateAccess(deqp::Context& context);
308
309	/* Functionality */
310	static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
311
312	static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
313								glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
314								glw::GLsizei image_size, const glw::GLvoid* data);
315
316	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
317
318	static void GetData(const glw::Functions& gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
319						glw::GLvoid* out_data);
320
321	static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
322								  glw::GLint* param);
323
324	static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
325					  glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
326					  const glw::GLvoid* data);
327
328	static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
329						glw::GLuint width, glw::GLuint height, glw::GLuint depth);
330
331	static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
332						 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
333						 glw::GLenum type, const glw::GLvoid* pixels);
334
335	/* Public fields */
336	glw::GLuint m_id;
337
338	/* Public constants */
339	static const glw::GLuint m_invalid_id;
340
341private:
342	/* Private fields */
343	deqp::Context& m_context;
344
345	/* Private static fields */
346	static FUNCTIONALITY_SUPPORT m_direct_state_access_support;
347};
348
349/** Represents Vertex array object
350 * Provides basic functionality
351 **/
352class VertexArray
353{
354public:
355	/* Public methods */
356	/* Ctr & Dtr */
357	VertexArray(deqp::Context& Context);
358	~VertexArray();
359
360	/* Init & Release */
361	void Release();
362
363	/* Public static methods */
364	static void Bind(const glw::Functions& gl, glw::GLuint id);
365	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
366
367	/* Public fields */
368	glw::GLuint m_id;
369
370	/* Public constants */
371	static const glw::GLuint m_invalid_id;
372
373private:
374	/* Private fields */
375	deqp::Context& m_context;
376};
377
378/* Global variables */
379static FUNCTIONALITY_SUPPORT m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
380
381/* Implementations of functions */
382/** Get support for direct state access
383 *
384 * @param context CTS context
385 **/
386FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context& context)
387{
388	if (FUNCTIONALITY_SUPPORT_NOT_DETERMINED == m_direct_state_access_support)
389	{
390		const Functions& gl = context.getRenderContext().getFunctions();
391
392		if (true == isGLVersionAtLeast(gl, 4, 5))
393		{
394			m_direct_state_access_support = FUNCTIONALITY_SUPPORT_CORE;
395		}
396		else
397		{
398			bool is_supported = context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
399
400			if (true == is_supported)
401			{
402				m_direct_state_access_support = FUNCTIONALITY_SUPPORT_EXTENSION;
403			}
404			else
405			{
406				m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NONE;
407			}
408		}
409	}
410
411	return m_direct_state_access_support;
412}
413
414/** Check if GL context meets version requirements
415 *
416 * @param gl             Functions
417 * @param required_major Minimum required MAJOR_VERSION
418 * @param required_minor Minimum required MINOR_VERSION
419 *
420 * @return true if GL context version is at least as requested, false otherwise
421 **/
422bool isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
423{
424	glw::GLint major = 0;
425	glw::GLint minor = 0;
426
427	gl.getIntegerv(GL_MAJOR_VERSION, &major);
428	gl.getIntegerv(GL_MINOR_VERSION, &minor);
429
430	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
431
432	if (major > required_major)
433	{
434		/* Major is higher than required one */
435		return true;
436	}
437	else if (major == required_major)
438	{
439		if (minor >= required_minor)
440		{
441			/* Major is equal to required one */
442			/* Minor is higher than or equal to required one */
443			return true;
444		}
445		else
446		{
447			/* Major is equal to required one */
448			/* Minor is lower than required one */
449			return false;
450		}
451	}
452	else
453	{
454		/* Major is lower than required one */
455		return false;
456	}
457}
458
459/* Buffer constants */
460const GLuint Buffer::m_invalid_id = -1;
461
462const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
463	GL_ARRAY_BUFFER,			  /*  0 */
464	GL_ATOMIC_COUNTER_BUFFER,	 /*  1 */
465	GL_COPY_READ_BUFFER,		  /*  2 */
466	GL_COPY_WRITE_BUFFER,		  /*  3 */
467	GL_DISPATCH_INDIRECT_BUFFER,  /*  4 */
468	GL_DRAW_INDIRECT_BUFFER,	  /*  5 */
469	GL_ELEMENT_ARRAY_BUFFER,	  /*  6 */
470	GL_PIXEL_PACK_BUFFER,		  /*  7 */
471	GL_PIXEL_UNPACK_BUFFER,		  /*  8 */
472	GL_QUERY_BUFFER,			  /*  9 */
473	GL_SHADER_STORAGE_BUFFER,	 /* 10 */
474	GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
475	GL_UNIFORM_BUFFER,			  /* 12 */
476};
477
478/** Constructor.
479 *
480 * @param context CTS context.
481 **/
482Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
483{
484}
485
486/** Destructor
487 *
488 **/
489Buffer::~Buffer()
490{
491	Release();
492}
493
494/** Initialize buffer instance
495 *
496 * @param target Buffer target
497 * @param usage  Buffer usage enum
498 * @param size   <size> parameter
499 * @param data   <data> parameter
500 **/
501void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data)
502{
503	/* Delete previous buffer instance */
504	Release();
505
506	m_target = target;
507
508	const Functions& gl = m_context.getRenderContext().getFunctions();
509
510	Generate(gl, m_id);
511	Bind(gl, m_id, m_target);
512	Data(gl, m_target, usage, size, data);
513}
514
515/** Initialize buffer instance
516 *
517 * @param target Buffer target
518 * @param usage  Buffer usage enum
519 * @param size   <size> parameter
520 * @param data   <data> parameter
521 **/
522void Buffer::InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid* data)
523{
524	/* Delete previous buffer instance */
525	Release();
526
527	m_target = target;
528
529	const Functions& gl = m_context.getRenderContext().getFunctions();
530
531	Generate(gl, m_id);
532	Bind(gl, m_id, m_target);
533	Storage(gl, m_target, flags, size, data);
534}
535
536/** Release buffer instance
537 *
538 **/
539void Buffer::Release()
540{
541	if (m_invalid_id != m_id)
542	{
543		const Functions& gl = m_context.getRenderContext().getFunctions();
544
545		gl.deleteBuffers(1, &m_id);
546		m_id = m_invalid_id;
547	}
548}
549
550/** Binds buffer to its target
551 *
552 **/
553void Buffer::Bind() const
554{
555	const Functions& gl = m_context.getRenderContext().getFunctions();
556
557	Bind(gl, m_id, m_target);
558}
559
560/** Binds indexed buffer
561 *
562 * @param index <index> parameter
563 **/
564void Buffer::BindBase(glw::GLuint index) const
565{
566	const Functions& gl = m_context.getRenderContext().getFunctions();
567
568	BindBase(gl, m_id, m_target, index);
569}
570
571/** Binds range of buffer
572 *
573 * @param index  <index> parameter
574 * @param offset <offset> parameter
575 * @param size   <size> parameter
576 **/
577void Buffer::BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const
578{
579	const Functions& gl = m_context.getRenderContext().getFunctions();
580
581	BindRange(gl, m_id, m_target, index, offset, size);
582}
583
584/** Maps contents of buffer into CPU space
585 *
586 * @param access Requested access
587 *
588 * @return Pointer to memory region available for CPU
589 **/
590Buffer::MoveMapOwner Buffer::MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access)
591{
592	const Functions& gl = m_context.getRenderContext().getFunctions();
593
594	Bind(gl, m_id, m_target);
595
596	void* data = MapRange(gl, m_target, offset, length, access);
597
598	MoveMapOwner map(this, data);
599
600	return map;
601}
602
603/** Unmaps contents of buffer
604 *
605 **/
606void Buffer::UnMap()
607{
608	const Functions& gl = m_context.getRenderContext().getFunctions();
609
610	UnMap(gl, m_target);
611}
612
613/** Loads entry points for direct state access extension
614 *
615 * @param context CTS context
616 **/
617void Buffer::LoadExtDirectStateAccess(deqp::Context& context)
618{
619	FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
620
621	switch (support)
622	{
623	case FUNCTIONALITY_SUPPORT_NONE:
624		/* Nothing to be done */
625		break;
626	case FUNCTIONALITY_SUPPORT_CORE:
627	case FUNCTIONALITY_SUPPORT_EXTENSION:
628		break;
629	default:
630		TCU_FAIL("Invalid enum");
631		break;
632	}
633}
634
635/** Bind buffer to given target
636 *
637 * @param gl     GL functions
638 * @param id     Id of buffer
639 * @param target Buffer target
640 **/
641void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
642{
643	gl.bindBuffer(target, id);
644	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
645}
646
647/** Binds indexed buffer
648 *
649 * @param gl     GL functions
650 * @param id     Id of buffer
651 * @param target Buffer target
652 * @param index  <index> parameter
653 **/
654void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
655{
656	gl.bindBufferBase(target, index, id);
657	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
658}
659
660/** Binds buffer range
661 *
662 * @param gl     GL functions
663 * @param id     Id of buffer
664 * @param target Buffer target
665 * @param index  <index> parameter
666 * @param offset <offset> parameter
667 * @param size   <size> parameter
668 **/
669void Buffer::BindRange(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
670					   glw::GLintptr offset, glw::GLsizeiptr size)
671{
672	gl.bindBufferRange(target, index, id, offset, size);
673	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
674}
675
676/** Allocate memory for buffer and sends initial content
677 *
678 * @param gl     GL functions
679 * @param target Buffer target
680 * @param usage  Buffer usage enum
681 * @param size   <size> parameter
682 * @param data   <data> parameter
683 **/
684void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
685				  const glw::GLvoid* data)
686{
687	gl.bufferData(target, size, data, usage);
688	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
689}
690
691/** Generate buffer
692 *
693 * @param gl     GL functions
694 * @param out_id Id of buffer
695 **/
696void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
697{
698	GLuint id = m_invalid_id;
699
700	gl.genBuffers(1, &id);
701	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
702
703	if (m_invalid_id == id)
704	{
705		TCU_FAIL("Got invalid id");
706	}
707
708	out_id = id;
709}
710
711/** Query parameter of named buffer
712 *
713 * @param gl     GL functions
714 * @param buffer Buffer name
715 * @param pname  Parameter name
716 * @param data   Storage for queried results
717 **/
718void Buffer::GetNamedParameter(const glw::Functions& gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint* data)
719{
720	gl.getNamedBufferParameteriv(buffer, pname, data);
721	GLU_EXPECT_NO_ERROR(gl.getError(), "GetNameBufferParameteriv");
722}
723
724/** Query parameter of bound buffer
725 *
726 * @param gl     GL functions
727 * @param Target Buffer target
728 * @param pname  Parameter name
729 * @param data   Storage for queried results
730 **/
731void Buffer::GetParameter(const glw::Functions& gl, glw::GLenum target, glw::GLenum value, glw::GLint* data)
732{
733	gl.getBufferParameteriv(target, value, data);
734	GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferParameteriv");
735}
736
737/** Get contents of buffer's region
738 *
739 * @param gl     GL functions
740 * @param target Buffer target
741 * @param offset Offset in buffer
742 * @param size   <size> parameter
743 * @param data   <data> parameter
744 **/
745void Buffer::GetSubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
746						glw::GLvoid* data)
747{
748	gl.getBufferSubData(target, offset, size, data);
749	GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferSubData");
750}
751
752/** Maps buffer content
753 *
754 * @param gl     GL functions
755 * @param target Buffer target
756 * @param access Access rights for mapped region
757 *
758 * @return Mapped memory
759 **/
760void* Buffer::Map(const glw::Functions& gl, glw::GLenum target, glw::GLenum access)
761{
762	void* result = gl.mapBuffer(target, access);
763	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
764
765	return result;
766}
767
768/** Maps buffer content
769 *
770 * @param gl     GL functions
771 * @param target Buffer target
772 * @param access Access rights for mapped region
773 *
774 * @return Mapped memory
775 **/
776void* Buffer::MapRange(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
777					   glw::GLenum access)
778{
779	void* result = gl.mapBufferRange(target, offset, length, access);
780	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
781
782	return result;
783}
784
785/** Allocate immutable memory for buffer and sends initial content
786 *
787 * @param gl     GL functions
788 * @param target Buffer target
789 * @param flags  Buffer flags
790 * @param size   <size> parameter
791 * @param data   <data> parameter
792 **/
793void Buffer::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
794					 const glw::GLvoid* data)
795{
796	gl.bufferStorage(target, size, data, flags);
797	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
798}
799
800/** Update range of buffer
801 *
802 * @param gl     GL functions
803 * @param target Buffer target
804 * @param offset Offset in buffer
805 * @param size   <size> parameter
806 * @param data   <data> parameter
807 **/
808void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
809					 glw::GLvoid* data)
810{
811	gl.bufferSubData(target, offset, size, data);
812	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
813}
814
815/** Unmaps buffer
816 *
817 * @param gl     GL functions
818 * @param target Buffer target
819 **/
820void Buffer::UnMap(const glw::Functions& gl, glw::GLenum target)
821{
822	gl.unmapBuffer(target);
823	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
824}
825
826/** Constructor
827 * Takes ownership of mapped region
828 *
829 * @param buffer Mapped buffer
830 * @param data   Mapped data
831 **/
832Buffer::MapOwner::MapOwner(Buffer& buffer, glw::GLvoid* data) : m_data(data), m_buffer(&buffer)
833{
834	/* Nothing to be done */
835}
836
837Buffer::MapOwner::MapOwner(const Buffer::MoveMapOwner& moveOwner) : m_data(moveOwner.data), m_buffer(moveOwner.buffer)
838{
839}
840
841/** Move constructor
842 * Transfer ownership of mapped region.
843 *
844 * @param map_owner Map owner
845 **/
846Buffer::MapOwner::MapOwner(MapOwner& map_owner) : m_data(map_owner.m_data), m_buffer(map_owner.m_buffer)
847{
848	map_owner.m_data   = 0;
849	map_owner.m_buffer = 0;
850}
851
852/** Destructor
853 * Unmaps buffer
854 **/
855Buffer::MapOwner::~MapOwner()
856{
857	m_data = 0;
858	if (0 != m_buffer)
859	{
860		m_buffer->Bind();
861		m_buffer->UnMap();
862		m_buffer = 0;
863	}
864}
865
866/* Framebuffer constants */
867const GLuint Framebuffer::m_invalid_id = -1;
868
869/** Constructor.
870 *
871 * @param context CTS context.
872 **/
873Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
874{
875	/* Nothing to done here */
876}
877
878/** Destructor
879 *
880 **/
881Framebuffer::~Framebuffer()
882{
883	Release();
884}
885
886/** Release texture instance
887 *
888 **/
889void Framebuffer::Release()
890{
891	if (m_invalid_id != m_id)
892	{
893		const Functions& gl = m_context.getRenderContext().getFunctions();
894
895		gl.deleteFramebuffers(1, &m_id);
896		m_id = m_invalid_id;
897	}
898}
899
900/** Attach texture to specified attachment
901 *
902 * @param gl         GL functions
903 * @param target     Framebuffer target
904 * @param attachment Attachment
905 * @param texture_id Texture id
906 * @param width      Texture width
907 * @param height     Texture height
908 **/
909void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
910								glw::GLuint texture_id, glw::GLuint width, glw::GLuint height)
911{
912	gl.framebufferTexture(target, attachment, texture_id, 0 /* level */);
913	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
914
915	gl.viewport(0 /* x */, 0 /* y */, width, height);
916	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
917}
918
919/** Binds framebuffer to DRAW_FRAMEBUFFER
920 *
921 * @param gl     GL functions
922 * @param target Framebuffer target
923 * @param id     ID of framebuffer
924 **/
925void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
926{
927	gl.bindFramebuffer(target, id);
928	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
929}
930
931/** Generate framebuffer
932 *
933 **/
934void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
935{
936	GLuint id = m_invalid_id;
937
938	gl.genFramebuffers(1, &id);
939	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
940
941	if (m_invalid_id == id)
942	{
943		TCU_FAIL("Invalid id");
944	}
945
946	out_id = id;
947}
948
949/* Program constants */
950const GLuint Program::m_invalid_id = 0;
951
952/** Constructor.
953 *
954 * @param context CTS context.
955 **/
956Program::Program(deqp::Context& context)
957	: m_id(m_invalid_id)
958	, m_compute(context)
959	, m_fragment(context)
960	, m_geometry(context)
961	, m_tess_ctrl(context)
962	, m_tess_eval(context)
963	, m_vertex(context)
964	, m_context(context)
965{
966	/* Nothing to be done here */
967}
968
969/** Destructor
970 *
971 **/
972Program::~Program()
973{
974	Release();
975}
976
977/** Initialize program instance
978 *
979 * @param compute_shader                Compute shader source code
980 * @param fragment_shader               Fragment shader source code
981 * @param geometry_shader               Geometry shader source code
982 * @param tesselation_control_shader    Tesselation control shader source code
983 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
984 * @param vertex_shader                 Vertex shader source code
985 **/
986void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
987				   const std::string& geometry_shader, const std::string& tesselation_control_shader,
988				   const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
989{
990	/* Delete previous program */
991	Release();
992
993	/* GL entry points */
994	const Functions& gl = m_context.getRenderContext().getFunctions();
995
996	/* Initialize shaders */
997	m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
998	m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
999	m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
1000	m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
1001	m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
1002	m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
1003
1004	/* Create program, set up transform feedback and attach shaders */
1005	Create(gl, m_id);
1006	Attach(gl, m_id, m_compute.m_id);
1007	Attach(gl, m_id, m_fragment.m_id);
1008	Attach(gl, m_id, m_geometry.m_id);
1009	Attach(gl, m_id, m_tess_ctrl.m_id);
1010	Attach(gl, m_id, m_tess_eval.m_id);
1011	Attach(gl, m_id, m_vertex.m_id);
1012
1013	/* Link program */
1014	Link(gl, m_id);
1015}
1016
1017/** Release program instance
1018 *
1019 **/
1020void Program::Release()
1021{
1022	const Functions& gl = m_context.getRenderContext().getFunctions();
1023
1024	if (m_invalid_id != m_id)
1025	{
1026		Use(gl, m_invalid_id);
1027
1028		gl.deleteProgram(m_id);
1029		m_id = m_invalid_id;
1030	}
1031
1032	m_compute.Release();
1033	m_fragment.Release();
1034	m_geometry.Release();
1035	m_tess_ctrl.Release();
1036	m_tess_eval.Release();
1037	m_vertex.Release();
1038}
1039
1040/** Attach shader to program
1041 *
1042 * @param gl         GL functions
1043 * @param program_id Id of program
1044 * @param shader_id  Id of shader
1045 **/
1046void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
1047{
1048	/* Sanity checks */
1049	if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
1050	{
1051		return;
1052	}
1053
1054	gl.attachShader(program_id, shader_id);
1055	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
1056}
1057
1058/** Create program instance
1059 *
1060 * @param gl     GL functions
1061 * @param out_id Id of program
1062 **/
1063void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
1064{
1065	const GLuint id = gl.createProgram();
1066	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
1067
1068	if (m_invalid_id == id)
1069	{
1070		TCU_FAIL("Failed to create program");
1071	}
1072
1073	out_id = id;
1074}
1075
1076/** Link program
1077 *
1078 * @param gl GL functions
1079 * @param id Id of program
1080 **/
1081void Program::Link(const glw::Functions& gl, glw::GLuint id)
1082{
1083	GLint status = GL_FALSE;
1084
1085	gl.linkProgram(id);
1086	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
1087
1088	/* Get link status */
1089	gl.getProgramiv(id, GL_LINK_STATUS, &status);
1090	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1091
1092	/* Log link error */
1093	if (GL_TRUE != status)
1094	{
1095		glw::GLint  length = 0;
1096		std::string message;
1097
1098		/* Get error log length */
1099		gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
1100		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1101
1102		message.resize(length, 0);
1103
1104		/* Get error log */
1105		gl.getProgramInfoLog(id, length, 0, &message[0]);
1106		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
1107
1108		TCU_FAIL(message.c_str());
1109	}
1110}
1111
1112/** Use program
1113 *
1114 * @param gl GL functions
1115 * @param id Id of program
1116 **/
1117void Program::Use(const glw::Functions& gl, glw::GLuint id)
1118{
1119	gl.useProgram(id);
1120	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1121}
1122
1123/* Shader's constants */
1124const GLuint Shader::m_invalid_id = 0;
1125
1126/** Constructor.
1127 *
1128 * @param context CTS context.
1129 **/
1130Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1131{
1132	/* Nothing to be done here */
1133}
1134
1135/** Destructor
1136 *
1137 **/
1138Shader::~Shader()
1139{
1140	Release();
1141}
1142
1143/** Initialize shader instance
1144 *
1145 * @param stage  Shader stage
1146 * @param source Source code
1147 **/
1148void Shader::Init(glw::GLenum stage, const std::string& source)
1149{
1150	if (true == source.empty())
1151	{
1152		/* No source == no shader */
1153		return;
1154	}
1155
1156	/* Delete any previous shader */
1157	Release();
1158
1159	/* Create, set source and compile */
1160	const Functions& gl = m_context.getRenderContext().getFunctions();
1161
1162	Create(gl, stage, m_id);
1163	Source(gl, m_id, source);
1164
1165	Compile(gl, m_id);
1166}
1167
1168/** Release shader instance
1169 *
1170 **/
1171void Shader::Release()
1172{
1173	if (m_invalid_id != m_id)
1174	{
1175		const Functions& gl = m_context.getRenderContext().getFunctions();
1176
1177		gl.deleteShader(m_id);
1178		m_id = m_invalid_id;
1179	}
1180}
1181
1182/** Compile shader
1183 *
1184 * @param gl GL functions
1185 * @param id Shader id
1186 **/
1187void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
1188{
1189	GLint status = GL_FALSE;
1190
1191	/* Compile */
1192	gl.compileShader(id);
1193	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
1194
1195	/* Get compilation status */
1196	gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
1197	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1198
1199	/* Log compilation error */
1200	if (GL_TRUE != status)
1201	{
1202		glw::GLint  length = 0;
1203		std::string message;
1204
1205		/* Error log length */
1206		gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
1207		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1208
1209		/* Prepare storage */
1210		message.resize(length, 0);
1211
1212		/* Get error log */
1213		gl.getShaderInfoLog(id, length, 0, &message[0]);
1214		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
1215
1216		TCU_FAIL(message.c_str());
1217	}
1218}
1219
1220/** Create shader
1221 *
1222 * @param gl     GL functions
1223 * @param stage  Shader stage
1224 * @param out_id Shader id
1225 **/
1226void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
1227{
1228	const GLuint id = gl.createShader(stage);
1229	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
1230
1231	if (m_invalid_id == id)
1232	{
1233		TCU_FAIL("Failed to create shader");
1234	}
1235
1236	out_id = id;
1237}
1238
1239/** Set shader's source code
1240 *
1241 * @param gl     GL functions
1242 * @param id     Shader id
1243 * @param source Shader source code
1244 **/
1245void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
1246{
1247	const GLchar* code = source.c_str();
1248
1249	gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
1250	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
1251}
1252
1253/* Texture static fields */
1254
1255FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
1256
1257/* Texture constants */
1258const GLuint Texture::m_invalid_id = -1;
1259
1260/** Constructor.
1261 *
1262 * @param context CTS context.
1263 **/
1264Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1265{
1266	/* Nothing to done here */
1267}
1268
1269/** Destructor
1270 *
1271 **/
1272Texture::~Texture()
1273{
1274	Release();
1275}
1276
1277/** Release texture instance
1278 *
1279 **/
1280void Texture::Release()
1281{
1282	if (m_invalid_id != m_id)
1283	{
1284		const Functions& gl = m_context.getRenderContext().getFunctions();
1285
1286		gl.deleteTextures(1, &m_id);
1287		m_id = m_invalid_id;
1288	}
1289}
1290
1291/** Loads entry points for direct state access extension
1292 *
1293 * @param context CTS context
1294 **/
1295void Texture::LoadExtDirectStateAccess(deqp::Context& context)
1296{
1297	FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
1298
1299	switch (support)
1300	{
1301	case FUNCTIONALITY_SUPPORT_NONE:
1302		/* Nothing to be done */
1303		break;
1304	case FUNCTIONALITY_SUPPORT_CORE:
1305	case FUNCTIONALITY_SUPPORT_EXTENSION:
1306		break;
1307	default:
1308		TCU_FAIL("Invalid enum");
1309		break;
1310	}
1311}
1312
1313/** Bind texture to target
1314 *
1315 * @param gl       GL functions
1316 * @param id       Id of texture
1317 * @param tex_type Type of texture
1318 **/
1319void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
1320{
1321	gl.bindTexture(target, id);
1322	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1323}
1324
1325/** Set contents of compressed texture
1326 *
1327 * @param gl              GL functions
1328 * @param target          Texture target
1329 * @param level           Mipmap level
1330 * @param internal_format Format of data
1331 * @param width           Width of texture
1332 * @param height          Height of texture
1333 * @param depth           Depth of texture
1334 * @param image_size      Size of data
1335 * @param data            Buffer with image data
1336 **/
1337void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
1338							  glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1339							  glw::GLsizei image_size, const glw::GLvoid* data)
1340{
1341	switch (target)
1342	{
1343	case GL_TEXTURE_1D:
1344		gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1345		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1346		break;
1347	case GL_TEXTURE_1D_ARRAY:
1348	case GL_TEXTURE_2D:
1349	case GL_TEXTURE_RECTANGLE:
1350		gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1351		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1352		break;
1353	case GL_TEXTURE_CUBE_MAP:
1354		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1355								image_size, data);
1356		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1357								image_size, data);
1358		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1359								image_size, data);
1360		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1361								image_size, data);
1362		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1363								image_size, data);
1364		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1365								image_size, data);
1366		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1367		break;
1368	case GL_TEXTURE_3D:
1369	case GL_TEXTURE_2D_ARRAY:
1370		gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1371		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1372		break;
1373	default:
1374		TCU_FAIL("Invliad enum");
1375		break;
1376	}
1377}
1378
1379/** Generate texture instance
1380 *
1381 * @param gl     GL functions
1382 * @param out_id Id of texture
1383 **/
1384void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1385{
1386	GLuint id = m_invalid_id;
1387
1388	gl.genTextures(1, &id);
1389	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1390
1391	if (m_invalid_id == id)
1392	{
1393		TCU_FAIL("Invalid id");
1394	}
1395
1396	out_id = id;
1397}
1398
1399/** Get texture data
1400 *
1401 * @param gl       GL functions
1402 * @param target   Texture target
1403 * @param format   Format of data
1404 * @param type     Type of data
1405 * @param out_data Buffer for data
1406 **/
1407void Texture::GetData(const glw::Functions& gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
1408					  glw::GLvoid* out_data)
1409{
1410	gl.getTexImage(target, 0 /* level */, format, type, out_data);
1411	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1412}
1413
1414/** Generate texture instance
1415 *
1416 * @param gl     GL functions
1417 * @param target Texture target
1418 * @param level  Mipmap level
1419 * @param pname  Parameter to query
1420 * @param param  Result of query
1421 **/
1422void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1423								glw::GLint* param)
1424{
1425	gl.getTexLevelParameteriv(target, level, pname, param);
1426	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1427}
1428
1429/** Set contents of texture
1430 *
1431 * @param gl              GL functions
1432 * @param target          Texture target
1433 * @param level           Mipmap level
1434 * @param internal_format Format of data
1435 * @param width           Width of texture
1436 * @param height          Height of texture
1437 * @param depth           Depth of texture
1438 * @param format          Format of data
1439 * @param type            Type of data
1440 * @param data            Buffer with image data
1441 **/
1442void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1443					glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1444					const glw::GLvoid* data)
1445{
1446	switch (target)
1447	{
1448	case GL_TEXTURE_1D:
1449		gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1450		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1451		break;
1452	case GL_TEXTURE_1D_ARRAY:
1453	case GL_TEXTURE_2D:
1454	case GL_TEXTURE_RECTANGLE:
1455		gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1456		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1457		break;
1458	case GL_TEXTURE_CUBE_MAP:
1459		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1460					  type, data);
1461		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1462					  type, data);
1463		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1464					  type, data);
1465		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1466					  type, data);
1467		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1468					  type, data);
1469		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1470					  type, data);
1471		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1472		break;
1473	case GL_TEXTURE_3D:
1474	case GL_TEXTURE_2D_ARRAY:
1475		gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1476		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1477		break;
1478	default:
1479		TCU_FAIL("Invliad enum");
1480		break;
1481	}
1482}
1483
1484/** Allocate storage for texture
1485 *
1486 * @param gl              GL functions
1487 * @param target          Texture target
1488 * @param levels          Number of levels
1489 * @param internal_format Internal format of texture
1490 * @param width           Width of texture
1491 * @param height          Height of texture
1492 * @param depth           Depth of texture
1493 **/
1494void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1495					  glw::GLuint width, glw::GLuint height, glw::GLuint depth)
1496{
1497	switch (target)
1498	{
1499	case GL_TEXTURE_1D:
1500		gl.texStorage1D(target, levels, internal_format, width);
1501		GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1502		break;
1503	case GL_TEXTURE_1D_ARRAY:
1504	case GL_TEXTURE_2D:
1505	case GL_TEXTURE_RECTANGLE:
1506	case GL_TEXTURE_CUBE_MAP:
1507		gl.texStorage2D(target, levels, internal_format, width, height);
1508		GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1509		break;
1510	case GL_TEXTURE_3D:
1511	case GL_TEXTURE_2D_ARRAY:
1512		gl.texStorage3D(target, levels, internal_format, width, height, depth);
1513		GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1514		break;
1515	default:
1516		TCU_FAIL("Invliad enum");
1517		break;
1518	}
1519}
1520
1521/** Set contents of texture
1522 *
1523 * @param gl              GL functions
1524 * @param target          Texture target
1525 * @param level           Mipmap level
1526 * @param x               X offset
1527 * @param y               Y offset
1528 * @param z               Z offset
1529 * @param width           Width of texture
1530 * @param height          Height of texture
1531 * @param depth           Depth of texture
1532 * @param format          Format of data
1533 * @param type            Type of data
1534 * @param pixels          Buffer with image data
1535 **/
1536void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1537					   glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1538					   glw::GLenum type, const glw::GLvoid* pixels)
1539{
1540	switch (target)
1541	{
1542	case GL_TEXTURE_1D:
1543		gl.texSubImage1D(target, level, x, width, format, type, pixels);
1544		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1545		break;
1546	case GL_TEXTURE_1D_ARRAY:
1547	case GL_TEXTURE_2D:
1548	case GL_TEXTURE_RECTANGLE:
1549		gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1550		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1551		break;
1552	case GL_TEXTURE_CUBE_MAP:
1553		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1554		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1555		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1556		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1557		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1558		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1559		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1560		break;
1561	case GL_TEXTURE_3D:
1562	case GL_TEXTURE_2D_ARRAY:
1563		gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1564		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1565		break;
1566	default:
1567		TCU_FAIL("Invliad enum");
1568		break;
1569	}
1570}
1571
1572/* VertexArray constants */
1573const GLuint VertexArray::m_invalid_id = -1;
1574
1575/** Constructor.
1576 *
1577 * @param context CTS context.
1578 **/
1579VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1580{
1581}
1582
1583/** Destructor
1584 *
1585 **/
1586VertexArray::~VertexArray()
1587{
1588	Release();
1589}
1590
1591/** Release vertex array object instance
1592 *
1593 **/
1594void VertexArray::Release()
1595{
1596	if (m_invalid_id != m_id)
1597	{
1598		const Functions& gl = m_context.getRenderContext().getFunctions();
1599
1600		Bind(gl, 0);
1601
1602		gl.deleteVertexArrays(1, &m_id);
1603
1604		m_id = m_invalid_id;
1605	}
1606}
1607
1608/** Binds Vertex array object
1609 *
1610 * @param gl GL functions
1611 * @param id ID of vertex array object
1612 **/
1613void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
1614{
1615	gl.bindVertexArray(id);
1616	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
1617}
1618
1619/** Generates Vertex array object
1620 *
1621 * @param gl     GL functions
1622 * @param out_id ID of vertex array object
1623 **/
1624void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1625{
1626	GLuint id = m_invalid_id;
1627
1628	gl.genVertexArrays(1, &id);
1629	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1630
1631	if (m_invalid_id == id)
1632	{
1633		TCU_FAIL("Invalid id");
1634	}
1635
1636	out_id = id;
1637}
1638
1639/** Constructor
1640 *
1641 * @param context Test context
1642 **/
1643ErrorsTest::ErrorsTest(deqp::Context& context)
1644	: TestCase(context, "errors", "Test if errors are generated as specified")
1645{
1646	/* Nothing to be done here */
1647}
1648
1649/** Execute test
1650 *
1651 * @return tcu::TestNode::STOP otherwise
1652 **/
1653tcu::TestNode::IterateResult ErrorsTest::iterate()
1654{
1655	const Functions& gl = m_context.getRenderContext().getFunctions();
1656
1657	bool test_result = true;
1658
1659	Buffer::LoadExtDirectStateAccess(m_context);
1660
1661	// No GL45 or GL_ARB_direct_state_access support
1662	if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
1663	{
1664		m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
1665		return tcu::TestNode::STOP;
1666	}
1667
1668	/*
1669	 * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to
1670	 * <target>; Check all targets;
1671	 */
1672	for (GLuint i = 0; i < Buffer::m_n_targets; ++i)
1673	{
1674		const GLenum target  = Buffer::m_targets[i];
1675		std::string  message = "BufferStorage was executed for id 0, target: ";
1676
1677		message.append(glu::getBufferTargetStr(target).toString().c_str());
1678
1679		Buffer::Bind(gl, 0 /* id */, target);
1680		gl.bufferStorage(target, 0 /* size */, 0 /* data */, GL_DYNAMIC_STORAGE_BIT /* flags */);
1681
1682		verifyError(GL_INVALID_OPERATION, message.c_str(), test_result);
1683	}
1684
1685	/*
1686	 * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and
1687	 * BufferData if buffer already have immutable store;
1688	 */
1689	{
1690		static const GLsizeiptr data_size = 32;
1691		static GLubyte			data[data_size];
1692
1693		Buffer buffer(m_context);
1694		buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1695
1696		/* NamedBufferStorage */
1697		if (0 != gl.namedBufferStorage)
1698		{
1699			gl.namedBufferStorage(buffer.m_id, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1700			verifyError(GL_INVALID_OPERATION, "NamedBufferStorage was executed for id with immutable storage",
1701						test_result);
1702		}
1703
1704		/* BufferStorage */
1705		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1706
1707		gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1708		verifyError(GL_INVALID_OPERATION, "BufferStorage was executed for target with immutable storage", test_result);
1709
1710		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1711	}
1712
1713	/*
1714	 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1715	 * <size> is less or equal to zero;
1716	 */
1717	{
1718		static const GLsizeiptr data_size = 32;
1719		static GLubyte			data[data_size];
1720
1721		Buffer buffer(m_context);
1722		gl.createBuffers(1, &buffer.m_id);
1723
1724		/* NamedBufferStorage */
1725		if (0 != gl.namedBufferStorage)
1726		{
1727			gl.namedBufferStorage(buffer.m_id, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1728			verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == 0", test_result);
1729
1730			gl.namedBufferStorage(buffer.m_id, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1731			verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == -16", test_result);
1732		}
1733
1734		/* BufferStorage */
1735		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1736
1737		gl.bufferStorage(GL_ARRAY_BUFFER, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1738		verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == 0", test_result);
1739
1740		gl.bufferStorage(GL_ARRAY_BUFFER, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1741		verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == -16", test_result);
1742
1743		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1744	}
1745
1746	/*
1747	 * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when
1748	 * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor
1749	 * MAP_WRITE_BIT;
1750	 */
1751	{
1752		static const GLsizeiptr data_size = 32;
1753		static GLubyte			data[data_size];
1754
1755		Buffer buffer(m_context);
1756		gl.createBuffers(1, &buffer.m_id);
1757
1758		/* NamedBufferStorage */
1759		if (0 != gl.namedBufferStorage)
1760		{
1761			gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_PERSISTENT_BIT);
1762			verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT",
1763						test_result);
1764		}
1765
1766		/* BufferStorage */
1767		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1768
1769		gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_PERSISTENT_BIT);
1770		verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", test_result);
1771
1772		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1773	}
1774
1775	/*
1776	 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1777	 * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT;
1778	 */
1779	{
1780		static const GLsizeiptr data_size = 32;
1781		static GLubyte			data[data_size];
1782
1783		Buffer buffer(m_context);
1784		gl.createBuffers(1, &buffer.m_id);
1785
1786		/* NamedBufferStorage */
1787		if (0 != gl.namedBufferStorage)
1788		{
1789			gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_COHERENT_BIT);
1790			verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_COHERENT_BIT",
1791						test_result);
1792		}
1793
1794		/* BufferStorage */
1795		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1796
1797		gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_COHERENT_BIT);
1798		verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_COHERENT_BIT", test_result);
1799
1800		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1801	}
1802
1803	/*
1804	 * - INVALID_OPERATION is generated by MapBufferRange if any of:
1805	 *   * MAP_COHERENT_BIT,
1806	 *   * MAP_PERSISTENT_BIT,
1807	 *   * MAP_READ_BIT,
1808	 *   * MAP_WRITE_BIT
1809	 * is included in <access> and not in buffer's storage flags;
1810	 */
1811	{
1812		static const GLsizeiptr data_size = 32;
1813		static GLubyte			data[data_size];
1814
1815		Buffer buffer(m_context);
1816		buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1817
1818		/* MapNamedBufferRange */
1819		if (0 != gl.mapNamedBufferRange)
1820		{
1821			gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1822			verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, "
1823											  "storage flags == GL_DYNAMIC_STORAGE_BIT",
1824						test_result);
1825
1826			gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1827			verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, "
1828											  "storage flags == GL_DYNAMIC_STORAGE_BIT",
1829						test_result);
1830
1831			gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1832			verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, "
1833											  "storage flags == GL_DYNAMIC_STORAGE_BIT",
1834						test_result);
1835
1836			gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1837			verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, "
1838											  "storage flags == GL_DYNAMIC_STORAGE_BIT",
1839						test_result);
1840		}
1841
1842		/* BufferStorage */
1843		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1844
1845		gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1846		verifyError(
1847			GL_INVALID_OPERATION,
1848			"MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1849			test_result);
1850
1851		gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1852		verifyError(
1853			GL_INVALID_OPERATION,
1854			"MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1855			test_result);
1856
1857		gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1858		verifyError(
1859			GL_INVALID_OPERATION,
1860			"MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1861			test_result);
1862
1863		gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1864		verifyError(
1865			GL_INVALID_OPERATION,
1866			"MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1867			test_result);
1868
1869		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1870	}
1871
1872	/*
1873	 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData
1874	 * when buffer has immutable store but its flags does not include
1875	 * DYNAMIC_STORAGE.
1876	 */
1877	{
1878		static const GLsizeiptr data_size = 32;
1879		static GLubyte			data[data_size];
1880
1881		Buffer buffer(m_context);
1882		buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size,
1883						   data);
1884
1885		/* NamedBufferSubData */
1886		if (0 != gl.namedBufferSubData)
1887		{
1888			gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data);
1889			verifyError(GL_INVALID_OPERATION,
1890						"NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result);
1891		}
1892
1893		/* BufferStorage */
1894		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1895
1896		gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data);
1897		verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT",
1898					test_result);
1899
1900		Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1901	}
1902
1903	/* Set result */
1904	if (true == test_result)
1905	{
1906		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1907	}
1908	else
1909	{
1910		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1911	}
1912
1913	/* Done */
1914	return tcu::TestNode::STOP;
1915}
1916
1917/** Verifies that expected error was generated
1918 *
1919 * @param expected_error  Expected error
1920 * @param error_message   Message that will be logged in case of wrong error
1921 * @param out_test_result Set to false if worng error was generated, not modified otherwise
1922 **/
1923void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result)
1924{
1925	const Functions& gl = m_context.getRenderContext().getFunctions();
1926
1927	const GLenum error = gl.getError();
1928
1929	if (error != expected_error)
1930	{
1931		out_test_result = false;
1932
1933		m_context.getTestContext().getLog()
1934			<< tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error)
1935			<< ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message
1936			<< tcu::TestLog::EndMessage;
1937	}
1938}
1939
1940/** Constructor
1941 *
1942 * @param context Test context
1943 **/
1944GetBufferParameterTest::GetBufferParameterTest(deqp::Context& context)
1945	: TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers")
1946{
1947	static const GLenum s_mapping_bits[] = { 0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT };
1948	static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]);
1949
1950	GLenum flags = 0;
1951
1952	for (GLuint dynamic = 0; dynamic < 2; ++dynamic)
1953	{
1954		flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT;
1955
1956		for (GLuint client = 0; client < 2; ++client)
1957		{
1958			flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT;
1959
1960			/* No "map" bits */
1961			if (0 != flags)
1962			{
1963				m_test_cases.push_back(testCase(flags, 0));
1964			}
1965
1966			for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx)
1967			{
1968				const GLenum flag_mapping_bits  = s_mapping_bits[flag_idx];
1969				const GLenum flags_with_mapping = flags | flag_mapping_bits;
1970
1971				for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx)
1972				{
1973					const GLenum access = s_mapping_bits[access_idx];
1974
1975					m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT));
1976					m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1977					m_test_cases.push_back(
1978						testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT));
1979					m_test_cases.push_back(
1980						testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1981					m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
1982													access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
1983				}
1984			}
1985		}
1986	}
1987}
1988
1989/** Execute test
1990 *
1991 * @return tcu::TestNode::STOP otherwise
1992 **/
1993tcu::TestNode::IterateResult GetBufferParameterTest::iterate()
1994{
1995	static const GLsizeiptr data_size = 32;
1996	static GLubyte			data[data_size];
1997
1998	Buffer::LoadExtDirectStateAccess(m_context);
1999
2000	// No GL45 or GL_ARB_direct_state_access support
2001	if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2002	{
2003		m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2004		return tcu::TestNode::STOP;
2005	}
2006
2007	const Functions& gl = m_context.getRenderContext().getFunctions();
2008
2009	bool test_result = true;
2010
2011	for (GLuint i = 0; i < m_test_cases.size(); ++i)
2012	{
2013		const testCase& test_case = m_test_cases[i];
2014		const GLenum	access	= test_case.m_access;
2015		const GLenum	flags	 = test_case.m_flags;
2016
2017		GLint queried_flags		= -1;
2018		GLint queried_immutable = -1;
2019		GLint queried_size		= -1;
2020
2021		Buffer buffer(m_context);
2022
2023		buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data);
2024		Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
2025
2026		if (0 != gl.getNamedBufferParameteriv)
2027		{
2028			Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2029			Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2030			Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size);
2031
2032			if (queried_flags != (GLint)flags)
2033			{
2034				test_result = false;
2035				m_context.getTestContext().getLog()
2036					<< tcu::TestLog::Message
2037					<< "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2038					<< " expected: " << flags << tcu::TestLog::EndMessage;
2039			}
2040		}
2041
2042		if (queried_flags != (GLint)flags)
2043		{
2044			test_result = false;
2045			m_context.getTestContext().getLog()
2046				<< tcu::TestLog::Message
2047				<< "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2048				<< " expected: " << flags << tcu::TestLog::EndMessage;
2049		}
2050
2051		if (queried_immutable != GL_TRUE)
2052		{
2053			test_result = false;
2054			m_context.getTestContext().getLog()
2055				<< tcu::TestLog::Message
2056				<< "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: "
2057				<< queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2058		}
2059
2060		if (queried_size != data_size)
2061		{
2062			test_result = false;
2063			m_context.getTestContext().getLog()
2064				<< tcu::TestLog::Message
2065				<< "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2066				<< " expected: " << data_size << tcu::TestLog::EndMessage;
2067		}
2068
2069		queried_flags	 = -1;
2070		queried_immutable = -1;
2071		queried_size	  = -1;
2072
2073		Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2074		Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2075		Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size);
2076
2077		if (queried_flags != (GLint)flags)
2078		{
2079			test_result = false;
2080			m_context.getTestContext().getLog()
2081				<< tcu::TestLog::Message
2082				<< "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2083				<< " expected: " << flags << tcu::TestLog::EndMessage;
2084		}
2085
2086		if (queried_immutable != GL_TRUE)
2087		{
2088			test_result = false;
2089			m_context.getTestContext().getLog()
2090				<< tcu::TestLog::Message
2091				<< "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable
2092				<< " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2093		}
2094
2095		if (queried_size != data_size)
2096		{
2097			test_result = false;
2098			m_context.getTestContext().getLog()
2099				<< tcu::TestLog::Message
2100				<< "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2101				<< " expected: " << data_size << tcu::TestLog::EndMessage;
2102		}
2103
2104		if (0 != access)
2105		{
2106			GLint queried_access = -1;
2107
2108			Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access));
2109
2110			if (0 != gl.getNamedBufferParameteriv)
2111			{
2112				Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2113			}
2114
2115			if (queried_access != (GLint)access)
2116			{
2117				test_result = false;
2118				m_context.getTestContext().getLog()
2119					<< tcu::TestLog::Message
2120					<< "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2121					<< " expected: " << access << tcu::TestLog::EndMessage;
2122			}
2123
2124			queried_access = -1;
2125
2126			Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2127
2128			if (queried_access != (GLint)access)
2129			{
2130				test_result = false;
2131				m_context.getTestContext().getLog()
2132					<< tcu::TestLog::Message
2133					<< "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2134					<< " expected: " << access << tcu::TestLog::EndMessage;
2135			}
2136		}
2137
2138		Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER);
2139	}
2140
2141	/* Set result */
2142	if (true == test_result)
2143	{
2144		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2145	}
2146	else
2147	{
2148		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2149	}
2150
2151	/* Done */
2152	return tcu::TestNode::STOP;
2153}
2154
2155/** Constructor
2156 *
2157 * @param context Test context
2158 **/
2159GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access)
2160{
2161}
2162
2163/** Constructor
2164 *
2165 * @param context Test context
2166 **/
2167DynamicStorageTest::DynamicStorageTest(deqp::Context& context)
2168	: TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected")
2169{
2170	/* Nothing to be done here */
2171}
2172
2173/** Execute test
2174 *
2175 * @return tcu::TestNode::STOP otherwise
2176 **/
2177tcu::TestNode::IterateResult DynamicStorageTest::iterate()
2178{
2179	static const size_t data_size = 64;
2180
2181	const Functions& gl = m_context.getRenderContext().getFunctions();
2182
2183	bool test_result = true;
2184
2185	/*
2186	 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to
2187	 * COPY_READ_BUFFER;
2188	 * - prepare 64 bytes immutable buffer filled with value 2; Do not set
2189	 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER;
2190	 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2191	 * filled with value 3; INVLIAD_OPERATION error should be generated;
2192	 * - inspect contents of buffer to verify it is filled with 2;
2193	 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to
2194	 * COPY_WRITE_BUFFER; No error should be generated;
2195	 * - inspect contents of buffer to verify it is filled with 1;
2196	 */
2197	{
2198		/* Prepare buffers */
2199		GLubyte read_data[data_size];
2200		GLubyte temp_data[data_size];
2201		GLubyte update_data[data_size];
2202		GLubyte write_data[data_size];
2203
2204		for (size_t i = 0; i < data_size; ++i)
2205		{
2206			read_data[i]   = 1;
2207			temp_data[i]   = 0;
2208			update_data[i] = 3;
2209			write_data[i]  = 2;
2210		}
2211
2212		Buffer read_buffer(m_context);
2213		Buffer write_buffer(m_context);
2214
2215		read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data);
2216		write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data);
2217
2218		/* Check bufferSubData */
2219		write_buffer.Bind();
2220		gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2221
2222		GLenum error = gl.getError();
2223		if (GL_INVALID_OPERATION != error)
2224		{
2225			test_result = false;
2226
2227			m_context.getTestContext().getLog()
2228				<< tcu::TestLog::Message << "Invalid error was generated. BufferSubData was executed on store without "
2229											"DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: "
2230				<< glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2231		}
2232
2233		Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2234
2235		if (0 != memcmp(temp_data, write_data, data_size))
2236		{
2237			test_result = false;
2238
2239			m_context.getTestContext().getLog()
2240				<< tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT."
2241				<< tcu::TestLog::EndMessage;
2242		}
2243
2244		/* Check copyBufferSubData */
2245		read_buffer.Bind();
2246		gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */,
2247							 data_size);
2248		GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData");
2249
2250		Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2251
2252		if (0 != memcmp(temp_data, read_data, data_size))
2253		{
2254			test_result = false;
2255
2256			m_context.getTestContext().getLog() << tcu::TestLog::Message
2257												<< "CopyBufferSubData stored invalid contents in write target buffer."
2258												<< tcu::TestLog::EndMessage;
2259		}
2260	}
2261
2262	/*
2263	 * - delete buffer and create new one; This time <flags> should contain
2264	 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER;
2265	 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2266	 * filled with value 3; No error should be generated;
2267	 * - inspect contents of buffer to verify it is filled with 3;
2268	 */
2269	{
2270		/* Prepare buffers */
2271		GLubyte temp_data[data_size];
2272		GLubyte update_data[data_size];
2273		GLubyte write_data[data_size];
2274
2275		for (size_t i = 0; i < data_size; ++i)
2276		{
2277			temp_data[i]   = 0;
2278			update_data[i] = 3;
2279			write_data[i]  = 2;
2280		}
2281
2282		Buffer write_buffer(m_context);
2283
2284		write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data);
2285
2286		/* Check bufferSubData */
2287		write_buffer.Bind();
2288		gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2289		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
2290
2291		Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2292
2293		if (0 != memcmp(temp_data, update_data, data_size))
2294		{
2295			test_result = false;
2296
2297			m_context.getTestContext().getLog() << tcu::TestLog::Message
2298												<< "BufferSubData stored invalid contents in write target buffer."
2299												<< tcu::TestLog::EndMessage;
2300		}
2301	}
2302
2303	/* Set result */
2304	if (true == test_result)
2305	{
2306		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2307	}
2308	else
2309	{
2310		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2311	}
2312
2313	/* Done */
2314	return tcu::TestNode::STOP;
2315}
2316
2317/** Constructor
2318 *
2319 * @param context Test context
2320 **/
2321MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context& context)
2322	: TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer")
2323{
2324	/* Nothing to be done here */
2325}
2326
2327/** Execute test
2328 *
2329 * @return tcu::TestNode::STOP otherwise
2330 **/
2331tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate()
2332{
2333	static const size_t		data_size			 = 64;
2334	static const GLintptr   mapped_region_offset = 16;
2335	static const GLsizeiptr mapped_region_size   = 16;
2336	static const testCase   test_cases[]		 = {
2337		{ 0, 16, false },  /* before mapped region */
2338		{ 32, 16, false }, /* after mapped region  */
2339		{ 8, 16, true },   /* at the beginning     */
2340		{ 24, 16, true },  /* at the end           */
2341		{ 12, 8, true },   /* in the middle        */
2342	};
2343	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
2344
2345	const Functions& gl = m_context.getRenderContext().getFunctions();
2346
2347	bool test_result = true;
2348
2349	/* Storage for data */
2350	GLubyte incrementing_data[data_size];
2351
2352	/* Prepare data */
2353	for (size_t i = 0; i < data_size; ++i)
2354	{
2355		incrementing_data[i] = (glw::GLubyte)i;
2356	}
2357
2358	/* Load DSA */
2359	Buffer::LoadExtDirectStateAccess(m_context);
2360
2361	// No GL45 or GL_ARB_direct_state_access support
2362	if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2363	{
2364		m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2365		return tcu::TestNode::STOP;
2366	}
2367
2368	/* Prepare buffer */
2369	Buffer buffer(m_context);
2370	buffer.InitStorage(GL_ARRAY_BUFFER,
2371					   GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2372					   0 /* data */);
2373	buffer.Bind();
2374
2375	/*
2376	 * - execute tested operation, to update whole buffer with incrementing values
2377	 * starting from 0; No error should be generated;
2378	 */
2379	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data);
2380	GLenum error = gl.getError();
2381
2382	if (GL_NO_ERROR != error)
2383	{
2384		test_result = false;
2385
2386		m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: "
2387											<< glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2388	}
2389
2390	if (0 != gl.namedBufferSubData)
2391	{
2392		gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2393		error = gl.getError();
2394	}
2395
2396	gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2397	error = gl.getError();
2398
2399	if (GL_NO_ERROR != error)
2400	{
2401		test_result = false;
2402
2403		m_context.getTestContext().getLog()
2404			<< tcu::TestLog::Message
2405			<< "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2406			<< tcu::TestLog::EndMessage;
2407	}
2408
2409	/*
2410	 * - map buffer contents with MapBufferRange; <access> should contain
2411	 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset>
2412	 * and <size>;
2413	 * - mapped region should contain values from 16 to 31;
2414	 * - execute tested operation, to update portions of buffer specified below;
2415	 * No error should be generated;
2416	 */
2417	{
2418		const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size,
2419												   GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2420
2421		if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size))
2422		{
2423			test_result = false;
2424
2425			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Mapped region contains unexpected data"
2426												<< tcu::TestLog::EndMessage;
2427		}
2428
2429		for (size_t i = 0; i < n_test_cases; ++i)
2430		{
2431			const GLintptr   offset = test_cases[i].m_offset;
2432			const GLsizeiptr size   = test_cases[i].m_size;
2433
2434			gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2435			error = gl.getError();
2436
2437			if (GL_NO_ERROR != error)
2438			{
2439				test_result = false;
2440
2441				m_context.getTestContext().getLog()
2442					<< tcu::TestLog::Message
2443					<< "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2444					<< tcu::TestLog::EndMessage;
2445			}
2446
2447			if (0 != gl.namedBufferSubData)
2448			{
2449				gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2450				error = gl.getError();
2451			}
2452
2453			if (GL_NO_ERROR != error)
2454			{
2455				test_result = false;
2456
2457				m_context.getTestContext().getLog()
2458					<< tcu::TestLog::Message
2459					<< "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2460					<< tcu::TestLog::EndMessage;
2461			}
2462		}
2463	}
2464
2465	/*
2466	 * - unmap buffer;
2467	 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2468	 * - execute tested operation to update regions specified below; It is expected
2469	 * that INVALID_OPERATION will be generated for cases that cross mapped region;
2470	 * No error should be generated for other cases.
2471	 */
2472	{
2473		Buffer::MapOwner tmp(
2474			buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2475
2476		for (size_t i = 0; i < n_test_cases; ++i)
2477		{
2478			const GLintptr   offset			   = test_cases[i].m_offset;
2479			const GLsizeiptr size			   = test_cases[i].m_size;
2480			const bool		 is_error_expected = test_cases[i].m_cross_mapped_region;
2481			const GLenum	 expected_error	= (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR;
2482
2483			gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2484			error = gl.getError();
2485
2486			if (expected_error != error)
2487			{
2488				test_result = false;
2489
2490				m_context.getTestContext().getLog()
2491					<< tcu::TestLog::Message
2492					<< "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2493					<< ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2494					<< ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2495					<< ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2496			}
2497
2498			if (0 != gl.namedBufferSubData)
2499			{
2500				gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2501				error = gl.getError();
2502			}
2503
2504			if (expected_error != error)
2505			{
2506				test_result = false;
2507
2508				m_context.getTestContext().getLog()
2509					<< tcu::TestLog::Message
2510					<< "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2511					<< ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2512					<< ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2513					<< ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2514			}
2515		}
2516	}
2517
2518	/* Set result */
2519	if (true == test_result)
2520	{
2521		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2522	}
2523	else
2524	{
2525		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2526	}
2527
2528	/* Done */
2529	return tcu::TestNode::STOP;
2530}
2531
2532/** Constructor
2533 *
2534 * @param context Test context
2535 **/
2536MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context& context)
2537	: TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer")
2538	, m_compressed_image_size(0)
2539	, m_compressed_internal_format(0)
2540{
2541	/* Nothing to be done here */
2542}
2543
2544/** Execute test
2545 *
2546 * @return tcu::TestNode::STOP otherwise
2547 **/
2548tcu::TestNode::IterateResult MapPersistentTextureTest::iterate()
2549{
2550	static const size_t data_size = 256;
2551
2552	const Functions& gl = m_context.getRenderContext().getFunctions();
2553
2554	bool test_result = true;
2555
2556	/* Storage for data */
2557	GLubyte data[data_size];
2558
2559	/* Prepare data */
2560	for (size_t i = 0; i < data_size; ++i)
2561	{
2562		data[i] = (glw::GLubyte)i;
2563	}
2564
2565	/* Load DSA */
2566	Buffer::LoadExtDirectStateAccess(m_context);
2567	Texture::LoadExtDirectStateAccess(m_context);
2568
2569	/* Get info about compressed image */
2570	getCompressedInfo();
2571
2572	/* Prepare buffer */
2573	Buffer buffer(m_context);
2574	buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2575					   data);
2576	Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2577
2578	/*
2579	 * - prepare texture in a way that is relevant for tested operation;
2580	 * - execute tested operation, no error should be generated;
2581	 * - delete texture and prepare next one;
2582	 */
2583	for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2584	{
2585		const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2586
2587		bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2588
2589		if (false == result)
2590		{
2591			test_result = false;
2592
2593			m_context.getTestContext().getLog() << tcu::TestLog::Message
2594												<< "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped"
2595												<< tcu::TestLog::EndMessage;
2596		}
2597	}
2598
2599	/*
2600	 * - map buffer contents with MapBufferRange, <access> should contain
2601	 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2602	 * - execute tested operation, no error should be generated;
2603	 */
2604	for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2605	{
2606		const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2607
2608		{
2609			Buffer::MapOwner tmp(
2610				buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2611		}
2612		Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2613
2614		bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2615
2616		if (false == result)
2617		{
2618			test_result = false;
2619
2620			m_context.getTestContext().getLog() << tcu::TestLog::Message
2621												<< "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped"
2622												<< tcu::TestLog::EndMessage;
2623		}
2624	}
2625
2626	/* Set result */
2627	if (true == test_result)
2628	{
2629		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2630	}
2631	else
2632	{
2633		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2634	}
2635
2636	/* Done */
2637	return tcu::TestNode::STOP;
2638}
2639
2640/** Return name of operation
2641 *
2642 * @param operation Operation which name will be returned
2643 *
2644 * @return Name of operation or 0 in case of invalid enum
2645 **/
2646const char* MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation)
2647{
2648	const char* name = 0;
2649
2650	switch (operation)
2651	{
2652	case OP_COMPRESSED_TEX_IMAGE:
2653		name = "CompressedTexImage";
2654		break;
2655	case OP_COMPRESSED_TEX_SUB_IMAGE:
2656		name = "CompressedTexSubImage";
2657		break;
2658	case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2659		name = "CompressedTextureSubImage";
2660		break;
2661	case OP_TEX_IMAGE:
2662		name = "TexImage";
2663		break;
2664	case OP_TEX_SUB_IMAGE:
2665		name = "TexSubImage";
2666		break;
2667	default:
2668		TCU_FAIL("Invalid enum");
2669	}
2670
2671	return name;
2672}
2673
2674/** Check format and size of compressed image
2675 *
2676 **/
2677void MapPersistentTextureTest::getCompressedInfo()
2678{
2679	const Functions& gl = m_context.getRenderContext().getFunctions();
2680
2681	/* Texture creation */
2682	Texture texture(m_context);
2683	Texture::Generate(gl, texture.m_id);
2684	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2685	Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE,
2686				   0); // glspec 4.5 pg 216
2687
2688	/* Queries */
2689	Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
2690							   &m_compressed_image_size);
2691	Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT,
2692							   &m_compressed_internal_format);
2693}
2694
2695/** Verifies results of tested operation
2696 *
2697 * @param operation      Operation to be tested
2698 * @param buffer         Buffer that will be used as GL_PIXEL_UNPACK_BUFFER
2699 * @param expected_error Expected error
2700 *
2701 * @return false in case of any error, true otherwise
2702 **/
2703bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer,
2704													 glw::GLenum expected_error)
2705{
2706	const Functions& gl = m_context.getRenderContext().getFunctions();
2707
2708	bool result = true;
2709
2710	GLenum  error = GL_NO_ERROR;
2711	Texture texture(m_context);
2712
2713	/* Prepare texture */
2714	Texture::Generate(gl, texture.m_id);
2715	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2716
2717	switch (operation)
2718	{
2719	case OP_COMPRESSED_TEX_IMAGE:
2720	case OP_TEX_IMAGE:
2721		break;
2722	case OP_COMPRESSED_TEX_SUB_IMAGE:
2723	case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2724		Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2725								 8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */,
2726								 0 /* empty image */);
2727		break;
2728	case OP_TEX_SUB_IMAGE:
2729		Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED,
2730					   GL_UNSIGNED_BYTE, 0 /* empty image */);
2731		break;
2732	default:
2733		TCU_FAIL("Invalid enum");
2734	}
2735
2736	/* Bind buffer to PIXEL_UNPACK */
2737	Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER);
2738
2739	/* Execute operation */
2740	switch (operation)
2741	{
2742	case OP_COMPRESSED_TEX_IMAGE:
2743		gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2744								8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */,
2745								0 /* offset to pixel unpack buffer */);
2746		error = gl.getError();
2747		break;
2748	case OP_COMPRESSED_TEX_SUB_IMAGE:
2749		gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */,
2750								   m_compressed_internal_format, m_compressed_image_size,
2751								   0 /* offset to pixel unpack buffer */);
2752		error = gl.getError();
2753		break;
2754	case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2755		if (0 != gl.compressedTextureSubImage2D)
2756		{
2757			gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */,
2758										   8 /* height */, m_compressed_internal_format, m_compressed_image_size,
2759										   0 /* offset to pixel unpack buffer */);
2760			error = gl.getError();
2761		}
2762		else
2763		{
2764			/* Not supported, ignore */
2765			error = expected_error;
2766		}
2767		break;
2768	case OP_TEX_IMAGE:
2769		gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED,
2770					  GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2771		error = gl.getError();
2772		break;
2773	case OP_TEX_SUB_IMAGE:
2774		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED,
2775						 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2776		error = gl.getError();
2777		break;
2778	default:
2779		TCU_FAIL("Invalid enum");
2780	}
2781
2782	/* Unbind buffer */
2783	Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2784
2785	/* Check result */
2786	if (expected_error != error)
2787	{
2788		result = false;
2789
2790		m_context.getTestContext().getLog() << tcu::TestLog::Message << getOperationName(operation)
2791											<< " generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2792											<< ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2793											<< tcu::TestLog::EndMessage;
2794	}
2795
2796	/* Done */
2797	return result;
2798}
2799
2800/** Constructor
2801 *
2802 * @param context Test context
2803 **/
2804MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context& context)
2805	: TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer")
2806{
2807	/* Nothing to be done here */
2808}
2809
2810/** Execute test
2811 *
2812 * @return tcu::TestNode::STOP otherwise
2813 **/
2814tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate()
2815{
2816	static const GLuint height	= 8;
2817	static const GLuint width	 = 8;
2818	static const size_t data_size = width * height;
2819
2820	const Functions& gl = m_context.getRenderContext().getFunctions();
2821
2822	bool test_result = true;
2823
2824	/* Prepare data */
2825	GLubyte initial_texture_data[data_size];
2826	GLubyte updated_texture_data[data_size];
2827
2828	for (size_t i = 0; i < data_size; ++i)
2829	{
2830		initial_texture_data[i] = (glw::GLubyte)i;
2831		updated_texture_data[i] = (glw::GLubyte)(data_size - i);
2832	}
2833
2834	/* Prepare GL objects */
2835	Buffer		buffer(m_context);
2836	Framebuffer framebuffer(m_context);
2837	Texture		texture(m_context);
2838
2839	buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2840					   0 /* data */);
2841
2842	Texture::Generate(gl, texture.m_id);
2843	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2844	Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */);
2845	Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
2846					  GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data);
2847
2848	Framebuffer::Generate(gl, framebuffer.m_id);
2849	Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id);
2850	Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
2851
2852	/*
2853	 * - execute ReadPixels to transfer texture contents to buffer, no error should
2854	 * be generated;
2855	 */
2856	buffer.Bind();
2857	gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2858				  0 /* offset in PIXEL_PACK_BUFFER */);
2859	GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer");
2860
2861	/*
2862	 * - update contents of texture with different image;
2863	 * - map buffer contents with MapBufferRange, <access> should contain
2864	 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2865	 * - execute ReadPixels to transfer texture contents to buffer, no error should
2866	 * be generated;
2867	 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish;
2868	 * - inspect contents of mapped buffer, to verify that latest data transfer was
2869	 * successful;
2870	 * - unmap buffer
2871	 */
2872	{
2873		Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
2874						  0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data);
2875
2876		const Buffer::MapOwner map(
2877			buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2878
2879		buffer.Bind();
2880		gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2881					  0 /* offset in PIXEL_PACK_BUFFER */);
2882		GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer");
2883
2884		gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
2885		GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2886
2887		gl.finish();
2888		GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
2889
2890		if (0 != memcmp(updated_texture_data, map.m_data, data_size))
2891		{
2892			test_result = false;
2893
2894			m_context.getTestContext().getLog()
2895				<< tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels"
2896				<< tcu::TestLog::EndMessage;
2897		}
2898	}
2899
2900	/*
2901	 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2902	 * - execute ReadPixels to transfer texture contents to buffer,
2903	 * INVALID_OPERATION error should be generated.
2904	 */
2905	{
2906		Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2907
2908		buffer.Bind();
2909		gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2910					  0 /* offset in PIXEL_PACK_BUFFER */);
2911		GLenum error = gl.getError();
2912
2913		if (GL_INVALID_OPERATION != error)
2914		{
2915			test_result = false;
2916
2917			m_context.getTestContext().getLog()
2918				<< tcu::TestLog::Message << "Wrong error was generated by ReadPixels. Expected INVALID_OPERATION as "
2919											"PIXEL_PACK buffer is mapped. Got: "
2920				<< glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2921		}
2922	}
2923
2924	/* Set result */
2925	if (true == test_result)
2926	{
2927		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2928	}
2929	else
2930	{
2931		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2932	}
2933
2934	/* Done */
2935	return tcu::TestNode::STOP;
2936}
2937
2938/** Constructor
2939 *
2940 * @param context Test context
2941 **/
2942MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context)
2943	: TestCase(context, "map_persistent_dispatch", "test dispatch operation against mapped buffer")
2944{
2945	/* Nothing to be done here */
2946}
2947
2948/** Constructor
2949 *
2950 * @param context          Test context
2951 * @param test_name        Test name
2952 * @param test_description Test description
2953 **/
2954MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context, const GLchar* test_name,
2955													 const GLchar* test_description)
2956	: TestCase(context, test_name, test_description)
2957{
2958	/* Nothing to be done here */
2959}
2960
2961/** Execute test
2962 *
2963 * @return tcu::TestNode::STOP otherwise
2964 **/
2965tcu::TestNode::IterateResult MapPersistentDispatchTest::iterate()
2966{
2967	static const GLchar* compute_shader = "#version 430 core\n"
2968										  "\n"
2969										  "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2970										  "\n"
2971										  "layout (binding = 0, std430) buffer DestinationData {\n"
2972										  "    uint values[];\n"
2973										  "} destination;\n"
2974										  "\n"
2975										  "layout (binding = 1, std430) buffer SourceData {\n"
2976										  "    uint values[];\n"
2977										  "} source;\n"
2978										  "\n"
2979										  "void main()\n"
2980										  "{\n"
2981										  "    uint index = gl_GlobalInvocationID.x;\n"
2982										  "    uint sum   = 0u;\n"
2983										  "\n"
2984										  "    for (uint i = 0u; i <= index; ++i)\n"
2985										  "    {\n"
2986										  "        sum += source.values[i];\n"
2987										  "    }\n"
2988										  "\n"
2989										  "    destination.values[index] = sum;\n"
2990										  "}\n"
2991										  "\n";
2992	static const GLuint data_size			= 16;
2993	static const GLuint destination_binding = 0;
2994	static const GLuint source_binding		= 1;
2995
2996	const Functions& gl = m_context.getRenderContext().getFunctions();
2997
2998	bool test_result = true;
2999
3000	/* Prepare data */
3001	GLuint destination_data[data_size];
3002	GLuint modified_source_data[data_size];
3003	GLuint modified_sum_data[data_size];
3004	GLuint source_data[data_size];
3005	GLuint sum_data[data_size];
3006
3007	GLuint modified_sum = 0;
3008	GLuint sum			= 0;
3009
3010	for (GLuint i = 0; i < data_size; ++i)
3011	{
3012		destination_data[i]		= 0;
3013		modified_source_data[i] = data_size - i;
3014		source_data[i]			= i;
3015
3016		modified_sum += modified_source_data[i];
3017		sum += source_data[i];
3018
3019		modified_sum_data[i] = modified_sum;
3020		sum_data[i]			 = sum;
3021	}
3022
3023	/* Prepare buffers */
3024	Buffer destination(m_context);
3025	Buffer source(m_context);
3026
3027	destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3028							data_size * sizeof(GLuint), destination_data);
3029
3030	source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3031					   data_size * sizeof(GLuint), source_data);
3032
3033	/* Prepare program */
3034	Program program(m_context);
3035	program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3036
3037	/*
3038	 * - bind buffers to SHADER_STORAGE_BUFFER;
3039	 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3040	 *   * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3041	 *   * MAP_WRITE_BIT flag shall be set for source;
3042	 *   * MAP_READ_BIT flag shall be set for destination;
3043	 * - dispatch program for 16x1x1 groups;
3044	 * - modify contents of source buffer via mapped memory;
3045	 * - execute Finish;
3046	 * - inspect contents of destination buffer via mapped memory; It is expected
3047	 * that it will contain results based on original content of source buffer;
3048	 * - dispatch program for 16x1x1 groups;
3049	 * - execute Finish;
3050	 * - inspect contents of destination buffer via mapped memory; It is expected
3051	 * that it will contain results based on modified content of source buffer.
3052	 */
3053	{
3054		/* Set program */
3055		Program::Use(gl, program.m_id);
3056
3057		/* Map buffers */
3058		destination.Bind();
3059		const Buffer::MapOwner destination_map(destination.MapRange(
3060			0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3061
3062		source.Bind();
3063		const Buffer::MapOwner source_map(
3064			source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3065							GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3066
3067		/* Clear binding point */
3068		Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3069
3070		/* Bind buffers */
3071		Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3072		Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3073
3074		/* Execute program for 16x1x1 groups */
3075		gl.dispatchCompute(16, 1, 1);
3076		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3077
3078		/* Make sure that program executed */
3079		gl.finish();
3080		GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3081
3082		if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3083		{
3084			test_result = false;
3085
3086			m_context.getTestContext().getLog() << tcu::TestLog::Message
3087												<< "Contents of mapped region does not correspond with expected results"
3088												<< tcu::TestLog::EndMessage;
3089		}
3090
3091		/* Modify source buffer via mapped area */
3092		memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3093
3094		/* Execute program for 16x1x1 groups */
3095		gl.dispatchCompute(16, 1, 1);
3096		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3097
3098		/* Make sure that program executed */
3099		gl.finish();
3100		GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3101
3102		if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3103		{
3104			test_result = false;
3105
3106			m_context.getTestContext().getLog() << tcu::TestLog::Message
3107												<< "Contents of mapped region does not correspond with expected results"
3108												<< tcu::TestLog::EndMessage;
3109		}
3110	}
3111
3112	/* Set result */
3113	if (true == test_result)
3114	{
3115		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3116	}
3117	else
3118	{
3119		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3120	}
3121
3122	/* Done */
3123	return tcu::TestNode::STOP;
3124}
3125
3126/** Constructor
3127 *
3128 * @param context Test context
3129 **/
3130MapPersistentFlushTest::MapPersistentFlushTest(deqp::Context& context)
3131	: TestCase(context, "map_persistent_flush", "Test mapped buffer against flushing")
3132{
3133	/* Nothing to be done here */
3134}
3135
3136/** Execute test
3137 *
3138 * @return tcu::TestNode::STOP otherwise
3139 **/
3140tcu::TestNode::IterateResult MapPersistentFlushTest::iterate()
3141{
3142	static const GLchar* compute_shader = "#version 430 core\n"
3143										  "\n"
3144										  "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3145										  "\n"
3146										  "layout (binding = 0, std430) buffer DestinationData {\n"
3147										  "    uint values[];\n"
3148										  "} destination;\n"
3149										  "\n"
3150										  "layout (binding = 1, std430) buffer SourceData {\n"
3151										  "    uint values[];\n"
3152										  "} source;\n"
3153										  "\n"
3154										  "void main()\n"
3155										  "{\n"
3156										  "    uint index = gl_GlobalInvocationID.x;\n"
3157										  "    uint sum   = 0u;\n"
3158										  "\n"
3159										  "    for (uint i = 0u; i <= index; ++i)\n"
3160										  "    {\n"
3161										  "        sum += source.values[i];\n"
3162										  "    }\n"
3163										  "\n"
3164										  "    destination.values[index] = sum;\n"
3165										  "}\n"
3166										  "\n";
3167	static const GLuint data_size			= 16;
3168	static const GLuint destination_binding = 0;
3169	static const GLuint source_binding		= 1;
3170
3171	const Functions& gl = m_context.getRenderContext().getFunctions();
3172
3173	bool test_result = true;
3174
3175	/* Prepare data */
3176	GLuint destination_data[data_size];
3177	GLuint modified_source_data[data_size];
3178	GLuint modified_sum_data[data_size];
3179	GLuint source_data[data_size];
3180	GLuint sum_data[data_size];
3181
3182	GLuint modified_sum = 0;
3183	GLuint sum			= 0;
3184
3185	for (GLuint i = 0; i < data_size; ++i)
3186	{
3187		destination_data[i]		= 0;
3188		modified_source_data[i] = data_size - i;
3189		source_data[i]			= i;
3190
3191		modified_sum += modified_source_data[i];
3192		sum += source_data[i];
3193
3194		modified_sum_data[i] = modified_sum;
3195		sum_data[i]			 = sum;
3196	}
3197
3198	/* Prepare buffers */
3199	Buffer destination(m_context);
3200	Buffer source(m_context);
3201
3202	destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3203							data_size * sizeof(GLuint), destination_data);
3204
3205	source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3206					   data_size * sizeof(GLuint), source_data);
3207
3208	/* Prepare program */
3209	Program program(m_context);
3210	program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3211
3212	/*
3213	 * - bind buffers to SHADER_STORAGE_BUFFER;
3214	 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3215	 *   * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3216	 *   * MAP_WRITE_BIT flag shall be set for source;
3217	 *   * MAP_READ_BIT flag shall be set for destination;
3218	 * - dispatch program for 16x1x1 groups;
3219	 * - modify contents of source buffer via mapped memory;
3220	 * - execute Finish;
3221	 * - inspect contents of destination buffer via mapped memory; It is expected
3222	 * that it will contain results based on original content of source buffer;
3223	 * - dispatch program for 16x1x1 groups;
3224	 * - execute Finish;
3225	 * - inspect contents of destination buffer via mapped memory; It is expected
3226	 * that it will contain results based on modified content of source buffer.
3227	 */
3228	{
3229		/* Set program */
3230		Program::Use(gl, program.m_id);
3231
3232		/* Map buffers */
3233		destination.Bind();
3234		const Buffer::MapOwner destination_map(destination.MapRange(
3235			0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3236
3237		source.Bind();
3238		const Buffer::MapOwner source_map(
3239			source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3240							GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3241
3242		/* Clear binding point */
3243		Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3244
3245		/* Bind buffers */
3246		Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3247		Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3248
3249		/* Execute program for 16x1x1 groups */
3250		gl.dispatchCompute(16, 1, 1);
3251		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3252
3253		/* Make sure that program executed */
3254		gl.finish();
3255		GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3256
3257		if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3258		{
3259			test_result = false;
3260
3261			m_context.getTestContext().getLog() << tcu::TestLog::Message
3262												<< "Contents of mapped region does not correspond with expected results"
3263												<< tcu::TestLog::EndMessage;
3264		}
3265
3266		/* Modify source buffer via mapped area */
3267		memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3268
3269		/*
3270		 * - apply FlushMappedBufferRange to ensure that modifications of source buffer
3271		 * are visible to server.
3272		 */
3273		source.Bind();
3274		gl.flushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /* offset */, data_size * sizeof(GLuint));
3275		GLU_EXPECT_NO_ERROR(gl.getError(), "FlushMappedBufferRange");
3276
3277		/* Clear binding point */
3278		Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3279
3280		/* Execute program for 16x1x1 groups */
3281		gl.dispatchCompute(16, 1, 1);
3282		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3283
3284		/* Make sure that program executed */
3285		gl.finish();
3286		GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3287
3288		if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3289		{
3290			test_result = false;
3291
3292			m_context.getTestContext().getLog() << tcu::TestLog::Message
3293												<< "Contents of mapped region does not correspond with expected results"
3294												<< tcu::TestLog::EndMessage;
3295		}
3296	}
3297
3298	/* Set result */
3299	if (true == test_result)
3300	{
3301		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3302	}
3303	else
3304	{
3305		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3306	}
3307
3308	/* Done */
3309	return tcu::TestNode::STOP;
3310}
3311
3312/** Constructor
3313 *
3314 * @param context Test context
3315 **/
3316MapPersistentDrawTest::MapPersistentDrawTest(deqp::Context& context)
3317	: TestCase(context, "map_persistent_draw", "Test draw operation against mapped buffer")
3318{
3319	/* Nothing to be done here */
3320}
3321
3322/** Execute test
3323 *
3324 * @return tcu::TestNode::STOP otherwise
3325 **/
3326tcu::TestNode::IterateResult MapPersistentDrawTest::iterate()
3327{
3328	/*
3329	 *   * fragment shader should pass value of "gs_fs_color" varying to red
3330	 *   channel of output color;
3331	 */
3332	static const GLchar* fragment_shader = "#version 440 core\n"
3333										   "\n"
3334										   "in  float gs_fs_color;\n"
3335										   "out vec4  fs_out_color;\n"
3336										   "\n"
3337										   "void main()\n"
3338										   "{\n"
3339										   "    fs_out_color = vec4(gs_fs_color, 0, 0, 1);\n"
3340										   "}\n"
3341										   "\n";
3342
3343	/*
3344	 *   * geometry shader should:
3345	 *     - define single uniform buffer array "rectangles" with unspecified size;
3346	 *     Rectangles should have two vec2 fields: position and size;
3347	 *     - define single atomic_uint "atom_color";
3348	 *     - increment "atom_color" once per execution;
3349	 *     - output a quad that is placed at rectangles[vs_gs_index].position and
3350	 *     has size equal rectangles[vs_gs_index].size;
3351	 *     - define output float varying "gs_fs_color" equal to "atom_color" / 255;
3352	 */
3353	static const GLchar* geometry_shader =
3354		"#version 440 core\n"
3355		"\n"
3356		"layout(points)                           in;\n"
3357		"layout(triangle_strip, max_vertices = 4) out;\n"
3358		"\n"
3359		"struct Rectangle {\n"
3360		"    vec2 position;\n"
3361		"    vec2 size;\n"
3362		"};\n"
3363		"\n"
3364		"layout (std140, binding = 0) uniform Rectangles {\n"
3365		"    Rectangle rectangle[2];\n"
3366		"} rectangles;\n"
3367		"\n"
3368		"layout (binding = 0) uniform atomic_uint atom_color;\n"
3369		"\n"
3370		"in  uint  vs_gs_index[];\n"
3371		"out float gs_fs_color;\n"
3372		"\n"
3373		"void main()\n"
3374		"{\n"
3375		"    const uint  atom_color_value = atomicCounterIncrement(atom_color);\n"
3376		"    //const uint  atom_color_value = vs_gs_index[0];\n"
3377		"    const float color            = float(atom_color_value) / 255.0;\n"
3378		"    //const float color            = rectangles.rectangle[1].size.x;\n"
3379		"\n"
3380		"    const float left   = rectangles.rectangle[vs_gs_index[0]].position.x;\n"
3381		"    const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n"
3382		"    const float right  = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n"
3383		"    const float top    = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n"
3384		"\n"
3385		"    //const float left   = rectangles.rectangle[0].position.x;\n"
3386		"    //const float bottom = rectangles.rectangle[0].position.y;\n"
3387		"    //const float right  = rectangles.rectangle[0].size.x + left;\n"
3388		"    //const float top    = rectangles.rectangle[0].size.y + bottom;\n"
3389		"\n"
3390		"    gs_fs_color = color;\n"
3391		"    gl_Position  = vec4(left, bottom, 0, 1);\n"
3392		"    EmitVertex();\n"
3393		"\n"
3394		"    gs_fs_color = color;\n"
3395		"    gl_Position  = vec4(left, top, 0, 1);\n"
3396		"    EmitVertex();\n"
3397		"\n"
3398		"    gs_fs_color = color;\n"
3399		"    gl_Position  = vec4(right, bottom, 0, 1);\n"
3400		"    EmitVertex();\n"
3401		"\n"
3402		"    gs_fs_color = color;\n"
3403		"    gl_Position  = vec4(right, top, 0, 1);\n"
3404		"    EmitVertex();\n"
3405		"}\n"
3406		"\n";
3407
3408	/*
3409	 *   * vertex shader should output single varying "vs_gs_index" of type uint,
3410	 *   equal to gl_VertexID;
3411	 */
3412	static const GLchar* vertex_shader = "#version 440 core\n"
3413										 "\n"
3414										 "out uint vs_gs_index;\n"
3415										 "\n"
3416										 "void main()\n"
3417										 "{\n"
3418										 "    vs_gs_index = gl_VertexID;\n"
3419										 "}\n"
3420										 "\n";
3421
3422	static const GLuint atom_binding		 = 0;
3423	static const size_t atom_data_size		 = 1 * sizeof(GLuint);
3424	static const GLuint expected_atom_first  = 3;
3425	static const GLuint expected_atom_second = 7;
3426	static const GLuint expected_pixel		 = 0xff000003;
3427	static const GLuint height				 = 16;
3428	static const GLuint n_rectangles		 = 2;
3429	static const GLuint pixel_size			 = 4 * sizeof(GLubyte);
3430	static const GLuint rectangles_binding   = 0;
3431	static const size_t rectangle_size		 = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */
3432	static const size_t rectangles_data_size = n_rectangles * rectangle_size;
3433	static const GLuint width				 = 16;
3434	static const GLuint line_size			 = width * pixel_size;
3435	static const GLuint pixel_offset		 = 8 * line_size + 7 * pixel_size;
3436	static const size_t texture_data_size	= height * line_size;
3437
3438	const Functions& gl = m_context.getRenderContext().getFunctions();
3439
3440	bool test_result = true;
3441
3442	/* Prepare data */
3443	GLuint  atom_first_data[1];
3444	GLuint  atom_second_data[1];
3445	GLubyte rectangles_first_data[rectangles_data_size];
3446	GLubyte rectangles_second_data[rectangles_data_size];
3447	GLubyte texture_data[texture_data_size];
3448
3449	atom_first_data[0]  = 1;
3450	atom_second_data[0] = 5;
3451
3452	{
3453		GLfloat* ptr = (GLfloat*)rectangles_first_data;
3454
3455		/* First.position*/
3456		ptr[0] = -0.5f;
3457		ptr[1] = -0.5f;
3458
3459		/* First.size*/
3460		ptr[2] = 1.0f;
3461		ptr[3] = 1.0f;
3462
3463		/* Second.position*/
3464		ptr[4 + 0] = -0.75f;
3465		ptr[4 + 1] = -0.75f;
3466
3467		/* Second.size*/
3468		ptr[4 + 2] = 1.5f;
3469		ptr[4 + 3] = 1.5f;
3470	}
3471
3472	{
3473		GLfloat* ptr = (GLfloat*)rectangles_second_data;
3474
3475		/* First.position*/
3476		ptr[0] = -1.0f;
3477		ptr[1] = -1.0f;
3478
3479		/* First.size*/
3480		ptr[2] = 0.5f;
3481		ptr[3] = 0.5f;
3482
3483		/* Second.position*/
3484		ptr[4 + 0] = 0.5f;
3485		ptr[4 + 1] = 0.5f;
3486
3487		/* Second.size*/
3488		ptr[4 + 2] = 0.5f;
3489		ptr[4 + 3] = 0.5f;
3490	}
3491
3492	/* Prepare buffers */
3493	Buffer atom(m_context);
3494	Buffer rectangles(m_context);
3495
3496	atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
3497					 atom_data_size, 0);
3498
3499	rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0);
3500
3501	/* Prepare framebuffer */
3502	Framebuffer framebuffer(m_context);
3503	Texture		texture(m_context);
3504
3505	Texture::Generate(gl, texture.m_id);
3506	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
3507	Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */);
3508
3509	Framebuffer::Generate(gl, framebuffer.m_id);
3510	Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
3511	Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
3512
3513	/* Prepare VAO */
3514	VertexArray vao(m_context);
3515
3516	VertexArray::Generate(gl, vao.m_id);
3517	VertexArray::Bind(gl, vao.m_id);
3518
3519	/* Prepare program */
3520	Program program(m_context);
3521	program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader);
3522	Program::Use(gl, program.m_id);
3523
3524	/*
3525	 * - make persistent mapping of both buffers for reads and writes;
3526	 * - modify "rectangles" buffer via mapped memory with the following two sets
3527	 *   * position [-0.5,-0.5], size [1.0,1.0],
3528	 *   * position [-0.25,-0.25], size [1.5,1.5];
3529	 * - modify "atom_color" buffer via mapped memory to value 1;
3530	 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3531	 * - enable blending with functions ONE for both source and destination;
3532	 * - execute DrawArrays for two vertices;
3533	 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3534	 * - inspect contents of:
3535	 *   * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3536	 *   * "atom_color" - to verify that it is equal to 3;
3537	 * - modify "rectangles" buffer via mapped memory with the following two sets
3538	 *   * position [-1.0,-1.0], size [0.5,0.5],
3539	 *   * position [0.5,0.5], size [0.5,0.5];
3540	 * - modify "atom_color" buffer via mapped memory to value 5;
3541	 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3542	 * - execute DrawArrays for two vertices;
3543	 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3544	 * - inspect contents of:
3545	 *   * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3546	 *   * "atom_color" - to verify that it is equal to 7;
3547	 *
3548	 *  Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile.
3549	 */
3550	{
3551		/* Choose specification */
3552		const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3553
3554		/* Map buffers */
3555		atom.Bind();
3556		const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size,
3557													  GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
3558														  (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3559
3560		rectangles.Bind();
3561		const Buffer::MapOwner rectangles_map(
3562			rectangles.MapRange(0 /* offset */, rectangles_data_size,
3563								GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3564
3565		/* Clear binding points */
3566		Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER);
3567		Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER);
3568
3569		/* Bind buffers */
3570		Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding);
3571		Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding);
3572
3573		/* Set up blending */
3574		gl.enable(GL_BLEND);
3575		gl.blendFunc(GL_ONE, GL_ONE);
3576
3577		/* Modify buffers */
3578		memcpy(atom_map.m_data, atom_first_data, atom_data_size);
3579		memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size);
3580
3581		/* Execute barrier or flush content. */
3582		if (is_gl_45)
3583		{
3584			gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3585			GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3586
3587			gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3588			GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3589		}
3590		else
3591		{
3592			gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3593			GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3594		}
3595
3596		/* Clear drawbuffer */
3597		GLint clear_color[4] = { 0, 0, 0, 0 };
3598		gl.clearBufferiv(GL_COLOR, 0, clear_color);
3599
3600		/* Execute program for 2 vertices */
3601		gl.drawArrays(GL_POINTS, 0, 2);
3602		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3603
3604		/* Execute barrier */
3605		gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3606		GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3607
3608		/* Inspect texture */
3609		Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3610		if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3611		{
3612			test_result = false;
3613
3614			m_context.getTestContext().getLog() << tcu::TestLog::Message
3615												<< "Contents of framebuffer does not correspond with expected results"
3616												<< tcu::TestLog::EndMessage;
3617			tcu::ConstPixelBufferAccess img(
3618				tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3619				1 /* depth */, texture_data);
3620			m_context.getTestContext().getLog()
3621				<< tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img);
3622		}
3623
3624		/* Inspect atom */
3625		if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint)))
3626		{
3627			test_result = false;
3628
3629			m_context.getTestContext().getLog() << tcu::TestLog::Message
3630												<< "Contents of ATOMIC_COUNTER buffer are invalid."
3631												<< tcu::TestLog::EndMessage;
3632		}
3633
3634		/* Modify buffers */
3635		memcpy(atom_map.m_data, atom_second_data, atom_data_size);
3636		memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size);
3637
3638		/* Execute barrier or flush content. */
3639		if (is_gl_45)
3640		{
3641			gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3642			GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3643
3644			gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3645			GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3646		}
3647		else
3648		{
3649			gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3650			GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3651		}
3652
3653		/* Execute program for 2 vertices */
3654		gl.drawArrays(GL_POINTS, 0, 2);
3655		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3656
3657		/* Execute barrier */
3658		gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3659		GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3660
3661		/* Inspect texture */
3662		Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3663		if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3664		{
3665			test_result = false;
3666
3667			m_context.getTestContext().getLog() << tcu::TestLog::Message
3668												<< "Contents of framebuffer does not correspond with expected results"
3669												<< tcu::TestLog::EndMessage;
3670			tcu::ConstPixelBufferAccess img(
3671				tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3672				1 /* depth */, texture_data);
3673			m_context.getTestContext().getLog()
3674				<< tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img);
3675		}
3676
3677		/* Inspect atom */
3678		if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint)))
3679		{
3680			test_result = false;
3681
3682			m_context.getTestContext().getLog() << tcu::TestLog::Message
3683												<< "Contents of ATOMIC_COUNTER buffer are invalid."
3684												<< tcu::TestLog::EndMessage;
3685		}
3686	}
3687
3688	/* Set result */
3689	if (true == test_result)
3690	{
3691		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3692	}
3693	else
3694	{
3695		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3696	}
3697
3698	/* Done */
3699	return tcu::TestNode::STOP;
3700}
3701} /* BufferStorage */
3702
3703/** Constructor.
3704 *
3705 *  @param context Rendering context.
3706 **/
3707BufferStorageTests::BufferStorageTests(deqp::Context& context)
3708	: TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality")
3709{
3710	/* Left blank on purpose */
3711}
3712
3713/** Initializes a texture_storage_multisample test group.
3714 *
3715 **/
3716void BufferStorageTests::init(void)
3717{
3718	addChild(new BufferStorage::ErrorsTest(m_context));
3719	addChild(new BufferStorage::GetBufferParameterTest(m_context));
3720	addChild(new BufferStorage::DynamicStorageTest(m_context));
3721	addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context));
3722	addChild(new BufferStorage::MapPersistentTextureTest(m_context));
3723	addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context));
3724	addChild(new BufferStorage::MapPersistentDispatchTest(m_context));
3725	addChild(new BufferStorage::MapPersistentFlushTest(m_context));
3726	addChild(new BufferStorage::MapPersistentDrawTest(m_context));
3727}
3728} /* gl4cts namespace */
3729