/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Reference Rendering Context.
 *//*--------------------------------------------------------------------*/

#include "sglrReferenceContext.hpp"
#include "sglrReferenceUtils.hpp"
#include "sglrShaderProgram.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuMatrix.hpp"
#include "tcuMatrixUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "gluDefs.hpp"
#include "gluTextureUtil.hpp"
#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deMemory.h"
#include "rrFragmentOperations.hpp"
#include "rrRenderer.hpp"

namespace sglr
{

using std::vector;
using std::map;

using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec4;
using tcu::RGBA;

// Reference context implementation
using namespace rc;

using tcu::TextureFormat;
using tcu::PixelBufferAccess;
using tcu::ConstPixelBufferAccess;

// Utilities for ReferenceContext
#define RC_RET_VOID

#define RC_ERROR_RET(ERR, RET)			\
do {									\
	setError(ERR);						\
	return RET;							\
} while (deGetFalse())

#define RC_IF_ERROR(COND, ERR, RET)		\
do {									\
	if (COND)							\
		RC_ERROR_RET(ERR, RET);			\
} while (deGetFalse())

static inline tcu::PixelBufferAccess nullAccess (void)
{
	return tcu::PixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), 0, 0, 0, DE_NULL);
}

static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
{
	return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
}

static inline bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
{
	return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
}

static inline bool isEmpty (const IVec4& rect)
{
	return rect.z() == 0 || rect.w() == 0;
}

inline int getNumMipLevels1D (int size)
{
	return deLog2Floor32(size)+1;
}

inline int getNumMipLevels2D (int width, int height)
{
	return deLog2Floor32(de::max(width, height))+1;
}

inline int getNumMipLevels3D (int width, int height, int depth)
{
	return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
}

inline int getMipLevelSize (int baseLevelSize, int levelNdx)
{
	return de::max(baseLevelSize >> levelNdx, 1);
}

inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
{
	return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
}

static tcu::CubeFace texTargetToFace (Framebuffer::TexTarget target)
{
	switch (target)
	{
		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X:	return tcu::CUBEFACE_NEGATIVE_X;
		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X:	return tcu::CUBEFACE_POSITIVE_X;
		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y:	return tcu::CUBEFACE_NEGATIVE_Y;
		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y:	return tcu::CUBEFACE_POSITIVE_Y;
		case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z:	return tcu::CUBEFACE_NEGATIVE_Z;
		case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z:	return tcu::CUBEFACE_POSITIVE_Z;
		default:											return tcu::CUBEFACE_LAST;
	}
}

static Framebuffer::TexTarget texLayeredTypeToTarget (Texture::Type type)
{
	switch (type)
	{
		case Texture::TYPE_2D_ARRAY:		return Framebuffer::TEXTARGET_2D_ARRAY;
		case Texture::TYPE_3D:				return Framebuffer::TEXTARGET_3D;
		case Texture::TYPE_CUBE_MAP_ARRAY:	return Framebuffer::TEXTARGET_CUBE_MAP_ARRAY;
		default:							return Framebuffer::TEXTARGET_LAST;
	}
}

static tcu::CubeFace mapGLCubeFace (deUint32 face)
{
	switch (face)
	{
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return tcu::CUBEFACE_NEGATIVE_X;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return tcu::CUBEFACE_POSITIVE_X;
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return tcu::CUBEFACE_NEGATIVE_Y;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return tcu::CUBEFACE_POSITIVE_Y;
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return tcu::CUBEFACE_NEGATIVE_Z;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return tcu::CUBEFACE_POSITIVE_Z;
		default:								return tcu::CUBEFACE_LAST;
	}
}

tcu::TextureFormat toTextureFormat (const tcu::PixelFormat& pixelFmt)
{
	static const struct
	{
		tcu::PixelFormat	pixelFmt;
		tcu::TextureFormat	texFmt;
	} pixelFormatMap[] =
	{
		{ tcu::PixelFormat(8,8,8,8),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8)			},
		{ tcu::PixelFormat(8,8,8,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_INT8)			},
		{ tcu::PixelFormat(4,4,4,4),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_4444)	},
		{ tcu::PixelFormat(5,5,5,1),	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_SHORT_5551)	},
		{ tcu::PixelFormat(5,6,5,0),	tcu::TextureFormat(tcu::TextureFormat::RGB,		tcu::TextureFormat::UNORM_SHORT_565)	}
	};

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
	{
		if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
			return pixelFormatMap[ndx].texFmt;
	}

	TCU_FAIL("Can't map pixel format to texture format");
}

tcu::TextureFormat toNonSRGBFormat (const tcu::TextureFormat& fmt)
{
	switch (fmt.order)
	{
		case tcu::TextureFormat::sRGB:
			return tcu::TextureFormat(tcu::TextureFormat::RGB,	fmt.type);
		case tcu::TextureFormat::sRGBA:
			return tcu::TextureFormat(tcu::TextureFormat::RGBA,	fmt.type);
		default:
			return fmt;
	}
}

tcu::TextureFormat getDepthFormat (int depthBits)
{
	switch (depthBits)
	{
		case 8:		return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
		case 16:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
		case 24:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
		case 32:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
		default:
			TCU_FAIL("Can't map depth buffer format");
	}
}

tcu::TextureFormat getStencilFormat (int stencilBits)
{
	switch (stencilBits)
	{
		case 8:		return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
		case 16:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
		case 24:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
		case 32:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
		default:
			TCU_FAIL("Can't map depth buffer format");
	}
}

static inline tcu::IVec4 intersect (const tcu::IVec4& a, const tcu::IVec4& b)
{
	int		x0	= de::max(a.x(), b.x());
	int		y0	= de::max(a.y(), b.y());
	int		x1	= de::min(a.x()+a.z(), b.x()+b.z());
	int		y1	= de::min(a.y()+a.w(), b.y()+b.w());
	int		w	= de::max(0, x1-x0);
	int		h	= de::max(0, y1-y0);

	return tcu::IVec4(x0, y0, w, h);
}

static inline tcu::IVec4 getBufferRect (const rr::MultisampleConstPixelBufferAccess& access)
{
	return tcu::IVec4(0, 0, access.raw().getHeight(), access.raw().getDepth());
}

ReferenceContextLimits::ReferenceContextLimits (const glu::RenderContext& renderCtx)
	: contextType				(renderCtx.getType())
	, maxTextureImageUnits		(0)
	, maxTexture2DSize			(0)
	, maxTextureCubeSize		(0)
	, maxTexture2DArrayLayers	(0)
	, maxTexture3DSize			(0)
	, maxRenderbufferSize		(0)
	, maxVertexAttribs			(0)
	, subpixelBits				(0)
{
	const glw::Functions& gl = renderCtx.getFunctions();

	// When the OpenGL ES's major version bigger than 3, and the expect context version is 3,
	// we need query the real GL context version and update the real version to reference context.
	if (glu::IsES3Compatible(gl) && isES2Context(contextType))
	{
		int majorVersion = contextType.getMajorVersion();
		int minorVersion = contextType.getMinorVersion();
		gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
		gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
		contextType.setAPI(glu::ApiType::es(majorVersion, minorVersion));
	}

	gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,		&maxTextureImageUnits);
	gl.getIntegerv(GL_MAX_TEXTURE_SIZE,				&maxTexture2DSize);
	gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE,	&maxTextureCubeSize);
	gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE,		&maxRenderbufferSize);
	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS,			&maxVertexAttribs);
	gl.getIntegerv(GL_SUBPIXEL_BITS,				&subpixelBits);

	if (contextSupports(contextType, glu::ApiType::es(3,0)) || glu::isContextTypeGLCore(contextType))
	{
		gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS,	&maxTexture2DArrayLayers);
		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE,		&maxTexture3DSize);
	}

	// Limit texture sizes to supported values
	maxTexture2DSize	= de::min(maxTexture2DSize,		(int)MAX_TEXTURE_SIZE);
	maxTextureCubeSize	= de::min(maxTextureCubeSize,	(int)MAX_TEXTURE_SIZE);
	maxTexture3DSize	= de::min(maxTexture3DSize,		(int)MAX_TEXTURE_SIZE);

	GLU_EXPECT_NO_ERROR(gl.getError(), GL_NO_ERROR);

	// \todo [pyry] Figure out following things:
	// + supported fbo configurations
	// ...

	// \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
	addExtension("GL_EXT_color_buffer_half_float");
	addExtension("GL_EXT_color_buffer_float");

	if (contextSupports(contextType, glu::ApiType::es(3,1)))
		addExtension("GL_EXT_texture_cube_map_array");
}

void ReferenceContextLimits::addExtension (const char* extension)
{
	extensionList.push_back(extension);

	if (!extensionStr.empty())
		extensionStr += " ";
	extensionStr += extension;
}

ReferenceContextBuffers::ReferenceContextBuffers (const tcu::PixelFormat& colorBits, int depthBits, int stencilBits, int width, int height, int samples)
{
	m_colorbuffer.setStorage(toTextureFormat(colorBits), samples, width, height);

	if (depthBits > 0)
		m_depthbuffer.setStorage(getDepthFormat(depthBits), samples, width, height);

	if (stencilBits > 0)
		m_stencilbuffer.setStorage(getStencilFormat(stencilBits), samples, width, height);
}

ReferenceContext::StencilState::StencilState (void)
	: func				(GL_ALWAYS)
	, ref				(0)
	, opMask			(~0u)
	, opStencilFail		(GL_KEEP)
	, opDepthFail		(GL_KEEP)
	, opDepthPass		(GL_KEEP)
	, writeMask			(~0u)
{
}

ReferenceContext::ReferenceContext (const ReferenceContextLimits& limits, const rr::MultisamplePixelBufferAccess& colorbuffer, const rr::MultisamplePixelBufferAccess& depthbuffer, const rr::MultisamplePixelBufferAccess& stencilbuffer)
	: Context							(limits.contextType)
	, m_limits							(limits)
	, m_defaultColorbuffer				(colorbuffer)
	, m_defaultDepthbuffer				(depthbuffer)
	, m_defaultStencilbuffer			(stencilbuffer)
	, m_clientVertexArray				(0, m_limits.maxVertexAttribs)

	, m_viewport						(0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth())

	, m_activeTexture					(0)
	, m_textureUnits					(m_limits.maxTextureImageUnits)
	, m_emptyTex1D						()
	, m_emptyTex2D						(isES2Context(limits.contextType))
	, m_emptyTexCube					(!isES2Context(limits.contextType))
	, m_emptyTex2DArray					()
	, m_emptyTex3D						()
	, m_emptyTexCubeArray				()

	, m_pixelUnpackRowLength			(0)
	, m_pixelUnpackSkipRows				(0)
	, m_pixelUnpackSkipPixels			(0)
	, m_pixelUnpackImageHeight			(0)
	, m_pixelUnpackSkipImages			(0)
	, m_pixelUnpackAlignment			(4)
	, m_pixelPackAlignment				(4)

	, m_readFramebufferBinding			(DE_NULL)
	, m_drawFramebufferBinding			(DE_NULL)
	, m_renderbufferBinding				(DE_NULL)
	, m_vertexArrayBinding				(DE_NULL)
	, m_currentProgram					(DE_NULL)

	, m_arrayBufferBinding				(DE_NULL)
	, m_pixelPackBufferBinding			(DE_NULL)
	, m_pixelUnpackBufferBinding		(DE_NULL)
	, m_transformFeedbackBufferBinding	(DE_NULL)
	, m_uniformBufferBinding			(DE_NULL)
	, m_copyReadBufferBinding			(DE_NULL)
	, m_copyWriteBufferBinding			(DE_NULL)
	, m_drawIndirectBufferBinding		(DE_NULL)

	, m_clearColor						(0.0f, 0.0f, 0.0f, 0.0f)
	, m_clearDepth						(1.0f)
	, m_clearStencil					(0)
	, m_scissorEnabled					(false)
	, m_scissorBox						(m_viewport)
	, m_stencilTestEnabled				(false)
	, m_depthTestEnabled				(false)
	, m_depthFunc						(GL_LESS)
	, m_depthRangeNear					(0.0f)
	, m_depthRangeFar					(1.0f)
	, m_polygonOffsetFactor				(0.0f)
	, m_polygonOffsetUnits				(0.0f)
	, m_polygonOffsetFillEnabled		(false)
	, m_provokingFirstVertexConvention	(false)
	, m_blendEnabled					(false)
	, m_blendModeRGB					(GL_FUNC_ADD)
	, m_blendModeAlpha					(GL_FUNC_ADD)
	, m_blendFactorSrcRGB				(GL_ONE)
	, m_blendFactorDstRGB				(GL_ZERO)
	, m_blendFactorSrcAlpha				(GL_ONE)
	, m_blendFactorDstAlpha				(GL_ZERO)
	, m_blendColor						(0.0f, 0.0f, 0.0f, 0.0f)
	, m_sRGBUpdateEnabled				(true)
	, m_depthClampEnabled				(false)
	, m_colorMask						(true, true, true, true)
	, m_depthMask						(true)
	, m_currentAttribs					(m_limits.maxVertexAttribs, rr::GenericVec4(tcu::Vec4(0, 0, 0, 1)))
	, m_lineWidth						(1.0f)
	, m_primitiveRestartFixedIndex		(false)
	, m_primitiveRestartSettableIndex	(false)
	, m_primitiveRestartIndex			(0)

	, m_lastError						(GL_NO_ERROR)
{
	// Create empty textures to be used when texture objects are incomplete.
	m_emptyTex1D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex1D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex1D.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTex1D.getSampler().magFilter	= tcu::Sampler::NEAREST;
	m_emptyTex1D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1);
	m_emptyTex1D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
	m_emptyTex1D.updateView(tcu::Sampler::MODE_LAST);

	m_emptyTex2D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex2D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex2D.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTex2D.getSampler().magFilter	= tcu::Sampler::NEAREST;
	m_emptyTex2D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
	m_emptyTex2D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
	m_emptyTex2D.updateView(tcu::Sampler::MODE_LAST);

	m_emptyTexCube.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTexCube.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTexCube.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTexCube.getSampler().magFilter	= tcu::Sampler::NEAREST;
	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
	{
		m_emptyTexCube.allocFace(0, (tcu::CubeFace)face, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
		m_emptyTexCube.getFace(0, (tcu::CubeFace)face).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
	}
	m_emptyTexCube.updateView(tcu::Sampler::MODE_LAST);

	m_emptyTex2DArray.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex2DArray.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex2DArray.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTex2DArray.getSampler().magFilter	= tcu::Sampler::NEAREST;
	m_emptyTex2DArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
	m_emptyTex2DArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
	m_emptyTex2DArray.updateView(tcu::Sampler::MODE_LAST);

	m_emptyTex3D.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex3D.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex3D.getSampler().wrapR		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTex3D.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTex3D.getSampler().magFilter	= tcu::Sampler::NEAREST;
	m_emptyTex3D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
	m_emptyTex3D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
	m_emptyTex3D.updateView(tcu::Sampler::MODE_LAST);

	m_emptyTexCubeArray.getSampler().wrapS		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTexCubeArray.getSampler().wrapT		= tcu::Sampler::CLAMP_TO_EDGE;
	m_emptyTexCubeArray.getSampler().minFilter	= tcu::Sampler::NEAREST;
	m_emptyTexCubeArray.getSampler().magFilter	= tcu::Sampler::NEAREST;
	m_emptyTexCubeArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 6);
	for (int faceNdx = 0; faceNdx < 6; faceNdx++)
		m_emptyTexCubeArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, faceNdx);
	m_emptyTexCubeArray.updateView(tcu::Sampler::MODE_LAST);

	for (int unitNdx = 0; unitNdx < m_limits.maxTextureImageUnits; unitNdx++)
		m_textureUnits[unitNdx].defaultCubeTex.getSampler().seamlessCubeMap = !isES2Context(limits.contextType);

	if (glu::isContextTypeGLCore(getType()))
		m_sRGBUpdateEnabled = false;
}

ReferenceContext::~ReferenceContext (void)
{
	// Destroy all objects -- verifies that ref counting works
	{
		vector<VertexArray*> vertexArrays;
		m_vertexArrays.getAll(vertexArrays);
		for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
			deleteVertexArray(*i);

		DE_ASSERT(m_clientVertexArray.getRefCount() == 1);
	}

	{
		vector<Texture*> textures;
		m_textures.getAll(textures);
		for (vector<Texture*>::iterator i = textures.begin(); i != textures.end(); i++)
			deleteTexture(*i);
	}

	{
		vector<Framebuffer*> framebuffers;
		m_framebuffers.getAll(framebuffers);
		for (vector<Framebuffer*>::iterator i = framebuffers.begin(); i != framebuffers.end(); i++)
			deleteFramebuffer(*i);
	}

	{
		vector<Renderbuffer*> renderbuffers;
		m_renderbuffers.getAll(renderbuffers);
		for (vector<Renderbuffer*>::iterator i = renderbuffers.begin(); i != renderbuffers.end(); i++)
			deleteRenderbuffer(*i);
	}

	{
		vector<DataBuffer*> buffers;
		m_buffers.getAll(buffers);
		for (vector<DataBuffer*>::iterator i = buffers.begin(); i != buffers.end(); i++)
			deleteBuffer(*i);
	}

	{
		vector<ShaderProgramObjectContainer*> programs;
		m_programs.getAll(programs);
		for (vector<ShaderProgramObjectContainer*>::iterator i = programs.begin(); i != programs.end(); i++)
			deleteProgramObject(*i);
	}
}

void ReferenceContext::activeTexture (deUint32 texture)
{
	if (deInBounds32(texture, GL_TEXTURE0, GL_TEXTURE0 + (deUint32)m_textureUnits.size()))
		m_activeTexture = texture - GL_TEXTURE0;
	else
		setError(GL_INVALID_ENUM);
}

void ReferenceContext::setTex1DBinding (int unitNdx, Texture1D* texture)
{
	if (m_textureUnits[unitNdx].tex1DBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].tex1DBinding);
		m_textureUnits[unitNdx].tex1DBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].tex1DBinding = texture;
	}
}

void ReferenceContext::setTex2DBinding (int unitNdx, Texture2D* texture)
{
	if (m_textureUnits[unitNdx].tex2DBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].tex2DBinding);
		m_textureUnits[unitNdx].tex2DBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].tex2DBinding = texture;
	}
}

void ReferenceContext::setTexCubeBinding (int unitNdx, TextureCube* texture)
{
	if (m_textureUnits[unitNdx].texCubeBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].texCubeBinding);
		m_textureUnits[unitNdx].texCubeBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].texCubeBinding = texture;
	}
}

void ReferenceContext::setTex2DArrayBinding (int unitNdx, Texture2DArray* texture)
{
	if (m_textureUnits[unitNdx].tex2DArrayBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].tex2DArrayBinding);
		m_textureUnits[unitNdx].tex2DArrayBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].tex2DArrayBinding = texture;
	}
}

void ReferenceContext::setTex3DBinding (int unitNdx, Texture3D* texture)
{
	if (m_textureUnits[unitNdx].tex3DBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].tex3DBinding);
		m_textureUnits[unitNdx].tex3DBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].tex3DBinding = texture;
	}
}

void ReferenceContext::setTexCubeArrayBinding (int unitNdx, TextureCubeArray* texture)
{
	if (m_textureUnits[unitNdx].texCubeArrayBinding)
	{
		m_textures.releaseReference(m_textureUnits[unitNdx].texCubeArrayBinding);
		m_textureUnits[unitNdx].texCubeArrayBinding = DE_NULL;
	}

	if (texture)
	{
		m_textures.acquireReference(texture);
		m_textureUnits[unitNdx].texCubeArrayBinding = texture;
	}
}

void ReferenceContext::bindTexture (deUint32 target, deUint32 texture)
{
	int unitNdx = m_activeTexture;

	RC_IF_ERROR(target != GL_TEXTURE_1D				&&
				target != GL_TEXTURE_2D				&&
				target != GL_TEXTURE_CUBE_MAP		&&
				target != GL_TEXTURE_2D_ARRAY		&&
				target != GL_TEXTURE_3D				&&
				target != GL_TEXTURE_CUBE_MAP_ARRAY,
				GL_INVALID_ENUM, RC_RET_VOID);

	RC_IF_ERROR(glu::isContextTypeES(m_limits.contextType) && (target == GL_TEXTURE_1D), GL_INVALID_ENUM, RC_RET_VOID);

	if (texture == 0)
	{
		// Clear binding.
		switch (target)
		{
			case GL_TEXTURE_1D:				setTex1DBinding			(unitNdx, DE_NULL);	break;
			case GL_TEXTURE_2D:				setTex2DBinding			(unitNdx, DE_NULL);	break;
			case GL_TEXTURE_CUBE_MAP:		setTexCubeBinding		(unitNdx, DE_NULL);	break;
			case GL_TEXTURE_2D_ARRAY:		setTex2DArrayBinding	(unitNdx, DE_NULL);	break;
			case GL_TEXTURE_3D:				setTex3DBinding			(unitNdx, DE_NULL);	break;
			case GL_TEXTURE_CUBE_MAP_ARRAY:	setTexCubeArrayBinding	(unitNdx, DE_NULL);	break;
			default:
				DE_ASSERT(false);
		}
	}
	else
	{
		Texture* texObj = m_textures.find(texture);

		if (texObj)
		{
			// Validate type.
			Texture::Type expectedType = Texture::TYPE_LAST;
			switch (target)
			{
				case GL_TEXTURE_1D:				expectedType = Texture::TYPE_1D;				break;
				case GL_TEXTURE_2D:				expectedType = Texture::TYPE_2D;				break;
				case GL_TEXTURE_CUBE_MAP:		expectedType = Texture::TYPE_CUBE_MAP;			break;
				case GL_TEXTURE_2D_ARRAY:		expectedType = Texture::TYPE_2D_ARRAY;			break;
				case GL_TEXTURE_3D:				expectedType = Texture::TYPE_3D;				break;
				case GL_TEXTURE_CUBE_MAP_ARRAY:	expectedType = Texture::TYPE_CUBE_MAP_ARRAY;	break;
				default:
					DE_ASSERT(false);
			}
			RC_IF_ERROR(texObj->getType() != expectedType, GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
		{
			// New texture object.
			bool seamlessCubeMap = !isES2Context(m_limits.contextType);
			switch (target)
			{
				case GL_TEXTURE_1D:				texObj = new Texture1D			(texture);					break;
				case GL_TEXTURE_2D:				texObj = new Texture2D			(texture);					break;
				case GL_TEXTURE_CUBE_MAP:		texObj = new TextureCube		(texture, seamlessCubeMap);	break;
				case GL_TEXTURE_2D_ARRAY:		texObj = new Texture2DArray		(texture);					break;
				case GL_TEXTURE_3D:				texObj = new Texture3D			(texture);					break;
				case GL_TEXTURE_CUBE_MAP_ARRAY:	texObj = new TextureCubeArray	(texture);					break;
				default:
					DE_ASSERT(false);
			}

			m_textures.insert(texObj);
		}

		switch (target)
		{
			case GL_TEXTURE_1D:				setTex1DBinding			(unitNdx, static_cast<Texture1D*>			(texObj));	break;
			case GL_TEXTURE_2D:				setTex2DBinding			(unitNdx, static_cast<Texture2D*>			(texObj));	break;
			case GL_TEXTURE_CUBE_MAP:		setTexCubeBinding		(unitNdx, static_cast<TextureCube*>			(texObj));	break;
			case GL_TEXTURE_2D_ARRAY:		setTex2DArrayBinding	(unitNdx, static_cast<Texture2DArray*>		(texObj));	break;
			case GL_TEXTURE_3D:				setTex3DBinding			(unitNdx, static_cast<Texture3D*>			(texObj));	break;
			case GL_TEXTURE_CUBE_MAP_ARRAY:	setTexCubeArrayBinding	(unitNdx, static_cast<TextureCubeArray*>	(texObj));	break;
			default:
				DE_ASSERT(false);
		}
	}
}

void ReferenceContext::genTextures (int numTextures, deUint32* textures)
{
	while (numTextures--)
		*textures++ = m_textures.allocateName();
}

void ReferenceContext::deleteTextures (int numTextures, const deUint32* textures)
{
	for (int i = 0; i < numTextures; i++)
	{
		deUint32	name		= textures[i];
		Texture*	texture		= name ? m_textures.find(name) : DE_NULL;

		if (texture)
			deleteTexture(texture);
	}
}

void ReferenceContext::deleteTexture (Texture* texture)
{
	// Unbind from context
	for (int unitNdx = 0; unitNdx < (int)m_textureUnits.size(); unitNdx++)
	{
		if (m_textureUnits[unitNdx].tex1DBinding				== texture)	setTex1DBinding			(unitNdx, DE_NULL);
		else if (m_textureUnits[unitNdx].tex2DBinding			== texture)	setTex2DBinding			(unitNdx, DE_NULL);
		else if (m_textureUnits[unitNdx].texCubeBinding			== texture)	setTexCubeBinding		(unitNdx, DE_NULL);
		else if (m_textureUnits[unitNdx].tex2DArrayBinding		== texture)	setTex2DArrayBinding	(unitNdx, DE_NULL);
		else if (m_textureUnits[unitNdx].tex3DBinding			== texture)	setTex3DBinding			(unitNdx, DE_NULL);
		else if (m_textureUnits[unitNdx].texCubeArrayBinding	== texture)	setTexCubeArrayBinding	(unitNdx, DE_NULL);
	}

	// Unbind from currently bound framebuffers
	for (int ndx = 0; ndx < 2; ndx++)
	{
		rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
		if (framebufferBinding)
		{
			int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
								+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);

			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
			{
				Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
				if (attachment.name == texture->getName())
				{
					for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
						releaseFboAttachmentReference(attachment);
					attachment = Framebuffer::Attachment();
				}
			}
		}
	}

	DE_ASSERT(texture->getRefCount() == 1);
	m_textures.releaseReference(texture);
}

void ReferenceContext::bindFramebuffer (deUint32 target, deUint32 name)
{
	Framebuffer* fbo = DE_NULL;

	RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
				target != GL_DRAW_FRAMEBUFFER	&&
				target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);

	if (name != 0)
	{
		// Find or create framebuffer object.
		fbo = m_framebuffers.find(name);
		if (!fbo)
		{
			fbo = new Framebuffer(name);
			m_framebuffers.insert(fbo);
		}
	}

	for (int ndx = 0; ndx < 2; ndx++)
	{
		deUint32			bindingTarget	= ndx ? GL_DRAW_FRAMEBUFFER			: GL_READ_FRAMEBUFFER;
		rc::Framebuffer*&	binding			= ndx ? m_drawFramebufferBinding	: m_readFramebufferBinding;

		if (target != GL_FRAMEBUFFER && target != bindingTarget)
			continue; // Doesn't match this target.

		// Remove old references
		if (binding)
		{
			// Clear all attachment point references
			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
				releaseFboAttachmentReference(binding->getAttachment((Framebuffer::AttachmentPoint)point));

			m_framebuffers.releaseReference(binding);
		}

		// Create new references
		if (fbo)
		{
			m_framebuffers.acquireReference(fbo);

			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
				acquireFboAttachmentReference(fbo->getAttachment((Framebuffer::AttachmentPoint)point));
		}

		binding = fbo;
	}
}

void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
{
	while (numFramebuffers--)
		*framebuffers++ = m_framebuffers.allocateName();
}

void ReferenceContext::deleteFramebuffer (Framebuffer* framebuffer)
{
	// Remove bindings.
	if (m_drawFramebufferBinding == framebuffer) bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
	if (m_readFramebufferBinding == framebuffer) bindFramebuffer(GL_READ_FRAMEBUFFER, 0);

	DE_ASSERT(framebuffer->getRefCount() == 1);
	m_framebuffers.releaseReference(framebuffer);
}

void ReferenceContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
{
	for (int i = 0; i < numFramebuffers; i++)
	{
		deUint32		name		= framebuffers[i];
		Framebuffer*	framebuffer	= name ? m_framebuffers.find(name) : DE_NULL;

		if (framebuffer)
			deleteFramebuffer(framebuffer);
	}
}

void ReferenceContext::bindRenderbuffer (deUint32 target, deUint32 name)
{
	Renderbuffer* rbo = DE_NULL;

	RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);

	if (name != 0)
	{
		rbo = m_renderbuffers.find(name);
		if (!rbo)
		{
			rbo = new Renderbuffer(name);
			m_renderbuffers.insert(rbo);
		}
	}

	// Remove old reference
	if (m_renderbufferBinding)
		m_renderbuffers.releaseReference(m_renderbufferBinding);

	// Create new reference
	if (rbo)
		m_renderbuffers.acquireReference(rbo);

	m_renderbufferBinding = rbo;
}

void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
{
	while (numRenderbuffers--)
		*renderbuffers++ = m_renderbuffers.allocateName();
}

void ReferenceContext::deleteRenderbuffer (Renderbuffer* renderbuffer)
{
	if (m_renderbufferBinding == renderbuffer)
		bindRenderbuffer(GL_RENDERBUFFER, 0);

	// Unbind from currently bound framebuffers
	for (int ndx = 0; ndx < 2; ndx++)
	{
		rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
		if (framebufferBinding)
		{
			int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
								+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);

			for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
			{
				Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
				if (attachment.name == renderbuffer->getName())
				{
					for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
						releaseFboAttachmentReference(attachment);
					attachment = Framebuffer::Attachment();
				}
			}
		}
	}

	DE_ASSERT(renderbuffer->getRefCount() == 1);
	m_renderbuffers.releaseReference(renderbuffer);
}

void ReferenceContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
{
	for (int i = 0; i < numRenderbuffers; i++)
	{
		deUint32		name			= renderbuffers[i];
		Renderbuffer*	renderbuffer	= name ? m_renderbuffers.find(name) : DE_NULL;

		if (renderbuffer)
			deleteRenderbuffer(renderbuffer);
	}
}

void ReferenceContext::pixelStorei (deUint32 pname, int param)
{
	switch (pname)
	{
		case GL_UNPACK_ALIGNMENT:
			RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackAlignment = param;
			break;

		case GL_PACK_ALIGNMENT:
			RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelPackAlignment = param;
			break;

		case GL_UNPACK_ROW_LENGTH:
			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackRowLength = param;
			break;

		case GL_UNPACK_SKIP_ROWS:
			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackSkipRows = param;
			break;

		case GL_UNPACK_SKIP_PIXELS:
			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackSkipPixels = param;
			break;

		case GL_UNPACK_IMAGE_HEIGHT:
			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackImageHeight = param;
			break;

		case GL_UNPACK_SKIP_IMAGES:
			RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
			m_pixelUnpackSkipImages = param;
			break;

		default:
			setError(GL_INVALID_ENUM);
	}
}

tcu::ConstPixelBufferAccess ReferenceContext::getUnpack2DAccess (const tcu::TextureFormat& format, int width, int height, const void* data)
{
	int				pixelSize	= format.getPixelSize();
	int				rowLen		= m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
	int				rowPitch	= deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
	const deUint8*	ptr			= (const deUint8*)data + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;

	return tcu::ConstPixelBufferAccess(format, width, height, 1, rowPitch, 0, ptr);
}

tcu::ConstPixelBufferAccess ReferenceContext::getUnpack3DAccess (const tcu::TextureFormat& format, int width, int height, int depth, const void* data)
{
	int				pixelSize	= format.getPixelSize();
	int				rowLen		= m_pixelUnpackRowLength	> 0 ? m_pixelUnpackRowLength	: width;
	int				imageHeight	= m_pixelUnpackImageHeight	> 0 ? m_pixelUnpackImageHeight	: height;
	int				rowPitch	= deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
	int				slicePitch	= imageHeight*rowPitch;
	const deUint8*	ptr			= (const deUint8*)data + m_pixelUnpackSkipImages*slicePitch + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;

	return tcu::ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, ptr);
}

static tcu::TextureFormat mapInternalFormat (deUint32 internalFormat)
{
	switch (internalFormat)
	{
		case GL_ALPHA:				return TextureFormat(TextureFormat::A,		TextureFormat::UNORM_INT8);
		case GL_LUMINANCE:			return TextureFormat(TextureFormat::L,		TextureFormat::UNORM_INT8);
		case GL_LUMINANCE_ALPHA:	return TextureFormat(TextureFormat::LA,		TextureFormat::UNORM_INT8);
		case GL_RGB:				return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
		case GL_RGBA:				return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);

		default:
			return glu::mapGLInternalFormat(internalFormat);
	}
}

static void depthValueFloatClampCopy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
{
	int width	= dst.getWidth();
	int height	= dst.getHeight();
	int depth	= dst.getDepth();

	DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);

	// clamping copy

	if (src.getFormat().order == tcu::TextureFormat::DS && dst.getFormat().order == tcu::TextureFormat::DS)
	{
		// copy only depth and stencil
		for (int z = 0; z < depth; z++)
		for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
			dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
		}
	}
	else
	{
		// copy only depth
		for (int z = 0; z < depth; z++)
		for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
			dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
	}
}

void ReferenceContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
{
	texImage2D(target, level, internalFormat, width, 1, border, format, type, data);
}

void ReferenceContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
{
	texImage3D(target, level, internalFormat, width, height, 1, border, format, type, data);
}

static void clearToTextureInitialValue (PixelBufferAccess access)
{
	const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::D || access.getFormat().order == tcu::TextureFormat::DS;
	const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::S || access.getFormat().order == tcu::TextureFormat::DS;
	const bool hasColor		= !hasDepth && !hasStencil;

	if (hasDepth)
		tcu::clearDepth(access, 0.0f);
	if (hasStencil)
		tcu::clearStencil(access, 0u);
	if (hasColor)
		tcu::clear(access, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
}

void ReferenceContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
{
	TextureUnit&		unit					= m_textureUnits[m_activeTexture];
	const void*			unpackPtr				= getPixelUnpackPtr(data);
	const bool			isDstFloatDepthFormat	= (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
	TextureFormat		storageFmt;
	TextureFormat		transferFmt;

	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || height < 0 || depth < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);

	// Map storage format.
	storageFmt = mapInternalFormat(internalFormat);
	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	// Map transfer format.
	transferFmt = glu::mapGLTransferFormat(format, type);
	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
	{
		// Validate size and level.
		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height != 1 || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, 1, unpackPtr);
			PixelBufferAccess		dst		(texture->getLevel(level));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getLevel(level));
		}
	}
	else if (target == GL_TEXTURE_2D)
	{
		// Validate size and level.
		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width, height);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, height, unpackPtr);
			PixelBufferAccess		dst		(texture->getLevel(level));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getLevel(level));
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
	{
		// Validate size and level.
		RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);

		TextureCube*	texture	= unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
		tcu::CubeFace	face	= mapGLCubeFace(target);

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getFace(level, face));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocFace(level, face, storageFmt, width, height);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack2DAccess(transferFmt, width, height, unpackPtr);
			PixelBufferAccess		dst		(texture->getFace(level, face));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getFace(level, face));
		}
	}
	else if (target == GL_TEXTURE_2D_ARRAY)
	{
		// Validate size and level.
		RC_IF_ERROR(width	> m_limits.maxTexture2DSize ||
					height	> m_limits.maxTexture2DSize ||
					depth	> m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture2DArray* texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight()	||
						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width, height, depth);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
			PixelBufferAccess		dst		(texture->getLevel(level));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getLevel(level));
		}
	}
	else if (target == GL_TEXTURE_3D)
	{
		// Validate size and level.
		RC_IF_ERROR(width	> m_limits.maxTexture3DSize ||
					height	> m_limits.maxTexture3DSize ||
					depth	> m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture3DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture3D* texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight()	||
						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width, height, depth);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
			PixelBufferAccess		dst		(texture->getLevel(level));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getLevel(level));
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
	{
		// Validate size and level.
		RC_IF_ERROR(width		!= height						||
					width		 > m_limits.maxTexture2DSize	||
					depth % 6	!= 0							||
					depth		 > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight()	||
						depth		!= dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width, height, depth);

		if (unpackPtr)
		{
			ConstPixelBufferAccess	src		= getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
			PixelBufferAccess		dst		(texture->getLevel(level));

			if (isDstFloatDepthFormat)
				depthValueFloatClampCopy(dst, src);
			else
				tcu::copy(dst, src);
		}
		else
		{
			// No data supplied, clear to initial
			clearToTextureInitialValue(texture->getLevel(level));
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
{
	texSubImage2D(target, level, xoffset, 0, width, 1, format, type, data);
}

void ReferenceContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
{
	texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, data);
}

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)
{
	TextureUnit& unit = m_textureUnits[m_activeTexture];

	RC_IF_ERROR(xoffset < 0 || yoffset < 0 || zoffset < 0,	GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || height < 0 || depth < 0,		GL_INVALID_VALUE, RC_RET_VOID);

	TextureFormat transferFmt = glu::mapGLTransferFormat(format, type);
	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, getPixelUnpackPtr(data));

	if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
	{
		Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else if (target == GL_TEXTURE_2D)
	{
		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
	{
		TextureCube&	texture		= unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
		tcu::CubeFace	face		= mapGLCubeFace(target);

		RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getFace(level, face);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else if (target == GL_TEXTURE_3D)
	{
		Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else if (target == GL_TEXTURE_2D_ARRAY)
	{
		Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
	{
		TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth()	||
					yoffset + height	> dst.getHeight()	||
					zoffset + depth		> dst.getDepth(),
					GL_INVALID_VALUE, RC_RET_VOID);

		// depth components are limited to [0,1] range
		if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
			depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
		else
			tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
{
	TextureUnit&							unit		= m_textureUnits[m_activeTexture];
	TextureFormat							storageFmt;
	rr::MultisampleConstPixelBufferAccess	src			= getReadColorbuffer();

	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);

	// Map storage format.
	storageFmt = mapInternalFormat(internalFormat);
	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	if (target == GL_TEXTURE_1D)
	{
		// Validate size and level.
		RC_IF_ERROR(width > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width);

		// Copy from current framebuffer.
		PixelBufferAccess dst = texture->getLevel(level);
		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
				continue; // Undefined pixel.

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo, 0);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
{
	TextureUnit&							unit		= m_textureUnits[m_activeTexture];
	TextureFormat							storageFmt;
	rr::MultisampleConstPixelBufferAccess	src			= getReadColorbuffer();

	RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || height < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);

	// Map storage format.
	storageFmt = mapInternalFormat(internalFormat);
	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	if (target == GL_TEXTURE_2D)
	{
		// Validate size and level.
		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);

		Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getLevel(level));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocLevel(level, storageFmt, width, height);

		// Copy from current framebuffer.
		PixelBufferAccess dst = texture->getLevel(level);
		for (int yo = 0; yo < height; yo++)
		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
				continue; // Undefined pixel.

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
	{
		// Validate size and level.
		RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);

		TextureCube*	texture	= unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
		tcu::CubeFace	face	= mapGLCubeFace(target);

		if (texture->isImmutable())
		{
			RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);

			ConstPixelBufferAccess dst(texture->getFace(level, face));
			RC_IF_ERROR(storageFmt	!= dst.getFormat()	||
						width		!= dst.getWidth()	||
						height		!= dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
		}
		else
			texture->allocFace(level, face, storageFmt, width, height);

		// Copy from current framebuffer.
		PixelBufferAccess dst = texture->getFace(level, face);
		for (int yo = 0; yo < height; yo++)
		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
				continue; // Undefined pixel.

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
{
	TextureUnit&							unit	= m_textureUnits[m_activeTexture];
	rr::MultisampleConstPixelBufferAccess	src		= getReadColorbuffer();

	RC_IF_ERROR(xoffset < 0,	GL_INVALID_VALUE,		RC_RET_VOID);
	RC_IF_ERROR(width < 0,		GL_INVALID_VALUE,		RC_RET_VOID);
	RC_IF_ERROR(isEmpty(src),	GL_INVALID_OPERATION,	RC_RET_VOID);

	if (target == GL_TEXTURE_1D)
	{
		Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width > dst.getWidth(), GL_INVALID_VALUE, RC_RET_VOID);

		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
				continue;

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo+xoffset, 0);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
{
	TextureUnit&							unit	= m_textureUnits[m_activeTexture];
	rr::MultisampleConstPixelBufferAccess	src		= getReadColorbuffer();

	RC_IF_ERROR(xoffset < 0 || yoffset < 0,					GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || height < 0,					GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(isEmpty(src),								GL_INVALID_OPERATION, RC_RET_VOID);

	if (target == GL_TEXTURE_2D)
	{
		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;

		RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getLevel(level);

		RC_IF_ERROR(xoffset + width		> dst.getWidth() ||
					yoffset + height	> dst.getHeight(),
					GL_INVALID_VALUE, RC_RET_VOID);

		for (int yo = 0; yo < height; yo++)
		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
				continue;

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
			 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
			 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
	{
		TextureCube&	texture		= unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
		tcu::CubeFace	face		= mapGLCubeFace(target);

		RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);

		PixelBufferAccess dst = texture.getFace(level, face);

		RC_IF_ERROR(xoffset + width		> dst.getWidth() ||
					yoffset + height	> dst.getHeight(),
					GL_INVALID_VALUE, RC_RET_VOID);

		for (int yo = 0; yo < height; yo++)
		for (int xo = 0; xo < width; xo++)
		{
			if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
				continue;

			dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
{
	DE_UNREF(target && level && xoffset && yoffset && zoffset && x && y && width && height);
	DE_ASSERT(false);
}

void ReferenceContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
{
	TextureUnit&		unit		= m_textureUnits[m_activeTexture];
	TextureFormat		storageFmt;

	RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);

	// Map storage format.
	storageFmt = mapInternalFormat(internalFormat);
	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	if (target == GL_TEXTURE_2D)
	{
		Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;

		RC_IF_ERROR(width > m_limits.maxTexture2DSize || height >= m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);

		texture.clearLevels();
		texture.setImmutable();

		for (int level = 0; level < levels; level++)
		{
			int levelW = de::max(1, width >> level);
			int levelH = de::max(1, height >> level);

			texture.allocLevel(level, storageFmt, levelW, levelH);
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP)
	{
		TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;

		RC_IF_ERROR(width > m_limits.maxTextureCubeSize || height > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);

		texture.clearLevels();
		texture.setImmutable();

		for (int level = 0; level < levels; level++)
		{
			int levelW = de::max(1, width >> level);
			int levelH = de::max(1, height >> level);

			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
				texture.allocFace(level, (tcu::CubeFace)face, storageFmt, levelW, levelH);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

void ReferenceContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
{
	TextureUnit&		unit		= m_textureUnits[m_activeTexture];
	TextureFormat		storageFmt;

	RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);

	// Map storage format.
	storageFmt = mapInternalFormat(internalFormat);
	RC_IF_ERROR(storageFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				storageFmt.type		== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	if (target == GL_TEXTURE_2D_ARRAY)
	{
		Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;

		RC_IF_ERROR(width	>	m_limits.maxTexture2DSize	||
					height	>=	m_limits.maxTexture2DSize	||
					depth	>=	m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);

		texture.clearLevels();
		texture.setImmutable();

		for (int level = 0; level < levels; level++)
		{
			int levelW = de::max(1, width >> level);
			int levelH = de::max(1, height >> level);

			texture.allocLevel(level, storageFmt, levelW, levelH, depth);
		}
	}
	else if (target == GL_TEXTURE_3D)
	{
		Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;

		RC_IF_ERROR(width	> m_limits.maxTexture3DSize	||
					height	> m_limits.maxTexture3DSize	||
					depth	> m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);

		texture.clearLevels();
		texture.setImmutable();

		for (int level = 0; level < levels; level++)
		{
			int levelW = de::max(1, width		>> level);
			int levelH = de::max(1, height	>> level);
			int levelD = de::max(1, depth		>> level);

			texture.allocLevel(level, storageFmt, levelW, levelH, levelD);
		}
	}
	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
	{
		TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;

		RC_IF_ERROR(width		!=	height								||
					depth % 6	!= 0									||
					width		>	m_limits.maxTexture2DSize			||
					depth		>=	m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
		RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);

		texture.clearLevels();
		texture.setImmutable();

		for (int level = 0; level < levels; level++)
		{
			int levelW = de::max(1, width >> level);
			int levelH = de::max(1, height >> level);

			texture.allocLevel(level, storageFmt, levelW, levelH, depth);
		}
	}
	else
		RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
}

// \todo [2014-02-19 pyry] Duplicated with code in gluTextureUtil.hpp

static inline tcu::Sampler::WrapMode mapGLWrapMode (int value)
{
	switch (value)
	{
		case GL_CLAMP_TO_EDGE:		return tcu::Sampler::CLAMP_TO_EDGE;
		case GL_REPEAT:				return tcu::Sampler::REPEAT_GL;
		case GL_MIRRORED_REPEAT:	return tcu::Sampler::MIRRORED_REPEAT_GL;
		default:					return tcu::Sampler::WRAPMODE_LAST;
	}
}

static inline tcu::Sampler::FilterMode mapGLFilterMode (int value)
{
	switch (value)
	{
		case GL_NEAREST:				return tcu::Sampler::NEAREST;
		case GL_LINEAR:					return tcu::Sampler::LINEAR;
		case GL_NEAREST_MIPMAP_NEAREST:	return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
		case GL_NEAREST_MIPMAP_LINEAR:	return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
		case GL_LINEAR_MIPMAP_NEAREST:	return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
		case GL_LINEAR_MIPMAP_LINEAR:	return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
		default:						return tcu::Sampler::FILTERMODE_LAST;
	}
}

void ReferenceContext::texParameteri (deUint32 target, deUint32 pname, int value)
{
	TextureUnit&	unit		= m_textureUnits[m_activeTexture];
	Texture*		texture		= DE_NULL;

	switch (target)
	{
		case GL_TEXTURE_1D:				texture = unit.tex1DBinding			? unit.tex1DBinding			: &unit.default1DTex;			break;
		case GL_TEXTURE_2D:				texture = unit.tex2DBinding			? unit.tex2DBinding			: &unit.default2DTex;			break;
		case GL_TEXTURE_CUBE_MAP:		texture = unit.texCubeBinding		? unit.texCubeBinding		: &unit.defaultCubeTex;			break;
		case GL_TEXTURE_2D_ARRAY:		texture = unit.tex2DArrayBinding	? unit.tex2DArrayBinding	: &unit.default2DArrayTex;		break;
		case GL_TEXTURE_3D:				texture = unit.tex3DBinding			? unit.tex3DBinding			: &unit.default3DTex;			break;
		case GL_TEXTURE_CUBE_MAP_ARRAY:	texture = unit.texCubeArrayBinding	? unit.texCubeArrayBinding	: &unit.defaultCubeArrayTex;	break;

		default:					RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
	}

	switch (pname)
	{
		case GL_TEXTURE_WRAP_S:
		{
			tcu::Sampler::WrapMode wrapS = mapGLWrapMode(value);
			RC_IF_ERROR(wrapS == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
			texture->getSampler().wrapS = wrapS;
			break;
		}

		case GL_TEXTURE_WRAP_T:
		{
			tcu::Sampler::WrapMode wrapT = mapGLWrapMode(value);
			RC_IF_ERROR(wrapT == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
			texture->getSampler().wrapT = wrapT;
			break;
		}

		case GL_TEXTURE_WRAP_R:
		{
			tcu::Sampler::WrapMode wrapR = mapGLWrapMode(value);
			RC_IF_ERROR(wrapR == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
			texture->getSampler().wrapR = wrapR;
			break;
		}

		case GL_TEXTURE_MIN_FILTER:
		{
			tcu::Sampler::FilterMode minMode = mapGLFilterMode(value);
			RC_IF_ERROR(minMode == tcu::Sampler::FILTERMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
			texture->getSampler().minFilter = minMode;
			break;
		}

		case GL_TEXTURE_MAG_FILTER:
		{
			tcu::Sampler::FilterMode magMode = mapGLFilterMode(value);
			RC_IF_ERROR(magMode != tcu::Sampler::LINEAR && magMode != tcu::Sampler::NEAREST,
						GL_INVALID_VALUE, RC_RET_VOID);
			texture->getSampler().magFilter = magMode;
			break;
		}

		case GL_TEXTURE_MAX_LEVEL:
		{
			RC_IF_ERROR(value < 0, GL_INVALID_VALUE, RC_RET_VOID);
			texture->setMaxLevel(value);
			break;
		}

		default:
			RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
	}
}

static inline Framebuffer::AttachmentPoint mapGLAttachmentPoint (deUint32 attachment)
{
	switch (attachment)
	{
		case GL_COLOR_ATTACHMENT0:	return Framebuffer::ATTACHMENTPOINT_COLOR0;
		case GL_DEPTH_ATTACHMENT:	return Framebuffer::ATTACHMENTPOINT_DEPTH;
		case GL_STENCIL_ATTACHMENT:	return Framebuffer::ATTACHMENTPOINT_STENCIL;
		default:					return Framebuffer::ATTACHMENTPOINT_LAST;
	}
}

static inline Framebuffer::TexTarget mapGLFboTexTarget (deUint32 target)
{
	switch (target)
	{
		case GL_TEXTURE_2D:						return Framebuffer::TEXTARGET_2D;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y;
		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:	return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z;
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X;
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y;
		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:	return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z;
		default:								return Framebuffer::TEXTARGET_LAST;
	}
}

void ReferenceContext::acquireFboAttachmentReference (const Framebuffer::Attachment& attachment)
{
	switch (attachment.type)
	{
		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
		{
			TCU_CHECK(attachment.name != 0);
			Texture* texture = m_textures.find(attachment.name);
			TCU_CHECK(texture);
			m_textures.acquireReference(texture);
			break;
		}

		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
		{
			TCU_CHECK(attachment.name != 0);
			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
			TCU_CHECK(rbo);
			m_renderbuffers.acquireReference(rbo);
			break;
		}

		default:
			break; // Silently ignore
	}
}

void ReferenceContext::releaseFboAttachmentReference (const Framebuffer::Attachment& attachment)
{
	switch (attachment.type)
	{
		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
		{
			TCU_CHECK(attachment.name != 0);
			Texture* texture = m_textures.find(attachment.name);
			TCU_CHECK(texture);
			m_textures.releaseReference(texture);
			break;
		}

		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
		{
			TCU_CHECK(attachment.name != 0);
			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
			TCU_CHECK(rbo);
			m_renderbuffers.releaseReference(rbo);
			break;
		}

		default:
			break; // Silently ignore
	}
}

void ReferenceContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
{
	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
	{
		// Attach to both depth and stencil.
		framebufferTexture2D(target, GL_DEPTH_ATTACHMENT,	textarget, texture, level);
		framebufferTexture2D(target, GL_STENCIL_ATTACHMENT,	textarget, texture, level);
	}
	else
	{
		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
		Texture*						texObj			= DE_NULL;
		Framebuffer::TexTarget			fboTexTarget	= mapGLFboTexTarget(textarget);

		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
					target != GL_DRAW_FRAMEBUFFER	&&
					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);

		// Select binding point.
		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);

		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);

		if (texture != 0)
		{
			texObj = m_textures.find(texture);

			RC_IF_ERROR(!texObj,		GL_INVALID_OPERATION,	RC_RET_VOID);
			RC_IF_ERROR(level != 0,		GL_INVALID_VALUE,		RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.

			if (texObj->getType() == Texture::TYPE_2D)
				RC_IF_ERROR(fboTexTarget != Framebuffer::TEXTARGET_2D, GL_INVALID_OPERATION, RC_RET_VOID);
			else
			{
				TCU_CHECK(texObj->getType() == Texture::TYPE_CUBE_MAP);
				if (!deInRange32(fboTexTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X, Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
					RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
			}
		}

		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
		for (int ndx = 0; ndx < bindingRefCount; ndx++)
			releaseFboAttachmentReference(fboAttachment);
		fboAttachment = Framebuffer::Attachment();

		if (texObj)
		{
			fboAttachment.type			= Framebuffer::ATTACHMENTTYPE_TEXTURE;
			fboAttachment.name			= texObj->getName();
			fboAttachment.texTarget		= fboTexTarget;
			fboAttachment.level			= level;

			for (int ndx = 0; ndx < bindingRefCount; ndx++)
				acquireFboAttachmentReference(fboAttachment);
		}
	}
}

void ReferenceContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
{
	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
	{
		// Attach to both depth and stencil.
		framebufferTextureLayer(target, GL_DEPTH_ATTACHMENT,	texture, level, layer);
		framebufferTextureLayer(target, GL_STENCIL_ATTACHMENT,	texture, level, layer);
	}
	else
	{
		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
		Texture*						texObj			= DE_NULL;

		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
					target != GL_DRAW_FRAMEBUFFER	&&
					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);

		// Select binding point.
		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);

		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);

		if (texture != 0)
		{
			texObj = m_textures.find(texture);

			RC_IF_ERROR(!texObj,		GL_INVALID_OPERATION,	RC_RET_VOID);
			RC_IF_ERROR(level != 0,		GL_INVALID_VALUE,		RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.

			RC_IF_ERROR(texObj->getType() != Texture::TYPE_2D_ARRAY			&&
						texObj->getType() != Texture::TYPE_3D				&&
						texObj->getType() != Texture::TYPE_CUBE_MAP_ARRAY,				GL_INVALID_OPERATION,	RC_RET_VOID);

			if (texObj->getType() == Texture::TYPE_2D_ARRAY || texObj->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
			{
				RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_ARRAY_TEXTURE_LAYERS),		GL_INVALID_VALUE,		RC_RET_VOID);
				RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_TEXTURE_SIZE)),GL_INVALID_VALUE,		RC_RET_VOID);
			}
			else if	(texObj->getType() == Texture::TYPE_3D)
			{
				RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_3D_TEXTURE_SIZE),				GL_INVALID_VALUE,		RC_RET_VOID);
				RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_3D_TEXTURE_SIZE)),	GL_INVALID_VALUE,		RC_RET_VOID);
			}
		}

		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
		for (int ndx = 0; ndx < bindingRefCount; ndx++)
			releaseFboAttachmentReference(fboAttachment);
		fboAttachment = Framebuffer::Attachment();

		if (texObj)
		{
			fboAttachment.type			= Framebuffer::ATTACHMENTTYPE_TEXTURE;
			fboAttachment.name			= texObj->getName();
			fboAttachment.texTarget		= texLayeredTypeToTarget(texObj->getType());
			fboAttachment.level			= level;
			fboAttachment.layer			= layer;

			DE_ASSERT(fboAttachment.texTarget != Framebuffer::TEXTARGET_LAST);

			for (int ndx = 0; ndx < bindingRefCount; ndx++)
				acquireFboAttachmentReference(fboAttachment);
		}
	}
}

void ReferenceContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
{
	if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
	{
		// Attach both to depth and stencil.
		framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT,	renderbuffertarget, renderbuffer);
		framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT,	renderbuffertarget, renderbuffer);
	}
	else
	{
		Framebuffer::AttachmentPoint	point			= mapGLAttachmentPoint(attachment);
		Renderbuffer*					rbo				= DE_NULL;

		RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
					target != GL_DRAW_FRAMEBUFFER	&&
					target != GL_READ_FRAMEBUFFER,				GL_INVALID_ENUM,		RC_RET_VOID);
		RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST,	GL_INVALID_ENUM,		RC_RET_VOID);

		// Select binding point.
		rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
		RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);

		// If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
		int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
							+ (framebufferBinding == m_readFramebufferBinding ? 1 : 0);

		if (renderbuffer != 0)
		{
			rbo = m_renderbuffers.find(renderbuffer);

			RC_IF_ERROR(renderbuffertarget != GL_RENDERBUFFER,	GL_INVALID_ENUM,		RC_RET_VOID);
			RC_IF_ERROR(!rbo,									GL_INVALID_OPERATION,	RC_RET_VOID);
		}

		Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
		for (int ndx = 0; ndx < bindingRefCount; ndx++)
			releaseFboAttachmentReference(fboAttachment);
		fboAttachment = Framebuffer::Attachment();

		if (rbo)
		{
			fboAttachment.type	= Framebuffer::ATTACHMENTTYPE_RENDERBUFFER;
			fboAttachment.name	= rbo->getName();

			for (int ndx = 0; ndx < bindingRefCount; ndx++)
				acquireFboAttachmentReference(fboAttachment);
		}
	}
}

deUint32 ReferenceContext::checkFramebufferStatus (deUint32 target)
{
	RC_IF_ERROR(target != GL_FRAMEBUFFER		&&
				target != GL_DRAW_FRAMEBUFFER	&&
				target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, 0);

	// Select binding point.
	rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;

	// Default framebuffer is always complete.
	if (!framebufferBinding)
		return GL_FRAMEBUFFER_COMPLETE;

	int		width				= -1;
	int		height				= -1;
	bool	hasAttachment		= false;
	bool	attachmentComplete	= true;
	bool	dimensionsOk		= true;

	for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
	{
		const Framebuffer::Attachment&	attachment			= framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
		int								attachmentWidth		= 0;
		int								attachmentHeight	= 0;
		tcu::TextureFormat				attachmentFormat;

		if (attachment.type == Framebuffer::ATTACHMENTTYPE_TEXTURE)
		{
			const Texture*					texture	= m_textures.find(attachment.name);
			tcu::ConstPixelBufferAccess		level;
			TCU_CHECK(texture);

			if (attachment.texTarget == Framebuffer::TEXTARGET_2D)
			{
				DE_ASSERT(texture->getType() == Texture::TYPE_2D);
				const Texture2D* tex2D = static_cast<const Texture2D*>(texture);

				if (tex2D->hasLevel(attachment.level))
					level = tex2D->getLevel(attachment.level);
			}
			else if (deInRange32(attachment.texTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X,
													   Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
			{
				DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP);

				const TextureCube*	texCube	= static_cast<const TextureCube*>(texture);
				const tcu::CubeFace	face	= texTargetToFace(attachment.texTarget);
				TCU_CHECK(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));

				if (texCube->hasFace(attachment.level, face))
					level = texCube->getFace(attachment.level, face);
			}
			else if (attachment.texTarget == Framebuffer::TEXTARGET_2D_ARRAY)
			{
				DE_ASSERT(texture->getType() == Texture::TYPE_2D_ARRAY);
				const Texture2DArray* tex2DArr = static_cast<const Texture2DArray*>(texture);

				if (tex2DArr->hasLevel(attachment.level))
					level = tex2DArr->getLevel(attachment.level); // \note Slice doesn't matter here.
			}
			else if (attachment.texTarget == Framebuffer::TEXTARGET_3D)
			{
				DE_ASSERT(texture->getType() == Texture::TYPE_3D);
				const Texture3D* tex3D = static_cast<const Texture3D*>(texture);

				if (tex3D->hasLevel(attachment.level))
					level = tex3D->getLevel(attachment.level); // \note Slice doesn't matter here.
			}
			else if (attachment.texTarget == Framebuffer::TEXTARGET_CUBE_MAP_ARRAY)
			{
				DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY);
				const TextureCubeArray* texCubeArr = static_cast<const TextureCubeArray*>(texture);

				if (texCubeArr->hasLevel(attachment.level))
					level = texCubeArr->getLevel(attachment.level); // \note Slice doesn't matter here.
			}
			else
				TCU_FAIL("Framebuffer attached to a texture but no valid target specified");

			attachmentWidth		= level.getWidth();
			attachmentHeight	= level.getHeight();
			attachmentFormat	= level.getFormat();
		}
		else if (attachment.type == Framebuffer::ATTACHMENTTYPE_RENDERBUFFER)
		{
			const Renderbuffer* renderbuffer = m_renderbuffers.find(attachment.name);
			TCU_CHECK(renderbuffer);

			attachmentWidth		= renderbuffer->getWidth();
			attachmentHeight	= renderbuffer->getHeight();
			attachmentFormat	= renderbuffer->getFormat();
		}
		else
		{
			TCU_CHECK(attachment.type == Framebuffer::ATTACHMENTTYPE_LAST);
			continue; // Skip rest of checks.
		}

		if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0)
		{
			width			= attachmentWidth;
			height			= attachmentHeight;
			hasAttachment	= true;
		}
		else if (attachmentWidth != width || attachmentHeight != height)
			dimensionsOk = false;

		// Validate attachment point compatibility.
		switch (attachmentFormat.order)
		{
			case TextureFormat::R:
			case TextureFormat::RG:
			case TextureFormat::RGB:
			case TextureFormat::RGBA:
			case TextureFormat::sRGB:
			case TextureFormat::sRGBA:
				if (point != Framebuffer::ATTACHMENTPOINT_COLOR0)
					attachmentComplete = false;
				break;

			case TextureFormat::D:
				if (point != Framebuffer::ATTACHMENTPOINT_DEPTH)
					attachmentComplete = false;
				break;

			case TextureFormat::S:
				if (point != Framebuffer::ATTACHMENTPOINT_STENCIL)
					attachmentComplete = false;
				break;

			case TextureFormat::DS:
				if (point != Framebuffer::ATTACHMENTPOINT_DEPTH &&
					point != Framebuffer::ATTACHMENTPOINT_STENCIL)
					attachmentComplete = false;
				break;

			default:
				TCU_FAIL("Unsupported attachment channel order");
		}
	}

	if (!attachmentComplete)
		return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
	else if (!hasAttachment)
		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
	else if (!dimensionsOk)
		return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
	else
		return GL_FRAMEBUFFER_COMPLETE;
}

void ReferenceContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
{
	DE_UNREF(target && attachment && pname && params);
	TCU_CHECK(false); // \todo [pyry] Implement
}

void ReferenceContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
{
	TextureFormat format = glu::mapGLInternalFormat(internalformat);

	RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(!m_renderbufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(!deInRange32(width, 0, m_limits.maxRenderbufferSize) ||
				!deInRange32(height, 0, m_limits.maxRenderbufferSize),
				GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(format.order == TextureFormat::CHANNELORDER_LAST ||
				format.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	m_renderbufferBinding->setStorage(format, (int)width, (int)height);
}

void ReferenceContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
{
	// \todo [2012-04-07 pyry] Implement MSAA support.
	DE_UNREF(samples);
	renderbufferStorage(target, internalFormat, width, height);
}

tcu::PixelBufferAccess ReferenceContext::getFboAttachment (const rc::Framebuffer& framebuffer, rc::Framebuffer::AttachmentPoint point)
{
	const Framebuffer::Attachment& attachment = framebuffer.getAttachment(point);

	switch (attachment.type)
	{
		case Framebuffer::ATTACHMENTTYPE_TEXTURE:
		{
			Texture* texture = m_textures.find(attachment.name);
			TCU_CHECK(texture);

			if (texture->getType() == Texture::TYPE_2D)
			{
				if (Texture2D* texture2D = dynamic_cast<Texture2D*>(texture))
					return texture2D->getLevel(attachment.level);
				else
					return nullAccess();
			}
			else if (texture->getType() == Texture::TYPE_CUBE_MAP)
			{
				if (TextureCube* cubeMap = dynamic_cast<TextureCube*>(texture))
					return cubeMap->getFace(attachment.level, texTargetToFace(attachment.texTarget));
				else
					return nullAccess();
			}
			else if (texture->getType() == Texture::TYPE_2D_ARRAY	||
					 texture->getType() == Texture::TYPE_3D			||
					 texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
			{
				tcu::PixelBufferAccess level;

				if (texture->getType() == Texture::TYPE_2D_ARRAY)
				{
					if (Texture2DArray* texture2DArray = dynamic_cast<Texture2DArray*>(texture))
						level = texture2DArray->getLevel(attachment.level);
				}
				else if (texture->getType() == Texture::TYPE_3D)
				{
					if (Texture3D* texture3D = dynamic_cast<Texture3D*>(texture))
						level = texture3D->getLevel(attachment.level);
				}
				else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
				{
					if (TextureCubeArray* cubeArray = dynamic_cast<TextureCubeArray*>(texture))
						level = cubeArray->getLevel(attachment.level);
				}

				void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;

				return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
			}
			else
				return nullAccess();
		}

		case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
		{
			Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
			TCU_CHECK(rbo);

			return rbo->getAccess();
		}

		default:
			return nullAccess();
	}
}

const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
{
	const TextureUnit& unit = m_textureUnits[unitNdx];
	return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
}

const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
{
	const TextureUnit& unit = m_textureUnits[unitNdx];
	return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
}

static bool isValidBufferTarget (deUint32 target)
{
	switch (target)
	{
		case GL_ARRAY_BUFFER:
		case GL_COPY_READ_BUFFER:
		case GL_COPY_WRITE_BUFFER:
		case GL_DRAW_INDIRECT_BUFFER:
		case GL_ELEMENT_ARRAY_BUFFER:
		case GL_PIXEL_PACK_BUFFER:
		case GL_PIXEL_UNPACK_BUFFER:
		case GL_TRANSFORM_FEEDBACK_BUFFER:
		case GL_UNIFORM_BUFFER:
			return true;

		default:
			return false;
	}
}

void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
{
	DataBuffer** bindingPoint = DE_NULL;
	VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);

	switch (target)
	{
		case GL_ARRAY_BUFFER:				bindingPoint = &m_arrayBufferBinding;								break;
		case GL_COPY_READ_BUFFER:			bindingPoint = &m_copyReadBufferBinding;							break;
		case GL_COPY_WRITE_BUFFER:			bindingPoint = &m_copyWriteBufferBinding;							break;
		case GL_DRAW_INDIRECT_BUFFER:		bindingPoint = &m_drawIndirectBufferBinding;						break;
		case GL_ELEMENT_ARRAY_BUFFER:		bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding;		break;
		case GL_PIXEL_PACK_BUFFER:			bindingPoint = &m_pixelPackBufferBinding;							break;
		case GL_PIXEL_UNPACK_BUFFER:		bindingPoint = &m_pixelUnpackBufferBinding;							break;
		case GL_TRANSFORM_FEEDBACK_BUFFER:	bindingPoint = &m_transformFeedbackBufferBinding;					break;
		case GL_UNIFORM_BUFFER:				bindingPoint = &m_uniformBufferBinding;								break;
		default:
			DE_ASSERT(false);
			return;
	}

	if (*bindingPoint)
	{
		m_buffers.releaseReference(*bindingPoint);
		*bindingPoint = DE_NULL;
	}

	if (buffer)
		m_buffers.acquireReference(buffer);

	*bindingPoint = buffer;
}

DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
{
	const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);

	switch (target)
	{
		case GL_ARRAY_BUFFER:				return m_arrayBufferBinding;
		case GL_COPY_READ_BUFFER:			return m_copyReadBufferBinding;
		case GL_COPY_WRITE_BUFFER:			return m_copyWriteBufferBinding;
		case GL_DRAW_INDIRECT_BUFFER:		return m_drawIndirectBufferBinding;
		case GL_ELEMENT_ARRAY_BUFFER:		return vertexArrayObject->m_elementArrayBufferBinding;
		case GL_PIXEL_PACK_BUFFER:			return m_pixelPackBufferBinding;
		case GL_PIXEL_UNPACK_BUFFER:		return m_pixelUnpackBufferBinding;
		case GL_TRANSFORM_FEEDBACK_BUFFER:	return m_transformFeedbackBufferBinding;
		case GL_UNIFORM_BUFFER:				return m_uniformBufferBinding;
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
{
	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);

	rc::DataBuffer*	bufObj	= DE_NULL;

	if (buffer != 0)
	{
		bufObj = m_buffers.find(buffer);
		if (!bufObj)
		{
			bufObj = new DataBuffer(buffer);
			m_buffers.insert(bufObj);
		}
	}

	setBufferBinding(target, bufObj);
}

void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
{
	RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);

	for (int ndx = 0; ndx < numBuffers; ndx++)
		buffers[ndx] = m_buffers.allocateName();
}

void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
{
	RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);

	for (int ndx = 0; ndx < numBuffers; ndx++)
	{
		deUint32	buffer	= buffers[ndx];
		DataBuffer*	bufObj	= DE_NULL;

		if (buffer == 0)
			continue;

		bufObj = m_buffers.find(buffer);

		if (bufObj)
			deleteBuffer(bufObj);
	}
}

void ReferenceContext::deleteBuffer (DataBuffer* buffer)
{
	static const deUint32 bindingPoints[] =
	{
		GL_ARRAY_BUFFER,
		GL_COPY_READ_BUFFER,
		GL_COPY_WRITE_BUFFER,
		GL_DRAW_INDIRECT_BUFFER,
		GL_ELEMENT_ARRAY_BUFFER,
		GL_PIXEL_PACK_BUFFER,
		GL_PIXEL_UNPACK_BUFFER,
		GL_TRANSFORM_FEEDBACK_BUFFER,
		GL_UNIFORM_BUFFER
	};

	for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
	{
		if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
			setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
	}

	{
		vector<VertexArray*> vertexArrays;
		m_vertexArrays.getAll(vertexArrays);
		vertexArrays.push_back(&m_clientVertexArray);

		for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
		{
			if ((*i)->m_elementArrayBufferBinding == buffer)
			{
				m_buffers.releaseReference(buffer);
				(*i)->m_elementArrayBufferBinding = DE_NULL;
			}

			for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
			{
				if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
				{
					m_buffers.releaseReference(buffer);
					(*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
					(*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
				}
			}
		}
	}

	DE_ASSERT(buffer->getRefCount() == 1);
	m_buffers.releaseReference(buffer);
}

void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
{
	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);

	DE_UNREF(usage);

	DataBuffer* buffer = getBufferBinding(target);
	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);

	DE_ASSERT((deIntptr)(int)size == size);
	buffer->setStorage((int)size);
	if (data)
		deMemcpy(buffer->getData(), data, (int)size);
}

void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
{
	RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);

	DataBuffer* buffer = getBufferBinding(target);

	RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);

	deMemcpy(buffer->getData()+offset, data, (int)size);
}

void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
{
	m_clearColor = Vec4(de::clamp(red,	0.0f, 1.0f),
						de::clamp(green,	0.0f, 1.0f),
						de::clamp(blue,	0.0f, 1.0f),
						de::clamp(alpha,	0.0f, 1.0f));
}

void ReferenceContext::clearDepthf (float depth)
{
	m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
}

void ReferenceContext::clearStencil (int stencil)
{
	m_clearStencil = stencil;
}

void ReferenceContext::scissor (int x, int y, int width, int height)
{
	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
	m_scissorBox = IVec4(x, y, width, height);
}

void ReferenceContext::enable (deUint32 cap)
{
	switch (cap)
	{
		case GL_BLEND:					m_blendEnabled				= true;	break;
		case GL_SCISSOR_TEST:			m_scissorEnabled			= true;	break;
		case GL_DEPTH_TEST:				m_depthTestEnabled			= true;	break;
		case GL_STENCIL_TEST:			m_stencilTestEnabled		= true;	break;
		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= true;	break;

		case GL_FRAMEBUFFER_SRGB:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_sRGBUpdateEnabled = true;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_DEPTH_CLAMP:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_depthClampEnabled = true;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_DITHER:
			// Not implemented - just ignored.
			break;

		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
			if (!glu::isContextTypeGLCore(getType()))
			{
				m_primitiveRestartFixedIndex = true;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_PRIMITIVE_RESTART:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_primitiveRestartSettableIndex = true;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		default:
			setError(GL_INVALID_ENUM);
			break;
	}
}

void ReferenceContext::disable (deUint32 cap)
{
	switch (cap)
	{
		case GL_BLEND:					m_blendEnabled				= false;	break;
		case GL_SCISSOR_TEST:			m_scissorEnabled			= false;	break;
		case GL_DEPTH_TEST:				m_depthTestEnabled			= false;	break;
		case GL_STENCIL_TEST:			m_stencilTestEnabled		= false;	break;
		case GL_POLYGON_OFFSET_FILL:	m_polygonOffsetFillEnabled	= false;	break;

		case GL_FRAMEBUFFER_SRGB:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_sRGBUpdateEnabled = false;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_DEPTH_CLAMP:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_depthClampEnabled = false;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_DITHER:
			break;

		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
			if (!glu::isContextTypeGLCore(getType()))
			{
				m_primitiveRestartFixedIndex = false;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		case GL_PRIMITIVE_RESTART:
			if (glu::isContextTypeGLCore(getType()))
			{
				m_primitiveRestartSettableIndex = false;
				break;
			}
			setError(GL_INVALID_ENUM);
			break;

		default:
			setError(GL_INVALID_ENUM);
			break;
	}
}

static bool isValidCompareFunc (deUint32 func)
{
	switch (func)
	{
		case GL_NEVER:
		case GL_LESS:
		case GL_LEQUAL:
		case GL_GREATER:
		case GL_GEQUAL:
		case GL_EQUAL:
		case GL_NOTEQUAL:
		case GL_ALWAYS:
			return true;

		default:
			return false;
	}
}

static bool isValidStencilOp (deUint32 op)
{
	switch (op)
	{
		case GL_KEEP:
		case GL_ZERO:
		case GL_REPLACE:
		case GL_INCR:
		case GL_INCR_WRAP:
		case GL_DECR:
		case GL_DECR_WRAP:
		case GL_INVERT:
			return true;

		default:
			return false;
	}
}

void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
{
	stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
}

void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
{
	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;

	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);

	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
	{
		if ((type == rr::FACETYPE_FRONT && setFront) ||
			(type == rr::FACETYPE_BACK && setBack))
		{
			m_stencil[type].func	= func;
			m_stencil[type].ref		= ref;
			m_stencil[type].opMask	= mask;
		}
	}
}

void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
{
	stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
}

void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
{
	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;

	RC_IF_ERROR(!isValidStencilOp(sfail)	||
				!isValidStencilOp(dpfail)	||
				!isValidStencilOp(dppass),
				GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);

	for (int type = 0; type < rr::FACETYPE_LAST; ++type)
	{
		if ((type == rr::FACETYPE_FRONT && setFront) ||
			(type == rr::FACETYPE_BACK && setBack))
		{
			m_stencil[type].opStencilFail	= sfail;
			m_stencil[type].opDepthFail		= dpfail;
			m_stencil[type].opDepthPass		= dppass;
		}
	}
}

void ReferenceContext::depthFunc (deUint32 func)
{
	RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
	m_depthFunc = func;
}

void ReferenceContext::depthRangef (float n, float f)
{
	m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
	m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
}

void ReferenceContext::depthRange (double n, double f)
{
	depthRangef((float)n, (float)f);
}

void ReferenceContext::polygonOffset (float factor, float units)
{
	m_polygonOffsetFactor = factor;
	m_polygonOffsetUnits = units;
}

void ReferenceContext::provokingVertex (deUint32 convention)
{
	// only in core
	DE_ASSERT(glu::isContextTypeGLCore(getType()));

	switch (convention)
	{
		case GL_FIRST_VERTEX_CONVENTION:	m_provokingFirstVertexConvention = true; break;
		case GL_LAST_VERTEX_CONVENTION:		m_provokingFirstVertexConvention = false; break;

		default:
			RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
	}
}

void ReferenceContext::primitiveRestartIndex (deUint32 index)
{
	// only in core
	DE_ASSERT(glu::isContextTypeGLCore(getType()));
	m_primitiveRestartIndex = index;
}

static inline bool isValidBlendEquation (deUint32 mode)
{
	return mode == GL_FUNC_ADD				||
		   mode == GL_FUNC_SUBTRACT			||
		   mode == GL_FUNC_REVERSE_SUBTRACT	||
		   mode == GL_MIN					||
		   mode == GL_MAX;
}

static bool isValidBlendFactor (deUint32 factor)
{
	switch (factor)
	{
		case GL_ZERO:
		case GL_ONE:
		case GL_SRC_COLOR:
		case GL_ONE_MINUS_SRC_COLOR:
		case GL_DST_COLOR:
		case GL_ONE_MINUS_DST_COLOR:
		case GL_SRC_ALPHA:
		case GL_ONE_MINUS_SRC_ALPHA:
		case GL_DST_ALPHA:
		case GL_ONE_MINUS_DST_ALPHA:
		case GL_CONSTANT_COLOR:
		case GL_ONE_MINUS_CONSTANT_COLOR:
		case GL_CONSTANT_ALPHA:
		case GL_ONE_MINUS_CONSTANT_ALPHA:
		case GL_SRC_ALPHA_SATURATE:
			return true;

		default:
			return false;
	}
}

void ReferenceContext::blendEquation (deUint32 mode)
{
	RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);

	m_blendModeRGB		= mode;
	m_blendModeAlpha	= mode;
}

void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
{
	RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
				!isValidBlendEquation(modeAlpha),
				GL_INVALID_ENUM, RC_RET_VOID);

	m_blendModeRGB		= modeRGB;
	m_blendModeAlpha	= modeAlpha;
}

void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
{
	RC_IF_ERROR(!isValidBlendFactor(src) ||
				!isValidBlendFactor(dst),
				GL_INVALID_ENUM, RC_RET_VOID);

	m_blendFactorSrcRGB		= src;
	m_blendFactorSrcAlpha	= src;
	m_blendFactorDstRGB		= dst;
	m_blendFactorDstAlpha	= dst;
}

void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
{
	RC_IF_ERROR(!isValidBlendFactor(srcRGB)		||
				!isValidBlendFactor(dstRGB)		||
				!isValidBlendFactor(srcAlpha)	||
				!isValidBlendFactor(dstAlpha),
				GL_INVALID_ENUM, RC_RET_VOID);

	m_blendFactorSrcRGB		= srcRGB;
	m_blendFactorSrcAlpha	= srcAlpha;
	m_blendFactorDstRGB		= dstRGB;
	m_blendFactorDstAlpha	= dstAlpha;
}

void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
{
	m_blendColor = Vec4(de::clamp(red,	0.0f, 1.0f),
						de::clamp(green,	0.0f, 1.0f),
						de::clamp(blue,	0.0f, 1.0f),
						de::clamp(alpha,	0.0f, 1.0f));
}

void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
{
	m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
}

void ReferenceContext::depthMask (deBool mask)
{
	m_depthMask = !!mask;
}

void ReferenceContext::stencilMask (deUint32 mask)
{
	stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
}

void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
{
	const bool	setFront	= face == GL_FRONT || face == GL_FRONT_AND_BACK;
	const bool	setBack		= face == GL_BACK || face == GL_FRONT_AND_BACK;

	RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);

	if (setFront)	m_stencil[rr::FACETYPE_FRONT].writeMask	= mask;
	if (setBack)	m_stencil[rr::FACETYPE_BACK].writeMask	= mask;
}

static int getNumStencilBits (const tcu::TextureFormat& format)
{
	switch (format.order)
	{
		case tcu::TextureFormat::S:
			switch (format.type)
			{
				case tcu::TextureFormat::UNSIGNED_INT8:		return 8;
				case tcu::TextureFormat::UNSIGNED_INT16:	return 16;
				case tcu::TextureFormat::UNSIGNED_INT32:	return 32;
				default:
					DE_ASSERT(false);
					return 0;
			}

		case tcu::TextureFormat::DS:
			switch (format.type)
			{
				case tcu::TextureFormat::UNSIGNED_INT_24_8:				return 8;
				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return 8;
				default:
					DE_ASSERT(false);
					return 0;
			}

		default:
			DE_ASSERT(false);
			return 0;
	}
}

static inline deUint32 maskStencil (int numBits, deUint32 s)
{
	return s & deBitMask32(0, numBits);
}

static inline void writeMaskedStencil (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, deUint32 stencil, deUint32 writeMask)
{
	DE_ASSERT(access.raw().getFormat().order == tcu::TextureFormat::S);

	const deUint32 oldVal = access.raw().getPixelUint(s, x, y).x();
	const deUint32 newVal = (oldVal & ~writeMask) | (stencil & writeMask);
	access.raw().setPixel(tcu::UVec4(newVal, 0u, 0u, 0u), s, x, y);
}

static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
{
	access.raw().setPixDepth(depth, s, x, y);
}

static rr::MultisamplePixelBufferAccess getDepthMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
{
	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_DEPTH));
}

static rr::MultisamplePixelBufferAccess getStencilMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
{
	return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_STENCIL));
}

deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
{
	if (mask & GL_COLOR_BUFFER_BIT)
	{
		rr::MultisampleConstPixelBufferAccess	src			= rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
		tcu::PixelBufferAccess					dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
		tcu::TextureChannelClass				dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
		bool									dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
															  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
															  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		bool									srcIsSRGB	= tcu::isSRGB(src.raw().getFormat());
		bool									dstIsSRGB	= tcu::isSRGB(dst.getFormat());
		const bool								convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());

		if (!convertSRGB)
		{
			tcu::ConstPixelBufferAccess	srcRaw	= src.raw();
			tcu::TextureFormat			srcFmt	= toNonSRGBFormat(srcRaw.getFormat());

			srcRaw	= tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
			src		= rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);

			dst		= tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
		}

		for (int x = 0; x < dstRect.z(); ++x)
		for (int y = 0; y < dstRect.w(); ++y)
		{
			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);

			if (dstIsFloat || srcIsSRGB)
			{
				Vec4 p = src.raw().getPixel(0, srcX,srcY);
				dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
			}
			else
				dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
		}
	}

	if (mask & GL_DEPTH_BUFFER_BIT)
	{
		rr::MultisampleConstPixelBufferAccess	src	= rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
		rr::MultisamplePixelBufferAccess		dst	= rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());

		for (int x = 0; x < dstRect.z(); ++x)
		for (int y = 0; y < dstRect.w(); ++y)
		{
			int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
			int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);

			writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
		}
	}

	if (mask & GL_STENCIL_BUFFER_BIT)
	{
		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));

		for (int x = 0; x < dstRect.z(); ++x)
		for (int y = 0; y < dstRect.w(); ++y)
		{
			int			srcX		= (flipX) ? (srcRect.z() - x - 1) : (x);
			int			srcY		= (flipY) ? (srcRect.z() - y - 1) : (y);
			deUint32	srcStencil	= src.raw().getPixelUint(0, srcX, srcY).x();

			writeMaskedStencil(dst, 0, x, y, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
		}
	}

	return GL_NO_ERROR;
}

void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
{
	// p0 in inclusive, p1 exclusive.
	// Negative width/height means swap.
	bool	swapSrcX	= srcX1 < srcX0;
	bool	swapSrcY	= srcY1 < srcY0;
	bool	swapDstX	= dstX1 < dstX0;
	bool	swapDstY	= dstY1 < dstY0;
	int		srcW		= de::abs(srcX1-srcX0);
	int		srcH		= de::abs(srcY1-srcY0);
	int		dstW		= de::abs(dstX1-dstX0);
	int		dstH		= de::abs(dstY1-dstY0);
	bool	scale		= srcW != dstW || srcH != dstH;
	int		srcOriginX	= swapSrcX ? srcX1 : srcX0;
	int		srcOriginY	= swapSrcY ? srcY1 : srcY0;
	int		dstOriginX	= swapDstX ? dstX1 : dstX0;
	int		dstOriginY	= swapDstY ? dstY1 : dstY0;
	IVec4	srcRect		= IVec4(srcOriginX, srcOriginY, srcW, srcH);
	IVec4	dstRect		= IVec4(dstOriginX, dstOriginY, dstW, dstH);

	RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);

	// Validate that both targets are complete.
	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
				checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);

	// Check samples count is valid
	RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);

	// Check size restrictions of multisampled case
	if (getReadColorbuffer().getNumSamples() != 1)
	{
		// Src and Dst rect dimensions must be the same
		RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);

		// Framebuffer formats must match
		if (mask & GL_COLOR_BUFFER_BIT)		RC_IF_ERROR(getReadColorbuffer().raw().getFormat()   != getDrawColorbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
		if (mask & GL_DEPTH_BUFFER_BIT)		RC_IF_ERROR(getReadDepthbuffer().raw().getFormat()   != getDrawDepthbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
		if (mask & GL_STENCIL_BUFFER_BIT)	RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
	}

	// Compute actual source rect.
	srcRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadColorbuffer()))	: srcRect;
	srcRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(srcRect, getBufferRect(getReadDepthbuffer()))	: srcRect;
	srcRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(srcRect, getBufferRect(getReadStencilbuffer()))	: srcRect;

	// Compute destination rect.
	dstRect = (mask & GL_COLOR_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawColorbuffer()))	: dstRect;
	dstRect = (mask & GL_DEPTH_BUFFER_BIT)		? intersect(dstRect, getBufferRect(getDrawDepthbuffer()))	: dstRect;
	dstRect = (mask & GL_STENCIL_BUFFER_BIT)	? intersect(dstRect, getBufferRect(getDrawStencilbuffer()))	: dstRect;
	dstRect = m_scissorEnabled					? intersect(dstRect, m_scissorBox)							: dstRect;

	if (isEmpty(srcRect) || isEmpty(dstRect))
		return; // Don't attempt copy.

	// Multisampled read buffer is a special case
	if (getReadColorbuffer().getNumSamples() != 1)
	{
		deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);

		if (error != GL_NO_ERROR)
			setError(error);

		return;
	}

	// \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1

	// Coordinate transformation:
	// Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
	tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
						* tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
										 (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
										 1.0f))
						* tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));

	if (mask & GL_COLOR_BUFFER_BIT)
	{
		tcu::ConstPixelBufferAccess		src			= tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
		tcu::PixelBufferAccess			dst			= tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
		tcu::TextureChannelClass		dstClass	= tcu::getTextureChannelClass(dst.getFormat().type);
		bool							dstIsFloat	= dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT		||
													  dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	||
													  dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		tcu::Sampler::FilterMode		sFilter		= (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
		tcu::Sampler					sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
													 sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
		bool							srcIsSRGB	= tcu::isSRGB(src.getFormat());
		bool							dstIsSRGB	= tcu::isSRGB(dst.getFormat());
		const bool						convertSRGB	= m_sRGBUpdateEnabled && glu::isContextTypeES(getType());

		if (!convertSRGB)
		{
			src	= tcu::ConstPixelBufferAccess	(toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
			dst	= tcu::PixelBufferAccess		(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
		}

		// \note We don't check for unsupported conversions, unlike spec requires.

		for (int yo = 0; yo < dstRect.w(); yo++)
		{
			for (int xo = 0; xo < dstRect.z(); xo++)
			{
				float	dX	= (float)xo + 0.5f;
				float	dY	= (float)yo + 0.5f;

				// \note Only affine part is used.
				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);

				// do not copy pixels outside the modified source region (modified by buffer intersection)
				if (sX < 0.0f || sX >= (float)srcRect.z() ||
					sY < 0.0f || sY >= (float)srcRect.w())
					continue;

				if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
				{
					Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
					dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
				}
				else
					dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
			}
		}
	}

	if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
	{
		rr::MultisampleConstPixelBufferAccess	src		= getDepthMultisampleAccess(rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
		rr::MultisamplePixelBufferAccess		dst		= getDepthMultisampleAccess(rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));

		for (int yo = 0; yo < dstRect.w(); yo++)
		{
			for (int xo = 0; xo < dstRect.z(); xo++)
			{
				const int sampleNdx = 0; // multisample read buffer case is already handled

				float	dX	= (float)xo + 0.5f;
				float	dY	= (float)yo + 0.5f;
				float	sX	= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
				float	sY	= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);

				writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixDepth(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)));
			}
		}
	}

	if (mask & GL_STENCIL_BUFFER_BIT)
	{
		rr::MultisampleConstPixelBufferAccess	src	= getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
		rr::MultisamplePixelBufferAccess		dst	= getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));

		for (int yo = 0; yo < dstRect.w(); yo++)
		{
			for (int xo = 0; xo < dstRect.z(); xo++)
			{
				const int	sampleNdx = 0; // multisample read buffer case is already handled

				float		dX			= (float)xo + 0.5f;
				float		dY			= (float)yo + 0.5f;
				float		sX			= transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
				float		sY			= transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
				deUint32	srcStencil	= src.raw().getPixelUint(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x();

				writeMaskedStencil(dst, sampleNdx, xo, yo, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
			}
		}
	}
}

void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
{
	RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);

	// \todo [2012-07-17 pyry] Support multiple color attachments.

	const Vec4		colorClearValue		(0.0f);
	const float		depthClearValue		= 1.0f;
	const int		stencilClearValue	= 0;

	bool			isFboBound			= m_drawFramebufferBinding != DE_NULL;
	bool			discardBuffers[3]	= { false, false, false }; // Color, depth, stencil

	for (int attNdx = 0; attNdx < numAttachments; attNdx++)
	{
		bool	isColor			= attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0		: GL_COLOR);
		bool	isDepth			= attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT		: GL_DEPTH);
		bool	isStencil		= attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT	: GL_STENCIL);
		bool	isDepthStencil	= isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;

		RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);

		if (isColor)						discardBuffers[0] = true;
		if (isDepth || isDepthStencil)		discardBuffers[1] = true;
		if (isStencil || isDepthStencil)	discardBuffers[2] = true;
	}

	for (int ndx = 0; ndx < 3; ndx++)
	{
		if (!discardBuffers[ndx])
			continue;

		bool								isColor					= ndx == 0;
		bool								isDepth					= ndx == 1;
		bool								isStencil				= ndx == 2;
		rr::MultisamplePixelBufferAccess	buf						= isColor ? getDrawColorbuffer()								:
																	  isDepth ? getDepthMultisampleAccess(getDrawDepthbuffer())		:
																				getStencilMultisampleAccess(getDrawStencilbuffer());

		if (isEmpty(buf))
			continue;

		tcu::IVec4							area					= intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
		rr::MultisamplePixelBufferAccess	access					= rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());

		if (isColor)
			rr::clear(access, colorClearValue);
		else if (isDepth)
			rr::clear(access, tcu::Vec4(depthClearValue));
		else if (isStencil)
			rr::clear(access, tcu::IVec4(stencilClearValue));
	}
}

void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
{
	// \todo [2012-07-17 pyry] Support multiple color attachments.
	rr::MultisampleConstPixelBufferAccess	colorBuf0	= getDrawColorbuffer();
	rr::MultisampleConstPixelBufferAccess	depthBuf	= getDrawDepthbuffer();
	rr::MultisampleConstPixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
	int										width		= 0;
	int										height		= 0;

	width = de::max(width, colorBuf0.raw().getHeight());
	width = de::max(width, depthBuf.raw().getHeight());
	width = de::max(width, stencilBuf.raw().getHeight());

	height = de::max(height, colorBuf0.raw().getDepth());
	height = de::max(height, depthBuf.raw().getDepth());
	height = de::max(height, stencilBuf.raw().getDepth());

	invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
}

void ReferenceContext::clear (deUint32 buffers)
{
	RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);

	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
	rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
	rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
	IVec4								baseArea	= m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
	IVec4								colorArea	= intersect(baseArea, getBufferRect(colorBuf0));
	IVec4								depthArea	= intersect(baseArea, getBufferRect(depthBuf));
	IVec4								stencilArea	= intersect(baseArea, getBufferRect(stencilBuf));
	bool								hasColor0	= !isEmpty(colorArea);
	bool								hasDepth	= !isEmpty(depthArea);
	bool								hasStencil	= !isEmpty(stencilArea);

	if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
	{
		rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
		bool								isSRGB		= tcu::isSRGB(colorBuf0.raw().getFormat());
		Vec4								c			= (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];

		if (!maskUsed)
			rr::clear(access, c);
		else if (!maskZero)
		{
			for (int y = 0; y < access.raw().getDepth(); y++)
				for (int x = 0; x < access.raw().getHeight(); x++)
					for (int s = 0; s < access.getNumSamples(); s++)
						access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
		}
		// else all channels masked out
	}

	if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
	{
		rr::MultisamplePixelBufferAccess access = getDepthMultisampleAccess(rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w()));
		rr::clearDepth(access, m_clearDepth);
	}

	if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
	{
		rr::MultisamplePixelBufferAccess	access					= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w()));
		int									stencilBits				= getNumStencilBits(stencilBuf.raw().getFormat());
		int									stencil					= maskStencil(stencilBits, m_clearStencil);

		if ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u))
		{
			// Slow path where depth or stencil is masked out in write.
			for (int y = 0; y < access.raw().getDepth(); y++)
				for (int x = 0; x < access.raw().getHeight(); x++)
					for (int s = 0; s < access.getNumSamples(); s++)
						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
		}
		else
			rr::clearStencil(access, stencil);
	}
}

void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
{
	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.

	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);

	if (buffer == GL_COLOR)
	{
		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));

		if (!isEmpty(area) && !maskZero)
		{
			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
			IVec4								color		(value[0], value[1], value[2], value[3]);

			if (!maskUsed)
				rr::clear(access, color);
			else
			{
				for (int y = 0; y < access.raw().getDepth(); y++)
					for (int x = 0; x < access.raw().getHeight(); x++)
						for (int s = 0; s < access.getNumSamples(); s++)
							access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
			}
		}
	}
	else
	{
		TCU_CHECK_INTERNAL(buffer == GL_STENCIL);

		rr::MultisamplePixelBufferAccess	stencilBuf	= getDrawStencilbuffer();
		IVec4								area		= intersect(baseArea, getBufferRect(stencilBuf));

		if (!isEmpty(area) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
		{
			rr::MultisamplePixelBufferAccess	access		= getStencilMultisampleAccess(rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w()));
			int									stencil		= value[0];

			for (int y = 0; y < access.raw().getDepth(); y++)
				for (int x = 0; x < access.raw().getHeight(); x++)
					for (int s = 0; s < access.getNumSamples(); s++)
						writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
		}
	}
}

void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
{
	RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.

	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);

	if (buffer == GL_COLOR)
	{
		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));

		if (!isEmpty(area) && !maskZero)
		{
			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
			Vec4								color		(value[0], value[1], value[2], value[3]);

			if (m_sRGBUpdateEnabled && tcu::isSRGB(access.raw().getFormat()))
				color = tcu::linearToSRGB(color);

			if (!maskUsed)
				rr::clear(access, color);
			else
			{
				for (int y = 0; y < access.raw().getDepth(); y++)
					for (int x = 0; x < access.raw().getHeight(); x++)
						for (int s = 0; s < access.getNumSamples(); s++)
							access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
			}
		}
	}
	else
	{
		TCU_CHECK_INTERNAL(buffer == GL_DEPTH);

		rr::MultisamplePixelBufferAccess	depthBuf	= getDrawDepthbuffer();
		IVec4								area		= intersect(baseArea, getBufferRect(depthBuf));

		if (!isEmpty(area) && m_depthMask)
		{
			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
			float								depth		= value[0];

			rr::clearDepth(access, depth);
		}
	}
}

void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
{
	RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.

	IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);

	TCU_CHECK_INTERNAL(buffer == GL_COLOR);
	{
		rr::MultisamplePixelBufferAccess	colorBuf	= getDrawColorbuffer();
		bool								maskUsed	= !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
		bool								maskZero	= !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
		IVec4								area		= intersect(baseArea, getBufferRect(colorBuf));

		if (!isEmpty(area) && !maskZero)
		{
			rr::MultisamplePixelBufferAccess	access		= rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
			tcu::UVec4							color		(value[0], value[1], value[2], value[3]);

			if (!maskUsed)
				rr::clear(access, color.asInt());
			else
			{
				for (int y = 0; y < access.raw().getDepth(); y++)
					for (int x = 0; x < access.raw().getHeight(); x++)
						for (int s = 0; s < access.getNumSamples(); s++)
							access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
			}
		}
	}
}

void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
{
	RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
	clearBufferfv(GL_DEPTH, drawbuffer, &depth);
	clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
}

void ReferenceContext::bindVertexArray (deUint32 array)
{
	rc::VertexArray* vertexArrayObject = DE_NULL;

	if (array != 0)
	{
		vertexArrayObject = m_vertexArrays.find(array);
		if (!vertexArrayObject)
		{
			vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
			m_vertexArrays.insert(vertexArrayObject);
		}
	}

	// Create new references
	if (vertexArrayObject)
		m_vertexArrays.acquireReference(vertexArrayObject);

	// Remove old references
	if (m_vertexArrayBinding)
		m_vertexArrays.releaseReference(m_vertexArrayBinding);

	m_vertexArrayBinding = vertexArrayObject;
}

void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
{
	RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);

	for (int ndx = 0; ndx < numArrays; ndx++)
		vertexArrays[ndx] = m_vertexArrays.allocateName();
}

void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
{
	for (int i = 0; i < numArrays; i++)
	{
		deUint32		name		= vertexArrays[i];
		VertexArray*	vertexArray	= name ? m_vertexArrays.find(name) : DE_NULL;

		if (vertexArray)
			deleteVertexArray(vertexArray);
	}
}

void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
{
	const bool allowBGRA	= !glu::isContextTypeES(getType());
	const int effectiveSize	= (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);

	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
				type != GL_INT					&&	type != GL_UNSIGNED_INT		&&
				type != GL_FIXED				&&	type != GL_DOUBLE			&&
				type != GL_FLOAT				&&	type != GL_HALF_FLOAT		&&
				type != GL_INT_2_10_10_10_REV	&&	type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
	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);
	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
	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);
	RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);

	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);

	vao.m_arrays[index].size			= rawSize;
	vao.m_arrays[index].stride			= stride;
	vao.m_arrays[index].type			= type;
	vao.m_arrays[index].normalized		= normalized == GL_TRUE;
	vao.m_arrays[index].integer			= false;
	vao.m_arrays[index].pointer			= pointer;

	// acquire new reference
	if (m_arrayBufferBinding)
		m_buffers.acquireReference(m_arrayBufferBinding);

	// release old reference
	if (vao.m_arrays[index].bufferBinding)
		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);

	vao.m_arrays[index].bufferDeleted	= false;
	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
}

void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(type != GL_BYTE					&&	type != GL_UNSIGNED_BYTE	&&
				type != GL_SHORT				&&	type != GL_UNSIGNED_SHORT	&&
				type != GL_INT					&&	type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
	RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
	RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);

	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);

	vao.m_arrays[index].size			= size;
	vao.m_arrays[index].stride			= stride;
	vao.m_arrays[index].type			= type;
	vao.m_arrays[index].normalized		= false;
	vao.m_arrays[index].integer			= true;
	vao.m_arrays[index].pointer			= pointer;

	// acquire new reference
	if (m_arrayBufferBinding)
		m_buffers.acquireReference(m_arrayBufferBinding);

	// release old reference
	if (vao.m_arrays[index].bufferBinding)
		m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);

	vao.m_arrays[index].bufferDeleted	= false;
	vao.m_arrays[index].bufferBinding	= m_arrayBufferBinding;
}

void ReferenceContext::enableVertexAttribArray (deUint32 index)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
	vao.m_arrays[index].enabled = true;
}

void ReferenceContext::disableVertexAttribArray (deUint32 index)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
	vao.m_arrays[index].enabled = false;
}

void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
	vao.m_arrays[index].divisor = divisor;
}

void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
}

void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
}

void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
}

void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
}

void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
}

void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
{
	RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);

	m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
}

deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
{
	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);

	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);

	if (name)
	{
		std::string nameString(name);

		for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
			if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
				return (int)ndx;
	}

	return -1;
}

void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
{
	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);

	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;

	if (location == -1)
		return;

	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.

	{
		const int scalarSize = glu::getDataTypeScalarSize(type);
		DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
		deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
	}
}

void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
{
	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);

	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;

	if (location == -1)
		return;

	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.

	switch (uniforms[location].type)
	{
		case glu::TYPE_INT:		uniforms[location].value.i = *v;	return;

		// \note texture unit is stored to value
		case glu::TYPE_SAMPLER_2D:
		case glu::TYPE_UINT_SAMPLER_2D:
		case glu::TYPE_INT_SAMPLER_2D:
		case glu::TYPE_SAMPLER_CUBE:
		case glu::TYPE_UINT_SAMPLER_CUBE:
		case glu::TYPE_INT_SAMPLER_CUBE:
		case glu::TYPE_SAMPLER_2D_ARRAY:
		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
		case glu::TYPE_SAMPLER_3D:
		case glu::TYPE_UINT_SAMPLER_3D:
		case glu::TYPE_INT_SAMPLER_3D:
		case glu::TYPE_SAMPLER_CUBE_ARRAY:
		case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
		case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
			uniforms[location].value.i = *v;
			return;

		default:
			setError(GL_INVALID_OPERATION);
			return;
	}
}

void ReferenceContext::uniform1f (deInt32 location, const float v0)
{
	uniform1fv(location, 1, &v0);
}

void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
{
	uniform1iv(location, 1, &v0);
}

void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
{
	uniformv(location, glu::TYPE_FLOAT, count, v);
}

void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
{
	uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
}

void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
{
	uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
}

void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
{
	uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
}

void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
{
	uniformv(location, glu::TYPE_INT_VEC2, count, v);
}

void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
{
	uniformv(location, glu::TYPE_INT_VEC3, count, v);
}

void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
{
	uniformv(location, glu::TYPE_INT_VEC4, count, v);
}

void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
{
	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);

	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;

	if (location == -1)
		return;

	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);

	if (count == 0)
		return;

	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);

	switch (uniforms[location].type)
	{
		case glu::TYPE_FLOAT_MAT3:
			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);

			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
				for (int row = 0; row < 3; ++row)
				for (int col = 0; col < 3; ++col)
					uniforms[location].value.m3[row*3+col] = value[col*3+row];
			else // input is row major
				for (int row = 0; row < 3; ++row)
				for (int col = 0; col < 3; ++col)
					uniforms[location].value.m3[row*3+col] = value[row*3+col];

			break;

		default:
			setError(GL_INVALID_OPERATION);
			return;
	}
}

void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
{
	RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);

	std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;

	if (location == -1)
		return;

	RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);

	if (count == 0)
		return;

	RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);

	switch (uniforms[location].type)
	{
		case glu::TYPE_FLOAT_MAT4:
			RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);

			if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
				for (int row = 0; row < 4; ++row)
				for (int col = 0; col < 4; ++col)
					uniforms[location].value.m4[row*3+col] = value[col*3+row];
			else // input is row major
				for (int row = 0; row < 4; ++row)
				for (int col = 0; col < 4; ++col)
					uniforms[location].value.m4[row*3+col] = value[row*3+col];

			break;

		default:
			setError(GL_INVALID_OPERATION);
			return;
	}
}

deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
{
	ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
	RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);

	std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;

	for (size_t i = 0; i < uniforms.size(); ++i)
		if (name && deStringEqual(uniforms[i].name.c_str(), name))
			return (int)i;

	return -1;
}

void ReferenceContext::lineWidth (float w)
{
	RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
	m_lineWidth = w;
}

void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
{
	if (m_vertexArrayBinding == vertexArray)
		bindVertexArray(0);

	if (vertexArray->m_elementArrayBufferBinding)
		m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);

	for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
		if (vertexArray->m_arrays[ndx].bufferBinding)
			m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);

	DE_ASSERT(vertexArray->getRefCount() == 1);
	m_vertexArrays.releaseReference(vertexArray);
}

void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
{
	// Unbinding program will delete it
	if (m_currentProgram == sp && sp->m_deleteFlag)
	{
		useProgram(0);
		return;
	}

	// Unbinding program will NOT delete it
	if (m_currentProgram == sp)
		useProgram(0);

	DE_ASSERT(sp->getRefCount() == 1);
	m_programs.releaseReference(sp);
}

void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
{
	drawArraysInstanced(mode, first, count, 1);
}

void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
{
	// Error conditions
	{
		RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);

		if (!predrawErrorChecks(mode))
			return;
	}

	// All is ok
	{
		const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);

		drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
	}
}

void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
{
	drawElementsInstanced(mode, count, type, indices, 1);
}

void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
{
	drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
}

void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
{
	drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
}

void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
{
	rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);

	// Error conditions
	{
		RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
					type != GL_UNSIGNED_SHORT &&
					type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
		RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);

		if (!predrawErrorChecks(mode))
			return;
	}

	// All is ok
	{
		const rr::PrimitiveType primitiveType	= sglr::rr_util::mapGLPrimitiveType(mode);
		const void*				indicesPtr		= (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + ((const deUint8*)indices - (const deUint8*)DE_NULL)) : (indices);

		drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
	}
}

void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
{
	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);

	drawElements(mode, count, type, indices);
}

void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
{
	RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);

	drawElementsBaseVertex(mode, count, type, indices, baseVertex);
}

void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
{
	struct DrawArraysIndirectCommand
	{
		deUint32 count;
		deUint32 primCount;
		deUint32 first;
		deUint32 reservedMustBeZero;
	};

	const DrawArraysIndirectCommand* command;

	// Check errors

	if (!predrawErrorChecks(mode))
		return;

	// Check pointer validity

	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);

	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                     > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
	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);

	// Check values

	command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);

	// draw
	drawArraysInstanced(mode, command->first, command->count, command->primCount);
}

void ReferenceContext::drawElementsIndirect	(deUint32 mode, deUint32 type, const void *indirect)
{
	struct DrawElementsIndirectCommand
	{
		deUint32 count;
		deUint32 primCount;
		deUint32 firstIndex;
		deInt32  baseVertex;
		deUint32 reservedMustBeZero;
	};

	const DrawElementsIndirectCommand* command;

	// Check errors

	if (!predrawErrorChecks(mode))
		return;

	RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
				type != GL_UNSIGNED_SHORT &&
				type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);

	RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);

	// Check pointer validity

	RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
	RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);

	// \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
	RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL)                                       > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
	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);

	// Check values

	command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
	RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);

	// Check command error conditions
	RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);

	// Draw
	{
		const size_t			sizeOfType		= (type == GL_UNSIGNED_BYTE) ?  (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
		const void*				indicesPtr		= glu::BufferOffsetAsPointer(command->firstIndex * sizeOfType);

		drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
	}
}

void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
{
	DE_UNREF(mode);
	DE_UNREF(first);
	DE_UNREF(count);
	DE_UNREF(primCount);

	// not supported in gles, prevent accidental use
	DE_ASSERT(false);
}

void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
{
	DE_UNREF(mode);
	DE_UNREF(count);
	DE_UNREF(type);
	DE_UNREF(indices);
	DE_UNREF(primCount);

	// not supported in gles, prevent accidental use
	DE_ASSERT(false);
}

void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
{
	DE_UNREF(mode);
	DE_UNREF(count);
	DE_UNREF(type);
	DE_UNREF(indices);
	DE_UNREF(primCount);
	DE_UNREF(baseVertex);

	// not supported in gles, prevent accidental use
	DE_ASSERT(false);
}

bool ReferenceContext::predrawErrorChecks (deUint32 mode)
{
	RC_IF_ERROR(mode != GL_POINTS &&
				mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
				mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
				mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
				mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
				GL_INVALID_ENUM, false);

	// \todo [jarkko] Uncomment following code when the buffer mapping support is added
	//for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
	//	if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
	//		RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);

	RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);

	// Geometry shader checks
	if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
	{
		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);

		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
			(mode != GL_LINES &&
			 mode != GL_LINE_STRIP &&
			 mode != GL_LINE_LOOP),
			 GL_INVALID_OPERATION, false);

		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
			(mode != GL_TRIANGLES &&
			 mode != GL_TRIANGLE_STRIP &&
			 mode != GL_TRIANGLE_FAN),
			 GL_INVALID_OPERATION, false);

		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
			(mode != GL_LINES_ADJACENCY &&
			 mode != GL_LINE_STRIP_ADJACENCY),
			 GL_INVALID_OPERATION, false);

		RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
			(mode != GL_TRIANGLES_ADJACENCY &&
			 mode != GL_TRIANGLE_STRIP_ADJACENCY),
			 GL_INVALID_OPERATION, false);
	}

	return true;
}

static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
{
	switch (derivedType)
	{
		case rr::PRIMITIVETYPE_TRIANGLES:
		case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
		case rr::PRIMITIVETYPE_TRIANGLE_FAN:
		case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
		case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
			return rr::PRIMITIVETYPE_TRIANGLES;

		case rr::PRIMITIVETYPE_LINES:
		case rr::PRIMITIVETYPE_LINE_STRIP:
		case rr::PRIMITIVETYPE_LINE_LOOP:
		case rr::PRIMITIVETYPE_LINES_ADJACENCY:
		case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
			return rr::PRIMITIVETYPE_LINES;

		case rr::PRIMITIVETYPE_POINTS:
			return rr::PRIMITIVETYPE_POINTS;

		default:
			DE_ASSERT(false);
			return rr::PRIMITIVETYPE_LAST;
	}
}

static deUint32 getFixedRestartIndex (rr::IndexType indexType)
{
	switch (indexType)
	{
		case rr::INDEXTYPE_UINT8:		return 0xFF;
		case rr::INDEXTYPE_UINT16:		return 0xFFFF;
		case rr::INDEXTYPE_UINT32:		return 0xFFFFFFFFul;

		case rr::INDEXTYPE_LAST:
		default:
			DE_ASSERT(false);
			return 0;
	}
}

void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
{
	// undefined results
	if (m_currentProgram == DE_NULL)
		return;

	rr::MultisamplePixelBufferAccess	colorBuf0	= getDrawColorbuffer();
	rr::MultisamplePixelBufferAccess	depthBuf	= getDepthMultisampleAccess(getDrawDepthbuffer());
	rr::MultisamplePixelBufferAccess	stencilBuf	= getStencilMultisampleAccess(getDrawStencilbuffer());
	const bool							hasStencil	= !isEmpty(stencilBuf);
	const int							stencilBits	= (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);

	const rr::RenderTarget				renderTarget(colorBuf0, depthBuf, stencilBuf);
	const rr::Program					program		(m_currentProgram->m_program->getVertexShader(),
													 m_currentProgram->m_program->getFragmentShader(),
													 (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
	rr::RenderState						state		((rr::ViewportState)(colorBuf0), m_limits.subpixelBits);

	const rr::Renderer					referenceRenderer;
	std::vector<rr::VertexAttrib>		vertexAttribs;

	// Gen state
	{
		const rr::PrimitiveType	baseType							= getPrimitiveBaseType(primitives.getPrimitiveType());
		const bool				polygonOffsetEnabled				= (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);

		//state.cullMode											= m_cullMode

		state.fragOps.scissorTestEnabled							= m_scissorEnabled;
		state.fragOps.scissorRectangle								= rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());

		state.fragOps.numStencilBits								= stencilBits;
		state.fragOps.stencilTestEnabled							= m_stencilTestEnabled;

		for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
		{
			state.fragOps.stencilStates[faceType].compMask	= m_stencil[faceType].opMask;
			state.fragOps.stencilStates[faceType].writeMask	= m_stencil[faceType].writeMask;
			state.fragOps.stencilStates[faceType].ref		= m_stencil[faceType].ref;
			state.fragOps.stencilStates[faceType].func		= sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
			state.fragOps.stencilStates[faceType].sFail		= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
			state.fragOps.stencilStates[faceType].dpFail	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
			state.fragOps.stencilStates[faceType].dpPass	= sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
		}

		state.fragOps.depthTestEnabled								= m_depthTestEnabled;
		state.fragOps.depthFunc										= sglr::rr_util::mapGLTestFunc(m_depthFunc);
		state.fragOps.depthMask										= m_depthMask;

		state.fragOps.blendMode										= m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
		state.fragOps.blendRGBState.equation						= sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
		state.fragOps.blendRGBState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
		state.fragOps.blendRGBState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
		state.fragOps.blendAState.equation							= sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
		state.fragOps.blendAState.srcFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
		state.fragOps.blendAState.dstFunc							= sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
		state.fragOps.blendColor									= m_blendColor;

		state.fragOps.sRGBEnabled									= m_sRGBUpdateEnabled;

		state.fragOps.colorMask										= m_colorMask;

		state.fragOps.depthClampEnabled								= m_depthClampEnabled;

		state.viewport.rect											= rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
		state.viewport.zn											= m_depthRangeNear;
		state.viewport.zf											= m_depthRangeFar;

		//state.point.pointSize										= m_pointSize;
		state.line.lineWidth										= m_lineWidth;

		state.fragOps.polygonOffsetEnabled							= polygonOffsetEnabled;
		state.fragOps.polygonOffsetFactor							= m_polygonOffsetFactor;
		state.fragOps.polygonOffsetUnits							= m_polygonOffsetUnits;

		{
			const rr::IndexType indexType = primitives.getIndexType();

			if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
			{
				state.restart.enabled = true;
				state.restart.restartIndex = getFixedRestartIndex(indexType);
			}
			else if (m_primitiveRestartSettableIndex)
			{
				// \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
				state.restart.enabled = true;
				state.restart.restartIndex = m_primitiveRestartIndex;
			}
			else
			{
				state.restart.enabled = false;
			}
		}

		state.provokingVertexConvention								= (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
	}

	// gen attributes
	{
		rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);

		vertexAttribs.resize(vao.m_arrays.size());
		for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
		{
			if (!vao.m_arrays[ndx].enabled)
			{
				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
				vertexAttribs[ndx].generic = m_currentAttribs[ndx];
			}
			else if (vao.m_arrays[ndx].bufferDeleted)
			{
				vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
				vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
			}
			else
			{
				vertexAttribs[ndx].type				= (vao.m_arrays[ndx].integer) ?
														(sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
														(sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
				vertexAttribs[ndx].size				= sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
				vertexAttribs[ndx].stride			= vao.m_arrays[ndx].stride;
				vertexAttribs[ndx].instanceDivisor	= vao.m_arrays[ndx].divisor;
				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);
			}
		}
	}

	// Set shader samplers
	for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
	{
		const tcu::Sampler::DepthStencilMode	depthStencilMode	= tcu::Sampler::MODE_DEPTH; // \todo[jarkko] support sampler state
		const int								texNdx				= m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;

		switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
		{
			case glu::TYPE_SAMPLER_1D:
			case glu::TYPE_UINT_SAMPLER_1D:
			case glu::TYPE_INT_SAMPLER_1D:
			{
				rc::Texture1D* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;

				break;
			}
			case glu::TYPE_SAMPLER_2D:
			case glu::TYPE_UINT_SAMPLER_2D:
			case glu::TYPE_INT_SAMPLER_2D:
			{
				rc::Texture2D* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;

				break;
			}
			case glu::TYPE_SAMPLER_CUBE:
			case glu::TYPE_UINT_SAMPLER_CUBE:
			case glu::TYPE_INT_SAMPLER_CUBE:
			{
				rc::TextureCube* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;

				break;
			}
			case glu::TYPE_SAMPLER_2D_ARRAY:
			case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
			case glu::TYPE_INT_SAMPLER_2D_ARRAY:
			{
				rc::Texture2DArray* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;

				break;
			}
			case glu::TYPE_SAMPLER_3D:
			case glu::TYPE_UINT_SAMPLER_3D:
			case glu::TYPE_INT_SAMPLER_3D:
			{
				rc::Texture3D* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;

				break;
			}
			case glu::TYPE_SAMPLER_CUBE_ARRAY:
			case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
			case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
			{
				rc::TextureCubeArray* tex = DE_NULL;

				if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
					tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);

				if (tex && tex->isComplete())
				{
					tex->updateView(depthStencilMode);
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
				}
				else
					m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;

				break;
			}
			default:
				// nothing
				break;
		}
	}

	referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
}

deUint32 ReferenceContext::createProgram (ShaderProgram* program)
{
	int name = m_programs.allocateName();

	m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));

	return name;
}

void ReferenceContext::useProgram (deUint32 program)
{
	rc::ShaderProgramObjectContainer* shaderProg			= DE_NULL;
	rc::ShaderProgramObjectContainer* programToBeDeleted	= DE_NULL;

	if (program)
	{
		shaderProg = m_programs.find(program);

		// shader has not been linked
		if (!shaderProg || shaderProg->m_deleteFlag)
			RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
	}

	if (m_currentProgram && m_currentProgram->m_deleteFlag)
		programToBeDeleted = m_currentProgram;

	m_currentProgram = shaderProg;

	if (programToBeDeleted)
	{
		DE_ASSERT(programToBeDeleted->getRefCount() == 1);
		deleteProgramObject(programToBeDeleted);
	}
}

void ReferenceContext::deleteProgram (deUint32 program)
{
	if (!program)
		return;

	rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
	if (shaderProg)
	{
		if (shaderProg == m_currentProgram)
		{
			m_currentProgram->m_deleteFlag = true;
		}
		else
		{
			DE_ASSERT(shaderProg->getRefCount() == 1);
			m_programs.releaseReference(shaderProg);
		}
	}
}

void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
{
	rr::MultisamplePixelBufferAccess	src = getReadColorbuffer();
	TextureFormat						transferFmt;

	// Map transfer format.
	transferFmt = glu::mapGLTransferFormat(format, type);
	RC_IF_ERROR(transferFmt.order	== TextureFormat::CHANNELORDER_LAST ||
				transferFmt.type	== TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);

	// Clamp input values
	const int copyX			= deClamp32(x,		0, src.raw().getHeight());
	const int copyY			= deClamp32(y,		0, src.raw().getDepth());
	const int copyWidth		= deClamp32(width,	0, src.raw().getHeight()-x);
	const int copyHeight	= deClamp32(height,	0, src.raw().getDepth()-y);

	PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
	rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
}

deUint32 ReferenceContext::getError (void)
{
	deUint32 err = m_lastError;
	m_lastError = GL_NO_ERROR;
	return err;
}

void ReferenceContext::finish (void)
{
}

inline void ReferenceContext::setError (deUint32 error)
{
	if (m_lastError == GL_NO_ERROR)
		m_lastError = error;
}

void ReferenceContext::getIntegerv (deUint32 pname, int* param)
{
	switch (pname)
	{
		case GL_MAX_TEXTURE_SIZE:			*param = m_limits.maxTexture2DSize;			break;
		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:	*param = m_limits.maxTextureCubeSize;		break;
		case GL_MAX_ARRAY_TEXTURE_LAYERS:	*param = m_limits.maxTexture2DArrayLayers;	break;
		case GL_MAX_3D_TEXTURE_SIZE:		*param = m_limits.maxTexture3DSize;			break;
		case GL_MAX_RENDERBUFFER_SIZE:		*param = m_limits.maxRenderbufferSize;		break;
		case GL_MAX_TEXTURE_IMAGE_UNITS:	*param = m_limits.maxTextureImageUnits;		break;
		case GL_MAX_VERTEX_ATTRIBS:			*param = m_limits.maxVertexAttribs;			break;

		default:
			setError(GL_INVALID_ENUM);
			break;
	}
}

const char* ReferenceContext::getString (deUint32 pname)
{
	switch (pname)
	{
		case GL_EXTENSIONS:		return m_limits.extensionStr.c_str();

		default:
			setError(GL_INVALID_ENUM);
			return DE_NULL;
	}
}

namespace rc
{

TextureLevelArray::TextureLevelArray (void)
{
}

TextureLevelArray::~TextureLevelArray (void)
{
	clear();
}

void TextureLevelArray::clear (void)
{
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
	{
		m_data[ndx].clear();
		m_access[ndx] = PixelBufferAccess();
	}
}

void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
{
	const int dataSize = format.getPixelSize()*width*height*depth;

	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));

	if (hasLevel(level))
		clearLevel(level);

	m_data[level].setStorage(dataSize);
	m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level].getPtr());
}

void TextureLevelArray::clearLevel (int level)
{
	DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));

	m_data[level].clear();
	m_access[level] = PixelBufferAccess();
}

void TextureLevelArray::updateSamplerMode (tcu::Sampler::DepthStencilMode mode)
{
	for (int levelNdx = 0; hasLevel(levelNdx); ++levelNdx)
		m_effectiveAccess[levelNdx] = tcu::getEffectiveDepthStencilAccess(m_access[levelNdx], mode);
}

Texture::Texture (deUint32 name, Type type, deBool seamless)
	: NamedObject	(name)
	, m_type		(type)
	, m_immutable	(false)
	, m_sampler		(tcu::Sampler::REPEAT_GL,
					 tcu::Sampler::REPEAT_GL,
					 tcu::Sampler::REPEAT_GL,
					 tcu::Sampler::NEAREST_MIPMAP_LINEAR,
					 tcu::Sampler::LINEAR,
					 0.0f,				// LOD threshold
					 true,				// normalized coords
					 tcu::Sampler::COMPAREMODE_NONE,
					 0,					// cmp channel ndx
					 tcu::Vec4(0.0f),	// border color
					 seamless			// seamless cube map, Default value is True.
					 )
	, m_baseLevel	(0)
	, m_maxLevel	(1000)
{
}

Texture1D::Texture1D (deUint32 name)
	: Texture	(name, TYPE_1D)
	, m_view	(0, DE_NULL)
{
}

Texture1D::~Texture1D (void)
{
}

void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
{
	m_levels.allocLevel(level, format, width, 1, 1);
}

bool Texture1D::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel))
	{
		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);

		if (mipmap)
		{
			const TextureFormat&	format		= level0.getFormat();
			const int				w			= level0.getWidth();
			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));

			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				if (hasLevel(baseLevel+levelNdx))
				{
					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
					const int							expectedW	= getMipLevelSize(w, levelNdx);

					if (level.getWidth()	!= expectedW	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

tcu::Vec4 Texture1D::sample (float s, float lod) const
{
	return m_view.sample(getSampler(), s, 0.0f, lod);
}

void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
{
	const float texWidth = (float)m_view.getWidth();

	const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
	const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
	const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
	const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
		const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
		const float p = mu * texWidth;

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
	}
}

void Texture1D::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
	{
		const int	width		= getLevel(baseLevel).getWidth();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;

		m_levels.updateSamplerMode(mode);
		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
	}
	else
		m_view = tcu::Texture2DView(0, DE_NULL);
}

Texture2D::Texture2D (deUint32 name, bool es2)
	: Texture	(name, TYPE_2D)
	, m_view	(0, DE_NULL, es2)
{
}

Texture2D::~Texture2D (void)
{
}

void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
{
	m_levels.allocLevel(level, format, width, height, 1);
}

bool Texture2D::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel))
	{
		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);

		if (mipmap)
		{
			const TextureFormat&	format		= level0.getFormat();
			const int				w			= level0.getWidth();
			const int				h			= level0.getHeight();
			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));

			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				if (hasLevel(baseLevel+levelNdx))
				{
					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
					const int							expectedW	= getMipLevelSize(w, levelNdx);
					const int							expectedH	= getMipLevelSize(h, levelNdx);

					if (level.getWidth()	!= expectedW	||
						level.getHeight()	!= expectedH	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

void Texture2D::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
	{
		// Update number of levels in mipmap pyramid.
		const int	width		= getLevel(baseLevel).getWidth();
		const int	height		= getLevel(baseLevel).getHeight();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;

		m_levels.updateSamplerMode(mode);
		m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
	}
	else
		m_view = tcu::Texture2DView(0, DE_NULL);
}

tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
{
	return m_view.sample(getSampler(), s, t, lod);
}

void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
{
	const float texWidth  = (float)m_view.getWidth();
	const float texHeight = (float)m_view.getHeight();

	const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
	const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
	const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
	const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
		const float p = de::max(mu * texWidth, mv * texHeight);

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
	}
}

TextureCube::TextureCube (deUint32 name, deBool seamless)
	: Texture(name, TYPE_CUBE_MAP, seamless)
{
}

TextureCube::~TextureCube (void)
{
}

void TextureCube::clearLevels (void)
{
	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		m_levels[face].clear();
}

void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
{
	m_levels[face].allocLevel(level, format, width, height, 1);
}

bool TextureCube::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
	{
		const int					width		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
		const int					height		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
		const tcu::TextureFormat&	format		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
		const bool					mipmap		= isMipmapFilter(getSampler().minFilter);
		const int					numLevels	= mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;

		if (width != height)
			return false; // Non-square is not supported.

		// \note Level 0 is always checked for consistency
		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
		{
			const int levelW	= getMipLevelSize(width,	levelNdx);
			const int levelH	= getMipLevelSize(height,	levelNdx);

			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
			{
				if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
				{
					const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);

					if (level.getWidth()	!= levelW	||
						level.getHeight()	!= levelH	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

void TextureCube::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int							baseLevel	= getBaseLevel();
	const tcu::ConstPixelBufferAccess*	faces[tcu::CUBEFACE_LAST];

	deMemset(&faces[0], 0, sizeof(faces));

	if (isComplete())
	{
		const int	size		= getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;

		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		{
			m_levels[face].updateSamplerMode(mode);
			faces[face] = m_levels[face].getEffectiveLevels() + baseLevel;
		}

		m_view = tcu::TextureCubeView(numLevels, faces);
	}
	else
		m_view = tcu::TextureCubeView(0, faces);
}

tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
{
	return m_view.sample(getSampler(), s, t, p, lod);
}

void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
{
	const float cubeSide = (float)m_view.getSize();

	// Each tex coord might be in a different face.

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const tcu::CubeFace face		= tcu::selectCubeFace(packetTexcoords[fragNdx]);
		const tcu::Vec2		coords[4]	=
		{
			tcu::projectToFace(face, packetTexcoords[0]),
			tcu::projectToFace(face, packetTexcoords[1]),
			tcu::projectToFace(face, packetTexcoords[2]),
			tcu::projectToFace(face, packetTexcoords[3]),
		};

		const tcu::Vec2 dFdx0 = coords[1] - coords[0];
		const tcu::Vec2 dFdx1 = coords[3] - coords[2];
		const tcu::Vec2 dFdy0 = coords[2] - coords[0];
		const tcu::Vec2 dFdy1 = coords[3] - coords[1];

		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
		const float p = de::max(mu * cubeSide, mv * cubeSide);

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
	}
}

Texture2DArray::Texture2DArray (deUint32 name)
	: Texture	(name, TYPE_2D_ARRAY)
	, m_view	(0, DE_NULL)
{
}

Texture2DArray::~Texture2DArray (void)
{
}

void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
{
	m_levels.allocLevel(level, format, width, height, numLayers);
}

bool Texture2DArray::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel))
	{
		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);

		if (mipmap)
		{
			const TextureFormat&	format		= level0.getFormat();
			const int				w			= level0.getWidth();
			const int				h			= level0.getHeight();
			const int				numLayers	= level0.getDepth();
			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));

			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				if (hasLevel(baseLevel+levelNdx))
				{
					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
					const int							expectedW	= getMipLevelSize(w, levelNdx);
					const int							expectedH	= getMipLevelSize(h, levelNdx);

					if (level.getWidth()	!= expectedW	||
						level.getHeight()	!= expectedH	||
						level.getDepth()	!= numLayers	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

void Texture2DArray::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
	{
		const int	width		= getLevel(baseLevel).getWidth();
		const int	height		= getLevel(baseLevel).getHeight();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;

		m_levels.updateSamplerMode(mode);
		m_view = tcu::Texture2DArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
	}
	else
		m_view = tcu::Texture2DArrayView(0, DE_NULL);
}

tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
{
	return m_view.sample(getSampler(), s, t, r, lod);
}

void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
{
	const float texWidth  = (float)m_view.getWidth();
	const float texHeight = (float)m_view.getHeight();

	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
		const float p = de::max(mu * texWidth, mv * texHeight);

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
	}
}

TextureCubeArray::TextureCubeArray (deUint32 name)
	: Texture	(name, TYPE_CUBE_MAP_ARRAY)
	, m_view	(0, DE_NULL)
{
}

TextureCubeArray::~TextureCubeArray (void)
{
}

void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
{
	DE_ASSERT(numLayers % 6 == 0);
	m_levels.allocLevel(level, format, width, height, numLayers);
}

bool TextureCubeArray::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel))
	{
		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);

		if (mipmap)
		{
			const TextureFormat&	format		= level0.getFormat();
			const int				w			= level0.getWidth();
			const int				h			= level0.getHeight();
			const int				numLayers	= level0.getDepth();
			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));

			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				if (hasLevel(baseLevel+levelNdx))
				{
					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
					const int							expectedW	= getMipLevelSize(w, levelNdx);
					const int							expectedH	= getMipLevelSize(h, levelNdx);

					if (level.getWidth()	!= expectedW	||
						level.getHeight()	!= expectedH	||
						level.getDepth()	!= numLayers	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

void TextureCubeArray::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
	{
		const int	width		= getLevel(baseLevel).getWidth();
		const int	height		= getLevel(baseLevel).getHeight();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;

		m_levels.updateSamplerMode(mode);
		m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
	}
	else
		m_view = tcu::TextureCubeArrayView(0, DE_NULL);
}

tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
{
	return m_view.sample(getSampler(), s, t, r, q, lod);
}

void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
{
	const float		cubeSide		= (float)m_view.getSize();
	const tcu::Vec3	cubeCoords[4]	=
	{
		packetTexcoords[0].toWidth<3>(),
		packetTexcoords[1].toWidth<3>(),
		packetTexcoords[2].toWidth<3>(),
		packetTexcoords[3].toWidth<3>()
	};

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const tcu::CubeFace face			= tcu::selectCubeFace(cubeCoords[fragNdx]);
		const tcu::Vec2		faceCoords[4]	=
		{
			tcu::projectToFace(face, cubeCoords[0]),
			tcu::projectToFace(face, cubeCoords[1]),
			tcu::projectToFace(face, cubeCoords[2]),
			tcu::projectToFace(face, cubeCoords[3]),
		};

		const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
		const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
		const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
		const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];

		const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
		const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
		const float p = de::max(mu * cubeSide, mv * cubeSide);

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
	}
}

Texture3D::Texture3D (deUint32 name)
	: Texture	(name, TYPE_3D)
	, m_view	(0, DE_NULL)
{
}

Texture3D::~Texture3D (void)
{
}

void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
{
	m_levels.allocLevel(level, format, width, height, depth);
}

bool Texture3D::isComplete (void) const
{
	const int	baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel))
	{
		const tcu::ConstPixelBufferAccess&	level0		= getLevel(baseLevel);
		const bool							mipmap		= isMipmapFilter(getSampler().minFilter);

		if (mipmap)
		{
			const TextureFormat&	format		= level0.getFormat();
			const int				w			= level0.getWidth();
			const int				h			= level0.getHeight();
			const int				d			= level0.getDepth();
			const int				numLevels	= de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));

			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				if (hasLevel(baseLevel+levelNdx))
				{
					const tcu::ConstPixelBufferAccess&	level		= getLevel(baseLevel+levelNdx);
					const int							expectedW	= getMipLevelSize(w, levelNdx);
					const int							expectedH	= getMipLevelSize(h, levelNdx);
					const int							expectedD	= getMipLevelSize(d, levelNdx);

					if (level.getWidth()	!= expectedW	||
						level.getHeight()	!= expectedH	||
						level.getDepth()	!= expectedD	||
						level.getFormat()	!= format)
						return false;
				}
				else
					return false;
			}
		}

		return true;
	}
	else
		return false;
}

tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
{
	return m_view.sample(getSampler(), s, t, r, lod);
}

void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
{
	const float texWidth  = (float)m_view.getWidth();
	const float texHeight = (float)m_view.getHeight();
	const float texDepth  = (float)m_view.getDepth();

	const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
	const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
	const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
	const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];

	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
	{
		const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
		const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;

		const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
		const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
		const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
		const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);

		const float	lod = deFloatLog2(p) + lodBias;

		output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
	}
}

void Texture3D::updateView (tcu::Sampler::DepthStencilMode mode)
{
	const int baseLevel	= getBaseLevel();

	if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
	{
		const int	width		= getLevel(baseLevel).getWidth();
		const int	height		= getLevel(baseLevel).getHeight();
		const int	depth		= getLevel(baseLevel).getDepth();
		const bool	isMipmap	= isMipmapFilter(getSampler().minFilter);
		const int	numLevels	= isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;

		m_levels.updateSamplerMode(mode);
		m_view = tcu::Texture3DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
	}
	else
		m_view = tcu::Texture3DView(0, DE_NULL);
}

Renderbuffer::Renderbuffer (deUint32 name)
	: NamedObject		(name)
{
}

Renderbuffer::~Renderbuffer (void)
{
}

void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
{
	m_data.setStorage(format, width, height);
}

Framebuffer::Framebuffer (deUint32 name)
	: NamedObject(name)
{
}

Framebuffer::~Framebuffer (void)
{
}

VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
	: NamedObject					(name)
	, m_elementArrayBufferBinding	(DE_NULL)
	, m_arrays						(maxVertexAttribs)
{
	for (int i = 0; i < maxVertexAttribs; ++i)
	{
		m_arrays[i].enabled			= false;
		m_arrays[i].size			= 4;
		m_arrays[i].stride			= 0;
		m_arrays[i].type			= GL_FLOAT;
		m_arrays[i].normalized		= false;
		m_arrays[i].integer			= false;
		m_arrays[i].divisor			= 0;
		m_arrays[i].bufferDeleted	= false;
		m_arrays[i].bufferBinding	= DE_NULL;
		m_arrays[i].pointer			= DE_NULL;
	}
}

ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
	: NamedObject	(name)
	, m_program		(program)
	, m_deleteFlag	(false)
{
}

ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
{
}

} // rc
} // sglr
