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 (ctxType.getAPI() == ApiType::es(3, 2))
    172 	{
    173 		version					= "OpenGL ES 3.2";
    174 		shadingLanguageVersion	= "OpenGL ES GLSL ES 3.2";
    175 	}
    176 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 3)
    177 	{
    178 		version					= "3.3.0";
    179 		shadingLanguageVersion	= "3.30";
    180 	}
    181 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() <= 4)
    182 	{
    183 		version					= "4.4.0";
    184 		shadingLanguageVersion	= "4.40";
    185 	}
    186 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() == 5)
    187 	{
    188 		version					= "4.5.0";
    189 		shadingLanguageVersion	= "4.50";
    190 	}
    191 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() == 6)
    192 	{
    193 		version					= "4.6.0";
    194 		shadingLanguageVersion	= "4.60";
    195 	}
    196 	else
    197 		throw tcu::NotSupportedError("Unsupported GL version", "", __FILE__, __LINE__);
    198 
    199 	if (isContextTypeES(ctxType))
    200 	{
    201 		addExtension("GL_EXT_color_buffer_float");
    202 		addExtension("GL_EXT_color_buffer_half_float");
    203 	}
    204 
    205 	// support compressed formats
    206 	{
    207 		static deUint32 compressedFormats[] =
    208 		{
    209 			GL_ETC1_RGB8_OES,
    210 			GL_COMPRESSED_R11_EAC,
    211 			GL_COMPRESSED_SIGNED_R11_EAC,
    212 			GL_COMPRESSED_RG11_EAC,
    213 			GL_COMPRESSED_SIGNED_RG11_EAC,
    214 			GL_COMPRESSED_RGB8_ETC2,
    215 			GL_COMPRESSED_SRGB8_ETC2,
    216 			GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
    217 			GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
    218 			GL_COMPRESSED_RGBA8_ETC2_EAC,
    219 			GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
    220 			GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
    221 			GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
    222 			GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
    223 			GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
    224 			GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
    225 			GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
    226 			GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
    227 			GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
    228 			GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
    229 			GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
    230 			GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
    231 			GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
    232 			GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
    233 			GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
    234 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
    235 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
    236 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
    237 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
    238 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
    239 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
    240 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
    241 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
    242 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
    243 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
    244 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
    245 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
    246 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
    247 			GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
    248 		};
    249 
    250 		addExtension("GL_KHR_texture_compression_astc_hdr");
    251 		addExtension("GL_KHR_texture_compression_astc_ldr");
    252 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(compressedFormats); ++ndx)
    253 			compressedTextureList.push_back(compressedFormats[ndx]);
    254 	}
    255 }
    256 
    257 Context::~Context (void)
    258 {
    259 }
    260 
    261 void Context::addExtension (const char* name)
    262 {
    263 	if (!extensions.empty())
    264 		extensions += " ";
    265 	extensions += name;
    266 
    267 	extensionList.push_back(name);
    268 }
    269 
    270 static de::ThreadLocal s_currentCtx;
    271 
    272 void setCurrentContext (Context* context)
    273 {
    274 	s_currentCtx.set((void*)context);
    275 }
    276 
    277 Context* getCurrentContext (void)
    278 {
    279 	return (Context*)s_currentCtx.get();
    280 }
    281 
    282 GLW_APICALL GLenum GLW_APIENTRY glGetError (void)
    283 {
    284 	Context* const	ctx		= getCurrentContext();
    285 	const GLenum	lastErr	= ctx->lastError;
    286 
    287 	ctx->lastError = GL_NO_ERROR;
    288 
    289 	return lastErr;
    290 }
    291 
    292 GLW_APICALL void GLW_APIENTRY glGetIntegerv (GLenum pname, GLint* params)
    293 {
    294 	Context* const ctx = getCurrentContext();
    295 
    296 	switch (pname)
    297 	{
    298 		case GL_NUM_EXTENSIONS:
    299 			*params = (int)ctx->extensionList.size();
    300 			break;
    301 
    302 		case GL_MAX_VERTEX_ATTRIBS:
    303 			*params = 32;
    304 			break;
    305 
    306 		case GL_MAX_DRAW_BUFFERS:
    307 		case GL_MAX_COLOR_ATTACHMENTS:
    308 			*params = 8;
    309 			break;
    310 
    311 		case GL_MAX_TEXTURE_IMAGE_UNITS:
    312 		case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    313 		case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    314 		case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
    315 		case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS:
    316 		case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS:
    317 			*params = 32;
    318 			break;
    319 
    320 		case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
    321 		case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
    322 		case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS:
    323 		case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
    324 		case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS:
    325 		case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
    326 			*params = 8;
    327 			break;
    328 
    329 		case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
    330 		case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
    331 		case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS:
    332 		case GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS:
    333 		case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS:
    334 		case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
    335 			*params = 8;
    336 			break;
    337 
    338 		case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
    339 			*params = 1u << 25;
    340 			break;
    341 
    342 		case GL_MAX_GEOMETRY_OUTPUT_VERTICES:
    343 			*params = 256;
    344 			break;
    345 
    346 		case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
    347 			*params = 2048;
    348 			break;
    349 
    350 		case GL_MAX_GEOMETRY_SHADER_INVOCATIONS:
    351 			*params = 4;
    352 			break;
    353 
    354 		case GL_MAX_COLOR_TEXTURE_SAMPLES:
    355 			*params = 8;
    356 			break;
    357 
    358 		case GL_MAX_TEXTURE_SIZE:
    359 		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    360 		case GL_MAX_3D_TEXTURE_SIZE:
    361 		case GL_MAX_RENDERBUFFER_SIZE:
    362 		case GL_MAX_TEXTURE_BUFFER_SIZE:
    363 			*params = 2048;
    364 			break;
    365 
    366 		case GL_MAX_ARRAY_TEXTURE_LAYERS:
    367 			*params = 128;
    368 			break;
    369 
    370 		case GL_NUM_SHADER_BINARY_FORMATS:
    371 			*params = 0;
    372 			break;
    373 
    374 		case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    375 			*params = (int)ctx->compressedTextureList.size();
    376 			break;
    377 
    378 		case GL_COMPRESSED_TEXTURE_FORMATS:
    379 			deMemcpy(params, &ctx->compressedTextureList[0], ctx->compressedTextureList.size()*sizeof(deUint32));
    380 			break;
    381 
    382 		case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
    383 			*params = 16;
    384 			break;
    385 
    386 		case GL_MAX_UNIFORM_BUFFER_BINDINGS:
    387 			*params = 32;
    388 			break;
    389 
    390 		case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
    391 			*params = 16;
    392 			break;
    393 
    394 		case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
    395 			*params = GL_RGBA;
    396 			break;
    397 
    398 		case GL_IMPLEMENTATION_COLOR_READ_TYPE:
    399 			*params = GL_UNSIGNED_BYTE;
    400 			break;
    401 
    402 		case GL_SAMPLE_BUFFERS:
    403 			*params = 0;
    404 			break;
    405 
    406 		default:
    407 			break;
    408 	}
    409 }
    410 
    411 GLW_APICALL void GLW_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params)
    412 {
    413 	switch (pname)
    414 	{
    415 		case GL_SHADER_COMPILER:
    416 			*params = GL_TRUE;
    417 			break;
    418 
    419 		default:
    420 			break;
    421 	}
    422 }
    423 
    424 GLW_APICALL void GLW_APIENTRY glGetFloatv (GLenum pname, GLfloat* params)
    425 {
    426 	switch (pname)
    427 	{
    428 		case GL_ALIASED_LINE_WIDTH_RANGE:
    429 		case GL_ALIASED_POINT_SIZE_RANGE:
    430 			params[0] = 0.0f;
    431 			params[1] = 64.0f;
    432 			break;
    433 
    434 		default:
    435 			break;
    436 	}
    437 }
    438 
    439 GLW_APICALL void GLW_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
    440 {
    441 	static const int s_sampleCounts[] = { 16, 8, 4, 2, 1 };
    442 
    443 	DE_UNREF(internalformat);
    444 	DE_UNREF(target);
    445 
    446 	switch (pname)
    447 	{
    448 		case GL_NUM_SAMPLE_COUNTS:
    449 			if (bufSize >= 1)
    450 				*params = DE_LENGTH_OF_ARRAY(s_sampleCounts);
    451 			break;
    452 
    453 		case GL_SAMPLES:
    454 			deMemcpy(params, s_sampleCounts, de::min(bufSize, DE_LENGTH_OF_ARRAY(s_sampleCounts)));
    455 			break;
    456 
    457 		default:
    458 			break;
    459 	}
    460 }
    461 
    462 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetString (GLenum name)
    463 {
    464 	Context* const ctx = getCurrentContext();
    465 
    466 	switch (name)
    467 	{
    468 		case GL_VENDOR:						return (const glw::GLubyte*)ctx->vendor.c_str();
    469 		case GL_VERSION:					return (const glw::GLubyte*)ctx->version.c_str();
    470 		case GL_RENDERER:					return (const glw::GLubyte*)ctx->renderer.c_str();
    471 		case GL_SHADING_LANGUAGE_VERSION:	return (const glw::GLubyte*)ctx->shadingLanguageVersion.c_str();
    472 		case GL_EXTENSIONS:					return (const glw::GLubyte*)ctx->extensions.c_str();
    473 		default:
    474 			ctx->lastError = GL_INVALID_ENUM;
    475 			return DE_NULL;
    476 	}
    477 }
    478 
    479 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetStringi (GLenum name, GLuint index)
    480 {
    481 	Context* const ctx = getCurrentContext();
    482 
    483 	if (name == GL_EXTENSIONS)
    484 	{
    485 		if ((size_t)index < ctx->extensionList.size())
    486 			return (const glw::GLubyte*)ctx->extensionList[index].c_str();
    487 		else
    488 		{
    489 			ctx->lastError = GL_INVALID_VALUE;
    490 			return DE_NULL;
    491 		}
    492 	}
    493 	else
    494 	{
    495 		ctx->lastError = GL_INVALID_ENUM;
    496 		return DE_NULL;
    497 	}
    498 }
    499 
    500 GLW_APICALL GLuint GLW_APIENTRY glCreateProgram ()
    501 {
    502 	Context* const ctx = getCurrentContext();
    503 	return (GLuint)ctx->programs.allocate();
    504 }
    505 
    506 GLW_APICALL GLuint GLW_APIENTRY glCreateShader (GLenum type)
    507 {
    508 	Context* const ctx = getCurrentContext();
    509 	DE_UNREF(type);
    510 	return (GLuint)ctx->shaders.allocate();
    511 }
    512 
    513 GLW_APICALL void GLW_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params)
    514 {
    515 	DE_UNREF(shader);
    516 
    517 	if (pname == GL_COMPILE_STATUS)
    518 		*params = GL_TRUE;
    519 }
    520 
    521 GLW_APICALL void GLW_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params)
    522 {
    523 	DE_UNREF(program);
    524 
    525 	if (pname == GL_LINK_STATUS)
    526 		*params = GL_TRUE;
    527 }
    528 
    529 GLW_APICALL void GLW_APIENTRY glGenTextures (GLsizei n, GLuint* textures)
    530 {
    531 	Context* const ctx = getCurrentContext();
    532 
    533 	if (textures)
    534 	{
    535 		for (int ndx = 0; ndx < n; ndx++)
    536 			textures[ndx] = ctx->textures.allocate();
    537 	}
    538 }
    539 
    540 GLW_APICALL void GLW_APIENTRY glGenQueries (GLsizei n, GLuint* ids)
    541 {
    542 	Context* const ctx = getCurrentContext();
    543 
    544 	if (ids)
    545 	{
    546 		for (int ndx = 0; ndx < n; ndx++)
    547 			ids[ndx] = ctx->queries.allocate();
    548 	}
    549 }
    550 
    551 GLW_APICALL void GLW_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers)
    552 {
    553 	Context* const ctx = getCurrentContext();
    554 
    555 	if (buffers)
    556 	{
    557 		for (int ndx = 0; ndx < n; ndx++)
    558 			buffers[ndx] = ctx->buffers.allocate();
    559 	}
    560 }
    561 
    562 GLW_APICALL void GLW_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers)
    563 {
    564 	Context* const ctx = getCurrentContext();
    565 
    566 	if (renderbuffers)
    567 	{
    568 		for (int ndx = 0; ndx < n; ndx++)
    569 			renderbuffers[ndx] = ctx->renderbuffers.allocate();
    570 	}
    571 }
    572 
    573 GLW_APICALL void GLW_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers)
    574 {
    575 	Context* const ctx = getCurrentContext();
    576 
    577 	if (framebuffers)
    578 	{
    579 		for (int ndx = 0; ndx < n; ndx++)
    580 			framebuffers[ndx] = ctx->framebuffers.allocate();
    581 	}
    582 }
    583 
    584 GLW_APICALL void GLW_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays)
    585 {
    586 	Context* const ctx = getCurrentContext();
    587 
    588 	if (arrays)
    589 	{
    590 		for (int ndx = 0; ndx < n; ndx++)
    591 			arrays[ndx] = ctx->vertexArrays.allocate();
    592 	}
    593 }
    594 
    595 GLW_APICALL void GLW_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers)
    596 {
    597 	Context* const ctx = getCurrentContext();
    598 
    599 	if (samplers)
    600 	{
    601 		for (int ndx = 0; ndx < count; ndx++)
    602 			samplers[ndx] = ctx->samplers.allocate();
    603 	}
    604 }
    605 
    606 GLW_APICALL void GLW_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids)
    607 {
    608 	Context* const ctx = getCurrentContext();
    609 
    610 	if (ids)
    611 	{
    612 		for (int ndx = 0; ndx < n; ndx++)
    613 			ids[ndx] = ctx->transformFeedbacks.allocate();
    614 	}
    615 }
    616 
    617 GLW_APICALL void GLW_APIENTRY glGenProgramPipelines (GLsizei n, GLuint* pipelines)
    618 {
    619 	Context* const ctx = getCurrentContext();
    620 
    621 	if (pipelines)
    622 	{
    623 		for (int ndx = 0; ndx < n; ndx++)
    624 			pipelines[ndx] = ctx->programPipelines.allocate();
    625 	}
    626 }
    627 
    628 GLW_APICALL GLvoid* GLW_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
    629 {
    630 	Context* const ctx = getCurrentContext();
    631 
    632 	DE_UNREF(target);
    633 	DE_UNREF(offset);
    634 	DE_UNREF(length);
    635 	DE_UNREF(access);
    636 
    637 	if (ctx->lastError == GL_NO_ERROR)
    638 		ctx->lastError = GL_INVALID_OPERATION;
    639 
    640 	return (GLvoid*)0;
    641 }
    642 
    643 GLW_APICALL GLenum GLW_APIENTRY glCheckFramebufferStatus (GLenum target)
    644 {
    645 	DE_UNREF(target);
    646 	return GL_FRAMEBUFFER_COMPLETE;
    647 }
    648 
    649 GLW_APICALL void GLW_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
    650 {
    651 	DE_UNREF(x);
    652 	DE_UNREF(y);
    653 
    654 	Context* const					ctx					= getCurrentContext();
    655 	const tcu::Vec4					clearColor			(0.0f, 0.0f, 0.0f, 1.0f); // black
    656 	const tcu::TextureFormat		transferFormat		= glu::mapGLTransferFormat(format, type);
    657 
    658 	// invalid formats
    659 	if (transferFormat.order == TextureFormat::CHANNELORDER_LAST || transferFormat.type == TextureFormat::CHANNELTYPE_LAST)
    660 	{
    661 		if (ctx->lastError == GL_NO_ERROR)
    662 			ctx->lastError = GL_INVALID_ENUM;
    663 		return;
    664 	}
    665 
    666 	// unsupported formats
    667 	if (!(format == GL_RGBA			&& type == GL_UNSIGNED_BYTE)	&&
    668 		!(format == GL_RGBA_INTEGER	&& type == GL_INT)				&&
    669 		!(format == GL_RGBA_INTEGER	&& type == GL_UNSIGNED_INT)		&&
    670 		!(format == GL_RGBA			&& type == GL_FLOAT))
    671 	{
    672 		if (ctx->lastError == GL_NO_ERROR)
    673 			ctx->lastError = GL_INVALID_ENUM;
    674 		return;
    675 	}
    676 
    677 	// invalid arguments
    678 	if (width < 0 || height < 0)
    679 	{
    680 		if (ctx->lastError == GL_NO_ERROR)
    681 			ctx->lastError = GL_INVALID_OPERATION;
    682 		return;
    683 	}
    684 
    685 	// read to buffer
    686 	if (ctx->pixelPackBufferBufferBinding)
    687 		return;
    688 
    689 	// read to use pointer
    690 	{
    691 		const int						targetRowLength		= (ctx->pixelPackRowLength != 0) ? (ctx->pixelPackRowLength) : (width);
    692 		const int						targetSkipRows		= ctx->pixelPackSkipRows;
    693 		const int						targetSkipPixels	= ctx->pixelPackSkipPixels;
    694 		const int						infiniteHeight		= targetSkipRows + height; // as much as needed
    695 		const int						targetRowPitch		= (ctx->pixelPackAlignment == 0) ? (targetRowLength * transferFormat.getPixelSize()) : (deAlign32(targetRowLength * transferFormat.getPixelSize(), ctx->pixelPackAlignment));
    696 
    697 		// Create access to the whole copy target
    698 		const tcu::PixelBufferAccess	targetAccess		(transferFormat, targetRowLength, infiniteHeight, 1, targetRowPitch, 0, pixels);
    699 
    700 		// Select (skip_pixels, skip_rows, width, height) subregion from it. Clip to horizontal boundaries
    701 		const tcu::PixelBufferAccess	targetRectAccess	= tcu::getSubregion(targetAccess,
    702 																				de::clamp(targetSkipPixels, 0, targetAccess.getWidth()-1),
    703 																				targetSkipRows,
    704 																				de::clamp(width, 0, de::max(0, targetAccess.getWidth() - targetSkipPixels)),
    705 																				height);
    706 
    707 		tcu::clear(targetRectAccess, clearColor);
    708 	}
    709 }
    710 
    711 GLW_APICALL void GLW_APIENTRY glBindBuffer (GLenum target, GLuint buffer)
    712 {
    713 	Context* const ctx = getCurrentContext();
    714 
    715 	if (target == GL_PIXEL_PACK_BUFFER)
    716 		ctx->pixelPackBufferBufferBinding = buffer;
    717 }
    718 
    719 GLW_APICALL void GLW_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers)
    720 {
    721 	Context* const ctx = getCurrentContext();
    722 
    723 	for (GLsizei ndx = 0; ndx < n; ++ndx)
    724 		if (buffers[ndx] && buffers[ndx] == ctx->pixelPackBufferBufferBinding)
    725 			ctx->pixelPackBufferBufferBinding = 0;
    726 }
    727 
    728 GLW_APICALL GLint GLW_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name)
    729 {
    730 	DE_UNREF(program);
    731 	return (GLint)(deStringHash(name) & 0x7FFFFFFF);
    732 }
    733 
    734 void initFunctions (glw::Functions* gl)
    735 {
    736 #	include "tcuNullRenderContextInitFuncs.inl"
    737 }
    738 
    739 static tcu::RenderTarget toRenderTarget (const RenderConfig& renderCfg)
    740 {
    741 	const int		width			= getValueOrDefault(renderCfg, &RenderConfig::width,		256);
    742 	const int		height			= getValueOrDefault(renderCfg, &RenderConfig::height,		256);
    743 	const int		redBits			= getValueOrDefault(renderCfg, &RenderConfig::redBits,		8);
    744 	const int		greenBits		= getValueOrDefault(renderCfg, &RenderConfig::greenBits,	8);
    745 	const int		blueBits		= getValueOrDefault(renderCfg, &RenderConfig::blueBits,		8);
    746 	const int		alphaBits		= getValueOrDefault(renderCfg, &RenderConfig::alphaBits,	8);
    747 	const int		depthBits		= getValueOrDefault(renderCfg, &RenderConfig::depthBits,	24);
    748 	const int		stencilBits		= getValueOrDefault(renderCfg, &RenderConfig::stencilBits,	8);
    749 	const int		numSamples		= getValueOrDefault(renderCfg, &RenderConfig::numSamples,	0);
    750 
    751 	return tcu::RenderTarget(width, height, tcu::PixelFormat(redBits, greenBits, blueBits, alphaBits), depthBits, stencilBits, numSamples);
    752 }
    753 
    754 RenderContext::RenderContext (const RenderConfig& renderCfg)
    755 	: m_ctxType			(renderCfg.type)
    756 	, m_renderTarget	(toRenderTarget(renderCfg))
    757 	, m_context			(DE_NULL)
    758 {
    759 	m_context = new Context(m_ctxType);
    760 
    761 	initFunctions(&m_functions);
    762 	setCurrentContext(m_context);
    763 }
    764 
    765 RenderContext::~RenderContext (void)
    766 {
    767 	setCurrentContext(DE_NULL);
    768 	delete m_context;
    769 }
    770 
    771 void RenderContext::postIterate (void)
    772 {
    773 }
    774 
    775 void RenderContext::makeCurrent (void)
    776 {
    777 }
    778 
    779 } // null
    780 } // tcu
    781