Home | History | Annotate | Download | only in null
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES Utilities
      3  * ------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Render context implementation that does no rendering.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "tcuNullRenderContext.hpp"
     25 #include "tcuTexture.hpp"
     26 #include "tcuTextureUtil.hpp"
     27 #include "deThreadLocal.hpp"
     28 #include "gluRenderConfig.hpp"
     29 #include "gluTextureUtil.hpp"
     30 #include "glwEnums.hpp"
     31 
     32 #include <string>
     33 #include <vector>
     34 
     35 namespace tcu
     36 {
     37 namespace null
     38 {
     39 
     40 using namespace glw;
     41 
     42 #include "tcuNullRenderContextFuncs.inl"
     43 
     44 using namespace glu;
     45 using std::string;
     46 using std::vector;
     47 
     48 class ObjectManager
     49 {
     50 public:
     51 	ObjectManager (void)
     52 		: m_lastObject(0)
     53 	{
     54 	}
     55 
     56 	deUint32 allocate (void)
     57 	{
     58 		deUint32 object = ++m_lastObject;
     59 		if (object == 0)
     60 			object = ++m_lastObject; // Just ignore overflow.
     61 		return object;
     62 	}
     63 
     64 	void free (deUint32 object)
     65 	{
     66 		DE_UNREF(object);
     67 	}
     68 
     69 private:
     70 	deUint32 m_lastObject;
     71 };
     72 
     73 class Context
     74 {
     75 public:
     76 							Context				(ContextType ctxType_);
     77 							~Context			(void);
     78 
     79 private:
     80 							Context				(const Context&);
     81 	Context&				operator=			(const Context&);
     82 
     83 	void					addExtension		(const char* name);
     84 
     85 public:
     86 	// GL state exposed to implementation functions.
     87 	const ContextType		ctxType;
     88 
     89 	string					vendor;
     90 	string					version;
     91 	string					renderer;
     92 	string					shadingLanguageVersion;
     93 	string					extensions;
     94 	vector<string>			extensionList;
     95 	vector<deUint32>		compressedTextureList;
     96 
     97 	GLenum					lastError;
     98 
     99 	int						pixelPackRowLength;
    100 	int						pixelPackSkipRows;
    101 	int						pixelPackSkipPixels;
    102 	int						pixelPackAlignment;
    103 
    104 	GLuint					pixelPackBufferBufferBinding;
    105 
    106 	ObjectManager			shaders;
    107 	ObjectManager			programs;
    108 	ObjectManager			textures;
    109 	ObjectManager			buffers;
    110 	ObjectManager			renderbuffers;
    111 	ObjectManager			framebuffers;
    112 	ObjectManager			samplers;
    113 	ObjectManager			vertexArrays;
    114 	ObjectManager			queries;
    115 	ObjectManager			transformFeedbacks;
    116 	ObjectManager			programPipelines;
    117 };
    118 
    119 Context::Context (ContextType ctxType_)
    120 	: ctxType						(ctxType_)
    121 	, vendor						("drawElements")
    122 	, renderer						("dummy")
    123 	, lastError						(GL_NO_ERROR)
    124 	, pixelPackRowLength			(0)
    125 	, pixelPackSkipRows				(0)
    126 	, pixelPackSkipPixels			(0)
    127 	, pixelPackAlignment			(0)
    128 	, pixelPackBufferBufferBinding	(0)
    129 {
    130 	using glu::ApiType;
    131 
    132 	if (ctxType.getAPI() == ApiType::es(2, 0))
    133 	{
    134 		version					= "OpenGL ES 2.0";
    135 		shadingLanguageVersion	= "OpenGL ES GLSL ES 1.0";
    136 	}
    137 	else if (ctxType.getAPI() == ApiType::es(3, 0))
    138 	{
    139 		version					= "OpenGL ES 3.0";
    140 		shadingLanguageVersion	= "OpenGL ES GLSL ES 3.0";
    141 	}
    142 	else if (ctxType.getAPI() == ApiType::es(3, 1))
    143 	{
    144 		version					= "OpenGL ES 3.1";
    145 		shadingLanguageVersion	= "OpenGL ES GLSL ES 3.1";
    146 		addExtension("GL_OES_texture_stencil8");
    147 		addExtension("GL_OES_sample_shading");
    148 		addExtension("GL_OES_sample_variables");
    149 		addExtension("GL_OES_shader_multisample_interpolation");
    150 		addExtension("GL_OES_shader_image_atomic");
    151 		addExtension("GL_OES_texture_storage_multisample_2d_array");
    152 		addExtension("GL_KHR_blend_equation_advanced");
    153 		addExtension("GL_KHR_blend_equation_advanced_coherent");
    154 		addExtension("GL_EXT_shader_io_blocks");
    155 		addExtension("GL_EXT_geometry_shader");
    156 		addExtension("GL_EXT_geometry_point_size");
    157 		addExtension("GL_EXT_tessellation_shader");
    158 		addExtension("GL_EXT_tessellation_point_size");
    159 		addExtension("GL_EXT_gpu_shader5");
    160 		addExtension("GL_EXT_shader_implicit_conversions");
    161 		addExtension("GL_EXT_texture_buffer");
    162 		addExtension("GL_EXT_texture_cube_map_array");
    163 		addExtension("GL_EXT_draw_buffers_indexed");
    164 		addExtension("GL_EXT_texture_sRGB_decode");
    165 		addExtension("GL_EXT_texture_border_clamp");
    166 		addExtension("GL_KHR_debug");
    167 		addExtension("GL_EXT_primitive_bounding_box");
    168 		addExtension("GL_ANDROID_extension_pack_es31a");
    169 		addExtension("GL_EXT_copy_image");
    170 	}
    171 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 3)
    172 	{
    173 		version					= "3.3.0";
    174 		shadingLanguageVersion	= "3.30";
    175 	}
    176 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() <= 4)
    177 	{
    178 		version					= "4.4.0";
    179 		shadingLanguageVersion	= "4.40";
    180 	}
    181 	else
    182 		throw tcu::NotSupportedError("Unsupported GL version", "", __FILE__, __LINE__);
    183 
    184 	if (isContextTypeES(ctxType))
    185 	{
    186 		addExtension("GL_EXT_color_buffer_float");
    187 		addExtension("GL_EXT_color_buffer_half_float");
    188 	}
    189 
    190 	// support compressed formats
    191 	{
    192 		static deUint32 compressedFormats[] =
    193 		{
    194 			GL_ETC1_RGB8_OES,
    195 			GL_COMPRESSED_R11_EAC,
    196 			GL_COMPRESSED_SIGNED_R11_EAC,
    197 			GL_COMPRESSED_RG11_EAC,
    198 			GL_COMPRESSED_SIGNED_RG11_EAC,
    199 			GL_COMPRESSED_RGB8_ETC2,
    200 			GL_COMPRESSED_SRGB8_ETC2,
    201 			GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
    202 			GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
    203 			GL_COMPRESSED_RGBA8_ETC2_EAC,
    204 			GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
    205 			GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
    206 			GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
    207 			GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
    208 			GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
    209 			GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
    210 			GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
    211 			GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
    212 			GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
    213 			GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
    214 			GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
    215 			GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
    216 			GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
    217 			GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
    218 			GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
    219 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
    220 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
    221 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
    222 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
    223 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
    224 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
    225 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
    226 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
    227 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
    228 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
    229 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
    230 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
    231 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
    232 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
    233 		};
    234 
    235 		addExtension("GL_KHR_texture_compression_astc_hdr");
    236 		addExtension("GL_KHR_texture_compression_astc_ldr");
    237 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(compressedFormats); ++ndx)
    238 			compressedTextureList.push_back(compressedFormats[ndx]);
    239 	}
    240 }
    241 
    242 Context::~Context (void)
    243 {
    244 }
    245 
    246 void Context::addExtension (const char* name)
    247 {
    248 	if (!extensions.empty())
    249 		extensions += " ";
    250 	extensions += name;
    251 
    252 	extensionList.push_back(name);
    253 }
    254 
    255 static de::ThreadLocal s_currentCtx;
    256 
    257 void setCurrentContext (Context* context)
    258 {
    259 	s_currentCtx.set((void*)context);
    260 }
    261 
    262 Context* getCurrentContext (void)
    263 {
    264 	return (Context*)s_currentCtx.get();
    265 }
    266 
    267 GLW_APICALL GLenum GLW_APIENTRY glGetError (void)
    268 {
    269 	Context* const	ctx		= getCurrentContext();
    270 	const GLenum	lastErr	= ctx->lastError;
    271 
    272 	ctx->lastError = GL_NO_ERROR;
    273 
    274 	return lastErr;
    275 }
    276 
    277 GLW_APICALL void GLW_APIENTRY glGetIntegerv (GLenum pname, GLint* params)
    278 {
    279 	Context* const ctx = getCurrentContext();
    280 
    281 	switch (pname)
    282 	{
    283 		case GL_NUM_EXTENSIONS:
    284 			*params = (int)ctx->extensionList.size();
    285 			break;
    286 
    287 		case GL_MAX_VERTEX_ATTRIBS:
    288 			*params = 32;
    289 			break;
    290 
    291 		case GL_MAX_DRAW_BUFFERS:
    292 		case GL_MAX_COLOR_ATTACHMENTS:
    293 			*params = 8;
    294 			break;
    295 
    296 		case GL_MAX_TEXTURE_IMAGE_UNITS:
    297 		case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    298 		case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    299 		case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
    300 		case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS:
    301 		case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS:
    302 			*params = 32;
    303 			break;
    304 
    305 		case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
    306 		case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
    307 		case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS:
    308 		case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
    309 		case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS:
    310 		case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
    311 			*params = 8;
    312 			break;
    313 
    314 		case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
    315 		case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
    316 		case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS:
    317 		case GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS:
    318 		case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS:
    319 		case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
    320 			*params = 8;
    321 			break;
    322 
    323 		case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
    324 			*params = 1u << 25;
    325 			break;
    326 
    327 		case GL_MAX_GEOMETRY_OUTPUT_VERTICES:
    328 			*params = 256;
    329 			break;
    330 
    331 		case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
    332 			*params = 2048;
    333 			break;
    334 
    335 		case GL_MAX_GEOMETRY_SHADER_INVOCATIONS:
    336 			*params = 4;
    337 			break;
    338 
    339 		case GL_MAX_COLOR_TEXTURE_SAMPLES:
    340 			*params = 8;
    341 			break;
    342 
    343 		case GL_MAX_TEXTURE_SIZE:
    344 		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    345 		case GL_MAX_3D_TEXTURE_SIZE:
    346 		case GL_MAX_RENDERBUFFER_SIZE:
    347 		case GL_MAX_TEXTURE_BUFFER_SIZE:
    348 			*params = 2048;
    349 			break;
    350 
    351 		case GL_MAX_ARRAY_TEXTURE_LAYERS:
    352 			*params = 128;
    353 			break;
    354 
    355 		case GL_NUM_SHADER_BINARY_FORMATS:
    356 			*params = 0;
    357 			break;
    358 
    359 		case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    360 			*params = (int)ctx->compressedTextureList.size();
    361 			break;
    362 
    363 		case GL_COMPRESSED_TEXTURE_FORMATS:
    364 			deMemcpy(params, &ctx->compressedTextureList[0], ctx->compressedTextureList.size()*sizeof(deUint32));
    365 			break;
    366 
    367 		case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
    368 			*params = 16;
    369 			break;
    370 
    371 		case GL_MAX_UNIFORM_BUFFER_BINDINGS:
    372 			*params = 32;
    373 			break;
    374 
    375 		case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
    376 			*params = 16;
    377 			break;
    378 
    379 		case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
    380 			*params = GL_RGBA;
    381 			break;
    382 
    383 		case GL_IMPLEMENTATION_COLOR_READ_TYPE:
    384 			*params = GL_UNSIGNED_BYTE;
    385 			break;
    386 
    387 		case GL_SAMPLE_BUFFERS:
    388 			*params = 0;
    389 			break;
    390 
    391 		default:
    392 			break;
    393 	}
    394 }
    395 
    396 GLW_APICALL void GLW_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params)
    397 {
    398 	switch (pname)
    399 	{
    400 		case GL_SHADER_COMPILER:
    401 			*params = GL_TRUE;
    402 			break;
    403 
    404 		default:
    405 			break;
    406 	}
    407 }
    408 
    409 GLW_APICALL void GLW_APIENTRY glGetFloatv (GLenum pname, GLfloat* params)
    410 {
    411 	switch (pname)
    412 	{
    413 		case GL_ALIASED_LINE_WIDTH_RANGE:
    414 		case GL_ALIASED_POINT_SIZE_RANGE:
    415 			params[0] = 0.0f;
    416 			params[1] = 64.0f;
    417 			break;
    418 
    419 		default:
    420 			break;
    421 	}
    422 }
    423 
    424 GLW_APICALL void GLW_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
    425 {
    426 	static const int s_sampleCounts[] = { 16, 8, 4, 2, 1 };
    427 
    428 	DE_UNREF(internalformat);
    429 	DE_UNREF(target);
    430 
    431 	switch (pname)
    432 	{
    433 		case GL_NUM_SAMPLE_COUNTS:
    434 			if (bufSize >= 1)
    435 				*params = DE_LENGTH_OF_ARRAY(s_sampleCounts);
    436 			break;
    437 
    438 		case GL_SAMPLES:
    439 			deMemcpy(params, s_sampleCounts, de::min(bufSize, DE_LENGTH_OF_ARRAY(s_sampleCounts)));
    440 			break;
    441 
    442 		default:
    443 			break;
    444 	}
    445 }
    446 
    447 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetString (GLenum name)
    448 {
    449 	Context* const ctx = getCurrentContext();
    450 
    451 	switch (name)
    452 	{
    453 		case GL_VENDOR:						return (const glw::GLubyte*)ctx->vendor.c_str();
    454 		case GL_VERSION:					return (const glw::GLubyte*)ctx->version.c_str();
    455 		case GL_RENDERER:					return (const glw::GLubyte*)ctx->renderer.c_str();
    456 		case GL_SHADING_LANGUAGE_VERSION:	return (const glw::GLubyte*)ctx->shadingLanguageVersion.c_str();
    457 		case GL_EXTENSIONS:					return (const glw::GLubyte*)ctx->extensions.c_str();
    458 		default:
    459 			ctx->lastError = GL_INVALID_ENUM;
    460 			return DE_NULL;
    461 	}
    462 }
    463 
    464 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetStringi (GLenum name, GLuint index)
    465 {
    466 	Context* const ctx = getCurrentContext();
    467 
    468 	if (name == GL_EXTENSIONS)
    469 	{
    470 		if ((size_t)index < ctx->extensionList.size())
    471 			return (const glw::GLubyte*)ctx->extensionList[index].c_str();
    472 		else
    473 		{
    474 			ctx->lastError = GL_INVALID_VALUE;
    475 			return DE_NULL;
    476 		}
    477 	}
    478 	else
    479 	{
    480 		ctx->lastError = GL_INVALID_ENUM;
    481 		return DE_NULL;
    482 	}
    483 }
    484 
    485 GLW_APICALL GLuint GLW_APIENTRY glCreateProgram ()
    486 {
    487 	Context* const ctx = getCurrentContext();
    488 	return (GLuint)ctx->programs.allocate();
    489 }
    490 
    491 GLW_APICALL GLuint GLW_APIENTRY glCreateShader (GLenum type)
    492 {
    493 	Context* const ctx = getCurrentContext();
    494 	DE_UNREF(type);
    495 	return (GLuint)ctx->shaders.allocate();
    496 }
    497 
    498 GLW_APICALL void GLW_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params)
    499 {
    500 	DE_UNREF(shader);
    501 
    502 	if (pname == GL_COMPILE_STATUS)
    503 		*params = GL_TRUE;
    504 }
    505 
    506 GLW_APICALL void GLW_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params)
    507 {
    508 	DE_UNREF(program);
    509 
    510 	if (pname == GL_LINK_STATUS)
    511 		*params = GL_TRUE;
    512 }
    513 
    514 GLW_APICALL void GLW_APIENTRY glGenTextures (GLsizei n, GLuint* textures)
    515 {
    516 	Context* const ctx = getCurrentContext();
    517 
    518 	if (textures)
    519 	{
    520 		for (int ndx = 0; ndx < n; ndx++)
    521 			textures[ndx] = ctx->textures.allocate();
    522 	}
    523 }
    524 
    525 GLW_APICALL void GLW_APIENTRY glGenQueries (GLsizei n, GLuint* ids)
    526 {
    527 	Context* const ctx = getCurrentContext();
    528 
    529 	if (ids)
    530 	{
    531 		for (int ndx = 0; ndx < n; ndx++)
    532 			ids[ndx] = ctx->queries.allocate();
    533 	}
    534 }
    535 
    536 GLW_APICALL void GLW_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers)
    537 {
    538 	Context* const ctx = getCurrentContext();
    539 
    540 	if (buffers)
    541 	{
    542 		for (int ndx = 0; ndx < n; ndx++)
    543 			buffers[ndx] = ctx->buffers.allocate();
    544 	}
    545 }
    546 
    547 GLW_APICALL void GLW_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers)
    548 {
    549 	Context* const ctx = getCurrentContext();
    550 
    551 	if (renderbuffers)
    552 	{
    553 		for (int ndx = 0; ndx < n; ndx++)
    554 			renderbuffers[ndx] = ctx->renderbuffers.allocate();
    555 	}
    556 }
    557 
    558 GLW_APICALL void GLW_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers)
    559 {
    560 	Context* const ctx = getCurrentContext();
    561 
    562 	if (framebuffers)
    563 	{
    564 		for (int ndx = 0; ndx < n; ndx++)
    565 			framebuffers[ndx] = ctx->framebuffers.allocate();
    566 	}
    567 }
    568 
    569 GLW_APICALL void GLW_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays)
    570 {
    571 	Context* const ctx = getCurrentContext();
    572 
    573 	if (arrays)
    574 	{
    575 		for (int ndx = 0; ndx < n; ndx++)
    576 			arrays[ndx] = ctx->vertexArrays.allocate();
    577 	}
    578 }
    579 
    580 GLW_APICALL void GLW_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers)
    581 {
    582 	Context* const ctx = getCurrentContext();
    583 
    584 	if (samplers)
    585 	{
    586 		for (int ndx = 0; ndx < count; ndx++)
    587 			samplers[ndx] = ctx->samplers.allocate();
    588 	}
    589 }
    590 
    591 GLW_APICALL void GLW_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids)
    592 {
    593 	Context* const ctx = getCurrentContext();
    594 
    595 	if (ids)
    596 	{
    597 		for (int ndx = 0; ndx < n; ndx++)
    598 			ids[ndx] = ctx->transformFeedbacks.allocate();
    599 	}
    600 }
    601 
    602 GLW_APICALL void GLW_APIENTRY glGenProgramPipelines (GLsizei n, GLuint* pipelines)
    603 {
    604 	Context* const ctx = getCurrentContext();
    605 
    606 	if (pipelines)
    607 	{
    608 		for (int ndx = 0; ndx < n; ndx++)
    609 			pipelines[ndx] = ctx->programPipelines.allocate();
    610 	}
    611 }
    612 
    613 GLW_APICALL GLvoid* GLW_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
    614 {
    615 	Context* const ctx = getCurrentContext();
    616 
    617 	DE_UNREF(target);
    618 	DE_UNREF(offset);
    619 	DE_UNREF(length);
    620 	DE_UNREF(access);
    621 
    622 	if (ctx->lastError == GL_NO_ERROR)
    623 		ctx->lastError = GL_INVALID_OPERATION;
    624 
    625 	return (GLvoid*)0;
    626 }
    627 
    628 GLW_APICALL GLenum GLW_APIENTRY glCheckFramebufferStatus (GLenum target)
    629 {
    630 	DE_UNREF(target);
    631 	return GL_FRAMEBUFFER_COMPLETE;
    632 }
    633 
    634 GLW_APICALL void GLW_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
    635 {
    636 	DE_UNREF(x);
    637 	DE_UNREF(y);
    638 
    639 	Context* const					ctx					= getCurrentContext();
    640 	const tcu::Vec4					clearColor			(0.0f, 0.0f, 0.0f, 1.0f); // black
    641 	const tcu::TextureFormat		transferFormat		= glu::mapGLTransferFormat(format, type);
    642 
    643 	// invalid formats
    644 	if (transferFormat.order == TextureFormat::CHANNELORDER_LAST || transferFormat.type == TextureFormat::CHANNELTYPE_LAST)
    645 	{
    646 		if (ctx->lastError == GL_NO_ERROR)
    647 			ctx->lastError = GL_INVALID_ENUM;
    648 		return;
    649 	}
    650 
    651 	// unsupported formats
    652 	if (!(format == GL_RGBA			&& type == GL_UNSIGNED_BYTE)	&&
    653 		!(format == GL_RGBA_INTEGER	&& type == GL_INT)				&&
    654 		!(format == GL_RGBA_INTEGER	&& type == GL_UNSIGNED_INT)		&&
    655 		!(format == GL_RGBA			&& type == GL_FLOAT))
    656 	{
    657 		if (ctx->lastError == GL_NO_ERROR)
    658 			ctx->lastError = GL_INVALID_ENUM;
    659 		return;
    660 	}
    661 
    662 	// invalid arguments
    663 	if (width < 0 || height < 0)
    664 	{
    665 		if (ctx->lastError == GL_NO_ERROR)
    666 			ctx->lastError = GL_INVALID_OPERATION;
    667 		return;
    668 	}
    669 
    670 	// read to buffer
    671 	if (ctx->pixelPackBufferBufferBinding)
    672 		return;
    673 
    674 	// read to use pointer
    675 	{
    676 		const int						targetRowLength		= (ctx->pixelPackRowLength != 0) ? (ctx->pixelPackRowLength) : (width);
    677 		const int						targetSkipRows		= ctx->pixelPackSkipRows;
    678 		const int						targetSkipPixels	= ctx->pixelPackSkipPixels;
    679 		const int						infiniteHeight		= targetSkipRows + height; // as much as needed
    680 		const int						targetRowPitch		= (ctx->pixelPackAlignment == 0) ? (targetRowLength * transferFormat.getPixelSize()) : (deAlign32(targetRowLength * transferFormat.getPixelSize(), ctx->pixelPackAlignment));
    681 
    682 		// Create access to the whole copy target
    683 		const tcu::PixelBufferAccess	targetAccess		(transferFormat, targetRowLength, infiniteHeight, 1, targetRowPitch, 0, pixels);
    684 
    685 		// Select (skip_pixels, skip_rows, width, height) subregion from it. Clip to horizontal boundaries
    686 		const tcu::PixelBufferAccess	targetRectAccess	= tcu::getSubregion(targetAccess,
    687 																				de::clamp(targetSkipPixels, 0, targetAccess.getWidth()-1),
    688 																				targetSkipRows,
    689 																				de::clamp(width, 0, de::max(0, targetAccess.getWidth() - targetSkipPixels)),
    690 																				height);
    691 
    692 		tcu::clear(targetRectAccess, clearColor);
    693 	}
    694 }
    695 
    696 GLW_APICALL void GLW_APIENTRY glBindBuffer (GLenum target, GLuint buffer)
    697 {
    698 	Context* const ctx = getCurrentContext();
    699 
    700 	if (target == GL_PIXEL_PACK_BUFFER)
    701 		ctx->pixelPackBufferBufferBinding = buffer;
    702 }
    703 
    704 GLW_APICALL void GLW_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers)
    705 {
    706 	Context* const ctx = getCurrentContext();
    707 
    708 	for (GLsizei ndx = 0; ndx < n; ++ndx)
    709 		if (buffers[ndx] && buffers[ndx] == ctx->pixelPackBufferBufferBinding)
    710 			ctx->pixelPackBufferBufferBinding = 0;
    711 }
    712 
    713 GLW_APICALL GLint GLW_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name)
    714 {
    715 	DE_UNREF(program);
    716 	return (GLint)(deStringHash(name) & 0x7FFFFFFF);
    717 }
    718 
    719 void initFunctions (glw::Functions* gl)
    720 {
    721 #	include "tcuNullRenderContextInitFuncs.inl"
    722 }
    723 
    724 static tcu::RenderTarget toRenderTarget (const RenderConfig& renderCfg)
    725 {
    726 	const int		width			= getValueOrDefault(renderCfg, &RenderConfig::width,		256);
    727 	const int		height			= getValueOrDefault(renderCfg, &RenderConfig::height,		256);
    728 	const int		redBits			= getValueOrDefault(renderCfg, &RenderConfig::redBits,		8);
    729 	const int		greenBits		= getValueOrDefault(renderCfg, &RenderConfig::greenBits,	8);
    730 	const int		blueBits		= getValueOrDefault(renderCfg, &RenderConfig::blueBits,		8);
    731 	const int		alphaBits		= getValueOrDefault(renderCfg, &RenderConfig::alphaBits,	8);
    732 	const int		depthBits		= getValueOrDefault(renderCfg, &RenderConfig::depthBits,	24);
    733 	const int		stencilBits		= getValueOrDefault(renderCfg, &RenderConfig::stencilBits,	8);
    734 	const int		numSamples		= getValueOrDefault(renderCfg, &RenderConfig::numSamples,	0);
    735 
    736 	return tcu::RenderTarget(width, height, tcu::PixelFormat(redBits, greenBits, blueBits, alphaBits), depthBits, stencilBits, numSamples);
    737 }
    738 
    739 RenderContext::RenderContext (const RenderConfig& renderCfg)
    740 	: m_ctxType			(renderCfg.type)
    741 	, m_renderTarget	(toRenderTarget(renderCfg))
    742 	, m_context			(DE_NULL)
    743 {
    744 	m_context = new Context(m_ctxType);
    745 
    746 	initFunctions(&m_functions);
    747 	setCurrentContext(m_context);
    748 }
    749 
    750 RenderContext::~RenderContext (void)
    751 {
    752 	setCurrentContext(DE_NULL);
    753 	delete m_context;
    754 }
    755 
    756 void RenderContext::postIterate (void)
    757 {
    758 }
    759 
    760 } // null
    761 } // tcu
    762