Added LLRenderTarget::resize and did a little cleanup.

This commit is contained in:
Shyotl
2012-07-26 03:05:22 -05:00
parent 726d8248c5
commit 701230b49c
3 changed files with 166 additions and 81 deletions

View File

@@ -76,6 +76,42 @@ LLRenderTarget::~LLRenderTarget()
release();
}
void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)
{
//for accounting, get the number of pixels added/subtracted
S32 pix_diff = (resx*resy)-(mResX*mResY);
mResX = resx;
mResY = resy;
for (U32 i = 0; i < mTex.size(); ++i)
{ //resize color attachments
gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
sBytesAllocated += pix_diff*4;
}
if (mDepth)
{ //resize depth attachment
if (mStencil)
{
//use render buffers where stencil buffers are in play
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
else
{
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
}
sBytesAllocated += pix_diff*4;
}
if(mSampleBuffer)
mSampleBuffer->resize(resx,resy);
}
void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
{
@@ -241,14 +277,14 @@ bool LLRenderTarget::allocateDepth()
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
sBytesAllocated += mResX*mResY*4;
if (glGetError() != GL_NO_ERROR)
{
llwarns << "Unable to allocate depth buffer for render target." << llendl;
return false;
}
sBytesAllocated += mResX*mResY*4;
return true;
}
@@ -309,7 +345,11 @@ void LLRenderTarget::release()
else
{
//Release before delete.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
if(mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
}
LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);
stop_glerror();
}
@@ -341,9 +381,6 @@ void LLRenderTarget::release()
if (mTex.size() > 0)
{
//Release before delete.
for (U32 i = 0; i < mTex.size(); ++i)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, LLTexUnit::getInternalType(mUsage), 0, 0);
sBytesAllocated -= mResX*mResY*4*mTex.size();
LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true);
mTex.clear();
@@ -472,7 +509,7 @@ void LLRenderTarget::flush(bool fetch_depth)
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
if (mSampleBuffer)
{
LLGLEnable multisample(GL_MULTISAMPLE);
@@ -482,7 +519,7 @@ void LLRenderTarget::flush(bool fetch_depth)
check_framebuffer_status();
glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
check_framebuffer_status();
stop_glerror();
if(gGLManager.mIsATI)
{
@@ -532,7 +569,6 @@ void LLRenderTarget::flush(bool fetch_depth)
}
}
}
void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
@@ -642,7 +678,8 @@ void LLRenderTarget::getViewport(S32* viewport)
// LLMultisampleBuffer implementation
//==================================================
LLMultisampleBuffer::LLMultisampleBuffer() :
mSamples(0)
mSamples(0),
mColorFormat(0)
{
}
@@ -743,6 +780,7 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
mUsage = usage;
mUseDepth = depth;
mStencil = stencil;
mColorFormat = color_fmt;
{
@@ -780,6 +818,42 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
return addColorAttachment(color_fmt);
}
void LLMultisampleBuffer::resize(U32 resx, U32 resy)
{
//for accounting, get the number of pixels added/subtracted
S32 pix_diff = (resx*resy)-(mResX*mResY);
mResX = resx;
mResY = resy;
for (U32 i = 0; i < mTex.size(); ++i)
{ //resize color attachments
glBindRenderbuffer(GL_RENDERBUFFER, mTex[i]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, mColorFormat, mResX, mResY);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
sBytesAllocated += pix_diff*4;
}
if (mDepth)
{ //resize depth attachment
if (mStencil)
{
//use render buffers where stencil buffers are in play
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
else
{
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
sBytesAllocated += pix_diff*4;
}
}
bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
{
if (color_fmt == 0)
@@ -829,12 +903,13 @@ bool LLMultisampleBuffer::allocateDepth()
clear_glerror();
if (mStencil)
{
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
}
else
{
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY);
}
if (glGetError() != GL_NO_ERROR)
{
llwarns << "Unable to allocate depth buffer for multisample render target." << llendl;
@@ -845,4 +920,3 @@ bool LLMultisampleBuffer::allocateDepth()
return true;
}

View File

@@ -80,6 +80,12 @@ public:
//multiple calls will release previously allocated resources
bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE);
//resize existing attachments to use new resolution and color format
// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
// DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
void resize(U32 resx, U32 resy, U32 color_fmt);
//provide this render target with a multisample resource.
void setSampleBuffer(LLMultisampleBuffer* buffer);
@@ -168,6 +174,7 @@ protected:
class LLMultisampleBuffer : public LLRenderTarget
{
U32 mSamples;
U32 mColorFormat;
public:
LLMultisampleBuffer();
virtual ~LLMultisampleBuffer();
@@ -180,6 +187,7 @@ public:
bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples);
virtual bool addColorAttachment(U32 color_fmt);
virtual bool allocateDepth();
void resize(U32 resx, U32 resy);
};
#endif //!LL_MESA_HEADLESS

View File

@@ -693,9 +693,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
//allocate deferred rendering color buffers
static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true);
const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later
if (!mDeferredScreen.allocate(resX, resY, format, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!addDeferredAttachments(mDeferredScreen)) return false;
@@ -9409,81 +9407,86 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
stateSort(*LLViewerCamera::getInstance(), result);
const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
LLCamera camera = *viewer_camera;
camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
LLVector2 tdim;
U32 resY = 0;
U32 resX = 0;
LLVector4a half_height;
half_height.setSub(ext[1], ext[0]);
half_height.mul(0.5f);
LLVector4a left;
left.load3(camera.getLeftAxis().mV);
left.mul(left);
left.normalize3fast();
LLVector4a up;
up.load3(camera.getUpAxis().mV);
up.mul(up);
up.normalize3fast();
tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
F32 distance = (pos-camera.getOrigin()).length();
F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
F32 aspect = tdim.mV[0]/tdim.mV[1];
glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
glh_set_current_projection(persp);
gGL.loadMatrix(persp.m);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
glh::matrix4f mat;
camera.getOpenGLTransform(mat.m);
mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
gGL.loadMatrix(mat.m);
glh_set_current_modelview(mat);
glClearColor(0.0f,0.0f,0.0f,0.0f);
gGL.setColorMask(true, true);
// get the number of pixels per angle
F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
resY != avatar->mImpostor.getHeight())
{
static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true); //TO-DO: Profile 16bit format later
avatar->mImpostor.allocate(resX,resY, (!LLPipeline::sRenderDeferred || shadow_precision) ? GL_RGBA : GL_RGBA16F_ARB,TRUE,FALSE);
const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
if (LLPipeline::sRenderDeferred)
camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
LLVector4a half_height;
half_height.setSub(ext[1], ext[0]);
half_height.mul(0.5f);
LLVector4a left;
left.load3(camera.getLeftAxis().mV);
left.mul(left);
left.normalize3fast();
LLVector4a up;
up.load3(camera.getUpAxis().mV);
up.mul(up);
up.normalize3fast();
tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
F32 distance = (pos-camera.getOrigin()).length();
F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
F32 aspect = tdim.mV[0]/tdim.mV[1];
glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
glh_set_current_projection(persp);
gGL.loadMatrix(persp.m);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
glh::matrix4f mat;
camera.getOpenGLTransform(mat.m);
mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
gGL.loadMatrix(mat.m);
glh_set_current_modelview(mat);
glClearColor(0.0f,0.0f,0.0f,0.0f);
gGL.setColorMask(true, true);
// get the number of pixels per angle
F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
if (!avatar->mImpostor.isComplete())
{
addDeferredAttachments(avatar->mImpostor);
avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
if (LLPipeline::sRenderDeferred)
{
addDeferredAttachments(avatar->mImpostor);
}
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
else if(resX != avatar->mImpostor.getWidth() ||
resY != avatar->mImpostor.getHeight())
{
avatar->mImpostor.resize(resX,resY,GL_RGBA);
}
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
avatar->mImpostor.bindTarget();
}
avatar->mImpostor.bindTarget();
if (LLPipeline::sRenderDeferred)
{
avatar->mImpostor.clear();