1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture buffer test case
22  *//*--------------------------------------------------------------------*/
23 
24 #include "glsTextureBufferCase.hpp"
25 
26 #include "tcuFormatUtil.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuSurface.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuResultCollector.hpp"
34 
35 #include "rrRenderer.hpp"
36 #include "rrShaders.hpp"
37 
38 #include "gluObjectWrapper.hpp"
39 #include "gluPixelTransfer.hpp"
40 #include "gluShaderProgram.hpp"
41 #include "gluShaderUtil.hpp"
42 #include "gluStrUtil.hpp"
43 #include "gluTexture.hpp"
44 #include "gluTextureUtil.hpp"
45 
46 #include "glwEnums.hpp"
47 #include "glwFunctions.hpp"
48 
49 #include "deRandom.hpp"
50 #include "deStringUtil.hpp"
51 #include "deUniquePtr.hpp"
52 
53 #include "deMemory.h"
54 #include "deString.h"
55 #include "deMath.h"
56 
57 #include <sstream>
58 #include <string>
59 #include <vector>
60 
61 using tcu::TestLog;
62 
63 using std::map;
64 using std::string;
65 using std::vector;
66 
67 using namespace deqp::gls::TextureBufferCaseUtil;
68 
69 namespace deqp
70 {
71 namespace gls
72 {
73 namespace
74 {
75 
76 enum
77 {
78 	MAX_VIEWPORT_WIDTH	= 256,
79 	MAX_VIEWPORT_HEIGHT	= 256,
80 	MIN_VIEWPORT_WIDTH	= 64,
81 	MIN_VIEWPORT_HEIGHT	= 64,
82 };
83 
extend2BitsToByte(deUint8 bits)84 deUint8 extend2BitsToByte (deUint8 bits)
85 {
86 	DE_ASSERT((bits & (~0x03u)) == 0);
87 
88 	return (deUint8)(bits | (bits << 2) | (bits << 4) | (bits << 6));
89 }
90 
genRandomCoords(de::Random rng,vector<deUint8> & coords,size_t offset,size_t size)91 void genRandomCoords (de::Random rng, vector<deUint8>& coords, size_t offset, size_t size)
92 {
93 	const deUint8 bits		= 2;
94 	const deUint8 bitMask	= deUint8((0x1u << bits) - 1);
95 
96 	coords.resize(size);
97 
98 	for (int i = 0; i < (int)size; i++)
99 	{
100 		const deUint8 xBits = deUint8(rng.getUint32() & bitMask);
101 		coords[i] = extend2BitsToByte(xBits);
102 	}
103 
104 	// Fill indices with nice quad
105 	{
106 		const deUint8 indices[] =
107 		{
108 			extend2BitsToByte(0x0u),
109 			extend2BitsToByte(0x1u),
110 			extend2BitsToByte(0x2u),
111 			extend2BitsToByte(0x3u)
112 		};
113 
114 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(indices); i++)
115 		{
116 			const deUint8	index	= indices[i];
117 			const size_t	posX	= (size_t(index) * 2) + 0;
118 			const size_t	posY	= (size_t(index) * 2) + 1;
119 
120 			if (posX >= offset && posX < offset+size)
121 				coords[posX - offset] = ((i % 2) == 0 ? extend2BitsToByte(0x0u) : extend2BitsToByte(0x3u));
122 
123 			if (posY >= offset && posY < offset+size)
124 				coords[posY - offset] = ((i / 2) == 1 ? extend2BitsToByte(0x3u) : extend2BitsToByte(0x0u));
125 		}
126 	}
127 
128 	// Fill beginning of buffer
129 	{
130 		const deUint8 indices[] =
131 		{
132 			extend2BitsToByte(0x0u),
133 			extend2BitsToByte(0x3u),
134 			extend2BitsToByte(0x1u),
135 
136 			extend2BitsToByte(0x1u),
137 			extend2BitsToByte(0x2u),
138 			extend2BitsToByte(0x0u),
139 
140 			extend2BitsToByte(0x0u),
141 			extend2BitsToByte(0x2u),
142 			extend2BitsToByte(0x1u),
143 
144 			extend2BitsToByte(0x1u),
145 			extend2BitsToByte(0x3u),
146 			extend2BitsToByte(0x0u)
147 		};
148 
149 		for (int i = (int)offset; i < DE_LENGTH_OF_ARRAY(indices) && i < (int)(offset + size); i++)
150 			coords[i-offset] = indices[i];
151 	}
152 }
153 
154 class CoordVertexShader : public rr::VertexShader
155 {
156 public:
CoordVertexShader(void)157 	CoordVertexShader (void)
158 		: rr::VertexShader(1, 1)
159 	{
160 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
161 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
162 	}
163 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const164 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
165 	{
166 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
167 		{
168 			rr::VertexPacket* const		packet		= packets[packetNdx];
169 			tcu::Vec4					position;
170 
171 			readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
172 
173 			packet->outputs[0]	= tcu::Vec4(1.0f);
174 			packet->position	= tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
175 		}
176 	}
177 };
178 
179 class TextureVertexShader : public rr::VertexShader
180 {
181 public:
TextureVertexShader(const tcu::ConstPixelBufferAccess & texture)182 	TextureVertexShader (const tcu::ConstPixelBufferAccess& texture)
183 		: rr::VertexShader	(1, 1)
184 		, m_texture			(texture)
185 	{
186 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
187 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
188 	}
189 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const190 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
191 	{
192 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
193 		{
194 			rr::VertexPacket* const		packet		= packets[packetNdx];
195 			tcu::Vec4					position;
196 			tcu::Vec4					texelValue;
197 
198 			readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
199 
200 			texelValue	= tcu::Vec4(m_texture.getPixel(de::clamp<int>((deRoundFloatToInt32(position.x() * 4) + 4) * (deRoundFloatToInt32(position.y() * 4) + 4), 0, m_texture.getWidth()-1), 0));
201 
202 			packet->outputs[0]	= texelValue;
203 			packet->position	= tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
204 		}
205 	}
206 
207 private:
208 	const tcu::ConstPixelBufferAccess m_texture;
209 };
210 
211 class CoordFragmentShader : public rr::FragmentShader
212 {
213 public:
CoordFragmentShader(void)214 	CoordFragmentShader (void)
215 		: rr::FragmentShader (1, 1)
216 	{
217 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
218 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
219 	}
220 
221 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const222 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
223 	{
224 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
225 		{
226 			rr::FragmentPacket&	packet		= packets[packetNdx];
227 
228 			const tcu::Vec4		vtxColor0	= rr::readVarying<float>(packet, context, 0, 0);
229 			const tcu::Vec4		vtxColor1	= rr::readVarying<float>(packet, context, 0, 1);
230 			const tcu::Vec4		vtxColor2	= rr::readVarying<float>(packet, context, 0, 2);
231 			const tcu::Vec4		vtxColor3	= rr::readVarying<float>(packet, context, 0, 3);
232 
233 			const tcu::Vec4		color0		= vtxColor0;
234 			const tcu::Vec4		color1		= vtxColor1;
235 			const tcu::Vec4		color2		= vtxColor2;
236 			const tcu::Vec4		color3		= vtxColor3;
237 
238 			rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
239 			rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
240 			rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
241 			rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
242 		}
243 	}
244 };
245 
246 class TextureFragmentShader : public rr::FragmentShader
247 {
248 public:
TextureFragmentShader(const tcu::ConstPixelBufferAccess & texture)249 	TextureFragmentShader (const tcu::ConstPixelBufferAccess& texture)
250 		: rr::FragmentShader	(1, 1)
251 		, m_texture				(texture)
252 	{
253 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
254 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
255 	}
256 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const257 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
258 	{
259 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
260 		{
261 			rr::FragmentPacket&	packet		= packets[packetNdx];
262 
263 			const tcu::IVec2	position0	= packet.position + tcu::IVec2(0, 0);
264 			const tcu::IVec2	position1	= packet.position + tcu::IVec2(1, 0);
265 			const tcu::IVec2	position2	= packet.position + tcu::IVec2(0, 1);
266 			const tcu::IVec2	position3	= packet.position + tcu::IVec2(1, 1);
267 
268 			const tcu::Vec4		texColor0	= m_texture.getPixel(de::clamp((position0.x() * position0.y()), 0, m_texture.getWidth()-1), 0);
269 			const tcu::Vec4		texColor1	= m_texture.getPixel(de::clamp((position1.x() * position1.y()), 0, m_texture.getWidth()-1), 0);
270 			const tcu::Vec4		texColor2	= m_texture.getPixel(de::clamp((position2.x() * position2.y()), 0, m_texture.getWidth()-1), 0);
271 			const tcu::Vec4		texColor3	= m_texture.getPixel(de::clamp((position3.x() * position3.y()), 0, m_texture.getWidth()-1), 0);
272 
273 			const tcu::Vec4		vtxColor0	= rr::readVarying<float>(packet, context, 0, 0);
274 			const tcu::Vec4		vtxColor1	= rr::readVarying<float>(packet, context, 0, 1);
275 			const tcu::Vec4		vtxColor2	= rr::readVarying<float>(packet, context, 0, 2);
276 			const tcu::Vec4		vtxColor3	= rr::readVarying<float>(packet, context, 0, 3);
277 
278 			const tcu::Vec4		color0		= 0.5f * (vtxColor0 + texColor0);
279 			const tcu::Vec4		color1		= 0.5f * (vtxColor1 + texColor1);
280 			const tcu::Vec4		color2		= 0.5f * (vtxColor2 + texColor2);
281 			const tcu::Vec4		color3		= 0.5f * (vtxColor3 + texColor3);
282 
283 			rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
284 			rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
285 			rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
286 			rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
287 		}
288 	}
289 
290 private:
291 	const tcu::ConstPixelBufferAccess m_texture;
292 };
293 
generateVertexShaderTemplate(RenderBits renderBits)294 string generateVertexShaderTemplate (RenderBits renderBits)
295 {
296 	std::ostringstream stream;
297 
298 	stream <<
299 		"${VERSION_HEADER}\n";
300 
301 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
302 		stream << "${TEXTURE_BUFFER_EXT}";
303 
304 	stream <<
305 		"${VTX_INPUT} layout(location = 0) ${HIGHP} vec2 i_coord;\n"
306 		"${VTX_OUTPUT} ${HIGHP} vec4 v_color;\n";
307 
308 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
309 	{
310 		stream <<
311 			"uniform ${HIGHP} samplerBuffer u_vtxSampler;\n";
312 	}
313 
314 	stream <<
315 		"\n"
316 		"void main (void)\n"
317 		"{\n";
318 
319 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
320 		stream << "\tv_color = texelFetch(u_vtxSampler, clamp((int(round(i_coord.x * 4.0)) + 4) * (int(round(i_coord.y * 4.0)) + 4), 0, textureSize(u_vtxSampler)-1));\n";
321 	else
322 		stream << "\tv_color = vec4(1.0);\n";
323 
324 	stream <<
325 		"\tgl_Position = vec4(2.0 * (i_coord - vec2(0.5)), 0.0, 1.0);\n"
326 		"}\n";
327 
328 	return stream.str();
329 }
330 
generateFragmentShaderTemplate(RenderBits renderBits)331 string generateFragmentShaderTemplate (RenderBits renderBits)
332 {
333 	std::ostringstream stream;
334 
335 	stream <<
336 		"${VERSION_HEADER}\n";
337 
338 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
339 		stream << "${TEXTURE_BUFFER_EXT}";
340 
341 	stream <<
342 		"${FRAG_OUTPUT} layout(location = 0) ${HIGHP} vec4 dEQP_FragColor;\n"
343 		"${FRAG_INPUT} ${HIGHP} vec4 v_color;\n";
344 
345 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
346 		stream << "uniform ${HIGHP} samplerBuffer u_fragSampler;\n";
347 
348 	stream <<
349 		"\n"
350 		"void main (void)\n"
351 		"{\n";
352 
353 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
354 		stream << "\t${HIGHP} vec4 color = 0.5 * (v_color + texelFetch(u_fragSampler, clamp(int(gl_FragCoord.x) * int(gl_FragCoord.y), 0, textureSize(u_fragSampler)-1)));\n";
355 	else
356 		stream << "\t${HIGHP} vec4 color = v_color;\n";
357 
358 	stream <<
359 		"\tdEQP_FragColor = vec4(color.xyz * color.w, 1.0);\n"
360 		"}\n";
361 
362 	return stream.str();
363 }
364 
specializeShader(const string & shaderTemplateString,glu::GLSLVersion glslVersion)365 string specializeShader (const string& shaderTemplateString, glu::GLSLVersion glslVersion)
366 {
367 	const tcu::StringTemplate	shaderTemplate(shaderTemplateString);
368 	map<string, string>			parameters;
369 
370 	parameters["VERSION_HEADER"]		= glu::getGLSLVersionDeclaration(glslVersion);
371 	parameters["VTX_OUTPUT"]			= "out";
372 	parameters["VTX_INPUT"]				= "in";
373 	parameters["FRAG_INPUT"]			= "in";
374 	parameters["FRAG_OUTPUT"]			= "out";
375 	parameters["HIGHP"]					= (glslVersion == glu::GLSL_VERSION_330 ? "" : "highp");
376 	parameters["TEXTURE_BUFFER_EXT"]	= (glslVersion == glu::GLSL_VERSION_330 ? "" : "#extension GL_EXT_texture_buffer : enable\n");
377 
378 	return shaderTemplate.specialize(parameters);
379 }
380 
createRenderProgram(glu::RenderContext & renderContext,RenderBits renderBits)381 glu::ShaderProgram* createRenderProgram (glu::RenderContext&	renderContext,
382 										 RenderBits				renderBits)
383 {
384 	const string				vertexShaderTemplate	= generateVertexShaderTemplate(renderBits);
385 	const string				fragmentShaderTemplate	= generateFragmentShaderTemplate(renderBits);
386 
387 	const glu::GLSLVersion		glslVersion				= glu::getContextTypeGLSLVersion(renderContext.getType());
388 
389 	const string				vertexShaderSource		= specializeShader(vertexShaderTemplate, glslVersion);
390 	const string				fragmentShaderSource	= specializeShader(fragmentShaderTemplate, glslVersion);
391 
392 	glu::ShaderProgram* const	program					= new glu::ShaderProgram(renderContext, glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
393 
394 	return program;
395 }
396 
logModifications(TestLog & log,ModifyBits modifyBits)397 void logModifications (TestLog& log, ModifyBits modifyBits)
398 {
399 	tcu::ScopedLogSection section(log, "Modify Operations", "Modify Operations");
400 
401 	const struct
402 	{
403 		ModifyBits	bit;
404 		const char*	str;
405 	} bitInfos[] =
406 	{
407 		{ MODIFYBITS_BUFFERDATA,			"Recreate buffer data with glBufferData()."			},
408 		{ MODIFYBITS_BUFFERSUBDATA,			"Modify texture buffer with glBufferSubData()."		},
409 		{ MODIFYBITS_MAPBUFFER_WRITE,		"Map buffer write-only and rewrite data."			},
410 		{ MODIFYBITS_MAPBUFFER_READWRITE,	"Map buffer readw-write check and rewrite data."	}
411 	};
412 
413 	DE_ASSERT(modifyBits != 0);
414 
415 	for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
416 	{
417 		if (modifyBits & bitInfos[infoNdx].bit)
418 			log << TestLog::Message << bitInfos[infoNdx].str << TestLog::EndMessage;
419 	}
420 }
421 
modifyBufferData(TestLog & log,de::Random & rng,glu::TextureBuffer & texture)422 void modifyBufferData (TestLog&				log,
423 					   de::Random&			rng,
424 					   glu::TextureBuffer&	texture)
425 {
426 	vector<deUint8> data;
427 
428 	genRandomCoords(rng, data, 0, texture.getBufferSize());
429 
430 	log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
431 
432 	{
433 		// replace getRefBuffer with a new buffer
434 		de::ArrayBuffer<deUint8> buffer(&(data[0]), data.size());
435 		texture.getRefBuffer().swap(buffer);
436 	}
437 
438 	texture.upload();
439 }
440 
modifyBufferSubData(TestLog & log,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)441 void modifyBufferSubData (TestLog&				log,
442 						  de::Random&			rng,
443 						  const glw::Functions&	gl,
444 						  glu::TextureBuffer&	texture)
445 {
446 	const size_t				minSize		= 4*16;
447 	const size_t				size		= de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
448 	const size_t				minOffset	= texture.getOffset();
449 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
450 	vector<deUint8>				data;
451 
452 	genRandomCoords(rng, data, offset, size);
453 
454 	log << TestLog::Message << "BufferSubData, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
455 
456 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
457 	gl.bufferSubData(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)data.size(), &(data[0]));
458 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
459 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
460 
461 	deMemcpy((deUint8*)texture.getRefBuffer().getPtr() + offset, &(data[0]), int(data.size()));
462 }
463 
modifyMapWrite(TestLog & log,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)464 void modifyMapWrite (TestLog&				log,
465 					 de::Random&			rng,
466 					 const glw::Functions&	gl,
467 					 glu::TextureBuffer&	texture)
468 {
469 	const size_t				minSize		= 4*16;
470 	const size_t				size		= de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
471 	const size_t				minOffset	= texture.getOffset();
472 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
473 	vector<deUint8>				data;
474 
475 	genRandomCoords(rng, data, offset, size);
476 
477 	log << TestLog::Message << "glMapBufferRange, Write Only, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
478 
479 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
480 	{
481 		deUint8* ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT);
482 
483 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
484 		TCU_CHECK(ptr);
485 
486 		for (int i = 0; i < (int)data.size(); i++)
487 			ptr[i] = data[i];
488 
489 		TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
490 	}
491 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
492 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
493 
494 	deMemcpy((deUint8*)texture.getRefBuffer().getPtr()+offset, &(data[0]), int(data.size()));
495 }
496 
modifyMapReadWrite(TestLog & log,tcu::ResultCollector & resultCollector,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)497 void modifyMapReadWrite (TestLog&				log,
498 						 tcu::ResultCollector&	resultCollector,
499 						 de::Random&			rng,
500 						 const glw::Functions&	gl,
501 						 glu::TextureBuffer&	texture)
502 {
503 	const size_t				minSize		= 4*16;
504 	const size_t				size		= de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
505 	const size_t				minOffset	= texture.getOffset();
506 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
507 	deUint8* const				refPtr		= (deUint8*)texture.getRefBuffer().getPtr() + offset;
508 	vector<deUint8>				data;
509 
510 	genRandomCoords(rng, data, offset, size);
511 
512 	log << TestLog::Message << "glMapBufferRange, Read Write, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
513 
514 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
515 	{
516 		size_t			invalidBytes	= 0;
517 		deUint8* const	ptr				= (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT|GL_MAP_READ_BIT);
518 
519 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
520 		TCU_CHECK(ptr);
521 
522 		for (int i = 0; i < (int)data.size(); i++)
523 		{
524 			if (ptr[i] != refPtr[i])
525 			{
526 				if (invalidBytes < 24)
527 					log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(refPtr[i]).toString() << TestLog::EndMessage;
528 
529 				invalidBytes++;
530 			}
531 
532 			ptr[i] = data[i];
533 		}
534 
535 		TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
536 
537 		if (invalidBytes > 0)
538 		{
539 			log << TestLog::Message << "Total of " << invalidBytes << " invalid bytes." << TestLog::EndMessage;
540 			resultCollector.fail("Invalid data in mapped buffer");
541 		}
542 	}
543 
544 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
545 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
546 
547 	for (int i = 0; i < (int)data.size(); i++)
548 		refPtr[i] = data[i];
549 }
550 
modify(TestLog & log,tcu::ResultCollector & resultCollector,glu::RenderContext & renderContext,ModifyBits modifyBits,de::Random & rng,glu::TextureBuffer & texture)551 void modify (TestLog&						log,
552 			 tcu::ResultCollector&			resultCollector,
553 			 glu::RenderContext&			renderContext,
554 			 ModifyBits						modifyBits,
555 			 de::Random&					rng,
556 			 glu::TextureBuffer&			texture)
557 {
558 	const tcu::ScopedLogSection modifySection(log, "Modifying Texture buffer", "Modifying Texture Buffer");
559 
560 	logModifications(log, modifyBits);
561 
562 	if (modifyBits & MODIFYBITS_BUFFERDATA)
563 		modifyBufferData(log, rng, texture);
564 
565 	if (modifyBits & MODIFYBITS_BUFFERSUBDATA)
566 		modifyBufferSubData(log, rng, renderContext.getFunctions(), texture);
567 
568 	if (modifyBits & MODIFYBITS_MAPBUFFER_WRITE)
569 		modifyMapWrite(log, rng, renderContext.getFunctions(), texture);
570 
571 	if (modifyBits & MODIFYBITS_MAPBUFFER_READWRITE)
572 		modifyMapReadWrite(log, resultCollector, rng, renderContext.getFunctions(), texture);
573 }
574 
renderGL(glu::RenderContext & renderContext,RenderBits renderBits,deUint32 coordSeed,int triangleCount,glu::ShaderProgram & program,glu::TextureBuffer & texture)575 void renderGL (glu::RenderContext&		renderContext,
576 			   RenderBits				renderBits,
577 			   deUint32					coordSeed,
578 			   int						triangleCount,
579 			   glu::ShaderProgram&		program,
580 			   glu::TextureBuffer&		texture)
581 {
582 	const glw::Functions&	gl			= renderContext.getFunctions();
583 	const glu::VertexArray	vao			(renderContext);
584 	const glu::Buffer		coordBuffer	(renderContext);
585 
586 	gl.useProgram(program.getProgram());
587 	gl.bindVertexArray(*vao);
588 
589 	gl.enableVertexAttribArray(0);
590 
591 	if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
592 	{
593 		gl.bindBuffer(GL_ARRAY_BUFFER, texture.getGLBuffer());
594 		gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
595 	}
596 	else
597 	{
598 		de::Random		rng(coordSeed);
599 		vector<deUint8> coords;
600 
601 		genRandomCoords(rng, coords, 0, 256*2);
602 
603 		gl.bindBuffer(GL_ARRAY_BUFFER, *coordBuffer);
604 		gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)coords.size(), &(coords[0]), GL_STREAM_DRAW);
605 		gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
606 	}
607 
608 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
609 	{
610 		const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_vtxSampler");
611 
612 		gl.activeTexture(GL_TEXTURE0);
613 		gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
614 		gl.uniform1i(location, 0);
615 	}
616 
617 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
618 	{
619 		const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_fragSampler");
620 
621 		gl.activeTexture(GL_TEXTURE1);
622 		gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
623 		gl.uniform1i(location, 1);
624 		gl.activeTexture(GL_TEXTURE0);
625 	}
626 
627 	if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
628 	{
629 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, texture.getGLBuffer());
630 		gl.drawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_BYTE, DE_NULL);
631 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
632 	}
633 	else
634 		gl.drawArrays(GL_TRIANGLES, 0, triangleCount * 3);
635 
636 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
637 	{
638 		gl.activeTexture(GL_TEXTURE1);
639 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
640 	}
641 
642 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
643 	{
644 		gl.activeTexture(GL_TEXTURE0);
645 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
646 	}
647 
648 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
649 	gl.disableVertexAttribArray(0);
650 
651 	gl.bindVertexArray(0);
652 	gl.useProgram(0);
653 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
654 }
655 
renderReference(RenderBits renderBits,deUint32 coordSeed,int triangleCount,const glu::TextureBuffer & texture,int maxTextureBufferSize,const tcu::PixelBufferAccess & target)656 void renderReference (RenderBits					renderBits,
657 					  deUint32						coordSeed,
658 					  int							triangleCount,
659 					  const glu::TextureBuffer&		texture,
660 					  int							maxTextureBufferSize,
661 					  const tcu::PixelBufferAccess&	target)
662 {
663 	const tcu::ConstPixelBufferAccess	effectiveAccess			= glu::getTextureBufferEffectiveRefTexture(texture, maxTextureBufferSize);
664 
665 	const CoordVertexShader				coordVertexShader;
666 	const TextureVertexShader			textureVertexShader		(effectiveAccess);
667 	const rr::VertexShader* const		vertexShader			= (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
668 
669 	const CoordFragmentShader			coordFragmmentShader;
670 	const TextureFragmentShader			textureFragmentShader	(effectiveAccess);
671 	const rr::FragmentShader* const		fragmentShader			= (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
672 
673 	const rr::Renderer					renderer;
674 	const rr::RenderState				renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())));
675 	const rr::RenderTarget				renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
676 
677 	const rr::Program					program(vertexShader, fragmentShader);
678 
679 	rr::VertexAttrib					vertexAttribs[1];
680 	vector<deUint8>						coords;
681 
682 	if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
683 	{
684 		vertexAttribs[0].type			= rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
685 		vertexAttribs[0].size			= 2;
686 		vertexAttribs[0].pointer		= texture.getRefBuffer().getPtr();
687 	}
688 	else
689 	{
690 		de::Random rng(coordSeed);
691 
692 		genRandomCoords(rng, coords, 0, 256*2);
693 
694 		vertexAttribs[0].type			= rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
695 		vertexAttribs[0].size			= 2;
696 		vertexAttribs[0].pointer		= &(coords[0]);
697 	}
698 
699 	if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
700 	{
701 		const rr::PrimitiveList	primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices(texture.getRefBuffer().getPtr(), rr::INDEXTYPE_UINT8));
702 		const rr::DrawCommand	cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
703 
704 		renderer.draw(cmd);
705 	}
706 	else
707 	{
708 		const rr::PrimitiveList	primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, 0);
709 		const rr::DrawCommand	cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
710 
711 		renderer.draw(cmd);
712 	}
713 }
714 
logRendering(TestLog & log,RenderBits renderBits)715 void logRendering (TestLog& log, RenderBits renderBits)
716 {
717 	const struct
718 	{
719 		RenderBits	bit;
720 		const char*	str;
721 	} bitInfos[] =
722 	{
723 		{ RENDERBITS_AS_VERTEX_ARRAY,		"vertex array"		},
724 		{ RENDERBITS_AS_INDEX_ARRAY,		"index array"		},
725 		{ RENDERBITS_AS_VERTEX_TEXTURE,		"vertex texture"	},
726 		{ RENDERBITS_AS_FRAGMENT_TEXTURE,	"fragment texture"	}
727 	};
728 
729 	std::ostringstream	stream;
730 	vector<const char*> usedAs;
731 
732 	DE_ASSERT(renderBits != 0);
733 
734 	for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
735 	{
736 		if (renderBits & bitInfos[infoNdx].bit)
737 			usedAs.push_back(bitInfos[infoNdx].str);
738 	}
739 
740 	stream << "Render using texture buffer as ";
741 
742 	for (int asNdx = 0; asNdx < (int)usedAs.size(); asNdx++)
743 	{
744 		if (asNdx+1 == (int)usedAs.size() && (int)usedAs.size() > 1)
745 			stream << " and ";
746 		else if (asNdx > 0)
747 			stream << ", ";
748 
749 		stream << usedAs[asNdx];
750 	}
751 
752 	stream << ".";
753 
754 	log << TestLog::Message << stream.str() << TestLog::EndMessage;
755 }
756 
render(TestLog & log,glu::RenderContext & renderContext,RenderBits renderBits,de::Random & rng,glu::ShaderProgram & program,glu::TextureBuffer & texture,const tcu::PixelBufferAccess & target)757 void render (TestLog&						log,
758 			 glu::RenderContext&			renderContext,
759 			 RenderBits						renderBits,
760 			 de::Random&					rng,
761 			 glu::ShaderProgram&			program,
762 			 glu::TextureBuffer&			texture,
763 			 const tcu::PixelBufferAccess&	target)
764 {
765 	const tcu::ScopedLogSection	renderSection			(log, "Render Texture buffer", "Render Texture Buffer");
766 	const int					triangleCount			= 8;
767 	const deUint32				coordSeed				= rng.getUint32();
768 	int							maxTextureBufferSize	= 0;
769 
770 	renderContext.getFunctions().getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
771 	GLU_EXPECT_NO_ERROR(renderContext.getFunctions().getError(), "query GL_MAX_TEXTURE_BUFFER_SIZE");
772 	DE_ASSERT(maxTextureBufferSize > 0); // checked in init()
773 
774 	logRendering(log, renderBits);
775 
776 	renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
777 	renderReference(renderBits, coordSeed, triangleCount, texture, maxTextureBufferSize, target);
778 }
779 
verifyScreen(TestLog & log,tcu::ResultCollector & resultCollector,glu::RenderContext & renderContext,const tcu::ConstPixelBufferAccess & referenceTarget)780 void verifyScreen (TestLog&								log,
781 				   tcu::ResultCollector&				resultCollector,
782 				   glu::RenderContext&					renderContext,
783 				   const tcu::ConstPixelBufferAccess&	referenceTarget)
784 {
785 	const tcu::ScopedLogSection	verifySection	(log, "Verify screen contents", "Verify screen contents");
786 	tcu::Surface				screen			(referenceTarget.getWidth(), referenceTarget.getHeight());
787 
788 	glu::readPixels(renderContext, 0, 0, screen.getAccess());
789 
790 	if (!tcu::fuzzyCompare(log, "Result of rendering", "Result of rendering", referenceTarget, screen.getAccess(), 0.05f, tcu::COMPARE_LOG_RESULT))
791 		resultCollector.fail("Rendering failed");
792 }
793 
logImplementationInfo(TestLog & log,glu::RenderContext & renderContext)794 void logImplementationInfo (TestLog& log, glu::RenderContext& renderContext)
795 {
796 	const tcu::ScopedLogSection		section	(log, "Implementation Values", "Implementation Values");
797 	de::UniquePtr<glu::ContextInfo>	info	(glu::ContextInfo::create(renderContext));
798 	const glw::Functions&			gl		= renderContext.getFunctions();
799 
800 	if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)))
801 	{
802 		deInt32 maxTextureSize = 0;
803 
804 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
805 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE)");
806 
807 		log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE : " <<  maxTextureSize << TestLog::EndMessage;
808 	}
809 	else if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer"))
810 	{
811 		{
812 			deInt32 maxTextureSize = 0;
813 
814 			gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
815 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE_EXT)");
816 
817 			log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE_EXT : " <<  maxTextureSize << TestLog::EndMessage;
818 		}
819 
820 		{
821 			deInt32 textureBufferAlignment = 0;
822 
823 			gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &textureBufferAlignment);
824 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)");
825 
826 			log << TestLog::Message << "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT : " <<  textureBufferAlignment << TestLog::EndMessage;
827 		}
828 	}
829 	else
830 		DE_ASSERT(DE_FALSE);
831 }
832 
logTextureInfo(TestLog & log,deUint32 format,size_t bufferSize,size_t offset,size_t size)833 void logTextureInfo (TestLog&	log,
834 					 deUint32	format,
835 					 size_t		bufferSize,
836 					 size_t		offset,
837 					 size_t		size)
838 {
839 	const tcu::ScopedLogSection	section(log, "Texture Info", "Texture Info");
840 
841 	log << TestLog::Message << "Texture format : " << glu::getTextureFormatStr(format) << TestLog::EndMessage;
842 	log << TestLog::Message << "Buffer size : " << bufferSize << TestLog::EndMessage;
843 
844 	if (offset != 0 || size != 0)
845 	{
846 		log << TestLog::Message << "Buffer range offset: " << offset << TestLog::EndMessage;
847 		log << TestLog::Message << "Buffer range size: " << size << TestLog::EndMessage;
848 	}
849 }
850 
runTests(tcu::TestContext & testCtx,glu::RenderContext & renderContext,de::Random & rng,deUint32 format,size_t bufferSize,size_t offset,size_t size,RenderBits preRender,glu::ShaderProgram * preRenderProgram,ModifyBits modifyType,RenderBits postRender,glu::ShaderProgram * postRenderProgram)851 void runTests (tcu::TestContext&	testCtx,
852 			   glu::RenderContext&	renderContext,
853 			   de::Random&			rng,
854 			   deUint32				format,
855 			   size_t				bufferSize,
856 			   size_t				offset,
857 			   size_t				size,
858 			   RenderBits			preRender,
859 			   glu::ShaderProgram*	preRenderProgram,
860 			   ModifyBits			modifyType,
861 			   RenderBits			postRender,
862 			   glu::ShaderProgram*	postRenderProgram)
863 {
864 	const tcu::RenderTarget	renderTarget	(renderContext.getRenderTarget());
865 	const glw::Functions&	gl				= renderContext.getFunctions();
866 
867 	const int				width			= de::min<int>(renderTarget.getWidth(), MAX_VIEWPORT_WIDTH);
868 	const int				height			= de::min<int>(renderTarget.getHeight(), MAX_VIEWPORT_HEIGHT);
869 	const tcu::Vec4			clearColor		(0.25f, 0.5f, 0.75f, 1.0f);
870 
871 	TestLog&				log				= testCtx.getLog();
872 	tcu::ResultCollector	resultCollector	(log);
873 
874 	logImplementationInfo(log, renderContext);
875 	logTextureInfo(log, format, bufferSize, offset, size);
876 
877 	{
878 		tcu::Surface			referenceTarget	(width, height);
879 		vector<deUint8>			bufferData;
880 
881 		genRandomCoords(rng, bufferData, 0, bufferSize);
882 
883 		for (deUint8 i = 0; i < 4; i++)
884 		{
885 			const deUint8 val = extend2BitsToByte(i);
886 
887 			if (val >= offset && val < offset + size)
888 			{
889 				bufferData[val*2 + 0] = (i / 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
890 				bufferData[val*2 + 1] = (i % 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
891 			}
892 		}
893 
894 		{
895 			glu::TextureBuffer texture (renderContext, format, bufferSize, offset, size, &(bufferData[0]));
896 
897 			TCU_CHECK_MSG(width >= MIN_VIEWPORT_WIDTH || height >= MIN_VIEWPORT_HEIGHT, "Too small viewport");
898 
899 			DE_ASSERT(preRender == 0 || preRenderProgram);
900 			DE_ASSERT(postRender == 0 || postRenderProgram);
901 
902 			gl.viewport(0, 0, width, height);
903 			gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
904 			gl.clear(GL_COLOR_BUFFER_BIT);
905 			GLU_EXPECT_NO_ERROR(gl.getError(), "Screen setup failed");
906 
907 			tcu::clear(referenceTarget.getAccess(), clearColor);
908 
909 			texture.upload();
910 
911 			if (preRender != 0)
912 				render(log, renderContext, preRender, rng, *preRenderProgram, texture, referenceTarget.getAccess());
913 
914 			if (modifyType != 0)
915 				modify(log, resultCollector, renderContext, modifyType, rng, texture);
916 
917 			if (postRender != 0)
918 				render(log, renderContext, postRender, rng, *postRenderProgram, texture, referenceTarget.getAccess());
919 		}
920 
921 		verifyScreen(log, resultCollector, renderContext, referenceTarget.getAccess());
922 
923 		resultCollector.setTestContextResult(testCtx);
924 	}
925 }
926 
927 } // anonymous
928 
TextureBufferCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,deUint32 format,size_t bufferSize,size_t offset,size_t size,RenderBits preRender,ModifyBits modify,RenderBits postRender,const char * name,const char * description)929 TextureBufferCase::TextureBufferCase (tcu::TestContext&		testCtx,
930 									  glu::RenderContext&	renderCtx,
931 									  deUint32				format,
932 									  size_t				bufferSize,
933 									  size_t				offset,
934 									  size_t				size,
935 									  RenderBits			preRender,
936 									  ModifyBits			modify,
937 									  RenderBits			postRender,
938 									  const char*			name,
939 									  const char*			description)
940 	: tcu::TestCase				(testCtx, name, description)
941 	, m_renderCtx				(renderCtx)
942 	, m_format					(format)
943 	, m_bufferSize				(bufferSize)
944 	, m_offset					(offset)
945 	, m_size					(size)
946 
947 	, m_preRender				(preRender)
948 	, m_modify					(modify)
949 	, m_postRender				(postRender)
950 
951 	, m_preRenderProgram		(DE_NULL)
952 	, m_postRenderProgram		(DE_NULL)
953 {
954 }
955 
~TextureBufferCase(void)956 TextureBufferCase::~TextureBufferCase (void)
957 {
958 	TextureBufferCase::deinit();
959 }
960 
init(void)961 void TextureBufferCase::init (void)
962 {
963 	de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(m_renderCtx));
964 
965 	if (!glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
966 		&& !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
967 		throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
968 
969 	{
970 		const int maxTextureBufferSize = info->getInt(GL_MAX_TEXTURE_BUFFER_SIZE);
971 		if (maxTextureBufferSize <= 0)
972 			TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");
973 	}
974 
975 	if (m_preRender != 0)
976 	{
977 		TestLog&					log			= m_testCtx.getLog();
978 		const char* const			sectionName	= (m_postRender != 0 ? "Primary render program" : "Render program");
979 		const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
980 
981 		m_preRenderProgram = createRenderProgram(m_renderCtx, m_preRender);
982 		m_testCtx.getLog() << (*m_preRenderProgram);
983 
984 		TCU_CHECK(m_preRenderProgram->isOk());
985 	}
986 
987 	if (m_postRender != 0)
988 	{
989 		// Reusing program
990 		if (m_preRender == m_postRender)
991 		{
992 			m_postRenderProgram = m_preRenderProgram;
993 		}
994 		else
995 		{
996 			TestLog&					log			= m_testCtx.getLog();
997 			const char* const			sectionName	= (m_preRender!= 0 ? "Secondary render program" : "Render program");
998 			const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
999 
1000 			m_postRenderProgram = createRenderProgram(m_renderCtx, m_postRender);
1001 			m_testCtx.getLog() << (*m_postRenderProgram);
1002 
1003 			TCU_CHECK(m_postRenderProgram->isOk());
1004 		}
1005 	}
1006 }
1007 
deinit(void)1008 void TextureBufferCase::deinit (void)
1009 {
1010 	if (m_preRenderProgram == m_postRenderProgram)
1011 		m_postRenderProgram = DE_NULL;
1012 
1013 	delete m_preRenderProgram;
1014 	m_preRenderProgram = DE_NULL;
1015 
1016 	delete m_postRenderProgram;
1017 	m_postRenderProgram = DE_NULL;
1018 }
1019 
iterate(void)1020 tcu::TestCase::IterateResult TextureBufferCase::iterate (void)
1021 {
1022 	de::Random	rng		(deInt32Hash(deStringHash(getName())));
1023 	size_t		offset;
1024 
1025 	if (m_offset != 0)
1026 	{
1027 		const glw::Functions&	gl			= m_renderCtx.getFunctions();
1028 		deInt32					alignment	= 0;
1029 
1030 		gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
1031 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)");
1032 
1033 		offset = m_offset * alignment;
1034 	}
1035 	else
1036 		offset = 0;
1037 
1038 	runTests(m_testCtx, m_renderCtx, rng, m_format, m_bufferSize, offset, m_size, m_preRender, m_preRenderProgram, m_modify, m_postRender, m_postRenderProgram);
1039 
1040 	return STOP;
1041 }
1042 
1043 } // gls
1044 } // deqp
1045