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 
43 using namespace glw;
44 
45 namespace gl4cts
46 {
47 namespace BufferStorage
48 {
49 /* Enums */
50 
51 /* Represents how functionality is supported */
52 enum 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  */
61 FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context& context);
62 bool 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  **/
69 class Buffer
70 {
71 public:
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 	{
MoveMapOwnergl4cts::BufferStorage::Buffer::MoveMapOwner77 		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 
170 private:
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  **/
181 class Framebuffer
182 {
183 public:
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 
206 private:
207 	/* Private fields */
208 	deqp::Context& m_context;
209 };
210 
211 /** Represents shader instance.
212  * Provides basic functionality for shaders.
213  **/
214 class Shader
215 {
216 public:
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 
240 private:
241 	/* Private fields */
242 	deqp::Context& m_context;
243 };
244 
245 /** Represents program instance.
246  * Provides basic functionality
247  **/
248 class Program
249 {
250 public:
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 
286 private:
287 	/* Private fields */
288 	deqp::Context& m_context;
289 };
290 
291 /** Represents texture instance
292  **/
293 class Texture
294 {
295 public:
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 
341 private:
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  **/
352 class VertexArray
353 {
354 public:
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 
373 private:
374 	/* Private fields */
375 	deqp::Context& m_context;
376 };
377 
378 /* Global variables */
379 static 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  **/
getDirectStateAccessSupport(deqp::Context & context)386 FUNCTIONALITY_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  **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)422 bool 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 */
460 const GLuint Buffer::m_invalid_id = -1;
461 
462 const 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  **/
Buffer(deqp::Context & context)482 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
483 {
484 }
485 
486 /** Destructor
487  *
488  **/
~Buffer()489 Buffer::~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  **/
InitData(glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)501 void 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  **/
InitStorage(glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)522 void 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  **/
Release()539 void 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  **/
Bind() const553 void 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  **/
BindBase(glw::GLuint index) const564 void 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  **/
BindRange(glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size) const577 void 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  **/
MapRange(glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)590 Buffer::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  **/
UnMap()606 void 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  **/
LoadExtDirectStateAccess(deqp::Context & context)617 void 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  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)641 void 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  **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)654 void 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  **/
BindRange(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)669 void 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  **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)684 void 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  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)696 void 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  **/
GetNamedParameter(const glw::Functions & gl,glw::GLuint buffer,glw::GLenum pname,glw::GLint * data)718 void 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  **/
GetParameter(const glw::Functions & gl,glw::GLenum target,glw::GLenum value,glw::GLint * data)731 void 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  **/
GetSubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)745 void 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  **/
Map(const glw::Functions & gl,glw::GLenum target,glw::GLenum access)760 void* 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  **/
MapRange(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)776 void* 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  **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)793 void 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  **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)808 void 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  **/
UnMap(const glw::Functions & gl,glw::GLenum target)820 void 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  **/
MapOwner(Buffer & buffer,glw::GLvoid * data)832 Buffer::MapOwner::MapOwner(Buffer& buffer, glw::GLvoid* data) : m_data(data), m_buffer(&buffer)
833 {
834 	/* Nothing to be done */
835 }
836 
MapOwner(const Buffer::MoveMapOwner & moveOwner)837 Buffer::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  **/
MapOwner(MapOwner & map_owner)846 Buffer::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  **/
~MapOwner()855 Buffer::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 */
867 const GLuint Framebuffer::m_invalid_id = -1;
868 
869 /** Constructor.
870  *
871  * @param context CTS context.
872  **/
Framebuffer(deqp::Context & context)873 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
874 {
875 	/* Nothing to done here */
876 }
877 
878 /** Destructor
879  *
880  **/
~Framebuffer()881 Framebuffer::~Framebuffer()
882 {
883 	Release();
884 }
885 
886 /** Release texture instance
887  *
888  **/
Release()889 void 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  **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)909 void 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  **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)925 void 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  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)934 void 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 */
950 const GLuint Program::m_invalid_id = 0;
951 
952 /** Constructor.
953  *
954  * @param context CTS context.
955  **/
Program(deqp::Context & context)956 Program::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  **/
~Program()972 Program::~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  **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tesselation_control_shader,const std::string & tesselation_evaluation_shader,const std::string & vertex_shader)986 void 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  **/
Release()1020 void 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  **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)1046 void 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  **/
Create(const glw::Functions & gl,glw::GLuint & out_id)1063 void 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  **/
Link(const glw::Functions & gl,glw::GLuint id)1081 void 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  **/
Use(const glw::Functions & gl,glw::GLuint id)1117 void 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 */
1124 const GLuint Shader::m_invalid_id = 0;
1125 
1126 /** Constructor.
1127  *
1128  * @param context CTS context.
1129  **/
Shader(deqp::Context & context)1130 Shader::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  **/
~Shader()1138 Shader::~Shader()
1139 {
1140 	Release();
1141 }
1142 
1143 /** Initialize shader instance
1144  *
1145  * @param stage  Shader stage
1146  * @param source Source code
1147  **/
Init(glw::GLenum stage,const std::string & source)1148 void 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  **/
Release()1171 void 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  **/
Compile(const glw::Functions & gl,glw::GLuint id)1187 void 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  **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)1226 void 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  **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)1245 void 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 
1255 FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
1256 
1257 /* Texture constants */
1258 const GLuint Texture::m_invalid_id = -1;
1259 
1260 /** Constructor.
1261  *
1262  * @param context CTS context.
1263  **/
Texture(deqp::Context & context)1264 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1265 {
1266 	/* Nothing to done here */
1267 }
1268 
1269 /** Destructor
1270  *
1271  **/
~Texture()1272 Texture::~Texture()
1273 {
1274 	Release();
1275 }
1276 
1277 /** Release texture instance
1278  *
1279  **/
Release()1280 void 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  **/
LoadExtDirectStateAccess(deqp::Context & context)1295 void 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  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1319 void 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  **/
CompressedImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLsizei image_size,const glw::GLvoid * data)1337 void 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  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1384 void 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  **/
GetData(const glw::Functions & gl,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1407 void 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  **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1422 void 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  **/
Image(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * data)1442 void 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  **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth)1494 void 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  **/
SubImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLint x,glw::GLint y,glw::GLint z,glw::GLsizei width,glw::GLsizei height,glw::GLsizei depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * pixels)1536 void 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 */
1573 const GLuint VertexArray::m_invalid_id = -1;
1574 
1575 /** Constructor.
1576  *
1577  * @param context CTS context.
1578  **/
VertexArray(deqp::Context & context)1579 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1580 {
1581 }
1582 
1583 /** Destructor
1584  *
1585  **/
~VertexArray()1586 VertexArray::~VertexArray()
1587 {
1588 	Release();
1589 }
1590 
1591 /** Release vertex array object instance
1592  *
1593  **/
Release()1594 void 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  **/
Bind(const glw::Functions & gl,glw::GLuint id)1613 void 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  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1624 void 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  **/
ErrorsTest(deqp::Context & context)1643 ErrorsTest::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  **/
iterate()1653 tcu::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  **/
verifyError(glw::GLenum expected_error,const glw::GLchar * error_message,bool & out_test_result)1923 void 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  **/
GetBufferParameterTest(deqp::Context & context)1944 GetBufferParameterTest::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  **/
iterate()1993 tcu::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  **/
testCase(glw::GLenum flags,glw::GLenum access)2159 GetBufferParameterTest::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  **/
DynamicStorageTest(deqp::Context & context)2167 DynamicStorageTest::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  **/
iterate()2177 tcu::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  **/
MapPersistentBufferSubDataTest(deqp::Context & context)2321 MapPersistentBufferSubDataTest::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  **/
iterate()2331 tcu::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  **/
MapPersistentTextureTest(deqp::Context & context)2536 MapPersistentTextureTest::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  **/
iterate()2548 tcu::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  **/
getOperationName(TESTED_OPERATION operation)2646 const 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  **/
getCompressedInfo()2677 void 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  **/
verifyTestedOperation(TESTED_OPERATION operation,Buffer & buffer,glw::GLenum expected_error)2703 bool 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  **/
MapPersistentReadPixelsTest(deqp::Context & context)2804 MapPersistentReadPixelsTest::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  **/
iterate()2814 tcu::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  **/
MapPersistentDispatchTest(deqp::Context & context)2942 MapPersistentDispatchTest::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  **/
MapPersistentDispatchTest(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)2954 MapPersistentDispatchTest::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  **/
iterate()2965 tcu::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  **/
MapPersistentFlushTest(deqp::Context & context)3130 MapPersistentFlushTest::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  **/
iterate()3140 tcu::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  **/
MapPersistentDrawTest(deqp::Context & context)3316 MapPersistentDrawTest::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  **/
iterate()3326 tcu::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  **/
BufferStorageTests(deqp::Context & context)3707 BufferStorageTests::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  **/
init(void)3716 void 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