• 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 				return dynamic_cast<Texture2D*>(texture)->getLevel(attachment.level);
2361 			else if (texture->getType() == Texture::TYPE_CUBE_MAP)
2362 				return dynamic_cast<TextureCube*>(texture)->getFace(attachment.level, texTargetToFace(attachment.texTarget));
2363 			else if (texture->getType() == Texture::TYPE_2D_ARRAY	||
2364 					 texture->getType() == Texture::TYPE_3D			||
2365 					 texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2366 			{
2367 				tcu::PixelBufferAccess level;
2368 
2369 				if (texture->getType() == Texture::TYPE_2D_ARRAY)
2370 					level = dynamic_cast<Texture2DArray*>(texture)->getLevel(attachment.level);
2371 				else if (texture->getType() == Texture::TYPE_3D)
2372 					level = dynamic_cast<Texture3D*>(texture)->getLevel(attachment.level);
2373 				else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2374 					level = dynamic_cast<TextureCubeArray*>(texture)->getLevel(attachment.level);
2375 
2376 				void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;
2377 
2378 				return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
2379 			}
2380 			else
2381 				return nullAccess();
2382 		}
2383 
2384 		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
2385 		{
2386 			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
2387 			TCU_CHECK(rbo);
2388 
2389 			return rbo->getAccess();
2390 		}
2391 
2392 		default:
2393 			return nullAccess();
2394 	}
2395 }
2396 
getTexture2D(int unitNdx) const2397 const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
2398 {
2399 	const TextureUnit& unit = m_textureUnits[unitNdx];
2400 	return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
2401 }
2402 
getTextureCube(int unitNdx) const2403 const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
2404 {
2405 	const TextureUnit& unit = m_textureUnits[unitNdx];
2406 	return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
2407 }
2408 
isValidBufferTarget(deUint32 target)2409 static bool isValidBufferTarget (deUint32 target)
2410 {
2411 	switch (target)
2412 	{
2413 		case GL_ARRAY_BUFFER:
2414 		case GL_COPY_READ_BUFFER:
2415 		case GL_COPY_WRITE_BUFFER:
2416 		case GL_DRAW_INDIRECT_BUFFER:
2417 		case GL_ELEMENT_ARRAY_BUFFER:
2418 		case GL_PIXEL_PACK_BUFFER:
2419 		case GL_PIXEL_UNPACK_BUFFER:
2420 		case GL_TRANSFORM_FEEDBACK_BUFFER:
2421 		case GL_UNIFORM_BUFFER:
2422 			return true;
2423 
2424 		default:
2425 			return false;
2426 	}
2427 }
2428 
setBufferBinding(deUint32 target,DataBuffer * buffer)2429 void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
2430 {
2431 	DataBuffer** bindingPoint = DE_NULL;
2432 	VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2433 
2434 	switch (target)
2435 	{
2436 		case GL_ARRAY_BUFFER:				bindingPoint = &m_arrayBufferBinding;								break;
2437 		case GL_COPY_READ_BUFFER:			bindingPoint = &m_copyReadBufferBinding;							break;
2438 		case GL_COPY_WRITE_BUFFER:			bindingPoint = &m_copyWriteBufferBinding;							break;
2439 		case GL_DRAW_INDIRECT_BUFFER:		bindingPoint = &m_drawIndirectBufferBinding;						break;
2440 		case GL_ELEMENT_ARRAY_BUFFER:		bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding;		break;
2441 		case GL_PIXEL_PACK_BUFFER:			bindingPoint = &m_pixelPackBufferBinding;							break;
2442 		case GL_PIXEL_UNPACK_BUFFER:		bindingPoint = &m_pixelUnpackBufferBinding;							break;
2443 		case GL_TRANSFORM_FEEDBACK_BUFFER:	bindingPoint = &m_transformFeedbackBufferBinding;					break;
2444 		case GL_UNIFORM_BUFFER:				bindingPoint = &m_uniformBufferBinding;								break;
2445 		default:
2446 			DE_ASSERT(false);
2447 			return;
2448 	}
2449 
2450 	if (*bindingPoint)
2451 	{
2452 		m_buffers.releaseReference(*bindingPoint);
2453 		*bindingPoint = DE_NULL;
2454 	}
2455 
2456 	if (buffer)
2457 		m_buffers.acquireReference(buffer);
2458 
2459 	*bindingPoint = buffer;
2460 }
2461 
getBufferBinding(deUint32 target) const2462 DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
2463 {
2464 	const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2465 
2466 	switch (target)
2467 	{
2468 		case GL_ARRAY_BUFFER:				return m_arrayBufferBinding;
2469 		case GL_COPY_READ_BUFFER:			return m_copyReadBufferBinding;
2470 		case GL_COPY_WRITE_BUFFER:			return m_copyWriteBufferBinding;
2471 		case GL_DRAW_INDIRECT_BUFFER:		return m_drawIndirectBufferBinding;
2472 		case GL_ELEMENT_ARRAY_BUFFER:		return vertexArrayObject->m_elementArrayBufferBinding;
2473 		case GL_PIXEL_PACK_BUFFER:			return m_pixelPackBufferBinding;
2474 		case GL_PIXEL_UNPACK_BUFFER:		return m_pixelUnpackBufferBinding;
2475 		case GL_TRANSFORM_FEEDBACK_BUFFER:	return m_transformFeedbackBufferBinding;
2476 		case GL_UNIFORM_BUFFER:				return m_uniformBufferBinding;
2477 		default:
2478 			DE_ASSERT(false);
2479 			return DE_NULL;
2480 	}
2481 }
2482 
bindBuffer(deUint32 target,deUint32 buffer)2483 void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
2484 {
2485 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2486 
2487 	rc::DataBuffer*	bufObj	= DE_NULL;
2488 
2489 	if (buffer != 0)
2490 	{
2491 		bufObj = m_buffers.find(buffer);
2492 		if (!bufObj)
2493 		{
2494 			bufObj = new DataBuffer(buffer);
2495 			m_buffers.insert(bufObj);
2496 		}
2497 	}
2498 
2499 	setBufferBinding(target, bufObj);
2500 }
2501 
genBuffers(int numBuffers,deUint32 * buffers)2502 void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
2503 {
2504 	RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);
2505 
2506 	for (int ndx = 0; ndx < numBuffers; ndx++)
2507 		buffers[ndx] = m_buffers.allocateName();
2508 }
2509 
deleteBuffers(int numBuffers,const deUint32 * buffers)2510 void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
2511 {
2512 	RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);
2513 
2514 	for (int ndx = 0; ndx < numBuffers; ndx++)
2515 	{
2516 		deUint32	buffer	= buffers[ndx];
2517 		DataBuffer*	bufObj	= DE_NULL;
2518 
2519 		if (buffer == 0)
2520 			continue;
2521 
2522 		bufObj = m_buffers.find(buffer);
2523 
2524 		if (bufObj)
2525 			deleteBuffer(bufObj);
2526 	}
2527 }
2528 
deleteBuffer(DataBuffer * buffer)2529 void ReferenceContext::deleteBuffer (DataBuffer* buffer)
2530 {
2531 	static const deUint32 bindingPoints[] =
2532 	{
2533 		GL_ARRAY_BUFFER,
2534 		GL_COPY_READ_BUFFER,
2535 		GL_COPY_WRITE_BUFFER,
2536 		GL_DRAW_INDIRECT_BUFFER,
2537 		GL_ELEMENT_ARRAY_BUFFER,
2538 		GL_PIXEL_PACK_BUFFER,
2539 		GL_PIXEL_UNPACK_BUFFER,
2540 		GL_TRANSFORM_FEEDBACK_BUFFER,
2541 		GL_UNIFORM_BUFFER
2542 	};
2543 
2544 	for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
2545 	{
2546 		if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
2547 			setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
2548 	}
2549 
2550 	{
2551 		vector<VertexArray*> vertexArrays;
2552 		m_vertexArrays.getAll(vertexArrays);
2553 		vertexArrays.push_back(&m_clientVertexArray);
2554 
2555 		for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
2556 		{
2557 			if ((*i)->m_elementArrayBufferBinding == buffer)
2558 			{
2559 				m_buffers.releaseReference(buffer);
2560 				(*i)->m_elementArrayBufferBinding = DE_NULL;
2561 			}
2562 
2563 			for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
2564 			{
2565 				if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
2566 				{
2567 					m_buffers.releaseReference(buffer);
2568 					(*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
2569 					(*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
2570 				}
2571 			}
2572 		}
2573 	}
2574 
2575 	DE_ASSERT(buffer->getRefCount() == 1);
2576 	m_buffers.releaseReference(buffer);
2577 }
2578 
bufferData(deUint32 target,deIntptr size,const void * data,deUint32 usage)2579 void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
2580 {
2581 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2582 	RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2583 
2584 	DE_UNREF(usage);
2585 
2586 	DataBuffer* buffer = getBufferBinding(target);
2587 	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2588 
2589 	DE_ASSERT((deIntptr)(int)size == size);
2590 	buffer->setStorage((int)size);
2591 	if (data)
2592 		deMemcpy(buffer->getData(), data, (int)size);
2593 }
2594 
bufferSubData(deUint32 target,deIntptr offset,deIntptr size,const void * data)2595 void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
2596 {
2597 	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2598 	RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2599 
2600 	DataBuffer* buffer = getBufferBinding(target);
2601 
2602 	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2603 	RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);
2604 
2605 	deMemcpy(buffer->getData()+offset, data, (int)size);
2606 }
2607 
clearColor(float red,float green,float blue,float alpha)2608 void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
2609 {
2610 	m_clearColor = Vec4(de::clamp(red,	0.0f, 1.0f),
2611 						de::clamp(green,	0.0f, 1.0f),
2612 						de::clamp(blue,	0.0f, 1.0f),
2613 						de::clamp(alpha,	0.0f, 1.0f));
2614 }
2615 
clearDepthf(float depth)2616 void ReferenceContext::clearDepthf (float depth)
2617 {
2618 	m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
2619 }
2620 
clearStencil(int stencil)2621 void ReferenceContext::clearStencil (int stencil)
2622 {
2623 	m_clearStencil = stencil;
2624 }
2625 
scissor(int x,int y,int width,int height)2626 void ReferenceContext::scissor (int x, int y, int width, int height)
2627 {
2628 	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
2629 	m_scissorBox = IVec4(x, y, width, height);
2630 }
2631 
enable(deUint32 cap)2632 void ReferenceContext::enable (deUint32 cap)
2633 {
2634 	switch (cap)
2635 	{
2636 		case GL_BLEND:					m_blendEnabled				= true;	break;
2637 		case GL_SCISSOR_TEST:			m_scissorEnabled			= true;	break;
2638 		case GL_DEPTH_TEST:				m_depthTestEnabled			= true;	break;
2639 		case GL_STENCIL_TEST:			m_stencilTestEnabled		= true;	break;
2640 		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= true;	break;
2641 
2642 		case GL_FRAMEBUFFER_SRGB:
2643 			if (glu::isContextTypeGLCore(getType()))
2644 			{
2645 				m_sRGBUpdateEnabled = true;
2646 				break;
2647 			}
2648 			setError(GL_INVALID_ENUM);
2649 			break;
2650 
2651 		case GL_DEPTH_CLAMP:
2652 			if (glu::isContextTypeGLCore(getType()))
2653 			{
2654 				m_depthClampEnabled = true;
2655 				break;
2656 			}
2657 			setError(GL_INVALID_ENUM);
2658 			break;
2659 
2660 		case GL_DITHER:
2661 			// Not implemented - just ignored.
2662 			break;
2663 
2664 		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2665 			if (!glu::isContextTypeGLCore(getType()))
2666 			{
2667 				m_primitiveRestartFixedIndex = true;
2668 				break;
2669 			}
2670 			setError(GL_INVALID_ENUM);
2671 			break;
2672 
2673 		case GL_PRIMITIVE_RESTART:
2674 			if (glu::isContextTypeGLCore(getType()))
2675 			{
2676 				m_primitiveRestartSettableIndex = true;
2677 				break;
2678 			}
2679 			setError(GL_INVALID_ENUM);
2680 			break;
2681 
2682 		default:
2683 			setError(GL_INVALID_ENUM);
2684 			break;
2685 	}
2686 }
2687 
disable(deUint32 cap)2688 void ReferenceContext::disable (deUint32 cap)
2689 {
2690 	switch (cap)
2691 	{
2692 		case GL_BLEND:					m_blendEnabled				= false;	break;
2693 		case GL_SCISSOR_TEST:			m_scissorEnabled			= false;	break;
2694 		case GL_DEPTH_TEST:				m_depthTestEnabled			= false;	break;
2695 		case GL_STENCIL_TEST:			m_stencilTestEnabled		= false;	break;
2696 		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= false;	break;
2697 
2698 		case GL_FRAMEBUFFER_SRGB:
2699 			if (glu::isContextTypeGLCore(getType()))
2700 			{
2701 				m_sRGBUpdateEnabled = false;
2702 				break;
2703 			}
2704 			setError(GL_INVALID_ENUM);
2705 			break;
2706 
2707 		case GL_DEPTH_CLAMP:
2708 			if (glu::isContextTypeGLCore(getType()))
2709 			{
2710 				m_depthClampEnabled = false;
2711 				break;
2712 			}
2713 			setError(GL_INVALID_ENUM);
2714 			break;
2715 
2716 		case GL_DITHER:
2717 			break;
2718 
2719 		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2720 			if (!glu::isContextTypeGLCore(getType()))
2721 			{
2722 				m_primitiveRestartFixedIndex = false;
2723 				break;
2724 			}
2725 			setError(GL_INVALID_ENUM);
2726 			break;
2727 
2728 		case GL_PRIMITIVE_RESTART:
2729 			if (glu::isContextTypeGLCore(getType()))
2730 			{
2731 				m_primitiveRestartSettableIndex = false;
2732 				break;
2733 			}
2734 			setError(GL_INVALID_ENUM);
2735 			break;
2736 
2737 		default:
2738 			setError(GL_INVALID_ENUM);
2739 			break;
2740 	}
2741 }
2742 
isValidCompareFunc(deUint32 func)2743 static bool isValidCompareFunc (deUint32 func)
2744 {
2745 	switch (func)
2746 	{
2747 		case GL_NEVER:
2748 		case GL_LESS:
2749 		case GL_LEQUAL:
2750 		case GL_GREATER:
2751 		case GL_GEQUAL:
2752 		case GL_EQUAL:
2753 		case GL_NOTEQUAL:
2754 		case GL_ALWAYS:
2755 			return true;
2756 
2757 		default:
2758 			return false;
2759 	}
2760 }
2761 
isValidStencilOp(deUint32 op)2762 static bool isValidStencilOp (deUint32 op)
2763 {
2764 	switch (op)
2765 	{
2766 		case GL_KEEP:
2767 		case GL_ZERO:
2768 		case GL_REPLACE:
2769 		case GL_INCR:
2770 		case GL_INCR_WRAP:
2771 		case GL_DECR:
2772 		case GL_DECR_WRAP:
2773 		case GL_INVERT:
2774 			return true;
2775 
2776 		default:
2777 			return false;
2778 	}
2779 }
2780 
stencilFunc(deUint32 func,int ref,deUint32 mask)2781 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
2782 {
2783 	stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2784 }
2785 
stencilFuncSeparate(deUint32 face,deUint32 func,int ref,deUint32 mask)2786 void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
2787 {
2788 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
2789 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
2790 
2791 	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2792 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2793 
2794 	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2795 	{
2796 		if ((type == rr::FACETYPE_FRONT && setFront) ||
2797 			(type == rr::FACETYPE_BACK && setBack))
2798 		{
2799 			m_stencil[type].func	= func;
2800 			m_stencil[type].ref		= ref;
2801 			m_stencil[type].opMask	= mask;
2802 		}
2803 	}
2804 }
2805 
stencilOp(deUint32 sfail,deUint32 dpfail,deUint32 dppass)2806 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2807 {
2808 	stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
2809 }
2810 
stencilOpSeparate(deUint32 face,deUint32 sfail,deUint32 dpfail,deUint32 dppass)2811 void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2812 {
2813 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
2814 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
2815 
2816 	RC_IF_ERROR(!isValidStencilOp(sfail)	||
2817 				!isValidStencilOp(dpfail)	||
2818 				!isValidStencilOp(dppass),
2819 				GL_INVALID_ENUM, RC_RET_VOID);
2820 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2821 
2822 	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2823 	{
2824 		if ((type == rr::FACETYPE_FRONT && setFront) ||
2825 			(type == rr::FACETYPE_BACK && setBack))
2826 		{
2827 			m_stencil[type].opStencilFail	= sfail;
2828 			m_stencil[type].opDepthFail		= dpfail;
2829 			m_stencil[type].opDepthPass		= dppass;
2830 		}
2831 	}
2832 }
2833 
depthFunc(deUint32 func)2834 void ReferenceContext::depthFunc (deUint32 func)
2835 {
2836 	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2837 	m_depthFunc = func;
2838 }
2839 
depthRangef(float n,float f)2840 void ReferenceContext::depthRangef (float n, float f)
2841 {
2842 	m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
2843 	m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
2844 }
2845 
depthRange(double n,double f)2846 void ReferenceContext::depthRange (double n, double f)
2847 {
2848 	depthRangef((float)n, (float)f);
2849 }
2850 
polygonOffset(float factor,float units)2851 void ReferenceContext::polygonOffset (float factor, float units)
2852 {
2853 	m_polygonOffsetFactor = factor;
2854 	m_polygonOffsetUnits = units;
2855 }
2856 
provokingVertex(deUint32 convention)2857 void ReferenceContext::provokingVertex (deUint32 convention)
2858 {
2859 	// only in core
2860 	DE_ASSERT(glu::isContextTypeGLCore(getType()));
2861 
2862 	switch (convention)
2863 	{
2864 		case GL_FIRST_VERTEX_CONVENTION:	m_provokingFirstVertexConvention = true; break;
2865 		case GL_LAST_VERTEX_CONVENTION:		m_provokingFirstVertexConvention = false; break;
2866 
2867 		default:
2868 			RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
2869 	}
2870 }
2871 
primitiveRestartIndex(deUint32 index)2872 void ReferenceContext::primitiveRestartIndex (deUint32 index)
2873 {
2874 	// only in core
2875 	DE_ASSERT(glu::isContextTypeGLCore(getType()));
2876 	m_primitiveRestartIndex = index;
2877 }
2878 
isValidBlendEquation(deUint32 mode)2879 static inline bool isValidBlendEquation (deUint32 mode)
2880 {
2881 	return mode == GL_FUNC_ADD				||
2882 		   mode == GL_FUNC_SUBTRACT			||
2883 		   mode == GL_FUNC_REVERSE_SUBTRACT	||
2884 		   mode == GL_MIN					||
2885 		   mode == GL_MAX;
2886 }
2887 
isValidBlendFactor(deUint32 factor)2888 static bool isValidBlendFactor (deUint32 factor)
2889 {
2890 	switch (factor)
2891 	{
2892 		case GL_ZERO:
2893 		case GL_ONE:
2894 		case GL_SRC_COLOR:
2895 		case GL_ONE_MINUS_SRC_COLOR:
2896 		case GL_DST_COLOR:
2897 		case GL_ONE_MINUS_DST_COLOR:
2898 		case GL_SRC_ALPHA:
2899 		case GL_ONE_MINUS_SRC_ALPHA:
2900 		case GL_DST_ALPHA:
2901 		case GL_ONE_MINUS_DST_ALPHA:
2902 		case GL_CONSTANT_COLOR:
2903 		case GL_ONE_MINUS_CONSTANT_COLOR:
2904 		case GL_CONSTANT_ALPHA:
2905 		case GL_ONE_MINUS_CONSTANT_ALPHA:
2906 		case GL_SRC_ALPHA_SATURATE:
2907 			return true;
2908 
2909 		default:
2910 			return false;
2911 	}
2912 }
2913 
blendEquation(deUint32 mode)2914 void ReferenceContext::blendEquation (deUint32 mode)
2915 {
2916 	RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);
2917 
2918 	m_blendModeRGB		= mode;
2919 	m_blendModeAlpha	= mode;
2920 }
2921 
blendEquationSeparate(deUint32 modeRGB,deUint32 modeAlpha)2922 void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
2923 {
2924 	RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
2925 				!isValidBlendEquation(modeAlpha),
2926 				GL_INVALID_ENUM, RC_RET_VOID);
2927 
2928 	m_blendModeRGB		= modeRGB;
2929 	m_blendModeAlpha	= modeAlpha;
2930 }
2931 
blendFunc(deUint32 src,deUint32 dst)2932 void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
2933 {
2934 	RC_IF_ERROR(!isValidBlendFactor(src) ||
2935 				!isValidBlendFactor(dst),
2936 				GL_INVALID_ENUM, RC_RET_VOID);
2937 
2938 	m_blendFactorSrcRGB		= src;
2939 	m_blendFactorSrcAlpha	= src;
2940 	m_blendFactorDstRGB		= dst;
2941 	m_blendFactorDstAlpha	= dst;
2942 }
2943 
blendFuncSeparate(deUint32 srcRGB,deUint32 dstRGB,deUint32 srcAlpha,deUint32 dstAlpha)2944 void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
2945 {
2946 	RC_IF_ERROR(!isValidBlendFactor(srcRGB)		||
2947 				!isValidBlendFactor(dstRGB)		||
2948 				!isValidBlendFactor(srcAlpha)	||
2949 				!isValidBlendFactor(dstAlpha),
2950 				GL_INVALID_ENUM, RC_RET_VOID);
2951 
2952 	m_blendFactorSrcRGB		= srcRGB;
2953 	m_blendFactorSrcAlpha	= srcAlpha;
2954 	m_blendFactorDstRGB		= dstRGB;
2955 	m_blendFactorDstAlpha	= dstAlpha;
2956 }
2957 
blendColor(float red,float green,float blue,float alpha)2958 void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
2959 {
2960 	m_blendColor = Vec4(de::clamp(red,	0.0f, 1.0f),
2961 						de::clamp(green,	0.0f, 1.0f),
2962 						de::clamp(blue,	0.0f, 1.0f),
2963 						de::clamp(alpha,	0.0f, 1.0f));
2964 }
2965 
colorMask(deBool r,deBool g,deBool b,deBool a)2966 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
2967 {
2968 	m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
2969 }
2970 
depthMask(deBool mask)2971 void ReferenceContext::depthMask (deBool mask)
2972 {
2973 	m_depthMask = !!mask;
2974 }
2975 
stencilMask(deUint32 mask)2976 void ReferenceContext::stencilMask (deUint32 mask)
2977 {
2978 	stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
2979 }
2980 
stencilMaskSeparate(deUint32 face,deUint32 mask)2981 void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
2982 {
2983 	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
2984 	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;
2985 
2986 	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2987 
2988 	if (setFront)	m_stencil[rr::FACETYPE_FRONT].writeMask	= mask;
2989 	if (setBack)	m_stencil[rr::FACETYPE_BACK].writeMask	= mask;
2990 }
2991 
getNumStencilBits(const tcu::TextureFormat & format)2992 static int getNumStencilBits (const tcu::TextureFormat& format)
2993 {
2994 	switch (format.order)
2995 	{
2996 		case tcu::TextureFormat::S:
2997 			switch (format.type)
2998 			{
2999 				case tcu::TextureFormat::UNSIGNED_INT8:		return 8;
3000 				case tcu::TextureFormat::UNSIGNED_INT16:	return 16;
3001 				case tcu::TextureFormat::UNSIGNED_INT32:	return 32;
3002 				default:
3003 					DE_ASSERT(false);
3004 					return 0;
3005 			}
3006 
3007 		case tcu::TextureFormat::DS:
3008 			switch (format.type)
3009 			{
3010 				case tcu::TextureFormat::UNSIGNED_INT_24_8:				return 8;
3011 				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return 8;
3012 				default:
3013 					DE_ASSERT(false);
3014 					return 0;
3015 			}
3016 
3017 		default:
3018 			DE_ASSERT(false);
3019 			return 0;
3020 	}
3021 }
3022 
maskStencil(int numBits,deUint32 s)3023 static inline deUint32 maskStencil (int numBits, deUint32 s)
3024 {
3025 	return s & deBitMask32(0, numBits);
3026 }
3027 
writeMaskedStencil(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,deUint32 stencil,deUint32 writeMask)3028 static inline void writeMaskedStencil (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, deUint32 stencil, deUint32 writeMask)
3029 {
3030 	DE_ASSERT(access.raw().getFormat().order == tcu::TextureFormat::S);
3031 
3032 	const deUint32 oldVal = access.raw().getPixelUint(s, x, y).x();
3033 	const deUint32 newVal = (oldVal & ~writeMask) | (stencil & writeMask);
3034 	access.raw().setPixel(tcu::UVec4(newVal, 0u, 0u, 0u), s, x, y);
3035 }
3036 
writeDepthOnly(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,float depth)3037 static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
3038 {
3039 	access.raw().setPixDepth(depth, s, x, y);
3040 }
3041 
getDepthMultisampleAccess(const rr::MultisamplePixelBufferAccess & combinedDSaccess)3042 static rr::MultisamplePixelBufferAccess getDepthMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3043 {
3044 	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_DEPTH));
3045 }
3046 
getStencilMultisampleAccess(const rr::MultisamplePixelBufferAccess & combinedDSaccess)3047 static rr::MultisamplePixelBufferAccess getStencilMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3048 {
3049 	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_STENCIL));
3050 }
3051 
blitResolveMultisampleFramebuffer(deUint32 mask,const IVec4 & srcRect,const IVec4 & dstRect,bool flipX,bool flipY)3052 deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
3053 {
3054 	if (mask & GL_COLOR_BUFFER_BIT)
3055 	{
3056 		rr::MultisampleConstPixelBufferAccess	src			= rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3057 		tcu::PixelBufferAccess					dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3058 		tcu::TextureChannelClass				dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
3059 		bool									dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
3060 															  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
3061 															  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3062 		bool									srcIsSRGB	= tcu::isSRGB(src.raw().getFormat());
3063 		bool									dstIsSRGB	= tcu::isSRGB(dst.getFormat());
3064 		const bool								convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3065 
3066 		if (!convertSRGB)
3067 		{
3068 			tcu::ConstPixelBufferAccess	srcRaw	= src.raw();
3069 			tcu::TextureFormat			srcFmt	= toNonSRGBFormat(srcRaw.getFormat());
3070 
3071 			srcRaw	= tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
3072 			src		= rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);
3073 
3074 			dst		= tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3075 		}
3076 
3077 		for (int x = 0; x < dstRect.z(); ++x)
3078 		for (int y = 0; y < dstRect.w(); ++y)
3079 		{
3080 			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3081 			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3082 
3083 			if (dstIsFloat || srcIsSRGB)
3084 			{
3085 				Vec4 p = src.raw().getPixel(0, srcX,srcY);
3086 				dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
3087 			}
3088 			else
3089 				dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
3090 		}
3091 	}
3092 
3093 	if (mask & GL_DEPTH_BUFFER_BIT)
3094 	{
3095 		rr::MultisampleConstPixelBufferAccess	src	= rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3096 		rr::MultisamplePixelBufferAccess		dst	= rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3097 
3098 		for (int x = 0; x < dstRect.z(); ++x)
3099 		for (int y = 0; y < dstRect.w(); ++y)
3100 		{
3101 			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3102 			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3103 
3104 			writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
3105 		}
3106 	}
3107 
3108 	if (mask & GL_STENCIL_BUFFER_BIT)
3109 	{
3110 		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3111 		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3112 
3113 		for (int x = 0; x < dstRect.z(); ++x)
3114 		for (int y = 0; y < dstRect.w(); ++y)
3115 		{
3116 			int			srcX		= (flipX) ? (srcRect.z() - x - 1) : (x);
3117 			int			srcY		= (flipY) ? (srcRect.z() - y - 1) : (y);
3118 			deUint32	srcStencil	= src.raw().getPixelUint(0, srcX, srcY).x();
3119 
3120 			writeMaskedStencil(dst, 0, x, y, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3121 		}
3122 	}
3123 
3124 	return GL_NO_ERROR;
3125 }
3126 
blitFramebuffer(int srcX0,int srcY0,int srcX1,int srcY1,int dstX0,int dstY0,int dstX1,int dstY1,deUint32 mask,deUint32 filter)3127 void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
3128 {
3129 	// p0 in inclusive, p1 exclusive.
3130 	// Negative width/height means swap.
3131 	bool	swapSrcX	= srcX1 < srcX0;
3132 	bool	swapSrcY	= srcY1 < srcY0;
3133 	bool	swapDstX	= dstX1 < dstX0;
3134 	bool	swapDstY	= dstY1 < dstY0;
3135 	int		srcW		= de::abs(srcX1-srcX0);
3136 	int		srcH		= de::abs(srcY1-srcY0);
3137 	int		dstW		= de::abs(dstX1-dstX0);
3138 	int		dstH		= de::abs(dstY1-dstY0);
3139 	bool	scale		= srcW != dstW || srcH != dstH;
3140 	int		srcOriginX	= swapSrcX ? srcX1 : srcX0;
3141 	int		srcOriginY	= swapSrcY ? srcY1 : srcY0;
3142 	int		dstOriginX	= swapDstX ? dstX1 : dstX0;
3143 	int		dstOriginY	= swapDstY ? dstY1 : dstY0;
3144 	IVec4	srcRect		= IVec4(srcOriginX, srcOriginY, srcW, srcH);
3145 	IVec4	dstRect		= IVec4(dstOriginX, dstOriginY, dstW, dstH);
3146 
3147 	RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
3148 	RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);
3149 
3150 	// Validate that both targets are complete.
3151 	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
3152 				checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);
3153 
3154 	// Check samples count is valid
3155 	RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);
3156 
3157 	// Check size restrictions of multisampled case
3158 	if (getReadColorbuffer().getNumSamples() != 1)
3159 	{
3160 		// Src and Dst rect dimensions must be the same
3161 		RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);
3162 
3163 		// Framebuffer formats must match
3164 		if (mask & GL_COLOR_BUFFER_BIT)		RC_IF_ERROR(getReadColorbuffer().raw().getFormat()   != getDrawColorbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3165 		if (mask & GL_DEPTH_BUFFER_BIT)		RC_IF_ERROR(getReadDepthbuffer().raw().getFormat()   != getDrawDepthbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3166 		if (mask & GL_STENCIL_BUFFER_BIT)	RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3167 	}
3168 
3169 	// Compute actual source rect.
3170 	srcRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadColorbuffer()))	: srcRect;
3171 	srcRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadDepthbuffer()))	: srcRect;
3172 	srcRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(srcRect, getBufferRect(getReadStencilbuffer()))	: srcRect;
3173 
3174 	// Compute destination rect.
3175 	dstRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawColorbuffer()))	: dstRect;
3176 	dstRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawDepthbuffer()))	: dstRect;
3177 	dstRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(dstRect, getBufferRect(getDrawStencilbuffer()))	: dstRect;
3178 	dstRect = m_scissorEnabled					? intersect(dstRect, m_scissorBox)							: dstRect;
3179 
3180 	if (isEmpty(srcRect) || isEmpty(dstRect))
3181 		return; // Don't attempt copy.
3182 
3183 	// Multisampled read buffer is a special case
3184 	if (getReadColorbuffer().getNumSamples() != 1)
3185 	{
3186 		deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);
3187 
3188 		if (error != GL_NO_ERROR)
3189 			setError(error);
3190 
3191 		return;
3192 	}
3193 
3194 	// \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
3195 
3196 	// Coordinate transformation:
3197 	// Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
3198 	tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
3199 						* tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
3200 										 (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
3201 										 1.0f))
3202 						* tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));
3203 
3204 	if (mask & GL_COLOR_BUFFER_BIT)
3205 	{
3206 		tcu::ConstPixelBufferAccess		src			= tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3207 		tcu::PixelBufferAccess			dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3208 		tcu::TextureChannelClass		dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
3209 		bool							dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
3210 													  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
3211 													  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3212 		tcu::Sampler::FilterMode		sFilter		= (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3213 		tcu::Sampler					sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
3214 													 sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
3215 		bool							srcIsSRGB	= tcu::isSRGB(src.getFormat());
3216 		bool							dstIsSRGB	= tcu::isSRGB(dst.getFormat());
3217 		const bool						convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3218 
3219 		if (!convertSRGB)
3220 		{
3221 			src	= tcu::ConstPixelBufferAccess	(toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
3222 			dst	= tcu::PixelBufferAccess		(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3223 		}
3224 
3225 		// \note We don't check for unsupported conversions, unlike spec requires.
3226 
3227 		for (int yo = 0; yo < dstRect.w(); yo++)
3228 		{
3229 			for (int xo = 0; xo < dstRect.z(); xo++)
3230 			{
3231 				float	dX	= (float)xo + 0.5f;
3232 				float	dY	= (float)yo + 0.5f;
3233 
3234 				// \note Only affine part is used.
3235 				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3236 				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3237 
3238 				// do not copy pixels outside the modified source region (modified by buffer intersection)
3239 				if (sX < 0.0f || sX >= (float)srcRect.z() ||
3240 					sY < 0.0f || sY >= (float)srcRect.w())
3241 					continue;
3242 
3243 				if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
3244 				{
3245 					Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
3246 					dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
3247 				}
3248 				else
3249 					dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
3250 			}
3251 		}
3252 	}
3253 
3254 	if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
3255 	{
3256 		rr::MultisampleConstPixelBufferAccess	src		= getDepthMultisampleAccess(rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3257 		rr::MultisamplePixelBufferAccess		dst		= getDepthMultisampleAccess(rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3258 
3259 		for (int yo = 0; yo < dstRect.w(); yo++)
3260 		{
3261 			for (int xo = 0; xo < dstRect.z(); xo++)
3262 			{
3263 				const int sampleNdx = 0; // multisample read buffer case is already handled
3264 
3265 				float	dX	= (float)xo + 0.5f;
3266 				float	dY	= (float)yo + 0.5f;
3267 				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3268 				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3269 
3270 				writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixDepth(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)));
3271 			}
3272 		}
3273 	}
3274 
3275 	if (mask & GL_STENCIL_BUFFER_BIT)
3276 	{
3277 		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3278 		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3279 
3280 		for (int yo = 0; yo < dstRect.w(); yo++)
3281 		{
3282 			for (int xo = 0; xo < dstRect.z(); xo++)
3283 			{
3284 				const int	sampleNdx = 0; // multisample read buffer case is already handled
3285 
3286 				float		dX			= (float)xo + 0.5f;
3287 				float		dY			= (float)yo + 0.5f;
3288 				float		sX			= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3289 				float		sY			= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3290 				deUint32	srcStencil	= src.raw().getPixelUint(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x();
3291 
3292 				writeMaskedStencil(dst, sampleNdx, xo, yo, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3293 			}
3294 		}
3295 	}
3296 }
3297 
invalidateSubFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments,int x,int y,int width,int height)3298 void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
3299 {
3300 	RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
3301 	RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
3302 	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
3303 
3304 	// \todo [2012-07-17 pyry] Support multiple color attachments.
3305 
3306 	const Vec4		colorClearValue		(0.0f);
3307 	const float		depthClearValue		= 1.0f;
3308 	const int		stencilClearValue	= 0;
3309 
3310 	bool			isFboBound			= m_drawFramebufferBinding != DE_NULL;
3311 	bool			discardBuffers[3]	= { false, false, false }; // Color, depth, stencil
3312 
3313 	for (int attNdx = 0; attNdx < numAttachments; attNdx++)
3314 	{
3315 		bool	isColor			= attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0		: GL_COLOR);
3316 		bool	isDepth			= attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT		: GL_DEPTH);
3317 		bool	isStencil		= attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT	: GL_STENCIL);
3318 		bool	isDepthStencil	= isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;
3319 
3320 		RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);
3321 
3322 		if (isColor)						discardBuffers[0] = true;
3323 		if (isDepth || isDepthStencil)		discardBuffers[1] = true;
3324 		if (isStencil || isDepthStencil)	discardBuffers[2] = true;
3325 	}
3326 
3327 	for (int ndx = 0; ndx < 3; ndx++)
3328 	{
3329 		if (!discardBuffers[ndx])
3330 			continue;
3331 
3332 		bool								isColor					= ndx == 0;
3333 		bool								isDepth					= ndx == 1;
3334 		bool								isStencil				= ndx == 2;
3335 		rr::MultisamplePixelBufferAccess	buf						= isColor ? getDrawColorbuffer()								:
3336 																	  isDepth ? getDepthMultisampleAccess(getDrawDepthbuffer())		:
3337 																				getStencilMultisampleAccess(getDrawStencilbuffer());
3338 
3339 		if (isEmpty(buf))
3340 			continue;
3341 
3342 		tcu::IVec4							area					= intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
3343 		rr::MultisamplePixelBufferAccess	access					= rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());
3344 
3345 		if (isColor)
3346 			rr::clear(access, colorClearValue);
3347 		else if (isDepth)
3348 			rr::clear(access, tcu::Vec4(depthClearValue));
3349 		else if (isStencil)
3350 			rr::clear(access, tcu::IVec4(stencilClearValue));
3351 	}
3352 }
3353 
invalidateFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments)3354 void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
3355 {
3356 	// \todo [2012-07-17 pyry] Support multiple color attachments.
3357 	rr::MultisampleConstPixelBufferAccess	colorBuf0	= getDrawColorbuffer();
3358 	rr::MultisampleConstPixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3359 	rr::MultisampleConstPixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3360 	int										width		= 0;
3361 	int										height		= 0;
3362 
3363 	width = de::max(width, colorBuf0.raw().getHeight());
3364 	width = de::max(width, depthBuf.raw().getHeight());
3365 	width = de::max(width, stencilBuf.raw().getHeight());
3366 
3367 	height = de::max(height, colorBuf0.raw().getDepth());
3368 	height = de::max(height, depthBuf.raw().getDepth());
3369 	height = de::max(height, stencilBuf.raw().getDepth());
3370 
3371 	invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
3372 }
3373 
clear(deUint32 buffers)3374 void ReferenceContext::clear (deUint32 buffers)
3375 {
3376 	RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);
3377 
3378 	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
3379 	rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3380 	rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3381 	IVec4								baseArea	= m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3382 	IVec4								colorArea	= intersect(baseArea, getBufferRect(colorBuf0));
3383 	IVec4								depthArea	= intersect(baseArea, getBufferRect(depthBuf));
3384 	IVec4								stencilArea	= intersect(baseArea, getBufferRect(stencilBuf));
3385 	bool								hasColor0	= !isEmpty(colorArea);
3386 	bool								hasDepth	= !isEmpty(depthArea);
3387 	bool								hasStencil	= !isEmpty(stencilArea);
3388 
3389 	if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
3390 	{
3391 		rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
3392 		bool								isSRGB		= tcu::isSRGB(colorBuf0.raw().getFormat());
3393 		Vec4								c			= (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
3394 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3395 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3396 
3397 		if (!maskUsed)
3398 			rr::clear(access, c);
3399 		else if (!maskZero)
3400 		{
3401 			for (int y = 0; y < access.raw().getDepth(); y++)
3402 				for (int x = 0; x < access.raw().getHeight(); x++)
3403 					for (int s = 0; s < access.getNumSamples(); s++)
3404 						access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3405 		}
3406 		// else all channels masked out
3407 	}
3408 
3409 	if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
3410 	{
3411 		rr::MultisamplePixelBufferAccess access = getDepthMultisampleAccess(rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w()));
3412 		rr::clearDepth(access, m_clearDepth);
3413 	}
3414 
3415 	if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
3416 	{
3417 		rr::MultisamplePixelBufferAccess	access					= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w()));
3418 		int									stencilBits				= getNumStencilBits(stencilBuf.raw().getFormat());
3419 		int									stencil					= maskStencil(stencilBits, m_clearStencil);
3420 
3421 		if ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u))
3422 		{
3423 			// Slow path where depth or stencil is masked out in write.
3424 			for (int y = 0; y < access.raw().getDepth(); y++)
3425 				for (int x = 0; x < access.raw().getHeight(); x++)
3426 					for (int s = 0; s < access.getNumSamples(); s++)
3427 						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3428 		}
3429 		else
3430 			rr::clearStencil(access, stencil);
3431 	}
3432 }
3433 
clearBufferiv(deUint32 buffer,int drawbuffer,const int * value)3434 void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
3435 {
3436 	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3437 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3438 
3439 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3440 
3441 	if (buffer == GL_COLOR)
3442 	{
3443 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3444 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3445 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3446 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3447 
3448 		if (!isEmpty(area) && !maskZero)
3449 		{
3450 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3451 			IVec4								color		(value[0], value[1], value[2], value[3]);
3452 
3453 			if (!maskUsed)
3454 				rr::clear(access, color);
3455 			else
3456 			{
3457 				for (int y = 0; y < access.raw().getDepth(); y++)
3458 					for (int x = 0; x < access.raw().getHeight(); x++)
3459 						for (int s = 0; s < access.getNumSamples(); s++)
3460 							access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
3461 			}
3462 		}
3463 	}
3464 	else
3465 	{
3466 		TCU_CHECK_INTERNAL(buffer == GL_STENCIL);
3467 
3468 		rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
3469 		IVec4								area		= intersect(baseArea, getBufferRect(stencilBuf));
3470 
3471 		if (!isEmpty(area) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
3472 		{
3473 			rr::MultisamplePixelBufferAccess	access		= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w()));
3474 			int									stencil		= value[0];
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 						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3480 		}
3481 	}
3482 }
3483 
clearBufferfv(deUint32 buffer,int drawbuffer,const float * value)3484 void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
3485 {
3486 	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
3487 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3488 
3489 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3490 
3491 	if (buffer == GL_COLOR)
3492 	{
3493 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3494 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3495 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3496 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3497 
3498 		if (!isEmpty(area) && !maskZero)
3499 		{
3500 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3501 			Vec4								color		(value[0], value[1], value[2], value[3]);
3502 
3503 			if (m_sRGBUpdateEnabled && tcu::isSRGB(access.raw().getFormat()))
3504 				color = tcu::linearToSRGB(color);
3505 
3506 			if (!maskUsed)
3507 				rr::clear(access, color);
3508 			else
3509 			{
3510 				for (int y = 0; y < access.raw().getDepth(); y++)
3511 					for (int x = 0; x < access.raw().getHeight(); x++)
3512 						for (int s = 0; s < access.getNumSamples(); s++)
3513 							access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3514 			}
3515 		}
3516 	}
3517 	else
3518 	{
3519 		TCU_CHECK_INTERNAL(buffer == GL_DEPTH);
3520 
3521 		rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
3522 		IVec4								area		= intersect(baseArea, getBufferRect(depthBuf));
3523 
3524 		if (!isEmpty(area) && m_depthMask)
3525 		{
3526 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
3527 			float								depth		= value[0];
3528 
3529 			rr::clearDepth(access, depth);
3530 		}
3531 	}
3532 }
3533 
clearBufferuiv(deUint32 buffer,int drawbuffer,const deUint32 * value)3534 void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
3535 {
3536 	RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
3537 	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3538 
3539 	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3540 
3541 	TCU_CHECK_INTERNAL(buffer == GL_COLOR);
3542 	{
3543 		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
3544 		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3545 		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3546 		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));
3547 
3548 		if (!isEmpty(area) && !maskZero)
3549 		{
3550 			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3551 			tcu::UVec4							color		(value[0], value[1], value[2], value[3]);
3552 
3553 			if (!maskUsed)
3554 				rr::clear(access, color.asInt());
3555 			else
3556 			{
3557 				for (int y = 0; y < access.raw().getDepth(); y++)
3558 					for (int x = 0; x < access.raw().getHeight(); x++)
3559 						for (int s = 0; s < access.getNumSamples(); s++)
3560 							access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
3561 			}
3562 		}
3563 	}
3564 }
3565 
clearBufferfi(deUint32 buffer,int drawbuffer,float depth,int stencil)3566 void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
3567 {
3568 	RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3569 	clearBufferfv(GL_DEPTH, drawbuffer, &depth);
3570 	clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
3571 }
3572 
bindVertexArray(deUint32 array)3573 void ReferenceContext::bindVertexArray (deUint32 array)
3574 {
3575 	rc::VertexArray* vertexArrayObject = DE_NULL;
3576 
3577 	if (array != 0)
3578 	{
3579 		vertexArrayObject = m_vertexArrays.find(array);
3580 		if (!vertexArrayObject)
3581 		{
3582 			vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
3583 			m_vertexArrays.insert(vertexArrayObject);
3584 		}
3585 	}
3586 
3587 	// Create new references
3588 	if (vertexArrayObject)
3589 		m_vertexArrays.acquireReference(vertexArrayObject);
3590 
3591 	// Remove old references
3592 	if (m_vertexArrayBinding)
3593 		m_vertexArrays.releaseReference(m_vertexArrayBinding);
3594 
3595 	m_vertexArrayBinding = vertexArrayObject;
3596 }
3597 
genVertexArrays(int numArrays,deUint32 * vertexArrays)3598 void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
3599 {
3600 	RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);
3601 
3602 	for (int ndx = 0; ndx < numArrays; ndx++)
3603 		vertexArrays[ndx] = m_vertexArrays.allocateName();
3604 }
3605 
deleteVertexArrays(int numArrays,const deUint32 * vertexArrays)3606 void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
3607 {
3608 	for (int i = 0; i < numArrays; i++)
3609 	{
3610 		deUint32		name		= vertexArrays[i];
3611 		VertexArray*	vertexArray	= name ? m_vertexArrays.find(name) : DE_NULL;
3612 
3613 		if (vertexArray)
3614 			deleteVertexArray(vertexArray);
3615 	}
3616 }
3617 
vertexAttribPointer(deUint32 index,int rawSize,deUint32 type,deBool normalized,int stride,const void * pointer)3618 void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
3619 {
3620 	const bool allowBGRA	= !glu::isContextTypeES(getType());
3621 	const int effectiveSize	= (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);
3622 
3623 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3624 	RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
3625 	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
3626 				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
3627 				type != GL_INT					&&	type != GL_UNSIGNED_INT		&&
3628 				type != GL_FIXED				&&	type != GL_DOUBLE			&&
3629 				type != GL_FLOAT				&&	type != GL_HALF_FLOAT		&&
3630 				type != GL_INT_2_10_10_10_REV	&&	type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
3631 	RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3632 	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3633 	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);
3634 	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3635 	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);
3636 	RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);
3637 
3638 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3639 
3640 	vao.m_arrays[index].size			= rawSize;
3641 	vao.m_arrays[index].stride			= stride;
3642 	vao.m_arrays[index].type			= type;
3643 	vao.m_arrays[index].normalized		= normalized == GL_TRUE;
3644 	vao.m_arrays[index].integer			= false;
3645 	vao.m_arrays[index].pointer			= pointer;
3646 
3647 	// acquire new reference
3648 	if (m_arrayBufferBinding)
3649 		m_buffers.acquireReference(m_arrayBufferBinding);
3650 
3651 	// release old reference
3652 	if (vao.m_arrays[index].bufferBinding)
3653 		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3654 
3655 	vao.m_arrays[index].bufferDeleted	= false;
3656 	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
3657 }
3658 
vertexAttribIPointer(deUint32 index,int size,deUint32 type,int stride,const void * pointer)3659 void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
3660 {
3661 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3662 	RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
3663 	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
3664 				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
3665 				type != GL_INT					&&	type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
3666 	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3667 	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3668 
3669 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3670 
3671 	vao.m_arrays[index].size			= size;
3672 	vao.m_arrays[index].stride			= stride;
3673 	vao.m_arrays[index].type			= type;
3674 	vao.m_arrays[index].normalized		= false;
3675 	vao.m_arrays[index].integer			= true;
3676 	vao.m_arrays[index].pointer			= pointer;
3677 
3678 	// acquire new reference
3679 	if (m_arrayBufferBinding)
3680 		m_buffers.acquireReference(m_arrayBufferBinding);
3681 
3682 	// release old reference
3683 	if (vao.m_arrays[index].bufferBinding)
3684 		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3685 
3686 	vao.m_arrays[index].bufferDeleted	= false;
3687 	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
3688 }
3689 
enableVertexAttribArray(deUint32 index)3690 void ReferenceContext::enableVertexAttribArray (deUint32 index)
3691 {
3692 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3693 
3694 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3695 	vao.m_arrays[index].enabled = true;
3696 }
3697 
disableVertexAttribArray(deUint32 index)3698 void ReferenceContext::disableVertexAttribArray (deUint32 index)
3699 {
3700 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3701 
3702 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3703 	vao.m_arrays[index].enabled = false;
3704 }
3705 
vertexAttribDivisor(deUint32 index,deUint32 divisor)3706 void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
3707 {
3708 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3709 
3710 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3711 	vao.m_arrays[index].divisor = divisor;
3712 }
3713 
vertexAttrib1f(deUint32 index,float x)3714 void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
3715 {
3716 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3717 
3718 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
3719 }
3720 
vertexAttrib2f(deUint32 index,float x,float y)3721 void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
3722 {
3723 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3724 
3725 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
3726 }
3727 
vertexAttrib3f(deUint32 index,float x,float y,float z)3728 void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
3729 {
3730 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3731 
3732 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
3733 }
3734 
vertexAttrib4f(deUint32 index,float x,float y,float z,float w)3735 void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
3736 {
3737 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3738 
3739 	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
3740 }
3741 
vertexAttribI4i(deUint32 index,deInt32 x,deInt32 y,deInt32 z,deInt32 w)3742 void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
3743 {
3744 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3745 
3746 	m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
3747 }
3748 
vertexAttribI4ui(deUint32 index,deUint32 x,deUint32 y,deUint32 z,deUint32 w)3749 void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
3750 {
3751 	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3752 
3753 	m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
3754 }
3755 
getAttribLocation(deUint32 program,const char * name)3756 deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
3757 {
3758 	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3759 
3760 	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3761 
3762 	if (name)
3763 	{
3764 		std::string nameString(name);
3765 
3766 		for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
3767 			if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
3768 				return (int)ndx;
3769 	}
3770 
3771 	return -1;
3772 }
3773 
uniformv(deInt32 location,glu::DataType type,deInt32 count,const void * v)3774 void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
3775 {
3776 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3777 
3778 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3779 
3780 	if (location == -1)
3781 		return;
3782 
3783 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3784 	RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
3785 	RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3786 
3787 	{
3788 		const int scalarSize = glu::getDataTypeScalarSize(type);
3789 		DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
3790 		deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
3791 	}
3792 }
3793 
uniform1iv(deInt32 location,deInt32 count,const deInt32 * v)3794 void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
3795 {
3796 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3797 
3798 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3799 
3800 	if (location == -1)
3801 		return;
3802 
3803 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), 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 	switch (uniforms[location].type)
3807 	{
3808 		case glu::TYPE_INT:		uniforms[location].value.i = *v;	return;
3809 
3810 		// \note texture unit is stored to value
3811 		case glu::TYPE_SAMPLER_2D:
3812 		case glu::TYPE_UINT_SAMPLER_2D:
3813 		case glu::TYPE_INT_SAMPLER_2D:
3814 		case glu::TYPE_SAMPLER_CUBE:
3815 		case glu::TYPE_UINT_SAMPLER_CUBE:
3816 		case glu::TYPE_INT_SAMPLER_CUBE:
3817 		case glu::TYPE_SAMPLER_2D_ARRAY:
3818 		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
3819 		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
3820 		case glu::TYPE_SAMPLER_3D:
3821 		case glu::TYPE_UINT_SAMPLER_3D:
3822 		case glu::TYPE_INT_SAMPLER_3D:
3823 		case glu::TYPE_SAMPLER_CUBE_ARRAY:
3824 		case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
3825 		case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
3826 			uniforms[location].value.i = *v;
3827 			return;
3828 
3829 		default:
3830 			setError(GL_INVALID_OPERATION);
3831 			return;
3832 	}
3833 }
3834 
uniform1f(deInt32 location,const float v0)3835 void ReferenceContext::uniform1f (deInt32 location, const float v0)
3836 {
3837 	uniform1fv(location, 1, &v0);
3838 }
3839 
uniform1i(deInt32 location,deInt32 v0)3840 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
3841 {
3842 	uniform1iv(location, 1, &v0);
3843 }
3844 
uniform1fv(deInt32 location,deInt32 count,const float * v)3845 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
3846 {
3847 	uniformv(location, glu::TYPE_FLOAT, count, v);
3848 }
3849 
uniform2fv(deInt32 location,deInt32 count,const float * v)3850 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
3851 {
3852 	uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
3853 }
3854 
uniform3fv(deInt32 location,deInt32 count,const float * v)3855 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
3856 {
3857 	uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
3858 }
3859 
uniform4fv(deInt32 location,deInt32 count,const float * v)3860 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
3861 {
3862 	uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
3863 }
3864 
uniform2iv(deInt32 location,deInt32 count,const deInt32 * v)3865 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
3866 {
3867 	uniformv(location, glu::TYPE_INT_VEC2, count, v);
3868 }
3869 
uniform3iv(deInt32 location,deInt32 count,const deInt32 * v)3870 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
3871 {
3872 	uniformv(location, glu::TYPE_INT_VEC3, count, v);
3873 }
3874 
uniform4iv(deInt32 location,deInt32 count,const deInt32 * v)3875 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
3876 {
3877 	uniformv(location, glu::TYPE_INT_VEC4, count, v);
3878 }
3879 
uniformMatrix3fv(deInt32 location,deInt32 count,deBool transpose,const float * value)3880 void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3881 {
3882 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3883 
3884 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3885 
3886 	if (location == -1)
3887 		return;
3888 
3889 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3890 
3891 	if (count == 0)
3892 		return;
3893 
3894 	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3895 
3896 	switch (uniforms[location].type)
3897 	{
3898 		case glu::TYPE_FLOAT_MAT3:
3899 			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3900 
3901 			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3902 				for (int row = 0; row < 3; ++row)
3903 				for (int col = 0; col < 3; ++col)
3904 					uniforms[location].value.m3[row*3+col] = value[col*3+row];
3905 			else // input is row major
3906 				for (int row = 0; row < 3; ++row)
3907 				for (int col = 0; col < 3; ++col)
3908 					uniforms[location].value.m3[row*3+col] = value[row*3+col];
3909 
3910 			break;
3911 
3912 		default:
3913 			setError(GL_INVALID_OPERATION);
3914 			return;
3915 	}
3916 }
3917 
uniformMatrix4fv(deInt32 location,deInt32 count,deBool transpose,const float * value)3918 void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3919 {
3920 	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3921 
3922 	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3923 
3924 	if (location == -1)
3925 		return;
3926 
3927 	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3928 
3929 	if (count == 0)
3930 		return;
3931 
3932 	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3933 
3934 	switch (uniforms[location].type)
3935 	{
3936 		case glu::TYPE_FLOAT_MAT4:
3937 			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3938 
3939 			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3940 				for (int row = 0; row < 4; ++row)
3941 				for (int col = 0; col < 4; ++col)
3942 					uniforms[location].value.m4[row*3+col] = value[col*3+row];
3943 			else // input is row major
3944 				for (int row = 0; row < 4; ++row)
3945 				for (int col = 0; col < 4; ++col)
3946 					uniforms[location].value.m4[row*3+col] = value[row*3+col];
3947 
3948 			break;
3949 
3950 		default:
3951 			setError(GL_INVALID_OPERATION);
3952 			return;
3953 	}
3954 }
3955 
getUniformLocation(deUint32 program,const char * name)3956 deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
3957 {
3958 	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3959 	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3960 
3961 	std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;
3962 
3963 	for (size_t i = 0; i < uniforms.size(); ++i)
3964 		if (name && deStringEqual(uniforms[i].name.c_str(), name))
3965 			return (int)i;
3966 
3967 	return -1;
3968 }
3969 
lineWidth(float w)3970 void ReferenceContext::lineWidth (float w)
3971 {
3972 	RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
3973 	m_lineWidth = w;
3974 }
3975 
deleteVertexArray(rc::VertexArray * vertexArray)3976 void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
3977 {
3978 	if (m_vertexArrayBinding == vertexArray)
3979 		bindVertexArray(0);
3980 
3981 	if (vertexArray->m_elementArrayBufferBinding)
3982 		m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);
3983 
3984 	for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
3985 		if (vertexArray->m_arrays[ndx].bufferBinding)
3986 			m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);
3987 
3988 	DE_ASSERT(vertexArray->getRefCount() == 1);
3989 	m_vertexArrays.releaseReference(vertexArray);
3990 }
3991 
deleteProgramObject(rc::ShaderProgramObjectContainer * sp)3992 void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
3993 {
3994 	// Unbinding program will delete it
3995 	if (m_currentProgram == sp && sp->m_deleteFlag)
3996 	{
3997 		useProgram(0);
3998 		return;
3999 	}
4000 
4001 	// Unbinding program will NOT delete it
4002 	if (m_currentProgram == sp)
4003 		useProgram(0);
4004 
4005 	DE_ASSERT(sp->getRefCount() == 1);
4006 	m_programs.releaseReference(sp);
4007 }
4008 
drawArrays(deUint32 mode,int first,int count)4009 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
4010 {
4011 	drawArraysInstanced(mode, first, count, 1);
4012 }
4013 
drawArraysInstanced(deUint32 mode,int first,int count,int instanceCount)4014 void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
4015 {
4016 	// Error conditions
4017 	{
4018 		RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4019 
4020 		if (!predrawErrorChecks(mode))
4021 			return;
4022 	}
4023 
4024 	// All is ok
4025 	{
4026 		const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4027 
4028 		drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
4029 	}
4030 }
4031 
drawElements(deUint32 mode,int count,deUint32 type,const void * indices)4032 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
4033 {
4034 	drawElementsInstanced(mode, count, type, indices, 1);
4035 }
4036 
drawElementsBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int baseVertex)4037 void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
4038 {
4039 	drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
4040 }
4041 
drawElementsInstanced(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount)4042 void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
4043 {
4044 	drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
4045 }
4046 
drawElementsInstancedBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount,int baseVertex)4047 void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
4048 {
4049 	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4050 
4051 	// Error conditions
4052 	{
4053 		RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4054 					type != GL_UNSIGNED_SHORT &&
4055 					type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4056 		RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4057 
4058 		if (!predrawErrorChecks(mode))
4059 			return;
4060 	}
4061 
4062 	// All is ok
4063 	{
4064 		const rr::PrimitiveType primitiveType	= sglr::rr_util::mapGLPrimitiveType(mode);
4065 		const void*				indicesPtr		= (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + ((const deUint8*)indices - (const deUint8*)DE_NULL)) : (indices);
4066 
4067 		drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
4068 	}
4069 }
4070 
drawRangeElements(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices)4071 void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
4072 {
4073 	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4074 
4075 	drawElements(mode, count, type, indices);
4076 }
4077 
drawRangeElementsBaseVertex(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices,int baseVertex)4078 void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
4079 {
4080 	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4081 
4082 	drawElementsBaseVertex(mode, count, type, indices, baseVertex);
4083 }
4084 
drawArraysIndirect(deUint32 mode,const void * indirect)4085 void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
4086 {
4087 	struct DrawArraysIndirectCommand
4088 	{
4089 		deUint32 count;
4090 		deUint32 primCount;
4091 		deUint32 first;
4092 		deUint32 reservedMustBeZero;
4093 	};
4094 
4095 	const DrawArraysIndirectCommand* command;
4096 
4097 	// Check errors
4098 
4099 	if (!predrawErrorChecks(mode))
4100 		return;
4101 
4102 	// Check pointer validity
4103 
4104 	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4105 	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4106 
4107 	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4108 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                     > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4109 	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);
4110 
4111 	// Check values
4112 
4113 	command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4114 	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4115 
4116 	// draw
4117 	drawArraysInstanced(mode, command->first, command->count, command->primCount);
4118 }
4119 
drawElementsIndirect(deUint32 mode,deUint32 type,const void * indirect)4120 void ReferenceContext::drawElementsIndirect	(deUint32 mode, deUint32 type, const void *indirect)
4121 {
4122 	struct DrawElementsIndirectCommand
4123 	{
4124 		deUint32 count;
4125 		deUint32 primCount;
4126 		deUint32 firstIndex;
4127 		deInt32  baseVertex;
4128 		deUint32 reservedMustBeZero;
4129 	};
4130 
4131 	const DrawElementsIndirectCommand* command;
4132 
4133 	// Check errors
4134 
4135 	if (!predrawErrorChecks(mode))
4136 		return;
4137 
4138 	RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4139 				type != GL_UNSIGNED_SHORT &&
4140 				type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4141 
4142 	RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);
4143 
4144 	// Check pointer validity
4145 
4146 	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4147 	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4148 
4149 	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4150 	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                       > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4151 	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);
4152 
4153 	// Check values
4154 
4155 	command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4156 	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4157 
4158 	// Check command error conditions
4159 	RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4160 
4161 	// Draw
4162 	{
4163 		const size_t			sizeOfType		= (type == GL_UNSIGNED_BYTE) ?  (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
4164 		const void*				indicesPtr		= glu::BufferOffsetAsPointer(command->firstIndex * sizeOfType);
4165 
4166 		drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
4167 	}
4168 }
4169 
multiDrawArrays(deUint32 mode,const int * first,const int * count,int primCount)4170 void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
4171 {
4172 	DE_UNREF(mode);
4173 	DE_UNREF(first);
4174 	DE_UNREF(count);
4175 	DE_UNREF(primCount);
4176 
4177 	// not supported in gles, prevent accidental use
4178 	DE_ASSERT(false);
4179 }
4180 
multiDrawElements(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount)4181 void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
4182 {
4183 	DE_UNREF(mode);
4184 	DE_UNREF(count);
4185 	DE_UNREF(type);
4186 	DE_UNREF(indices);
4187 	DE_UNREF(primCount);
4188 
4189 	// not supported in gles, prevent accidental use
4190 	DE_ASSERT(false);
4191 }
4192 
multiDrawElementsBaseVertex(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount,const int * baseVertex)4193 void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
4194 {
4195 	DE_UNREF(mode);
4196 	DE_UNREF(count);
4197 	DE_UNREF(type);
4198 	DE_UNREF(indices);
4199 	DE_UNREF(primCount);
4200 	DE_UNREF(baseVertex);
4201 
4202 	// not supported in gles, prevent accidental use
4203 	DE_ASSERT(false);
4204 }
4205 
predrawErrorChecks(deUint32 mode)4206 bool ReferenceContext::predrawErrorChecks (deUint32 mode)
4207 {
4208 	RC_IF_ERROR(mode != GL_POINTS &&
4209 				mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
4210 				mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
4211 				mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
4212 				mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
4213 				GL_INVALID_ENUM, false);
4214 
4215 	// \todo [jarkko] Uncomment following code when the buffer mapping support is added
4216 	//for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4217 	//	if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
4218 	//		RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4219 
4220 	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);
4221 
4222 	// Geometry shader checks
4223 	if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
4224 	{
4225 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);
4226 
4227 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
4228 			(mode != GL_LINES &&
4229 			 mode != GL_LINE_STRIP &&
4230 			 mode != GL_LINE_LOOP),
4231 			 GL_INVALID_OPERATION, false);
4232 
4233 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
4234 			(mode != GL_TRIANGLES &&
4235 			 mode != GL_TRIANGLE_STRIP &&
4236 			 mode != GL_TRIANGLE_FAN),
4237 			 GL_INVALID_OPERATION, false);
4238 
4239 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
4240 			(mode != GL_LINES_ADJACENCY &&
4241 			 mode != GL_LINE_STRIP_ADJACENCY),
4242 			 GL_INVALID_OPERATION, false);
4243 
4244 		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
4245 			(mode != GL_TRIANGLES_ADJACENCY &&
4246 			 mode != GL_TRIANGLE_STRIP_ADJACENCY),
4247 			 GL_INVALID_OPERATION, false);
4248 	}
4249 
4250 	return true;
4251 }
4252 
getPrimitiveBaseType(rr::PrimitiveType derivedType)4253 static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
4254 {
4255 	switch (derivedType)
4256 	{
4257 		case rr::PRIMITIVETYPE_TRIANGLES:
4258 		case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
4259 		case rr::PRIMITIVETYPE_TRIANGLE_FAN:
4260 		case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
4261 		case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
4262 			return rr::PRIMITIVETYPE_TRIANGLES;
4263 
4264 		case rr::PRIMITIVETYPE_LINES:
4265 		case rr::PRIMITIVETYPE_LINE_STRIP:
4266 		case rr::PRIMITIVETYPE_LINE_LOOP:
4267 		case rr::PRIMITIVETYPE_LINES_ADJACENCY:
4268 		case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
4269 			return rr::PRIMITIVETYPE_LINES;
4270 
4271 		case rr::PRIMITIVETYPE_POINTS:
4272 			return rr::PRIMITIVETYPE_POINTS;
4273 
4274 		default:
4275 			DE_ASSERT(false);
4276 			return rr::PRIMITIVETYPE_LAST;
4277 	}
4278 }
4279 
getFixedRestartIndex(rr::IndexType indexType)4280 static deUint32 getFixedRestartIndex (rr::IndexType indexType)
4281 {
4282 	switch (indexType)
4283 	{
4284 		case rr::INDEXTYPE_UINT8:		return 0xFF;
4285 		case rr::INDEXTYPE_UINT16:		return 0xFFFF;
4286 		case rr::INDEXTYPE_UINT32:		return 0xFFFFFFFFul;
4287 
4288 		case rr::INDEXTYPE_LAST:
4289 		default:
4290 			DE_ASSERT(false);
4291 			return 0;
4292 	}
4293 }
4294 
drawWithReference(const rr::PrimitiveList & primitives,int instanceCount)4295 void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
4296 {
4297 	// undefined results
4298 	if (m_currentProgram == DE_NULL)
4299 		return;
4300 
4301 	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
4302 	rr::MultisamplePixelBufferAccess	depthBuf	= getDepthMultisampleAccess(getDrawDepthbuffer());
4303 	rr::MultisamplePixelBufferAccess	stencilBuf	= getStencilMultisampleAccess(getDrawStencilbuffer());
4304 	const bool							hasStencil	= !isEmpty(stencilBuf);
4305 	const int							stencilBits	= (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);
4306 
4307 	const rr::RenderTarget				renderTarget(colorBuf0, depthBuf, stencilBuf);
4308 	const rr::Program					program		(m_currentProgram->m_program->getVertexShader(),
4309 													 m_currentProgram->m_program->getFragmentShader(),
4310 													 (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
4311 	rr::RenderState						state		((rr::ViewportState)(colorBuf0), m_limits.subpixelBits);
4312 
4313 	const rr::Renderer					referenceRenderer;
4314 	std::vector<rr::VertexAttrib>		vertexAttribs;
4315 
4316 	// Gen state
4317 	{
4318 		const rr::PrimitiveType	baseType							= getPrimitiveBaseType(primitives.getPrimitiveType());
4319 		const bool				polygonOffsetEnabled				= (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);
4320 
4321 		//state.cullMode											= m_cullMode
4322 
4323 		state.fragOps.scissorTestEnabled							= m_scissorEnabled;
4324 		state.fragOps.scissorRectangle								= rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());
4325 
4326 		state.fragOps.numStencilBits								= stencilBits;
4327 		state.fragOps.stencilTestEnabled							= m_stencilTestEnabled;
4328 
4329 		for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
4330 		{
4331 			state.fragOps.stencilStates[faceType].compMask	= m_stencil[faceType].opMask;
4332 			state.fragOps.stencilStates[faceType].writeMask	= m_stencil[faceType].writeMask;
4333 			state.fragOps.stencilStates[faceType].ref		= m_stencil[faceType].ref;
4334 			state.fragOps.stencilStates[faceType].func		= sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
4335 			state.fragOps.stencilStates[faceType].sFail		= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
4336 			state.fragOps.stencilStates[faceType].dpFail	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
4337 			state.fragOps.stencilStates[faceType].dpPass	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
4338 		}
4339 
4340 		state.fragOps.depthTestEnabled								= m_depthTestEnabled;
4341 		state.fragOps.depthFunc										= sglr::rr_util::mapGLTestFunc(m_depthFunc);
4342 		state.fragOps.depthMask										= m_depthMask;
4343 
4344 		state.fragOps.blendMode										= m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
4345 		state.fragOps.blendRGBState.equation						= sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
4346 		state.fragOps.blendRGBState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
4347 		state.fragOps.blendRGBState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
4348 		state.fragOps.blendAState.equation							= sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
4349 		state.fragOps.blendAState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
4350 		state.fragOps.blendAState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
4351 		state.fragOps.blendColor									= m_blendColor;
4352 
4353 		state.fragOps.sRGBEnabled									= m_sRGBUpdateEnabled;
4354 
4355 		state.fragOps.colorMask										= m_colorMask;
4356 
4357 		state.fragOps.depthClampEnabled								= m_depthClampEnabled;
4358 
4359 		state.viewport.rect											= rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
4360 		state.viewport.zn											= m_depthRangeNear;
4361 		state.viewport.zf											= m_depthRangeFar;
4362 
4363 		//state.point.pointSize										= m_pointSize;
4364 		state.line.lineWidth										= m_lineWidth;
4365 
4366 		state.fragOps.polygonOffsetEnabled							= polygonOffsetEnabled;
4367 		state.fragOps.polygonOffsetFactor							= m_polygonOffsetFactor;
4368 		state.fragOps.polygonOffsetUnits							= m_polygonOffsetUnits;
4369 
4370 		{
4371 			const rr::IndexType indexType = primitives.getIndexType();
4372 
4373 			if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
4374 			{
4375 				state.restart.enabled = true;
4376 				state.restart.restartIndex = getFixedRestartIndex(indexType);
4377 			}
4378 			else if (m_primitiveRestartSettableIndex)
4379 			{
4380 				// \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
4381 				state.restart.enabled = true;
4382 				state.restart.restartIndex = m_primitiveRestartIndex;
4383 			}
4384 			else
4385 			{
4386 				state.restart.enabled = false;
4387 			}
4388 		}
4389 
4390 		state.provokingVertexConvention								= (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
4391 	}
4392 
4393 	// gen attributes
4394 	{
4395 		rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4396 
4397 		vertexAttribs.resize(vao.m_arrays.size());
4398 		for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4399 		{
4400 			if (!vao.m_arrays[ndx].enabled)
4401 			{
4402 				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
4403 				vertexAttribs[ndx].generic = m_currentAttribs[ndx];
4404 			}
4405 			else if (vao.m_arrays[ndx].bufferDeleted)
4406 			{
4407 				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
4408 				vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
4409 			}
4410 			else
4411 			{
4412 				vertexAttribs[ndx].type				= (vao.m_arrays[ndx].integer) ?
4413 														(sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
4414 														(sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
4415 				vertexAttribs[ndx].size				= sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
4416 				vertexAttribs[ndx].stride			= vao.m_arrays[ndx].stride;
4417 				vertexAttribs[ndx].instanceDivisor	= vao.m_arrays[ndx].divisor;
4418 				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);
4419 			}
4420 		}
4421 	}
4422 
4423 	// Set shader samplers
4424 	for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
4425 	{
4426 		const tcu::Sampler::DepthStencilMode	depthStencilMode	= tcu::Sampler::MODE_DEPTH; // \todo[jarkko] support sampler state
4427 		const int								texNdx				= m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;
4428 
4429 		switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
4430 		{
4431 			case glu::TYPE_SAMPLER_1D:
4432 			case glu::TYPE_UINT_SAMPLER_1D:
4433 			case glu::TYPE_INT_SAMPLER_1D:
4434 			{
4435 				rc::Texture1D* tex = DE_NULL;
4436 
4437 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4438 					tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);
4439 
4440 				if (tex && tex->isComplete())
4441 				{
4442 					tex->updateView(depthStencilMode);
4443 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
4444 				}
4445 				else
4446 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;
4447 
4448 				break;
4449 			}
4450 			case glu::TYPE_SAMPLER_2D:
4451 			case glu::TYPE_UINT_SAMPLER_2D:
4452 			case glu::TYPE_INT_SAMPLER_2D:
4453 			{
4454 				rc::Texture2D* tex = DE_NULL;
4455 
4456 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4457 					tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);
4458 
4459 				if (tex && tex->isComplete())
4460 				{
4461 					tex->updateView(depthStencilMode);
4462 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
4463 				}
4464 				else
4465 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;
4466 
4467 				break;
4468 			}
4469 			case glu::TYPE_SAMPLER_CUBE:
4470 			case glu::TYPE_UINT_SAMPLER_CUBE:
4471 			case glu::TYPE_INT_SAMPLER_CUBE:
4472 			{
4473 				rc::TextureCube* tex = DE_NULL;
4474 
4475 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4476 					tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);
4477 
4478 				if (tex && tex->isComplete())
4479 				{
4480 					tex->updateView(depthStencilMode);
4481 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
4482 				}
4483 				else
4484 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;
4485 
4486 				break;
4487 			}
4488 			case glu::TYPE_SAMPLER_2D_ARRAY:
4489 			case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
4490 			case glu::TYPE_INT_SAMPLER_2D_ARRAY:
4491 			{
4492 				rc::Texture2DArray* tex = DE_NULL;
4493 
4494 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4495 					tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);
4496 
4497 				if (tex && tex->isComplete())
4498 				{
4499 					tex->updateView(depthStencilMode);
4500 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
4501 				}
4502 				else
4503 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;
4504 
4505 				break;
4506 			}
4507 			case glu::TYPE_SAMPLER_3D:
4508 			case glu::TYPE_UINT_SAMPLER_3D:
4509 			case glu::TYPE_INT_SAMPLER_3D:
4510 			{
4511 				rc::Texture3D* tex = DE_NULL;
4512 
4513 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4514 					tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);
4515 
4516 				if (tex && tex->isComplete())
4517 				{
4518 					tex->updateView(depthStencilMode);
4519 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
4520 				}
4521 				else
4522 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;
4523 
4524 				break;
4525 			}
4526 			case glu::TYPE_SAMPLER_CUBE_ARRAY:
4527 			case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
4528 			case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
4529 			{
4530 				rc::TextureCubeArray* tex = DE_NULL;
4531 
4532 				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4533 					tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);
4534 
4535 				if (tex && tex->isComplete())
4536 				{
4537 					tex->updateView(depthStencilMode);
4538 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
4539 				}
4540 				else
4541 					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;
4542 
4543 				break;
4544 			}
4545 			default:
4546 				// nothing
4547 				break;
4548 		}
4549 	}
4550 
4551 	referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
4552 }
4553 
createProgram(ShaderProgram * program)4554 deUint32 ReferenceContext::createProgram (ShaderProgram* program)
4555 {
4556 	int name = m_programs.allocateName();
4557 
4558 	m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));
4559 
4560 	return name;
4561 }
4562 
useProgram(deUint32 program)4563 void ReferenceContext::useProgram (deUint32 program)
4564 {
4565 	rc::ShaderProgramObjectContainer* shaderProg			= DE_NULL;
4566 	rc::ShaderProgramObjectContainer* programToBeDeleted	= DE_NULL;
4567 
4568 	if (program)
4569 	{
4570 		shaderProg = m_programs.find(program);
4571 
4572 		// shader has not been linked
4573 		if (!shaderProg || shaderProg->m_deleteFlag)
4574 			RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4575 	}
4576 
4577 	if (m_currentProgram && m_currentProgram->m_deleteFlag)
4578 		programToBeDeleted = m_currentProgram;
4579 
4580 	m_currentProgram = shaderProg;
4581 
4582 	if (programToBeDeleted)
4583 	{
4584 		DE_ASSERT(programToBeDeleted->getRefCount() == 1);
4585 		deleteProgramObject(programToBeDeleted);
4586 	}
4587 }
4588 
deleteProgram(deUint32 program)4589 void ReferenceContext::deleteProgram (deUint32 program)
4590 {
4591 	if (!program)
4592 		return;
4593 
4594 	rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
4595 	if (shaderProg)
4596 	{
4597 		if (shaderProg == m_currentProgram)
4598 		{
4599 			m_currentProgram->m_deleteFlag = true;
4600 		}
4601 		else
4602 		{
4603 			DE_ASSERT(shaderProg->getRefCount() == 1);
4604 			m_programs.releaseReference(shaderProg);
4605 		}
4606 	}
4607 }
4608 
readPixels(int x,int y,int width,int height,deUint32 format,deUint32 type,void * data)4609 void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
4610 {
4611 	rr::MultisamplePixelBufferAccess	src = getReadColorbuffer();
4612 	TextureFormat						transferFmt;
4613 
4614 	// Map transfer format.
4615 	transferFmt = glu::mapGLTransferFormat(format, type);
4616 	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
4617 				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
4618 
4619 	// Clamp input values
4620 	const int copyX			= deClamp32(x,		0, src.raw().getHeight());
4621 	const int copyY			= deClamp32(y,		0, src.raw().getDepth());
4622 	const int copyWidth		= deClamp32(width,	0, src.raw().getHeight()-x);
4623 	const int copyHeight	= deClamp32(height,	0, src.raw().getDepth()-y);
4624 
4625 	PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
4626 	rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
4627 }
4628 
getError(void)4629 deUint32 ReferenceContext::getError (void)
4630 {
4631 	deUint32 err = m_lastError;
4632 	m_lastError = GL_NO_ERROR;
4633 	return err;
4634 }
4635 
finish(void)4636 void ReferenceContext::finish (void)
4637 {
4638 }
4639 
setError(deUint32 error)4640 inline void ReferenceContext::setError (deUint32 error)
4641 {
4642 	if (m_lastError == GL_NO_ERROR)
4643 		m_lastError = error;
4644 }
4645 
getIntegerv(deUint32 pname,int * param)4646 void ReferenceContext::getIntegerv (deUint32 pname, int* param)
4647 {
4648 	switch (pname)
4649 	{
4650 		case GL_MAX_TEXTURE_SIZE:			*param = m_limits.maxTexture2DSize;			break;
4651 		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:	*param = m_limits.maxTextureCubeSize;		break;
4652 		case GL_MAX_ARRAY_TEXTURE_LAYERS:	*param = m_limits.maxTexture2DArrayLayers;	break;
4653 		case GL_MAX_3D_TEXTURE_SIZE:		*param = m_limits.maxTexture3DSize;			break;
4654 		case GL_MAX_RENDERBUFFER_SIZE:		*param = m_limits.maxRenderbufferSize;		break;
4655 		case GL_MAX_TEXTURE_IMAGE_UNITS:	*param = m_limits.maxTextureImageUnits;		break;
4656 		case GL_MAX_VERTEX_ATTRIBS:			*param = m_limits.maxVertexAttribs;			break;
4657 
4658 		default:
4659 			setError(GL_INVALID_ENUM);
4660 			break;
4661 	}
4662 }
4663 
getString(deUint32 pname)4664 const char* ReferenceContext::getString (deUint32 pname)
4665 {
4666 	switch (pname)
4667 	{
4668 		case GL_EXTENSIONS:		return m_limits.extensionStr.c_str();
4669 
4670 		default:
4671 			setError(GL_INVALID_ENUM);
4672 			return DE_NULL;
4673 	}
4674 }
4675 
4676 namespace rc
4677 {
4678 
TextureLevelArray(void)4679 TextureLevelArray::TextureLevelArray (void)
4680 {
4681 }
4682 
~TextureLevelArray(void)4683 TextureLevelArray::~TextureLevelArray (void)
4684 {
4685 	clear();
4686 }
4687 
clear(void)4688 void TextureLevelArray::clear (void)
4689 {
4690 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));
4691 
4692 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
4693 	{
4694 		m_data[ndx].clear();
4695 		m_access[ndx] = PixelBufferAccess();
4696 	}
4697 }
4698 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)4699 void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
4700 {
4701 	const int dataSize = format.getPixelSize()*width*height*depth;
4702 
4703 	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4704 
4705 	if (hasLevel(level))
4706 		clearLevel(level);
4707 
4708 	m_data[level].setStorage(dataSize);
4709 	m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level].getPtr());
4710 }
4711 
clearLevel(int level)4712 void TextureLevelArray::clearLevel (int level)
4713 {
4714 	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4715 
4716 	m_data[level].clear();
4717 	m_access[level] = PixelBufferAccess();
4718 }
4719 
updateSamplerMode(tcu::Sampler::DepthStencilMode mode)4720 void TextureLevelArray::updateSamplerMode (tcu::Sampler::DepthStencilMode mode)
4721 {
4722 	for (int levelNdx = 0; hasLevel(levelNdx); ++levelNdx)
4723 		m_effectiveAccess[levelNdx] = tcu::getEffectiveDepthStencilAccess(m_access[levelNdx], mode);
4724 }
4725 
Texture(deUint32 name,Type type,deBool seamless)4726 Texture::Texture (deUint32 name, Type type, deBool seamless)
4727 	: NamedObject	(name)
4728 	, m_type		(type)
4729 	, m_immutable	(false)
4730 	, m_sampler		(tcu::Sampler::REPEAT_GL,
4731 					 tcu::Sampler::REPEAT_GL,
4732 					 tcu::Sampler::REPEAT_GL,
4733 					 tcu::Sampler::NEAREST_MIPMAP_LINEAR,
4734 					 tcu::Sampler::LINEAR,
4735 					 0.0f,				// LOD threshold
4736 					 true,				// normalized coords
4737 					 tcu::Sampler::COMPAREMODE_NONE,
4738 					 0,					// cmp channel ndx
4739 					 tcu::Vec4(0.0f),	// border color
4740 					 seamless			// seamless cube map, Default value is True.
4741 					 )
4742 	, m_baseLevel	(0)
4743 	, m_maxLevel	(1000)
4744 {
4745 }
4746 
Texture1D(deUint32 name)4747 Texture1D::Texture1D (deUint32 name)
4748 	: Texture	(name, TYPE_1D)
4749 	, m_view	(0, DE_NULL)
4750 {
4751 }
4752 
~Texture1D(void)4753 Texture1D::~Texture1D (void)
4754 {
4755 }
4756 
allocLevel(int level,const tcu::TextureFormat & format,int width)4757 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
4758 {
4759 	m_levels.allocLevel(level, format, width, 1, 1);
4760 }
4761 
isComplete(void) const4762 bool Texture1D::isComplete (void) const
4763 {
4764 	const int	baseLevel	= getBaseLevel();
4765 
4766 	if (hasLevel(baseLevel))
4767 	{
4768 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
4769 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
4770 
4771 		if (mipmap)
4772 		{
4773 			const TextureFormat&	format		= level0.getFormat();
4774 			const int				w			= level0.getWidth();
4775 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));
4776 
4777 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4778 			{
4779 				if (hasLevel(baseLevel+levelNdx))
4780 				{
4781 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
4782 					const int							expectedW	= getMipLevelSize(w, levelNdx);
4783 
4784 					if (level.getWidth()	!= expectedW	||
4785 						level.getFormat()	!= format)
4786 						return false;
4787 				}
4788 				else
4789 					return false;
4790 			}
4791 		}
4792 
4793 		return true;
4794 	}
4795 	else
4796 		return false;
4797 }
4798 
sample(float s,float lod) const4799 tcu::Vec4 Texture1D::sample (float s, float lod) const
4800 {
4801 	return m_view.sample(getSampler(), s, 0.0f, lod);
4802 }
4803 
sample4(tcu::Vec4 output[4],const float packetTexcoords[4],float lodBias) const4804 void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
4805 {
4806 	const float texWidth = (float)m_view.getWidth();
4807 
4808 	const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4809 	const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4810 	const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4811 	const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4812 
4813 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4814 	{
4815 		const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
4816 		const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;
4817 
4818 		const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
4819 		const float p = mu * texWidth;
4820 
4821 		const float	lod = deFloatLog2(p) + lodBias;
4822 
4823 		output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
4824 	}
4825 }
4826 
updateView(tcu::Sampler::DepthStencilMode mode)4827 void Texture1D::updateView (tcu::Sampler::DepthStencilMode mode)
4828 {
4829 	const int baseLevel	= getBaseLevel();
4830 
4831 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4832 	{
4833 		const int	width		= getLevel(baseLevel).getWidth();
4834 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
4835 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;
4836 
4837 		m_levels.updateSamplerMode(mode);
4838 		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4839 	}
4840 	else
4841 		m_view = tcu::Texture2DView(0, DE_NULL);
4842 }
4843 
Texture2D(deUint32 name,bool es2)4844 Texture2D::Texture2D (deUint32 name, bool es2)
4845 	: Texture	(name, TYPE_2D)
4846 	, m_view	(0, DE_NULL, es2)
4847 {
4848 }
4849 
~Texture2D(void)4850 Texture2D::~Texture2D (void)
4851 {
4852 }
4853 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height)4854 void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
4855 {
4856 	m_levels.allocLevel(level, format, width, height, 1);
4857 }
4858 
isComplete(void) const4859 bool Texture2D::isComplete (void) const
4860 {
4861 	const int	baseLevel	= getBaseLevel();
4862 
4863 	if (hasLevel(baseLevel))
4864 	{
4865 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
4866 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
4867 
4868 		if (mipmap)
4869 		{
4870 			const TextureFormat&	format		= level0.getFormat();
4871 			const int				w			= level0.getWidth();
4872 			const int				h			= level0.getHeight();
4873 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
4874 
4875 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4876 			{
4877 				if (hasLevel(baseLevel+levelNdx))
4878 				{
4879 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
4880 					const int							expectedW	= getMipLevelSize(w, levelNdx);
4881 					const int							expectedH	= getMipLevelSize(h, levelNdx);
4882 
4883 					if (level.getWidth()	!= expectedW	||
4884 						level.getHeight()	!= expectedH	||
4885 						level.getFormat()	!= format)
4886 						return false;
4887 				}
4888 				else
4889 					return false;
4890 			}
4891 		}
4892 
4893 		return true;
4894 	}
4895 	else
4896 		return false;
4897 }
4898 
updateView(tcu::Sampler::DepthStencilMode mode)4899 void Texture2D::updateView (tcu::Sampler::DepthStencilMode mode)
4900 {
4901 	const int baseLevel	= getBaseLevel();
4902 
4903 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4904 	{
4905 		// Update number of levels in mipmap pyramid.
4906 		const int	width		= getLevel(baseLevel).getWidth();
4907 		const int	height		= getLevel(baseLevel).getHeight();
4908 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
4909 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4910 
4911 		m_levels.updateSamplerMode(mode);
4912 		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4913 	}
4914 	else
4915 		m_view = tcu::Texture2DView(0, DE_NULL);
4916 }
4917 
sample(float s,float t,float lod) const4918 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
4919 {
4920 	return m_view.sample(getSampler(), s, t, lod);
4921 }
4922 
sample4(tcu::Vec4 output[4],const tcu::Vec2 packetTexcoords[4],float lodBias) const4923 void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
4924 {
4925 	const float texWidth  = (float)m_view.getWidth();
4926 	const float texHeight = (float)m_view.getHeight();
4927 
4928 	const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4929 	const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4930 	const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4931 	const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4932 
4933 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4934 	{
4935 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
4936 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
4937 
4938 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
4939 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
4940 		const float p = de::max(mu * texWidth, mv * texHeight);
4941 
4942 		const float	lod = deFloatLog2(p) + lodBias;
4943 
4944 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
4945 	}
4946 }
4947 
TextureCube(deUint32 name,deBool seamless)4948 TextureCube::TextureCube (deUint32 name, deBool seamless)
4949 	: Texture(name, TYPE_CUBE_MAP, seamless)
4950 {
4951 }
4952 
~TextureCube(void)4953 TextureCube::~TextureCube (void)
4954 {
4955 }
4956 
clearLevels(void)4957 void TextureCube::clearLevels (void)
4958 {
4959 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4960 		m_levels[face].clear();
4961 }
4962 
allocFace(int level,tcu::CubeFace face,const tcu::TextureFormat & format,int width,int height)4963 void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
4964 {
4965 	m_levels[face].allocLevel(level, format, width, height, 1);
4966 }
4967 
isComplete(void) const4968 bool TextureCube::isComplete (void) const
4969 {
4970 	const int	baseLevel	= getBaseLevel();
4971 
4972 	if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
4973 	{
4974 		const int					width		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
4975 		const int					height		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
4976 		const tcu::TextureFormat&	format		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
4977 		const bool					mipmap		= isMipmapFilter(getSampler().minFilter);
4978 		const int					numLevels	= mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4979 
4980 		if (width != height)
4981 			return false; // Non-square is not supported.
4982 
4983 		// \note Level 0 is always checked for consistency
4984 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
4985 		{
4986 			const int levelW	= getMipLevelSize(width,	levelNdx);
4987 			const int levelH	= getMipLevelSize(height,	levelNdx);
4988 
4989 			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4990 			{
4991 				if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
4992 				{
4993 					const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);
4994 
4995 					if (level.getWidth()	!= levelW	||
4996 						level.getHeight()	!= levelH	||
4997 						level.getFormat()	!= format)
4998 						return false;
4999 				}
5000 				else
5001 					return false;
5002 			}
5003 		}
5004 
5005 		return true;
5006 	}
5007 	else
5008 		return false;
5009 }
5010 
updateView(tcu::Sampler::DepthStencilMode mode)5011 void TextureCube::updateView (tcu::Sampler::DepthStencilMode mode)
5012 {
5013 	const int							baseLevel	= getBaseLevel();
5014 	const tcu::ConstPixelBufferAccess*	faces[tcu::CUBEFACE_LAST];
5015 
5016 	deMemset(&faces[0], 0, sizeof(faces));
5017 
5018 	if (isComplete())
5019 	{
5020 		const int	size		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
5021 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5022 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;
5023 
5024 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5025 		{
5026 			m_levels[face].updateSamplerMode(mode);
5027 			faces[face] = m_levels[face].getEffectiveLevels() + baseLevel;
5028 		}
5029 
5030 		m_view = tcu::TextureCubeView(numLevels, faces);
5031 	}
5032 	else
5033 		m_view = tcu::TextureCubeView(0, faces);
5034 }
5035 
sample(float s,float t,float p,float lod) const5036 tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
5037 {
5038 	return m_view.sample(getSampler(), s, t, p, lod);
5039 }
5040 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5041 void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5042 {
5043 	const float cubeSide = (float)m_view.getSize();
5044 
5045 	// Each tex coord might be in a different face.
5046 
5047 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5048 	{
5049 		const tcu::CubeFace face		= tcu::selectCubeFace(packetTexcoords[fragNdx]);
5050 		const tcu::Vec2		coords[4]	=
5051 		{
5052 			tcu::projectToFace(face, packetTexcoords[0]),
5053 			tcu::projectToFace(face, packetTexcoords[1]),
5054 			tcu::projectToFace(face, packetTexcoords[2]),
5055 			tcu::projectToFace(face, packetTexcoords[3]),
5056 		};
5057 
5058 		const tcu::Vec2 dFdx0 = coords[1] - coords[0];
5059 		const tcu::Vec2 dFdx1 = coords[3] - coords[2];
5060 		const tcu::Vec2 dFdy0 = coords[2] - coords[0];
5061 		const tcu::Vec2 dFdy1 = coords[3] - coords[1];
5062 
5063 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5064 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5065 
5066 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5067 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5068 		const float p = de::max(mu * cubeSide, mv * cubeSide);
5069 
5070 		const float	lod = deFloatLog2(p) + lodBias;
5071 
5072 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5073 	}
5074 }
5075 
Texture2DArray(deUint32 name)5076 Texture2DArray::Texture2DArray (deUint32 name)
5077 	: Texture	(name, TYPE_2D_ARRAY)
5078 	, m_view	(0, DE_NULL)
5079 {
5080 }
5081 
~Texture2DArray(void)5082 Texture2DArray::~Texture2DArray (void)
5083 {
5084 }
5085 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5086 void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5087 {
5088 	m_levels.allocLevel(level, format, width, height, numLayers);
5089 }
5090 
isComplete(void) const5091 bool Texture2DArray::isComplete (void) const
5092 {
5093 	const int	baseLevel	= getBaseLevel();
5094 
5095 	if (hasLevel(baseLevel))
5096 	{
5097 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5098 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5099 
5100 		if (mipmap)
5101 		{
5102 			const TextureFormat&	format		= level0.getFormat();
5103 			const int				w			= level0.getWidth();
5104 			const int				h			= level0.getHeight();
5105 			const int				numLayers	= level0.getDepth();
5106 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5107 
5108 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5109 			{
5110 				if (hasLevel(baseLevel+levelNdx))
5111 				{
5112 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5113 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5114 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5115 
5116 					if (level.getWidth()	!= expectedW	||
5117 						level.getHeight()	!= expectedH	||
5118 						level.getDepth()	!= numLayers	||
5119 						level.getFormat()	!= format)
5120 						return false;
5121 				}
5122 				else
5123 					return false;
5124 			}
5125 		}
5126 
5127 		return true;
5128 	}
5129 	else
5130 		return false;
5131 }
5132 
updateView(tcu::Sampler::DepthStencilMode mode)5133 void Texture2DArray::updateView (tcu::Sampler::DepthStencilMode mode)
5134 {
5135 	const int baseLevel	= getBaseLevel();
5136 
5137 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5138 	{
5139 		const int	width		= getLevel(baseLevel).getWidth();
5140 		const int	height		= getLevel(baseLevel).getHeight();
5141 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5142 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5143 
5144 		m_levels.updateSamplerMode(mode);
5145 		m_view = tcu::Texture2DArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5146 	}
5147 	else
5148 		m_view = tcu::Texture2DArrayView(0, DE_NULL);
5149 }
5150 
sample(float s,float t,float r,float lod) const5151 tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
5152 {
5153 	return m_view.sample(getSampler(), s, t, r, lod);
5154 }
5155 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5156 void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5157 {
5158 	const float texWidth  = (float)m_view.getWidth();
5159 	const float texHeight = (float)m_view.getHeight();
5160 
5161 	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5162 	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5163 	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5164 	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5165 
5166 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5167 	{
5168 		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5169 		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5170 
5171 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5172 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5173 		const float p = de::max(mu * texWidth, mv * texHeight);
5174 
5175 		const float	lod = deFloatLog2(p) + lodBias;
5176 
5177 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5178 	}
5179 }
5180 
TextureCubeArray(deUint32 name)5181 TextureCubeArray::TextureCubeArray (deUint32 name)
5182 	: Texture	(name, TYPE_CUBE_MAP_ARRAY)
5183 	, m_view	(0, DE_NULL)
5184 {
5185 }
5186 
~TextureCubeArray(void)5187 TextureCubeArray::~TextureCubeArray (void)
5188 {
5189 }
5190 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5191 void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5192 {
5193 	DE_ASSERT(numLayers % 6 == 0);
5194 	m_levels.allocLevel(level, format, width, height, numLayers);
5195 }
5196 
isComplete(void) const5197 bool TextureCubeArray::isComplete (void) const
5198 {
5199 	const int	baseLevel	= getBaseLevel();
5200 
5201 	if (hasLevel(baseLevel))
5202 	{
5203 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5204 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5205 
5206 		if (mipmap)
5207 		{
5208 			const TextureFormat&	format		= level0.getFormat();
5209 			const int				w			= level0.getWidth();
5210 			const int				h			= level0.getHeight();
5211 			const int				numLayers	= level0.getDepth();
5212 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5213 
5214 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5215 			{
5216 				if (hasLevel(baseLevel+levelNdx))
5217 				{
5218 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5219 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5220 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5221 
5222 					if (level.getWidth()	!= expectedW	||
5223 						level.getHeight()	!= expectedH	||
5224 						level.getDepth()	!= numLayers	||
5225 						level.getFormat()	!= format)
5226 						return false;
5227 				}
5228 				else
5229 					return false;
5230 			}
5231 		}
5232 
5233 		return true;
5234 	}
5235 	else
5236 		return false;
5237 }
5238 
updateView(tcu::Sampler::DepthStencilMode mode)5239 void TextureCubeArray::updateView (tcu::Sampler::DepthStencilMode mode)
5240 {
5241 	const int baseLevel	= getBaseLevel();
5242 
5243 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5244 	{
5245 		const int	width		= getLevel(baseLevel).getWidth();
5246 		const int	height		= getLevel(baseLevel).getHeight();
5247 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5248 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5249 
5250 		m_levels.updateSamplerMode(mode);
5251 		m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5252 	}
5253 	else
5254 		m_view = tcu::TextureCubeArrayView(0, DE_NULL);
5255 }
5256 
sample(float s,float t,float r,float q,float lod) const5257 tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
5258 {
5259 	return m_view.sample(getSampler(), s, t, r, q, lod);
5260 }
5261 
sample4(tcu::Vec4 output[4],const tcu::Vec4 packetTexcoords[4],float lodBias) const5262 void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
5263 {
5264 	const float		cubeSide		= (float)m_view.getSize();
5265 	const tcu::Vec3	cubeCoords[4]	=
5266 	{
5267 		packetTexcoords[0].toWidth<3>(),
5268 		packetTexcoords[1].toWidth<3>(),
5269 		packetTexcoords[2].toWidth<3>(),
5270 		packetTexcoords[3].toWidth<3>()
5271 	};
5272 
5273 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5274 	{
5275 		const tcu::CubeFace face			= tcu::selectCubeFace(cubeCoords[fragNdx]);
5276 		const tcu::Vec2		faceCoords[4]	=
5277 		{
5278 			tcu::projectToFace(face, cubeCoords[0]),
5279 			tcu::projectToFace(face, cubeCoords[1]),
5280 			tcu::projectToFace(face, cubeCoords[2]),
5281 			tcu::projectToFace(face, cubeCoords[3]),
5282 		};
5283 
5284 		const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
5285 		const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
5286 		const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
5287 		const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];
5288 
5289 		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5290 		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5291 
5292 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5293 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5294 		const float p = de::max(mu * cubeSide, mv * cubeSide);
5295 
5296 		const float	lod = deFloatLog2(p) + lodBias;
5297 
5298 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
5299 	}
5300 }
5301 
Texture3D(deUint32 name)5302 Texture3D::Texture3D (deUint32 name)
5303 	: Texture	(name, TYPE_3D)
5304 	, m_view	(0, DE_NULL)
5305 {
5306 }
5307 
~Texture3D(void)5308 Texture3D::~Texture3D (void)
5309 {
5310 }
5311 
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)5312 void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
5313 {
5314 	m_levels.allocLevel(level, format, width, height, depth);
5315 }
5316 
isComplete(void) const5317 bool Texture3D::isComplete (void) const
5318 {
5319 	const int	baseLevel	= getBaseLevel();
5320 
5321 	if (hasLevel(baseLevel))
5322 	{
5323 		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
5324 		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);
5325 
5326 		if (mipmap)
5327 		{
5328 			const TextureFormat&	format		= level0.getFormat();
5329 			const int				w			= level0.getWidth();
5330 			const int				h			= level0.getHeight();
5331 			const int				d			= level0.getDepth();
5332 			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));
5333 
5334 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5335 			{
5336 				if (hasLevel(baseLevel+levelNdx))
5337 				{
5338 					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
5339 					const int							expectedW	= getMipLevelSize(w, levelNdx);
5340 					const int							expectedH	= getMipLevelSize(h, levelNdx);
5341 					const int							expectedD	= getMipLevelSize(d, levelNdx);
5342 
5343 					if (level.getWidth()	!= expectedW	||
5344 						level.getHeight()	!= expectedH	||
5345 						level.getDepth()	!= expectedD	||
5346 						level.getFormat()	!= format)
5347 						return false;
5348 				}
5349 				else
5350 					return false;
5351 			}
5352 		}
5353 
5354 		return true;
5355 	}
5356 	else
5357 		return false;
5358 }
5359 
sample(float s,float t,float r,float lod) const5360 tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
5361 {
5362 	return m_view.sample(getSampler(), s, t, r, lod);
5363 }
5364 
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5365 void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5366 {
5367 	const float texWidth  = (float)m_view.getWidth();
5368 	const float texHeight = (float)m_view.getHeight();
5369 	const float texDepth  = (float)m_view.getDepth();
5370 
5371 	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5372 	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5373 	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5374 	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5375 
5376 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5377 	{
5378 		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5379 		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5380 
5381 		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5382 		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5383 		const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
5384 		const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);
5385 
5386 		const float	lod = deFloatLog2(p) + lodBias;
5387 
5388 		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5389 	}
5390 }
5391 
updateView(tcu::Sampler::DepthStencilMode mode)5392 void Texture3D::updateView (tcu::Sampler::DepthStencilMode mode)
5393 {
5394 	const int baseLevel	= getBaseLevel();
5395 
5396 	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5397 	{
5398 		const int	width		= getLevel(baseLevel).getWidth();
5399 		const int	height		= getLevel(baseLevel).getHeight();
5400 		const int	depth		= getLevel(baseLevel).getDepth();
5401 		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
5402 		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;
5403 
5404 		m_levels.updateSamplerMode(mode);
5405 		m_view = tcu::Texture3DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5406 	}
5407 	else
5408 		m_view = tcu::Texture3DView(0, DE_NULL);
5409 }
5410 
Renderbuffer(deUint32 name)5411 Renderbuffer::Renderbuffer (deUint32 name)
5412 	: NamedObject		(name)
5413 {
5414 }
5415 
~Renderbuffer(void)5416 Renderbuffer::~Renderbuffer (void)
5417 {
5418 }
5419 
setStorage(const TextureFormat & format,int width,int height)5420 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
5421 {
5422 	m_data.setStorage(format, width, height);
5423 }
5424 
Framebuffer(deUint32 name)5425 Framebuffer::Framebuffer (deUint32 name)
5426 	: NamedObject(name)
5427 {
5428 }
5429 
~Framebuffer(void)5430 Framebuffer::~Framebuffer (void)
5431 {
5432 }
5433 
VertexArray(deUint32 name,int maxVertexAttribs)5434 VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
5435 	: NamedObject					(name)
5436 	, m_elementArrayBufferBinding	(DE_NULL)
5437 	, m_arrays						(maxVertexAttribs)
5438 {
5439 	for (int i = 0; i < maxVertexAttribs; ++i)
5440 	{
5441 		m_arrays[i].enabled			= false;
5442 		m_arrays[i].size			= 4;
5443 		m_arrays[i].stride			= 0;
5444 		m_arrays[i].type			= GL_FLOAT;
5445 		m_arrays[i].normalized		= false;
5446 		m_arrays[i].integer			= false;
5447 		m_arrays[i].divisor			= 0;
5448 		m_arrays[i].bufferDeleted	= false;
5449 		m_arrays[i].bufferBinding	= DE_NULL;
5450 		m_arrays[i].pointer			= DE_NULL;
5451 	}
5452 }
5453 
ShaderProgramObjectContainer(deUint32 name,ShaderProgram * program)5454 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
5455 	: NamedObject	(name)
5456 	, m_program		(program)
5457 	, m_deleteFlag	(false)
5458 {
5459 }
5460 
~ShaderProgramObjectContainer(void)5461 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
5462 {
5463 }
5464 
5465 } // rc
5466 } // sglr
5467