• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
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 Reference Rendering Context.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "sglrReferenceContext.hpp"
25 #include "sglrReferenceUtils.hpp"
26 #include "sglrShaderProgram.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuMatrix.hpp"
29 #include "tcuMatrixUtil.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "gluDefs.hpp"
32 #include "gluTextureUtil.hpp"
33 #include "gluContextInfo.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deMemory.h"
37 #include "rrFragmentOperations.hpp"
38 #include "rrRenderer.hpp"
39 
40 namespace sglr
41 {
42 
43 using std::vector;
44 using std::map;
45 
46 using tcu::Vec2;
47 using tcu::Vec3;
48 using tcu::Vec4;
49 using tcu::IVec2;
50 using tcu::IVec4;
51 using tcu::RGBA;
52 
53 // Reference context implementation
54 using namespace rc;
55 
56 using tcu::TextureFormat;
57 using tcu::PixelBufferAccess;
58 using tcu::ConstPixelBufferAccess;
59 
60 // Utilities for ReferenceContext
61 #define RC_RET_VOID
62 
63 #define RC_ERROR_RET(ERR, RET)			\
64 do {									\
65 	setError(ERR);						\
66 	return RET;							\
67 } while (deGetFalse())
68 
69 #define RC_IF_ERROR(COND, ERR, RET)		\
70 do {									\
71 	if (COND)							\
72 		RC_ERROR_RET(ERR, RET);			\
73 } while (deGetFalse())
74 
nullAccess(void)75 static inline tcu::PixelBufferAccess nullAccess (void)
76 {
77 	return tcu::PixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), 0, 0, 0, DE_NULL);
78 }
79 
isEmpty(const tcu::ConstPixelBufferAccess & access)80 static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
81 {
82 	return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
83 }
84 
isEmpty(const rr::MultisampleConstPixelBufferAccess & access)85 static inline bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
86 {
87 	return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
88 }
89 
isEmpty(const IVec4 & rect)90 static inline bool isEmpty (const IVec4& rect)
91 {
92 	return rect.z() == 0 || rect.w() == 0;
93 }
94 
getNumMipLevels1D(int size)95 inline int getNumMipLevels1D (int size)
96 {
97 	return deLog2Floor32(size)+1;
98 }
99 
getNumMipLevels2D(int width,int height)100 inline int getNumMipLevels2D (int width, int height)
101 {
102 	return deLog2Floor32(de::max(width, height))+1;
103 }
104 
getNumMipLevels3D(int width,int height,int depth)105 inline int getNumMipLevels3D (int width, int height, int depth)
106 {
107 	return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
108 }
109 
getMipLevelSize(int baseLevelSize,int levelNdx)110 inline int getMipLevelSize (int baseLevelSize, int levelNdx)
111 {
112 	return de::max(baseLevelSize >> levelNdx, 1);
113 }
114 
isMipmapFilter(const tcu::Sampler::FilterMode mode)115 inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
116 {
117 	return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
118 }
119 
texTargetToFace(Framebuffer::TexTarget target)120 static tcu::CubeFace texTargetToFace (Framebuffer::TexTarget target)
121 {
122 	switch (target)
123 	{
124 		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X:	return tcu::CUBEFACE_NEGATIVE_X;
125 		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X:	return tcu::CUBEFACE_POSITIVE_X;
126 		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y:	return tcu::CUBEFACE_NEGATIVE_Y;
127 		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y:	return tcu::CUBEFACE_POSITIVE_Y;
128 		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z:	return tcu::CUBEFACE_NEGATIVE_Z;
129 		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z:	return tcu::CUBEFACE_POSITIVE_Z;
130 		default:											return tcu::CUBEFACE_LAST;
131 	}
132 }
133 
texLayeredTypeToTarget(Texture::Type type)134 static Framebuffer::TexTarget texLayeredTypeToTarget (Texture::Type type)
135 {
136 	switch (type)
137 	{
138 		case Texture::TYPE_2D_ARRAY:		return Framebuffer::TEXTARGET_2D_ARRAY;
139 		case Texture::TYPE_3D:				return Framebuffer::TEXTARGET_3D;
140 		case Texture::TYPE_CUBE_MAP_ARRAY:	return Framebuffer::TEXTARGET_CUBE_MAP_ARRAY;
141 		default:							return Framebuffer::TEXTARGET_LAST;
142 	}
143 }
144 
mapGLCubeFace(deUint32 face)145 static tcu::CubeFace mapGLCubeFace (deUint32 face)
146 {
147 	switch (face)
148 	{
149 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return tcu::CUBEFACE_NEGATIVE_X;
150 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return tcu::CUBEFACE_POSITIVE_X;
151 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return tcu::CUBEFACE_NEGATIVE_Y;
152 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return tcu::CUBEFACE_POSITIVE_Y;
153 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return tcu::CUBEFACE_NEGATIVE_Z;
154 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return tcu::CUBEFACE_POSITIVE_Z;
155 		default:								return tcu::CUBEFACE_LAST;
156 	}
157 }
158 
toTextureFormat(const tcu::PixelFormat & pixelFmt)159 tcu::TextureFormat toTextureFormat (const tcu::PixelFormat& pixelFmt)
160 {
161 	static const struct
162 	{
163 		tcu::PixelFormat	pixelFmt;
164 		tcu::TextureFormat	texFmt;
165 	} pixelFormatMap[] =
166 	{
167 		{ tcu::PixelFormat(8,8,8,8),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8)			},
168 		{ tcu::PixelFormat(8,8,8,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_INT8)			},
169 		{ tcu::PixelFormat(4,4,4,4),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_4444)	},
170 		{ tcu::PixelFormat(5,5,5,1),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_5551)	},
171 		{ tcu::PixelFormat(5,6,5,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_SHORT_565)	}
172 	};
173 
174 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
175 	{
176 		if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
177 			return pixelFormatMap[ndx].texFmt;
178 	}
179 
180 	TCU_FAIL("Can't map pixel format to texture format");
181 }
182 
toNonSRGBFormat(const tcu::TextureFormat & fmt)183 tcu::TextureFormat toNonSRGBFormat (const tcu::TextureFormat& fmt)
184 {
185 	switch (fmt.order)
186 	{
187 		case tcu::TextureFormat::sRGB:
188 			return tcu::TextureFormat(tcu::TextureFormat::RGB,	fmt.type);
189 		case tcu::TextureFormat::sRGBA:
190 			return tcu::TextureFormat(tcu::TextureFormat::RGBA,	fmt.type);
191 		default:
192 			return fmt;
193 	}
194 }
195 
getDepthFormat(int depthBits)196 tcu::TextureFormat getDepthFormat (int depthBits)
197 {
198 	switch (depthBits)
199 	{
200 		case 8:		return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
201 		case 16:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
202 		case 24:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
203 		case 32:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
204 		default:
205 			TCU_FAIL("Can't map depth buffer format");
206 	}
207 }
208 
getStencilFormat(int stencilBits)209 tcu::TextureFormat getStencilFormat (int stencilBits)
210 {
211 	switch (stencilBits)
212 	{
213 		case 8:		return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
214 		case 16:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
215 		case 24:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
216 		case 32:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
217 		default:
218 			TCU_FAIL("Can't map depth buffer format");
219 	}
220 }
221 
intersect(const tcu::IVec4 & a,const tcu::IVec4 & b)222 static inline tcu::IVec4 intersect (const tcu::IVec4& a, const tcu::IVec4& b)
223 {
224 	int		x0	= de::max(a.x(), b.x());
225 	int		y0	= de::max(a.y(), b.y());
226 	int		x1	= de::min(a.x()+a.z(), b.x()+b.z());
227 	int		y1	= de::min(a.y()+a.w(), b.y()+b.w());
228 	int		w	= de::max(0, x1-x0);
229 	int		h	= de::max(0, y1-y0);
230 
231 	return tcu::IVec4(x0, y0, w, h);
232 }
233 
getBufferRect(const rr::MultisampleConstPixelBufferAccess & access)234 static inline tcu::IVec4 getBufferRect (const rr::MultisampleConstPixelBufferAccess& access)
235 {
236 	return tcu::IVec4(0, 0, access.raw().getHeight(), access.raw().getDepth());
237 }
238 
ReferenceContextLimits(const glu::RenderContext & renderCtx)239 ReferenceContextLimits::ReferenceContextLimits (const glu::RenderContext& renderCtx)
240 	: contextType				(renderCtx.getType())
241 	, maxTextureImageUnits		(0)
242 	, maxTexture2DSize			(0)
243 	, maxTextureCubeSize		(0)
244 	, maxTexture2DArrayLayers	(0)
245 	, maxTexture3DSize			(0)
246 	, maxRenderbufferSize		(0)
247 	, maxVertexAttribs			(0)
248 	, subpixelBits				(0)
249 {
250 	const glw::Functions& gl = renderCtx.getFunctions();
251 
252 	// When the OpenGL ES's major version bigger than 3, and the expect context version is 3,
253 	// we need query the real GL context version and update the real version to reference context.
254 	if (glu::IsES3Compatible(gl) && isES2Context(contextType))
255 	{
256 		int majorVersion = contextType.getMajorVersion();
257 		int minorVersion = contextType.getMinorVersion();
258 		gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
259 		gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
260 		contextType.setAPI(glu::ApiType::es(majorVersion, minorVersion));
261 	}
262 
263 	gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,		&maxTextureImageUnits);
264 	gl.getIntegerv(GL_MAX_TEXTURE_SIZE,				&maxTexture2DSize);
265 	gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE,	&maxTextureCubeSize);
266 	gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE,		&maxRenderbufferSize);
267 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS,			&maxVertexAttribs);
268 	gl.getIntegerv(GL_SUBPIXEL_BITS,				&subpixelBits);
269 
270 	if (contextSupports(contextType, glu::ApiType::es(3,0)) || glu::isContextTypeGLCore(contextType))
271 	{
272 		gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS,	&maxTexture2DArrayLayers);
273 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE,		&maxTexture3DSize);
274 	}
275 
276 	// Limit texture sizes to supported values
277 	maxTexture2DSize	= de::min(maxTexture2DSize,		(int)MAX_TEXTURE_SIZE);
278 	maxTextureCubeSize	= de::min(maxTextureCubeSize,	(int)MAX_TEXTURE_SIZE);
279 	maxTexture3DSize	= de::min(maxTexture3DSize,		(int)MAX_TEXTURE_SIZE);
280 
281 	GLU_EXPECT_NO_ERROR(gl.getError(), GL_NO_ERROR);
282 
283 	// \todo [pyry] Figure out following things:
284 	// + supported fbo configurations
285 	// ...
286 
287 	// \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
288 	addExtension("GL_EXT_color_buffer_half_float");
289 	addExtension("GL_EXT_color_buffer_float");
290 
291 	if (contextSupports(contextType, glu::ApiType::es(3,1)))
292 		addExtension("GL_EXT_texture_cube_map_array");
293 }
294 
addExtension(const char * extension)295 void ReferenceContextLimits::addExtension (const char* extension)
296 {
297 	extensionList.push_back(extension);
298 
299 	if (!extensionStr.empty())
300 		extensionStr += " ";
301 	extensionStr += extension;
302 }
303 
ReferenceContextBuffers(const tcu::PixelFormat & colorBits,int depthBits,int stencilBits,int width,int height,int samples)304 ReferenceContextBuffers::ReferenceContextBuffers (const tcu::PixelFormat& colorBits, int depthBits, int stencilBits, int width, int height, int samples)
305 {
306 	m_colorbuffer.setStorage(toTextureFormat(colorBits), samples, width, height);
307 
308 	if (depthBits > 0)
309 		m_depthbuffer.setStorage(getDepthFormat(depthBits), samples, width, height);
310 
311 	if (stencilBits > 0)
312 		m_stencilbuffer.setStorage(getStencilFormat(stencilBits), samples, width, height);
313 }
314 
StencilState(void)315 ReferenceContext::StencilState::StencilState (void)
316 	: func				(GL_ALWAYS)
317 	, ref				(0)
318 	, opMask			(~0u)
319 	, opStencilFail		(GL_KEEP)
320 	, opDepthFail		(GL_KEEP)
321 	, opDepthPass		(GL_KEEP)
322 	, writeMask			(~0u)
323 {
324 }
325 
ReferenceContext(const ReferenceContextLimits & limits,const rr::MultisamplePixelBufferAccess & colorbuffer,const rr::MultisamplePixelBufferAccess & depthbuffer,const rr::MultisamplePixelBufferAccess & stencilbuffer)326 ReferenceContext::ReferenceContext (const ReferenceContextLimits& limits, const rr::MultisamplePixelBufferAccess& colorbuffer, const rr::MultisamplePixelBufferAccess& depthbuffer, const rr::MultisamplePixelBufferAccess& stencilbuffer)
327 	: Context							(limits.contextType)
328 	, m_limits							(limits)
329 	, m_defaultColorbuffer				(colorbuffer)
330 	, m_defaultDepthbuffer				(depthbuffer)
331 	, m_defaultStencilbuffer			(stencilbuffer)
332 	, m_clientVertexArray				(0, m_limits.maxVertexAttribs)
333 
334 	, m_viewport						(0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth())
335 
336 	, m_activeTexture					(0)
337 	, m_textureUnits					(m_limits.maxTextureImageUnits)
338 	, m_emptyTex1D						()
339 	, m_emptyTex2D						(isES2Context(limits.contextType))
340 	, m_emptyTexCube					(!isES2Context(limits.contextType))
341 	, m_emptyTex2DArray					()
342 	, m_emptyTex3D						()
343 	, m_emptyTexCubeArray				()
344 
345 	, m_pixelUnpackRowLength			(0)
346 	, m_pixelUnpackSkipRows				(0)
347 	, m_pixelUnpackSkipPixels			(0)
348 	, m_pixelUnpackImageHeight			(0)
349 	, m_pixelUnpackSkipImages			(0)
350 	, m_pixelUnpackAlignment			(4)
351 	, m_pixelPackAlignment				(4)
352 
353 	, m_readFramebufferBinding			(DE_NULL)
354 	, m_drawFramebufferBinding			(DE_NULL)
355 	, m_renderbufferBinding				(DE_NULL)
356 	, m_vertexArrayBinding				(DE_NULL)
357 	, m_currentProgram					(DE_NULL)
358 
359 	, m_arrayBufferBinding				(DE_NULL)
360 	, m_pixelPackBufferBinding			(DE_NULL)
361 	, m_pixelUnpackBufferBinding		(DE_NULL)
362 	, m_transformFeedbackBufferBinding	(DE_NULL)
363 	, m_uniformBufferBinding			(DE_NULL)
364 	, m_copyReadBufferBinding			(DE_NULL)
365 	, m_copyWriteBufferBinding			(DE_NULL)
366 	, m_drawIndirectBufferBinding		(DE_NULL)
367 
368 	, m_clearColor						(0.0f, 0.0f, 0.0f, 0.0f)
369 	, m_clearDepth						(1.0f)
370 	, m_clearStencil					(0)
371 	, m_scissorEnabled					(false)
372 	, m_scissorBox						(m_viewport)
373 	, m_stencilTestEnabled				(false)
374 	, m_depthTestEnabled				(false)
375 	, m_depthFunc						(GL_LESS)
376 	, m_depthRangeNear					(0.0f)
377 	, m_depthRangeFar					(1.0f)
378 	, m_polygonOffsetFactor				(0.0f)
379 	, m_polygonOffsetUnits				(0.0f)
380 	, m_polygonOffsetFillEnabled		(false)
381 	, m_provokingFirstVertexConvention	(false)
382 	, m_blendEnabled					(false)
383 	, m_blendModeRGB					(GL_FUNC_ADD)
384 	, m_blendModeAlpha					(GL_FUNC_ADD)
385 	, m_blendFactorSrcRGB				(GL_ONE)
386 	, m_blendFactorDstRGB				(GL_ZERO)
387 	, m_blendFactorSrcAlpha				(GL_ONE)
388 	, m_blendFactorDstAlpha				(GL_ZERO)
389 	, m_blendColor						(0.0f, 0.0f, 0.0f, 0.0f)
390 	, m_sRGBUpdateEnabled				(true)
391 	, m_depthClampEnabled				(false)
392 	, m_colorMask						(true, true, true, true)
393 	, m_depthMask						(true)
394 	, m_currentAttribs					(m_limits.maxVertexAttribs, rr::GenericVec4(tcu::Vec4(0, 0, 0, 1)))
395 	, m_lineWidth						(1.0f)
396 	, m_primitiveRestartFixedIndex		(false)
397 	, m_primitiveRestartSettableIndex	(false)
398 	, m_primitiveRestartIndex			(0)
399 
400 	, m_lastError						(GL_NO_ERROR)
401 {
402 	// Create empty textures to be used when texture objects are incomplete.
403 	m_emptyTex1D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
404 	m_emptyTex1D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
405 	m_emptyTex1D.getSampler().minFilter	= tcu::Sampler::NEAREST;
406 	m_emptyTex1D.getSampler().magFilter	= tcu::Sampler::NEAREST;
407 	m_emptyTex1D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1);
408 	m_emptyTex1D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
409 	m_emptyTex1D.updateView(tcu::Sampler::MODE_LAST);
410 
411 	m_emptyTex2D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
412 	m_emptyTex2D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
413 	m_emptyTex2D.getSampler().minFilter	= tcu::Sampler::NEAREST;
414 	m_emptyTex2D.getSampler().magFilter	= tcu::Sampler::NEAREST;
415 	m_emptyTex2D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
416 	m_emptyTex2D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
417 	m_emptyTex2D.updateView(tcu::Sampler::MODE_LAST);
418 
419 	m_emptyTexCube.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
420 	m_emptyTexCube.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
421 	m_emptyTexCube.getSampler().minFilter	= tcu::Sampler::NEAREST;
422 	m_emptyTexCube.getSampler().magFilter	= tcu::Sampler::NEAREST;
423 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
424 	{
425 		m_emptyTexCube.allocFace(0, (tcu::CubeFace)face, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
426 		m_emptyTexCube.getFace(0, (tcu::CubeFace)face).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
427 	}
428 	m_emptyTexCube.updateView(tcu::Sampler::MODE_LAST);
429 
430 	m_emptyTex2DArray.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
431 	m_emptyTex2DArray.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
432 	m_emptyTex2DArray.getSampler().minFilter	= tcu::Sampler::NEAREST;
433 	m_emptyTex2DArray.getSampler().magFilter	= tcu::Sampler::NEAREST;
434 	m_emptyTex2DArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
435 	m_emptyTex2DArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
436 	m_emptyTex2DArray.updateView(tcu::Sampler::MODE_LAST);
437 
438 	m_emptyTex3D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
439 	m_emptyTex3D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
440 	m_emptyTex3D.getSampler().wrapR		= tcu::Sampler::CLAMP_TO_EDGE;
441 	m_emptyTex3D.getSampler().minFilter	= tcu::Sampler::NEAREST;
442 	m_emptyTex3D.getSampler().magFilter	= tcu::Sampler::NEAREST;
443 	m_emptyTex3D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
444 	m_emptyTex3D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
445 	m_emptyTex3D.updateView(tcu::Sampler::MODE_LAST);
446 
447 	m_emptyTexCubeArray.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
448 	m_emptyTexCubeArray.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
449 	m_emptyTexCubeArray.getSampler().minFilter	= tcu::Sampler::NEAREST;
450 	m_emptyTexCubeArray.getSampler().magFilter	= tcu::Sampler::NEAREST;
451 	m_emptyTexCubeArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 6);
452 	for (int faceNdx = 0; faceNdx < 6; faceNdx++)
453 		m_emptyTexCubeArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, faceNdx);
454 	m_emptyTexCubeArray.updateView(tcu::Sampler::MODE_LAST);
455 
456 	for (int unitNdx = 0; unitNdx < m_limits.maxTextureImageUnits; unitNdx++)
457 		m_textureUnits[unitNdx].defaultCubeTex.getSampler().seamlessCubeMap = !isES2Context(limits.contextType);
458 
459 	if (glu::isContextTypeGLCore(getType()))
460 		m_sRGBUpdateEnabled = false;
461 }
462 
~ReferenceContext(void)463 ReferenceContext::~ReferenceContext (void)
464 {
465 	// Destroy all objects -- verifies that ref counting works
466 	{
467 		vector<VertexArray*> vertexArrays;
468 		m_vertexArrays.getAll(vertexArrays);
469 		for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
470 			deleteVertexArray(*i);
471 
472 		DE_ASSERT(m_clientVertexArray.getRefCount() == 1);
473 	}
474 
475 	{
476 		vector<Texture*> textures;
477 		m_textures.getAll(textures);
478 		for (vector<Texture*>::iterator i = textures.begin(); i != textures.end(); i++)
479 			deleteTexture(*i);
480 	}
481 
482 	{
483 		vector<Framebuffer*> framebuffers;
484 		m_framebuffers.getAll(framebuffers);
485 		for (vector<Framebuffer*>::iterator i = framebuffers.begin(); i != framebuffers.end(); i++)
486 			deleteFramebuffer(*i);
487 	}
488 
489 	{
490 		vector<Renderbuffer*> renderbuffers;
491 		m_renderbuffers.getAll(renderbuffers);
492 		for (vector<Renderbuffer*>::iterator i = renderbuffers.begin(); i != renderbuffers.end(); i++)
493 			deleteRenderbuffer(*i);
494 	}
495 
496 	{
497 		vector<DataBuffer*> buffers;
498 		m_buffers.getAll(buffers);
499 		for (vector<DataBuffer*>::iterator i = buffers.begin(); i != buffers.end(); i++)
500 			deleteBuffer(*i);
501 	}
502 
503 	{
504 		vector<ShaderProgramObjectContainer*> programs;
505 		m_programs.getAll(programs);
506 		for (vector<ShaderProgramObjectContainer*>::iterator i = programs.begin(); i != programs.end(); i++)
507 			deleteProgramObject(*i);
508 	}
509 }
510 
activeTexture(deUint32 texture)511 void ReferenceContext::activeTexture (deUint32 texture)
512 {
513 	if (deInBounds32(texture, GL_TEXTURE0, GL_TEXTURE0 + (deUint32)m_textureUnits.size()))
514 		m_activeTexture = texture - GL_TEXTURE0;
515 	else
516 		setError(GL_INVALID_ENUM);
517 }
518 
setTex1DBinding(int unitNdx,Texture1D * texture)519 void ReferenceContext::setTex1DBinding (int unitNdx, Texture1D* texture)
520 {
521 	if (m_textureUnits[unitNdx].tex1DBinding)
522 	{
523 		m_textures.releaseReference(m_textureUnits[unitNdx].tex1DBinding);
524 		m_textureUnits[unitNdx].tex1DBinding = DE_NULL;
525 	}
526 
527 	if (texture)
528 	{
529 		m_textures.acquireReference(texture);
530 		m_textureUnits[unitNdx].tex1DBinding = texture;
531 	}
532 }
533 
setTex2DBinding(int unitNdx,Texture2D * texture)534 void ReferenceContext::setTex2DBinding (int unitNdx, Texture2D* texture)
535 {
536 	if (m_textureUnits[unitNdx].tex2DBinding)
537 	{
538 		m_textures.releaseReference(m_textureUnits[unitNdx].tex2DBinding);
539 		m_textureUnits[unitNdx].tex2DBinding = DE_NULL;
540 	}
541 
542 	if (texture)
543 	{
544 		m_textures.acquireReference(texture);
545 		m_textureUnits[unitNdx].tex2DBinding = texture;
546 	}
547 }
548 
setTexCubeBinding(int unitNdx,TextureCube * texture)549 void ReferenceContext::setTexCubeBinding (int unitNdx, TextureCube* texture)
550 {
551 	if (m_textureUnits[unitNdx].texCubeBinding)
552 	{
553 		m_textures.releaseReference(m_textureUnits[unitNdx].texCubeBinding);
554 		m_textureUnits[unitNdx].texCubeBinding = DE_NULL;
555 	}
556 
557 	if (texture)
558 	{
559 		m_textures.acquireReference(texture);
560 		m_textureUnits[unitNdx].texCubeBinding = texture;
561 	}
562 }
563 
setTex2DArrayBinding(int unitNdx,Texture2DArray * texture)564 void ReferenceContext::setTex2DArrayBinding (int unitNdx, Texture2DArray* texture)
565 {
566 	if (m_textureUnits[unitNdx].tex2DArrayBinding)
567 	{
568 		m_textures.releaseReference(m_textureUnits[unitNdx].tex2DArrayBinding);
569 		m_textureUnits[unitNdx].tex2DArrayBinding = DE_NULL;
570 	}
571 
572 	if (texture)
573 	{
574 		m_textures.acquireReference(texture);
575 		m_textureUnits[unitNdx].tex2DArrayBinding = texture;
576 	}
577 }
578 
setTex3DBinding(int unitNdx,Texture3D * texture)579 void ReferenceContext::setTex3DBinding (int unitNdx, Texture3D* texture)
580 {
581 	if (m_textureUnits[unitNdx].tex3DBinding)
582 	{
583 		m_textures.releaseReference(m_textureUnits[unitNdx].tex3DBinding);
584 		m_textureUnits[unitNdx].tex3DBinding = DE_NULL;
585 	}
586 
587 	if (texture)
588 	{
589 		m_textures.acquireReference(texture);
590 		m_textureUnits[unitNdx].tex3DBinding = texture;
591 	}
592 }
593 
setTexCubeArrayBinding(int unitNdx,TextureCubeArray * texture)594 void ReferenceContext::setTexCubeArrayBinding (int unitNdx, TextureCubeArray* texture)
595 {
596 	if (m_textureUnits[unitNdx].texCubeArrayBinding)
597 	{
598 		m_textures.releaseReference(m_textureUnits[unitNdx].texCubeArrayBinding);
599 		m_textureUnits[unitNdx].texCubeArrayBinding = DE_NULL;
600 	}
601 
602 	if (texture)
603 	{
604 		m_textures.acquireReference(texture);
605 		m_textureUnits[unitNdx].texCubeArrayBinding = texture;
606 	}
607 }
608 
bindTexture(deUint32 target,deUint32 texture)609 void ReferenceContext::bindTexture (deUint32 target, deUint32 texture)
610 {
611 	int unitNdx = m_activeTexture;
612 
613 	RC_IF_ERROR(target != GL_TEXTURE_1D				&&
614 				target != GL_TEXTURE_2D				&&
615 				target != GL_TEXTURE_CUBE_MAP		&&
616 				target != GL_TEXTURE_2D_ARRAY		&&
617 				target != GL_TEXTURE_3D				&&
618 				target != GL_TEXTURE_CUBE_MAP_ARRAY,
619 				GL_INVALID_ENUM, RC_RET_VOID);
620 
621 	RC_IF_ERROR(glu::isContextTypeES(m_limits.contextType) && (target == GL_TEXTURE_1D), GL_INVALID_ENUM, RC_RET_VOID);
622 
623 	if (texture == 0)
624 	{
625 		// Clear binding.
626 		switch (target)
627 		{
628 			case GL_TEXTURE_1D:				setTex1DBinding			(unitNdx, DE_NULL);	break;
629 			case GL_TEXTURE_2D:				setTex2DBinding			(unitNdx, DE_NULL);	break;
630 			case GL_TEXTURE_CUBE_MAP:		setTexCubeBinding		(unitNdx, DE_NULL);	break;
631 			case GL_TEXTURE_2D_ARRAY:		setTex2DArrayBinding	(unitNdx, DE_NULL);	break;
632 			case GL_TEXTURE_3D:				setTex3DBinding			(unitNdx, DE_NULL);	break;
633 			case GL_TEXTURE_CUBE_MAP_ARRAY:	setTexCubeArrayBinding	(unitNdx, DE_NULL);	break;
634 			default:
635 				DE_ASSERT(false);
636 		}
637 	}
638 	else
639 	{
640 		Texture* texObj = m_textures.find(texture);
641 
642 		if (texObj)
643 		{
644 			// Validate type.
645 			Texture::Type expectedType = Texture::TYPE_LAST;
646 			switch (target)
647 			{
648 				case GL_TEXTURE_1D:				expectedType = Texture::TYPE_1D;				break;
649 				case GL_TEXTURE_2D:				expectedType = Texture::TYPE_2D;				break;
650 				case GL_TEXTURE_CUBE_MAP:		expectedType = Texture::TYPE_CUBE_MAP;			break;
651 				case GL_TEXTURE_2D_ARRAY:		expectedType = Texture::TYPE_2D_ARRAY;			break;
652 				case GL_TEXTURE_3D:				expectedType = Texture::TYPE_3D;				break;
653 				case GL_TEXTURE_CUBE_MAP_ARRAY:	expectedType = Texture::TYPE_CUBE_MAP_ARRAY;	break;
654 				default:
655 					DE_ASSERT(false);
656 			}
657 			RC_IF_ERROR(texObj->getType() != expectedType, GL_INVALID_OPERATION, RC_RET_VOID);
658 		}
659 		else
660 		{
661 			// New texture object.
662 			bool seamlessCubeMap = !isES2Context(m_limits.contextType);
663 			switch (target)
664 			{
665 				case GL_TEXTURE_1D:				texObj = new Texture1D			(texture);					break;
666 				case GL_TEXTURE_2D:				texObj = new Texture2D			(texture);					break;
667 				case GL_TEXTURE_CUBE_MAP:		texObj = new TextureCube		(texture, seamlessCubeMap);	break;
668 				case GL_TEXTURE_2D_ARRAY:		texObj = new Texture2DArray		(texture);					break;
669 				case GL_TEXTURE_3D:				texObj = new Texture3D			(texture);					break;
670 				case GL_TEXTURE_CUBE_MAP_ARRAY:	texObj = new TextureCubeArray	(texture);					break;
671 				default:
672 					DE_ASSERT(false);
673 			}
674 
675 			m_textures.insert(texObj);
676 		}
677 
678 		switch (target)
679 		{
680 			case GL_TEXTURE_1D:				setTex1DBinding			(unitNdx, static_cast<Texture1D*>			(texObj));	break;
681 			case GL_TEXTURE_2D:				setTex2DBinding			(unitNdx, static_cast<Texture2D*>			(texObj));	break;
682 			case GL_TEXTURE_CUBE_MAP:		setTexCubeBinding		(unitNdx, static_cast<TextureCube*>			(texObj));	break;
683 			case GL_TEXTURE_2D_ARRAY:		setTex2DArrayBinding	(unitNdx, static_cast<Texture2DArray*>		(texObj));	break;
684 			case GL_TEXTURE_3D:				setTex3DBinding			(unitNdx, static_cast<Texture3D*>			(texObj));	break;
685 			case GL_TEXTURE_CUBE_MAP_ARRAY:	setTexCubeArrayBinding	(unitNdx, static_cast<TextureCubeArray*>	(texObj));	break;
686 			default:
687 				DE_ASSERT(false);
688 		}
689 	}
690 }
691 
genTextures(int numTextures,deUint32 * textures)692 void ReferenceContext::genTextures (int numTextures, deUint32* textures)
693 {
694 	while (numTextures--)
695 		*textures++ = m_textures.allocateName();
696 }
697 
deleteTextures(int numTextures,const deUint32 * textures)698 void ReferenceContext::deleteTextures (int numTextures, const deUint32* textures)
699 {
700 	for (int i = 0; i < numTextures; i++)
701 	{
702 		deUint32	name		= textures[i];
703 		Texture*	texture		= name ? m_textures.find(name) : DE_NULL;
704 
705 		if (texture)
706 			deleteTexture(texture);
707 	}
708 }
709 
deleteTexture(Texture * texture)710 void ReferenceContext::deleteTexture (Texture* texture)
711 {
712 	// Unbind from context
713 	for (int unitNdx = 0; unitNdx < (int)m_textureUnits.size(); unitNdx++)
714 	{
715 		if (m_textureUnits[unitNdx].tex1DBinding				== texture)	setTex1DBinding			(unitNdx, DE_NULL);
716 		else if (m_textureUnits[unitNdx].tex2DBinding			== texture)	setTex2DBinding			(unitNdx, DE_NULL);
717 		else if (m_textureUnits[unitNdx].texCubeBinding			== texture)	setTexCubeBinding		(unitNdx, DE_NULL);
718 		else if (m_textureUnits[unitNdx].tex2DArrayBinding		== texture)	setTex2DArrayBinding	(unitNdx, DE_NULL);
719 		else if (m_textureUnits[unitNdx].tex3DBinding			== texture)	setTex3DBinding			(unitNdx, DE_NULL);
720 		else if (m_textureUnits[unitNdx].texCubeArrayBinding	== texture)	setTexCubeArrayBinding	(unitNdx, DE_NULL);
721 	}
722 
723 	// Unbind from currently bound framebuffers
724 	for (int ndx = 0; ndx < 2; ndx++)
725 	{
726 		rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
727 		if (framebufferBinding)
728 		{
729 			int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
730 								+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
731 
732 			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
733 			{
734 				Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
735 				if (attachment.name == texture->getName())
736 				{
737 					for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
738 						releaseFboAttachmentReference(attachment);
739 					attachment = Framebuffer::Attachment();
740 				}
741 			}
742 		}
743 	}
744 
745 	DE_ASSERT(texture->getRefCount() == 1);
746 	m_textures.releaseReference(texture);
747 }
748 
bindFramebuffer(deUint32 target,deUint32 name)749 void ReferenceContext::bindFramebuffer (deUint32 target, deUint32 name)
750 {
751 	Framebuffer* fbo = DE_NULL;
752 
753 	RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
754 				target != GL_DRAW_FRAMEBUFFER	&&
755 				target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
756 
757 	if (name != 0)
758 	{
759 		// Find or create framebuffer object.
760 		fbo = m_framebuffers.find(name);
761 		if (!fbo)
762 		{
763 			fbo = new Framebuffer(name);
764 			m_framebuffers.insert(fbo);
765 		}
766 	}
767 
768 	for (int ndx = 0; ndx < 2; ndx++)
769 	{
770 		deUint32			bindingTarget	= ndx ? GL_DRAW_FRAMEBUFFER			: GL_READ_FRAMEBUFFER;
771 		rc::Framebuffer*&	binding			= ndx ? m_drawFramebufferBinding	: m_readFramebufferBinding;
772 
773 		if (target != GL_FRAMEBUFFER && target != bindingTarget)
774 			continue; // Doesn't match this target.
775 
776 		// Remove old references
777 		if (binding)
778 		{
779 			// Clear all attachment point references
780 			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
781 				releaseFboAttachmentReference(binding->getAttachment((Framebuffer::AttachmentPoint)point));
782 
783 			m_framebuffers.releaseReference(binding);
784 		}
785 
786 		// Create new references
787 		if (fbo)
788 		{
789 			m_framebuffers.acquireReference(fbo);
790 
791 			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
792 				acquireFboAttachmentReference(fbo->getAttachment((Framebuffer::AttachmentPoint)point));
793 		}
794 
795 		binding = fbo;
796 	}
797 }
798 
genFramebuffers(int numFramebuffers,deUint32 * framebuffers)799 void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
800 {
801 	while (numFramebuffers--)
802 		*framebuffers++ = m_framebuffers.allocateName();
803 }
804 
deleteFramebuffer(Framebuffer * framebuffer)805 void ReferenceContext::deleteFramebuffer (Framebuffer* framebuffer)
806 {
807 	// Remove bindings.
808 	if (m_drawFramebufferBinding == framebuffer) bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
809 	if (m_readFramebufferBinding == framebuffer) bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
810 
811 	DE_ASSERT(framebuffer->getRefCount() == 1);
812 	m_framebuffers.releaseReference(framebuffer);
813 }
814 
deleteFramebuffers(int numFramebuffers,const deUint32 * framebuffers)815 void ReferenceContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
816 {
817 	for (int i = 0; i < numFramebuffers; i++)
818 	{
819 		deUint32		name		= framebuffers[i];
820 		Framebuffer*	framebuffer	= name ? m_framebuffers.find(name) : DE_NULL;
821 
822 		if (framebuffer)
823 			deleteFramebuffer(framebuffer);
824 	}
825 }
826 
bindRenderbuffer(deUint32 target,deUint32 name)827 void ReferenceContext::bindRenderbuffer (deUint32 target, deUint32 name)
828 {
829 	Renderbuffer* rbo = DE_NULL;
830 
831 	RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
832 
833 	if (name != 0)
834 	{
835 		rbo = m_renderbuffers.find(name);
836 		if (!rbo)
837 		{
838 			rbo = new Renderbuffer(name);
839 			m_renderbuffers.insert(rbo);
840 		}
841 	}
842 
843 	// Remove old reference
844 	if (m_renderbufferBinding)
845 		m_renderbuffers.releaseReference(m_renderbufferBinding);
846 
847 	// Create new reference
848 	if (rbo)
849 		m_renderbuffers.acquireReference(rbo);
850 
851 	m_renderbufferBinding = rbo;
852 }
853 
genRenderbuffers(int numRenderbuffers,deUint32 * renderbuffers)854 void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
855 {
856 	while (numRenderbuffers--)
857 		*renderbuffers++ = m_renderbuffers.allocateName();
858 }
859 
deleteRenderbuffer(Renderbuffer * renderbuffer)860 void ReferenceContext::deleteRenderbuffer (Renderbuffer* renderbuffer)
861 {
862 	if (m_renderbufferBinding == renderbuffer)
863 		bindRenderbuffer(GL_RENDERBUFFER, 0);
864 
865 	// Unbind from currently bound framebuffers
866 	for (int ndx = 0; ndx < 2; ndx++)
867 	{
868 		rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
869 		if (framebufferBinding)
870 		{
871 			int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
872 								+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
873 
874 			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
875 			{
876 				Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
877 				if (attachment.name == renderbuffer->getName())
878 				{
879 					for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
880 						releaseFboAttachmentReference(attachment);
881 					attachment = Framebuffer::Attachment();
882 				}
883 			}
884 		}
885 	}
886 
887 	DE_ASSERT(renderbuffer->getRefCount() == 1);
888 	m_renderbuffers.releaseReference(renderbuffer);
889 }
890 
deleteRenderbuffers(int numRenderbuffers,const deUint32 * renderbuffers)891 void ReferenceContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
892 {
893 	for (int i = 0; i < numRenderbuffers; i++)
894 	{
895 		deUint32		name			= renderbuffers[i];
896 		Renderbuffer*	renderbuffer	= name ? m_renderbuffers.find(name) : DE_NULL;
897 
898 		if (renderbuffer)
899 			deleteRenderbuffer(renderbuffer);
900 	}
901 }
902 
pixelStorei(deUint32 pname,int param)903 void ReferenceContext::pixelStorei (deUint32 pname, int param)
904 {
905 	switch (pname)
906 	{
907 		case GL_UNPACK_ALIGNMENT:
908 			RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
909 			m_pixelUnpackAlignment = param;
910 			break;
911 
912 		case GL_PACK_ALIGNMENT:
913 			RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
914 			m_pixelPackAlignment = param;
915 			break;
916 
917 		case GL_UNPACK_ROW_LENGTH:
918 			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
919 			m_pixelUnpackRowLength = param;
920 			break;
921 
922 		case GL_UNPACK_SKIP_ROWS:
923 			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
924 			m_pixelUnpackSkipRows = param;
925 			break;
926 
927 		case GL_UNPACK_SKIP_PIXELS:
928 			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
929 			m_pixelUnpackSkipPixels = param;
930 			break;
931 
932 		case GL_UNPACK_IMAGE_HEIGHT:
933 			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
934 			m_pixelUnpackImageHeight = param;
935 			break;
936 
937 		case GL_UNPACK_SKIP_IMAGES:
938 			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
939 			m_pixelUnpackSkipImages = param;
940 			break;
941 
942 		default:
943 			setError(GL_INVALID_ENUM);
944 	}
945 }
946 
getUnpack2DAccess(const tcu::TextureFormat & format,int width,int height,const void * data)947 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack2DAccess (const tcu::TextureFormat& format, int width, int height, const void* data)
948 {
949 	int				pixelSize	= format.getPixelSize();
950 	int				rowLen		= m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
951 	int				rowPitch	= deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
952 	const deUint8*	ptr			= (const deUint8*)data + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
953 
954 	return tcu::ConstPixelBufferAccess(format, width, height, 1, rowPitch, 0, ptr);
955 }
956 
getUnpack3DAccess(const tcu::TextureFormat & format,int width,int height,int depth,const void * data)957 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack3DAccess (const tcu::TextureFormat& format, int width, int height, int depth, const void* data)
958 {
959 	int				pixelSize	= format.getPixelSize();
960 	int				rowLen		= m_pixelUnpackRowLength	> 0 ? m_pixelUnpackRowLength	: width;
961 	int				imageHeight	= m_pixelUnpackImageHeight	> 0 ? m_pixelUnpackImageHeight	: height;
962 	int				rowPitch	= deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
963 	int				slicePitch	= imageHeight*rowPitch;
964 	const deUint8*	ptr			= (const deUint8*)data + m_pixelUnpackSkipImages*slicePitch + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
965 
966 	return tcu::ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, ptr);
967 }
968 
mapInternalFormat(deUint32 internalFormat)969 static tcu::TextureFormat mapInternalFormat (deUint32 internalFormat)
970 {
971 	switch (internalFormat)
972 	{
973 		case GL_ALPHA:				return TextureFormat(TextureFormat::A,		TextureFormat::UNORM_INT8);
974 		case GL_LUMINANCE:			return TextureFormat(TextureFormat::L,		TextureFormat::UNORM_INT8);
975 		case GL_LUMINANCE_ALPHA:	return TextureFormat(TextureFormat::LA,		TextureFormat::UNORM_INT8);
976 		case GL_RGB:				return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
977 		case GL_RGBA:				return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
978 
979 		default:
980 			return glu::mapGLInternalFormat(internalFormat);
981 	}
982 }
983 
depthValueFloatClampCopy(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src)984 static void depthValueFloatClampCopy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
985 {
986 	int width	= dst.getWidth();
987 	int height	= dst.getHeight();
988 	int depth	= dst.getDepth();
989 
990 	DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
991 
992 	// clamping copy
993 
994 	if (src.getFormat().order == tcu::TextureFormat::DS && dst.getFormat().order == tcu::TextureFormat::DS)
995 	{
996 		// copy only depth and stencil
997 		for (int z = 0; z < depth; z++)
998 		for (int y = 0; y < height; y++)
999 		for (int x = 0; x < width; x++)
1000 		{
1001 			dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1002 			dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
1003 		}
1004 	}
1005 	else
1006 	{
1007 		// copy only depth
1008 		for (int z = 0; z < depth; z++)
1009 		for (int y = 0; y < height; y++)
1010 		for (int x = 0; x < width; x++)
1011 			dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1012 	}
1013 }
1014 
texImage1D(deUint32 target,int level,deUint32 internalFormat,int width,int border,deUint32 format,deUint32 type,const void * data)1015 void ReferenceContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
1016 {
1017 	texImage2D(target, level, internalFormat, width, 1, border, format, type, data);
1018 }
1019 
texImage2D(deUint32 target,int level,deUint32 internalFormat,int width,int height,int border,deUint32 format,deUint32 type,const void * data)1020 void ReferenceContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
1021 {
1022 	texImage3D(target, level, internalFormat, width, height, 1, border, format, type, data);
1023 }
1024 
clearToTextureInitialValue(PixelBufferAccess access)1025 static void clearToTextureInitialValue (PixelBufferAccess access)
1026 {
1027 	const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::D || access.getFormat().order == tcu::TextureFormat::DS;
1028 	const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::S || access.getFormat().order == tcu::TextureFormat::DS;
1029 	const bool hasColor		= !hasDepth && !hasStencil;
1030 
1031 	if (hasDepth)
1032 		tcu::clearDepth(access, 0.0f);
1033 	if (hasStencil)
1034 		tcu::clearStencil(access, 0u);
1035 	if (hasColor)
1036 		tcu::clear(access, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1037 }
1038 
texImage3D(deUint32 target,int level,deUint32 internalFormat,int width,int height,int depth,int border,deUint32 format,deUint32 type,const void * data)1039 void ReferenceContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
1040 {
1041 	TextureUnit&		unit					= m_textureUnits[m_activeTexture];
1042 	const void*			unpackPtr				= getPixelUnpackPtr(data);
1043 	const bool			isDstFloatDepthFormat	= (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
1044 	TextureFormat		storageFmt;
1045 	TextureFormat		transferFmt;
1046 
1047 	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1048 	RC_IF_ERROR(width < 0 || height < 0 || depth < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1049 
1050 	// Map storage format.
1051 	storageFmt = mapInternalFormat(internalFormat);
1052 	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1053 				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1054 
1055 	// Map transfer format.
1056 	transferFmt = glu::mapGLTransferFormat(format, type);
1057 	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1058 				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1059 
1060 	if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1061 	{
1062 		// Validate size and level.
1063 		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height != 1 || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1064 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1065 
1066 		Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1067 
1068 		if (texture->isImmutable())
1069 		{
1070 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1071 
1072 			ConstPixelBufferAccess dst(texture->getLevel(level));
1073 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1074 						width		!= dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1075 		}
1076 		else
1077 			texture->allocLevel(level, storageFmt, width);
1078 
1079 		if (unpackPtr)
1080 		{
1081 			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, 1, unpackPtr);
1082 			PixelBufferAccess		dst		(texture->getLevel(level));
1083 
1084 			if (isDstFloatDepthFormat)
1085 				depthValueFloatClampCopy(dst, src);
1086 			else
1087 				tcu::copy(dst, src);
1088 		}
1089 		else
1090 		{
1091 			// No data supplied, clear to initial
1092 			clearToTextureInitialValue(texture->getLevel(level));
1093 		}
1094 	}
1095 	else if (target == GL_TEXTURE_2D)
1096 	{
1097 		// Validate size and level.
1098 		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1099 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1100 
1101 		Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1102 
1103 		if (texture->isImmutable())
1104 		{
1105 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1106 
1107 			ConstPixelBufferAccess dst(texture->getLevel(level));
1108 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1109 						width		!= dst.getWidth()	||
1110 						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1111 		}
1112 		else
1113 			texture->allocLevel(level, storageFmt, width, height);
1114 
1115 		if (unpackPtr)
1116 		{
1117 			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1118 			PixelBufferAccess		dst		(texture->getLevel(level));
1119 
1120 			if (isDstFloatDepthFormat)
1121 				depthValueFloatClampCopy(dst, src);
1122 			else
1123 				tcu::copy(dst, src);
1124 		}
1125 		else
1126 		{
1127 			// No data supplied, clear to initial
1128 			clearToTextureInitialValue(texture->getLevel(level));
1129 		}
1130 	}
1131 	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1132 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1133 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1134 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1135 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1136 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1137 	{
1138 		// Validate size and level.
1139 		RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1140 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1141 
1142 		TextureCube*	texture	= unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1143 		tcu::CubeFace	face	= mapGLCubeFace(target);
1144 
1145 		if (texture->isImmutable())
1146 		{
1147 			RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1148 
1149 			ConstPixelBufferAccess dst(texture->getFace(level, face));
1150 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1151 						width		!= dst.getWidth()	||
1152 						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1153 		}
1154 		else
1155 			texture->allocFace(level, face, storageFmt, width, height);
1156 
1157 		if (unpackPtr)
1158 		{
1159 			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1160 			PixelBufferAccess		dst		(texture->getFace(level, face));
1161 
1162 			if (isDstFloatDepthFormat)
1163 				depthValueFloatClampCopy(dst, src);
1164 			else
1165 				tcu::copy(dst, src);
1166 		}
1167 		else
1168 		{
1169 			// No data supplied, clear to initial
1170 			clearToTextureInitialValue(texture->getFace(level, face));
1171 		}
1172 	}
1173 	else if (target == GL_TEXTURE_2D_ARRAY)
1174 	{
1175 		// Validate size and level.
1176 		RC_IF_ERROR(width	> m_limits.maxTexture2DSize ||
1177 					height	> m_limits.maxTexture2DSize ||
1178 					depth	> m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1179 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1180 
1181 		Texture2DArray* texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex;
1182 
1183 		if (texture->isImmutable())
1184 		{
1185 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1186 
1187 			ConstPixelBufferAccess dst(texture->getLevel(level));
1188 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1189 						width		!= dst.getWidth()	||
1190 						height		!= dst.getHeight()	||
1191 						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1192 		}
1193 		else
1194 			texture->allocLevel(level, storageFmt, width, height, depth);
1195 
1196 		if (unpackPtr)
1197 		{
1198 			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1199 			PixelBufferAccess		dst		(texture->getLevel(level));
1200 
1201 			if (isDstFloatDepthFormat)
1202 				depthValueFloatClampCopy(dst, src);
1203 			else
1204 				tcu::copy(dst, src);
1205 		}
1206 		else
1207 		{
1208 			// No data supplied, clear to initial
1209 			clearToTextureInitialValue(texture->getLevel(level));
1210 		}
1211 	}
1212 	else if (target == GL_TEXTURE_3D)
1213 	{
1214 		// Validate size and level.
1215 		RC_IF_ERROR(width	> m_limits.maxTexture3DSize ||
1216 					height	> m_limits.maxTexture3DSize ||
1217 					depth	> m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1218 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture3DSize), GL_INVALID_VALUE, RC_RET_VOID);
1219 
1220 		Texture3D* texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex;
1221 
1222 		if (texture->isImmutable())
1223 		{
1224 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1225 
1226 			ConstPixelBufferAccess dst(texture->getLevel(level));
1227 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1228 						width		!= dst.getWidth()	||
1229 						height		!= dst.getHeight()	||
1230 						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1231 		}
1232 		else
1233 			texture->allocLevel(level, storageFmt, width, height, depth);
1234 
1235 		if (unpackPtr)
1236 		{
1237 			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1238 			PixelBufferAccess		dst		(texture->getLevel(level));
1239 
1240 			if (isDstFloatDepthFormat)
1241 				depthValueFloatClampCopy(dst, src);
1242 			else
1243 				tcu::copy(dst, src);
1244 		}
1245 		else
1246 		{
1247 			// No data supplied, clear to initial
1248 			clearToTextureInitialValue(texture->getLevel(level));
1249 		}
1250 	}
1251 	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1252 	{
1253 		// Validate size and level.
1254 		RC_IF_ERROR(width		!= height						||
1255 					width		 > m_limits.maxTexture2DSize	||
1256 					depth % 6	!= 0							||
1257 					depth		 > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1258 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1259 
1260 		TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;
1261 
1262 		if (texture->isImmutable())
1263 		{
1264 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1265 
1266 			ConstPixelBufferAccess dst(texture->getLevel(level));
1267 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1268 						width		!= dst.getWidth()	||
1269 						height		!= dst.getHeight()	||
1270 						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1271 		}
1272 		else
1273 			texture->allocLevel(level, storageFmt, width, height, depth);
1274 
1275 		if (unpackPtr)
1276 		{
1277 			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1278 			PixelBufferAccess		dst		(texture->getLevel(level));
1279 
1280 			if (isDstFloatDepthFormat)
1281 				depthValueFloatClampCopy(dst, src);
1282 			else
1283 				tcu::copy(dst, src);
1284 		}
1285 		else
1286 		{
1287 			// No data supplied, clear to initial
1288 			clearToTextureInitialValue(texture->getLevel(level));
1289 		}
1290 	}
1291 	else
1292 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1293 }
1294 
texSubImage1D(deUint32 target,int level,int xoffset,int width,deUint32 format,deUint32 type,const void * data)1295 void ReferenceContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
1296 {
1297 	texSubImage2D(target, level, xoffset, 0, width, 1, format, type, data);
1298 }
1299 
texSubImage2D(deUint32 target,int level,int xoffset,int yoffset,int width,int height,deUint32 format,deUint32 type,const void * data)1300 void ReferenceContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
1301 {
1302 	texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, data);
1303 }
1304 
texSubImage3D(deUint32 target,int level,int xoffset,int yoffset,int zoffset,int width,int height,int depth,deUint32 format,deUint32 type,const void * data)1305 void ReferenceContext::texSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, deUint32 format, deUint32 type, const void* data)
1306 {
1307 	TextureUnit& unit = m_textureUnits[m_activeTexture];
1308 
1309 	RC_IF_ERROR(xoffset < 0 || yoffset < 0 || zoffset < 0,	GL_INVALID_VALUE, RC_RET_VOID);
1310 	RC_IF_ERROR(width < 0 || height < 0 || depth < 0,		GL_INVALID_VALUE, RC_RET_VOID);
1311 
1312 	TextureFormat transferFmt = glu::mapGLTransferFormat(format, type);
1313 	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1314 				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1315 
1316 	ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, getPixelUnpackPtr(data));
1317 
1318 	if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1319 	{
1320 		Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1321 
1322 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1323 
1324 		PixelBufferAccess dst = texture.getLevel(level);
1325 
1326 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1327 					yoffset + height	> dst.getHeight()	||
1328 					zoffset + depth		> dst.getDepth(),
1329 					GL_INVALID_VALUE, RC_RET_VOID);
1330 
1331 		// depth components are limited to [0,1] range
1332 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1333 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1334 		else
1335 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1336 	}
1337 	else if (target == GL_TEXTURE_2D)
1338 	{
1339 		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1340 
1341 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1342 
1343 		PixelBufferAccess dst = texture.getLevel(level);
1344 
1345 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1346 					yoffset + height	> dst.getHeight()	||
1347 					zoffset + depth		> dst.getDepth(),
1348 					GL_INVALID_VALUE, RC_RET_VOID);
1349 
1350 		// depth components are limited to [0,1] range
1351 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1352 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1353 		else
1354 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1355 	}
1356 	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1357 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1358 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1359 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1360 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1361 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1362 	{
1363 		TextureCube&	texture		= unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1364 		tcu::CubeFace	face		= mapGLCubeFace(target);
1365 
1366 		RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1367 
1368 		PixelBufferAccess dst = texture.getFace(level, face);
1369 
1370 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1371 					yoffset + height	> dst.getHeight()	||
1372 					zoffset + depth		> dst.getDepth(),
1373 					GL_INVALID_VALUE, RC_RET_VOID);
1374 
1375 		// depth components are limited to [0,1] range
1376 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1377 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1378 		else
1379 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1380 	}
1381 	else if (target == GL_TEXTURE_3D)
1382 	{
1383 		Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1384 
1385 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1386 
1387 		PixelBufferAccess dst = texture.getLevel(level);
1388 
1389 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1390 					yoffset + height	> dst.getHeight()	||
1391 					zoffset + depth		> dst.getDepth(),
1392 					GL_INVALID_VALUE, RC_RET_VOID);
1393 
1394 		// depth components are limited to [0,1] range
1395 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1396 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1397 		else
1398 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1399 	}
1400 	else if (target == GL_TEXTURE_2D_ARRAY)
1401 	{
1402 		Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1403 
1404 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1405 
1406 		PixelBufferAccess dst = texture.getLevel(level);
1407 
1408 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1409 					yoffset + height	> dst.getHeight()	||
1410 					zoffset + depth		> dst.getDepth(),
1411 					GL_INVALID_VALUE, RC_RET_VOID);
1412 
1413 		// depth components are limited to [0,1] range
1414 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1415 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1416 		else
1417 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1418 	}
1419 	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1420 	{
1421 		TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1422 
1423 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1424 
1425 		PixelBufferAccess dst = texture.getLevel(level);
1426 
1427 		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
1428 					yoffset + height	> dst.getHeight()	||
1429 					zoffset + depth		> dst.getDepth(),
1430 					GL_INVALID_VALUE, RC_RET_VOID);
1431 
1432 		// depth components are limited to [0,1] range
1433 		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1434 			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1435 		else
1436 			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1437 	}
1438 	else
1439 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1440 }
1441 
copyTexImage1D(deUint32 target,int level,deUint32 internalFormat,int x,int y,int width,int border)1442 void ReferenceContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
1443 {
1444 	TextureUnit&							unit		= m_textureUnits[m_activeTexture];
1445 	TextureFormat							storageFmt;
1446 	rr::MultisampleConstPixelBufferAccess	src			= getReadColorbuffer();
1447 
1448 	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1449 	RC_IF_ERROR(width < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1450 	RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1451 
1452 	// Map storage format.
1453 	storageFmt = mapInternalFormat(internalFormat);
1454 	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1455 				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1456 
1457 	if (target == GL_TEXTURE_1D)
1458 	{
1459 		// Validate size and level.
1460 		RC_IF_ERROR(width > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1461 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1462 
1463 		Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1464 
1465 		if (texture->isImmutable())
1466 		{
1467 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1468 
1469 			ConstPixelBufferAccess dst(texture->getLevel(level));
1470 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1471 						width		!= dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1472 		}
1473 		else
1474 			texture->allocLevel(level, storageFmt, width);
1475 
1476 		// Copy from current framebuffer.
1477 		PixelBufferAccess dst = texture->getLevel(level);
1478 		for (int xo = 0; xo < width; xo++)
1479 		{
1480 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1481 				continue; // Undefined pixel.
1482 
1483 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo, 0);
1484 		}
1485 	}
1486 	else
1487 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1488 }
1489 
copyTexImage2D(deUint32 target,int level,deUint32 internalFormat,int x,int y,int width,int height,int border)1490 void ReferenceContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
1491 {
1492 	TextureUnit&							unit		= m_textureUnits[m_activeTexture];
1493 	TextureFormat							storageFmt;
1494 	rr::MultisampleConstPixelBufferAccess	src			= getReadColorbuffer();
1495 
1496 	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1497 	RC_IF_ERROR(width < 0 || height < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1498 	RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1499 
1500 	// Map storage format.
1501 	storageFmt = mapInternalFormat(internalFormat);
1502 	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1503 				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1504 
1505 	if (target == GL_TEXTURE_2D)
1506 	{
1507 		// Validate size and level.
1508 		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1509 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1510 
1511 		Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1512 
1513 		if (texture->isImmutable())
1514 		{
1515 			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1516 
1517 			ConstPixelBufferAccess dst(texture->getLevel(level));
1518 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1519 						width		!= dst.getWidth()	||
1520 						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1521 		}
1522 		else
1523 			texture->allocLevel(level, storageFmt, width, height);
1524 
1525 		// Copy from current framebuffer.
1526 		PixelBufferAccess dst = texture->getLevel(level);
1527 		for (int yo = 0; yo < height; yo++)
1528 		for (int xo = 0; xo < width; xo++)
1529 		{
1530 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1531 				continue; // Undefined pixel.
1532 
1533 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1534 		}
1535 	}
1536 	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1537 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1538 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1539 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1540 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1541 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1542 	{
1543 		// Validate size and level.
1544 		RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1545 		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1546 
1547 		TextureCube*	texture	= unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1548 		tcu::CubeFace	face	= mapGLCubeFace(target);
1549 
1550 		if (texture->isImmutable())
1551 		{
1552 			RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1553 
1554 			ConstPixelBufferAccess dst(texture->getFace(level, face));
1555 			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
1556 						width		!= dst.getWidth()	||
1557 						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1558 		}
1559 		else
1560 			texture->allocFace(level, face, storageFmt, width, height);
1561 
1562 		// Copy from current framebuffer.
1563 		PixelBufferAccess dst = texture->getFace(level, face);
1564 		for (int yo = 0; yo < height; yo++)
1565 		for (int xo = 0; xo < width; xo++)
1566 		{
1567 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1568 				continue; // Undefined pixel.
1569 
1570 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1571 		}
1572 	}
1573 	else
1574 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1575 }
1576 
copyTexSubImage1D(deUint32 target,int level,int xoffset,int x,int y,int width)1577 void ReferenceContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
1578 {
1579 	TextureUnit&							unit	= m_textureUnits[m_activeTexture];
1580 	rr::MultisampleConstPixelBufferAccess	src		= getReadColorbuffer();
1581 
1582 	RC_IF_ERROR(xoffset < 0,	GL_INVALID_VALUE,		RC_RET_VOID);
1583 	RC_IF_ERROR(width < 0,		GL_INVALID_VALUE,		RC_RET_VOID);
1584 	RC_IF_ERROR(isEmpty(src),	GL_INVALID_OPERATION,	RC_RET_VOID);
1585 
1586 	if (target == GL_TEXTURE_1D)
1587 	{
1588 		Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1589 
1590 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1591 
1592 		PixelBufferAccess dst = texture.getLevel(level);
1593 
1594 		RC_IF_ERROR(xoffset + width > dst.getWidth(), GL_INVALID_VALUE, RC_RET_VOID);
1595 
1596 		for (int xo = 0; xo < width; xo++)
1597 		{
1598 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1599 				continue;
1600 
1601 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo+xoffset, 0);
1602 		}
1603 	}
1604 	else
1605 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1606 }
1607 
copyTexSubImage2D(deUint32 target,int level,int xoffset,int yoffset,int x,int y,int width,int height)1608 void ReferenceContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
1609 {
1610 	TextureUnit&							unit	= m_textureUnits[m_activeTexture];
1611 	rr::MultisampleConstPixelBufferAccess	src		= getReadColorbuffer();
1612 
1613 	RC_IF_ERROR(xoffset < 0 || yoffset < 0,					GL_INVALID_VALUE, RC_RET_VOID);
1614 	RC_IF_ERROR(width < 0 || height < 0,					GL_INVALID_VALUE, RC_RET_VOID);
1615 	RC_IF_ERROR(isEmpty(src),								GL_INVALID_OPERATION, RC_RET_VOID);
1616 
1617 	if (target == GL_TEXTURE_2D)
1618 	{
1619 		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1620 
1621 		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1622 
1623 		PixelBufferAccess dst = texture.getLevel(level);
1624 
1625 		RC_IF_ERROR(xoffset + width		> dst.getWidth() ||
1626 					yoffset + height	> dst.getHeight(),
1627 					GL_INVALID_VALUE, RC_RET_VOID);
1628 
1629 		for (int yo = 0; yo < height; yo++)
1630 		for (int xo = 0; xo < width; xo++)
1631 		{
1632 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1633 				continue;
1634 
1635 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1636 		}
1637 	}
1638 	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1639 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1640 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1641 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1642 			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1643 			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1644 	{
1645 		TextureCube&	texture		= unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1646 		tcu::CubeFace	face		= mapGLCubeFace(target);
1647 
1648 		RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1649 
1650 		PixelBufferAccess dst = texture.getFace(level, face);
1651 
1652 		RC_IF_ERROR(xoffset + width		> dst.getWidth() ||
1653 					yoffset + height	> dst.getHeight(),
1654 					GL_INVALID_VALUE, RC_RET_VOID);
1655 
1656 		for (int yo = 0; yo < height; yo++)
1657 		for (int xo = 0; xo < width; xo++)
1658 		{
1659 			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1660 				continue;
1661 
1662 			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1663 		}
1664 	}
1665 	else
1666 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1667 }
1668 
copyTexSubImage3D(deUint32 target,int level,int xoffset,int yoffset,int zoffset,int x,int y,int width,int height)1669 void ReferenceContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
1670 {
1671 	DE_UNREF(target && level && xoffset && yoffset && zoffset && x && y && width && height);
1672 	DE_ASSERT(false);
1673 }
1674 
texStorage2D(deUint32 target,int levels,deUint32 internalFormat,int width,int height)1675 void ReferenceContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
1676 {
1677 	TextureUnit&		unit		= m_textureUnits[m_activeTexture];
1678 	TextureFormat		storageFmt;
1679 
1680 	RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1681 	RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1682 
1683 	// Map storage format.
1684 	storageFmt = mapInternalFormat(internalFormat);
1685 	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1686 				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1687 
1688 	if (target == GL_TEXTURE_2D)
1689 	{
1690 		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1691 
1692 		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height >= m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1693 		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1694 
1695 		texture.clearLevels();
1696 		texture.setImmutable();
1697 
1698 		for (int level = 0; level < levels; level++)
1699 		{
1700 			int levelW = de::max(1, width >> level);
1701 			int levelH = de::max(1, height >> level);
1702 
1703 			texture.allocLevel(level, storageFmt, levelW, levelH);
1704 		}
1705 	}
1706 	else if (target == GL_TEXTURE_CUBE_MAP)
1707 	{
1708 		TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1709 
1710 		RC_IF_ERROR(width > m_limits.maxTextureCubeSize || height > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1711 		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1712 
1713 		texture.clearLevels();
1714 		texture.setImmutable();
1715 
1716 		for (int level = 0; level < levels; level++)
1717 		{
1718 			int levelW = de::max(1, width >> level);
1719 			int levelH = de::max(1, height >> level);
1720 
1721 			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1722 				texture.allocFace(level, (tcu::CubeFace)face, storageFmt, levelW, levelH);
1723 		}
1724 	}
1725 	else
1726 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1727 }
1728 
texStorage3D(deUint32 target,int levels,deUint32 internalFormat,int width,int height,int depth)1729 void ReferenceContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
1730 {
1731 	TextureUnit&		unit		= m_textureUnits[m_activeTexture];
1732 	TextureFormat		storageFmt;
1733 
1734 	RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1735 	RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1736 
1737 	// Map storage format.
1738 	storageFmt = mapInternalFormat(internalFormat);
1739 	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
1740 				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1741 
1742 	if (target == GL_TEXTURE_2D_ARRAY)
1743 	{
1744 		Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1745 
1746 		RC_IF_ERROR(width	>	m_limits.maxTexture2DSize	||
1747 					height	>=	m_limits.maxTexture2DSize	||
1748 					depth	>=	m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1749 		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1750 
1751 		texture.clearLevels();
1752 		texture.setImmutable();
1753 
1754 		for (int level = 0; level < levels; level++)
1755 		{
1756 			int levelW = de::max(1, width >> level);
1757 			int levelH = de::max(1, height >> level);
1758 
1759 			texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1760 		}
1761 	}
1762 	else if (target == GL_TEXTURE_3D)
1763 	{
1764 		Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1765 
1766 		RC_IF_ERROR(width	> m_limits.maxTexture3DSize	||
1767 					height	> m_limits.maxTexture3DSize	||
1768 					depth	> m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1769 		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1770 
1771 		texture.clearLevels();
1772 		texture.setImmutable();
1773 
1774 		for (int level = 0; level < levels; level++)
1775 		{
1776 			int levelW = de::max(1, width		>> level);
1777 			int levelH = de::max(1, height	>> level);
1778 			int levelD = de::max(1, depth		>> level);
1779 
1780 			texture.allocLevel(level, storageFmt, levelW, levelH, levelD);
1781 		}
1782 	}
1783 	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1784 	{
1785 		TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1786 
1787 		RC_IF_ERROR(width		!=	height								||
1788 					depth % 6	!= 0									||
1789 					width		>	m_limits.maxTexture2DSize			||
1790 					depth		>=	m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1791 		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1792 
1793 		texture.clearLevels();
1794 		texture.setImmutable();
1795 
1796 		for (int level = 0; level < levels; level++)
1797 		{
1798 			int levelW = de::max(1, width >> level);
1799 			int levelH = de::max(1, height >> level);
1800 
1801 			texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1802 		}
1803 	}
1804 	else
1805 		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1806 }
1807 
1808 // \todo [2014-02-19 pyry] Duplicated with code in gluTextureUtil.hpp
1809 
mapGLWrapMode(int value)1810 static inline tcu::Sampler::WrapMode mapGLWrapMode (int value)
1811 {
1812 	switch (value)
1813 	{
1814 		case GL_CLAMP_TO_EDGE:		return tcu::Sampler::CLAMP_TO_EDGE;
1815 		case GL_REPEAT:				return tcu::Sampler::REPEAT_GL;
1816 		case GL_MIRRORED_REPEAT:	return tcu::Sampler::MIRRORED_REPEAT_GL;
1817 		default:					return tcu::Sampler::WRAPMODE_LAST;
1818 	}
1819 }
1820 
mapGLFilterMode(int value)1821 static inline tcu::Sampler::FilterMode mapGLFilterMode (int value)
1822 {
1823 	switch (value)
1824 	{
1825 		case GL_NEAREST:				return tcu::Sampler::NEAREST;
1826 		case GL_LINEAR:					return tcu::Sampler::LINEAR;
1827 		case GL_NEAREST_MIPMAP_NEAREST:	return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
1828 		case GL_NEAREST_MIPMAP_LINEAR:	return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
1829 		case GL_LINEAR_MIPMAP_NEAREST:	return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
1830 		case GL_LINEAR_MIPMAP_LINEAR:	return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
1831 		default:						return tcu::Sampler::FILTERMODE_LAST;
1832 	}
1833 }
1834 
texParameteri(deUint32 target,deUint32 pname,int value)1835 void ReferenceContext::texParameteri (deUint32 target, deUint32 pname, int value)
1836 {
1837 	TextureUnit&	unit		= m_textureUnits[m_activeTexture];
1838 	Texture*		texture		= DE_NULL;
1839 
1840 	switch (target)
1841 	{
1842 		case GL_TEXTURE_1D:				texture = unit.tex1DBinding			? unit.tex1DBinding			: &unit.default1DTex;			break;
1843 		case GL_TEXTURE_2D:				texture = unit.tex2DBinding			? unit.tex2DBinding			: &unit.default2DTex;			break;
1844 		case GL_TEXTURE_CUBE_MAP:		texture = unit.texCubeBinding		? unit.texCubeBinding		: &unit.defaultCubeTex;			break;
1845 		case GL_TEXTURE_2D_ARRAY:		texture = unit.tex2DArrayBinding	? unit.tex2DArrayBinding	: &unit.default2DArrayTex;		break;
1846 		case GL_TEXTURE_3D:				texture = unit.tex3DBinding			? unit.tex3DBinding			: &unit.default3DTex;			break;
1847 		case GL_TEXTURE_CUBE_MAP_ARRAY:	texture = unit.texCubeArrayBinding	? unit.texCubeArrayBinding	: &unit.defaultCubeArrayTex;	break;
1848 
1849 		default:					RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1850 	}
1851 
1852 	switch (pname)
1853 	{
1854 		case GL_TEXTURE_WRAP_S:
1855 		{
1856 			tcu::Sampler::WrapMode wrapS = mapGLWrapMode(value);
1857 			RC_IF_ERROR(wrapS == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1858 			texture->getSampler().wrapS = wrapS;
1859 			break;
1860 		}
1861 
1862 		case GL_TEXTURE_WRAP_T:
1863 		{
1864 			tcu::Sampler::WrapMode wrapT = mapGLWrapMode(value);
1865 			RC_IF_ERROR(wrapT == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1866 			texture->getSampler().wrapT = wrapT;
1867 			break;
1868 		}
1869 
1870 		case GL_TEXTURE_WRAP_R:
1871 		{
1872 			tcu::Sampler::WrapMode wrapR = mapGLWrapMode(value);
1873 			RC_IF_ERROR(wrapR == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1874 			texture->getSampler().wrapR = wrapR;
1875 			break;
1876 		}
1877 
1878 		case GL_TEXTURE_MIN_FILTER:
1879 		{
1880 			tcu::Sampler::FilterMode minMode = mapGLFilterMode(value);
1881 			RC_IF_ERROR(minMode == tcu::Sampler::FILTERMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1882 			texture->getSampler().minFilter = minMode;
1883 			break;
1884 		}
1885 
1886 		case GL_TEXTURE_MAG_FILTER:
1887 		{
1888 			tcu::Sampler::FilterMode magMode = mapGLFilterMode(value);
1889 			RC_IF_ERROR(magMode != tcu::Sampler::LINEAR && magMode != tcu::Sampler::NEAREST,
1890 						GL_INVALID_VALUE, RC_RET_VOID);
1891 			texture->getSampler().magFilter = magMode;
1892 			break;
1893 		}
1894 
1895 		case GL_TEXTURE_MAX_LEVEL:
1896 		{
1897 			RC_IF_ERROR(value < 0, GL_INVALID_VALUE, RC_RET_VOID);
1898 			texture->setMaxLevel(value);
1899 			break;
1900 		}
1901 
1902 		default:
1903 			RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1904 	}
1905 }
1906 
mapGLAttachmentPoint(deUint32 attachment)1907 static inline Framebuffer::AttachmentPoint mapGLAttachmentPoint (deUint32 attachment)
1908 {
1909 	switch (attachment)
1910 	{
1911 		case GL_COLOR_ATTACHMENT0:	return Framebuffer::ATTACHMENTPOINT_COLOR0;
1912 		case GL_DEPTH_ATTACHMENT:	return Framebuffer::ATTACHMENTPOINT_DEPTH;
1913 		case GL_STENCIL_ATTACHMENT:	return Framebuffer::ATTACHMENTPOINT_STENCIL;
1914 		default:					return Framebuffer::ATTACHMENTPOINT_LAST;
1915 	}
1916 }
1917 
mapGLFboTexTarget(deUint32 target)1918 static inline Framebuffer::TexTarget mapGLFboTexTarget (deUint32 target)
1919 {
1920 	switch (target)
1921 	{
1922 		case GL_TEXTURE_2D:						return Framebuffer::TEXTARGET_2D;
1923 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X;
1924 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y;
1925 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z;
1926 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X;
1927 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y;
1928 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z;
1929 		default:								return Framebuffer::TEXTARGET_LAST;
1930 	}
1931 }
1932 
acquireFboAttachmentReference(const Framebuffer::Attachment & attachment)1933 void ReferenceContext::acquireFboAttachmentReference (const Framebuffer::Attachment& attachment)
1934 {
1935 	switch (attachment.type)
1936 	{
1937 		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1938 		{
1939 			TCU_CHECK(attachment.name != 0);
1940 			Texture* texture = m_textures.find(attachment.name);
1941 			TCU_CHECK(texture);
1942 			m_textures.acquireReference(texture);
1943 			break;
1944 		}
1945 
1946 		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1947 		{
1948 			TCU_CHECK(attachment.name != 0);
1949 			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1950 			TCU_CHECK(rbo);
1951 			m_renderbuffers.acquireReference(rbo);
1952 			break;
1953 		}
1954 
1955 		default:
1956 			break; // Silently ignore
1957 	}
1958 }
1959 
releaseFboAttachmentReference(const Framebuffer::Attachment & attachment)1960 void ReferenceContext::releaseFboAttachmentReference (const Framebuffer::Attachment& attachment)
1961 {
1962 	switch (attachment.type)
1963 	{
1964 		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1965 		{
1966 			TCU_CHECK(attachment.name != 0);
1967 			Texture* texture = m_textures.find(attachment.name);
1968 			TCU_CHECK(texture);
1969 			m_textures.releaseReference(texture);
1970 			break;
1971 		}
1972 
1973 		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1974 		{
1975 			TCU_CHECK(attachment.name != 0);
1976 			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1977 			TCU_CHECK(rbo);
1978 			m_renderbuffers.releaseReference(rbo);
1979 			break;
1980 		}
1981 
1982 		default:
1983 			break; // Silently ignore
1984 	}
1985 }
1986 
framebufferTexture2D(deUint32 target,deUint32 attachment,deUint32 textarget,deUint32 texture,int level)1987 void ReferenceContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
1988 {
1989 	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
1990 	{
1991 		// Attach to both depth and stencil.
1992 		framebufferTexture2D(target, GL_DEPTH_ATTACHMENT,	textarget, texture, level);
1993 		framebufferTexture2D(target, GL_STENCIL_ATTACHMENT,	textarget, texture, level);
1994 	}
1995 	else
1996 	{
1997 		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
1998 		Texture*						texObj			= DE_NULL;
1999 		Framebuffer::TexTarget			fboTexTarget	= mapGLFboTexTarget(textarget);
2000 
2001 		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
2002 					target != GL_DRAW_FRAMEBUFFER	&&
2003 					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
2004 		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);
2005 
2006 		// Select binding point.
2007 		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2008 		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2009 
2010 		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2011 		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2012 							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2013 
2014 		if (texture != 0)
2015 		{
2016 			texObj = m_textures.find(texture);
2017 
2018 			RC_IF_ERROR(!texObj,		GL_INVALID_OPERATION,	RC_RET_VOID);
2019 			RC_IF_ERROR(level != 0,		GL_INVALID_VALUE,		RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2020 
2021 			if (texObj->getType() == Texture::TYPE_2D)
2022 				RC_IF_ERROR(fboTexTarget != Framebuffer::TEXTARGET_2D, GL_INVALID_OPERATION, RC_RET_VOID);
2023 			else
2024 			{
2025 				TCU_CHECK(texObj->getType() == Texture::TYPE_CUBE_MAP);
2026 				if (!deInRange32(fboTexTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X, Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2027 					RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
2028 			}
2029 		}
2030 
2031 		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2032 		for (int ndx = 0; ndx < bindingRefCount; ndx++)
2033 			releaseFboAttachmentReference(fboAttachment);
2034 		fboAttachment = Framebuffer::Attachment();
2035 
2036 		if (texObj)
2037 		{
2038 			fboAttachment.type			= Framebuffer::ATTACHMENTTYPE_TEXTURE;
2039 			fboAttachment.name			= texObj->getName();
2040 			fboAttachment.texTarget		= fboTexTarget;
2041 			fboAttachment.level			= level;
2042 
2043 			for (int ndx = 0; ndx < bindingRefCount; ndx++)
2044 				acquireFboAttachmentReference(fboAttachment);
2045 		}
2046 	}
2047 }
2048 
framebufferTextureLayer(deUint32 target,deUint32 attachment,deUint32 texture,int level,int layer)2049 void ReferenceContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
2050 {
2051 	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2052 	{
2053 		// Attach to both depth and stencil.
2054 		framebufferTextureLayer(target, GL_DEPTH_ATTACHMENT,	texture, level, layer);
2055 		framebufferTextureLayer(target, GL_STENCIL_ATTACHMENT,	texture, level, layer);
2056 	}
2057 	else
2058 	{
2059 		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
2060 		Texture*						texObj			= DE_NULL;
2061 
2062 		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
2063 					target != GL_DRAW_FRAMEBUFFER	&&
2064 					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
2065 		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);
2066 
2067 		// Select binding point.
2068 		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2069 		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2070 
2071 		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2072 		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2073 							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2074 
2075 		if (texture != 0)
2076 		{
2077 			texObj = m_textures.find(texture);
2078 
2079 			RC_IF_ERROR(!texObj,		GL_INVALID_OPERATION,	RC_RET_VOID);
2080 			RC_IF_ERROR(level != 0,		GL_INVALID_VALUE,		RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2081 
2082 			RC_IF_ERROR(texObj->getType() != Texture::TYPE_2D_ARRAY			&&
2083 						texObj->getType() != Texture::TYPE_3D				&&
2084 						texObj->getType() != Texture::TYPE_CUBE_MAP_ARRAY,				GL_INVALID_OPERATION,	RC_RET_VOID);
2085 
2086 			if (texObj->getType() == Texture::TYPE_2D_ARRAY || texObj->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2087 			{
2088 				RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_ARRAY_TEXTURE_LAYERS),		GL_INVALID_VALUE,		RC_RET_VOID);
2089 				RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_TEXTURE_SIZE)),GL_INVALID_VALUE,		RC_RET_VOID);
2090 			}
2091 			else if	(texObj->getType() == Texture::TYPE_3D)
2092 			{
2093 				RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_3D_TEXTURE_SIZE),				GL_INVALID_VALUE,		RC_RET_VOID);
2094 				RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_3D_TEXTURE_SIZE)),	GL_INVALID_VALUE,		RC_RET_VOID);
2095 			}
2096 		}
2097 
2098 		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2099 		for (int ndx = 0; ndx < bindingRefCount; ndx++)
2100 			releaseFboAttachmentReference(fboAttachment);
2101 		fboAttachment = Framebuffer::Attachment();
2102 
2103 		if (texObj)
2104 		{
2105 			fboAttachment.type			= Framebuffer::ATTACHMENTTYPE_TEXTURE;
2106 			fboAttachment.name			= texObj->getName();
2107 			fboAttachment.texTarget		= texLayeredTypeToTarget(texObj->getType());
2108 			fboAttachment.level			= level;
2109 			fboAttachment.layer			= layer;
2110 
2111 			DE_ASSERT(fboAttachment.texTarget != Framebuffer::TEXTARGET_LAST);
2112 
2113 			for (int ndx = 0; ndx < bindingRefCount; ndx++)
2114 				acquireFboAttachmentReference(fboAttachment);
2115 		}
2116 	}
2117 }
2118 
framebufferRenderbuffer(deUint32 target,deUint32 attachment,deUint32 renderbuffertarget,deUint32 renderbuffer)2119 void ReferenceContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
2120 {
2121 	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2122 	{
2123 		// Attach both to depth and stencil.
2124 		framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT,	renderbuffertarget, renderbuffer);
2125 		framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT,	renderbuffertarget, renderbuffer);
2126 	}
2127 	else
2128 	{
2129 		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
2130 		Renderbuffer*					rbo				= DE_NULL;
2131 
2132 		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
2133 					target != GL_DRAW_FRAMEBUFFER	&&
2134 					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
2135 		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);
2136 
2137 		// Select binding point.
2138 		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2139 		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2140 
2141 		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2142 		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2143 							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2144 
2145 		if (renderbuffer != 0)
2146 		{
2147 			rbo = m_renderbuffers.find(renderbuffer);
2148 
2149 			RC_IF_ERROR(renderbuffertarget != GL_RENDERBUFFER,	GL_INVALID_ENUM,		RC_RET_VOID);
2150 			RC_IF_ERROR(!rbo,									GL_INVALID_OPERATION,	RC_RET_VOID);
2151 		}
2152 
2153 		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2154 		for (int ndx = 0; ndx < bindingRefCount; ndx++)
2155 			releaseFboAttachmentReference(fboAttachment);
2156 		fboAttachment = Framebuffer::Attachment();
2157 
2158 		if (rbo)
2159 		{
2160 			fboAttachment.type	= Framebuffer::ATTACHMENTTYPE_RENDERBUFFER;
2161 			fboAttachment.name	= rbo->getName();
2162 
2163 			for (int ndx = 0; ndx < bindingRefCount; ndx++)
2164 				acquireFboAttachmentReference(fboAttachment);
2165 		}
2166 	}
2167 }
2168 
checkFramebufferStatus(deUint32 target)2169 deUint32 ReferenceContext::checkFramebufferStatus (deUint32 target)
2170 {
2171 	RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
2172 				target != GL_DRAW_FRAMEBUFFER	&&
2173 				target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, 0);
2174 
2175 	// Select binding point.
2176 	rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2177 
2178 	// Default framebuffer is always complete.
2179 	if (!framebufferBinding)
2180 		return GL_FRAMEBUFFER_COMPLETE;
2181 
2182 	int		width				= -1;
2183 	int		height				= -1;
2184 	bool	hasAttachment		= false;
2185 	bool	attachmentComplete	= true;
2186 	bool	dimensionsOk		= true;
2187 
2188 	for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
2189 	{
2190 		const Framebuffer::Attachment&	attachment			= framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
2191 		int								attachmentWidth		= 0;
2192 		int								attachmentHeight	= 0;
2193 		tcu::TextureFormat				attachmentFormat;
2194 
2195 		if (attachment.type == Framebuffer::ATTACHMENTTYPE_TEXTURE)
2196 		{
2197 			const Texture*					texture	= m_textures.find(attachment.name);
2198 			tcu::ConstPixelBufferAccess		level;
2199 			TCU_CHECK(texture);
2200 
2201 			if (attachment.texTarget == Framebuffer::TEXTARGET_2D)
2202 			{
2203 				DE_ASSERT(texture->getType() == Texture::TYPE_2D);
2204 				const Texture2D* tex2D = static_cast<const Texture2D*>(texture);
2205 
2206 				if (tex2D->hasLevel(attachment.level))
2207 					level = tex2D->getLevel(attachment.level);
2208 			}
2209 			else if (deInRange32(attachment.texTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X,
2210 													   Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2211 			{
2212 				DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP);
2213 
2214 				const TextureCube*	texCube	= static_cast<const TextureCube*>(texture);
2215 				const tcu::CubeFace	face	= texTargetToFace(attachment.texTarget);
2216 				TCU_CHECK(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
2217 
2218 				if (texCube->hasFace(attachment.level, face))
2219 					level = texCube->getFace(attachment.level, face);
2220 			}
2221 			else if (attachment.texTarget == Framebuffer::TEXTARGET_2D_ARRAY)
2222 			{
2223 				DE_ASSERT(texture->getType() == Texture::TYPE_2D_ARRAY);
2224 				const Texture2DArray* tex2DArr = static_cast<const Texture2DArray*>(texture);
2225 
2226 				if (tex2DArr->hasLevel(attachment.level))
2227 					level = tex2DArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2228 			}
2229 			else if (attachment.texTarget == Framebuffer::TEXTARGET_3D)
2230 			{
2231 				DE_ASSERT(texture->getType() == Texture::TYPE_3D);
2232 				const Texture3D* tex3D = static_cast<const Texture3D*>(texture);
2233 
2234 				if (tex3D->hasLevel(attachment.level))
2235 					level = tex3D->getLevel(attachment.level); // \note Slice doesn't matter here.
2236 			}
2237 			else if (attachment.texTarget == Framebuffer::TEXTARGET_CUBE_MAP_ARRAY)
2238 			{
2239 				DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY);
2240 				const TextureCubeArray* texCubeArr = static_cast<const TextureCubeArray*>(texture);
2241 
2242 				if (texCubeArr->hasLevel(attachment.level))
2243 					level = texCubeArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2244 			}
2245 			else
2246 				TCU_FAIL("Framebuffer attached to a texture but no valid target specified");
2247 
2248 			attachmentWidth		= level.getWidth();
2249 			attachmentHeight	= level.getHeight();
2250 			attachmentFormat	= level.getFormat();
2251 		}
2252 		else if (attachment.type == Framebuffer::ATTACHMENTTYPE_RENDERBUFFER)
2253 		{
2254 			const Renderbuffer* renderbuffer = m_renderbuffers.find(attachment.name);
2255 			TCU_CHECK(renderbuffer);
2256 
2257 			attachmentWidth		= renderbuffer->getWidth();
2258 			attachmentHeight	= renderbuffer->getHeight();
2259 			attachmentFormat	= renderbuffer->getFormat();
2260 		}
2261 		else
2262 		{
2263 			TCU_CHECK(attachment.type == Framebuffer::ATTACHMENTTYPE_LAST);
2264 			continue; // Skip rest of checks.
2265 		}
2266 
2267 		if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0)
2268 		{
2269 			width			= attachmentWidth;
2270 			height			= attachmentHeight;
2271 			hasAttachment	= true;
2272 		}
2273 		else if (attachmentWidth != width || attachmentHeight != height)
2274 			dimensionsOk = false;
2275 
2276 		// Validate attachment point compatibility.
2277 		switch (attachmentFormat.order)
2278 		{
2279 			case TextureFormat::R:
2280 			case TextureFormat::RG:
2281 			case TextureFormat::RGB:
2282 			case TextureFormat::RGBA:
2283 			case TextureFormat::sRGB:
2284 			case TextureFormat::sRGBA:
2285 				if (point != Framebuffer::ATTACHMENTPOINT_COLOR0)
2286 					attachmentComplete = false;
2287 				break;
2288 
2289 			case TextureFormat::D:
2290 				if (point != Framebuffer::ATTACHMENTPOINT_DEPTH)
2291 					attachmentComplete = false;
2292 				break;
2293 
2294 			case TextureFormat::S:
2295 				if (point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2296 					attachmentComplete = false;
2297 				break;
2298 
2299 			case TextureFormat::DS:
2300 				if (point != Framebuffer::ATTACHMENTPOINT_DEPTH &&
2301 					point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2302 					attachmentComplete = false;
2303 				break;
2304 
2305 			default:
2306 				TCU_FAIL("Unsupported attachment channel order");
2307 		}
2308 	}
2309 
2310 	if (!attachmentComplete)
2311 		return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2312 	else if (!hasAttachment)
2313 		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
2314 	else if (!dimensionsOk)
2315 		return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
2316 	else
2317 		return GL_FRAMEBUFFER_COMPLETE;
2318 }
2319 
getFramebufferAttachmentParameteriv(deUint32 target,deUint32 attachment,deUint32 pname,int * params)2320 void ReferenceContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
2321 {
2322 	DE_UNREF(target && attachment && pname && params);
2323 	TCU_CHECK(false); // \todo [pyry] Implement
2324 }
2325 
renderbufferStorage(deUint32 target,deUint32 internalformat,int width,int height)2326 void ReferenceContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
2327 {
2328 	TextureFormat format = glu::mapGLInternalFormat(internalformat);
2329 
2330 	RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2331 	RC_IF_ERROR(!m_renderbufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2332 	RC_IF_ERROR(!deInRange32(width, 0, m_limits.maxRenderbufferSize) ||
2333 				!deInRange32(height, 0, m_limits.maxRenderbufferSize),
2334 				GL_INVALID_OPERATION, RC_RET_VOID);
2335 	RC_IF_ERROR(format.order == TextureFormat::CHANNELORDER_LAST ||
2336 				format.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2337 
2338 	m_renderbufferBinding->setStorage(format, (int)width, (int)height);
2339 }
2340 
renderbufferStorageMultisample(deUint32 target,int samples,deUint32 internalFormat,int width,int height)2341 void ReferenceContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
2342 {
2343 	// \todo [2012-04-07 pyry] Implement MSAA support.
2344 	DE_UNREF(samples);
2345 	renderbufferStorage(target, internalFormat, width, height);
2346 }
2347 
getFboAttachment(const rc::Framebuffer & framebuffer,rc::Framebuffer::AttachmentPoint point)2348 tcu::PixelBufferAccess ReferenceContext::getFboAttachment (const rc::Framebuffer& framebuffer, rc::Framebuffer::AttachmentPoint point)
2349 {
2350 	const Framebuffer::Attachment& attachment = framebuffer.getAttachment(point);
2351 
2352 	switch (attachment.type)
2353 	{
2354 		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
2355 		{
2356 			Texture* texture = m_textures.find(attachment.name);
2357 			TCU_CHECK(texture);
2358 
2359 			if (texture->getType() == Texture::TYPE_2D)
2360 			{
2361 				if (Texture2D* texture2D = dynamic_cast<Texture2D*>(texture))
2362 					return texture2D->getLevel(attachment.level);
2363 				else
2364 					return nullAccess();
2365 			}
2366 			else if (texture->getType() == Texture::TYPE_CUBE_MAP)
2367 			{
2368 				if (TextureCube* cubeMap = dynamic_cast<TextureCube*>(texture))
2369 					return cubeMap->getFace(attachment.level, texTargetToFace(attachment.texTarget));
2370 				else
2371 					return nullAccess();
2372 			}
2373 			else if (texture->getType() == Texture::TYPE_2D_ARRAY	||
2374 					 texture->getType() == Texture::TYPE_3D			||
2375 					 texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2376 			{
2377 				tcu::PixelBufferAccess level;
2378 
2379 				if (texture->getType() == Texture::TYPE_2D_ARRAY)
2380 				{
2381 					if (Texture2DArray* texture2DArray = dynamic_cast<Texture2DArray*>(texture))
2382 						level = texture2DArray->getLevel(attachment.level);
2383 				}
2384 				else if (texture->getType() == Texture::TYPE_3D)
2385 				{
2386 					if (Texture3D* texture3D = dynamic_cast<Texture3D*>(texture))
2387 						level = texture3D->getLevel(attachment.level);
2388 				}
2389 				else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2390 				{
2391 					if (TextureCubeArray* cubeArray = dynamic_cast<TextureCubeArray*>(texture))
2392 						level = cubeArray->getLevel(attachment.level);
2393 				}
2394 
2395 				void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;
2396 
2397 				return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
2398 			}
2399 			else
2400 				return nullAccess();
2401 		}
2402 
2403 		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
2404 		{
2405 			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
2406 			TCU_CHECK(rbo);
2407 
2408 			return rbo->getAccess();
2409 		}
2410 
2411 		default:
2412 			return nullAccess();
2413 	}
2414 }
2415 
getTexture2D(int unitNdx) const2416 const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
2417 {
2418 	const TextureUnit& unit = m_textureUnits[unitNdx];
2419 	return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
2420 }
2421 
getTextureCube(int unitNdx) const2422 const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
2423 {
2424 	const TextureUnit& unit = m_textureUnits[unitNdx];
2425 	return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
2426 }
2427 
isValidBufferTarget(deUint32 target)2428 static bool isValidBufferTarget (deUint32 target)
2429 {
2430 	switch (target)
2431 	{
2432 		case GL_ARRAY_BUFFER:
2433 		case GL_COPY_READ_BUFFER:
2434 		case GL_COPY_WRITE_BUFFER:
2435 		case GL_DRAW_INDIRECT_BUFFER:
2436 		case GL_ELEMENT_ARRAY_BUFFER:
2437 		case GL_PIXEL_PACK_BUFFER:
2438 		case GL_PIXEL_UNPACK_BUFFER:
2439 		case GL_TRANSFORM_FEEDBACK_BUFFER:
2440 		case GL_UNIFORM_BUFFER:
2441 			return true;
2442 
2443 		default:
2444 			return false;
2445 	}
2446 }
2447 
setBufferBinding(deUint32 target,DataBuffer * buffer)2448 void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
2449 {
2450 	DataBuffer** bindingPoint = DE_NULL;
2451 	VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2452 
2453 	switch (target)
2454 	{
2455 		case GL_ARRAY_BUFFER:				bindingPoint = &m_arrayBufferBinding;								break;
2456 		case GL_COPY_READ_BUFFER:			bindingPoint = &m_copyReadBufferBinding;							break;
2457 		case GL_COPY_WRITE_BUFFER:			bindingPoint = &m_copyWriteBufferBinding;							break;
2458 		case GL_DRAW_INDIRECT_BUFFER:		bindingPoint = &m_drawIndirectBufferBinding;						break;
2459 		case GL_ELEMENT_ARRAY_BUFFER:		bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding;		break;
2460 		case GL_PIXEL_PACK_BUFFER:			bindingPoint = &m_pixelPackBufferBinding;							break;
2461 		case GL_PIXEL_UNPACK_BUFFER:		bindingPoint = &m_pixelUnpackBufferBinding;							break;
2462 		case GL_TRANSFORM_FEEDBACK_BUFFER:	bindingPoint = &m_transformFeedbackBufferBinding;					break;
2463 		case GL_UNIFORM_BUFFER:				bindingPoint = &m_uniformBufferBinding;								break;
2464 		default:
2465 			DE_ASSERT(false);
2466 			return;
2467 	}
2468 
2469 	if (*bindingPoint)
2470 	{
2471 		m_buffers.releaseReference(*bindingPoint);
2472 		*bindingPoint = DE_NULL;
2473 	}
2474 
2475 	if (buffer)
2476 		m_buffers.acquireReference(buffer);
2477 
2478 	*bindingPoint = buffer;
2479 }
2480 
getBufferBinding(deUint32 target) const2481 DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
2482 {
2483 	const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2484 
2485 	switch (target)
2486 	{
2487 		case GL_ARRAY_BUFFER:				return m_arrayBufferBinding;
2488 		case GL_COPY_READ_BUFFER:			return m_copyReadBufferBinding;
2489 		case GL_COPY_WRITE_BUFFER:			return m_copyWriteBufferBinding;
2490 		case GL_DRAW_INDIRECT_BUFFER:		return m_drawIndirectBufferBinding;
2491 		case GL_ELEMENT_ARRAY_BUFFER:		return vertexArrayObject->m_elementArrayBufferBinding;
2492 		case GL_PIXEL_PACK_BUFFER:			return m_pixelPackBufferBinding;
2493 		case GL_PIXEL_UNPACK_BUFFER:		return m_pixelUnpackBufferBinding;
2494 		case GL_TRANSFORM_FEEDBACK_BUFFER:	return m_transformFeedbackBufferBinding;
2495 		case GL_UNIFORM_BUFFER:				return m_uniformBufferBinding;
2496 		default:
2497 			DE_ASSERT(false);
2498 			return DE_NULL;
2499 	}
2500 }
2501 
bindBuffer(deUint32 target,deUint32 buffer)2502 void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
2503 {
2504 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2505 
2506 	rc::DataBuffer*	bufObj	= DE_NULL;
2507 
2508 	if (buffer != 0)
2509 	{
2510 		bufObj = m_buffers.find(buffer);
2511 		if (!bufObj)
2512 		{
2513 			bufObj = new DataBuffer(buffer);
2514 			m_buffers.insert(bufObj);
2515 		}
2516 	}
2517 
2518 	setBufferBinding(target, bufObj);
2519 }
2520 
genBuffers(int numBuffers,deUint32 * buffers)2521 void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
2522 {
2523 	RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);
2524 
2525 	for (int ndx = 0; ndx < numBuffers; ndx++)
2526 		buffers[ndx] = m_buffers.allocateName();
2527 }
2528 
deleteBuffers(int numBuffers,const deUint32 * buffers)2529 void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
2530 {
2531 	RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);
2532 
2533 	for (int ndx = 0; ndx < numBuffers; ndx++)
2534 	{
2535 		deUint32	buffer	= buffers[ndx];
2536 		DataBuffer*	bufObj	= DE_NULL;
2537 
2538 		if (buffer == 0)
2539 			continue;
2540 
2541 		bufObj = m_buffers.find(buffer);
2542 
2543 		if (bufObj)
2544 			deleteBuffer(bufObj);
2545 	}
2546 }
2547 
deleteBuffer(DataBuffer * buffer)2548 void ReferenceContext::deleteBuffer (DataBuffer* buffer)
2549 {
2550 	static const deUint32 bindingPoints[] =
2551 	{
2552 		GL_ARRAY_BUFFER,
2553 		GL_COPY_READ_BUFFER,
2554 		GL_COPY_WRITE_BUFFER,
2555 		GL_DRAW_INDIRECT_BUFFER,
2556 		GL_ELEMENT_ARRAY_BUFFER,
2557 		GL_PIXEL_PACK_BUFFER,
2558 		GL_PIXEL_UNPACK_BUFFER,
2559 		GL_TRANSFORM_FEEDBACK_BUFFER,
2560 		GL_UNIFORM_BUFFER
2561 	};
2562 
2563 	for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
2564 	{
2565 		if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
2566 			setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
2567 	}
2568 
2569 	{
2570 		vector<VertexArray*> vertexArrays;
2571 		m_vertexArrays.getAll(vertexArrays);
2572 		vertexArrays.push_back(&m_clientVertexArray);
2573 
2574 		for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
2575 		{
2576 			if ((*i)->m_elementArrayBufferBinding == buffer)
2577 			{
2578 				m_buffers.releaseReference(buffer);
2579 				(*i)->m_elementArrayBufferBinding = DE_NULL;
2580 			}
2581 
2582 			for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
2583 			{
2584 				if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
2585 				{
2586 					m_buffers.releaseReference(buffer);
2587 					(*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
2588 					(*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
2589 				}
2590 			}
2591 		}
2592 	}
2593 
2594 	DE_ASSERT(buffer->getRefCount() == 1);
2595 	m_buffers.releaseReference(buffer);
2596 }
2597 
bufferData(deUint32 target,deIntptr size,const void * data,deUint32 usage)2598 void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
2599 {
2600 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2601 	RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2602 
2603 	DE_UNREF(usage);
2604 
2605 	DataBuffer* buffer = getBufferBinding(target);
2606 	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2607 
2608 	DE_ASSERT((deIntptr)(int)size == size);
2609 	buffer->setStorage((int)size);
2610 	if (data)
2611 		deMemcpy(buffer->getData(), data, (int)size);
2612 }
2613 
bufferSubData(deUint32 target,deIntptr offset,deIntptr size,const void * data)2614 void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
2615 {
2616 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2617 	RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2618 
2619 	DataBuffer* buffer = getBufferBinding(target);
2620 
2621 	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2622 	RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);
2623 
2624 	deMemcpy(buffer->getData()+offset, data, (int)size);
2625 }
2626 
clearColor(float red,float green,float blue,float alpha)2627 void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
2628 {
2629 	m_clearColor = Vec4(de::clamp(red,	0.0f, 1.0f),
2630 						de::clamp(green,	0.0f, 1.0f),
2631 						de::clamp(blue,	0.0f, 1.0f),
2632 						de::clamp(alpha,	0.0f, 1.0f));
2633 }
2634 
clearDepthf(float depth)2635 void ReferenceContext::clearDepthf (float depth)
2636 {
2637 	m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
2638 }
2639 
clearStencil(int stencil)2640 void ReferenceContext::clearStencil (int stencil)
2641 {
2642 	m_clearStencil = stencil;
2643 }
2644 
scissor(int x,int y,int width,int height)2645 void ReferenceContext::scissor (int x, int y, int width, int height)
2646 {
2647 	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
2648 	m_scissorBox = IVec4(x, y, width, height);
2649 }
2650 
enable(deUint32 cap)2651 void ReferenceContext::enable (deUint32 cap)
2652 {
2653 	switch (cap)
2654 	{
2655 		case GL_BLEND:					m_blendEnabled				= true;	break;
2656 		case GL_SCISSOR_TEST:			m_scissorEnabled			= true;	break;
2657 		case GL_DEPTH_TEST:				m_depthTestEnabled			= true;	break;
2658 		case GL_STENCIL_TEST:			m_stencilTestEnabled		= true;	break;
2659 		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= true;	break;
2660 
2661 		case GL_FRAMEBUFFER_SRGB:
2662 			if (glu::isContextTypeGLCore(getType()))
2663 			{
2664 				m_sRGBUpdateEnabled = true;
2665 				break;
2666 			}
2667 			setError(GL_INVALID_ENUM);
2668 			break;
2669 
2670 		case GL_DEPTH_CLAMP:
2671 			if (glu::isContextTypeGLCore(getType()))
2672 			{
2673 				m_depthClampEnabled = true;
2674 				break;
2675 			}
2676 			setError(GL_INVALID_ENUM);
2677 			break;
2678 
2679 		case GL_DITHER:
2680 			// Not implemented - just ignored.
2681 			break;
2682 
2683 		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2684 			if (!glu::isContextTypeGLCore(getType()))
2685 			{
2686 				m_primitiveRestartFixedIndex = true;
2687 				break;
2688 			}
2689 			setError(GL_INVALID_ENUM);
2690 			break;
2691 
2692 		case GL_PRIMITIVE_RESTART:
2693 			if (glu::isContextTypeGLCore(getType()))
2694 			{
2695 				m_primitiveRestartSettableIndex = true;
2696 				break;
2697 			}
2698 			setError(GL_INVALID_ENUM);
2699 			break;
2700 
2701 		default:
2702 			setError(GL_INVALID_ENUM);
2703 			break;
2704 	}
2705 }
2706 
disable(deUint32 cap)2707 void ReferenceContext::disable (deUint32 cap)
2708 {
2709 	switch (cap)
2710 	{
2711 		case GL_BLEND:					m_blendEnabled				= false;	break;
2712 		case GL_SCISSOR_TEST:			m_scissorEnabled			= false;	break;
2713 		case GL_DEPTH_TEST:				m_depthTestEnabled			= false;	break;
2714 		case GL_STENCIL_TEST:			m_stencilTestEnabled		= false;	break;
2715 		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= false;	break;
2716 
2717 		case GL_FRAMEBUFFER_SRGB:
2718 			if (glu::isContextTypeGLCore(getType()))
2719 			{
2720 				m_sRGBUpdateEnabled = false;
2721 				break;
2722 			}
2723 			setError(GL_INVALID_ENUM);
2724 			break;
2725 
2726 		case GL_DEPTH_CLAMP:
2727 			if (glu::isContextTypeGLCore(getType()))
2728 			{
2729 				m_depthClampEnabled = false;
2730 				break;
2731 			}
2732 			setError(GL_INVALID_ENUM);
2733 			break;
2734 
2735 		case GL_DITHER:
2736 			break;
2737 
2738 		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2739 			if (!glu::isContextTypeGLCore(getType()))
2740 			{
2741 				m_primitiveRestartFixedIndex = false;
2742 				break;
2743 			}
2744 			setError(GL_INVALID_ENUM);
2745 			break;
2746 
2747 		case GL_PRIMITIVE_RESTART:
2748 			if (glu::isContextTypeGLCore(getType()))
2749 			{
2750 				m_primitiveRestartSettableIndex = false;
2751 				break;
2752 			}
2753 			setError(GL_INVALID_ENUM);
2754 			break;
2755 
2756 		default:
2757 			setError(GL_INVALID_ENUM);
2758 			break;
2759 	}
2760 }
2761 
isValidCompareFunc(deUint32 func)2762 static bool isValidCompareFunc (deUint32 func)
2763 {
2764 	switch (func)
2765 	{
2766 		case GL_NEVER:
2767 		case GL_LESS:
2768 		case GL_LEQUAL:
2769 		case GL_GREATER:
2770 		case GL_GEQUAL:
2771 		case GL_EQUAL:
2772 		case GL_NOTEQUAL:
2773 		case GL_ALWAYS:
2774 			return true;
2775 
2776 		default:
2777 			return false;
2778 	}
2779 }
2780 
isValidStencilOp(deUint32 op)2781 static bool isValidStencilOp (deUint32 op)
2782 {
2783 	switch (op)
2784 	{
2785 		case GL_KEEP:
2786 		case GL_ZERO:
2787 		case GL_REPLACE:
2788 		case GL_INCR:
2789 		case GL_INCR_WRAP:
2790 		case GL_DECR:
2791 		case GL_DECR_WRAP:
2792 		case GL_INVERT:
2793 			return true;
2794 
2795 		default:
2796 			return false;
2797 	}
2798 }
2799 
stencilFunc(deUint32 func,int ref,deUint32 mask)2800 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
2801 {
2802 	stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2803 }
2804 
stencilFuncSeparate(deUint32 face,deUint32 func,int ref,deUint32 mask)2805 void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
2806 {
2807 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
2808 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
2809 
2810 	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2811 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2812 
2813 	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2814 	{
2815 		if ((type == rr::FACETYPE_FRONT && setFront) ||
2816 			(type == rr::FACETYPE_BACK && setBack))
2817 		{
2818 			m_stencil[type].func	= func;
2819 			m_stencil[type].ref		= ref;
2820 			m_stencil[type].opMask	= mask;
2821 		}
2822 	}
2823 }
2824 
stencilOp(deUint32 sfail,deUint32 dpfail,deUint32 dppass)2825 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2826 {
2827 	stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
2828 }
2829 
stencilOpSeparate(deUint32 face,deUint32 sfail,deUint32 dpfail,deUint32 dppass)2830 void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2831 {
2832 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
2833 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
2834 
2835 	RC_IF_ERROR(!isValidStencilOp(sfail)	||
2836 				!isValidStencilOp(dpfail)	||
2837 				!isValidStencilOp(dppass),
2838 				GL_INVALID_ENUM, RC_RET_VOID);
2839 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2840 
2841 	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2842 	{
2843 		if ((type == rr::FACETYPE_FRONT && setFront) ||
2844 			(type == rr::FACETYPE_BACK && setBack))
2845 		{
2846 			m_stencil[type].opStencilFail	= sfail;
2847 			m_stencil[type].opDepthFail		= dpfail;
2848 			m_stencil[type].opDepthPass		= dppass;
2849 		}
2850 	}
2851 }
2852 
depthFunc(deUint32 func)2853 void ReferenceContext::depthFunc (deUint32 func)
2854 {
2855 	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2856 	m_depthFunc = func;
2857 }
2858 
depthRangef(float n,float f)2859 void ReferenceContext::depthRangef (float n, float f)
2860 {
2861 	m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
2862 	m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
2863 }
2864 
depthRange(double n,double f)2865 void ReferenceContext::depthRange (double n, double f)
2866 {
2867 	depthRangef((float)n, (float)f);
2868 }
2869 
polygonOffset(float factor,float units)2870 void ReferenceContext::polygonOffset (float factor, float units)
2871 {
2872 	m_polygonOffsetFactor = factor;
2873 	m_polygonOffsetUnits = units;
2874 }
2875 
provokingVertex(deUint32 convention)2876 void ReferenceContext::provokingVertex (deUint32 convention)
2877 {
2878 	// only in core
2879 	DE_ASSERT(glu::isContextTypeGLCore(getType()));
2880 
2881 	switch (convention)
2882 	{
2883 		case GL_FIRST_VERTEX_CONVENTION:	m_provokingFirstVertexConvention = true; break;
2884 		case GL_LAST_VERTEX_CONVENTION:		m_provokingFirstVertexConvention = false; break;
2885 
2886 		default:
2887 			RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
2888 	}
2889 }
2890 
primitiveRestartIndex(deUint32 index)2891 void ReferenceContext::primitiveRestartIndex (deUint32 index)
2892 {
2893 	// only in core
2894 	DE_ASSERT(glu::isContextTypeGLCore(getType()));
2895 	m_primitiveRestartIndex = index;
2896 }
2897 
isValidBlendEquation(deUint32 mode)2898 static inline bool isValidBlendEquation (deUint32 mode)
2899 {
2900 	return mode == GL_FUNC_ADD				||
2901 		   mode == GL_FUNC_SUBTRACT			||
2902 		   mode == GL_FUNC_REVERSE_SUBTRACT	||
2903 		   mode == GL_MIN					||
2904 		   mode == GL_MAX;
2905 }
2906 
isValidBlendFactor(deUint32 factor)2907 static bool isValidBlendFactor (deUint32 factor)
2908 {
2909 	switch (factor)
2910 	{
2911 		case GL_ZERO:
2912 		case GL_ONE:
2913 		case GL_SRC_COLOR:
2914 		case GL_ONE_MINUS_SRC_COLOR:
2915 		case GL_DST_COLOR:
2916 		case GL_ONE_MINUS_DST_COLOR:
2917 		case GL_SRC_ALPHA:
2918 		case GL_ONE_MINUS_SRC_ALPHA:
2919 		case GL_DST_ALPHA:
2920 		case GL_ONE_MINUS_DST_ALPHA:
2921 		case GL_CONSTANT_COLOR:
2922 		case GL_ONE_MINUS_CONSTANT_COLOR:
2923 		case GL_CONSTANT_ALPHA:
2924 		case GL_ONE_MINUS_CONSTANT_ALPHA:
2925 		case GL_SRC_ALPHA_SATURATE:
2926 			return true;
2927 
2928 		default:
2929 			return false;
2930 	}
2931 }
2932 
blendEquation(deUint32 mode)2933 void ReferenceContext::blendEquation (deUint32 mode)
2934 {
2935 	RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);
2936 
2937 	m_blendModeRGB		= mode;
2938 	m_blendModeAlpha	= mode;
2939 }
2940 
blendEquationSeparate(deUint32 modeRGB,deUint32 modeAlpha)2941 void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
2942 {
2943 	RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
2944 				!isValidBlendEquation(modeAlpha),
2945 				GL_INVALID_ENUM, RC_RET_VOID);
2946 
2947 	m_blendModeRGB		= modeRGB;
2948 	m_blendModeAlpha	= modeAlpha;
2949 }
2950 
blendFunc(deUint32 src,deUint32 dst)2951 void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
2952 {
2953 	RC_IF_ERROR(!isValidBlendFactor(src) ||
2954 				!isValidBlendFactor(dst),
2955 				GL_INVALID_ENUM, RC_RET_VOID);
2956 
2957 	m_blendFactorSrcRGB		= src;
2958 	m_blendFactorSrcAlpha	= src;
2959 	m_blendFactorDstRGB		= dst;
2960 	m_blendFactorDstAlpha	= dst;
2961 }
2962 
blendFuncSeparate(deUint32 srcRGB,deUint32 dstRGB,deUint32 srcAlpha,deUint32 dstAlpha)2963 void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
2964 {
2965 	RC_IF_ERROR(!isValidBlendFactor(srcRGB)		||
2966 				!isValidBlendFactor(dstRGB)		||
2967 				!isValidBlendFactor(srcAlpha)	||
2968 				!isValidBlendFactor(dstAlpha),
2969 				GL_INVALID_ENUM, RC_RET_VOID);
2970 
2971 	m_blendFactorSrcRGB		= srcRGB;
2972 	m_blendFactorSrcAlpha	= srcAlpha;
2973 	m_blendFactorDstRGB		= dstRGB;
2974 	m_blendFactorDstAlpha	= dstAlpha;
2975 }
2976 
blendColor(float red,float green,float blue,float alpha)2977 void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
2978 {
2979 	m_blendColor = Vec4(de::clamp(red,	0.0f, 1.0f),
2980 						de::clamp(green,	0.0f, 1.0f),
2981 						de::clamp(blue,	0.0f, 1.0f),
2982 						de::clamp(alpha,	0.0f, 1.0f));
2983 }
2984 
colorMask(deBool r,deBool g,deBool b,deBool a)2985 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
2986 {
2987 	m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
2988 }
2989 
depthMask(deBool mask)2990 void ReferenceContext::depthMask (deBool mask)
2991 {
2992 	m_depthMask = !!mask;
2993 }
2994 
stencilMask(deUint32 mask)2995 void ReferenceContext::stencilMask (deUint32 mask)
2996 {
2997 	stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
2998 }
2999 
stencilMaskSeparate(deUint32 face,deUint32 mask)3000 void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
3001 {
3002 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
3003 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
3004 
3005 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
3006 
3007 	if (setFront)	m_stencil[rr::FACETYPE_FRONT].writeMask	= mask;
3008 	if (setBack)	m_stencil[rr::FACETYPE_BACK].writeMask	= mask;
3009 }
3010 
getNumStencilBits(const tcu::TextureFormat & format)3011 static int getNumStencilBits (const tcu::TextureFormat& format)
3012 {
3013 	switch (format.order)
3014 	{
3015 		case tcu::TextureFormat::S:
3016 			switch (format.type)
3017 			{
3018 				case tcu::TextureFormat::UNSIGNED_INT8:		return 8;
3019 				case tcu::TextureFormat::UNSIGNED_INT16:	return 16;
3020 				case tcu::TextureFormat::UNSIGNED_INT32:	return 32;
3021 				default:
3022 					DE_ASSERT(false);
3023 					return 0;
3024 			}
3025 
3026 		case tcu::TextureFormat::DS:
3027 			switch (format.type)
3028 			{
3029 				case tcu::TextureFormat::UNSIGNED_INT_24_8:				return 8;
3030 				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return 8;
3031 				default:
3032 					DE_ASSERT(false);
3033 					return 0;
3034 			}
3035 
3036 		default:
3037 			DE_ASSERT(false);
3038 			return 0;
3039 	}
3040 }
3041 
maskStencil(int numBits,deUint32 s)3042 static inline deUint32 maskStencil (int numBits, deUint32 s)
3043 {
3044 	return s & deBitMask32(0, numBits);
3045 }
3046 
writeMaskedStencil(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,deUint32 stencil,deUint32 writeMask)3047 static inline void writeMaskedStencil (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, deUint32 stencil, deUint32 writeMask)
3048 {
3049 	DE_ASSERT(access.raw().getFormat().order == tcu::TextureFormat::S);
3050 
3051 	const deUint32 oldVal = access.raw().getPixelUint(s, x, y).x();
3052 	const deUint32 newVal = (oldVal & ~writeMask) | (stencil & writeMask);
3053 	access.raw().setPixel(tcu::UVec4(newVal, 0u, 0u, 0u), s, x, y);
3054 }
3055 
writeDepthOnly(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,float depth)3056 static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
3057 {
3058 	access.raw().setPixDepth(depth, s, x, y);
3059 }
3060 
getDepthMultisampleAccess(const rr::MultisamplePixelBufferAccess & combinedDSaccess)3061 static rr::MultisamplePixelBufferAccess getDepthMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3062 {
3063 	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_DEPTH));
3064 }
3065 
getStencilMultisampleAccess(const rr::MultisamplePixelBufferAccess & combinedDSaccess)3066 static rr::MultisamplePixelBufferAccess getStencilMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3067 {
3068 	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_STENCIL));
3069 }
3070 
blitResolveMultisampleFramebuffer(deUint32 mask,const IVec4 & srcRect,const IVec4 & dstRect,bool flipX,bool flipY)3071 deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
3072 {
3073 	if (mask & GL_COLOR_BUFFER_BIT)
3074 	{
3075 		rr::MultisampleConstPixelBufferAccess	src			= rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3076 		tcu::PixelBufferAccess					dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3077 		tcu::TextureChannelClass				dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
3078 		bool									dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
3079 															  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
3080 															  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3081 		bool									srcIsSRGB	= tcu::isSRGB(src.raw().getFormat());
3082 		bool									dstIsSRGB	= tcu::isSRGB(dst.getFormat());
3083 		const bool								convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3084 
3085 		if (!convertSRGB)
3086 		{
3087 			tcu::ConstPixelBufferAccess	srcRaw	= src.raw();
3088 			tcu::TextureFormat			srcFmt	= toNonSRGBFormat(srcRaw.getFormat());
3089 
3090 			srcRaw	= tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
3091 			src		= rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);
3092 
3093 			dst		= tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3094 		}
3095 
3096 		for (int x = 0; x < dstRect.z(); ++x)
3097 		for (int y = 0; y < dstRect.w(); ++y)
3098 		{
3099 			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3100 			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3101 
3102 			if (dstIsFloat || srcIsSRGB)
3103 			{
3104 				Vec4 p = src.raw().getPixel(0, srcX,srcY);
3105 				dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
3106 			}
3107 			else
3108 				dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
3109 		}
3110 	}
3111 
3112 	if (mask & GL_DEPTH_BUFFER_BIT)
3113 	{
3114 		rr::MultisampleConstPixelBufferAccess	src	= rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3115 		rr::MultisamplePixelBufferAccess		dst	= rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3116 
3117 		for (int x = 0; x < dstRect.z(); ++x)
3118 		for (int y = 0; y < dstRect.w(); ++y)
3119 		{
3120 			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3121 			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3122 
3123 			writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
3124 		}
3125 	}
3126 
3127 	if (mask & GL_STENCIL_BUFFER_BIT)
3128 	{
3129 		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3130 		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3131 
3132 		for (int x = 0; x < dstRect.z(); ++x)
3133 		for (int y = 0; y < dstRect.w(); ++y)
3134 		{
3135 			int			srcX		= (flipX) ? (srcRect.z() - x - 1) : (x);
3136 			int			srcY		= (flipY) ? (srcRect.z() - y - 1) : (y);
3137 			deUint32	srcStencil	= src.raw().getPixelUint(0, srcX, srcY).x();
3138 
3139 			writeMaskedStencil(dst, 0, x, y, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3140 		}
3141 	}
3142 
3143 	return GL_NO_ERROR;
3144 }
3145 
blitFramebuffer(int srcX0,int srcY0,int srcX1,int srcY1,int dstX0,int dstY0,int dstX1,int dstY1,deUint32 mask,deUint32 filter)3146 void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
3147 {
3148 	// p0 in inclusive, p1 exclusive.
3149 	// Negative width/height means swap.
3150 	bool	swapSrcX	= srcX1 < srcX0;
3151 	bool	swapSrcY	= srcY1 < srcY0;
3152 	bool	swapDstX	= dstX1 < dstX0;
3153 	bool	swapDstY	= dstY1 < dstY0;
3154 	int		srcW		= de::abs(srcX1-srcX0);
3155 	int		srcH		= de::abs(srcY1-srcY0);
3156 	int		dstW		= de::abs(dstX1-dstX0);
3157 	int		dstH		= de::abs(dstY1-dstY0);
3158 	bool	scale		= srcW != dstW || srcH != dstH;
3159 	int		srcOriginX	= swapSrcX ? srcX1 : srcX0;
3160 	int		srcOriginY	= swapSrcY ? srcY1 : srcY0;
3161 	int		dstOriginX	= swapDstX ? dstX1 : dstX0;
3162 	int		dstOriginY	= swapDstY ? dstY1 : dstY0;
3163 	IVec4	srcRect		= IVec4(srcOriginX, srcOriginY, srcW, srcH);
3164 	IVec4	dstRect		= IVec4(dstOriginX, dstOriginY, dstW, dstH);
3165 
3166 	RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
3167 	RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);
3168 
3169 	// Validate that both targets are complete.
3170 	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
3171 				checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);
3172 
3173 	// Check samples count is valid
3174 	RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);
3175 
3176 	// Check size restrictions of multisampled case
3177 	if (getReadColorbuffer().getNumSamples() != 1)
3178 	{
3179 		// Src and Dst rect dimensions must be the same
3180 		RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);
3181 
3182 		// Framebuffer formats must match
3183 		if (mask & GL_COLOR_BUFFER_BIT)		RC_IF_ERROR(getReadColorbuffer().raw().getFormat()   != getDrawColorbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3184 		if (mask & GL_DEPTH_BUFFER_BIT)		RC_IF_ERROR(getReadDepthbuffer().raw().getFormat()   != getDrawDepthbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3185 		if (mask & GL_STENCIL_BUFFER_BIT)	RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3186 	}
3187 
3188 	// Compute actual source rect.
3189 	srcRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadColorbuffer()))	: srcRect;
3190 	srcRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadDepthbuffer()))	: srcRect;
3191 	srcRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(srcRect, getBufferRect(getReadStencilbuffer()))	: srcRect;
3192 
3193 	// Compute destination rect.
3194 	dstRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawColorbuffer()))	: dstRect;
3195 	dstRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawDepthbuffer()))	: dstRect;
3196 	dstRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(dstRect, getBufferRect(getDrawStencilbuffer()))	: dstRect;
3197 	dstRect = m_scissorEnabled					? intersect(dstRect, m_scissorBox)							: dstRect;
3198 
3199 	if (isEmpty(srcRect) || isEmpty(dstRect))
3200 		return; // Don't attempt copy.
3201 
3202 	// Multisampled read buffer is a special case
3203 	if (getReadColorbuffer().getNumSamples() != 1)
3204 	{
3205 		deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);
3206 
3207 		if (error != GL_NO_ERROR)
3208 			setError(error);
3209 
3210 		return;
3211 	}
3212 
3213 	// \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
3214 
3215 	// Coordinate transformation:
3216 	// Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
3217 	tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
3218 						* tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
3219 										 (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
3220 										 1.0f))
3221 						* tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));
3222 
3223 	if (mask & GL_COLOR_BUFFER_BIT)
3224 	{
3225 		tcu::ConstPixelBufferAccess		src			= tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3226 		tcu::PixelBufferAccess			dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3227 		tcu::TextureChannelClass		dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
3228 		bool							dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
3229 													  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
3230 													  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3231 		tcu::Sampler::FilterMode		sFilter		= (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3232 		tcu::Sampler					sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
3233 													 sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
3234 		bool							srcIsSRGB	= tcu::isSRGB(src.getFormat());
3235 		bool							dstIsSRGB	= tcu::isSRGB(dst.getFormat());
3236 		const bool						convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3237 
3238 		if (!convertSRGB)
3239 		{
3240 			src	= tcu::ConstPixelBufferAccess	(toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
3241 			dst	= tcu::PixelBufferAccess		(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3242 		}
3243 
3244 		// \note We don't check for unsupported conversions, unlike spec requires.
3245 
3246 		for (int yo = 0; yo < dstRect.w(); yo++)
3247 		{
3248 			for (int xo = 0; xo < dstRect.z(); xo++)
3249 			{
3250 				float	dX	= (float)xo + 0.5f;
3251 				float	dY	= (float)yo + 0.5f;
3252 
3253 				// \note Only affine part is used.
3254 				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3255 				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3256 
3257 				// do not copy pixels outside the modified source region (modified by buffer intersection)
3258 				if (sX < 0.0f || sX >= (float)srcRect.z() ||
3259 					sY < 0.0f || sY >= (float)srcRect.w())
3260 					continue;
3261 
3262 				if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
3263 				{
3264 					Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
3265 					dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
3266 				}
3267 				else
3268 					dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
3269 			}
3270 		}
3271 	}
3272 
3273 	if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
3274 	{
3275 		rr::MultisampleConstPixelBufferAccess	src		= getDepthMultisampleAccess(rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3276 		rr::MultisamplePixelBufferAccess		dst		= getDepthMultisampleAccess(rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3277 
3278 		for (int yo = 0; yo < dstRect.w(); yo++)
3279 		{
3280 			for (int xo = 0; xo < dstRect.z(); xo++)
3281 			{
3282 				const int sampleNdx = 0; // multisample read buffer case is already handled
3283 
3284 				float	dX	= (float)xo + 0.5f;
3285 				float	dY	= (float)yo + 0.5f;
3286 				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3287 				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3288 
3289 				writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixDepth(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)));
3290 			}
3291 		}
3292 	}
3293 
3294 	if (mask & GL_STENCIL_BUFFER_BIT)
3295 	{
3296 		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3297 		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3298 
3299 		for (int yo = 0; yo < dstRect.w(); yo++)
3300 		{
3301 			for (int xo = 0; xo < dstRect.z(); xo++)
3302 			{
3303 				const int	sampleNdx = 0; // multisample read buffer case is already handled
3304 
3305 				float		dX			= (float)xo + 0.5f;
3306 				float		dY			= (float)yo + 0.5f;
3307 				float		sX			= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3308 				float		sY			= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3309 				deUint32	srcStencil	= src.raw().getPixelUint(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x();
3310 
3311 				writeMaskedStencil(dst, sampleNdx, xo, yo, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3312 			}
3313 		}
3314 	}
3315 }
3316 
invalidateSubFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments,int x,int y,int width,int height)3317 void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
3318 {
3319 	RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
3320 	RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
3321 	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
3322 
3323 	// \todo [2012-07-17 pyry] Support multiple color attachments.
3324 
3325 	const Vec4		colorClearValue		(0.0f);
3326 	const float		depthClearValue		= 1.0f;
3327 	const int		stencilClearValue	= 0;
3328 
3329 	bool			isFboBound			= m_drawFramebufferBinding != DE_NULL;
3330 	bool			discardBuffers[3]	= { false, false, false }; // Color, depth, stencil
3331 
3332 	for (int attNdx = 0; attNdx < numAttachments; attNdx++)
3333 	{
3334 		bool	isColor			= attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0		: GL_COLOR);
3335 		bool	isDepth			= attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT		: GL_DEPTH);
3336 		bool	isStencil		= attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT	: GL_STENCIL);
3337 		bool	isDepthStencil	= isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;
3338 
3339 		RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);
3340 
3341 		if (isColor)						discardBuffers[0] = true;
3342 		if (isDepth || isDepthStencil)		discardBuffers[1] = true;
3343 		if (isStencil || isDepthStencil)	discardBuffers[2] = true;
3344 	}
3345 
3346 	for (int ndx = 0; ndx < 3; ndx++)
3347 	{
3348 		if (!discardBuffers[ndx])
3349 			continue;
3350 
3351 		bool								isColor					= ndx == 0;
3352 		bool								isDepth					= ndx == 1;
3353 		bool								isStencil				= ndx == 2;
3354 		rr::MultisamplePixelBufferAccess	buf						= isColor ? getDrawColorbuffer()								:
3355 																	  isDepth ? getDepthMultisampleAccess(getDrawDepthbuffer())		:
3356 																				getStencilMultisampleAccess(getDrawStencilbuffer());
3357 
3358 		if (isEmpty(buf))
3359 			continue;
3360 
3361 		tcu::IVec4							area					= intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
3362 		rr::MultisamplePixelBufferAccess	access					= rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());
3363 
3364 		if (isColor)
3365 			rr::clear(access, colorClearValue);
3366 		else if (isDepth)
3367 			rr::clear(access, tcu::Vec4(depthClearValue));
3368 		else if (isStencil)
3369 			rr::clear(access, tcu::IVec4(stencilClearValue));
3370 	}
3371 }
3372 
invalidateFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments)3373 void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
3374 {
3375 	// \todo [2012-07-17 pyry] Support multiple color attachments.
3376 	rr::MultisampleConstPixelBufferAccess	colorBuf0	= getDrawColorbuffer();
3377 	rr::MultisampleConstPixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3378 	rr::MultisampleConstPixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3379 	int										width		= 0;
3380 	int										height		= 0;
3381 
3382 	width = de::max(width, colorBuf0.raw().getHeight());
3383 	width = de::max(width, depthBuf.raw().getHeight());
3384 	width = de::max(width, stencilBuf.raw().getHeight());
3385 
3386 	height = de::max(height, colorBuf0.raw().getDepth());
3387 	height = de::max(height, depthBuf.raw().getDepth());
3388 	height = de::max(height, stencilBuf.raw().getDepth());
3389 
3390 	invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
3391 }
3392 
clear(deUint32 buffers)3393 void ReferenceContext::clear (deUint32 buffers)
3394 {
3395 	RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);
3396 
3397 	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
3398 	rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3399 	rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3400 	IVec4								baseArea	= m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3401 	IVec4								colorArea	= intersect(baseArea, getBufferRect(colorBuf0));
3402 	IVec4								depthArea	= intersect(baseArea, getBufferRect(depthBuf));
3403 	IVec4								stencilArea	= intersect(baseArea, getBufferRect(stencilBuf));
3404 	bool								hasColor0	= !isEmpty(colorArea);
3405 	bool								hasDepth	= !isEmpty(depthArea);
3406 	bool								hasStencil	= !isEmpty(stencilArea);
3407 
3408 	if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
3409 	{
3410 		rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
3411 		bool								isSRGB		= tcu::isSRGB(colorBuf0.raw().getFormat());
3412 		Vec4								c			= (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
3413 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3414 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3415 
3416 		if (!maskUsed)
3417 			rr::clear(access, c);
3418 		else if (!maskZero)
3419 		{
3420 			for (int y = 0; y < access.raw().getDepth(); y++)
3421 				for (int x = 0; x < access.raw().getHeight(); x++)
3422 					for (int s = 0; s < access.getNumSamples(); s++)
3423 						access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3424 		}
3425 		// else all channels masked out
3426 	}
3427 
3428 	if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
3429 	{
3430 		rr::MultisamplePixelBufferAccess access = getDepthMultisampleAccess(rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w()));
3431 		rr::clearDepth(access, m_clearDepth);
3432 	}
3433 
3434 	if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
3435 	{
3436 		rr::MultisamplePixelBufferAccess	access					= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w()));
3437 		int									stencilBits				= getNumStencilBits(stencilBuf.raw().getFormat());
3438 		int									stencil					= maskStencil(stencilBits, m_clearStencil);
3439 
3440 		if ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u))
3441 		{
3442 			// Slow path where depth or stencil is masked out in write.
3443 			for (int y = 0; y < access.raw().getDepth(); y++)
3444 				for (int x = 0; x < access.raw().getHeight(); x++)
3445 					for (int s = 0; s < access.getNumSamples(); s++)
3446 						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3447 		}
3448 		else
3449 			rr::clearStencil(access, stencil);
3450 	}
3451 }
3452 
clearBufferiv(deUint32 buffer,int drawbuffer,const int * value)3453 void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
3454 {
3455 	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3456 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3457 
3458 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3459 
3460 	if (buffer == GL_COLOR)
3461 	{
3462 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3463 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3464 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3465 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3466 
3467 		if (!isEmpty(area) && !maskZero)
3468 		{
3469 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3470 			IVec4								color		(value[0], value[1], value[2], value[3]);
3471 
3472 			if (!maskUsed)
3473 				rr::clear(access, color);
3474 			else
3475 			{
3476 				for (int y = 0; y < access.raw().getDepth(); y++)
3477 					for (int x = 0; x < access.raw().getHeight(); x++)
3478 						for (int s = 0; s < access.getNumSamples(); s++)
3479 							access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
3480 			}
3481 		}
3482 	}
3483 	else
3484 	{
3485 		TCU_CHECK_INTERNAL(buffer == GL_STENCIL);
3486 
3487 		rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3488 		IVec4								area		= intersect(baseArea, getBufferRect(stencilBuf));
3489 
3490 		if (!isEmpty(area) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
3491 		{
3492 			rr::MultisamplePixelBufferAccess	access		= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w()));
3493 			int									stencil		= value[0];
3494 
3495 			for (int y = 0; y < access.raw().getDepth(); y++)
3496 				for (int x = 0; x < access.raw().getHeight(); x++)
3497 					for (int s = 0; s < access.getNumSamples(); s++)
3498 						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3499 		}
3500 	}
3501 }
3502 
clearBufferfv(deUint32 buffer,int drawbuffer,const float * value)3503 void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
3504 {
3505 	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
3506 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3507 
3508 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3509 
3510 	if (buffer == GL_COLOR)
3511 	{
3512 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3513 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3514 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3515 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3516 
3517 		if (!isEmpty(area) && !maskZero)
3518 		{
3519 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3520 			Vec4								color		(value[0], value[1], value[2], value[3]);
3521 
3522 			if (m_sRGBUpdateEnabled && tcu::isSRGB(access.raw().getFormat()))
3523 				color = tcu::linearToSRGB(color);
3524 
3525 			if (!maskUsed)
3526 				rr::clear(access, color);
3527 			else
3528 			{
3529 				for (int y = 0; y < access.raw().getDepth(); y++)
3530 					for (int x = 0; x < access.raw().getHeight(); x++)
3531 						for (int s = 0; s < access.getNumSamples(); s++)
3532 							access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3533 			}
3534 		}
3535 	}
3536 	else
3537 	{
3538 		TCU_CHECK_INTERNAL(buffer == GL_DEPTH);
3539 
3540 		rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3541 		IVec4								area		= intersect(baseArea, getBufferRect(depthBuf));
3542 
3543 		if (!isEmpty(area) && m_depthMask)
3544 		{
3545 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
3546 			float								depth		= value[0];
3547 
3548 			rr::clearDepth(access, depth);
3549 		}
3550 	}
3551 }
3552 
clearBufferuiv(deUint32 buffer,int drawbuffer,const deUint32 * value)3553 void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
3554 {
3555 	RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
3556 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3557 
3558 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3559 
3560 	TCU_CHECK_INTERNAL(buffer == GL_COLOR);
3561 	{
3562 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3563 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3564 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3565 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3566 
3567 		if (!isEmpty(area) && !maskZero)
3568 		{
3569 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3570 			tcu::UVec4							color		(value[0], value[1], value[2], value[3]);
3571 
3572 			if (!maskUsed)
3573 				rr::clear(access, color.asInt());
3574 			else
3575 			{
3576 				for (int y = 0; y < access.raw().getDepth(); y++)
3577 					for (int x = 0; x < access.raw().getHeight(); x++)
3578 						for (int s = 0; s < access.getNumSamples(); s++)
3579 							access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
3580 			}
3581 		}
3582 	}
3583 }
3584 
clearBufferfi(deUint32 buffer,int drawbuffer,float depth,int stencil)3585 void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
3586 {
3587 	RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3588 	clearBufferfv(GL_DEPTH, drawbuffer, &depth);
3589 	clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
3590 }
3591 
bindVertexArray(deUint32 array)3592 void ReferenceContext::bindVertexArray (deUint32 array)
3593 {
3594 	rc::VertexArray* vertexArrayObject = DE_NULL;
3595 
3596 	if (array != 0)
3597 	{
3598 		vertexArrayObject = m_vertexArrays.find(array);
3599 		if (!vertexArrayObject)
3600 		{
3601 			vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
3602 			m_vertexArrays.insert(vertexArrayObject);
3603 		}
3604 	}
3605 
3606 	// Create new references
3607 	if (vertexArrayObject)
3608 		m_vertexArrays.acquireReference(vertexArrayObject);
3609 
3610 	// Remove old references
3611 	if (m_vertexArrayBinding)
3612 		m_vertexArrays.releaseReference(m_vertexArrayBinding);
3613 
3614 	m_vertexArrayBinding = vertexArrayObject;
3615 }
3616 
genVertexArrays(int numArrays,deUint32 * vertexArrays)3617 void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
3618 {
3619 	RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);
3620 
3621 	for (int ndx = 0; ndx < numArrays; ndx++)
3622 		vertexArrays[ndx] = m_vertexArrays.allocateName();
3623 }
3624 
deleteVertexArrays(int numArrays,const deUint32 * vertexArrays)3625 void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
3626 {
3627 	for (int i = 0; i < numArrays; i++)
3628 	{
3629 		deUint32		name		= vertexArrays[i];
3630 		VertexArray*	vertexArray	= name ? m_vertexArrays.find(name) : DE_NULL;
3631 
3632 		if (vertexArray)
3633 			deleteVertexArray(vertexArray);
3634 	}
3635 }
3636 
vertexAttribPointer(deUint32 index,int rawSize,deUint32 type,deBool normalized,int stride,const void * pointer)3637 void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
3638 {
3639 	const bool allowBGRA	= !glu::isContextTypeES(getType());
3640 	const int effectiveSize	= (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);
3641 
3642 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3643 	RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
3644 	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
3645 				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
3646 				type != GL_INT					&&	type != GL_UNSIGNED_INT		&&
3647 				type != GL_FIXED				&&	type != GL_DOUBLE			&&
3648 				type != GL_FLOAT				&&	type != GL_HALF_FLOAT		&&
3649 				type != GL_INT_2_10_10_10_REV	&&	type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
3650 	RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3651 	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3652 	RC_IF_ERROR((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && effectiveSize != 4, GL_INVALID_OPERATION, RC_RET_VOID);
3653 	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3654 	RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE, GL_INVALID_OPERATION, RC_RET_VOID);
3655 	RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);
3656 
3657 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3658 
3659 	vao.m_arrays[index].size			= rawSize;
3660 	vao.m_arrays[index].stride			= stride;
3661 	vao.m_arrays[index].type			= type;
3662 	vao.m_arrays[index].normalized		= normalized == GL_TRUE;
3663 	vao.m_arrays[index].integer			= false;
3664 	vao.m_arrays[index].pointer			= pointer;
3665 
3666 	// acquire new reference
3667 	if (m_arrayBufferBinding)
3668 		m_buffers.acquireReference(m_arrayBufferBinding);
3669 
3670 	// release old reference
3671 	if (vao.m_arrays[index].bufferBinding)
3672 		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3673 
3674 	vao.m_arrays[index].bufferDeleted	= false;
3675 	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
3676 }
3677 
vertexAttribIPointer(deUint32 index,int size,deUint32 type,int stride,const void * pointer)3678 void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
3679 {
3680 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3681 	RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
3682 	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
3683 				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
3684 				type != GL_INT					&&	type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
3685 	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3686 	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3687 
3688 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3689 
3690 	vao.m_arrays[index].size			= size;
3691 	vao.m_arrays[index].stride			= stride;
3692 	vao.m_arrays[index].type			= type;
3693 	vao.m_arrays[index].normalized		= false;
3694 	vao.m_arrays[index].integer			= true;
3695 	vao.m_arrays[index].pointer			= pointer;
3696 
3697 	// acquire new reference
3698 	if (m_arrayBufferBinding)
3699 		m_buffers.acquireReference(m_arrayBufferBinding);
3700 
3701 	// release old reference
3702 	if (vao.m_arrays[index].bufferBinding)
3703 		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3704 
3705 	vao.m_arrays[index].bufferDeleted	= false;
3706 	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
3707 }
3708 
enableVertexAttribArray(deUint32 index)3709 void ReferenceContext::enableVertexAttribArray (deUint32 index)
3710 {
3711 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3712 
3713 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3714 	vao.m_arrays[index].enabled = true;
3715 }
3716 
disableVertexAttribArray(deUint32 index)3717 void ReferenceContext::disableVertexAttribArray (deUint32 index)
3718 {
3719 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3720 
3721 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3722 	vao.m_arrays[index].enabled = false;
3723 }
3724 
vertexAttribDivisor(deUint32 index,deUint32 divisor)3725 void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
3726 {
3727 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3728 
3729 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3730 	vao.m_arrays[index].divisor = divisor;
3731 }
3732 
vertexAttrib1f(deUint32 index,float x)3733 void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
3734 {
3735 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3736 
3737 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
3738 }
3739 
vertexAttrib2f(deUint32 index,float x,float y)3740 void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
3741 {
3742 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3743 
3744 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
3745 }
3746 
vertexAttrib3f(deUint32 index,float x,float y,float z)3747 void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
3748 {
3749 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3750 
3751 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
3752 }
3753 
vertexAttrib4f(deUint32 index,float x,float y,float z,float w)3754 void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
3755 {
3756 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3757 
3758 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
3759 }
3760 
vertexAttribI4i(deUint32 index,deInt32 x,deInt32 y,deInt32 z,deInt32 w)3761 void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
3762 {
3763 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3764 
3765 	m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
3766 }
3767 
vertexAttribI4ui(deUint32 index,deUint32 x,deUint32 y,deUint32 z,deUint32 w)3768 void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
3769 {
3770 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3771 
3772 	m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
3773 }
3774 
getAttribLocation(deUint32 program,const char * name)3775 deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
3776 {
3777 	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3778 
3779 	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3780 
3781 	if (name)
3782 	{
3783 		std::string nameString(name);
3784 
3785 		for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
3786 			if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
3787 				return (int)ndx;
3788 	}
3789 
3790 	return -1;
3791 }
3792 
uniformv(deInt32 location,glu::DataType type,deInt32 count,const void * v)3793 void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
3794 {
3795 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3796 
3797 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3798 
3799 	if (location == -1)
3800 		return;
3801 
3802 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3803 	RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
3804 	RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3805 
3806 	{
3807 		const int scalarSize = glu::getDataTypeScalarSize(type);
3808 		DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
3809 		deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
3810 	}
3811 }
3812 
uniform1iv(deInt32 location,deInt32 count,const deInt32 * v)3813 void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
3814 {
3815 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3816 
3817 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3818 
3819 	if (location == -1)
3820 		return;
3821 
3822 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3823 	RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3824 
3825 	switch (uniforms[location].type)
3826 	{
3827 		case glu::TYPE_INT:		uniforms[location].value.i = *v;	return;
3828 
3829 		// \note texture unit is stored to value
3830 		case glu::TYPE_SAMPLER_2D:
3831 		case glu::TYPE_UINT_SAMPLER_2D:
3832 		case glu::TYPE_INT_SAMPLER_2D:
3833 		case glu::TYPE_SAMPLER_CUBE:
3834 		case glu::TYPE_UINT_SAMPLER_CUBE:
3835 		case glu::TYPE_INT_SAMPLER_CUBE:
3836 		case glu::TYPE_SAMPLER_2D_ARRAY:
3837 		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
3838 		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
3839 		case glu::TYPE_SAMPLER_3D:
3840 		case glu::TYPE_UINT_SAMPLER_3D:
3841 		case glu::TYPE_INT_SAMPLER_3D:
3842 		case glu::TYPE_SAMPLER_CUBE_ARRAY:
3843 		case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
3844 		case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
3845 			uniforms[location].value.i = *v;
3846 			return;
3847 
3848 		default:
3849 			setError(GL_INVALID_OPERATION);
3850 			return;
3851 	}
3852 }
3853 
uniform1f(deInt32 location,const float v0)3854 void ReferenceContext::uniform1f (deInt32 location, const float v0)
3855 {
3856 	uniform1fv(location, 1, &v0);
3857 }
3858 
uniform1i(deInt32 location,deInt32 v0)3859 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
3860 {
3861 	uniform1iv(location, 1, &v0);
3862 }
3863 
uniform1fv(deInt32 location,deInt32 count,const float * v)3864 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
3865 {
3866 	uniformv(location, glu::TYPE_FLOAT, count, v);
3867 }
3868 
uniform2fv(deInt32 location,deInt32 count,const float * v)3869 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
3870 {
3871 	uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
3872 }
3873 
uniform3fv(deInt32 location,deInt32 count,const float * v)3874 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
3875 {
3876 	uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
3877 }
3878 
uniform4fv(deInt32 location,deInt32 count,const float * v)3879 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
3880 {
3881 	uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
3882 }
3883 
uniform2iv(deInt32 location,deInt32 count,const deInt32 * v)3884 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
3885 {
3886 	uniformv(location, glu::TYPE_INT_VEC2, count, v);
3887 }
3888 
uniform3iv(deInt32 location,deInt32 count,const deInt32 * v)3889 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
3890 {
3891 	uniformv(location, glu::TYPE_INT_VEC3, count, v);
3892 }
3893 
uniform4iv(deInt32 location,deInt32 count,const deInt32 * v)3894 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
3895 {
3896 	uniformv(location, glu::TYPE_INT_VEC4, count, v);
3897 }
3898 
uniformMatrix3fv(deInt32 location,deInt32 count,deBool transpose,const float * value)3899 void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3900 {
3901 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3902 
3903 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3904 
3905 	if (location == -1)
3906 		return;
3907 
3908 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3909 
3910 	if (count == 0)
3911 		return;
3912 
3913 	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3914 
3915 	switch (uniforms[location].type)
3916 	{
3917 		case glu::TYPE_FLOAT_MAT3:
3918 			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3919 
3920 			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3921 				for (int row = 0; row < 3; ++row)
3922 				for (int col = 0; col < 3; ++col)
3923 					uniforms[location].value.m3[row*3+col] = value[col*3+row];
3924 			else // input is row major
3925 				for (int row = 0; row < 3; ++row)
3926 				for (int col = 0; col < 3; ++col)
3927 					uniforms[location].value.m3[row*3+col] = value[row*3+col];
3928 
3929 			break;
3930 
3931 		default:
3932 			setError(GL_INVALID_OPERATION);
3933 			return;
3934 	}
3935 }
3936 
uniformMatrix4fv(deInt32 location,deInt32 count,deBool transpose,const float * value)3937 void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3938 {
3939 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3940 
3941 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3942 
3943 	if (location == -1)
3944 		return;
3945 
3946 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3947 
3948 	if (count == 0)
3949 		return;
3950 
3951 	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3952 
3953 	switch (uniforms[location].type)
3954 	{
3955 		case glu::TYPE_FLOAT_MAT4:
3956 			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3957 
3958 			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3959 				for (int row = 0; row < 4; ++row)
3960 				for (int col = 0; col < 4; ++col)
3961 					uniforms[location].value.m4[row*3+col] = value[col*3+row];
3962 			else // input is row major
3963 				for (int row = 0; row < 4; ++row)
3964 				for (int col = 0; col < 4; ++col)
3965 					uniforms[location].value.m4[row*3+col] = value[row*3+col];
3966 
3967 			break;
3968 
3969 		default:
3970 			setError(GL_INVALID_OPERATION);
3971 			return;
3972 	}
3973 }
3974 
getUniformLocation(deUint32 program,const char * name)3975 deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
3976 {
3977 	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3978 	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3979 
3980 	std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;
3981 
3982 	for (size_t i = 0; i < uniforms.size(); ++i)
3983 		if (name && deStringEqual(uniforms[i].name.c_str(), name))
3984 			return (int)i;
3985 
3986 	return -1;
3987 }
3988 
lineWidth(float w)3989 void ReferenceContext::lineWidth (float w)
3990 {
3991 	RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
3992 	m_lineWidth = w;
3993 }
3994 
deleteVertexArray(rc::VertexArray * vertexArray)3995 void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
3996 {
3997 	if (m_vertexArrayBinding == vertexArray)
3998 		bindVertexArray(0);
3999 
4000 	if (vertexArray->m_elementArrayBufferBinding)
4001 		m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);
4002 
4003 	for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
4004 		if (vertexArray->m_arrays[ndx].bufferBinding)
4005 			m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);
4006 
4007 	DE_ASSERT(vertexArray->getRefCount() == 1);
4008 	m_vertexArrays.releaseReference(vertexArray);
4009 }
4010 
deleteProgramObject(rc::ShaderProgramObjectContainer * sp)4011 void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
4012 {
4013 	// Unbinding program will delete it
4014 	if (m_currentProgram == sp && sp->m_deleteFlag)
4015 	{
4016 		useProgram(0);
4017 		return;
4018 	}
4019 
4020 	// Unbinding program will NOT delete it
4021 	if (m_currentProgram == sp)
4022 		useProgram(0);
4023 
4024 	DE_ASSERT(sp->getRefCount() == 1);
4025 	m_programs.releaseReference(sp);
4026 }
4027 
drawArrays(deUint32 mode,int first,int count)4028 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
4029 {
4030 	drawArraysInstanced(mode, first, count, 1);
4031 }
4032 
drawArraysInstanced(deUint32 mode,int first,int count,int instanceCount)4033 void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
4034 {
4035 	// Error conditions
4036 	{
4037 		RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4038 
4039 		if (!predrawErrorChecks(mode))
4040 			return;
4041 	}
4042 
4043 	// All is ok
4044 	{
4045 		const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4046 
4047 		drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
4048 	}
4049 }
4050 
drawElements(deUint32 mode,int count,deUint32 type,const void * indices)4051 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
4052 {
4053 	drawElementsInstanced(mode, count, type, indices, 1);
4054 }
4055 
drawElementsBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int baseVertex)4056 void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
4057 {
4058 	drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
4059 }
4060 
drawElementsInstanced(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount)4061 void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
4062 {
4063 	drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
4064 }
4065 
drawElementsInstancedBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount,int baseVertex)4066 void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
4067 {
4068 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4069 
4070 	// Error conditions
4071 	{
4072 		RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4073 					type != GL_UNSIGNED_SHORT &&
4074 					type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4075 		RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4076 
4077 		if (!predrawErrorChecks(mode))
4078 			return;
4079 	}
4080 
4081 	// All is ok
4082 	{
4083 		const rr::PrimitiveType primitiveType	= sglr::rr_util::mapGLPrimitiveType(mode);
4084 		const void*				indicesPtr		= (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + ((const deUint8*)indices - (const deUint8*)DE_NULL)) : (indices);
4085 
4086 		drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
4087 	}
4088 }
4089 
drawRangeElements(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices)4090 void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
4091 {
4092 	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4093 
4094 	drawElements(mode, count, type, indices);
4095 }
4096 
drawRangeElementsBaseVertex(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices,int baseVertex)4097 void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
4098 {
4099 	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4100 
4101 	drawElementsBaseVertex(mode, count, type, indices, baseVertex);
4102 }
4103 
drawArraysIndirect(deUint32 mode,const void * indirect)4104 void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
4105 {
4106 	struct DrawArraysIndirectCommand
4107 	{
4108 		deUint32 count;
4109 		deUint32 primCount;
4110 		deUint32 first;
4111 		deUint32 reservedMustBeZero;
4112 	};
4113 
4114 	const DrawArraysIndirectCommand* command;
4115 
4116 	// Check errors
4117 
4118 	if (!predrawErrorChecks(mode))
4119 		return;
4120 
4121 	// Check pointer validity
4122 
4123 	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4124 	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4125 
4126 	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4127 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                     > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4128 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) + sizeof(DrawArraysIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4129 
4130 	// Check values
4131 
4132 	command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4133 	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4134 
4135 	// draw
4136 	drawArraysInstanced(mode, command->first, command->count, command->primCount);
4137 }
4138 
drawElementsIndirect(deUint32 mode,deUint32 type,const void * indirect)4139 void ReferenceContext::drawElementsIndirect	(deUint32 mode, deUint32 type, const void *indirect)
4140 {
4141 	struct DrawElementsIndirectCommand
4142 	{
4143 		deUint32 count;
4144 		deUint32 primCount;
4145 		deUint32 firstIndex;
4146 		deInt32  baseVertex;
4147 		deUint32 reservedMustBeZero;
4148 	};
4149 
4150 	const DrawElementsIndirectCommand* command;
4151 
4152 	// Check errors
4153 
4154 	if (!predrawErrorChecks(mode))
4155 		return;
4156 
4157 	RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4158 				type != GL_UNSIGNED_SHORT &&
4159 				type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4160 
4161 	RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);
4162 
4163 	// Check pointer validity
4164 
4165 	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4166 	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4167 
4168 	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4169 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                       > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4170 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) + sizeof(DrawElementsIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4171 
4172 	// Check values
4173 
4174 	command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4175 	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4176 
4177 	// Check command error conditions
4178 	RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4179 
4180 	// Draw
4181 	{
4182 		const size_t			sizeOfType		= (type == GL_UNSIGNED_BYTE) ?  (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
4183 		const void*				indicesPtr		= glu::BufferOffsetAsPointer(command->firstIndex * sizeOfType);
4184 
4185 		drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
4186 	}
4187 }
4188 
multiDrawArrays(deUint32 mode,const int * first,const int * count,int primCount)4189 void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
4190 {
4191 	DE_UNREF(mode);
4192 	DE_UNREF(first);
4193 	DE_UNREF(count);
4194 	DE_UNREF(primCount);
4195 
4196 	// not supported in gles, prevent accidental use
4197 	DE_ASSERT(false);
4198 }
4199 
multiDrawElements(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount)4200 void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
4201 {
4202 	DE_UNREF(mode);
4203 	DE_UNREF(count);
4204 	DE_UNREF(type);
4205 	DE_UNREF(indices);
4206 	DE_UNREF(primCount);
4207 
4208 	// not supported in gles, prevent accidental use
4209 	DE_ASSERT(false);
4210 }
4211 
multiDrawElementsBaseVertex(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount,const int * baseVertex)4212 void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
4213 {
4214 	DE_UNREF(mode);
4215 	DE_UNREF(count);
4216 	DE_UNREF(type);
4217 	DE_UNREF(indices);
4218 	DE_UNREF(primCount);
4219 	DE_UNREF(baseVertex);
4220 
4221 	// not supported in gles, prevent accidental use
4222 	DE_ASSERT(false);
4223 }
4224 
predrawErrorChecks(deUint32 mode)4225 bool ReferenceContext::predrawErrorChecks (deUint32 mode)
4226 {
4227 	RC_IF_ERROR(mode != GL_POINTS &&
4228 				mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
4229 				mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
4230 				mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
4231 				mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
4232 				GL_INVALID_ENUM, false);
4233 
4234 	// \todo [jarkko] Uncomment following code when the buffer mapping support is added
4235 	//for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4236 	//	if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
4237 	//		RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4238 
4239 	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);
4240 
4241 	// Geometry shader checks
4242 	if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
4243 	{
4244 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);
4245 
4246 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
4247 			(mode != GL_LINES &&
4248 			 mode != GL_LINE_STRIP &&
4249 			 mode != GL_LINE_LOOP),
4250 			 GL_INVALID_OPERATION, false);
4251 
4252 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
4253 			(mode != GL_TRIANGLES &&
4254 			 mode != GL_TRIANGLE_STRIP &&
4255 			 mode != GL_TRIANGLE_FAN),
4256 			 GL_INVALID_OPERATION, false);
4257 
4258 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
4259 			(mode != GL_LINES_ADJACENCY &&
4260 			 mode != GL_LINE_STRIP_ADJACENCY),
4261 			 GL_INVALID_OPERATION, false);
4262 
4263 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
4264 			(mode != GL_TRIANGLES_ADJACENCY &&
4265 			 mode != GL_TRIANGLE_STRIP_ADJACENCY),
4266 			 GL_INVALID_OPERATION, false);
4267 	}
4268 
4269 	return true;
4270 }
4271 
getPrimitiveBaseType(rr::PrimitiveType derivedType)4272 static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
4273 {
4274 	switch (derivedType)
4275 	{
4276 		case rr::PRIMITIVETYPE_TRIANGLES:
4277 		case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
4278 		case rr::PRIMITIVETYPE_TRIANGLE_FAN:
4279 		case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
4280 		case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
4281 			return rr::PRIMITIVETYPE_TRIANGLES;
4282 
4283 		case rr::PRIMITIVETYPE_LINES:
4284 		case rr::PRIMITIVETYPE_LINE_STRIP:
4285 		case rr::PRIMITIVETYPE_LINE_LOOP:
4286 		case rr::PRIMITIVETYPE_LINES_ADJACENCY:
4287 		case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
4288 			return rr::PRIMITIVETYPE_LINES;
4289 
4290 		case rr::PRIMITIVETYPE_POINTS:
4291 			return rr::PRIMITIVETYPE_POINTS;
4292 
4293 		default:
4294 			DE_ASSERT(false);
4295 			return rr::PRIMITIVETYPE_LAST;
4296 	}
4297 }
4298 
getFixedRestartIndex(rr::IndexType indexType)4299 static deUint32 getFixedRestartIndex (rr::IndexType indexType)
4300 {
4301 	switch (indexType)
4302 	{
4303 		case rr::INDEXTYPE_UINT8:		return 0xFF;
4304 		case rr::INDEXTYPE_UINT16:		return 0xFFFF;
4305 		case rr::INDEXTYPE_UINT32:		return 0xFFFFFFFFul;
4306 
4307 		case rr::INDEXTYPE_LAST:
4308 		default:
4309 			DE_ASSERT(false);
4310 			return 0;
4311 	}
4312 }
4313 
drawWithReference(const rr::PrimitiveList & primitives,int instanceCount)4314 void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
4315 {
4316 	// undefined results
4317 	if (m_currentProgram == DE_NULL)
4318 		return;
4319 
4320 	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
4321 	rr::MultisamplePixelBufferAccess	depthBuf	= getDepthMultisampleAccess(getDrawDepthbuffer());
4322 	rr::MultisamplePixelBufferAccess	stencilBuf	= getStencilMultisampleAccess(getDrawStencilbuffer());
4323 	const bool							hasStencil	= !isEmpty(stencilBuf);
4324 	const int							stencilBits	= (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);
4325 
4326 	const rr::RenderTarget				renderTarget(colorBuf0, depthBuf, stencilBuf);
4327 	const rr::Program					program		(m_currentProgram->m_program->getVertexShader(),
4328 													 m_currentProgram->m_program->getFragmentShader(),
4329 													 (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
4330 	rr::RenderState						state		((rr::ViewportState)(colorBuf0), m_limits.subpixelBits);
4331 
4332 	const rr::Renderer					referenceRenderer;
4333 	std::vector<rr::VertexAttrib>		vertexAttribs;
4334 
4335 	// Gen state
4336 	{
4337 		const rr::PrimitiveType	baseType							= getPrimitiveBaseType(primitives.getPrimitiveType());
4338 		const bool				polygonOffsetEnabled				= (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);
4339 
4340 		//state.cullMode											= m_cullMode
4341 
4342 		state.fragOps.scissorTestEnabled							= m_scissorEnabled;
4343 		state.fragOps.scissorRectangle								= rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());
4344 
4345 		state.fragOps.numStencilBits								= stencilBits;
4346 		state.fragOps.stencilTestEnabled							= m_stencilTestEnabled;
4347 
4348 		for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
4349 		{
4350 			state.fragOps.stencilStates[faceType].compMask	= m_stencil[faceType].opMask;
4351 			state.fragOps.stencilStates[faceType].writeMask	= m_stencil[faceType].writeMask;
4352 			state.fragOps.stencilStates[faceType].ref		= m_stencil[faceType].ref;
4353 			state.fragOps.stencilStates[faceType].func		= sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
4354 			state.fragOps.stencilStates[faceType].sFail		= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
4355 			state.fragOps.stencilStates[faceType].dpFail	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
4356 			state.fragOps.stencilStates[faceType].dpPass	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
4357 		}
4358 
4359 		state.fragOps.depthTestEnabled								= m_depthTestEnabled;
4360 		state.fragOps.depthFunc										= sglr::rr_util::mapGLTestFunc(m_depthFunc);
4361 		state.fragOps.depthMask										= m_depthMask;
4362 
4363 		state.fragOps.blendMode										= m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
4364 		state.fragOps.blendRGBState.equation						= sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
4365 		state.fragOps.blendRGBState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
4366 		state.fragOps.blendRGBState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
4367 		state.fragOps.blendAState.equation							= sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
4368 		state.fragOps.blendAState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
4369 		state.fragOps.blendAState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
4370 		state.fragOps.blendColor									= m_blendColor;
4371 
4372 		state.fragOps.sRGBEnabled									= m_sRGBUpdateEnabled;
4373 
4374 		state.fragOps.colorMask										= m_colorMask;
4375 
4376 		state.fragOps.depthClampEnabled								= m_depthClampEnabled;
4377 
4378 		state.viewport.rect											= rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
4379 		state.viewport.zn											= m_depthRangeNear;
4380 		state.viewport.zf											= m_depthRangeFar;
4381 
4382 		//state.point.pointSize										= m_pointSize;
4383 		state.line.lineWidth										= m_lineWidth;
4384 
4385 		state.fragOps.polygonOffsetEnabled							= polygonOffsetEnabled;
4386 		state.fragOps.polygonOffsetFactor							= m_polygonOffsetFactor;
4387 		state.fragOps.polygonOffsetUnits							= m_polygonOffsetUnits;
4388 
4389 		{
4390 			const rr::IndexType indexType = primitives.getIndexType();
4391 
4392 			if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
4393 			{
4394 				state.restart.enabled = true;
4395 				state.restart.restartIndex = getFixedRestartIndex(indexType);
4396 			}
4397 			else if (m_primitiveRestartSettableIndex)
4398 			{
4399 				// \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
4400 				state.restart.enabled = true;
4401 				state.restart.restartIndex = m_primitiveRestartIndex;
4402 			}
4403 			else
4404 			{
4405 				state.restart.enabled = false;
4406 			}
4407 		}
4408 
4409 		state.provokingVertexConvention								= (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
4410 	}
4411 
4412 	// gen attributes
4413 	{
4414 		rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4415 
4416 		vertexAttribs.resize(vao.m_arrays.size());
4417 		for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4418 		{
4419 			if (!vao.m_arrays[ndx].enabled)
4420 			{
4421 				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
4422 				vertexAttribs[ndx].generic = m_currentAttribs[ndx];
4423 			}
4424 			else if (vao.m_arrays[ndx].bufferDeleted)
4425 			{
4426 				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
4427 				vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
4428 			}
4429 			else
4430 			{
4431 				vertexAttribs[ndx].type				= (vao.m_arrays[ndx].integer) ?
4432 														(sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
4433 														(sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
4434 				vertexAttribs[ndx].size				= sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
4435 				vertexAttribs[ndx].stride			= vao.m_arrays[ndx].stride;
4436 				vertexAttribs[ndx].instanceDivisor	= vao.m_arrays[ndx].divisor;
4437 				vertexAttribs[ndx].pointer			= (vao.m_arrays[ndx].bufferBinding) ? (vao.m_arrays[ndx].bufferBinding->getData() + ((const deUint8*)vao.m_arrays[ndx].pointer - (const deUint8*)DE_NULL)) : (vao.m_arrays[ndx].pointer);
4438 			}
4439 		}
4440 	}
4441 
4442 	// Set shader samplers
4443 	for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
4444 	{
4445 		const tcu::Sampler::DepthStencilMode	depthStencilMode	= tcu::Sampler::MODE_DEPTH; // \todo[jarkko] support sampler state
4446 		const int								texNdx				= m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;
4447 
4448 		switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
4449 		{
4450 			case glu::TYPE_SAMPLER_1D:
4451 			case glu::TYPE_UINT_SAMPLER_1D:
4452 			case glu::TYPE_INT_SAMPLER_1D:
4453 			{
4454 				rc::Texture1D* tex = DE_NULL;
4455 
4456 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4457 					tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);
4458 
4459 				if (tex && tex->isComplete())
4460 				{
4461 					tex->updateView(depthStencilMode);
4462 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
4463 				}
4464 				else
4465 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;
4466 
4467 				break;
4468 			}
4469 			case glu::TYPE_SAMPLER_2D:
4470 			case glu::TYPE_UINT_SAMPLER_2D:
4471 			case glu::TYPE_INT_SAMPLER_2D:
4472 			{
4473 				rc::Texture2D* tex = DE_NULL;
4474 
4475 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4476 					tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);
4477 
4478 				if (tex && tex->isComplete())
4479 				{
4480 					tex->updateView(depthStencilMode);
4481 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
4482 				}
4483 				else
4484 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;
4485 
4486 				break;
4487 			}
4488 			case glu::TYPE_SAMPLER_CUBE:
4489 			case glu::TYPE_UINT_SAMPLER_CUBE:
4490 			case glu::TYPE_INT_SAMPLER_CUBE:
4491 			{
4492 				rc::TextureCube* tex = DE_NULL;
4493 
4494 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4495 					tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);
4496 
4497 				if (tex && tex->isComplete())
4498 				{
4499 					tex->updateView(depthStencilMode);
4500 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
4501 				}
4502 				else
4503 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;
4504 
4505 				break;
4506 			}
4507 			case glu::TYPE_SAMPLER_2D_ARRAY:
4508 			case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
4509 			case glu::TYPE_INT_SAMPLER_2D_ARRAY:
4510 			{
4511 				rc::Texture2DArray* tex = DE_NULL;
4512 
4513 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4514 					tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);
4515 
4516 				if (tex && tex->isComplete())
4517 				{
4518 					tex->updateView(depthStencilMode);
4519 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
4520 				}
4521 				else
4522 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;
4523 
4524 				break;
4525 			}
4526 			case glu::TYPE_SAMPLER_3D:
4527 			case glu::TYPE_UINT_SAMPLER_3D:
4528 			case glu::TYPE_INT_SAMPLER_3D:
4529 			{
4530 				rc::Texture3D* tex = DE_NULL;
4531 
4532 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4533 					tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);
4534 
4535 				if (tex && tex->isComplete())
4536 				{
4537 					tex->updateView(depthStencilMode);
4538 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
4539 				}
4540 				else
4541 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;
4542 
4543 				break;
4544 			}
4545 			case glu::TYPE_SAMPLER_CUBE_ARRAY:
4546 			case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
4547 			case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
4548 			{
4549 				rc::TextureCubeArray* tex = DE_NULL;
4550 
4551 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4552 					tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);
4553 
4554 				if (tex && tex->isComplete())
4555 				{
4556 					tex->updateView(depthStencilMode);
4557 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
4558 				}
4559 				else
4560 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;
4561 
4562 				break;
4563 			}
4564 			default:
4565 				// nothing
4566 				break;
4567 		}
4568 	}
4569 
4570 	referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
4571 }
4572 
createProgram(ShaderProgram * program)4573 deUint32 ReferenceContext::createProgram (ShaderProgram* program)
4574 {
4575 	int name = m_programs.allocateName();
4576 
4577 	m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));
4578 
4579 	return name;
4580 }
4581 
useProgram(deUint32 program)4582 void ReferenceContext::useProgram (deUint32 program)
4583 {
4584 	rc::ShaderProgramObjectContainer* shaderProg			= DE_NULL;
4585 	rc::ShaderProgramObjectContainer* programToBeDeleted	= DE_NULL;
4586 
4587 	if (program)
4588 	{
4589 		shaderProg = m_programs.find(program);
4590 
4591 		// shader has not been linked
4592 		if (!shaderProg || shaderProg->m_deleteFlag)
4593 			RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4594 	}
4595 
4596 	if (m_currentProgram && m_currentProgram->m_deleteFlag)
4597 		programToBeDeleted = m_currentProgram;
4598 
4599 	m_currentProgram = shaderProg;
4600 
4601 	if (programToBeDeleted)
4602 	{
4603 		DE_ASSERT(programToBeDeleted->getRefCount() == 1);
4604 		deleteProgramObject(programToBeDeleted);
4605 	}
4606 }
4607 
deleteProgram(deUint32 program)4608 void ReferenceContext::deleteProgram (deUint32 program)
4609 {
4610 	if (!program)
4611 		return;
4612 
4613 	rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
4614 	if (shaderProg)
4615 	{
4616 		if (shaderProg == m_currentProgram)
4617 		{
4618 			m_currentProgram->m_deleteFlag = true;
4619 		}
4620 		else
4621 		{
4622 			DE_ASSERT(shaderProg->getRefCount() == 1);
4623 			m_programs.releaseReference(shaderProg);
4624 		}
4625 	}
4626 }
4627 
readPixels(int x,int y,int width,int height,deUint32 format,deUint32 type,void * data)4628 void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
4629 {
4630 	rr::MultisamplePixelBufferAccess	src = getReadColorbuffer();
4631 	TextureFormat						transferFmt;
4632 
4633 	// Map transfer format.
4634 	transferFmt = glu::mapGLTransferFormat(format, type);
4635 	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
4636 				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
4637 
4638 	// Clamp input values
4639 	const int copyX			= deClamp32(x,		0, src.raw().getHeight());
4640 	const int copyY			= deClamp32(y,		0, src.raw().getDepth());
4641 	const int copyWidth		= deClamp32(width,	0, src.raw().getHeight()-x);
4642 	const int copyHeight	= deClamp32(height,	0, src.raw().getDepth()-y);
4643 
4644 	PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
4645 	rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
4646 }
4647 
getError(void)4648 deUint32 ReferenceContext::getError (void)
4649 {
4650 	deUint32 err = m_lastError;
4651 	m_lastError = GL_NO_ERROR;
4652 	return err;
4653 }
4654 
finish(void)4655 void ReferenceContext::finish (void)
4656 {
4657 }
4658 
setError(deUint32 error)4659 inline void ReferenceContext::setError (deUint32 error)
4660 {
4661 	if (m_lastError == GL_NO_ERROR)
4662 		m_lastError = error;
4663 }
4664 
getIntegerv(deUint32 pname,int * param)4665 void ReferenceContext::getIntegerv (deUint32 pname, int* param)
4666 {
4667 	switch (pname)
4668 	{
4669 		case GL_MAX_TEXTURE_SIZE:			*param = m_limits.maxTexture2DSize;			break;
4670 		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:	*param = m_limits.maxTextureCubeSize;		break;
4671 		case GL_MAX_ARRAY_TEXTURE_LAYERS:	*param = m_limits.maxTexture2DArrayLayers;	break;
4672 		case GL_MAX_3D_TEXTURE_SIZE:		*param = m_limits.maxTexture3DSize;			break;
4673 		case GL_MAX_RENDERBUFFER_SIZE:		*param = m_limits.maxRenderbufferSize;		break;
4674 		case GL_MAX_TEXTURE_IMAGE_UNITS:	*param = m_limits.maxTextureImageUnits;		break;
4675 		case GL_MAX_VERTEX_ATTRIBS:			*param = m_limits.maxVertexAttribs;			break;
4676 
4677 		default:
4678 			setError(GL_INVALID_ENUM);
4679 			break;
4680 	}
4681 }
4682 
getString(deUint32 pname)4683 const char* ReferenceContext::getString (deUint32 pname)
4684 {
4685 	switch (pname)
4686 	{
4687 		case GL_EXTENSIONS:		return m_limits.extensionStr.c_str();
4688 
4689 		default:
4690 			setError(GL_INVALID_ENUM);
4691 			return DE_NULL;
4692 	}
4693 }
4694 
4695 namespace rc
4696 {
4697 
TextureLevelArray(void)4698 TextureLevelArray::TextureLevelArray (void)
4699 {
4700 }
4701 
~TextureLevelArray(void)4702 TextureLevelArray::~TextureLevelArray (void)
4703 {
4704 	clear();
4705 }
4706 
clear(void)4707 void TextureLevelArray::clear (void)
4708 {
4709 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));
4710 
4711 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
4712 	{
4713 		m_data[ndx].clear();
4714 		m_access[ndx] = PixelBufferAccess();
4715 	}
4716 }
4717 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)4718 void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
4719 {
4720 	const int dataSize = format.getPixelSize()*width*height*depth;
4721 
4722 	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4723 
4724 	if (hasLevel(level))
4725 		clearLevel(level);
4726 
4727 	m_data[level].setStorage(dataSize);
4728 	m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level].getPtr());
4729 }
4730 
clearLevel(int level)4731 void TextureLevelArray::clearLevel (int level)
4732 {
4733 	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4734 
4735 	m_data[level].clear();
4736 	m_access[level] = PixelBufferAccess();
4737 }
4738 
updateSamplerMode(tcu::Sampler::DepthStencilMode mode)4739 void TextureLevelArray::updateSamplerMode (tcu::Sampler::DepthStencilMode mode)
4740 {
4741 	for (int levelNdx = 0; hasLevel(levelNdx); ++levelNdx)
4742 		m_effectiveAccess[levelNdx] = tcu::getEffectiveDepthStencilAccess(m_access[levelNdx], mode);
4743 }
4744 
Texture(deUint32 name,Type type,deBool seamless)4745 Texture::Texture (deUint32 name, Type type, deBool seamless)
4746 	: NamedObject	(name)
4747 	, m_type		(type)
4748 	, m_immutable	(false)
4749 	, m_sampler		(tcu::Sampler::REPEAT_GL,
4750 					 tcu::Sampler::REPEAT_GL,
4751 					 tcu::Sampler::REPEAT_GL,
4752 					 tcu::Sampler::NEAREST_MIPMAP_LINEAR,
4753 					 tcu::Sampler::LINEAR,
4754 					 0.0f,				// LOD threshold
4755 					 true,				// normalized coords
4756 					 tcu::Sampler::COMPAREMODE_NONE,
4757 					 0,					// cmp channel ndx
4758 					 tcu::Vec4(0.0f),	// border color
4759 					 seamless			// seamless cube map, Default value is True.
4760 					 )
4761 	, m_baseLevel	(0)
4762 	, m_maxLevel	(1000)
4763 {
4764 }
4765 
Texture1D(deUint32 name)4766 Texture1D::Texture1D (deUint32 name)
4767 	: Texture	(name, TYPE_1D)
4768 	, m_view	(0, DE_NULL)
4769 {
4770 }
4771 
~Texture1D(void)4772 Texture1D::~Texture1D (void)
4773 {
4774 }
4775 
allocLevel(int level,const tcu::TextureFormat & format,int width)4776 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
4777 {
4778 	m_levels.allocLevel(level, format, width, 1, 1);
4779 }
4780 
isComplete(void) const4781 bool Texture1D::isComplete (void) const
4782 {
4783 	const int	baseLevel	= getBaseLevel();
4784 
4785 	if (hasLevel(baseLevel))
4786 	{
4787 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
4788 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
4789 
4790 		if (mipmap)
4791 		{
4792 			const TextureFormat&	format		= level0.getFormat();
4793 			const int				w			= level0.getWidth();
4794 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));
4795 
4796 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4797 			{
4798 				if (hasLevel(baseLevel+levelNdx))
4799 				{
4800 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
4801 					const int							expectedW	= getMipLevelSize(w, levelNdx);
4802 
4803 					if (level.getWidth()	!= expectedW	||
4804 						level.getFormat()	!= format)
4805 						return false;
4806 				}
4807 				else
4808 					return false;
4809 			}
4810 		}
4811 
4812 		return true;
4813 	}
4814 	else
4815 		return false;
4816 }
4817 
sample(float s,float lod) const4818 tcu::Vec4 Texture1D::sample (float s, float lod) const
4819 {
4820 	return m_view.sample(getSampler(), s, 0.0f, lod);
4821 }
4822 
sample4(tcu::Vec4 output[4],const float packetTexcoords[4],float lodBias) const4823 void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
4824 {
4825 	const float texWidth = (float)m_view.getWidth();
4826 
4827 	const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4828 	const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4829 	const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4830 	const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4831 
4832 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4833 	{
4834 		const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
4835 		const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;
4836 
4837 		const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
4838 		const float p = mu * texWidth;
4839 
4840 		const float	lod = deFloatLog2(p) + lodBias;
4841 
4842 		output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
4843 	}
4844 }
4845 
updateView(tcu::Sampler::DepthStencilMode mode)4846 void Texture1D::updateView (tcu::Sampler::DepthStencilMode mode)
4847 {
4848 	const int baseLevel	= getBaseLevel();
4849 
4850 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4851 	{
4852 		const int	width		= getLevel(baseLevel).getWidth();
4853 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
4854 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;
4855 
4856 		m_levels.updateSamplerMode(mode);
4857 		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4858 	}
4859 	else
4860 		m_view = tcu::Texture2DView(0, DE_NULL);
4861 }
4862 
Texture2D(deUint32 name,bool es2)4863 Texture2D::Texture2D (deUint32 name, bool es2)
4864 	: Texture	(name, TYPE_2D)
4865 	, m_view	(0, DE_NULL, es2)
4866 {
4867 }
4868 
~Texture2D(void)4869 Texture2D::~Texture2D (void)
4870 {
4871 }
4872 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height)4873 void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
4874 {
4875 	m_levels.allocLevel(level, format, width, height, 1);
4876 }
4877 
isComplete(void) const4878 bool Texture2D::isComplete (void) const
4879 {
4880 	const int	baseLevel	= getBaseLevel();
4881 
4882 	if (hasLevel(baseLevel))
4883 	{
4884 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
4885 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
4886 
4887 		if (mipmap)
4888 		{
4889 			const TextureFormat&	format		= level0.getFormat();
4890 			const int				w			= level0.getWidth();
4891 			const int				h			= level0.getHeight();
4892 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
4893 
4894 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4895 			{
4896 				if (hasLevel(baseLevel+levelNdx))
4897 				{
4898 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
4899 					const int							expectedW	= getMipLevelSize(w, levelNdx);
4900 					const int							expectedH	= getMipLevelSize(h, levelNdx);
4901 
4902 					if (level.getWidth()	!= expectedW	||
4903 						level.getHeight()	!= expectedH	||
4904 						level.getFormat()	!= format)
4905 						return false;
4906 				}
4907 				else
4908 					return false;
4909 			}
4910 		}
4911 
4912 		return true;
4913 	}
4914 	else
4915 		return false;
4916 }
4917 
updateView(tcu::Sampler::DepthStencilMode mode)4918 void Texture2D::updateView (tcu::Sampler::DepthStencilMode mode)
4919 {
4920 	const int baseLevel	= getBaseLevel();
4921 
4922 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4923 	{
4924 		// Update number of levels in mipmap pyramid.
4925 		const int	width		= getLevel(baseLevel).getWidth();
4926 		const int	height		= getLevel(baseLevel).getHeight();
4927 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
4928 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4929 
4930 		m_levels.updateSamplerMode(mode);
4931 		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4932 	}
4933 	else
4934 		m_view = tcu::Texture2DView(0, DE_NULL);
4935 }
4936 
sample(float s,float t,float lod) const4937 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
4938 {
4939 	return m_view.sample(getSampler(), s, t, lod);
4940 }
4941 
sample4(tcu::Vec4 output[4],const tcu::Vec2 packetTexcoords[4],float lodBias) const4942 void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
4943 {
4944 	const float texWidth  = (float)m_view.getWidth();
4945 	const float texHeight = (float)m_view.getHeight();
4946 
4947 	const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4948 	const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4949 	const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4950 	const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4951 
4952 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4953 	{
4954 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
4955 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
4956 
4957 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
4958 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
4959 		const float p = de::max(mu * texWidth, mv * texHeight);
4960 
4961 		const float	lod = deFloatLog2(p) + lodBias;
4962 
4963 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
4964 	}
4965 }
4966 
TextureCube(deUint32 name,deBool seamless)4967 TextureCube::TextureCube (deUint32 name, deBool seamless)
4968 	: Texture(name, TYPE_CUBE_MAP, seamless)
4969 {
4970 }
4971 
~TextureCube(void)4972 TextureCube::~TextureCube (void)
4973 {
4974 }
4975 
clearLevels(void)4976 void TextureCube::clearLevels (void)
4977 {
4978 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4979 		m_levels[face].clear();
4980 }
4981 
allocFace(int level,tcu::CubeFace face,const tcu::TextureFormat & format,int width,int height)4982 void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
4983 {
4984 	m_levels[face].allocLevel(level, format, width, height, 1);
4985 }
4986 
isComplete(void) const4987 bool TextureCube::isComplete (void) const
4988 {
4989 	const int	baseLevel	= getBaseLevel();
4990 
4991 	if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
4992 	{
4993 		const int					width		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
4994 		const int					height		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
4995 		const tcu::TextureFormat&	format		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
4996 		const bool					mipmap		= isMipmapFilter(getSampler().minFilter);
4997 		const int					numLevels	= mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4998 
4999 		if (width != height)
5000 			return false; // Non-square is not supported.
5001 
5002 		// \note Level 0 is always checked for consistency
5003 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
5004 		{
5005 			const int levelW	= getMipLevelSize(width,	levelNdx);
5006 			const int levelH	= getMipLevelSize(height,	levelNdx);
5007 
5008 			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5009 			{
5010 				if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
5011 				{
5012 					const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);
5013 
5014 					if (level.getWidth()	!= levelW	||
5015 						level.getHeight()	!= levelH	||
5016 						level.getFormat()	!= format)
5017 						return false;
5018 				}
5019 				else
5020 					return false;
5021 			}
5022 		}
5023 
5024 		return true;
5025 	}
5026 	else
5027 		return false;
5028 }
5029 
updateView(tcu::Sampler::DepthStencilMode mode)5030 void TextureCube::updateView (tcu::Sampler::DepthStencilMode mode)
5031 {
5032 	const int							baseLevel	= getBaseLevel();
5033 	const tcu::ConstPixelBufferAccess*	faces[tcu::CUBEFACE_LAST];
5034 
5035 	deMemset(&faces[0], 0, sizeof(faces));
5036 
5037 	if (isComplete())
5038 	{
5039 		const int	size		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
5040 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5041 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;
5042 
5043 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5044 		{
5045 			m_levels[face].updateSamplerMode(mode);
5046 			faces[face] = m_levels[face].getEffectiveLevels() + baseLevel;
5047 		}
5048 
5049 		m_view = tcu::TextureCubeView(numLevels, faces);
5050 	}
5051 	else
5052 		m_view = tcu::TextureCubeView(0, faces);
5053 }
5054 
sample(float s,float t,float p,float lod) const5055 tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
5056 {
5057 	return m_view.sample(getSampler(), s, t, p, lod);
5058 }
5059 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5060 void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5061 {
5062 	const float cubeSide = (float)m_view.getSize();
5063 
5064 	// Each tex coord might be in a different face.
5065 
5066 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5067 	{
5068 		const tcu::CubeFace face		= tcu::selectCubeFace(packetTexcoords[fragNdx]);
5069 		const tcu::Vec2		coords[4]	=
5070 		{
5071 			tcu::projectToFace(face, packetTexcoords[0]),
5072 			tcu::projectToFace(face, packetTexcoords[1]),
5073 			tcu::projectToFace(face, packetTexcoords[2]),
5074 			tcu::projectToFace(face, packetTexcoords[3]),
5075 		};
5076 
5077 		const tcu::Vec2 dFdx0 = coords[1] - coords[0];
5078 		const tcu::Vec2 dFdx1 = coords[3] - coords[2];
5079 		const tcu::Vec2 dFdy0 = coords[2] - coords[0];
5080 		const tcu::Vec2 dFdy1 = coords[3] - coords[1];
5081 
5082 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5083 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5084 
5085 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5086 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5087 		const float p = de::max(mu * cubeSide, mv * cubeSide);
5088 
5089 		const float	lod = deFloatLog2(p) + lodBias;
5090 
5091 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5092 	}
5093 }
5094 
Texture2DArray(deUint32 name)5095 Texture2DArray::Texture2DArray (deUint32 name)
5096 	: Texture	(name, TYPE_2D_ARRAY)
5097 	, m_view	(0, DE_NULL)
5098 {
5099 }
5100 
~Texture2DArray(void)5101 Texture2DArray::~Texture2DArray (void)
5102 {
5103 }
5104 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5105 void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5106 {
5107 	m_levels.allocLevel(level, format, width, height, numLayers);
5108 }
5109 
isComplete(void) const5110 bool Texture2DArray::isComplete (void) const
5111 {
5112 	const int	baseLevel	= getBaseLevel();
5113 
5114 	if (hasLevel(baseLevel))
5115 	{
5116 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5117 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5118 
5119 		if (mipmap)
5120 		{
5121 			const TextureFormat&	format		= level0.getFormat();
5122 			const int				w			= level0.getWidth();
5123 			const int				h			= level0.getHeight();
5124 			const int				numLayers	= level0.getDepth();
5125 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5126 
5127 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5128 			{
5129 				if (hasLevel(baseLevel+levelNdx))
5130 				{
5131 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5132 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5133 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5134 
5135 					if (level.getWidth()	!= expectedW	||
5136 						level.getHeight()	!= expectedH	||
5137 						level.getDepth()	!= numLayers	||
5138 						level.getFormat()	!= format)
5139 						return false;
5140 				}
5141 				else
5142 					return false;
5143 			}
5144 		}
5145 
5146 		return true;
5147 	}
5148 	else
5149 		return false;
5150 }
5151 
updateView(tcu::Sampler::DepthStencilMode mode)5152 void Texture2DArray::updateView (tcu::Sampler::DepthStencilMode mode)
5153 {
5154 	const int baseLevel	= getBaseLevel();
5155 
5156 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5157 	{
5158 		const int	width		= getLevel(baseLevel).getWidth();
5159 		const int	height		= getLevel(baseLevel).getHeight();
5160 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5161 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5162 
5163 		m_levels.updateSamplerMode(mode);
5164 		m_view = tcu::Texture2DArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5165 	}
5166 	else
5167 		m_view = tcu::Texture2DArrayView(0, DE_NULL);
5168 }
5169 
sample(float s,float t,float r,float lod) const5170 tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
5171 {
5172 	return m_view.sample(getSampler(), s, t, r, lod);
5173 }
5174 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5175 void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5176 {
5177 	const float texWidth  = (float)m_view.getWidth();
5178 	const float texHeight = (float)m_view.getHeight();
5179 
5180 	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5181 	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5182 	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5183 	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5184 
5185 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5186 	{
5187 		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5188 		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5189 
5190 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5191 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5192 		const float p = de::max(mu * texWidth, mv * texHeight);
5193 
5194 		const float	lod = deFloatLog2(p) + lodBias;
5195 
5196 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5197 	}
5198 }
5199 
TextureCubeArray(deUint32 name)5200 TextureCubeArray::TextureCubeArray (deUint32 name)
5201 	: Texture	(name, TYPE_CUBE_MAP_ARRAY)
5202 	, m_view	(0, DE_NULL)
5203 {
5204 }
5205 
~TextureCubeArray(void)5206 TextureCubeArray::~TextureCubeArray (void)
5207 {
5208 }
5209 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5210 void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5211 {
5212 	DE_ASSERT(numLayers % 6 == 0);
5213 	m_levels.allocLevel(level, format, width, height, numLayers);
5214 }
5215 
isComplete(void) const5216 bool TextureCubeArray::isComplete (void) const
5217 {
5218 	const int	baseLevel	= getBaseLevel();
5219 
5220 	if (hasLevel(baseLevel))
5221 	{
5222 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5223 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5224 
5225 		if (mipmap)
5226 		{
5227 			const TextureFormat&	format		= level0.getFormat();
5228 			const int				w			= level0.getWidth();
5229 			const int				h			= level0.getHeight();
5230 			const int				numLayers	= level0.getDepth();
5231 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5232 
5233 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5234 			{
5235 				if (hasLevel(baseLevel+levelNdx))
5236 				{
5237 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5238 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5239 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5240 
5241 					if (level.getWidth()	!= expectedW	||
5242 						level.getHeight()	!= expectedH	||
5243 						level.getDepth()	!= numLayers	||
5244 						level.getFormat()	!= format)
5245 						return false;
5246 				}
5247 				else
5248 					return false;
5249 			}
5250 		}
5251 
5252 		return true;
5253 	}
5254 	else
5255 		return false;
5256 }
5257 
updateView(tcu::Sampler::DepthStencilMode mode)5258 void TextureCubeArray::updateView (tcu::Sampler::DepthStencilMode mode)
5259 {
5260 	const int baseLevel	= getBaseLevel();
5261 
5262 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5263 	{
5264 		const int	width		= getLevel(baseLevel).getWidth();
5265 		const int	height		= getLevel(baseLevel).getHeight();
5266 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5267 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5268 
5269 		m_levels.updateSamplerMode(mode);
5270 		m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5271 	}
5272 	else
5273 		m_view = tcu::TextureCubeArrayView(0, DE_NULL);
5274 }
5275 
sample(float s,float t,float r,float q,float lod) const5276 tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
5277 {
5278 	return m_view.sample(getSampler(), s, t, r, q, lod);
5279 }
5280 
sample4(tcu::Vec4 output[4],const tcu::Vec4 packetTexcoords[4],float lodBias) const5281 void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
5282 {
5283 	const float		cubeSide		= (float)m_view.getSize();
5284 	const tcu::Vec3	cubeCoords[4]	=
5285 	{
5286 		packetTexcoords[0].toWidth<3>(),
5287 		packetTexcoords[1].toWidth<3>(),
5288 		packetTexcoords[2].toWidth<3>(),
5289 		packetTexcoords[3].toWidth<3>()
5290 	};
5291 
5292 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5293 	{
5294 		const tcu::CubeFace face			= tcu::selectCubeFace(cubeCoords[fragNdx]);
5295 		const tcu::Vec2		faceCoords[4]	=
5296 		{
5297 			tcu::projectToFace(face, cubeCoords[0]),
5298 			tcu::projectToFace(face, cubeCoords[1]),
5299 			tcu::projectToFace(face, cubeCoords[2]),
5300 			tcu::projectToFace(face, cubeCoords[3]),
5301 		};
5302 
5303 		const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
5304 		const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
5305 		const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
5306 		const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];
5307 
5308 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5309 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5310 
5311 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5312 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5313 		const float p = de::max(mu * cubeSide, mv * cubeSide);
5314 
5315 		const float	lod = deFloatLog2(p) + lodBias;
5316 
5317 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
5318 	}
5319 }
5320 
Texture3D(deUint32 name)5321 Texture3D::Texture3D (deUint32 name)
5322 	: Texture	(name, TYPE_3D)
5323 	, m_view	(0, DE_NULL)
5324 {
5325 }
5326 
~Texture3D(void)5327 Texture3D::~Texture3D (void)
5328 {
5329 }
5330 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)5331 void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
5332 {
5333 	m_levels.allocLevel(level, format, width, height, depth);
5334 }
5335 
isComplete(void) const5336 bool Texture3D::isComplete (void) const
5337 {
5338 	const int	baseLevel	= getBaseLevel();
5339 
5340 	if (hasLevel(baseLevel))
5341 	{
5342 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5343 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5344 
5345 		if (mipmap)
5346 		{
5347 			const TextureFormat&	format		= level0.getFormat();
5348 			const int				w			= level0.getWidth();
5349 			const int				h			= level0.getHeight();
5350 			const int				d			= level0.getDepth();
5351 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));
5352 
5353 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5354 			{
5355 				if (hasLevel(baseLevel+levelNdx))
5356 				{
5357 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5358 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5359 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5360 					const int							expectedD	= getMipLevelSize(d, levelNdx);
5361 
5362 					if (level.getWidth()	!= expectedW	||
5363 						level.getHeight()	!= expectedH	||
5364 						level.getDepth()	!= expectedD	||
5365 						level.getFormat()	!= format)
5366 						return false;
5367 				}
5368 				else
5369 					return false;
5370 			}
5371 		}
5372 
5373 		return true;
5374 	}
5375 	else
5376 		return false;
5377 }
5378 
sample(float s,float t,float r,float lod) const5379 tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
5380 {
5381 	return m_view.sample(getSampler(), s, t, r, lod);
5382 }
5383 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5384 void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5385 {
5386 	const float texWidth  = (float)m_view.getWidth();
5387 	const float texHeight = (float)m_view.getHeight();
5388 	const float texDepth  = (float)m_view.getDepth();
5389 
5390 	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5391 	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5392 	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5393 	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5394 
5395 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5396 	{
5397 		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5398 		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5399 
5400 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5401 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5402 		const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
5403 		const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);
5404 
5405 		const float	lod = deFloatLog2(p) + lodBias;
5406 
5407 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5408 	}
5409 }
5410 
updateView(tcu::Sampler::DepthStencilMode mode)5411 void Texture3D::updateView (tcu::Sampler::DepthStencilMode mode)
5412 {
5413 	const int baseLevel	= getBaseLevel();
5414 
5415 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5416 	{
5417 		const int	width		= getLevel(baseLevel).getWidth();
5418 		const int	height		= getLevel(baseLevel).getHeight();
5419 		const int	depth		= getLevel(baseLevel).getDepth();
5420 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5421 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;
5422 
5423 		m_levels.updateSamplerMode(mode);
5424 		m_view = tcu::Texture3DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5425 	}
5426 	else
5427 		m_view = tcu::Texture3DView(0, DE_NULL);
5428 }
5429 
Renderbuffer(deUint32 name)5430 Renderbuffer::Renderbuffer (deUint32 name)
5431 	: NamedObject		(name)
5432 {
5433 }
5434 
~Renderbuffer(void)5435 Renderbuffer::~Renderbuffer (void)
5436 {
5437 }
5438 
setStorage(const TextureFormat & format,int width,int height)5439 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
5440 {
5441 	m_data.setStorage(format, width, height);
5442 }
5443 
Framebuffer(deUint32 name)5444 Framebuffer::Framebuffer (deUint32 name)
5445 	: NamedObject(name)
5446 {
5447 }
5448 
~Framebuffer(void)5449 Framebuffer::~Framebuffer (void)
5450 {
5451 }
5452 
VertexArray(deUint32 name,int maxVertexAttribs)5453 VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
5454 	: NamedObject					(name)
5455 	, m_elementArrayBufferBinding	(DE_NULL)
5456 	, m_arrays						(maxVertexAttribs)
5457 {
5458 	for (int i = 0; i < maxVertexAttribs; ++i)
5459 	{
5460 		m_arrays[i].enabled			= false;
5461 		m_arrays[i].size			= 4;
5462 		m_arrays[i].stride			= 0;
5463 		m_arrays[i].type			= GL_FLOAT;
5464 		m_arrays[i].normalized		= false;
5465 		m_arrays[i].integer			= false;
5466 		m_arrays[i].divisor			= 0;
5467 		m_arrays[i].bufferDeleted	= false;
5468 		m_arrays[i].bufferBinding	= DE_NULL;
5469 		m_arrays[i].pointer			= DE_NULL;
5470 	}
5471 }
5472 
ShaderProgramObjectContainer(deUint32 name,ShaderProgram * program)5473 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
5474 	: NamedObject	(name)
5475 	, m_program		(program)
5476 	, m_deleteFlag	(false)
5477 {
5478 }
5479 
~ShaderProgramObjectContainer(void)5480 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
5481 {
5482 }
5483 
5484 } // rc
5485 } // sglr
5486