// // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // Renderbuffer.cpp: the gl::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 "libGLESv2/Renderbuffer.h" #include "libGLESv2/main.h" #include "libGLESv2/Texture.h" #include "libGLESv2/utilities.h" namespace gl { unsigned int RenderbufferStorage::mCurrentSerial = 1; Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id) { ASSERT(storage != NULL); mStorage = storage; } Renderbuffer::~Renderbuffer() { delete mStorage; } bool Renderbuffer::isColorbuffer() const { return mStorage->isColorbuffer(); } bool Renderbuffer::isDepthbuffer() const { return mStorage->isDepthbuffer(); } bool Renderbuffer::isStencilbuffer() const { return mStorage->isStencilbuffer(); } IDirect3DSurface9 *Renderbuffer::getRenderTarget() { return mStorage->getRenderTarget(); } IDirect3DSurface9 *Renderbuffer::getDepthStencil() { return mStorage->getDepthStencil(); } int Renderbuffer::getWidth() const { return mStorage->getWidth(); } int Renderbuffer::getHeight() const { return mStorage->getHeight(); } GLenum Renderbuffer::getFormat() const { return mStorage->getFormat(); } D3DFORMAT Renderbuffer::getD3DFormat() const { return mStorage->getD3DFormat(); } unsigned int Renderbuffer::getSerial() const { return mStorage->getSerial(); } void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage != NULL); delete mStorage; mStorage = newStorage; } RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) { mWidth = 0; mHeight = 0; mFormat = GL_RGBA4; mD3DFormat = D3DFMT_A8R8G8B8; mSamples = 0; } RenderbufferStorage::~RenderbufferStorage() { } bool RenderbufferStorage::isColorbuffer() const { return false; } bool RenderbufferStorage::isDepthbuffer() const { return false; } bool RenderbufferStorage::isStencilbuffer() const { return false; } IDirect3DSurface9 *RenderbufferStorage::getRenderTarget() { return NULL; } IDirect3DSurface9 *RenderbufferStorage::getDepthStencil() { return NULL; } int RenderbufferStorage::getWidth() const { return mWidth; } int RenderbufferStorage::getHeight() const { return mHeight; } void RenderbufferStorage::setSize(int width, int height) { mWidth = width; mHeight = height; } GLenum RenderbufferStorage::getFormat() const { return mFormat; } bool RenderbufferStorage::isFloatingPoint() const { return false; // no floating point renderbuffers } D3DFORMAT RenderbufferStorage::getD3DFormat() const { return mD3DFormat; } GLsizei RenderbufferStorage::getSamples() const { return mSamples; } unsigned int RenderbufferStorage::getSerial() const { return mSerial; } unsigned int RenderbufferStorage::issueSerial() { return mCurrentSerial++; } Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget) { if (renderTarget) { renderTarget->AddRef(); D3DSURFACE_DESC description; renderTarget->GetDesc(&description); setSize(description.Width, description.Height); mFormat = dx2es::ConvertBackBufferFormat(description.Format); mD3DFormat = description.Format; mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType); } } Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL) { setSize(texture->getWidth(), texture->getHeight()); mD3DFormat = texture->getD3DFormat(); mSamples = 0; } Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) { IDirect3DDevice9 *device = getDevice(); mRenderTarget = NULL; D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format); int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples); if (supportedSamples == -1) { error(GL_OUT_OF_MEMORY); return; } if (width > 0 && height > 0) { HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL); if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) { error(GL_OUT_OF_MEMORY); return; } ASSERT(SUCCEEDED(result)); } if (mRenderTarget) { setSize(width, height); mFormat = format; mD3DFormat = requestedFormat; mSamples = supportedSamples; } } Colorbuffer::~Colorbuffer() { if (mRenderTarget) { mRenderTarget->Release(); } } bool Colorbuffer::isColorbuffer() const { return true; } GLuint Colorbuffer::getRedSize() const { if (mRenderTarget) { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); return es2dx::GetRedSize(description.Format); } return 0; } GLuint Colorbuffer::getGreenSize() const { if (mRenderTarget) { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); return es2dx::GetGreenSize(description.Format); } return 0; } GLuint Colorbuffer::getBlueSize() const { if (mRenderTarget) { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); return es2dx::GetBlueSize(description.Format); } return 0; } GLuint Colorbuffer::getAlphaSize() const { if (mRenderTarget) { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); return es2dx::GetAlphaSize(description.Format); } return 0; } IDirect3DSurface9 *Colorbuffer::getRenderTarget() { return mRenderTarget; } DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil) { if (depthStencil) { depthStencil->AddRef(); D3DSURFACE_DESC description; depthStencil->GetDesc(&description); setSize(description.Width, description.Height); mFormat = dx2es::ConvertDepthStencilFormat(description.Format); mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType); mD3DFormat = description.Format; } } DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) { IDirect3DDevice9 *device = getDevice(); mDepthStencil = NULL; int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples); if (supportedSamples == -1) { error(GL_OUT_OF_MEMORY); return; } HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mDepthStencil, 0); if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) { error(GL_OUT_OF_MEMORY); return; } ASSERT(SUCCEEDED(result)); if (mDepthStencil) { setSize(width, height); mFormat = GL_DEPTH24_STENCIL8_OES; mD3DFormat = D3DFMT_D24S8; mSamples = supportedSamples; } } DepthStencilbuffer::~DepthStencilbuffer() { if (mDepthStencil) { mDepthStencil->Release(); } } bool DepthStencilbuffer::isDepthbuffer() const { return true; } bool DepthStencilbuffer::isStencilbuffer() const { return true; } GLuint DepthStencilbuffer::getDepthSize() const { if (mDepthStencil) { D3DSURFACE_DESC description; mDepthStencil->GetDesc(&description); return es2dx::GetDepthSize(description.Format); } return 0; } GLuint DepthStencilbuffer::getStencilSize() const { if (mDepthStencil) { D3DSURFACE_DESC description; mDepthStencil->GetDesc(&description); return es2dx::GetStencilSize(description.Format); } return 0; } IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil() { return mDepthStencil; } Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) { if (depthStencil) { mFormat = 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 (getDepthStencil()) { mFormat = 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() { } bool Depthbuffer::isDepthbuffer() const { return true; } bool Depthbuffer::isStencilbuffer() const { return false; } Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) { if (depthStencil) { mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function // will expect one of the valid renderbuffer formats for use in // glRenderbufferStorage } else { mFormat = GL_RGBA4; //default format } } Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) { if (getDepthStencil()) { mFormat = 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() { } bool Stencilbuffer::isDepthbuffer() const { return false; } bool Stencilbuffer::isStencilbuffer() const { return true; } }