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 // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer 16 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. 17 18 #include "Framebuffer.h" 19 20 #include "main.h" 21 #include "Renderbuffer.h" 22 #include "Texture.h" 23 #include "utilities.h" 24 25 namespace es2 26 { 27 28 bool Framebuffer::IsRenderbuffer(GLenum type) 29 { 30 return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT; 31 } 32 33 Framebuffer::Framebuffer() 34 { 35 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) 36 { 37 mColorbufferType[i] = GL_NONE; 38 } 39 mDepthbufferType = GL_NONE; 40 mStencilbufferType = GL_NONE; 41 42 readBuffer = GL_BACK; 43 drawBuffer[0] = GL_BACK; 44 for(int i = 1; i < MAX_COLOR_ATTACHMENTS; ++i) 45 { 46 drawBuffer[i] = GL_NONE; 47 } 48 } 49 50 Framebuffer::~Framebuffer() 51 { 52 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) 53 { 54 mColorbufferPointer[i] = nullptr; 55 } 56 mDepthbufferPointer = nullptr; 57 mStencilbufferPointer = nullptr; 58 } 59 60 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const 61 { 62 Context *context = getContext(); 63 Renderbuffer *buffer = nullptr; 64 65 if(type == GL_NONE) 66 { 67 buffer = nullptr; 68 } 69 else if(IsRenderbuffer(type)) 70 { 71 buffer = context->getRenderbuffer(handle); 72 } 73 else if(IsTextureTarget(type)) 74 { 75 buffer = context->getTexture(handle)->getRenderbuffer(type, level, layer); 76 } 77 else UNREACHABLE(type); 78 79 return buffer; 80 } 81 82 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer) 83 { 84 mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE; 85 mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level, layer); 86 } 87 88 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) 89 { 90 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE; 91 mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level, layer); 92 } 93 94 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) 95 { 96 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE; 97 mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level, layer); 98 } 99 100 void Framebuffer::setReadBuffer(GLenum buf) 101 { 102 readBuffer = buf; 103 } 104 105 void Framebuffer::setDrawBuffer(GLuint index, GLenum buf) 106 { 107 drawBuffer[index] = buf; 108 } 109 110 GLenum Framebuffer::getReadBuffer() const 111 { 112 return readBuffer; 113 } 114 115 GLenum Framebuffer::getDrawBuffer(GLuint index) const 116 { 117 return drawBuffer[index]; 118 } 119 120 void Framebuffer::detachTexture(GLuint texture) 121 { 122 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) 123 { 124 if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i])) 125 { 126 mColorbufferType[i] = GL_NONE; 127 mColorbufferPointer[i] = nullptr; 128 } 129 } 130 131 if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType)) 132 { 133 mDepthbufferType = GL_NONE; 134 mDepthbufferPointer = nullptr; 135 } 136 137 if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType)) 138 { 139 mStencilbufferType = GL_NONE; 140 mStencilbufferPointer = nullptr; 141 } 142 } 143 144 void Framebuffer::detachRenderbuffer(GLuint renderbuffer) 145 { 146 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) 147 { 148 if(mColorbufferPointer[i].name() == renderbuffer && IsRenderbuffer(mColorbufferType[i])) 149 { 150 mColorbufferType[i] = GL_NONE; 151 mColorbufferPointer[i] = nullptr; 152 } 153 } 154 155 if(mDepthbufferPointer.name() == renderbuffer && IsRenderbuffer(mDepthbufferType)) 156 { 157 mDepthbufferType = GL_NONE; 158 mDepthbufferPointer = nullptr; 159 } 160 161 if(mStencilbufferPointer.name() == renderbuffer && IsRenderbuffer(mStencilbufferType)) 162 { 163 mStencilbufferType = GL_NONE; 164 mStencilbufferPointer = nullptr; 165 } 166 } 167 168 // Increments refcount on surface. 169 // caller must Release() the returned surface 170 egl::Image *Framebuffer::getRenderTarget(GLuint index) 171 { 172 Renderbuffer *colorbuffer = mColorbufferPointer[index]; 173 174 if(colorbuffer) 175 { 176 return colorbuffer->getRenderTarget(); 177 } 178 179 return nullptr; 180 } 181 182 egl::Image *Framebuffer::getReadRenderTarget() 183 { 184 Context *context = getContext(); 185 return getRenderTarget(context->getReadFramebufferColorIndex()); 186 } 187 188 // Increments refcount on surface. 189 // caller must Release() the returned surface 190 egl::Image *Framebuffer::getDepthBuffer() 191 { 192 Renderbuffer *depthbuffer = mDepthbufferPointer; 193 194 if(depthbuffer) 195 { 196 return depthbuffer->getRenderTarget(); 197 } 198 199 return nullptr; 200 } 201 202 // Increments refcount on surface. 203 // caller must Release() the returned surface 204 egl::Image *Framebuffer::getStencilBuffer() 205 { 206 Renderbuffer *stencilbuffer = mStencilbufferPointer; 207 208 if(stencilbuffer) 209 { 210 return stencilbuffer->getRenderTarget(); 211 } 212 213 return nullptr; 214 } 215 216 Renderbuffer *Framebuffer::getColorbuffer(GLuint index) 217 { 218 return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr; 219 } 220 221 Renderbuffer *Framebuffer::getReadColorbuffer() 222 { 223 Context *context = getContext(); 224 return getColorbuffer(context->getReadFramebufferColorIndex()); 225 } 226 227 Renderbuffer *Framebuffer::getDepthbuffer() 228 { 229 return mDepthbufferPointer; 230 } 231 232 Renderbuffer *Framebuffer::getStencilbuffer() 233 { 234 return mStencilbufferPointer; 235 } 236 237 GLenum Framebuffer::getColorbufferType(GLuint index) 238 { 239 return mColorbufferType[index]; 240 } 241 242 GLenum Framebuffer::getDepthbufferType() 243 { 244 return mDepthbufferType; 245 } 246 247 GLenum Framebuffer::getStencilbufferType() 248 { 249 return mStencilbufferType; 250 } 251 252 GLuint Framebuffer::getColorbufferName(GLuint index) 253 { 254 return mColorbufferPointer[index].name(); 255 } 256 257 GLuint Framebuffer::getDepthbufferName() 258 { 259 return mDepthbufferPointer.name(); 260 } 261 262 GLuint Framebuffer::getStencilbufferName() 263 { 264 return mStencilbufferPointer.name(); 265 } 266 267 GLint Framebuffer::getColorbufferLayer(GLuint index) 268 { 269 Renderbuffer *colorbuffer = mColorbufferPointer[index]; 270 return colorbuffer ? colorbuffer->getLayer() : 0; 271 } 272 273 GLint Framebuffer::getDepthbufferLayer() 274 { 275 return mDepthbufferPointer ? mDepthbufferPointer->getLayer() : 0; 276 } 277 278 GLint Framebuffer::getStencilbufferLayer() 279 { 280 return mStencilbufferPointer ? mStencilbufferPointer->getLayer() : 0; 281 } 282 283 bool Framebuffer::hasStencil() 284 { 285 if(mStencilbufferType != GL_NONE) 286 { 287 Renderbuffer *stencilbufferObject = getStencilbuffer(); 288 289 if(stencilbufferObject) 290 { 291 return stencilbufferObject->getStencilSize() > 0; 292 } 293 } 294 295 return false; 296 } 297 298 GLenum Framebuffer::completeness() 299 { 300 int width; 301 int height; 302 int samples; 303 304 return completeness(width, height, samples); 305 } 306 307 GLenum Framebuffer::completeness(int &width, int &height, int &samples) 308 { 309 width = -1; 310 height = -1; 311 samples = -1; 312 313 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) 314 { 315 if(mColorbufferType[i] != GL_NONE) 316 { 317 Renderbuffer *colorbuffer = getColorbuffer(i); 318 319 if(!colorbuffer) 320 { 321 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 322 } 323 324 if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= colorbuffer->getLayer())) 325 { 326 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 327 } 328 329 if(IsRenderbuffer(mColorbufferType[i])) 330 { 331 if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion())) 332 { 333 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 334 } 335 } 336 else if(IsTextureTarget(mColorbufferType[i])) 337 { 338 GLenum format = colorbuffer->getFormat(); 339 340 if(!IsColorRenderable(format, egl::getClientVersion())) 341 { 342 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 343 } 344 345 if(IsDepthTexture(format) || IsStencilTexture(format)) 346 { 347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 348 } 349 } 350 else 351 { 352 UNREACHABLE(mColorbufferType[i]); 353 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 354 } 355 356 width = colorbuffer->getWidth(); 357 height = colorbuffer->getHeight(); 358 359 if(samples == -1) 360 { 361 samples = colorbuffer->getSamples(); 362 } 363 else if(samples != colorbuffer->getSamples()) 364 { 365 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 366 } 367 } 368 } 369 370 Renderbuffer *depthbuffer = nullptr; 371 Renderbuffer *stencilbuffer = nullptr; 372 373 if(mDepthbufferType != GL_NONE) 374 { 375 depthbuffer = getDepthbuffer(); 376 377 if(!depthbuffer) 378 { 379 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 380 } 381 382 if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) 383 { 384 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 385 } 386 387 if(IsRenderbuffer(mDepthbufferType)) 388 { 389 if(!es2::IsDepthRenderable(depthbuffer->getFormat())) 390 { 391 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 392 } 393 } 394 else if(IsTextureTarget(mDepthbufferType)) 395 { 396 if(!es2::IsDepthTexture(depthbuffer->getFormat())) 397 { 398 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 399 } 400 } 401 else 402 { 403 UNREACHABLE(mDepthbufferType); 404 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 405 } 406 407 if(width == -1 || height == -1) 408 { 409 width = depthbuffer->getWidth(); 410 height = depthbuffer->getHeight(); 411 samples = depthbuffer->getSamples(); 412 } 413 else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) 414 { 415 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 416 } 417 else if(samples != depthbuffer->getSamples()) 418 { 419 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 420 } 421 } 422 423 if(mStencilbufferType != GL_NONE) 424 { 425 stencilbuffer = getStencilbuffer(); 426 427 if(!stencilbuffer) 428 { 429 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 430 } 431 432 if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) 433 { 434 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 435 } 436 437 if(IsRenderbuffer(mStencilbufferType)) 438 { 439 if(!es2::IsStencilRenderable(stencilbuffer->getFormat())) 440 { 441 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 442 } 443 } 444 else if(IsTextureTarget(mStencilbufferType)) 445 { 446 GLenum internalformat = stencilbuffer->getFormat(); 447 448 if(!es2::IsStencilTexture(internalformat)) 449 { 450 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 451 } 452 } 453 else 454 { 455 UNREACHABLE(mStencilbufferType); 456 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 457 } 458 459 if(width == -1 || height == -1) 460 { 461 width = stencilbuffer->getWidth(); 462 height = stencilbuffer->getHeight(); 463 samples = stencilbuffer->getSamples(); 464 } 465 else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) 466 { 467 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 468 } 469 else if(samples != stencilbuffer->getSamples()) 470 { 471 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 472 } 473 } 474 475 if((egl::getClientVersion() >= 3) && depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) 476 { 477 // In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness: 478 // "The framebuffer object target is said to be framebuffer complete if all the following conditions are true: 479 // [...] 480 // Depth and stencil attachments, if present, are the same image. 481 // { FRAMEBUFFER_UNSUPPORTED }" 482 return GL_FRAMEBUFFER_UNSUPPORTED; 483 } 484 485 // We need to have at least one attachment to be complete 486 if(width == -1 || height == -1) 487 { 488 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; 489 } 490 491 return GL_FRAMEBUFFER_COMPLETE; 492 } 493 494 GLenum Framebuffer::getImplementationColorReadFormat() 495 { 496 Renderbuffer *colorbuffer = getReadColorbuffer(); 497 498 if(colorbuffer) 499 { 500 // Don't return GL_RGBA since that's always supported. Provide a second option here. 501 switch(colorbuffer->getInternalFormat()) 502 { 503 case sw::FORMAT_A8B8G8R8I: 504 case sw::FORMAT_A8B8G8R8UI: 505 case sw::FORMAT_A16B16G16R16I: 506 case sw::FORMAT_A16B16G16R16UI: 507 case sw::FORMAT_A32B32G32R32I: 508 case sw::FORMAT_A32B32G32R32UI:return GL_RGBA_INTEGER; 509 case sw::FORMAT_A2B10G10R10: return GL_RGB10_A2; 510 case sw::FORMAT_A8B8G8R8I_SNORM: 511 case sw::FORMAT_A16B16G16R16F: 512 case sw::FORMAT_A32B32G32R32F: 513 case sw::FORMAT_A8R8G8B8: 514 case sw::FORMAT_A8B8G8R8: 515 case sw::FORMAT_SRGB8_A8: 516 case sw::FORMAT_A1R5G5B5: return GL_BGRA_EXT; 517 case sw::FORMAT_X8B8G8R8I: 518 case sw::FORMAT_X8B8G8R8UI: 519 case sw::FORMAT_X16B16G16R16I: 520 case sw::FORMAT_X16B16G16R16UI: 521 case sw::FORMAT_X32B32G32R32I: 522 case sw::FORMAT_X32B32G32R32UI:return GL_RGB_INTEGER; 523 case sw::FORMAT_X32B32G32R32F: 524 case sw::FORMAT_B16G16R16F: 525 case sw::FORMAT_X8B8G8R8I_SNORM: 526 case sw::FORMAT_SRGB8_X8: 527 case sw::FORMAT_X8B8G8R8: return GL_RGB; 528 case sw::FORMAT_X8R8G8B8: return 0x80E0; // GL_BGR_EXT 529 case sw::FORMAT_R5G6B5: return GL_RGB; 530 case sw::FORMAT_G8R8I: 531 case sw::FORMAT_G8R8UI: 532 case sw::FORMAT_G16R16I: 533 case sw::FORMAT_G16R16UI: 534 case sw::FORMAT_G32R32I: 535 case sw::FORMAT_G32R32UI: return GL_RG_INTEGER; 536 case sw::FORMAT_G8R8: 537 case sw::FORMAT_G8R8I_SNORM: 538 case sw::FORMAT_G16R16F: 539 case sw::FORMAT_G32R32F: return GL_RG; 540 case sw::FORMAT_R8I: 541 case sw::FORMAT_R8UI: 542 case sw::FORMAT_R16I: 543 case sw::FORMAT_R16UI: 544 case sw::FORMAT_R32I: 545 case sw::FORMAT_R32UI: return GL_RED_INTEGER; 546 case sw::FORMAT_R8: 547 case sw::FORMAT_R8I_SNORM: 548 case sw::FORMAT_R16F: 549 case sw::FORMAT_R32F: return GL_RED; 550 default: 551 UNREACHABLE(colorbuffer->getInternalFormat()); 552 } 553 } 554 555 return GL_RGBA; 556 } 557 558 GLenum Framebuffer::getImplementationColorReadType() 559 { 560 Renderbuffer *colorbuffer = getReadColorbuffer(); 561 562 if(colorbuffer) 563 { 564 switch(colorbuffer->getInternalFormat()) 565 { 566 case sw::FORMAT_R16F: 567 case sw::FORMAT_G16R16F: 568 case sw::FORMAT_B16G16R16F: 569 case sw::FORMAT_A16B16G16R16F: 570 case sw::FORMAT_R32F: 571 case sw::FORMAT_G32R32F: 572 case sw::FORMAT_B32G32R32F: 573 case sw::FORMAT_X32B32G32R32F: 574 case sw::FORMAT_A32B32G32R32F: return GL_FLOAT; 575 case sw::FORMAT_R8I_SNORM: 576 case sw::FORMAT_G8R8I_SNORM: 577 case sw::FORMAT_X8B8G8R8I_SNORM: 578 case sw::FORMAT_A8B8G8R8I_SNORM:return GL_BYTE; 579 case sw::FORMAT_R8: 580 case sw::FORMAT_G8R8: 581 case sw::FORMAT_SRGB8_X8: 582 case sw::FORMAT_SRGB8_A8: 583 case sw::FORMAT_A8R8G8B8: 584 case sw::FORMAT_A8B8G8R8: 585 case sw::FORMAT_X8R8G8B8: 586 case sw::FORMAT_X8B8G8R8: return GL_UNSIGNED_BYTE; 587 case sw::FORMAT_R8I: 588 case sw::FORMAT_G8R8I: 589 case sw::FORMAT_X8B8G8R8I: 590 case sw::FORMAT_A8B8G8R8I: 591 case sw::FORMAT_R16I: 592 case sw::FORMAT_G16R16I: 593 case sw::FORMAT_X16B16G16R16I: 594 case sw::FORMAT_A16B16G16R16I: 595 case sw::FORMAT_R32I: 596 case sw::FORMAT_G32R32I: 597 case sw::FORMAT_X32B32G32R32I: 598 case sw::FORMAT_A32B32G32R32I: return GL_INT; 599 case sw::FORMAT_R8UI: 600 case sw::FORMAT_G8R8UI: 601 case sw::FORMAT_X8B8G8R8UI: 602 case sw::FORMAT_A8B8G8R8UI: 603 case sw::FORMAT_R16UI: 604 case sw::FORMAT_G16R16UI: 605 case sw::FORMAT_X16B16G16R16UI: 606 case sw::FORMAT_A16B16G16R16UI: 607 case sw::FORMAT_R32UI: 608 case sw::FORMAT_G32R32UI: 609 case sw::FORMAT_X32B32G32R32UI: 610 case sw::FORMAT_A32B32G32R32UI:return GL_UNSIGNED_INT; 611 case sw::FORMAT_A2B10G10R10: return GL_UNSIGNED_INT_10_10_10_2_OES; 612 case sw::FORMAT_A1R5G5B5: return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT; 613 case sw::FORMAT_R5G6B5: return GL_UNSIGNED_SHORT_5_6_5; 614 default: 615 UNREACHABLE(colorbuffer->getInternalFormat()); 616 } 617 } 618 619 return GL_UNSIGNED_BYTE; 620 } 621 622 GLenum Framebuffer::getDepthReadFormat() 623 { 624 Renderbuffer *depthbuffer = getDepthbuffer(); 625 626 if(depthbuffer) 627 { 628 // There is only one depth read format. 629 return GL_DEPTH_COMPONENT; 630 } 631 632 // If there is no depth buffer, GL_INVALID_OPERATION occurs. 633 return GL_NONE; 634 } 635 636 GLenum Framebuffer::getDepthReadType() 637 { 638 Renderbuffer *depthbuffer = getDepthbuffer(); 639 640 if(depthbuffer) 641 { 642 switch(depthbuffer->getInternalFormat()) 643 { 644 case sw::FORMAT_D16: return GL_UNSIGNED_SHORT; 645 case sw::FORMAT_D24S8: return GL_UNSIGNED_INT_24_8_OES; 646 case sw::FORMAT_D32: return GL_UNSIGNED_INT; 647 case sw::FORMAT_D32F: 648 case sw::FORMAT_D32F_COMPLEMENTARY: 649 case sw::FORMAT_D32F_LOCKABLE: 650 case sw::FORMAT_D32FS8_TEXTURE: 651 case sw::FORMAT_D32FS8_SHADOW: return GL_FLOAT; 652 default: 653 UNREACHABLE(depthbuffer->getInternalFormat()); 654 } 655 } 656 657 // If there is no depth buffer, GL_INVALID_OPERATION occurs. 658 return GL_NONE; 659 } 660 661 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) 662 { 663 GLenum defaultRenderbufferType = egl::getClientVersion() < 3 ? GL_RENDERBUFFER : GL_FRAMEBUFFER_DEFAULT; 664 mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer); 665 mColorbufferType[0] = defaultRenderbufferType; 666 667 for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++) 668 { 669 mColorbufferPointer[i] = nullptr; 670 mColorbufferType[i] = GL_NONE; 671 } 672 673 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil); 674 mDepthbufferPointer = depthStencilRenderbuffer; 675 mStencilbufferPointer = depthStencilRenderbuffer; 676 677 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? defaultRenderbufferType : GL_NONE; 678 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? defaultRenderbufferType : GL_NONE; 679 } 680 681 } 682