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 std::string; 41 using std::vector; 42 using namespace glw; 43 using namespace glu; 44 45 class ObjectManager 46 { 47 public: 48 ObjectManager (void) 49 : m_lastObject(0) 50 { 51 } 52 53 deUint32 allocate (void) 54 { 55 deUint32 object = ++m_lastObject; 56 if (object == 0) 57 object = ++m_lastObject; // Just ignore overflow. 58 return object; 59 } 60 61 void free (deUint32 object) 62 { 63 DE_UNREF(object); 64 } 65 66 private: 67 deUint32 m_lastObject; 68 }; 69 70 class Context 71 { 72 public: 73 Context (ContextType ctxType_); 74 ~Context (void); 75 76 private: 77 Context (const Context&); 78 Context& operator= (const Context&); 79 80 void addExtension (const char* name); 81 82 public: 83 // GL state exposed to implementation functions. 84 const ContextType ctxType; 85 86 string vendor; 87 string version; 88 string renderer; 89 string shadingLanguageVersion; 90 string extensions; 91 vector<string> extensionList; 92 93 GLenum lastError; 94 95 int pixelPackRowLength; 96 int pixelPackSkipRows; 97 int pixelPackSkipPixels; 98 int pixelPackAlignment; 99 100 GLuint pixelPackBufferBufferBinding; 101 102 ObjectManager shaders; 103 ObjectManager programs; 104 ObjectManager textures; 105 ObjectManager buffers; 106 ObjectManager renderbuffers; 107 ObjectManager framebuffers; 108 ObjectManager samplers; 109 ObjectManager vertexArrays; 110 ObjectManager queries; 111 ObjectManager transformFeedbacks; 112 ObjectManager programPipelines; 113 }; 114 115 Context::Context (ContextType ctxType_) 116 : ctxType (ctxType_) 117 , vendor ("drawElements") 118 , renderer ("dummy") 119 , lastError (GL_NO_ERROR) 120 , pixelPackRowLength (0) 121 , pixelPackSkipRows (0) 122 , pixelPackSkipPixels (0) 123 , pixelPackAlignment (0) 124 , pixelPackBufferBufferBinding (0) 125 { 126 using glu::ApiType; 127 128 if (ctxType.getAPI() == ApiType::es(2, 0)) 129 { 130 version = "OpenGL ES 2.0"; 131 shadingLanguageVersion = "OpenGL ES GLSL ES 1.0"; 132 } 133 else if (ctxType.getAPI() == ApiType::es(3, 0)) 134 { 135 version = "OpenGL ES 3.0"; 136 shadingLanguageVersion = "OpenGL ES GLSL ES 3.0"; 137 } 138 else if (ctxType.getAPI() == ApiType::es(3, 1)) 139 { 140 version = "OpenGL ES 3.1"; 141 shadingLanguageVersion = "OpenGL ES GLSL ES 3.1"; 142 addExtension("GL_OES_texture_stencil8"); 143 addExtension("GL_OES_sample_shading"); 144 addExtension("GL_OES_sample_variables"); 145 addExtension("GL_OES_shader_multisample_interpolation"); 146 addExtension("GL_OES_shader_image_atomics"); 147 addExtension("GL_OES_texture_storage_multisample_2d_array"); 148 addExtension("GL_KHR_blend_equation_advanced"); 149 addExtension("GL_KHR_blend_equation_advanced_coherent"); 150 addExtension("GL_EXT_shader_io_blocks"); 151 addExtension("GL_EXT_geometry_shader"); 152 addExtension("GL_EXT_geometry_point_size"); 153 addExtension("GL_EXT_tessellation_shader"); 154 addExtension("GL_EXT_tessellation_point_size"); 155 addExtension("GL_EXT_gpu_shader5"); 156 } 157 else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 3) 158 { 159 version = "3.3.0"; 160 shadingLanguageVersion = "3.30"; 161 } 162 else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() <= 4) 163 { 164 version = "4.4.0"; 165 shadingLanguageVersion = "4.40"; 166 } 167 else 168 throw tcu::NotSupportedError("Unsupported GL version", "", __FILE__, __LINE__); 169 170 if (isContextTypeES(ctxType)) 171 addExtension("GL_EXT_color_buffer_float"); 172 } 173 174 Context::~Context (void) 175 { 176 } 177 178 void Context::addExtension (const char* name) 179 { 180 if (!extensions.empty()) 181 extensions += " "; 182 extensions += name; 183 184 extensionList.push_back(name); 185 } 186 187 static de::ThreadLocal s_currentCtx; 188 189 void setCurrentContext (Context* context) 190 { 191 s_currentCtx.set((void*)context); 192 } 193 194 Context* getCurrentContext (void) 195 { 196 return (Context*)s_currentCtx.get(); 197 } 198 199 GLW_APICALL GLenum GLW_APIENTRY glGetError (void) 200 { 201 Context* const ctx = getCurrentContext(); 202 const GLenum lastErr = ctx->lastError; 203 204 ctx->lastError = GL_NO_ERROR; 205 206 return lastErr; 207 } 208 209 GLW_APICALL void GLW_APIENTRY glGetIntegerv (GLenum pname, GLint* params) 210 { 211 Context* const ctx = getCurrentContext(); 212 213 switch (pname) 214 { 215 case GL_NUM_EXTENSIONS: 216 *params = (int)ctx->extensionList.size(); 217 break; 218 219 case GL_MAX_VERTEX_ATTRIBS: 220 *params = 32; 221 break; 222 223 case GL_MAX_DRAW_BUFFERS: 224 case GL_MAX_COLOR_ATTACHMENTS: 225 *params = 8; 226 break; 227 228 case GL_MAX_TEXTURE_IMAGE_UNITS: 229 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 230 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 231 case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS: 232 case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS: 233 case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS: 234 *params = 16; 235 break; 236 237 case GL_MAX_TEXTURE_SIZE: 238 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: 239 case GL_MAX_3D_TEXTURE_SIZE: 240 case GL_MAX_RENDERBUFFER_SIZE: 241 *params = 2048; 242 break; 243 244 case GL_MAX_ARRAY_TEXTURE_LAYERS: 245 *params = 128; 246 break; 247 248 case GL_NUM_SHADER_BINARY_FORMATS: 249 *params = 0; 250 break; 251 252 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: 253 *params = 0; 254 break; 255 256 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: 257 *params = 16; 258 break; 259 260 case GL_MAX_UNIFORM_BUFFER_BINDINGS: 261 *params = 32; 262 break; 263 264 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: 265 *params = 16; 266 break; 267 268 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 269 *params = GL_RGBA; 270 break; 271 272 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 273 *params = GL_UNSIGNED_BYTE; 274 break; 275 276 case GL_SAMPLE_BUFFERS: 277 *params = 0; 278 break; 279 280 default: 281 break; 282 } 283 } 284 285 GLW_APICALL void GLW_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params) 286 { 287 switch (pname) 288 { 289 case GL_SHADER_COMPILER: 290 *params = GL_TRUE; 291 break; 292 293 default: 294 break; 295 } 296 } 297 298 GLW_APICALL void GLW_APIENTRY glGetFloatv (GLenum pname, GLfloat* params) 299 { 300 switch (pname) 301 { 302 case GL_ALIASED_LINE_WIDTH_RANGE: 303 case GL_ALIASED_POINT_SIZE_RANGE: 304 params[0] = 0.0f; 305 params[1] = 64.0f; 306 break; 307 308 default: 309 break; 310 } 311 } 312 313 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetString (GLenum name) 314 { 315 Context* const ctx = getCurrentContext(); 316 317 switch (name) 318 { 319 case GL_VENDOR: return (const glw::GLubyte*)ctx->vendor.c_str(); 320 case GL_VERSION: return (const glw::GLubyte*)ctx->version.c_str(); 321 case GL_RENDERER: return (const glw::GLubyte*)ctx->renderer.c_str(); 322 case GL_SHADING_LANGUAGE_VERSION: return (const glw::GLubyte*)ctx->shadingLanguageVersion.c_str(); 323 case GL_EXTENSIONS: return (const glw::GLubyte*)ctx->extensions.c_str(); 324 default: 325 ctx->lastError = GL_INVALID_ENUM; 326 return DE_NULL; 327 } 328 } 329 330 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetStringi (GLenum name, GLuint index) 331 { 332 Context* const ctx = getCurrentContext(); 333 334 if (name == GL_EXTENSIONS) 335 { 336 if ((size_t)index < ctx->extensionList.size()) 337 return (const glw::GLubyte*)ctx->extensionList[index].c_str(); 338 else 339 { 340 ctx->lastError = GL_INVALID_VALUE; 341 return DE_NULL; 342 } 343 } 344 else 345 { 346 ctx->lastError = GL_INVALID_ENUM; 347 return DE_NULL; 348 } 349 } 350 351 GLW_APICALL GLuint GLW_APIENTRY glCreateProgram () 352 { 353 Context* const ctx = getCurrentContext(); 354 return (GLuint)ctx->programs.allocate(); 355 } 356 357 GLW_APICALL GLuint GLW_APIENTRY glCreateShader (GLenum type) 358 { 359 Context* const ctx = getCurrentContext(); 360 DE_UNREF(type); 361 return (GLuint)ctx->shaders.allocate(); 362 } 363 364 GLW_APICALL void GLW_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params) 365 { 366 DE_UNREF(shader); 367 368 if (pname == GL_COMPILE_STATUS) 369 *params = GL_TRUE; 370 } 371 372 GLW_APICALL void GLW_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params) 373 { 374 DE_UNREF(program); 375 376 if (pname == GL_LINK_STATUS) 377 *params = GL_TRUE; 378 } 379 380 GLW_APICALL void GLW_APIENTRY glGenTextures (GLsizei n, GLuint* textures) 381 { 382 Context* const ctx = getCurrentContext(); 383 384 if (textures) 385 { 386 for (int ndx = 0; ndx < n; ndx++) 387 textures[ndx] = ctx->textures.allocate(); 388 } 389 } 390 391 GLW_APICALL void GLW_APIENTRY glGenQueries (GLsizei n, GLuint* ids) 392 { 393 Context* const ctx = getCurrentContext(); 394 395 if (ids) 396 { 397 for (int ndx = 0; ndx < n; ndx++) 398 ids[ndx] = ctx->queries.allocate(); 399 } 400 } 401 402 GLW_APICALL void GLW_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers) 403 { 404 Context* const ctx = getCurrentContext(); 405 406 if (buffers) 407 { 408 for (int ndx = 0; ndx < n; ndx++) 409 buffers[ndx] = ctx->buffers.allocate(); 410 } 411 } 412 413 GLW_APICALL void GLW_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) 414 { 415 Context* const ctx = getCurrentContext(); 416 417 if (renderbuffers) 418 { 419 for (int ndx = 0; ndx < n; ndx++) 420 renderbuffers[ndx] = ctx->renderbuffers.allocate(); 421 } 422 } 423 424 GLW_APICALL void GLW_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers) 425 { 426 Context* const ctx = getCurrentContext(); 427 428 if (framebuffers) 429 { 430 for (int ndx = 0; ndx < n; ndx++) 431 framebuffers[ndx] = ctx->framebuffers.allocate(); 432 } 433 } 434 435 GLW_APICALL void GLW_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays) 436 { 437 Context* const ctx = getCurrentContext(); 438 439 if (arrays) 440 { 441 for (int ndx = 0; ndx < n; ndx++) 442 arrays[ndx] = ctx->vertexArrays.allocate(); 443 } 444 } 445 446 GLW_APICALL void GLW_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers) 447 { 448 Context* const ctx = getCurrentContext(); 449 450 if (samplers) 451 { 452 for (int ndx = 0; ndx < count; ndx++) 453 samplers[ndx] = ctx->samplers.allocate(); 454 } 455 } 456 457 GLW_APICALL void GLW_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids) 458 { 459 Context* const ctx = getCurrentContext(); 460 461 if (ids) 462 { 463 for (int ndx = 0; ndx < n; ndx++) 464 ids[ndx] = ctx->transformFeedbacks.allocate(); 465 } 466 } 467 468 GLW_APICALL void GLW_APIENTRY glGenProgramPipelines (GLsizei n, GLuint* pipelines) 469 { 470 Context* const ctx = getCurrentContext(); 471 472 if (pipelines) 473 { 474 for (int ndx = 0; ndx < n; ndx++) 475 pipelines[ndx] = ctx->programPipelines.allocate(); 476 } 477 } 478 479 GLW_APICALL GLvoid* GLW_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) 480 { 481 Context* const ctx = getCurrentContext(); 482 483 DE_UNREF(target); 484 DE_UNREF(offset); 485 DE_UNREF(length); 486 DE_UNREF(access); 487 488 if (ctx->lastError == GL_NO_ERROR) 489 ctx->lastError = GL_INVALID_OPERATION; 490 491 return (GLvoid*)0; 492 } 493 494 GLW_APICALL GLenum GLW_APIENTRY glCheckFramebufferStatus (GLenum target) 495 { 496 DE_UNREF(target); 497 return GL_FRAMEBUFFER_COMPLETE; 498 } 499 500 GLW_APICALL void GLW_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) 501 { 502 DE_UNREF(x); 503 DE_UNREF(y); 504 505 Context* const ctx = getCurrentContext(); 506 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); // black 507 const tcu::TextureFormat transferFormat = glu::mapGLTransferFormat(format, type); 508 509 // invalid formats 510 if (transferFormat.order == TextureFormat::CHANNELORDER_LAST || transferFormat.type == TextureFormat::CHANNELTYPE_LAST) 511 { 512 if (ctx->lastError == GL_NO_ERROR) 513 ctx->lastError = GL_INVALID_ENUM; 514 return; 515 } 516 517 // unsupported formats 518 if (!(format == GL_RGBA && type == GL_UNSIGNED_BYTE) && 519 !(format == GL_RGBA_INTEGER && type == GL_INT) && 520 !(format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT) && 521 !(format == GL_RGBA && type == GL_FLOAT)) 522 { 523 if (ctx->lastError == GL_NO_ERROR) 524 ctx->lastError = GL_INVALID_ENUM; 525 return; 526 } 527 528 // invalid arguments 529 if (width < 0 || height < 0) 530 { 531 if (ctx->lastError == GL_NO_ERROR) 532 ctx->lastError = GL_INVALID_OPERATION; 533 return; 534 } 535 536 // read to buffer 537 if (ctx->pixelPackBufferBufferBinding) 538 return; 539 540 // read to use pointer 541 { 542 const int targetRowLength = (ctx->pixelPackRowLength != 0) ? (ctx->pixelPackRowLength) : (width); 543 const int targetSkipRows = ctx->pixelPackSkipRows; 544 const int targetSkipPixels = ctx->pixelPackSkipPixels; 545 const int infiniteHeight = targetSkipRows + height; // as much as needed 546 const int targetRowPitch = (ctx->pixelPackAlignment == 0) ? (targetRowLength * transferFormat.getPixelSize()) : (deAlign32(targetRowLength * transferFormat.getPixelSize(), ctx->pixelPackAlignment)); 547 548 // Create access to the whole copy target 549 const tcu::PixelBufferAccess targetAccess (transferFormat, targetRowLength, infiniteHeight, 1, targetRowPitch, 0, pixels); 550 551 // Select (skip_pixels, skip_rows, width, height) subregion from it. Clip to horizontal boundaries 552 const tcu::PixelBufferAccess targetRectAccess = tcu::getSubregion(targetAccess, 553 de::clamp(targetSkipPixels, 0, targetAccess.getWidth()-1), 554 targetSkipRows, 555 de::clamp(width, 0, de::max(0, targetAccess.getWidth() - targetSkipPixels)), 556 height); 557 558 tcu::clear(targetRectAccess, clearColor); 559 } 560 } 561 562 GLW_APICALL void GLW_APIENTRY glBindBuffer (GLenum target, GLuint buffer) 563 { 564 Context* const ctx = getCurrentContext(); 565 566 if (target == GL_PIXEL_PACK_BUFFER) 567 ctx->pixelPackBufferBufferBinding = buffer; 568 } 569 570 GLW_APICALL void GLW_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers) 571 { 572 Context* const ctx = getCurrentContext(); 573 574 for (GLsizei ndx = 0; ndx < n; ++ndx) 575 if (buffers[ndx] && buffers[ndx] == ctx->pixelPackBufferBufferBinding) 576 ctx->pixelPackBufferBufferBinding = 0; 577 } 578 579 #include "tcuNullRenderContextFuncs.inl" 580 581 void initFunctions (glw::Functions* gl) 582 { 583 # include "tcuNullRenderContextInitFuncs.inl" 584 } 585 586 static tcu::RenderTarget toRenderTarget (const RenderConfig& renderCfg) 587 { 588 const int width = getValueOrDefault(renderCfg, &RenderConfig::width, 256); 589 const int height = getValueOrDefault(renderCfg, &RenderConfig::height, 256); 590 const int redBits = getValueOrDefault(renderCfg, &RenderConfig::redBits, 8); 591 const int greenBits = getValueOrDefault(renderCfg, &RenderConfig::greenBits, 8); 592 const int blueBits = getValueOrDefault(renderCfg, &RenderConfig::blueBits, 8); 593 const int alphaBits = getValueOrDefault(renderCfg, &RenderConfig::alphaBits, 8); 594 const int depthBits = getValueOrDefault(renderCfg, &RenderConfig::depthBits, 24); 595 const int stencilBits = getValueOrDefault(renderCfg, &RenderConfig::stencilBits, 8); 596 const int numSamples = getValueOrDefault(renderCfg, &RenderConfig::numSamples, 0); 597 598 return tcu::RenderTarget(width, height, tcu::PixelFormat(redBits, greenBits, blueBits, alphaBits), depthBits, stencilBits, numSamples); 599 } 600 601 RenderContext::RenderContext (const RenderConfig& renderCfg) 602 : m_ctxType (renderCfg.type) 603 , m_renderTarget (toRenderTarget(renderCfg)) 604 , m_context (DE_NULL) 605 { 606 m_context = new Context(m_ctxType); 607 608 initFunctions(&m_functions); 609 setCurrentContext(m_context); 610 } 611 612 RenderContext::~RenderContext (void) 613 { 614 setCurrentContext(DE_NULL); 615 delete m_context; 616 } 617 618 void RenderContext::postIterate (void) 619 { 620 } 621 622 } // null 623 } // tcu 624