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