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