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 // Renderbuffer.cpp: the Renderbuffer class and its derived classes 16 // Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer 17 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. 18 19 #include "Renderbuffer.h" 20 21 #include "main.h" 22 #include "Texture.h" 23 #include "utilities.h" 24 25 namespace es2 26 { 27 RenderbufferInterface::RenderbufferInterface() 28 { 29 } 30 31 // The default case for classes inherited from RenderbufferInterface is not to 32 // need to do anything upon the reference count to the parent Renderbuffer incrementing 33 // or decrementing. 34 void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy) 35 { 36 } 37 38 void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) 39 { 40 } 41 42 GLuint RenderbufferInterface::getRedSize() const 43 { 44 return GetRedSize(getFormat()); 45 } 46 47 GLuint RenderbufferInterface::getGreenSize() const 48 { 49 return GetGreenSize(getFormat()); 50 } 51 52 GLuint RenderbufferInterface::getBlueSize() const 53 { 54 return GetBlueSize(getFormat()); 55 } 56 57 GLuint RenderbufferInterface::getAlphaSize() const 58 { 59 return GetAlphaSize(getFormat()); 60 } 61 62 GLuint RenderbufferInterface::getDepthSize() const 63 { 64 return GetDepthSize(getFormat()); 65 } 66 67 GLuint RenderbufferInterface::getStencilSize() const 68 { 69 return GetStencilSize(getFormat()); 70 } 71 72 ///// RenderbufferTexture2D Implementation //////// 73 74 RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level) 75 { 76 mTexture2D = texture; 77 } 78 79 RenderbufferTexture2D::~RenderbufferTexture2D() 80 { 81 mTexture2D = nullptr; 82 } 83 84 // Textures need to maintain their own reference count for references via 85 // Renderbuffers acting as proxies. Here, we notify the texture of a reference. 86 void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy) 87 { 88 mTexture2D->addProxyRef(proxy); 89 } 90 91 void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) 92 { 93 mTexture2D->releaseProxy(proxy); 94 } 95 96 // Increments refcount on image. 97 // caller must release() the returned image 98 egl::Image *RenderbufferTexture2D::getRenderTarget() 99 { 100 return mTexture2D->getRenderTarget(GL_TEXTURE_2D, mLevel); 101 } 102 103 // Increments refcount on image. 104 // caller must release() the returned image 105 egl::Image *RenderbufferTexture2D::createSharedImage() 106 { 107 return mTexture2D->createSharedImage(GL_TEXTURE_2D, mLevel); 108 } 109 110 bool RenderbufferTexture2D::isShared() const 111 { 112 return mTexture2D->isShared(GL_TEXTURE_2D, mLevel); 113 } 114 115 GLsizei RenderbufferTexture2D::getWidth() const 116 { 117 return mTexture2D->getWidth(GL_TEXTURE_2D, mLevel); 118 } 119 120 GLsizei RenderbufferTexture2D::getHeight() const 121 { 122 return mTexture2D->getHeight(GL_TEXTURE_2D, mLevel); 123 } 124 125 GLint RenderbufferTexture2D::getFormat() const 126 { 127 return mTexture2D->getFormat(GL_TEXTURE_2D, mLevel); 128 } 129 130 GLsizei RenderbufferTexture2D::getSamples() const 131 { 132 return 0; // Core OpenGL ES 3.0 does not support multisample textures. 133 } 134 135 ///// RenderbufferTexture2DRect Implementation //////// 136 137 RenderbufferTexture2DRect::RenderbufferTexture2DRect(Texture2DRect *texture) 138 { 139 mTexture2DRect = texture; 140 } 141 142 RenderbufferTexture2DRect::~RenderbufferTexture2DRect() 143 { 144 mTexture2DRect = NULL; 145 } 146 147 // Textures need to maintain their own reference count for references via 148 // Renderbuffers acting as proxies. Here, we notify the texture of a reference. 149 void RenderbufferTexture2DRect::addProxyRef(const Renderbuffer *proxy) 150 { 151 mTexture2DRect->addProxyRef(proxy); 152 } 153 154 void RenderbufferTexture2DRect::releaseProxy(const Renderbuffer *proxy) 155 { 156 mTexture2DRect->releaseProxy(proxy); 157 } 158 159 // Increments refcount on image. 160 // caller must release() the returned image 161 egl::Image *RenderbufferTexture2DRect::getRenderTarget() 162 { 163 return mTexture2DRect->getRenderTarget(GL_TEXTURE_RECTANGLE_ARB, 0); 164 } 165 166 // Increments refcount on image. 167 // caller must release() the returned image 168 egl::Image *RenderbufferTexture2DRect::createSharedImage() 169 { 170 return mTexture2DRect->createSharedImage(GL_TEXTURE_RECTANGLE_ARB, 0); 171 } 172 173 bool RenderbufferTexture2DRect::isShared() const 174 { 175 return mTexture2DRect->isShared(GL_TEXTURE_RECTANGLE_ARB, 0); 176 } 177 178 GLsizei RenderbufferTexture2DRect::getWidth() const 179 { 180 return mTexture2DRect->getWidth(GL_TEXTURE_RECTANGLE_ARB, 0); 181 } 182 183 GLsizei RenderbufferTexture2DRect::getHeight() const 184 { 185 return mTexture2DRect->getHeight(GL_TEXTURE_RECTANGLE_ARB, 0); 186 } 187 188 GLint RenderbufferTexture2DRect::getFormat() const 189 { 190 return mTexture2DRect->getFormat(GL_TEXTURE_RECTANGLE_ARB, 0); 191 } 192 193 GLsizei RenderbufferTexture2DRect::getSamples() const 194 { 195 return 0; // Core OpenGL ES 3.0 does not support multisample textures. 196 } 197 198 ///// RenderbufferTexture3D Implementation //////// 199 200 RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level) : mLevel(level) 201 { 202 mTexture3D = texture; 203 } 204 205 RenderbufferTexture3D::~RenderbufferTexture3D() 206 { 207 mTexture3D = NULL; 208 } 209 210 // Textures need to maintain their own reference count for references via 211 // Renderbuffers acting as proxies. Here, we notify the texture of a reference. 212 void RenderbufferTexture3D::addProxyRef(const Renderbuffer *proxy) 213 { 214 mTexture3D->addProxyRef(proxy); 215 } 216 217 void RenderbufferTexture3D::releaseProxy(const Renderbuffer *proxy) 218 { 219 mTexture3D->releaseProxy(proxy); 220 } 221 222 // Increments refcount on image. 223 // caller must release() the returned image 224 egl::Image *RenderbufferTexture3D::getRenderTarget() 225 { 226 return mTexture3D->getRenderTarget(mTexture3D->getTarget(), mLevel); 227 } 228 229 // Increments refcount on image. 230 // caller must release() the returned image 231 egl::Image *RenderbufferTexture3D::createSharedImage() 232 { 233 return mTexture3D->createSharedImage(mTexture3D->getTarget(), mLevel); 234 } 235 236 bool RenderbufferTexture3D::isShared() const 237 { 238 return mTexture3D->isShared(mTexture3D->getTarget(), mLevel); 239 } 240 241 GLsizei RenderbufferTexture3D::getWidth() const 242 { 243 return mTexture3D->getWidth(mTexture3D->getTarget(), mLevel); 244 } 245 246 GLsizei RenderbufferTexture3D::getHeight() const 247 { 248 return mTexture3D->getHeight(mTexture3D->getTarget(), mLevel); 249 } 250 251 GLsizei RenderbufferTexture3D::getDepth() const 252 { 253 return mTexture3D->getDepth(mTexture3D->getTarget(), mLevel); 254 } 255 256 GLint RenderbufferTexture3D::getFormat() const 257 { 258 return mTexture3D->getFormat(mTexture3D->getTarget(), mLevel); 259 } 260 261 GLsizei RenderbufferTexture3D::getSamples() const 262 { 263 return 0; // Core OpenGL ES 3.0 does not support multisample textures. 264 } 265 266 ///// RenderbufferTextureCubeMap Implementation //////// 267 268 RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level) : mTarget(target), mLevel(level) 269 { 270 mTextureCubeMap = texture; 271 } 272 273 RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap() 274 { 275 mTextureCubeMap = NULL; 276 } 277 278 // Textures need to maintain their own reference count for references via 279 // Renderbuffers acting as proxies. Here, we notify the texture of a reference. 280 void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy) 281 { 282 mTextureCubeMap->addProxyRef(proxy); 283 } 284 285 void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) 286 { 287 mTextureCubeMap->releaseProxy(proxy); 288 } 289 290 // Increments refcount on image. 291 // caller must release() the returned image 292 egl::Image *RenderbufferTextureCubeMap::getRenderTarget() 293 { 294 return mTextureCubeMap->getRenderTarget(mTarget, mLevel); 295 } 296 297 // Increments refcount on image. 298 // caller must release() the returned image 299 egl::Image *RenderbufferTextureCubeMap::createSharedImage() 300 { 301 return mTextureCubeMap->createSharedImage(mTarget, mLevel); 302 } 303 304 bool RenderbufferTextureCubeMap::isShared() const 305 { 306 return mTextureCubeMap->isShared(mTarget, mLevel); 307 } 308 309 GLsizei RenderbufferTextureCubeMap::getWidth() const 310 { 311 return mTextureCubeMap->getWidth(mTarget, mLevel); 312 } 313 314 GLsizei RenderbufferTextureCubeMap::getHeight() const 315 { 316 return mTextureCubeMap->getHeight(mTarget, mLevel); 317 } 318 319 GLint RenderbufferTextureCubeMap::getFormat() const 320 { 321 return mTextureCubeMap->getFormat(mTarget, mLevel); 322 } 323 324 GLsizei RenderbufferTextureCubeMap::getSamples() const 325 { 326 return 0; // Core OpenGL ES 3.0 does not support multisample textures. 327 } 328 329 ////// Renderbuffer Implementation ////// 330 331 Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name) 332 { 333 ASSERT(instance); 334 mInstance = instance; 335 } 336 337 Renderbuffer::~Renderbuffer() 338 { 339 delete mInstance; 340 } 341 342 // The RenderbufferInterface contained in this Renderbuffer may need to maintain 343 // its own reference count, so we pass it on here. 344 void Renderbuffer::addRef() 345 { 346 mInstance->addProxyRef(this); 347 348 Object::addRef(); 349 } 350 351 void Renderbuffer::release() 352 { 353 mInstance->releaseProxy(this); 354 355 Object::release(); 356 } 357 358 // Increments refcount on image. 359 // caller must Release() the returned image 360 egl::Image *Renderbuffer::getRenderTarget() 361 { 362 return mInstance->getRenderTarget(); 363 } 364 365 // Increments refcount on image. 366 // caller must Release() the returned image 367 egl::Image *Renderbuffer::createSharedImage() 368 { 369 return mInstance->createSharedImage(); 370 } 371 372 bool Renderbuffer::isShared() const 373 { 374 return mInstance->isShared(); 375 } 376 377 GLsizei Renderbuffer::getWidth() const 378 { 379 return mInstance->getWidth(); 380 } 381 382 GLsizei Renderbuffer::getHeight() const 383 { 384 return mInstance->getHeight(); 385 } 386 387 GLsizei Renderbuffer::getDepth() const 388 { 389 return mInstance->getDepth(); 390 } 391 392 GLint Renderbuffer::getLevel() const 393 { 394 return mInstance->getLevel(); 395 } 396 397 GLint Renderbuffer::getFormat() const 398 { 399 return mInstance->getFormat(); 400 } 401 402 GLuint Renderbuffer::getRedSize() const 403 { 404 return mInstance->getRedSize(); 405 } 406 407 GLuint Renderbuffer::getGreenSize() const 408 { 409 return mInstance->getGreenSize(); 410 } 411 412 GLuint Renderbuffer::getBlueSize() const 413 { 414 return mInstance->getBlueSize(); 415 } 416 417 GLuint Renderbuffer::getAlphaSize() const 418 { 419 return mInstance->getAlphaSize(); 420 } 421 422 GLuint Renderbuffer::getDepthSize() const 423 { 424 return mInstance->getDepthSize(); 425 } 426 427 GLuint Renderbuffer::getStencilSize() const 428 { 429 return mInstance->getStencilSize(); 430 } 431 432 GLsizei Renderbuffer::getSamples() const 433 { 434 return mInstance->getSamples(); 435 } 436 437 void Renderbuffer::setLevel(GLint level) 438 { 439 return mInstance->setLevel(level); 440 } 441 442 void Renderbuffer::setStorage(RenderbufferStorage *newStorage) 443 { 444 ASSERT(newStorage); 445 446 delete mInstance; 447 mInstance = newStorage; 448 } 449 450 RenderbufferStorage::RenderbufferStorage() 451 { 452 mWidth = 0; 453 mHeight = 0; 454 format = GL_NONE; 455 mSamples = 0; 456 } 457 458 RenderbufferStorage::~RenderbufferStorage() 459 { 460 } 461 462 GLsizei RenderbufferStorage::getWidth() const 463 { 464 return mWidth; 465 } 466 467 GLsizei RenderbufferStorage::getHeight() const 468 { 469 return mHeight; 470 } 471 472 GLint RenderbufferStorage::getFormat() const 473 { 474 return format; 475 } 476 477 GLsizei RenderbufferStorage::getSamples() const 478 { 479 return mSamples; 480 } 481 482 Colorbuffer::Colorbuffer(egl::Image *renderTarget) : mRenderTarget(renderTarget) 483 { 484 if(renderTarget) 485 { 486 renderTarget->addRef(); 487 488 mWidth = renderTarget->getWidth(); 489 mHeight = renderTarget->getHeight(); 490 format = renderTarget->getFormat(); 491 mSamples = renderTarget->getDepth() & ~1; 492 } 493 } 494 495 Colorbuffer::Colorbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mRenderTarget(nullptr) 496 { 497 int supportedSamples = Context::getSupportedMultisampleCount(samples); 498 499 if(width > 0 && height > 0) 500 { 501 if(height > sw::OUTLINE_RESOLUTION) 502 { 503 error(GL_OUT_OF_MEMORY); 504 return; 505 } 506 507 mRenderTarget = egl::Image::create(width, height, internalformat, supportedSamples, false); 508 509 if(!mRenderTarget) 510 { 511 error(GL_OUT_OF_MEMORY); 512 return; 513 } 514 } 515 516 mWidth = width; 517 mHeight = height; 518 format = internalformat; 519 mSamples = supportedSamples; 520 } 521 522 Colorbuffer::~Colorbuffer() 523 { 524 if(mRenderTarget) 525 { 526 mRenderTarget->release(); 527 } 528 } 529 530 // Increments refcount on image. 531 // caller must release() the returned image 532 egl::Image *Colorbuffer::getRenderTarget() 533 { 534 if(mRenderTarget) 535 { 536 mRenderTarget->addRef(); 537 } 538 539 return mRenderTarget; 540 } 541 542 // Increments refcount on image. 543 // caller must release() the returned image 544 egl::Image *Colorbuffer::createSharedImage() 545 { 546 if(mRenderTarget) 547 { 548 mRenderTarget->addRef(); 549 mRenderTarget->markShared(); 550 } 551 552 return mRenderTarget; 553 } 554 555 bool Colorbuffer::isShared() const 556 { 557 return mRenderTarget->isShared(); 558 } 559 560 DepthStencilbuffer::DepthStencilbuffer(egl::Image *depthStencil) : mDepthStencil(depthStencil) 561 { 562 if(depthStencil) 563 { 564 depthStencil->addRef(); 565 566 mWidth = depthStencil->getWidth(); 567 mHeight = depthStencil->getHeight(); 568 format = depthStencil->getFormat(); 569 mSamples = depthStencil->getDepth() & ~1; 570 } 571 } 572 573 DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mDepthStencil(nullptr) 574 { 575 int supportedSamples = Context::getSupportedMultisampleCount(samples); 576 577 if(width > 0 && height > 0) 578 { 579 if(height > sw::OUTLINE_RESOLUTION) 580 { 581 error(GL_OUT_OF_MEMORY); 582 return; 583 } 584 585 mDepthStencil = egl::Image::create(width, height, internalformat, supportedSamples, false); 586 587 if(!mDepthStencil) 588 { 589 error(GL_OUT_OF_MEMORY); 590 return; 591 } 592 } 593 594 mWidth = width; 595 mHeight = height; 596 format = internalformat; 597 mSamples = supportedSamples; 598 } 599 600 DepthStencilbuffer::~DepthStencilbuffer() 601 { 602 if(mDepthStencil) 603 { 604 mDepthStencil->release(); 605 } 606 } 607 608 // Increments refcount on image. 609 // caller must release() the returned image 610 egl::Image *DepthStencilbuffer::getRenderTarget() 611 { 612 if(mDepthStencil) 613 { 614 mDepthStencil->addRef(); 615 } 616 617 return mDepthStencil; 618 } 619 620 // Increments refcount on image. 621 // caller must release() the returned image 622 egl::Image *DepthStencilbuffer::createSharedImage() 623 { 624 if(mDepthStencil) 625 { 626 mDepthStencil->addRef(); 627 mDepthStencil->markShared(); 628 } 629 630 return mDepthStencil; 631 } 632 633 bool DepthStencilbuffer::isShared() const 634 { 635 return mDepthStencil->isShared(); 636 } 637 638 Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) 639 { 640 } 641 642 Depthbuffer::Depthbuffer(int width, int height, GLenum internalformat, GLsizei samples) : DepthStencilbuffer(width, height, internalformat, samples) 643 { 644 } 645 646 Depthbuffer::~Depthbuffer() 647 { 648 } 649 650 Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) 651 { 652 } 653 654 Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, GL_STENCIL_INDEX8, samples) 655 { 656 } 657 658 Stencilbuffer::~Stencilbuffer() 659 { 660 } 661 662 } 663