Home | History | Annotate | Download | only in simplereference
      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 
     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 
     79 static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
     80 {
     81 	return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
     82 }
     83 
     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 
     89 static inline bool isEmpty (const IVec4& rect)
     90 {
     91 	return rect.z() == 0 || rect.w() == 0;
     92 }
     93 
     94 inline int getNumMipLevels1D (int size)
     95 {
     96 	return deLog2Floor32(size)+1;
     97 }
     98 
     99 inline int getNumMipLevels2D (int width, int height)
    100 {
    101 	return deLog2Floor32(de::max(width, height))+1;
    102 }
    103 
    104 inline int getNumMipLevels3D (int width, int height, int depth)
    105 {
    106 	return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
    107 }
    108 
    109 inline int getMipLevelSize (int baseLevelSize, int levelNdx)
    110 {
    111 	return de::max(baseLevelSize >> levelNdx, 1);
    112 }
    113 
    114 inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
    115 {
    116 	return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
    117 }
    118 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    674 void ReferenceContext::genTextures (int numTextures, deUint32* textures)
    675 {
    676 	while (numTextures--)
    677 		*textures++ = m_textures.allocateName();
    678 }
    679 
    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 
    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 
    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 
    781 void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
    782 {
    783 	while (numFramebuffers--)
    784 		*framebuffers++ = m_framebuffers.allocateName();
    785 }
    786 
    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 
    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 
    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 
    836 void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
    837 {
    838 	while (numRenderbuffers--)
    839 		*renderbuffers++ = m_renderbuffers.allocateName();
    840 }
    841 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2358 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 
   2364 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 
   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 
   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 
   2423 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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2577 void ReferenceContext::clearDepthf (float depth)
   2578 {
   2579 	m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
   2580 }
   2581 
   2582 void ReferenceContext::clearStencil (int stencil)
   2583 {
   2584 	m_clearStencil = stencil;
   2585 }
   2586 
   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 
   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 
   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 
   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 
   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 
   2742 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
   2743 {
   2744 	stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
   2745 }
   2746 
   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 
   2767 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
   2768 {
   2769 	stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
   2770 }
   2771 
   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 
   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 
   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 
   2807 void ReferenceContext::depthRange (double n, double f)
   2808 {
   2809 	depthRangef((float)n, (float)f);
   2810 }
   2811 
   2812 void ReferenceContext::polygonOffset (float factor, float units)
   2813 {
   2814 	m_polygonOffsetFactor = factor;
   2815 	m_polygonOffsetUnits = units;
   2816 }
   2817 
   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 
   2833 void ReferenceContext::primitiveRestartIndex (deUint32 index)
   2834 {
   2835 	// only in core
   2836 	DE_ASSERT(glu::isContextTypeGLCore(getType()));
   2837 	m_primitiveRestartIndex = index;
   2838 }
   2839 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2927 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
   2928 {
   2929 	m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
   2930 }
   2931 
   2932 void ReferenceContext::depthMask (deBool mask)
   2933 {
   2934 	m_depthMask = !!mask;
   2935 }
   2936 
   2937 void ReferenceContext::stencilMask (deUint32 mask)
   2938 {
   2939 	stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
   2940 }
   2941 
   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 
   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 
   2984 static inline int maskStencil (int bits, int s) { return s & ((1<<bits)-1); }
   2985 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   3838 void ReferenceContext::uniform1f (deInt32 location, const float v0)
   3839 {
   3840 	uniform1fv(location, 1, &v0);
   3841 }
   3842 
   3843 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
   3844 {
   3845 	uniform1iv(location, 1, &v0);
   3846 }
   3847 
   3848 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
   3849 {
   3850 	uniformv(location, glu::TYPE_FLOAT, count, v);
   3851 }
   3852 
   3853 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
   3854 {
   3855 	uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
   3856 }
   3857 
   3858 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
   3859 {
   3860 	uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
   3861 }
   3862 
   3863 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
   3864 {
   3865 	uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
   3866 }
   3867 
   3868 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
   3869 {
   3870 	uniformv(location, glu::TYPE_INT_VEC2, count, v);
   3871 }
   3872 
   3873 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
   3874 {
   3875 	uniformv(location, glu::TYPE_INT_VEC3, count, v);
   3876 }
   3877 
   3878 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
   3879 {
   3880 	uniformv(location, glu::TYPE_INT_VEC4, count, v);
   3881 }
   3882 
   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 
   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 
   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 
   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 
   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 
   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 
   4012 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
   4013 {
   4014 	drawArraysInstanced(mode, first, count, 1);
   4015 }
   4016 
   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 
   4035 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
   4036 {
   4037 	drawElementsInstanced(mode, count, type, indices, 1);
   4038 }
   4039 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   4631 deUint32 ReferenceContext::getError (void)
   4632 {
   4633 	deUint32 err = m_lastError;
   4634 	m_lastError = GL_NO_ERROR;
   4635 	return err;
   4636 }
   4637 
   4638 void ReferenceContext::finish (void)
   4639 {
   4640 }
   4641 
   4642 inline void ReferenceContext::setError (deUint32 error)
   4643 {
   4644 	if (m_lastError == GL_NO_ERROR)
   4645 		m_lastError = error;
   4646 }
   4647 
   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 
   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 
   4681 TextureLevelArray::TextureLevelArray (void)
   4682 {
   4683 	deMemset(&m_data[0], 0, sizeof(m_data));
   4684 }
   4685 
   4686 TextureLevelArray::~TextureLevelArray (void)
   4687 {
   4688 	clear();
   4689 }
   4690 
   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 
   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 
   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 
   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 
   4748 Texture1D::Texture1D (deUint32 name)
   4749 	: Texture	(name, TYPE_1D)
   4750 	, m_view	(0, DE_NULL)
   4751 {
   4752 }
   4753 
   4754 Texture1D::~Texture1D (void)
   4755 {
   4756 }
   4757 
   4758 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
   4759 {
   4760 	m_levels.allocLevel(level, format, width, 1, 1);
   4761 }
   4762 
   4763 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 
   4800 tcu::Vec4 Texture1D::sample (float s, float lod) const
   4801 {
   4802 	return m_view.sample(getSampler(), s, 0.0f, lod);
   4803 }
   4804 
   4805 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 
   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 
   4844 Texture2D::Texture2D (deUint32 name)
   4845 	: Texture	(name, TYPE_2D)
   4846 	, m_view	(0, DE_NULL)
   4847 {
   4848 }
   4849 
   4850 Texture2D::~Texture2D (void)
   4851 {
   4852 }
   4853 
   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 
   4859 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 
   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 
   4917 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
   4918 {
   4919 	return m_view.sample(getSampler(), s, t, lod);
   4920 }
   4921 
   4922 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 
   4947 TextureCube::TextureCube (deUint32 name)
   4948 	: Texture(name, TYPE_CUBE_MAP)
   4949 {
   4950 }
   4951 
   4952 TextureCube::~TextureCube (void)
   4953 {
   4954 }
   4955 
   4956 void TextureCube::clearLevels (void)
   4957 {
   4958 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
   4959 		m_levels[face].clear();
   4960 }
   4961 
   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 
   4967 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 
   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 
   5032 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 
   5037 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 
   5072 Texture2DArray::Texture2DArray (deUint32 name)
   5073 	: Texture	(name, TYPE_2D_ARRAY)
   5074 	, m_view	(0, DE_NULL)
   5075 {
   5076 }
   5077 
   5078 Texture2DArray::~Texture2DArray (void)
   5079 {
   5080 }
   5081 
   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 
   5087 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 
   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 
   5146 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 
   5151 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 
   5176 TextureCubeArray::TextureCubeArray (deUint32 name)
   5177 	: Texture	(name, TYPE_CUBE_MAP_ARRAY)
   5178 	, m_view	(0, DE_NULL)
   5179 {
   5180 }
   5181 
   5182 TextureCubeArray::~TextureCubeArray (void)
   5183 {
   5184 }
   5185 
   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 
   5192 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 
   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 
   5251 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 
   5256 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 
   5296 Texture3D::Texture3D (deUint32 name)
   5297 	: Texture	(name, TYPE_3D)
   5298 	, m_view	(0, DE_NULL)
   5299 {
   5300 }
   5301 
   5302 Texture3D::~Texture3D (void)
   5303 {
   5304 }
   5305 
   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 
   5311 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 
   5354 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 
   5359 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 
   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 
   5404 Renderbuffer::Renderbuffer (deUint32 name)
   5405 	: NamedObject		(name)
   5406 {
   5407 }
   5408 
   5409 Renderbuffer::~Renderbuffer (void)
   5410 {
   5411 }
   5412 
   5413 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
   5414 {
   5415 	m_data.setStorage(format, width, height);
   5416 }
   5417 
   5418 Framebuffer::Framebuffer (deUint32 name)
   5419 	: NamedObject(name)
   5420 {
   5421 }
   5422 
   5423 Framebuffer::~Framebuffer (void)
   5424 {
   5425 }
   5426 
   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 
   5447 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
   5448 	: NamedObject	(name)
   5449 	, m_program		(program)
   5450 	, m_deleteFlag	(false)
   5451 {
   5452 }
   5453 
   5454 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
   5455 {
   5456 }
   5457 
   5458 } // rc
   5459 } // sglr
   5460