/*-------------------------------------------------------------------------
 * 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 "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();

	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					()
	, 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);

	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.
			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);	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)
				return dynamic_cast<Texture2D*>(texture)->getLevel(attachment.level);
			else if (texture->getType() == Texture::TYPE_CUBE_MAP)
				return dynamic_cast<TextureCube*>(texture)->getFace(attachment.level, texTargetToFace(attachment.texTarget));
			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)
					level = dynamic_cast<Texture2DArray*>(texture)->getLevel(attachment.level);
				else if (texture->getType() == Texture::TYPE_3D)
					level = dynamic_cast<Texture3D*>(texture)->getLevel(attachment.level);
				else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
					level = dynamic_cast<TextureCubeArray*>(texture)->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)
	: 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
					 true				// seamless cube map \todo [2014-02-19 pyry] Default value ok?
					 )
	, 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)
	: Texture(name, TYPE_CUBE_MAP)
{
}

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
