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