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