| // 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. |
| |
| #include "Renderbuffer.h" |
| |
| #include "main.h" |
| #include "Texture.h" |
| #include "utilities.h" |
| |
| namespace gl |
| { |
| 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 sw2es::GetRedSize(getInternalFormat()); |
| } |
| |
| GLuint RenderbufferInterface::getGreenSize() const |
| { |
| return sw2es::GetGreenSize(getInternalFormat()); |
| } |
| |
| GLuint RenderbufferInterface::getBlueSize() const |
| { |
| return sw2es::GetBlueSize(getInternalFormat()); |
| } |
| |
| GLuint RenderbufferInterface::getAlphaSize() const |
| { |
| return sw2es::GetAlphaSize(getInternalFormat()); |
| } |
| |
| GLuint RenderbufferInterface::getDepthSize() const |
| { |
| return sw2es::GetDepthSize(getInternalFormat()); |
| } |
| |
| GLuint RenderbufferInterface::getStencilSize() const |
| { |
| return sw2es::GetStencilSize(getInternalFormat()); |
| } |
| |
| ///// RenderbufferTexture2D Implementation //////// |
| |
| RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture) |
| { |
| 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 surface. |
| // caller must release() the returned surface |
| Image *RenderbufferTexture2D::getRenderTarget() |
| { |
| return mTexture2D->getRenderTarget(GL_TEXTURE_2D, 0); |
| } |
| |
| GLsizei RenderbufferTexture2D::getWidth() const |
| { |
| return mTexture2D->getWidth(GL_TEXTURE_2D, 0); |
| } |
| |
| GLsizei RenderbufferTexture2D::getHeight() const |
| { |
| return mTexture2D->getHeight(GL_TEXTURE_2D, 0); |
| } |
| |
| GLenum RenderbufferTexture2D::getFormat() const |
| { |
| return mTexture2D->getFormat(GL_TEXTURE_2D, 0); |
| } |
| |
| sw::Format RenderbufferTexture2D::getInternalFormat() const |
| { |
| return mTexture2D->getInternalFormat(GL_TEXTURE_2D, 0); |
| } |
| |
| GLsizei RenderbufferTexture2D::getSamples() const |
| { |
| return 0; |
| } |
| |
| ///// RenderbufferTextureCubeMap Implementation //////// |
| |
| RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target) |
| { |
| mTextureCubeMap = texture; |
| } |
| |
| RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap() |
| { |
| mTextureCubeMap = 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 RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy) |
| { |
| mTextureCubeMap->addProxyRef(proxy); |
| } |
| |
| void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) |
| { |
| mTextureCubeMap->releaseProxy(proxy); |
| } |
| |
| // Increments refcount on surface. |
| // caller must release() the returned surface |
| Image *RenderbufferTextureCubeMap::getRenderTarget() |
| { |
| return mTextureCubeMap->getRenderTarget(mTarget, 0); |
| } |
| |
| GLsizei RenderbufferTextureCubeMap::getWidth() const |
| { |
| return mTextureCubeMap->getWidth(mTarget, 0); |
| } |
| |
| GLsizei RenderbufferTextureCubeMap::getHeight() const |
| { |
| return mTextureCubeMap->getHeight(mTarget, 0); |
| } |
| |
| GLenum RenderbufferTextureCubeMap::getFormat() const |
| { |
| return mTextureCubeMap->getFormat(mTarget, 0); |
| } |
| |
| sw::Format RenderbufferTextureCubeMap::getInternalFormat() const |
| { |
| return mTextureCubeMap->getInternalFormat(mTarget, 0); |
| } |
| |
| GLsizei RenderbufferTextureCubeMap::getSamples() const |
| { |
| return 0; |
| } |
| |
| ////// 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 surface. |
| // caller must Release() the returned surface |
| Image *Renderbuffer::getRenderTarget() |
| { |
| return mInstance->getRenderTarget(); |
| } |
| |
| GLsizei Renderbuffer::getWidth() const |
| { |
| return mInstance->getWidth(); |
| } |
| |
| GLsizei Renderbuffer::getHeight() const |
| { |
| return mInstance->getHeight(); |
| } |
| |
| GLenum Renderbuffer::getFormat() const |
| { |
| return mInstance->getFormat(); |
| } |
| |
| sw::Format Renderbuffer::getInternalFormat() const |
| { |
| return mInstance->getInternalFormat(); |
| } |
| |
| 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::setStorage(RenderbufferStorage *newStorage) |
| { |
| ASSERT(newStorage); |
| |
| delete mInstance; |
| mInstance = newStorage; |
| } |
| |
| RenderbufferStorage::RenderbufferStorage() |
| { |
| mWidth = 0; |
| mHeight = 0; |
| format = GL_RGBA4; |
| internalFormat = sw::FORMAT_A8R8G8B8; |
| mSamples = 0; |
| } |
| |
| RenderbufferStorage::~RenderbufferStorage() |
| { |
| } |
| |
| // Increments refcount on surface. |
| // caller must Release() the returned surface |
| Image *RenderbufferStorage::getRenderTarget() |
| { |
| return nullptr; |
| } |
| |
| GLsizei RenderbufferStorage::getWidth() const |
| { |
| return mWidth; |
| } |
| |
| GLsizei RenderbufferStorage::getHeight() const |
| { |
| return mHeight; |
| } |
| |
| GLenum RenderbufferStorage::getFormat() const |
| { |
| return format; |
| } |
| |
| sw::Format RenderbufferStorage::getInternalFormat() const |
| { |
| return internalFormat; |
| } |
| |
| GLsizei RenderbufferStorage::getSamples() const |
| { |
| return mSamples; |
| } |
| |
| Colorbuffer::Colorbuffer(Image *renderTarget) : mRenderTarget(renderTarget) |
| { |
| if(renderTarget) |
| { |
| renderTarget->addRef(); |
| |
| mWidth = renderTarget->getWidth(); |
| mHeight = renderTarget->getHeight(); |
| internalFormat = renderTarget->getInternalFormat(); |
| format = sw2es::ConvertBackBufferFormat(internalFormat); |
| mSamples = renderTarget->getMultiSampleDepth() & ~1; |
| } |
| } |
| |
| Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(nullptr) |
| { |
| Device *device = getDevice(); |
| |
| sw::Format requestedFormat = es2sw::ConvertRenderbufferFormat(format); |
| int supportedSamples = Context::getSupportedMultisampleCount(samples); |
| |
| if(width > 0 && height > 0) |
| { |
| mRenderTarget = device->createRenderTarget(width, height, requestedFormat, supportedSamples, false); |
| |
| if(!mRenderTarget) |
| { |
| error(GL_OUT_OF_MEMORY); |
| return; |
| } |
| } |
| |
| mWidth = width; |
| mHeight = height; |
| this->format = format; |
| internalFormat = requestedFormat; |
| mSamples = supportedSamples; |
| } |
| |
| Colorbuffer::~Colorbuffer() |
| { |
| if(mRenderTarget) |
| { |
| mRenderTarget->release(); |
| } |
| } |
| |
| // Increments refcount on surface. |
| // caller must release() the returned surface |
| Image *Colorbuffer::getRenderTarget() |
| { |
| if(mRenderTarget) |
| { |
| mRenderTarget->addRef(); |
| } |
| |
| return mRenderTarget; |
| } |
| |
| DepthStencilbuffer::DepthStencilbuffer(Image *depthStencil) : mDepthStencil(depthStencil) |
| { |
| if(depthStencil) |
| { |
| depthStencil->addRef(); |
| |
| mWidth = depthStencil->getWidth(); |
| mHeight = depthStencil->getHeight(); |
| internalFormat = depthStencil->getInternalFormat(); |
| format = sw2es::ConvertDepthStencilFormat(internalFormat); |
| mSamples = depthStencil->getMultiSampleDepth() & ~1; |
| } |
| } |
| |
| DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) : mDepthStencil(nullptr) |
| { |
| Device *device = getDevice(); |
| |
| int supportedSamples = Context::getSupportedMultisampleCount(samples); |
| |
| if(width > 0 && height > 0) |
| { |
| mDepthStencil = device->createDepthStencilSurface(width, height, sw::FORMAT_D24S8, supportedSamples, false); |
| |
| if(!mDepthStencil) |
| { |
| error(GL_OUT_OF_MEMORY); |
| return; |
| } |
| } |
| |
| mWidth = width; |
| mHeight = height; |
| format = GL_DEPTH24_STENCIL8_EXT; |
| internalFormat = sw::FORMAT_D24S8; |
| mSamples = supportedSamples; |
| } |
| |
| DepthStencilbuffer::~DepthStencilbuffer() |
| { |
| if(mDepthStencil) |
| { |
| mDepthStencil->release(); |
| } |
| } |
| |
| // Increments refcount on surface. |
| // caller must release() the returned surface |
| Image *DepthStencilbuffer::getRenderTarget() |
| { |
| if(mDepthStencil) |
| { |
| mDepthStencil->addRef(); |
| } |
| |
| return mDepthStencil; |
| } |
| |
| Depthbuffer::Depthbuffer(Image *depthStencil) : DepthStencilbuffer(depthStencil) |
| { |
| if(depthStencil) |
| { |
| format = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function |
| // will expect one of the valid renderbuffer formats for use in |
| // glRenderbufferStorage |
| } |
| } |
| |
| Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) |
| { |
| if(mDepthStencil) |
| { |
| format = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function |
| // will expect one of the valid renderbuffer formats for use in |
| // glRenderbufferStorage |
| } |
| } |
| |
| Depthbuffer::~Depthbuffer() |
| { |
| } |
| |
| Stencilbuffer::Stencilbuffer(Image *depthStencil) : DepthStencilbuffer(depthStencil) |
| { |
| if(depthStencil) |
| { |
| format = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function |
| // will expect one of the valid renderbuffer formats for use in |
| // glRenderbufferStorage |
| } |
| } |
| |
| Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) |
| { |
| if(mDepthStencil) |
| { |
| format = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function |
| // will expect one of the valid renderbuffer formats for use in |
| // glRenderbufferStorage |
| } |
| } |
| |
| Stencilbuffer::~Stencilbuffer() |
| { |
| } |
| |
| } |