1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // libGLESv3.cpp: Implements the exported OpenGL ES 3.0 functions. 16 17 #include "main.h" 18 #include "Buffer.h" 19 #include "Fence.h" 20 #include "Framebuffer.h" 21 #include "Program.h" 22 #include "Query.h" 23 #include "Sampler.h" 24 #include "Texture.h" 25 #include "mathutil.h" 26 #include "TransformFeedback.h" 27 #include "VertexArray.h" 28 #include "common/debug.h" 29 30 #include <GLES3/gl3.h> 31 #include <GLES2/gl2ext.h> 32 33 #include <limits.h> 34 35 using namespace es2; 36 37 static bool validImageSize(GLint level, GLsizei width, GLsizei height) 38 { 39 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0) 40 { 41 return false; 42 } 43 44 return true; 45 } 46 47 static bool ValidateQueryTarget(GLenum target) 48 { 49 switch(target) 50 { 51 case GL_ANY_SAMPLES_PASSED: 52 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: 53 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: 54 break; 55 default: 56 return false; 57 } 58 59 return true; 60 } 61 62 bool ValidateTexParamParameters(GLenum pname, GLint param) 63 { 64 switch(pname) 65 { 66 case GL_TEXTURE_WRAP_S: 67 case GL_TEXTURE_WRAP_T: 68 case GL_TEXTURE_WRAP_R: 69 switch(param) 70 { 71 case GL_REPEAT: 72 case GL_CLAMP_TO_EDGE: 73 case GL_MIRRORED_REPEAT: 74 return true; 75 default: 76 return error(GL_INVALID_ENUM, false); 77 } 78 79 case GL_TEXTURE_MIN_FILTER: 80 switch(param) 81 { 82 case GL_NEAREST: 83 case GL_LINEAR: 84 case GL_NEAREST_MIPMAP_NEAREST: 85 case GL_LINEAR_MIPMAP_NEAREST: 86 case GL_NEAREST_MIPMAP_LINEAR: 87 case GL_LINEAR_MIPMAP_LINEAR: 88 return true; 89 default: 90 return error(GL_INVALID_ENUM, false); 91 } 92 break; 93 94 case GL_TEXTURE_MAG_FILTER: 95 switch(param) 96 { 97 case GL_NEAREST: 98 case GL_LINEAR: 99 return true; 100 default: 101 return error(GL_INVALID_ENUM, false); 102 } 103 break; 104 105 case GL_TEXTURE_USAGE_ANGLE: 106 switch(param) 107 { 108 case GL_NONE: 109 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: 110 return true; 111 default: 112 return error(GL_INVALID_ENUM, false); 113 } 114 break; 115 116 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 117 // we assume the parameter passed to this validation method is truncated, not rounded 118 if(param < 1) 119 { 120 return error(GL_INVALID_VALUE, false); 121 } 122 return true; 123 124 case GL_TEXTURE_MIN_LOD: 125 case GL_TEXTURE_MAX_LOD: 126 // any value is permissible 127 return true; 128 129 case GL_TEXTURE_COMPARE_MODE: 130 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 131 switch(param) 132 { 133 case GL_NONE: 134 case GL_COMPARE_REF_TO_TEXTURE: 135 return true; 136 default: 137 return error(GL_INVALID_ENUM, false); 138 } 139 break; 140 141 case GL_TEXTURE_COMPARE_FUNC: 142 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 143 switch(param) 144 { 145 case GL_LEQUAL: 146 case GL_GEQUAL: 147 case GL_LESS: 148 case GL_GREATER: 149 case GL_EQUAL: 150 case GL_NOTEQUAL: 151 case GL_ALWAYS: 152 case GL_NEVER: 153 return true; 154 default: 155 return error(GL_INVALID_ENUM, false); 156 } 157 break; 158 159 case GL_TEXTURE_SWIZZLE_R: 160 case GL_TEXTURE_SWIZZLE_G: 161 case GL_TEXTURE_SWIZZLE_B: 162 case GL_TEXTURE_SWIZZLE_A: 163 switch(param) 164 { 165 case GL_RED: 166 case GL_GREEN: 167 case GL_BLUE: 168 case GL_ALPHA: 169 case GL_ZERO: 170 case GL_ONE: 171 return true; 172 default: 173 return error(GL_INVALID_ENUM, false); 174 } 175 break; 176 177 case GL_TEXTURE_BASE_LEVEL: 178 case GL_TEXTURE_MAX_LEVEL: 179 if(param < 0) 180 { 181 return error(GL_INVALID_VALUE, false); 182 } 183 return true; 184 185 default: 186 return error(GL_INVALID_ENUM, false); 187 } 188 } 189 190 static bool ValidateSamplerObjectParameter(GLenum pname) 191 { 192 switch(pname) 193 { 194 case GL_TEXTURE_MIN_FILTER: 195 case GL_TEXTURE_MAG_FILTER: 196 case GL_TEXTURE_WRAP_S: 197 case GL_TEXTURE_WRAP_T: 198 case GL_TEXTURE_WRAP_R: 199 case GL_TEXTURE_MIN_LOD: 200 case GL_TEXTURE_MAX_LOD: 201 case GL_TEXTURE_COMPARE_MODE: 202 case GL_TEXTURE_COMPARE_FUNC: 203 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 204 return true; 205 default: 206 return false; 207 } 208 } 209 210 extern "C" 211 { 212 213 GL_APICALL void GL_APIENTRY glReadBuffer(GLenum src) 214 { 215 TRACE("(GLenum src = 0x%X)", src); 216 217 es2::Context *context = es2::getContext(); 218 219 if(context) 220 { 221 GLuint readFramebufferName = context->getReadFramebufferName(); 222 223 switch(src) 224 { 225 case GL_BACK: 226 if(readFramebufferName != 0) 227 { 228 return error(GL_INVALID_OPERATION); 229 } 230 context->setFramebufferReadBuffer(src); 231 break; 232 case GL_NONE: 233 context->setFramebufferReadBuffer(src); 234 break; 235 case GL_COLOR_ATTACHMENT0: 236 case GL_COLOR_ATTACHMENT1: 237 case GL_COLOR_ATTACHMENT2: 238 case GL_COLOR_ATTACHMENT3: 239 case GL_COLOR_ATTACHMENT4: 240 case GL_COLOR_ATTACHMENT5: 241 case GL_COLOR_ATTACHMENT6: 242 case GL_COLOR_ATTACHMENT7: 243 case GL_COLOR_ATTACHMENT8: 244 case GL_COLOR_ATTACHMENT9: 245 case GL_COLOR_ATTACHMENT10: 246 case GL_COLOR_ATTACHMENT11: 247 case GL_COLOR_ATTACHMENT12: 248 case GL_COLOR_ATTACHMENT13: 249 case GL_COLOR_ATTACHMENT14: 250 case GL_COLOR_ATTACHMENT15: 251 case GL_COLOR_ATTACHMENT16: 252 case GL_COLOR_ATTACHMENT17: 253 case GL_COLOR_ATTACHMENT18: 254 case GL_COLOR_ATTACHMENT19: 255 case GL_COLOR_ATTACHMENT20: 256 case GL_COLOR_ATTACHMENT21: 257 case GL_COLOR_ATTACHMENT22: 258 case GL_COLOR_ATTACHMENT23: 259 case GL_COLOR_ATTACHMENT24: 260 case GL_COLOR_ATTACHMENT25: 261 case GL_COLOR_ATTACHMENT26: 262 case GL_COLOR_ATTACHMENT27: 263 case GL_COLOR_ATTACHMENT28: 264 case GL_COLOR_ATTACHMENT29: 265 case GL_COLOR_ATTACHMENT30: 266 case GL_COLOR_ATTACHMENT31: 267 { 268 GLuint index = (src - GL_COLOR_ATTACHMENT0); 269 if(index >= MAX_COLOR_ATTACHMENTS) 270 { 271 return error(GL_INVALID_OPERATION); 272 } 273 if(readFramebufferName == 0) 274 { 275 return error(GL_INVALID_OPERATION); 276 } 277 context->setFramebufferReadBuffer(src); 278 } 279 break; 280 default: 281 return error(GL_INVALID_ENUM); 282 } 283 } 284 } 285 286 GL_APICALL void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) 287 { 288 TRACE("(GLenum mode = 0x%X, GLuint start = %d, GLuint end = %d, " 289 "GLsizei count = %d, GLenum type = 0x%x, const void* indices = %p)", 290 mode, start, end, count, type, indices); 291 292 switch(mode) 293 { 294 case GL_POINTS: 295 case GL_LINES: 296 case GL_LINE_LOOP: 297 case GL_LINE_STRIP: 298 case GL_TRIANGLES: 299 case GL_TRIANGLE_FAN: 300 case GL_TRIANGLE_STRIP: 301 break; 302 default: 303 return error(GL_INVALID_ENUM); 304 } 305 306 switch(type) 307 { 308 case GL_UNSIGNED_BYTE: 309 case GL_UNSIGNED_SHORT: 310 case GL_UNSIGNED_INT: 311 break; 312 default: 313 return error(GL_INVALID_ENUM); 314 } 315 316 if((count < 0) || (end < start)) 317 { 318 return error(GL_INVALID_VALUE); 319 } 320 321 es2::Context *context = es2::getContext(); 322 323 if(context) 324 { 325 es2::TransformFeedback* transformFeedback = context->getTransformFeedback(); 326 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) 327 { 328 return error(GL_INVALID_OPERATION); 329 } 330 331 context->drawElements(mode, start, end, count, type, indices); 332 } 333 } 334 335 GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *data) 336 { 337 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " 338 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " 339 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)", 340 target, level, internalformat, width, height, depth, border, format, type, data); 341 342 switch(target) 343 { 344 case GL_TEXTURE_3D: 345 case GL_TEXTURE_2D_ARRAY: 346 break; 347 default: 348 return error(GL_INVALID_ENUM); 349 } 350 351 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) 352 { 353 return error(GL_INVALID_VALUE); 354 } 355 356 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level; 357 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D)) 358 { 359 return error(GL_INVALID_VALUE); 360 } 361 362 if(border != 0) 363 { 364 return error(GL_INVALID_VALUE); 365 } 366 367 es2::Context *context = es2::getContext(); 368 369 if(context) 370 { 371 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, context->getClientVersion()); 372 if(validationError != GL_NO_ERROR) 373 { 374 return error(validationError); 375 } 376 377 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 378 379 if(!texture) 380 { 381 return error(GL_INVALID_OPERATION); 382 } 383 384 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type)); 385 if(validationError != GL_NO_ERROR) 386 { 387 return error(validationError); 388 } 389 390 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type); 391 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data); 392 } 393 } 394 395 GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data) 396 { 397 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " 398 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " 399 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)", 400 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); 401 402 switch(target) 403 { 404 case GL_TEXTURE_3D: 405 case GL_TEXTURE_2D_ARRAY: 406 break; 407 default: 408 return error(GL_INVALID_ENUM); 409 } 410 411 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) 412 { 413 return error(GL_INVALID_VALUE); 414 } 415 416 if((width < 0) || (height < 0) || (depth < 0) || (xoffset < 0) || (yoffset < 0) || (zoffset < 0)) 417 { 418 return error(GL_INVALID_VALUE); 419 } 420 421 es2::Context *context = es2::getContext(); 422 423 if(context) 424 { 425 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 426 427 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion()); 428 if(validationError != GL_NO_ERROR) 429 { 430 return error(validationError); 431 } 432 433 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type)); 434 if(validationError != GL_NO_ERROR) 435 { 436 return error(validationError); 437 } 438 439 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data); 440 } 441 } 442 443 GL_APICALL void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) 444 { 445 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " 446 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", 447 target, level, xoffset, yoffset, zoffset, x, y, width, height); 448 449 switch(target) 450 { 451 case GL_TEXTURE_3D: 452 case GL_TEXTURE_2D_ARRAY: 453 break; 454 default: 455 return error(GL_INVALID_ENUM); 456 } 457 458 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) 459 { 460 return error(GL_INVALID_VALUE); 461 } 462 463 if((width < 0) || (height < 0) || (xoffset < 0) || (yoffset < 0) || (zoffset < 0)) 464 { 465 return error(GL_INVALID_VALUE); 466 } 467 468 es2::Context *context = es2::getContext(); 469 470 if(context) 471 { 472 es2::Framebuffer *framebuffer = context->getReadFramebuffer(); 473 474 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) 475 { 476 return error(GL_INVALID_FRAMEBUFFER_OPERATION); 477 } 478 479 es2::Renderbuffer *source = framebuffer->getReadColorbuffer(); 480 481 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1)) 482 { 483 return error(GL_INVALID_OPERATION); 484 } 485 486 GLenum colorbufferFormat = source->getFormat(); 487 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 488 489 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion()); 490 if(validationError != GL_NO_ERROR) 491 { 492 return error(validationError); 493 } 494 495 GLenum textureFormat = texture->getFormat(target, level); 496 497 if(!ValidateCopyFormats(textureFormat, colorbufferFormat)) 498 { 499 return; 500 } 501 502 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); 503 } 504 } 505 506 GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) 507 { 508 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " 509 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)", 510 target, level, internalformat, width, height, depth, border, imageSize, data); 511 512 switch(target) 513 { 514 case GL_TEXTURE_3D: 515 case GL_TEXTURE_2D_ARRAY: 516 break; 517 default: 518 return error(GL_INVALID_ENUM); 519 } 520 521 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) 522 { 523 return error(GL_INVALID_VALUE); 524 } 525 526 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level; 527 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) || (border != 0) || (imageSize < 0)) 528 { 529 return error(GL_INVALID_VALUE); 530 } 531 532 if(!IsCompressed(internalformat, egl::getClientVersion())) 533 { 534 return error(GL_INVALID_ENUM); 535 } 536 537 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth) 538 { 539 return error(GL_INVALID_VALUE); 540 } 541 542 es2::Context *context = es2::getContext(); 543 544 if(context) 545 { 546 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 547 548 if(!texture) 549 { 550 return error(GL_INVALID_OPERATION); 551 } 552 553 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize); 554 if(validationError != GL_NO_ERROR) 555 { 556 return error(validationError); 557 } 558 559 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); 560 } 561 } 562 563 GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) 564 { 565 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " 566 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " 567 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)", 568 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); 569 570 switch(target) 571 { 572 case GL_TEXTURE_3D: 573 case GL_TEXTURE_2D_ARRAY: 574 break; 575 default: 576 return error(GL_INVALID_ENUM); 577 } 578 579 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS) 580 { 581 return error(GL_INVALID_VALUE); 582 } 583 584 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0) 585 { 586 return error(GL_INVALID_VALUE); 587 } 588 589 if(!IsCompressed(format, egl::getClientVersion())) 590 { 591 return error(GL_INVALID_ENUM); 592 } 593 594 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth) 595 { 596 return error(GL_INVALID_VALUE); 597 } 598 599 bool is_ETC2_EAC = false; 600 switch(format) 601 { 602 case GL_COMPRESSED_R11_EAC: 603 case GL_COMPRESSED_SIGNED_R11_EAC: 604 case GL_COMPRESSED_RG11_EAC: 605 case GL_COMPRESSED_SIGNED_RG11_EAC: 606 case GL_COMPRESSED_RGB8_ETC2: 607 case GL_COMPRESSED_SRGB8_ETC2: 608 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 609 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 610 case GL_COMPRESSED_RGBA8_ETC2_EAC: 611 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 612 if(target != GL_TEXTURE_2D_ARRAY) 613 { 614 return error(GL_INVALID_OPERATION); 615 } 616 617 if(((width % 4) != 0) || ((height % 4) != 0) || 618 ((xoffset % 4) != 0) || ((yoffset % 4) != 0)) 619 { 620 return error(GL_INVALID_OPERATION); 621 } 622 623 is_ETC2_EAC = true; 624 break; 625 default: 626 break; 627 } 628 629 es2::Context *context = es2::getContext(); 630 631 if(context) 632 { 633 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 634 635 if(!texture) 636 { 637 return error(GL_INVALID_OPERATION); 638 } 639 640 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize); 641 if(validationError != GL_NO_ERROR) 642 { 643 return error(validationError); 644 } 645 646 if(is_ETC2_EAC) 647 { 648 if(((width + xoffset) != texture->getWidth(target, level)) || 649 ((height + yoffset) != texture->getHeight(target, level)) || 650 ((depth + zoffset) != texture->getDepth(target, level))) 651 { 652 return error(GL_INVALID_OPERATION); 653 } 654 } 655 656 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); 657 } 658 } 659 660 GL_APICALL void GL_APIENTRY glGenQueries(GLsizei n, GLuint *ids) 661 { 662 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids); 663 664 if(n < 0) 665 { 666 return error(GL_INVALID_VALUE); 667 } 668 669 es2::Context *context = es2::getContext(); 670 671 if(context) 672 { 673 for(int i = 0; i < n; i++) 674 { 675 ids[i] = context->createQuery(); 676 } 677 } 678 } 679 680 GL_APICALL void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint *ids) 681 { 682 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids); 683 684 if(n < 0) 685 { 686 return error(GL_INVALID_VALUE); 687 } 688 689 es2::Context *context = es2::getContext(); 690 691 if(context) 692 { 693 for(int i = 0; i < n; i++) 694 { 695 context->deleteQuery(ids[i]); 696 } 697 } 698 } 699 700 GL_APICALL GLboolean GL_APIENTRY glIsQuery(GLuint id) 701 { 702 TRACE("(GLuint id = %d)", id); 703 704 if(id == 0) 705 { 706 return GL_FALSE; 707 } 708 709 es2::Context *context = es2::getContext(); 710 711 if(context) 712 { 713 es2::Query *queryObject = context->getQuery(id); 714 715 if(queryObject) 716 { 717 return GL_TRUE; 718 } 719 } 720 721 return GL_FALSE; 722 } 723 724 GL_APICALL void GL_APIENTRY glBeginQuery(GLenum target, GLuint id) 725 { 726 TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id); 727 728 if(!ValidateQueryTarget(target)) 729 { 730 return error(GL_INVALID_ENUM); 731 } 732 733 if(id == 0) 734 { 735 return error(GL_INVALID_OPERATION); 736 } 737 738 es2::Context *context = es2::getContext(); 739 740 if(context) 741 { 742 context->beginQuery(target, id); 743 } 744 } 745 746 GL_APICALL void GL_APIENTRY glEndQuery(GLenum target) 747 { 748 TRACE("(GLenum target = 0x%X)", target); 749 750 if(!ValidateQueryTarget(target)) 751 { 752 return error(GL_INVALID_ENUM); 753 } 754 755 es2::Context *context = es2::getContext(); 756 757 if(context) 758 { 759 context->endQuery(target); 760 } 761 } 762 763 GL_APICALL void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint *params) 764 { 765 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", 766 target, pname, params); 767 768 if(!ValidateQueryTarget(target) || (pname != GL_CURRENT_QUERY)) 769 { 770 return error(GL_INVALID_ENUM); 771 } 772 773 es2::Context *context = es2::getContext(); 774 775 if(context) 776 { 777 params[0] = context->getActiveQuery(target); 778 } 779 } 780 781 GL_APICALL void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) 782 { 783 TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLint *params = %p)", 784 id, pname, params); 785 786 switch(pname) 787 { 788 case GL_QUERY_RESULT: 789 case GL_QUERY_RESULT_AVAILABLE: 790 break; 791 default: 792 return error(GL_INVALID_ENUM); 793 } 794 795 es2::Context *context = es2::getContext(); 796 797 if(context) 798 { 799 es2::Query *queryObject = context->getQuery(id); 800 801 if(!queryObject) 802 { 803 return error(GL_INVALID_OPERATION); 804 } 805 806 if(context->getActiveQuery(queryObject->getType()) == id) 807 { 808 return error(GL_INVALID_OPERATION); 809 } 810 811 switch(pname) 812 { 813 case GL_QUERY_RESULT: 814 params[0] = queryObject->getResult(); 815 break; 816 case GL_QUERY_RESULT_AVAILABLE: 817 params[0] = queryObject->isResultAvailable(); 818 break; 819 default: 820 ASSERT(false); 821 } 822 } 823 } 824 825 GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) 826 { 827 TRACE("(GLenum target = 0x%X)", target); 828 829 es2::Context *context = es2::getContext(); 830 831 if(context) 832 { 833 es2::Buffer *buffer = nullptr; 834 if(!context->getBuffer(target, &buffer)) 835 { 836 return error(GL_INVALID_ENUM, GL_TRUE); 837 } 838 839 if(!buffer) 840 { 841 // A null buffer means that "0" is bound to the requested buffer target 842 return error(GL_INVALID_OPERATION, GL_TRUE); 843 } 844 845 if(!buffer->isMapped()) 846 { 847 // Already unmapped 848 return error(GL_INVALID_OPERATION, GL_TRUE); 849 } 850 851 return buffer->unmap() ? GL_TRUE : GL_FALSE; 852 } 853 854 return GL_TRUE; 855 } 856 857 GL_APICALL void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params) 858 { 859 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", 860 target, pname, params); 861 862 if(pname != GL_BUFFER_MAP_POINTER) 863 { 864 return error(GL_INVALID_ENUM); 865 } 866 867 es2::Context *context = es2::getContext(); 868 869 if(context) 870 { 871 es2::Buffer *buffer = nullptr; 872 if(!context->getBuffer(target, &buffer)) 873 { 874 return error(GL_INVALID_ENUM); 875 } 876 877 if(!buffer) 878 { 879 // A null buffer means that "0" is bound to the requested buffer target 880 return error(GL_INVALID_OPERATION); 881 } 882 883 *params = buffer->isMapped() ? (void*)(((const char*)buffer->data()) + buffer->offset()) : nullptr; 884 } 885 } 886 887 GL_APICALL void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs) 888 { 889 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs); 890 891 if(n < 0 || n > MAX_DRAW_BUFFERS) 892 { 893 return error(GL_INVALID_VALUE); 894 } 895 896 es2::Context *context = es2::getContext(); 897 898 if(context) 899 { 900 GLuint drawFramebufferName = context->getDrawFramebufferName(); 901 902 if((drawFramebufferName == 0) && (n != 1)) 903 { 904 return error(GL_INVALID_OPERATION); 905 } 906 907 for(unsigned int i = 0; i < (unsigned)n; i++) 908 { 909 switch(bufs[i]) 910 { 911 case GL_BACK: 912 if(drawFramebufferName != 0) 913 { 914 return error(GL_INVALID_OPERATION); 915 } 916 break; 917 case GL_NONE: 918 break; 919 case GL_COLOR_ATTACHMENT0: 920 case GL_COLOR_ATTACHMENT1: 921 case GL_COLOR_ATTACHMENT2: 922 case GL_COLOR_ATTACHMENT3: 923 case GL_COLOR_ATTACHMENT4: 924 case GL_COLOR_ATTACHMENT5: 925 case GL_COLOR_ATTACHMENT6: 926 case GL_COLOR_ATTACHMENT7: 927 case GL_COLOR_ATTACHMENT8: 928 case GL_COLOR_ATTACHMENT9: 929 case GL_COLOR_ATTACHMENT10: 930 case GL_COLOR_ATTACHMENT11: 931 case GL_COLOR_ATTACHMENT12: 932 case GL_COLOR_ATTACHMENT13: 933 case GL_COLOR_ATTACHMENT14: 934 case GL_COLOR_ATTACHMENT15: 935 case GL_COLOR_ATTACHMENT16: 936 case GL_COLOR_ATTACHMENT17: 937 case GL_COLOR_ATTACHMENT18: 938 case GL_COLOR_ATTACHMENT19: 939 case GL_COLOR_ATTACHMENT20: 940 case GL_COLOR_ATTACHMENT21: 941 case GL_COLOR_ATTACHMENT22: 942 case GL_COLOR_ATTACHMENT23: 943 case GL_COLOR_ATTACHMENT24: 944 case GL_COLOR_ATTACHMENT25: 945 case GL_COLOR_ATTACHMENT26: 946 case GL_COLOR_ATTACHMENT27: 947 case GL_COLOR_ATTACHMENT28: 948 case GL_COLOR_ATTACHMENT29: 949 case GL_COLOR_ATTACHMENT30: 950 case GL_COLOR_ATTACHMENT31: 951 { 952 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0); 953 954 if(index >= MAX_COLOR_ATTACHMENTS) 955 { 956 return error(GL_INVALID_OPERATION); 957 } 958 959 if(index != i) 960 { 961 return error(GL_INVALID_OPERATION); 962 } 963 964 if(drawFramebufferName == 0) 965 { 966 return error(GL_INVALID_OPERATION); 967 } 968 } 969 break; 970 default: 971 return error(GL_INVALID_ENUM); 972 } 973 } 974 975 context->setFramebufferDrawBuffers(n, bufs); 976 } 977 } 978 979 GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 980 { 981 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 982 983 if(count < 0) 984 { 985 return error(GL_INVALID_VALUE); 986 } 987 988 es2::Context *context = es2::getContext(); 989 990 if(context) 991 { 992 es2::Program *program = context->getCurrentProgram(); 993 994 if(!program) 995 { 996 return error(GL_INVALID_OPERATION); 997 } 998 999 if(location == -1) 1000 { 1001 return; 1002 } 1003 1004 if(!program->setUniformMatrix2x3fv(location, count, transpose, value)) 1005 { 1006 return error(GL_INVALID_OPERATION); 1007 } 1008 } 1009 } 1010 1011 GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 1012 { 1013 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 1014 1015 if(count < 0) 1016 { 1017 return error(GL_INVALID_VALUE); 1018 } 1019 1020 es2::Context *context = es2::getContext(); 1021 1022 if(context) 1023 { 1024 es2::Program *program = context->getCurrentProgram(); 1025 1026 if(!program) 1027 { 1028 return error(GL_INVALID_OPERATION); 1029 } 1030 1031 if(location == -1) 1032 { 1033 return; 1034 } 1035 1036 if(!program->setUniformMatrix3x2fv(location, count, transpose, value)) 1037 { 1038 return error(GL_INVALID_OPERATION); 1039 } 1040 } 1041 } 1042 1043 GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 1044 { 1045 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 1046 1047 if(count < 0) 1048 { 1049 return error(GL_INVALID_VALUE); 1050 } 1051 1052 es2::Context *context = es2::getContext(); 1053 1054 if(context) 1055 { 1056 es2::Program *program = context->getCurrentProgram(); 1057 1058 if(!program) 1059 { 1060 return error(GL_INVALID_OPERATION); 1061 } 1062 1063 if(location == -1) 1064 { 1065 return; 1066 } 1067 1068 if(!program->setUniformMatrix2x4fv(location, count, transpose, value)) 1069 { 1070 return error(GL_INVALID_OPERATION); 1071 } 1072 } 1073 } 1074 1075 GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 1076 { 1077 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 1078 1079 if(count < 0) 1080 { 1081 return error(GL_INVALID_VALUE); 1082 } 1083 1084 es2::Context *context = es2::getContext(); 1085 1086 if(context) 1087 { 1088 es2::Program *program = context->getCurrentProgram(); 1089 1090 if(!program) 1091 { 1092 return error(GL_INVALID_OPERATION); 1093 } 1094 1095 if(location == -1) 1096 { 1097 return; 1098 } 1099 1100 if(!program->setUniformMatrix4x2fv(location, count, transpose, value)) 1101 { 1102 return error(GL_INVALID_OPERATION); 1103 } 1104 } 1105 } 1106 1107 GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 1108 { 1109 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 1110 1111 if(count < 0) 1112 { 1113 return error(GL_INVALID_VALUE); 1114 } 1115 1116 es2::Context *context = es2::getContext(); 1117 1118 if(context) 1119 { 1120 es2::Program *program = context->getCurrentProgram(); 1121 1122 if(!program) 1123 { 1124 return error(GL_INVALID_OPERATION); 1125 } 1126 1127 if(location == -1) 1128 { 1129 return; 1130 } 1131 1132 if(!program->setUniformMatrix3x4fv(location, count, transpose, value)) 1133 { 1134 return error(GL_INVALID_OPERATION); 1135 } 1136 } 1137 } 1138 1139 GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 1140 { 1141 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value); 1142 1143 if(count < 0) 1144 { 1145 return error(GL_INVALID_VALUE); 1146 } 1147 1148 es2::Context *context = es2::getContext(); 1149 1150 if(context) 1151 { 1152 es2::Program *program = context->getCurrentProgram(); 1153 1154 if(!program) 1155 { 1156 return error(GL_INVALID_OPERATION); 1157 } 1158 1159 if(location == -1) 1160 { 1161 return; 1162 } 1163 1164 if(!program->setUniformMatrix4x3fv(location, count, transpose, value)) 1165 { 1166 return error(GL_INVALID_OPERATION); 1167 } 1168 } 1169 } 1170 1171 GL_APICALL void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) 1172 { 1173 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " 1174 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " 1175 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", 1176 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); 1177 1178 switch(filter) 1179 { 1180 case GL_NEAREST: 1181 break; 1182 case GL_LINEAR: 1183 if((mask & GL_DEPTH_BUFFER_BIT) || (mask & GL_STENCIL_BUFFER_BIT)) 1184 { 1185 return error(GL_INVALID_OPERATION); 1186 } 1187 break; 1188 default: 1189 return error(GL_INVALID_ENUM); 1190 } 1191 1192 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) 1193 { 1194 return error(GL_INVALID_VALUE); 1195 } 1196 1197 es2::Context *context = es2::getContext(); 1198 1199 if(context) 1200 { 1201 if(context->getReadFramebufferName() == context->getDrawFramebufferName()) 1202 { 1203 ERR("Blits with the same source and destination framebuffer are not supported by this implementation."); 1204 return error(GL_INVALID_OPERATION); 1205 } 1206 1207 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter == GL_LINEAR, true); 1208 } 1209 } 1210 1211 GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) 1212 { 1213 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)", 1214 target, attachment, texture, level, layer); 1215 1216 // GLES 3.0.4 spec, p.209, section 4.4.2 1217 // If texture is zero, any image or array of images attached to the attachment point 1218 // named by attachment is detached. Any additional parameters(level, textarget, 1219 // and / or layer) are ignored when texture is zero. 1220 if(texture != 0 && (layer < 0 || level < 0)) 1221 { 1222 return error(GL_INVALID_VALUE); 1223 } 1224 1225 es2::Context *context = es2::getContext(); 1226 1227 if(context) 1228 { 1229 Texture* textureObject = context->getTexture(texture); 1230 GLenum textarget = GL_NONE; 1231 if(texture != 0) 1232 { 1233 if(!textureObject) 1234 { 1235 return error(GL_INVALID_OPERATION); 1236 } 1237 1238 textarget = textureObject->getTarget(); 1239 switch(textarget) 1240 { 1241 case GL_TEXTURE_3D: 1242 case GL_TEXTURE_2D_ARRAY: 1243 if(layer >= es2::IMPLEMENTATION_MAX_TEXTURE_SIZE || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) 1244 { 1245 return error(GL_INVALID_VALUE); 1246 } 1247 break; 1248 default: 1249 return error(GL_INVALID_OPERATION); 1250 } 1251 1252 if(textureObject->isCompressed(textarget, level)) 1253 { 1254 return error(GL_INVALID_OPERATION); 1255 } 1256 } 1257 1258 es2::Framebuffer *framebuffer = nullptr; 1259 switch(target) 1260 { 1261 case GL_DRAW_FRAMEBUFFER: 1262 case GL_FRAMEBUFFER: 1263 if(context->getDrawFramebufferName() == 0) 1264 { 1265 return error(GL_INVALID_OPERATION); 1266 } 1267 framebuffer = context->getDrawFramebuffer(); 1268 break; 1269 case GL_READ_FRAMEBUFFER: 1270 if(context->getReadFramebufferName() == 0) 1271 { 1272 return error(GL_INVALID_OPERATION); 1273 } 1274 framebuffer = context->getReadFramebuffer(); 1275 break; 1276 default: 1277 return error(GL_INVALID_ENUM); 1278 } 1279 1280 if(!framebuffer) 1281 { 1282 return error(GL_INVALID_OPERATION); 1283 } 1284 1285 switch(attachment) 1286 { 1287 case GL_COLOR_ATTACHMENT0: 1288 case GL_COLOR_ATTACHMENT1: 1289 case GL_COLOR_ATTACHMENT2: 1290 case GL_COLOR_ATTACHMENT3: 1291 case GL_COLOR_ATTACHMENT4: 1292 case GL_COLOR_ATTACHMENT5: 1293 case GL_COLOR_ATTACHMENT6: 1294 case GL_COLOR_ATTACHMENT7: 1295 case GL_COLOR_ATTACHMENT8: 1296 case GL_COLOR_ATTACHMENT9: 1297 case GL_COLOR_ATTACHMENT10: 1298 case GL_COLOR_ATTACHMENT11: 1299 case GL_COLOR_ATTACHMENT12: 1300 case GL_COLOR_ATTACHMENT13: 1301 case GL_COLOR_ATTACHMENT14: 1302 case GL_COLOR_ATTACHMENT15: 1303 case GL_COLOR_ATTACHMENT16: 1304 case GL_COLOR_ATTACHMENT17: 1305 case GL_COLOR_ATTACHMENT18: 1306 case GL_COLOR_ATTACHMENT19: 1307 case GL_COLOR_ATTACHMENT20: 1308 case GL_COLOR_ATTACHMENT21: 1309 case GL_COLOR_ATTACHMENT22: 1310 case GL_COLOR_ATTACHMENT23: 1311 case GL_COLOR_ATTACHMENT24: 1312 case GL_COLOR_ATTACHMENT25: 1313 case GL_COLOR_ATTACHMENT26: 1314 case GL_COLOR_ATTACHMENT27: 1315 case GL_COLOR_ATTACHMENT28: 1316 case GL_COLOR_ATTACHMENT29: 1317 case GL_COLOR_ATTACHMENT30: 1318 case GL_COLOR_ATTACHMENT31: 1319 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level, layer); 1320 break; 1321 case GL_DEPTH_ATTACHMENT: 1322 framebuffer->setDepthbuffer(textarget, texture, level, layer); 1323 break; 1324 case GL_STENCIL_ATTACHMENT: 1325 framebuffer->setStencilbuffer(textarget, texture, level, layer); 1326 break; 1327 case GL_DEPTH_STENCIL_ATTACHMENT: 1328 framebuffer->setDepthbuffer(textarget, texture, level, layer); 1329 framebuffer->setStencilbuffer(textarget, texture, level, layer); 1330 break; 1331 default: 1332 return error(GL_INVALID_ENUM); 1333 } 1334 } 1335 } 1336 1337 GL_APICALL void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) 1338 { 1339 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)", 1340 target, offset, length, access); 1341 1342 if((offset < 0) || (length < 0)) 1343 { 1344 return error(GL_INVALID_VALUE, nullptr); 1345 } 1346 1347 if(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) 1348 { 1349 // Must be able to read or write the buffer 1350 return error(GL_INVALID_OPERATION, nullptr); 1351 } 1352 else if((access & GL_MAP_READ_BIT) && (access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT))) 1353 { 1354 // GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT and GL_MAP_UNSYNCHRONIZED_BIT can't be used with GL_MAP_READ_BIT 1355 return error(GL_INVALID_OPERATION, nullptr); 1356 } 1357 else if((!(access & GL_MAP_WRITE_BIT)) && (access & GL_MAP_FLUSH_EXPLICIT_BIT)) 1358 { 1359 // GL_MAP_FLUSH_EXPLICIT_BIT can't be used without GL_MAP_WRITE_BIT 1360 return error(GL_INVALID_OPERATION, nullptr); 1361 } 1362 1363 es2::Context *context = es2::getContext(); 1364 1365 if(context) 1366 { 1367 es2::Buffer *buffer = nullptr; 1368 if(!context->getBuffer(target, &buffer)) 1369 { 1370 return error(GL_INVALID_ENUM, nullptr); 1371 } 1372 1373 if(!buffer) 1374 { 1375 // A null buffer means that "0" is bound to the requested buffer target 1376 return error(GL_INVALID_OPERATION, nullptr); 1377 } 1378 1379 if(buffer->isMapped()) 1380 { 1381 // It is an invalid operation to map an already mapped buffer 1382 return error(GL_INVALID_OPERATION, nullptr); 1383 } 1384 1385 GLsizeiptr bufferSize = buffer->size(); 1386 if((offset + length) > bufferSize) 1387 { 1388 return error(GL_INVALID_VALUE, nullptr); 1389 } 1390 1391 if((access & ~(GL_MAP_READ_BIT | 1392 GL_MAP_WRITE_BIT | 1393 GL_MAP_INVALIDATE_RANGE_BIT | 1394 GL_MAP_INVALIDATE_BUFFER_BIT | 1395 GL_MAP_FLUSH_EXPLICIT_BIT | 1396 GL_MAP_UNSYNCHRONIZED_BIT)) != 0) 1397 { 1398 return error(GL_INVALID_VALUE, nullptr); 1399 } 1400 1401 return buffer->mapRange(offset, length, access); 1402 } 1403 1404 return nullptr; 1405 } 1406 1407 GL_APICALL void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) 1408 { 1409 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", 1410 target, offset, length); 1411 1412 if((offset < 0) || (length < 0)) 1413 { 1414 return error(GL_INVALID_VALUE); 1415 } 1416 1417 es2::Context *context = es2::getContext(); 1418 1419 if(context) 1420 { 1421 es2::Buffer *buffer = nullptr; 1422 if(!context->getBuffer(target, &buffer)) 1423 { 1424 return error(GL_INVALID_ENUM); 1425 } 1426 1427 if(!buffer) 1428 { 1429 // A null buffer means that "0" is bound to the requested buffer target 1430 return error(GL_INVALID_OPERATION); 1431 } 1432 1433 if(!buffer->isMapped()) 1434 { 1435 // Buffer must be mapped 1436 return error(GL_INVALID_OPERATION); 1437 } 1438 1439 GLsizeiptr bufferSize = buffer->length(); 1440 if((offset + length) > bufferSize) 1441 { 1442 return error(GL_INVALID_VALUE); 1443 } 1444 1445 if(!(buffer->access() & GL_MAP_FLUSH_EXPLICIT_BIT)) 1446 { 1447 // Flush must be explicitly allowed 1448 return error(GL_INVALID_OPERATION); 1449 } 1450 1451 buffer->flushMappedRange(offset, length); 1452 } 1453 } 1454 1455 GL_APICALL void GL_APIENTRY glBindVertexArray(GLuint array) 1456 { 1457 TRACE("(GLuint array = %d)", array); 1458 1459 es2::Context *context = es2::getContext(); 1460 1461 if(context) 1462 { 1463 if(!context->isVertexArray(array)) 1464 { 1465 return error(GL_INVALID_OPERATION); 1466 } 1467 1468 context->bindVertexArray(array); 1469 } 1470 } 1471 1472 GL_APICALL void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays) 1473 { 1474 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays); 1475 1476 if(n < 0) 1477 { 1478 return error(GL_INVALID_VALUE); 1479 } 1480 1481 es2::Context *context = es2::getContext(); 1482 1483 if(context) 1484 { 1485 for(int i = 0; i < n; i++) 1486 { 1487 context->deleteVertexArray(arrays[i]); 1488 } 1489 } 1490 } 1491 1492 GL_APICALL void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays) 1493 { 1494 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays); 1495 1496 if(n < 0) 1497 { 1498 return error(GL_INVALID_VALUE); 1499 } 1500 1501 es2::Context *context = es2::getContext(); 1502 1503 if(context) 1504 { 1505 for(int i = 0; i < n; i++) 1506 { 1507 arrays[i] = context->createVertexArray(); 1508 } 1509 } 1510 } 1511 1512 GL_APICALL GLboolean GL_APIENTRY glIsVertexArray(GLuint array) 1513 { 1514 TRACE("(GLuint array = %d)", array); 1515 1516 if(array == 0) 1517 { 1518 return GL_FALSE; 1519 } 1520 1521 es2::Context *context = es2::getContext(); 1522 1523 if(context) 1524 { 1525 es2::VertexArray *arrayObject = context->getVertexArray(array); 1526 1527 if(arrayObject) 1528 { 1529 return GL_TRUE; 1530 } 1531 } 1532 1533 return GL_FALSE; 1534 } 1535 1536 GL_APICALL void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data) 1537 { 1538 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint* data = %p)", 1539 target, index, data); 1540 1541 es2::Context *context = es2::getContext(); 1542 1543 if(context) 1544 { 1545 if(!context->getTransformFeedbackiv(index, target, data) && 1546 !context->getUniformBufferiv(index, target, data) && 1547 !context->getIntegerv(target, data)) 1548 { 1549 GLenum nativeType; 1550 unsigned int numParams = 0; 1551 if(!context->getQueryParameterInfo(target, &nativeType, &numParams)) 1552 return error(GL_INVALID_ENUM); 1553 1554 if(numParams == 0) 1555 return; // it is known that target is valid, but there are no parameters to return 1556 1557 if(nativeType == GL_BOOL) 1558 { 1559 GLboolean *boolParams = nullptr; 1560 boolParams = new GLboolean[numParams]; 1561 1562 context->getBooleanv(target, boolParams); 1563 1564 for(unsigned int i = 0; i < numParams; ++i) 1565 { 1566 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1; 1567 } 1568 1569 delete[] boolParams; 1570 } 1571 else if(nativeType == GL_FLOAT) 1572 { 1573 GLfloat *floatParams = nullptr; 1574 floatParams = new GLfloat[numParams]; 1575 1576 context->getFloatv(target, floatParams); 1577 1578 for(unsigned int i = 0; i < numParams; ++i) 1579 { 1580 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR) 1581 { 1582 data[i] = convert_float_fixed(floatParams[i]); 1583 } 1584 else 1585 { 1586 data[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); 1587 } 1588 } 1589 1590 delete[] floatParams; 1591 } 1592 } 1593 } 1594 } 1595 1596 GL_APICALL void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode) 1597 { 1598 TRACE("(GLenum primitiveMode = 0x%X)", primitiveMode); 1599 1600 switch(primitiveMode) 1601 { 1602 case GL_POINTS: 1603 case GL_LINES: 1604 case GL_TRIANGLES: 1605 break; 1606 default: 1607 return error(GL_INVALID_ENUM); 1608 } 1609 1610 es2::Context *context = es2::getContext(); 1611 1612 if(context) 1613 { 1614 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(); 1615 1616 if(transformFeedbackObject) 1617 { 1618 if(transformFeedbackObject->isActive()) 1619 { 1620 return error(GL_INVALID_OPERATION); 1621 } 1622 transformFeedbackObject->begin(primitiveMode); 1623 } 1624 else 1625 { 1626 return error(GL_INVALID_OPERATION); 1627 } 1628 } 1629 } 1630 1631 GL_APICALL void GL_APIENTRY glEndTransformFeedback(void) 1632 { 1633 TRACE("()"); 1634 1635 es2::Context *context = es2::getContext(); 1636 1637 if(context) 1638 { 1639 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(); 1640 1641 if(transformFeedbackObject) 1642 { 1643 if(!transformFeedbackObject->isActive()) 1644 { 1645 return error(GL_INVALID_OPERATION); 1646 } 1647 transformFeedbackObject->end(); 1648 } 1649 else 1650 { 1651 return error(GL_INVALID_OPERATION); 1652 } 1653 } 1654 } 1655 1656 GL_APICALL void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) 1657 { 1658 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)", 1659 target, index, buffer, offset, size); 1660 1661 if(buffer != 0 && size <= 0) 1662 { 1663 return error(GL_INVALID_VALUE); 1664 } 1665 1666 es2::Context *context = es2::getContext(); 1667 1668 if(context) 1669 { 1670 switch(target) 1671 { 1672 case GL_TRANSFORM_FEEDBACK_BUFFER: 1673 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) 1674 { 1675 return error(GL_INVALID_VALUE); 1676 } 1677 if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4 1678 { 1679 return error(GL_INVALID_VALUE); 1680 } 1681 context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); 1682 context->bindGenericTransformFeedbackBuffer(buffer); 1683 break; 1684 case GL_UNIFORM_BUFFER: 1685 if(index >= MAX_UNIFORM_BUFFER_BINDINGS) 1686 { 1687 return error(GL_INVALID_VALUE); 1688 } 1689 if(offset % UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0) 1690 { 1691 return error(GL_INVALID_VALUE); 1692 } 1693 context->bindIndexedUniformBuffer(buffer, index, offset, size); 1694 context->bindGenericUniformBuffer(buffer); 1695 break; 1696 default: 1697 return error(GL_INVALID_ENUM); 1698 } 1699 } 1700 } 1701 1702 GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) 1703 { 1704 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)", 1705 target, index, buffer); 1706 1707 es2::Context *context = es2::getContext(); 1708 1709 if(context) 1710 { 1711 switch(target) 1712 { 1713 case GL_TRANSFORM_FEEDBACK_BUFFER: 1714 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) 1715 { 1716 return error(GL_INVALID_VALUE); 1717 } 1718 context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); 1719 context->bindGenericTransformFeedbackBuffer(buffer); 1720 break; 1721 case GL_UNIFORM_BUFFER: 1722 if(index >= MAX_UNIFORM_BUFFER_BINDINGS) 1723 { 1724 return error(GL_INVALID_VALUE); 1725 } 1726 context->bindIndexedUniformBuffer(buffer, index, 0, 0); 1727 context->bindGenericUniformBuffer(buffer); 1728 break; 1729 default: 1730 return error(GL_INVALID_ENUM); 1731 } 1732 } 1733 } 1734 1735 GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode) 1736 { 1737 TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = %p, GLenum bufferMode = 0x%X)", 1738 program, count, varyings, bufferMode); 1739 1740 switch(bufferMode) 1741 { 1742 case GL_SEPARATE_ATTRIBS: 1743 if(count > MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) 1744 { 1745 return error(GL_INVALID_VALUE); 1746 } 1747 case GL_INTERLEAVED_ATTRIBS: 1748 break; 1749 default: 1750 return error(GL_INVALID_ENUM); 1751 } 1752 1753 es2::Context *context = es2::getContext(); 1754 1755 if(context) 1756 { 1757 es2::Program *programObject = context->getProgram(program); 1758 1759 if(!programObject) 1760 { 1761 return error(GL_INVALID_VALUE); 1762 } 1763 1764 programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); 1765 } 1766 } 1767 1768 GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) 1769 { 1770 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)", 1771 program, index, bufSize, length, size, type, name); 1772 1773 if(bufSize < 0) 1774 { 1775 return error(GL_INVALID_VALUE); 1776 } 1777 1778 es2::Context *context = es2::getContext(); 1779 1780 if(context) 1781 { 1782 es2::Program *programObject = context->getProgram(program); 1783 1784 if(!programObject) 1785 { 1786 return error(GL_INVALID_VALUE); 1787 } 1788 1789 if(index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount())) 1790 { 1791 return error(GL_INVALID_VALUE); 1792 } 1793 1794 programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); 1795 } 1796 } 1797 1798 GL_APICALL void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer) 1799 { 1800 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)", 1801 index, size, type, stride, pointer); 1802 1803 if(index >= es2::MAX_VERTEX_ATTRIBS) 1804 { 1805 return error(GL_INVALID_VALUE); 1806 } 1807 1808 if(size < 1 || size > 4 || stride < 0) 1809 { 1810 return error(GL_INVALID_VALUE); 1811 } 1812 1813 switch(type) 1814 { 1815 case GL_BYTE: 1816 case GL_UNSIGNED_BYTE: 1817 case GL_SHORT: 1818 case GL_UNSIGNED_SHORT: 1819 case GL_INT: 1820 case GL_UNSIGNED_INT: 1821 break; 1822 default: 1823 return error(GL_INVALID_ENUM); 1824 } 1825 1826 es2::Context *context = es2::getContext(); 1827 1828 if(context) 1829 { 1830 es2::VertexArray* vertexArray = context->getCurrentVertexArray(); 1831 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && pointer) 1832 { 1833 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound 1834 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL. 1835 return error(GL_INVALID_OPERATION); 1836 } 1837 1838 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, true, stride, pointer); 1839 } 1840 } 1841 1842 GL_APICALL void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) 1843 { 1844 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = %p)", 1845 index, pname, params); 1846 1847 es2::Context *context = es2::getContext(); 1848 1849 if(context) 1850 { 1851 if(index >= es2::MAX_VERTEX_ATTRIBS) 1852 { 1853 return error(GL_INVALID_VALUE); 1854 } 1855 1856 const es2::VertexAttribute &attribState = context->getVertexAttribState(index); 1857 1858 switch(pname) 1859 { 1860 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 1861 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); 1862 break; 1863 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 1864 *params = attribState.mSize; 1865 break; 1866 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 1867 *params = attribState.mStride; 1868 break; 1869 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 1870 *params = attribState.mType; 1871 break; 1872 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 1873 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE); 1874 break; 1875 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 1876 *params = attribState.mBoundBuffer.name(); 1877 break; 1878 case GL_CURRENT_VERTEX_ATTRIB: 1879 { 1880 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index]; 1881 for(int i = 0; i < 4; ++i) 1882 { 1883 params[i] = attrib.getCurrentValueI(i); 1884 } 1885 } 1886 break; 1887 case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 1888 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE); 1889 break; 1890 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: 1891 *params = attribState.mDivisor; 1892 break; 1893 default: return error(GL_INVALID_ENUM); 1894 } 1895 } 1896 } 1897 1898 GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) 1899 { 1900 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = %p)", 1901 index, pname, params); 1902 1903 es2::Context *context = es2::getContext(); 1904 1905 if(context) 1906 { 1907 if(index >= es2::MAX_VERTEX_ATTRIBS) 1908 { 1909 return error(GL_INVALID_VALUE); 1910 } 1911 1912 const es2::VertexAttribute &attribState = context->getVertexAttribState(index); 1913 1914 switch(pname) 1915 { 1916 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 1917 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); 1918 break; 1919 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 1920 *params = attribState.mSize; 1921 break; 1922 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 1923 *params = attribState.mStride; 1924 break; 1925 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 1926 *params = attribState.mType; 1927 break; 1928 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 1929 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE); 1930 break; 1931 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 1932 *params = attribState.mBoundBuffer.name(); 1933 break; 1934 case GL_CURRENT_VERTEX_ATTRIB: 1935 { 1936 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index]; 1937 for(int i = 0; i < 4; ++i) 1938 { 1939 params[i] = attrib.getCurrentValueUI(i); 1940 } 1941 } 1942 break; 1943 case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 1944 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE); 1945 break; 1946 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: 1947 *params = attribState.mDivisor; 1948 break; 1949 default: return error(GL_INVALID_ENUM); 1950 } 1951 } 1952 } 1953 1954 GL_APICALL void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) 1955 { 1956 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", 1957 index, x, y, z, w); 1958 1959 if(index >= es2::MAX_VERTEX_ATTRIBS) 1960 { 1961 return error(GL_INVALID_VALUE); 1962 } 1963 1964 es2::Context *context = es2::getContext(); 1965 1966 if(context) 1967 { 1968 GLint vals[4] = { x, y, z, w }; 1969 context->setVertexAttrib(index, vals); 1970 } 1971 } 1972 1973 GL_APICALL void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) 1974 { 1975 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", 1976 index, x, y, z, w); 1977 1978 if(index >= es2::MAX_VERTEX_ATTRIBS) 1979 { 1980 return error(GL_INVALID_VALUE); 1981 } 1982 1983 es2::Context *context = es2::getContext(); 1984 1985 if(context) 1986 { 1987 GLuint vals[4] = { x, y, z, w }; 1988 context->setVertexAttrib(index, vals); 1989 } 1990 } 1991 1992 GL_APICALL void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v) 1993 { 1994 TRACE("(GLuint index = %d, GLint *v = %p)", index, v); 1995 1996 if(index >= es2::MAX_VERTEX_ATTRIBS) 1997 { 1998 return error(GL_INVALID_VALUE); 1999 } 2000 2001 es2::Context *context = es2::getContext(); 2002 2003 if(context) 2004 { 2005 context->setVertexAttrib(index, v); 2006 } 2007 } 2008 2009 GL_APICALL void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v) 2010 { 2011 TRACE("(GLuint index = %d, GLint *v = %p)", index, v); 2012 2013 if(index >= es2::MAX_VERTEX_ATTRIBS) 2014 { 2015 return error(GL_INVALID_VALUE); 2016 } 2017 2018 es2::Context *context = es2::getContext(); 2019 2020 if(context) 2021 { 2022 context->setVertexAttrib(index, v); 2023 } 2024 } 2025 2026 GL_APICALL void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params) 2027 { 2028 TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = %p)", 2029 program, location, params); 2030 2031 es2::Context *context = es2::getContext(); 2032 2033 if(context) 2034 { 2035 es2::Program *programObject = context->getProgram(program); 2036 2037 if(!programObject) 2038 { 2039 if(context->getShader(program)) 2040 { 2041 return error(GL_INVALID_OPERATION); 2042 } 2043 else 2044 { 2045 return error(GL_INVALID_VALUE); 2046 } 2047 } 2048 2049 if(!programObject->isLinked()) 2050 { 2051 return error(GL_INVALID_OPERATION); 2052 } 2053 2054 if(!programObject->getUniformuiv(location, nullptr, params)) 2055 { 2056 return error(GL_INVALID_OPERATION); 2057 } 2058 } 2059 } 2060 2061 GL_APICALL GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name) 2062 { 2063 TRACE("(GLuint program = %d, const GLchar *name = %p)", program, name); 2064 2065 es2::Context *context = es2::getContext(); 2066 2067 if(context) 2068 { 2069 es2::Program *programObject = context->getProgram(program); 2070 2071 if(!programObject) 2072 { 2073 if(context->getShader(program)) 2074 { 2075 return error(GL_INVALID_OPERATION, -1); 2076 } 2077 else 2078 { 2079 return error(GL_INVALID_VALUE, -1); 2080 } 2081 } 2082 2083 if(!programObject->isLinked()) 2084 { 2085 return error(GL_INVALID_OPERATION, -1); 2086 } 2087 2088 return programObject->getFragDataLocation(name); 2089 } 2090 2091 return -1; 2092 } 2093 2094 GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) 2095 { 2096 glUniform1uiv(location, 1, &v0); 2097 } 2098 2099 GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1) 2100 { 2101 GLuint xy[2] = { v0, v1 }; 2102 2103 glUniform2uiv(location, 1, (GLuint*)&xy); 2104 } 2105 2106 GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) 2107 { 2108 GLuint xyz[3] = { v0, v1, v2 }; 2109 2110 glUniform3uiv(location, 1, (GLuint*)&xyz); 2111 } 2112 2113 GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) 2114 { 2115 GLuint xyzw[4] = { v0, v1, v2, v3 }; 2116 2117 glUniform4uiv(location, 1, (GLuint*)&xyzw); 2118 } 2119 2120 GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value) 2121 { 2122 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)", 2123 location, count, value); 2124 2125 if(count < 0) 2126 { 2127 return error(GL_INVALID_VALUE); 2128 } 2129 2130 es2::Context *context = es2::getContext(); 2131 2132 if(context) 2133 { 2134 es2::Program *program = context->getCurrentProgram(); 2135 2136 if(!program) 2137 { 2138 return error(GL_INVALID_OPERATION); 2139 } 2140 2141 if(location == -1) 2142 { 2143 return; 2144 } 2145 2146 if(!program->setUniform1uiv(location, count, value)) 2147 { 2148 return error(GL_INVALID_OPERATION); 2149 } 2150 } 2151 } 2152 2153 GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value) 2154 { 2155 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)", 2156 location, count, value); 2157 2158 if(count < 0) 2159 { 2160 return error(GL_INVALID_VALUE); 2161 } 2162 2163 es2::Context *context = es2::getContext(); 2164 2165 if(context) 2166 { 2167 es2::Program *program = context->getCurrentProgram(); 2168 2169 if(!program) 2170 { 2171 return error(GL_INVALID_OPERATION); 2172 } 2173 2174 if(location == -1) 2175 { 2176 return; 2177 } 2178 2179 if(!program->setUniform2uiv(location, count, value)) 2180 { 2181 return error(GL_INVALID_OPERATION); 2182 } 2183 } 2184 } 2185 2186 GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value) 2187 { 2188 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)", 2189 location, count, value); 2190 2191 if(count < 0) 2192 { 2193 return error(GL_INVALID_VALUE); 2194 } 2195 2196 es2::Context *context = es2::getContext(); 2197 2198 if(context) 2199 { 2200 es2::Program *program = context->getCurrentProgram(); 2201 2202 if(!program) 2203 { 2204 return error(GL_INVALID_OPERATION); 2205 } 2206 2207 if(location == -1) 2208 { 2209 return; 2210 } 2211 2212 if(!program->setUniform3uiv(location, count, value)) 2213 { 2214 return error(GL_INVALID_OPERATION); 2215 } 2216 } 2217 } 2218 2219 GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value) 2220 { 2221 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)", 2222 location, count, value); 2223 2224 if(count < 0) 2225 { 2226 return error(GL_INVALID_VALUE); 2227 } 2228 2229 es2::Context *context = es2::getContext(); 2230 2231 if(context) 2232 { 2233 es2::Program *program = context->getCurrentProgram(); 2234 2235 if(!program) 2236 { 2237 return error(GL_INVALID_OPERATION); 2238 } 2239 2240 if(location == -1) 2241 { 2242 return; 2243 } 2244 2245 if(!program->setUniform4uiv(location, count, value)) 2246 { 2247 return error(GL_INVALID_OPERATION); 2248 } 2249 } 2250 } 2251 2252 GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 2253 { 2254 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)", 2255 buffer, drawbuffer, value); 2256 2257 es2::Context *context = es2::getContext(); 2258 2259 if(context) 2260 { 2261 switch(buffer) 2262 { 2263 case GL_COLOR: 2264 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS) 2265 { 2266 return error(GL_INVALID_VALUE); 2267 } 2268 else 2269 { 2270 context->clearColorBuffer(drawbuffer, value); 2271 } 2272 break; 2273 case GL_STENCIL: 2274 if(drawbuffer != 0) 2275 { 2276 return error(GL_INVALID_VALUE); 2277 } 2278 else 2279 { 2280 context->clearStencilBuffer(value[0]); 2281 } 2282 break; 2283 default: 2284 return error(GL_INVALID_ENUM); 2285 } 2286 } 2287 } 2288 2289 GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 2290 { 2291 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)", 2292 buffer, drawbuffer, value); 2293 2294 es2::Context *context = es2::getContext(); 2295 2296 if(context) 2297 { 2298 switch(buffer) 2299 { 2300 case GL_COLOR: 2301 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS) 2302 { 2303 return error(GL_INVALID_VALUE); 2304 } 2305 else 2306 { 2307 context->clearColorBuffer(drawbuffer, value); 2308 } 2309 break; 2310 default: 2311 return error(GL_INVALID_ENUM); 2312 } 2313 } 2314 } 2315 2316 GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 2317 { 2318 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)", 2319 buffer, drawbuffer, value); 2320 2321 es2::Context *context = es2::getContext(); 2322 2323 if(context) 2324 { 2325 switch(buffer) 2326 { 2327 case GL_COLOR: 2328 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS) 2329 { 2330 return error(GL_INVALID_VALUE); 2331 } 2332 else 2333 { 2334 context->clearColorBuffer(drawbuffer, value); 2335 } 2336 break; 2337 case GL_DEPTH: 2338 if(drawbuffer != 0) 2339 { 2340 return error(GL_INVALID_VALUE); 2341 } 2342 else 2343 { 2344 context->clearDepthBuffer(value[0]); 2345 } 2346 break; 2347 default: 2348 return error(GL_INVALID_ENUM); 2349 } 2350 } 2351 } 2352 2353 GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) 2354 { 2355 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)", 2356 buffer, drawbuffer, depth, stencil); 2357 2358 es2::Context *context = es2::getContext(); 2359 2360 if(context) 2361 { 2362 switch(buffer) 2363 { 2364 case GL_DEPTH_STENCIL: 2365 if(drawbuffer != 0) 2366 { 2367 return error(GL_INVALID_VALUE); 2368 } 2369 else 2370 { 2371 context->clearDepthBuffer(depth); 2372 context->clearStencilBuffer(stencil); 2373 } 2374 break; 2375 default: 2376 return error(GL_INVALID_ENUM); 2377 } 2378 } 2379 } 2380 2381 GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index) 2382 { 2383 TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index); 2384 2385 es2::Context *context = es2::getContext(); 2386 if(context) 2387 { 2388 GLuint numExtensions; 2389 context->getExtensions(0, &numExtensions); 2390 2391 if(index >= numExtensions) 2392 { 2393 return error(GL_INVALID_VALUE, (GLubyte*)nullptr); 2394 } 2395 2396 switch(name) 2397 { 2398 case GL_EXTENSIONS: 2399 return context->getExtensions(index); 2400 default: 2401 return error(GL_INVALID_ENUM, (GLubyte*)nullptr); 2402 } 2403 } 2404 2405 return (GLubyte*)nullptr; 2406 } 2407 2408 GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) 2409 { 2410 TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", 2411 readTarget, writeTarget, readOffset, writeOffset, size); 2412 2413 if(readOffset < 0 || writeOffset < 0 || size < 0) 2414 { 2415 return error(GL_INVALID_VALUE); 2416 } 2417 2418 es2::Context *context = es2::getContext(); 2419 2420 if(context) 2421 { 2422 es2::Buffer *readBuffer = nullptr, *writeBuffer = nullptr; 2423 if(!context->getBuffer(readTarget, &readBuffer) || !context->getBuffer(writeTarget, &writeBuffer)) 2424 { 2425 return error(GL_INVALID_ENUM); 2426 } 2427 if(!readBuffer || readBuffer->isMapped() || !writeBuffer || writeBuffer->isMapped()) 2428 { 2429 return error(GL_INVALID_OPERATION); 2430 } 2431 if(readBuffer == writeBuffer) 2432 { 2433 // If same buffer, check for overlap 2434 if(((readOffset >= writeOffset) && (readOffset < (writeOffset + size))) || 2435 ((writeOffset >= readOffset) && (writeOffset < (readOffset + size)))) 2436 { 2437 return error(GL_INVALID_VALUE); 2438 } 2439 } 2440 2441 if((static_cast<size_t>(readOffset + size) > readBuffer->size()) || 2442 (static_cast<size_t>(writeOffset + size) > writeBuffer->size())) 2443 { 2444 return error(GL_INVALID_VALUE); 2445 } 2446 2447 writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset); 2448 } 2449 } 2450 2451 GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices) 2452 { 2453 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)", 2454 program, uniformCount, uniformNames, uniformIndices); 2455 2456 if(uniformCount < 0) 2457 { 2458 return error(GL_INVALID_VALUE); 2459 } 2460 2461 es2::Context *context = es2::getContext(); 2462 2463 if(context) 2464 { 2465 es2::Program *programObject = context->getProgram(program); 2466 2467 if(!programObject) 2468 { 2469 if(context->getShader(program)) 2470 { 2471 return error(GL_INVALID_OPERATION); 2472 } 2473 else 2474 { 2475 return error(GL_INVALID_VALUE); 2476 } 2477 } 2478 2479 if(!programObject->isLinked()) 2480 { 2481 for(int uniformId = 0; uniformId < uniformCount; uniformId++) 2482 { 2483 uniformIndices[uniformId] = GL_INVALID_INDEX; 2484 } 2485 } 2486 else 2487 { 2488 for(int uniformId = 0; uniformId < uniformCount; uniformId++) 2489 { 2490 uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]); 2491 } 2492 } 2493 } 2494 } 2495 2496 GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) 2497 { 2498 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLenum pname = 0x%X, GLuint *uniformIndices = %p)", 2499 program, uniformCount, uniformIndices, pname, uniformIndices); 2500 2501 switch(pname) 2502 { 2503 case GL_UNIFORM_TYPE: 2504 case GL_UNIFORM_SIZE: 2505 case GL_UNIFORM_NAME_LENGTH: 2506 case GL_UNIFORM_BLOCK_INDEX: 2507 case GL_UNIFORM_OFFSET: 2508 case GL_UNIFORM_ARRAY_STRIDE: 2509 case GL_UNIFORM_MATRIX_STRIDE: 2510 case GL_UNIFORM_IS_ROW_MAJOR: 2511 break; 2512 default: 2513 return error(GL_INVALID_ENUM); 2514 } 2515 2516 if(uniformCount < 0) 2517 { 2518 return error(GL_INVALID_VALUE); 2519 } 2520 2521 es2::Context *context = es2::getContext(); 2522 2523 if(context) 2524 { 2525 es2::Program *programObject = context->getProgram(program); 2526 2527 if(!programObject) 2528 { 2529 if(context->getShader(program)) 2530 { 2531 return error(GL_INVALID_OPERATION); 2532 } 2533 else 2534 { 2535 return error(GL_INVALID_VALUE); 2536 } 2537 } 2538 2539 for(int uniformId = 0; uniformId < uniformCount; uniformId++) 2540 { 2541 const GLuint index = uniformIndices[uniformId]; 2542 2543 if(index >= programObject->getActiveUniformCount()) 2544 { 2545 return error(GL_INVALID_VALUE); 2546 } 2547 } 2548 2549 for(int uniformId = 0; uniformId < uniformCount; uniformId++) 2550 { 2551 const GLuint index = uniformIndices[uniformId]; 2552 params[uniformId] = programObject->getActiveUniformi(index, pname); 2553 } 2554 } 2555 } 2556 2557 GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) 2558 { 2559 TRACE("(GLuint program = %d, const GLchar *uniformBlockName = %p)", 2560 program, uniformBlockName); 2561 2562 es2::Context *context = es2::getContext(); 2563 2564 if(context) 2565 { 2566 es2::Program *programObject = context->getProgram(program); 2567 2568 if(!programObject) 2569 { 2570 if(context->getShader(program)) 2571 { 2572 return error(GL_INVALID_OPERATION, GL_INVALID_INDEX); 2573 } 2574 else 2575 { 2576 return error(GL_INVALID_VALUE, GL_INVALID_INDEX); 2577 } 2578 } 2579 2580 return programObject->getUniformBlockIndex(uniformBlockName); 2581 } 2582 2583 return GL_INVALID_INDEX; 2584 } 2585 2586 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) 2587 { 2588 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)", 2589 program, uniformBlockIndex, pname, params); 2590 2591 es2::Context *context = es2::getContext(); 2592 2593 if(context) 2594 { 2595 es2::Program *programObject = context->getProgram(program); 2596 2597 if(!programObject) 2598 { 2599 return error(GL_INVALID_OPERATION); 2600 } 2601 2602 switch(pname) 2603 { 2604 case GL_UNIFORM_BLOCK_BINDING: 2605 *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex)); 2606 break; 2607 case GL_UNIFORM_BLOCK_DATA_SIZE: 2608 case GL_UNIFORM_BLOCK_NAME_LENGTH: 2609 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: 2610 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 2611 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 2612 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 2613 programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params); 2614 break; 2615 default: 2616 return error(GL_INVALID_ENUM); 2617 } 2618 } 2619 } 2620 2621 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) 2622 { 2623 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLchar *uniformBlockName = %p)", 2624 program, uniformBlockIndex, bufSize, length, uniformBlockName); 2625 2626 if(bufSize < 0) 2627 { 2628 return error(GL_INVALID_VALUE); 2629 } 2630 2631 es2::Context *context = es2::getContext(); 2632 2633 if(context) 2634 { 2635 es2::Program *programObject = context->getProgram(program); 2636 2637 if(!programObject) 2638 { 2639 return error(GL_INVALID_OPERATION); 2640 } 2641 2642 programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); 2643 } 2644 } 2645 2646 GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) 2647 { 2648 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)", 2649 program, uniformBlockIndex, uniformBlockBinding); 2650 2651 if(uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS) 2652 { 2653 return error(GL_INVALID_VALUE); 2654 } 2655 2656 es2::Context *context = es2::getContext(); 2657 2658 if(context) 2659 { 2660 es2::Program *programObject = context->getProgram(program); 2661 2662 if(!programObject) 2663 { 2664 return error(GL_INVALID_VALUE); 2665 } 2666 2667 programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); 2668 } 2669 } 2670 2671 GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) 2672 { 2673 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", 2674 mode, first, count, instanceCount); 2675 2676 switch(mode) 2677 { 2678 case GL_POINTS: 2679 case GL_LINES: 2680 case GL_LINE_LOOP: 2681 case GL_LINE_STRIP: 2682 case GL_TRIANGLES: 2683 case GL_TRIANGLE_FAN: 2684 case GL_TRIANGLE_STRIP: 2685 break; 2686 default: 2687 return error(GL_INVALID_ENUM); 2688 } 2689 2690 if(count < 0 || instanceCount < 0) 2691 { 2692 return error(GL_INVALID_VALUE); 2693 } 2694 2695 es2::Context *context = es2::getContext(); 2696 2697 if(context) 2698 { 2699 es2::TransformFeedback* transformFeedback = context->getTransformFeedback(); 2700 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode())) 2701 { 2702 return error(GL_INVALID_OPERATION); 2703 } 2704 2705 context->drawArrays(mode, first, count, instanceCount); 2706 } 2707 } 2708 2709 GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount) 2710 { 2711 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)", 2712 mode, count, type, indices, instanceCount); 2713 2714 switch(mode) 2715 { 2716 case GL_POINTS: 2717 case GL_LINES: 2718 case GL_LINE_LOOP: 2719 case GL_LINE_STRIP: 2720 case GL_TRIANGLES: 2721 case GL_TRIANGLE_FAN: 2722 case GL_TRIANGLE_STRIP: 2723 break; 2724 default: 2725 return error(GL_INVALID_ENUM); 2726 } 2727 2728 switch(type) 2729 { 2730 case GL_UNSIGNED_BYTE: 2731 case GL_UNSIGNED_SHORT: 2732 case GL_UNSIGNED_INT: 2733 break; 2734 default: 2735 return error(GL_INVALID_ENUM); 2736 } 2737 2738 if(count < 0 || instanceCount < 0) 2739 { 2740 return error(GL_INVALID_VALUE); 2741 } 2742 2743 es2::Context *context = es2::getContext(); 2744 2745 if(context) 2746 { 2747 es2::TransformFeedback* transformFeedback = context->getTransformFeedback(); 2748 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) 2749 { 2750 return error(GL_INVALID_OPERATION); 2751 } 2752 2753 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount); 2754 } 2755 } 2756 2757 GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags) 2758 { 2759 TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags); 2760 2761 switch(condition) 2762 { 2763 case GL_SYNC_GPU_COMMANDS_COMPLETE: 2764 break; 2765 default: 2766 return error(GL_INVALID_ENUM, nullptr); 2767 } 2768 2769 if(flags != 0) 2770 { 2771 return error(GL_INVALID_VALUE, nullptr); 2772 } 2773 2774 es2::Context *context = es2::getContext(); 2775 2776 if(context) 2777 { 2778 return context->createFenceSync(condition, flags); 2779 } 2780 2781 return nullptr; 2782 } 2783 2784 GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync) 2785 { 2786 TRACE("(GLsync sync = %p)", sync); 2787 2788 es2::Context *context = es2::getContext(); 2789 2790 if(context) 2791 { 2792 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync); 2793 2794 if(fenceSyncObject) 2795 { 2796 return GL_TRUE; 2797 } 2798 } 2799 2800 return GL_FALSE; 2801 } 2802 2803 GL_APICALL void GL_APIENTRY glDeleteSync(GLsync sync) 2804 { 2805 TRACE("(GLsync sync = %p)", sync); 2806 2807 if(!sync) 2808 { 2809 return; 2810 } 2811 2812 es2::Context *context = es2::getContext(); 2813 2814 if(context) 2815 { 2816 if(!context->getFenceSync(sync)) 2817 { 2818 return error(GL_INVALID_VALUE); 2819 } 2820 2821 context->deleteFenceSync(sync); 2822 } 2823 } 2824 2825 GL_APICALL GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) 2826 { 2827 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout); 2828 2829 if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) 2830 { 2831 return error(GL_INVALID_VALUE, GL_FALSE); 2832 } 2833 2834 es2::Context *context = es2::getContext(); 2835 2836 if(context) 2837 { 2838 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync); 2839 2840 if(fenceSyncObject) 2841 { 2842 return fenceSyncObject->clientWait(flags, timeout); 2843 } 2844 else 2845 { 2846 return error(GL_INVALID_VALUE, GL_FALSE); 2847 } 2848 } 2849 2850 return GL_FALSE; 2851 } 2852 2853 GL_APICALL void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) 2854 { 2855 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout); 2856 2857 if(flags != 0) 2858 { 2859 return error(GL_INVALID_VALUE); 2860 } 2861 2862 if(timeout != GL_TIMEOUT_IGNORED) 2863 { 2864 return error(GL_INVALID_VALUE); 2865 } 2866 2867 es2::Context *context = es2::getContext(); 2868 2869 if(context) 2870 { 2871 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync); 2872 2873 if(fenceSyncObject) 2874 { 2875 fenceSyncObject->serverWait(flags, timeout); 2876 } 2877 else 2878 { 2879 return error(GL_INVALID_VALUE); 2880 } 2881 } 2882 } 2883 2884 GL_APICALL void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *data) 2885 { 2886 TRACE("(GLenum pname = 0x%X, GLint64 *data = %p)", pname, data); 2887 2888 es2::Context *context = es2::getContext(); 2889 2890 if(context) 2891 { 2892 if(!(context->getIntegerv(pname, data))) 2893 { 2894 GLenum nativeType; 2895 unsigned int numParams = 0; 2896 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams)) 2897 return error(GL_INVALID_ENUM); 2898 2899 if(numParams == 0) 2900 return; // it is known that pname is valid, but there are no parameters to return 2901 2902 if(nativeType == GL_BOOL) 2903 { 2904 GLboolean *boolParams = nullptr; 2905 boolParams = new GLboolean[numParams]; 2906 2907 context->getBooleanv(pname, boolParams); 2908 2909 for(unsigned int i = 0; i < numParams; ++i) 2910 { 2911 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1; 2912 } 2913 2914 delete[] boolParams; 2915 } 2916 else if(nativeType == GL_FLOAT) 2917 { 2918 GLfloat *floatParams = nullptr; 2919 floatParams = new GLfloat[numParams]; 2920 2921 context->getFloatv(pname, floatParams); 2922 2923 for(unsigned int i = 0; i < numParams; ++i) 2924 { 2925 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) 2926 { 2927 data[i] = (GLint64)(convert_float_fixed(floatParams[i])); 2928 } 2929 else 2930 { 2931 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); 2932 } 2933 } 2934 2935 delete[] floatParams; 2936 } 2937 } 2938 } 2939 } 2940 2941 GL_APICALL void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) 2942 { 2943 TRACE("(GLsync sync = %p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = %p, GLint *values = %p)", 2944 sync, pname, bufSize, length, values); 2945 2946 if(bufSize < 0) 2947 { 2948 return error(GL_INVALID_VALUE); 2949 } 2950 2951 es2::Context *context = es2::getContext(); 2952 2953 if(context) 2954 { 2955 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync); 2956 if(!fenceSyncObject) 2957 { 2958 return error(GL_INVALID_VALUE); 2959 } 2960 2961 fenceSyncObject->getSynciv(pname, length, values); 2962 } 2963 } 2964 2965 GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data) 2966 { 2967 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint64 *data = %p)", target, index, data); 2968 2969 es2::Context *context = es2::getContext(); 2970 2971 if(context) 2972 { 2973 if(!context->getTransformFeedbackiv(index, target, data) && 2974 !context->getUniformBufferiv(index, target, data) && 2975 !context->getIntegerv(target, data)) 2976 { 2977 GLenum nativeType; 2978 unsigned int numParams = 0; 2979 if(!context->getQueryParameterInfo(target, &nativeType, &numParams)) 2980 return error(GL_INVALID_ENUM); 2981 2982 if(numParams == 0) 2983 return; // it is known that target is valid, but there are no parameters to return 2984 2985 if(nativeType == GL_BOOL) 2986 { 2987 GLboolean *boolParams = nullptr; 2988 boolParams = new GLboolean[numParams]; 2989 2990 context->getBooleanv(target, boolParams); 2991 2992 for(unsigned int i = 0; i < numParams; ++i) 2993 { 2994 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1; 2995 } 2996 2997 delete[] boolParams; 2998 } 2999 else if(nativeType == GL_FLOAT) 3000 { 3001 GLfloat *floatParams = nullptr; 3002 floatParams = new GLfloat[numParams]; 3003 3004 context->getFloatv(target, floatParams); 3005 3006 for(unsigned int i = 0; i < numParams; ++i) 3007 { 3008 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR) 3009 { 3010 data[i] = (GLint64)(convert_float_fixed(floatParams[i])); 3011 } 3012 else 3013 { 3014 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); 3015 } 3016 } 3017 3018 delete[] floatParams; 3019 } 3020 } 3021 } 3022 } 3023 3024 GL_APICALL void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) 3025 { 3026 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = %p)", target, pname, params); 3027 3028 es2::Context *context = es2::getContext(); 3029 3030 if(context) 3031 { 3032 es2::Buffer *buffer = nullptr; 3033 3034 if(!context->getBuffer(target, &buffer)) 3035 { 3036 return error(GL_INVALID_ENUM); 3037 } 3038 3039 if(!buffer) 3040 { 3041 // A null buffer means that "0" is bound to the requested buffer target 3042 return error(GL_INVALID_OPERATION); 3043 } 3044 3045 switch(pname) 3046 { 3047 case GL_BUFFER_USAGE: 3048 *params = buffer->usage(); 3049 break; 3050 case GL_BUFFER_SIZE: 3051 *params = buffer->size(); 3052 break; 3053 case GL_BUFFER_ACCESS_FLAGS: 3054 *params = buffer->access(); 3055 break; 3056 case GL_BUFFER_MAPPED: 3057 *params = buffer->isMapped(); 3058 break; 3059 case GL_BUFFER_MAP_LENGTH: 3060 *params = buffer->length(); 3061 break; 3062 case GL_BUFFER_MAP_OFFSET: 3063 *params = buffer->offset(); 3064 break; 3065 default: 3066 return error(GL_INVALID_ENUM); 3067 } 3068 } 3069 } 3070 3071 GL_APICALL void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers) 3072 { 3073 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers); 3074 3075 if(count < 0) 3076 { 3077 return error(GL_INVALID_VALUE); 3078 } 3079 3080 es2::Context *context = es2::getContext(); 3081 3082 if(context) 3083 { 3084 for(int i = 0; i < count; i++) 3085 { 3086 samplers[i] = context->createSampler(); 3087 } 3088 } 3089 } 3090 3091 GL_APICALL void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers) 3092 { 3093 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers); 3094 3095 if(count < 0) 3096 { 3097 return error(GL_INVALID_VALUE); 3098 } 3099 3100 es2::Context *context = es2::getContext(); 3101 3102 if(context) 3103 { 3104 for(int i = 0; i < count; i++) 3105 { 3106 context->deleteSampler(samplers[i]); 3107 } 3108 } 3109 } 3110 3111 GL_APICALL GLboolean GL_APIENTRY glIsSampler(GLuint sampler) 3112 { 3113 TRACE("(GLuint sampler = %d)", sampler); 3114 3115 if(sampler == 0) 3116 { 3117 return GL_FALSE; 3118 } 3119 3120 es2::Context *context = es2::getContext(); 3121 3122 if(context) 3123 { 3124 if(context->isSampler(sampler)) 3125 { 3126 return GL_TRUE; 3127 } 3128 } 3129 3130 return GL_FALSE; 3131 } 3132 3133 GL_APICALL void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler) 3134 { 3135 TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler); 3136 3137 if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS) 3138 { 3139 return error(GL_INVALID_VALUE); 3140 } 3141 3142 es2::Context *context = es2::getContext(); 3143 3144 if(context) 3145 { 3146 if(sampler != 0 && !context->isSampler(sampler)) 3147 { 3148 return error(GL_INVALID_OPERATION); 3149 } 3150 3151 context->bindSampler(unit, sampler); 3152 } 3153 } 3154 3155 GL_APICALL void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) 3156 { 3157 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint param = %d)", 3158 sampler, pname, param); 3159 3160 glSamplerParameteriv(sampler, pname, ¶m); 3161 } 3162 3163 GL_APICALL void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param) 3164 { 3165 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = %p)", 3166 sampler, pname, param); 3167 3168 if(!ValidateSamplerObjectParameter(pname)) 3169 { 3170 return error(GL_INVALID_ENUM); 3171 } 3172 3173 if(!ValidateTexParamParameters(pname, *param)) 3174 { 3175 return; 3176 } 3177 3178 es2::Context *context = es2::getContext(); 3179 3180 if(context) 3181 { 3182 if(!context->isSampler(sampler)) 3183 { 3184 return error(GL_INVALID_OPERATION); 3185 } 3186 3187 context->samplerParameteri(sampler, pname, *param); 3188 } 3189 } 3190 3191 GL_APICALL void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) 3192 { 3193 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat param = %f)", 3194 sampler, pname, param); 3195 3196 glSamplerParameterfv(sampler, pname, ¶m); 3197 } 3198 3199 GL_APICALL void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param) 3200 { 3201 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = %p)", 3202 sampler, pname, param); 3203 3204 if(!ValidateSamplerObjectParameter(pname)) 3205 { 3206 return error(GL_INVALID_ENUM); 3207 } 3208 3209 es2::Context *context = es2::getContext(); 3210 3211 if(context) 3212 { 3213 if(!context->isSampler(sampler)) 3214 { 3215 return error(GL_INVALID_OPERATION); 3216 } 3217 3218 if(ValidateTexParamParameters(pname, static_cast<GLint>(roundf(*param)))) 3219 { 3220 context->samplerParameterf(sampler, pname, *param); 3221 } 3222 } 3223 } 3224 3225 GL_APICALL void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) 3226 { 3227 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = %p)", 3228 sampler, pname, params); 3229 3230 if(!ValidateSamplerObjectParameter(pname)) 3231 { 3232 return error(GL_INVALID_ENUM); 3233 } 3234 3235 es2::Context *context = es2::getContext(); 3236 3237 if(context) 3238 { 3239 if(!context->isSampler(sampler)) 3240 { 3241 return error(GL_INVALID_OPERATION); 3242 } 3243 3244 *params = context->getSamplerParameteri(sampler, pname); 3245 } 3246 } 3247 3248 GL_APICALL void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) 3249 { 3250 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = %p)", 3251 sampler, pname, params); 3252 3253 if(!ValidateSamplerObjectParameter(pname)) 3254 { 3255 return error(GL_INVALID_ENUM); 3256 } 3257 3258 es2::Context *context = es2::getContext(); 3259 3260 if(context) 3261 { 3262 if(!context->isSampler(sampler)) 3263 { 3264 return error(GL_INVALID_OPERATION); 3265 } 3266 3267 *params = context->getSamplerParameterf(sampler, pname); 3268 } 3269 } 3270 3271 GL_APICALL void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) 3272 { 3273 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor); 3274 3275 es2::Context *context = es2::getContext(); 3276 3277 if(context) 3278 { 3279 if(index >= es2::MAX_VERTEX_ATTRIBS) 3280 { 3281 return error(GL_INVALID_VALUE); 3282 } 3283 3284 context->setVertexAttribDivisor(index, divisor); 3285 } 3286 } 3287 3288 GL_APICALL void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) 3289 { 3290 TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id); 3291 3292 if(target != GL_TRANSFORM_FEEDBACK) 3293 { 3294 return error(GL_INVALID_ENUM); 3295 } 3296 3297 es2::Context *context = es2::getContext(); 3298 3299 if(context) 3300 { 3301 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(); 3302 3303 if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused()) 3304 { 3305 return error(GL_INVALID_OPERATION); 3306 } 3307 3308 if(!context->isTransformFeedback(id)) 3309 { 3310 return error(GL_INVALID_OPERATION); 3311 } 3312 3313 context->bindTransformFeedback(id); 3314 } 3315 } 3316 3317 GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids) 3318 { 3319 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids); 3320 3321 if(n < 0) 3322 { 3323 return error(GL_INVALID_VALUE); 3324 } 3325 3326 es2::Context *context = es2::getContext(); 3327 3328 if(context) 3329 { 3330 for(int i = 0; i < n; i++) 3331 { 3332 if(ids[i] != 0) 3333 { 3334 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(ids[i]); 3335 3336 if(transformFeedbackObject && transformFeedbackObject->isActive()) 3337 { 3338 return error(GL_INVALID_OPERATION); 3339 } 3340 3341 context->deleteTransformFeedback(ids[i]); 3342 } 3343 } 3344 } 3345 } 3346 3347 GL_APICALL void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids) 3348 { 3349 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids); 3350 3351 if(n < 0) 3352 { 3353 return error(GL_INVALID_VALUE); 3354 } 3355 3356 es2::Context *context = es2::getContext(); 3357 3358 if(context) 3359 { 3360 for(int i = 0; i < n; i++) 3361 { 3362 ids[i] = context->createTransformFeedback(); 3363 } 3364 } 3365 } 3366 3367 GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) 3368 { 3369 TRACE("(GLuint id = %d)", id); 3370 3371 if(id == 0) 3372 { 3373 return GL_FALSE; 3374 } 3375 3376 es2::Context *context = es2::getContext(); 3377 3378 if(context) 3379 { 3380 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id); 3381 3382 if(transformFeedbackObject) 3383 { 3384 return GL_TRUE; 3385 } 3386 } 3387 3388 return GL_FALSE; 3389 } 3390 3391 GL_APICALL void GL_APIENTRY glPauseTransformFeedback(void) 3392 { 3393 TRACE("()"); 3394 3395 es2::Context *context = es2::getContext(); 3396 3397 if(context) 3398 { 3399 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(); 3400 3401 if(transformFeedbackObject) 3402 { 3403 if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused()) 3404 { 3405 return error(GL_INVALID_OPERATION); 3406 } 3407 transformFeedbackObject->setPaused(true); 3408 } 3409 } 3410 } 3411 3412 GL_APICALL void GL_APIENTRY glResumeTransformFeedback(void) 3413 { 3414 TRACE("()"); 3415 3416 es2::Context *context = es2::getContext(); 3417 3418 if(context) 3419 { 3420 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(); 3421 3422 if(transformFeedbackObject) 3423 { 3424 if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused()) 3425 { 3426 return error(GL_INVALID_OPERATION); 3427 } 3428 transformFeedbackObject->setPaused(false); 3429 } 3430 } 3431 } 3432 3433 GL_APICALL void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) 3434 { 3435 TRACE("(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLenum *binaryFormat = %p, void *binary = %p)", 3436 program, bufSize, length, binaryFormat, binary); 3437 3438 if(bufSize < 0) 3439 { 3440 return error(GL_INVALID_VALUE); 3441 } 3442 3443 es2::Context *context = es2::getContext(); 3444 3445 if(context) 3446 { 3447 es2::Program *programObject = context->getProgram(program); 3448 3449 if(!programObject || !programObject->isLinked()) 3450 { 3451 return error(GL_INVALID_OPERATION); 3452 } 3453 } 3454 3455 // SwiftShader doesn't return a program binary and sets the program binay size to 0, so any attempt at getting one is invalid. 3456 return error(GL_INVALID_OPERATION); 3457 } 3458 3459 GL_APICALL void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) 3460 { 3461 TRACE("(GLuint program = %d, GLenum binaryFormat = 0x%X, const void *binary = %p, GLsizei length = %d)", 3462 program, binaryFormat, binaryFormat, length); 3463 3464 if(length < 0) 3465 { 3466 return error(GL_INVALID_VALUE); 3467 } 3468 3469 es2::Context *context = es2::getContext(); 3470 3471 if(context) 3472 { 3473 es2::Program *programObject = context->getProgram(program); 3474 3475 if(!programObject) 3476 { 3477 return error(GL_INVALID_OPERATION); 3478 } 3479 } 3480 3481 // Regardless of what the binaryFormat is, it is unrecognized by SwiftShader, since it supports no format. 3482 return error(GL_INVALID_ENUM); 3483 } 3484 3485 GL_APICALL void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) 3486 { 3487 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint value = %d)", 3488 program, pname, value); 3489 3490 es2::Context *context = es2::getContext(); 3491 3492 if(context) 3493 { 3494 es2::Program *programObject = context->getProgram(program); 3495 3496 if(!programObject) 3497 { 3498 return error(GL_INVALID_VALUE); 3499 } 3500 3501 switch(pname) 3502 { 3503 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: 3504 if((value != GL_TRUE) && (value != GL_FALSE)) 3505 { 3506 return error(GL_INVALID_VALUE); 3507 } 3508 programObject->setBinaryRetrievable(value != GL_FALSE); 3509 break; 3510 default: 3511 return error(GL_INVALID_ENUM); 3512 } 3513 } 3514 } 3515 3516 GL_APICALL void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) 3517 { 3518 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p)", 3519 target, numAttachments, attachments); 3520 3521 glInvalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, std::numeric_limits<GLsizei>::max(), std::numeric_limits<GLsizei>::max()); 3522 } 3523 3524 GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) 3525 { 3526 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", 3527 target, numAttachments, attachments, x, y, width, height); 3528 3529 es2::Context *context = es2::getContext(); 3530 3531 if(context) 3532 { 3533 if(numAttachments < 0 || width < 0 || height < 0) 3534 { 3535 return error(GL_INVALID_VALUE); 3536 } 3537 3538 es2::Framebuffer *framebuffer = nullptr; 3539 switch(target) 3540 { 3541 case GL_DRAW_FRAMEBUFFER: 3542 case GL_FRAMEBUFFER: 3543 framebuffer = context->getDrawFramebuffer(); 3544 break; 3545 case GL_READ_FRAMEBUFFER: 3546 framebuffer = context->getReadFramebuffer(); 3547 break; 3548 default: 3549 return error(GL_INVALID_ENUM); 3550 } 3551 3552 if(framebuffer) 3553 { 3554 for(int i = 0; i < numAttachments; i++) 3555 { 3556 switch(attachments[i]) 3557 { 3558 case GL_COLOR: 3559 case GL_DEPTH: 3560 case GL_STENCIL: 3561 if(!framebuffer->isDefaultFramebuffer()) 3562 { 3563 return error(GL_INVALID_ENUM); 3564 } 3565 break; 3566 case GL_DEPTH_ATTACHMENT: 3567 case GL_STENCIL_ATTACHMENT: 3568 case GL_DEPTH_STENCIL_ATTACHMENT: 3569 break; 3570 default: 3571 if(attachments[i] >= GL_COLOR_ATTACHMENT0 && 3572 attachments[i] <= GL_COLOR_ATTACHMENT31) 3573 { 3574 if(attachments[i] - GL_COLOR_ATTACHMENT0 >= MAX_DRAW_BUFFERS) 3575 { 3576 return error(GL_INVALID_OPERATION); 3577 } 3578 } 3579 else 3580 { 3581 return error(GL_INVALID_ENUM); 3582 } 3583 break; 3584 } 3585 } 3586 } 3587 3588 // UNIMPLEMENTED(); // It is valid for this function to be treated as a no-op 3589 } 3590 } 3591 3592 GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) 3593 { 3594 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", 3595 target, levels, internalformat, width, height); 3596 3597 if(width < 1 || height < 1 || levels < 1 || ((target == GL_TEXTURE_RECTANGLE_ARB) && (levels != 1))) 3598 { 3599 return error(GL_INVALID_VALUE); 3600 } 3601 3602 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1)) 3603 { 3604 return error(GL_INVALID_OPERATION); 3605 } 3606 3607 bool isCompressed = IsCompressed(internalformat, egl::getClientVersion()); 3608 if(!IsSizedInternalFormat(internalformat) && !isCompressed) 3609 { 3610 return error(GL_INVALID_ENUM); 3611 } 3612 3613 es2::Context *context = es2::getContext(); 3614 3615 if(context) 3616 { 3617 switch(target) 3618 { 3619 case GL_TEXTURE_RECTANGLE_ARB: 3620 if(isCompressed) // Rectangle textures cannot be compressed 3621 { 3622 return error(GL_INVALID_ENUM); 3623 } 3624 // Fall through to GL_TEXTURE_2D case. 3625 case GL_TEXTURE_2D: 3626 { 3627 if((width > es2::IMPLEMENTATION_MAX_TEXTURE_SIZE) || 3628 (height > es2::IMPLEMENTATION_MAX_TEXTURE_SIZE)) 3629 { 3630 return error(GL_INVALID_VALUE); 3631 } 3632 3633 es2::Texture2D *texture = context->getTexture2D(target); 3634 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE) 3635 { 3636 return error(GL_INVALID_OPERATION); 3637 } 3638 3639 for(int level = 0; level < levels; level++) 3640 { 3641 texture->setImage(level, width, height, internalformat, GL_NONE, GL_NONE, context->getUnpackParameters(), nullptr); 3642 width = std::max(1, (width / 2)); 3643 height = std::max(1, (height / 2)); 3644 } 3645 texture->makeImmutable(levels); 3646 } 3647 break; 3648 case GL_TEXTURE_CUBE_MAP: 3649 { 3650 if((width > es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE) || 3651 (height > es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE)) 3652 { 3653 return error(GL_INVALID_VALUE); 3654 } 3655 3656 es2::TextureCubeMap *texture = context->getTextureCubeMap(); 3657 if(!texture || texture->name == 0 || texture->getImmutableFormat()) 3658 { 3659 return error(GL_INVALID_OPERATION); 3660 } 3661 3662 for(int level = 0; level < levels; level++) 3663 { 3664 for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) 3665 { 3666 texture->setImage(face, level, width, height, internalformat, GL_NONE, GL_NONE, context->getUnpackParameters(), nullptr); 3667 } 3668 width = std::max(1, (width / 2)); 3669 height = std::max(1, (height / 2)); 3670 } 3671 texture->makeImmutable(levels); 3672 } 3673 break; 3674 default: 3675 return error(GL_INVALID_ENUM); 3676 } 3677 } 3678 } 3679 3680 GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) 3681 { 3682 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d)", 3683 target, levels, internalformat, width, height, depth); 3684 3685 if(width < 1 || height < 1 || depth < 1 || levels < 1) 3686 { 3687 return error(GL_INVALID_VALUE); 3688 } 3689 3690 if(!IsSizedInternalFormat(internalformat) && !IsCompressed(internalformat, egl::getClientVersion())) 3691 { 3692 return error(GL_INVALID_ENUM); 3693 } 3694 3695 es2::Context *context = es2::getContext(); 3696 3697 if(context) 3698 { 3699 switch(target) 3700 { 3701 case GL_TEXTURE_3D: 3702 { 3703 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1)) 3704 { 3705 return error(GL_INVALID_OPERATION); 3706 } 3707 3708 es2::Texture3D *texture = context->getTexture3D(); 3709 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE) 3710 { 3711 return error(GL_INVALID_OPERATION); 3712 } 3713 3714 for(int level = 0; level < levels; level++) 3715 { 3716 texture->setImage(level, width, height, depth, internalformat, GL_NONE, GL_NONE, context->getUnpackParameters(), nullptr); 3717 width = std::max(1, (width / 2)); 3718 height = std::max(1, (height / 2)); 3719 depth = std::max(1, (depth / 2)); 3720 } 3721 texture->makeImmutable(levels); 3722 } 3723 break; 3724 case GL_TEXTURE_2D_ARRAY: 3725 { 3726 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1)) 3727 { 3728 return error(GL_INVALID_OPERATION); 3729 } 3730 3731 es2::Texture3D *texture = context->getTexture2DArray(); 3732 if(!texture || texture->name == 0 || texture->getImmutableFormat()) 3733 { 3734 return error(GL_INVALID_OPERATION); 3735 } 3736 3737 for(int level = 0; level < levels; level++) 3738 { 3739 texture->setImage(level, width, height, depth, internalformat, GL_NONE, GL_NONE, context->getUnpackParameters(), nullptr); 3740 3741 width = std::max(1, (width / 2)); 3742 height = std::max(1, (height / 2)); 3743 } 3744 texture->makeImmutable(levels); 3745 } 3746 break; 3747 default: 3748 return error(GL_INVALID_ENUM); 3749 } 3750 } 3751 } 3752 3753 GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) 3754 { 3755 TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLint *params = %p)", 3756 target, internalformat, pname, bufSize, params); 3757 3758 if(bufSize < 0) 3759 { 3760 return error(GL_INVALID_VALUE); 3761 } 3762 3763 if(bufSize == 0) 3764 { 3765 return; 3766 } 3767 3768 // OpenGL ES 3.0, section 4.4.4: "An internal format is color-renderable if it is one of the formats 3769 // from table 3.13 noted as color-renderable or if it is unsized format RGBA or RGB." 3770 // Since we only use sized formats internally, replace them here (assuming type = GL_UNSIGNED_BYTE). 3771 if(internalformat == GL_RGB) internalformat = GL_RGB8; 3772 if(internalformat == GL_RGBA) internalformat = GL_RGBA8; 3773 3774 if(!IsColorRenderable(internalformat, egl::getClientVersion()) && 3775 !IsDepthRenderable(internalformat, egl::getClientVersion()) && 3776 !IsStencilRenderable(internalformat, egl::getClientVersion())) 3777 { 3778 return error(GL_INVALID_ENUM); 3779 } 3780 3781 switch(target) 3782 { 3783 case GL_RENDERBUFFER: 3784 break; 3785 default: 3786 return error(GL_INVALID_ENUM); 3787 } 3788 3789 GLint numMultisampleCounts = NUM_MULTISAMPLE_COUNTS; 3790 3791 // Integer types have no multisampling 3792 GLenum type = GetColorComponentType(internalformat); 3793 if(type != GL_UNSIGNED_NORMALIZED && type != GL_FLOAT) 3794 { 3795 numMultisampleCounts = 0; 3796 } 3797 3798 switch(pname) 3799 { 3800 case GL_NUM_SAMPLE_COUNTS: 3801 *params = numMultisampleCounts; 3802 break; 3803 case GL_SAMPLES: 3804 for(int i = 0; i < numMultisampleCounts && i < bufSize; i++) 3805 { 3806 params[i] = multisampleCount[i]; 3807 } 3808 break; 3809 default: 3810 return error(GL_INVALID_ENUM); 3811 } 3812 } 3813 3814 } 3815