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