|  | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // Renderbuffer.cpp: the Renderbuffer class and its derived classes | 
|  | // Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer | 
|  | // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. | 
|  |  | 
|  | #include "Renderbuffer.h" | 
|  |  | 
|  | #include "main.h" | 
|  | #include "Texture.h" | 
|  | #include "utilities.h" | 
|  |  | 
|  | namespace es2 | 
|  | { | 
|  | RenderbufferInterface::RenderbufferInterface() | 
|  | { | 
|  | } | 
|  |  | 
|  | // The default case for classes inherited from RenderbufferInterface is not to | 
|  | // need to do anything upon the reference count to the parent Renderbuffer incrementing | 
|  | // or decrementing. | 
|  | void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy) | 
|  | { | 
|  | } | 
|  |  | 
|  | void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) | 
|  | { | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getRedSize() const | 
|  | { | 
|  | return GetRedSize(getFormat()); | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getGreenSize() const | 
|  | { | 
|  | return GetGreenSize(getFormat()); | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getBlueSize() const | 
|  | { | 
|  | return GetBlueSize(getFormat()); | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getAlphaSize() const | 
|  | { | 
|  | return GetAlphaSize(getFormat()); | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getDepthSize() const | 
|  | { | 
|  | return GetDepthSize(getFormat()); | 
|  | } | 
|  |  | 
|  | GLuint RenderbufferInterface::getStencilSize() const | 
|  | { | 
|  | return GetStencilSize(getFormat()); | 
|  | } | 
|  |  | 
|  | ///// RenderbufferTexture2D Implementation //////// | 
|  |  | 
|  | RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level) | 
|  | { | 
|  | mTexture2D = texture; | 
|  | } | 
|  |  | 
|  | RenderbufferTexture2D::~RenderbufferTexture2D() | 
|  | { | 
|  | mTexture2D = nullptr; | 
|  | } | 
|  |  | 
|  | // Textures need to maintain their own reference count for references via | 
|  | // Renderbuffers acting as proxies. Here, we notify the texture of a reference. | 
|  | void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture2D->addProxyRef(proxy); | 
|  | } | 
|  |  | 
|  | void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture2D->releaseProxy(proxy); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture2D::getRenderTarget() | 
|  | { | 
|  | return mTexture2D->getRenderTarget(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture2D::createSharedImage() | 
|  | { | 
|  | return mTexture2D->createSharedImage(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | bool RenderbufferTexture2D::isShared() const | 
|  | { | 
|  | return mTexture2D->isShared(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2D::getWidth() const | 
|  | { | 
|  | return mTexture2D->getWidth(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2D::getHeight() const | 
|  | { | 
|  | return mTexture2D->getHeight(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | GLint RenderbufferTexture2D::getFormat() const | 
|  | { | 
|  | return mTexture2D->getFormat(GL_TEXTURE_2D, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2D::getSamples() const | 
|  | { | 
|  | return 0;   // Core OpenGL ES 3.0 does not support multisample textures. | 
|  | } | 
|  |  | 
|  | ///// RenderbufferTexture2DRect Implementation //////// | 
|  |  | 
|  | RenderbufferTexture2DRect::RenderbufferTexture2DRect(Texture2DRect *texture) | 
|  | { | 
|  | mTexture2DRect = texture; | 
|  | } | 
|  |  | 
|  | RenderbufferTexture2DRect::~RenderbufferTexture2DRect() | 
|  | { | 
|  | mTexture2DRect = NULL; | 
|  | } | 
|  |  | 
|  | // Textures need to maintain their own reference count for references via | 
|  | // Renderbuffers acting as proxies. Here, we notify the texture of a reference. | 
|  | void RenderbufferTexture2DRect::addProxyRef(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture2DRect->addProxyRef(proxy); | 
|  | } | 
|  |  | 
|  | void RenderbufferTexture2DRect::releaseProxy(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture2DRect->releaseProxy(proxy); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture2DRect::getRenderTarget() | 
|  | { | 
|  | return mTexture2DRect->getRenderTarget(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture2DRect::createSharedImage() | 
|  | { | 
|  | return mTexture2DRect->createSharedImage(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | bool RenderbufferTexture2DRect::isShared() const | 
|  | { | 
|  | return mTexture2DRect->isShared(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2DRect::getWidth() const | 
|  | { | 
|  | return mTexture2DRect->getWidth(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2DRect::getHeight() const | 
|  | { | 
|  | return mTexture2DRect->getHeight(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | GLint RenderbufferTexture2DRect::getFormat() const | 
|  | { | 
|  | return mTexture2DRect->getFormat(GL_TEXTURE_RECTANGLE_ARB, 0); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture2DRect::getSamples() const | 
|  | { | 
|  | return 0;   // Core OpenGL ES 3.0 does not support multisample textures. | 
|  | } | 
|  |  | 
|  | ///// RenderbufferTexture3D Implementation //////// | 
|  |  | 
|  | RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level) : mLevel(level) | 
|  | { | 
|  | mTexture3D = texture; | 
|  | } | 
|  |  | 
|  | RenderbufferTexture3D::~RenderbufferTexture3D() | 
|  | { | 
|  | mTexture3D = NULL; | 
|  | } | 
|  |  | 
|  | // Textures need to maintain their own reference count for references via | 
|  | // Renderbuffers acting as proxies. Here, we notify the texture of a reference. | 
|  | void RenderbufferTexture3D::addProxyRef(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture3D->addProxyRef(proxy); | 
|  | } | 
|  |  | 
|  | void RenderbufferTexture3D::releaseProxy(const Renderbuffer *proxy) | 
|  | { | 
|  | mTexture3D->releaseProxy(proxy); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture3D::getRenderTarget() | 
|  | { | 
|  | return mTexture3D->getRenderTarget(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTexture3D::createSharedImage() | 
|  | { | 
|  | return mTexture3D->createSharedImage(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | bool RenderbufferTexture3D::isShared() const | 
|  | { | 
|  | return mTexture3D->isShared(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture3D::getWidth() const | 
|  | { | 
|  | return mTexture3D->getWidth(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture3D::getHeight() const | 
|  | { | 
|  | return mTexture3D->getHeight(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture3D::getDepth() const | 
|  | { | 
|  | return mTexture3D->getDepth(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | GLint RenderbufferTexture3D::getFormat() const | 
|  | { | 
|  | return mTexture3D->getFormat(mTexture3D->getTarget(), mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTexture3D::getSamples() const | 
|  | { | 
|  | return 0;   // Core OpenGL ES 3.0 does not support multisample textures. | 
|  | } | 
|  |  | 
|  | ///// RenderbufferTextureCubeMap Implementation //////// | 
|  |  | 
|  | RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level) : mTarget(target), mLevel(level) | 
|  | { | 
|  | mTextureCubeMap = texture; | 
|  | } | 
|  |  | 
|  | RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap() | 
|  | { | 
|  | mTextureCubeMap = NULL; | 
|  | } | 
|  |  | 
|  | // Textures need to maintain their own reference count for references via | 
|  | // Renderbuffers acting as proxies. Here, we notify the texture of a reference. | 
|  | void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy) | 
|  | { | 
|  | mTextureCubeMap->addProxyRef(proxy); | 
|  | } | 
|  |  | 
|  | void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) | 
|  | { | 
|  | mTextureCubeMap->releaseProxy(proxy); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTextureCubeMap::getRenderTarget() | 
|  | { | 
|  | return mTextureCubeMap->getRenderTarget(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *RenderbufferTextureCubeMap::createSharedImage() | 
|  | { | 
|  | return mTextureCubeMap->createSharedImage(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | bool RenderbufferTextureCubeMap::isShared() const | 
|  | { | 
|  | return mTextureCubeMap->isShared(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTextureCubeMap::getWidth() const | 
|  | { | 
|  | return mTextureCubeMap->getWidth(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTextureCubeMap::getHeight() const | 
|  | { | 
|  | return mTextureCubeMap->getHeight(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | GLint RenderbufferTextureCubeMap::getFormat() const | 
|  | { | 
|  | return mTextureCubeMap->getFormat(mTarget, mLevel); | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferTextureCubeMap::getSamples() const | 
|  | { | 
|  | return 0;   // Core OpenGL ES 3.0 does not support multisample textures. | 
|  | } | 
|  |  | 
|  | ////// Renderbuffer Implementation ////// | 
|  |  | 
|  | Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name) | 
|  | { | 
|  | ASSERT(instance); | 
|  | mInstance = instance; | 
|  | } | 
|  |  | 
|  | Renderbuffer::~Renderbuffer() | 
|  | { | 
|  | delete mInstance; | 
|  | } | 
|  |  | 
|  | // The RenderbufferInterface contained in this Renderbuffer may need to maintain | 
|  | // its own reference count, so we pass it on here. | 
|  | void Renderbuffer::addRef() | 
|  | { | 
|  | mInstance->addProxyRef(this); | 
|  |  | 
|  | Object::addRef(); | 
|  | } | 
|  |  | 
|  | void Renderbuffer::release() | 
|  | { | 
|  | mInstance->releaseProxy(this); | 
|  |  | 
|  | Object::release(); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must Release() the returned image | 
|  | egl::Image *Renderbuffer::getRenderTarget() | 
|  | { | 
|  | return mInstance->getRenderTarget(); | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must Release() the returned image | 
|  | egl::Image *Renderbuffer::createSharedImage() | 
|  | { | 
|  | return mInstance->createSharedImage(); | 
|  | } | 
|  |  | 
|  | bool Renderbuffer::isShared() const | 
|  | { | 
|  | return mInstance->isShared(); | 
|  | } | 
|  |  | 
|  | GLsizei Renderbuffer::getWidth() const | 
|  | { | 
|  | return mInstance->getWidth(); | 
|  | } | 
|  |  | 
|  | GLsizei Renderbuffer::getHeight() const | 
|  | { | 
|  | return mInstance->getHeight(); | 
|  | } | 
|  |  | 
|  | GLsizei Renderbuffer::getDepth() const | 
|  | { | 
|  | return mInstance->getDepth(); | 
|  | } | 
|  |  | 
|  | GLint Renderbuffer::getLevel() const | 
|  | { | 
|  | return mInstance->getLevel(); | 
|  | } | 
|  |  | 
|  | GLint Renderbuffer::getFormat() const | 
|  | { | 
|  | return mInstance->getFormat(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getRedSize() const | 
|  | { | 
|  | return mInstance->getRedSize(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getGreenSize() const | 
|  | { | 
|  | return mInstance->getGreenSize(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getBlueSize() const | 
|  | { | 
|  | return mInstance->getBlueSize(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getAlphaSize() const | 
|  | { | 
|  | return mInstance->getAlphaSize(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getDepthSize() const | 
|  | { | 
|  | return mInstance->getDepthSize(); | 
|  | } | 
|  |  | 
|  | GLuint Renderbuffer::getStencilSize() const | 
|  | { | 
|  | return mInstance->getStencilSize(); | 
|  | } | 
|  |  | 
|  | GLsizei Renderbuffer::getSamples() const | 
|  | { | 
|  | return mInstance->getSamples(); | 
|  | } | 
|  |  | 
|  | void Renderbuffer::setLevel(GLint level) | 
|  | { | 
|  | return mInstance->setLevel(level); | 
|  | } | 
|  |  | 
|  | void Renderbuffer::setStorage(RenderbufferStorage *newStorage) | 
|  | { | 
|  | ASSERT(newStorage); | 
|  |  | 
|  | delete mInstance; | 
|  | mInstance = newStorage; | 
|  | } | 
|  |  | 
|  | RenderbufferStorage::RenderbufferStorage() | 
|  | { | 
|  | mWidth = 0; | 
|  | mHeight = 0; | 
|  | format = GL_NONE; | 
|  | mSamples = 0; | 
|  | } | 
|  |  | 
|  | RenderbufferStorage::~RenderbufferStorage() | 
|  | { | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferStorage::getWidth() const | 
|  | { | 
|  | return mWidth; | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferStorage::getHeight() const | 
|  | { | 
|  | return mHeight; | 
|  | } | 
|  |  | 
|  | GLint RenderbufferStorage::getFormat() const | 
|  | { | 
|  | return format; | 
|  | } | 
|  |  | 
|  | GLsizei RenderbufferStorage::getSamples() const | 
|  | { | 
|  | return mSamples; | 
|  | } | 
|  |  | 
|  | Colorbuffer::Colorbuffer(egl::Image *renderTarget) : mRenderTarget(renderTarget) | 
|  | { | 
|  | if(renderTarget) | 
|  | { | 
|  | renderTarget->addRef(); | 
|  |  | 
|  | mWidth = renderTarget->getWidth(); | 
|  | mHeight = renderTarget->getHeight(); | 
|  | format = renderTarget->getFormat(); | 
|  | mSamples = renderTarget->getDepth() & ~1; | 
|  | } | 
|  | } | 
|  |  | 
|  | Colorbuffer::Colorbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mRenderTarget(nullptr) | 
|  | { | 
|  | int supportedSamples = Context::getSupportedMultisampleCount(samples); | 
|  |  | 
|  | if(width > 0 && height > 0) | 
|  | { | 
|  | if(height > sw::OUTLINE_RESOLUTION) | 
|  | { | 
|  | error(GL_OUT_OF_MEMORY); | 
|  | return; | 
|  | } | 
|  |  | 
|  | mRenderTarget = egl::Image::create(width, height, internalformat, supportedSamples, false); | 
|  |  | 
|  | if(!mRenderTarget) | 
|  | { | 
|  | error(GL_OUT_OF_MEMORY); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | mWidth = width; | 
|  | mHeight = height; | 
|  | format = internalformat; | 
|  | mSamples = supportedSamples; | 
|  | } | 
|  |  | 
|  | Colorbuffer::~Colorbuffer() | 
|  | { | 
|  | if(mRenderTarget) | 
|  | { | 
|  | mRenderTarget->release(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *Colorbuffer::getRenderTarget() | 
|  | { | 
|  | if(mRenderTarget) | 
|  | { | 
|  | mRenderTarget->addRef(); | 
|  | } | 
|  |  | 
|  | return mRenderTarget; | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *Colorbuffer::createSharedImage() | 
|  | { | 
|  | if(mRenderTarget) | 
|  | { | 
|  | mRenderTarget->addRef(); | 
|  | mRenderTarget->markShared(); | 
|  | } | 
|  |  | 
|  | return mRenderTarget; | 
|  | } | 
|  |  | 
|  | bool Colorbuffer::isShared() const | 
|  | { | 
|  | return mRenderTarget->isShared(); | 
|  | } | 
|  |  | 
|  | DepthStencilbuffer::DepthStencilbuffer(egl::Image *depthStencil) : mDepthStencil(depthStencil) | 
|  | { | 
|  | if(depthStencil) | 
|  | { | 
|  | depthStencil->addRef(); | 
|  |  | 
|  | mWidth = depthStencil->getWidth(); | 
|  | mHeight = depthStencil->getHeight(); | 
|  | format = depthStencil->getFormat(); | 
|  | mSamples = depthStencil->getDepth() & ~1; | 
|  | } | 
|  | } | 
|  |  | 
|  | DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mDepthStencil(nullptr) | 
|  | { | 
|  | int supportedSamples = Context::getSupportedMultisampleCount(samples); | 
|  |  | 
|  | if(width > 0 && height > 0) | 
|  | { | 
|  | if(height > sw::OUTLINE_RESOLUTION) | 
|  | { | 
|  | error(GL_OUT_OF_MEMORY); | 
|  | return; | 
|  | } | 
|  |  | 
|  | mDepthStencil = egl::Image::create(width, height, internalformat, supportedSamples, false); | 
|  |  | 
|  | if(!mDepthStencil) | 
|  | { | 
|  | error(GL_OUT_OF_MEMORY); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | mWidth = width; | 
|  | mHeight = height; | 
|  | format = internalformat; | 
|  | mSamples = supportedSamples; | 
|  | } | 
|  |  | 
|  | DepthStencilbuffer::~DepthStencilbuffer() | 
|  | { | 
|  | if(mDepthStencil) | 
|  | { | 
|  | mDepthStencil->release(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *DepthStencilbuffer::getRenderTarget() | 
|  | { | 
|  | if(mDepthStencil) | 
|  | { | 
|  | mDepthStencil->addRef(); | 
|  | } | 
|  |  | 
|  | return mDepthStencil; | 
|  | } | 
|  |  | 
|  | // Increments refcount on image. | 
|  | // caller must release() the returned image | 
|  | egl::Image *DepthStencilbuffer::createSharedImage() | 
|  | { | 
|  | if(mDepthStencil) | 
|  | { | 
|  | mDepthStencil->addRef(); | 
|  | mDepthStencil->markShared(); | 
|  | } | 
|  |  | 
|  | return mDepthStencil; | 
|  | } | 
|  |  | 
|  | bool DepthStencilbuffer::isShared() const | 
|  | { | 
|  | return mDepthStencil->isShared(); | 
|  | } | 
|  |  | 
|  | Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) | 
|  | { | 
|  | } | 
|  |  | 
|  | Depthbuffer::Depthbuffer(int width, int height, GLenum internalformat, GLsizei samples) : DepthStencilbuffer(width, height, internalformat, samples) | 
|  | { | 
|  | } | 
|  |  | 
|  | Depthbuffer::~Depthbuffer() | 
|  | { | 
|  | } | 
|  |  | 
|  | Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) | 
|  | { | 
|  | } | 
|  |  | 
|  | Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, GL_STENCIL_INDEX8, samples) | 
|  | { | 
|  | } | 
|  |  | 
|  | Stencilbuffer::~Stencilbuffer() | 
|  | { | 
|  | } | 
|  |  | 
|  | } |