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