summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llcubemap.cpp12
-rw-r--r--indra/llrender/llfontgl.cpp3
-rw-r--r--indra/llrender/llgl.cpp50
-rw-r--r--indra/llrender/llgl.h2
-rw-r--r--indra/llrender/llglheaders.h39
-rw-r--r--indra/llrender/llglslshader.cpp7
-rw-r--r--indra/llrender/llglslshader.h7
-rw-r--r--indra/llrender/llimagegl.cpp12
-rw-r--r--indra/llrender/llrender.cpp29
-rw-r--r--indra/llrender/llrender.h2
-rw-r--r--indra/llrender/llrendertarget.cpp47
-rw-r--r--indra/llrender/llrendertarget.h14
-rw-r--r--indra/llrender/llvertexbuffer.cpp219
-rw-r--r--indra/llrender/llvertexbuffer.h12
14 files changed, 378 insertions, 77 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index fb22d7f1f5..1b10354c22 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -259,7 +259,7 @@ void LLCubeMap::setMatrix(S32 stage)
if (mMatrixStage < 0) return;
- if (stage > 0)
+ //if (stage > 0)
{
gGL.getTexUnit(stage)->activate();
}
@@ -278,17 +278,17 @@ void LLCubeMap::setMatrix(S32 stage)
glLoadMatrixf((F32 *)trans.mMatrix);
glMatrixMode(GL_MODELVIEW);
- if (stage > 0)
+ /*if (stage > 0)
{
gGL.getTexUnit(0)->activate();
- }
+ }*/
}
void LLCubeMap::restoreMatrix()
{
if (mMatrixStage < 0) return;
- if (mMatrixStage > 0)
+ //if (mMatrixStage > 0)
{
gGL.getTexUnit(mMatrixStage)->activate();
}
@@ -296,10 +296,10 @@ void LLCubeMap::restoreMatrix()
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
- if (mMatrixStage > 0)
+ /*if (mMatrixStage > 0)
{
gGL.getTexUnit(0)->activate();
- }
+ }*/
}
void LLCubeMap::setReflection (void)
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 180ae4dfa6..607473d416 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -189,6 +189,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
+ // Depth translation, so that floating text appears 'inworld'
+ // and is correclty occluded.
+ gGL.translatef(0.f,0.f,sCurOrigin.mZ);
S32 chars_drawn = 0;
S32 i;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c224ab0e9b..39f59c0bd8 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -128,9 +128,21 @@ PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
// GL_ARB_map_buffer_range
-PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
-
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL;
+
+// GL_ARB_sync
+PFNGLFENCESYNCPROC glFenceSync = NULL;
+PFNGLISSYNCPROC glIsSync = NULL;
+PFNGLDELETESYNCPROC glDeleteSync = NULL;
+PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL;
+PFNGLWAITSYNCPROC glWaitSync = NULL;
+PFNGLGETINTEGER64VPROC glGetInteger64v = NULL;
+PFNGLGETSYNCIVPROC glGetSynciv = NULL;
+
+// GL_APPLE_flush_buffer_range
+PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL;
// vertex object prototypes
PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
@@ -334,9 +346,10 @@ LLGLManager::LLGLManager() :
mHasFramebufferObject(FALSE),
mMaxSamples(0),
mHasBlendFuncSeparate(FALSE),
-
+ mHasSync(FALSE),
mHasVertexBufferObject(FALSE),
mHasMapBufferRange(FALSE),
+ mHasFlushBufferRange(FALSE),
mHasPBuffer(FALSE),
mHasShaderObjects(FALSE),
mHasVertexShader(FALSE),
@@ -774,7 +787,9 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
+ mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
+ mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
#ifdef GL_ARB_framebuffer_object
@@ -969,6 +984,16 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
+ if (mHasSync)
+ {
+ glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
+ glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync");
+ glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
+ glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
+ glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
+ glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
+ glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
+ }
if (mHasMapBufferRange)
{
glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
@@ -1354,6 +1379,8 @@ void LLGLState::checkStates(const std::string& msg)
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
+ stop_glerror();
+
BOOL error = FALSE;
if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
@@ -1374,7 +1401,9 @@ void LLGLState::checkStates(const std::string& msg)
{
LLGLenum state = iter->first;
LLGLboolean cur_state = iter->second;
+ stop_glerror();
LLGLboolean gl_state = glIsEnabled(state);
+ stop_glerror();
if(cur_state != gl_state)
{
dumpStates();
@@ -1399,11 +1428,11 @@ void LLGLState::checkStates(const std::string& msg)
void LLGLState::checkTextureChannels(const std::string& msg)
{
+#if 0
if (!gDebugGL)
{
return;
}
-
stop_glerror();
GLint activeTexture;
@@ -1569,6 +1598,7 @@ void LLGLState::checkTextureChannels(const std::string& msg)
LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
}
}
+#endif
}
void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
@@ -1685,7 +1715,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
}
}
- if (glIsEnabled(GL_TEXTURE_2D))
+ /*if (glIsEnabled(GL_TEXTURE_2D))
{
if (!(data_mask & 0x0008))
{
@@ -1708,7 +1738,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl;
}
}
- }
+ }*/
glClientActiveTextureARB(GL_TEXTURE0_ARB);
gGL.getTexUnit(0)->activate();
@@ -2110,8 +2140,7 @@ void LLGLNamePool::release(GLuint name)
void LLGLNamePool::upkeepPools()
{
LLMemType mt(LLMemType::MTYPE_UPKEEP_POOLS);
- tracker_t::LLInstanceTrackerScopedGuard guard;
- for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter)
+ for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter)
{
LLGLNamePool & pool = *iter;
pool.upkeep();
@@ -2121,8 +2150,7 @@ void LLGLNamePool::upkeepPools()
//static
void LLGLNamePool::cleanupPools()
{
- tracker_t::LLInstanceTrackerScopedGuard guard;
- for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter)
+ for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter)
{
LLGLNamePool & pool = *iter;
pool.cleanup();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index d1bee00161..d736133f3f 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -88,7 +88,9 @@ public:
// ARB Extensions
BOOL mHasVertexBufferObject;
+ BOOL mHasSync;
BOOL mHasMapBufferRange;
+ BOOL mHasFlushBufferRange;
BOOL mHasPBuffer;
BOOL mHasShaderObjects;
BOOL mHasVertexShader;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index f35f329f00..851a75629e 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -68,6 +68,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC glFenceSync;
+extern PFNGLISSYNCPROC glIsSync;
+extern PFNGLDELETESYNCPROC glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
+extern PFNGLWAITSYNCPROC glWaitSync;
+extern PFNGLGETINTEGER64VPROC glGetInteger64v;
+extern PFNGLGETSYNCIVPROC glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
@@ -310,6 +323,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC glFenceSync;
+extern PFNGLISSYNCPROC glIsSync;
+extern PFNGLDELETESYNCPROC glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
+extern PFNGLWAITSYNCPROC glWaitSync;
+extern PFNGLGETINTEGER64VPROC glGetInteger64v;
+extern PFNGLGETSYNCIVPROC glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
@@ -519,6 +545,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC glFenceSync;
+extern PFNGLISSYNCPROC glIsSync;
+extern PFNGLDELETESYNCPROC glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
+extern PFNGLWAITSYNCPROC glWaitSync;
+extern PFNGLGETINTEGER64VPROC glGetInteger64v;
+extern PFNGLGETSYNCIVPROC glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index ad2c662dfc..80c93bb0d2 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -49,6 +49,11 @@ using std::make_pair;
using std::string;
GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+bool LLGLSLShader::sNoFixedFunction = false;
+
+//UI shader -- declared here so llui_libtest will link properly
+LLGLSLShader gUIProgram;
+LLGLSLShader gSolidColorProgram;
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
@@ -376,6 +381,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
void LLGLSLShader::bind()
{
+ gGL.flush();
if (gGLManager.mHasShaderObjects)
{
glUseProgramObjectARB(mProgramObject);
@@ -390,6 +396,7 @@ void LLGLSLShader::bind()
void LLGLSLShader::unbind()
{
+ gGL.flush();
if (gGLManager.mHasShaderObjects)
{
stop_glerror();
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 4922eb6d67..621e0b82ee 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -67,6 +67,7 @@ public:
LLGLSLShader();
static GLhandleARB sCurBoundShader;
+ static bool sNoFixedFunction;
void unload();
BOOL createShader(std::vector<std::string> * attributes,
@@ -141,4 +142,10 @@ public:
std::string mName;
};
+//UI shader (declared here so llui_libtest will link properly)
+extern LLGLSLShader gUIProgram;
+//output vec4(color.rgb,color.a*tex0[tc0].a)
+extern LLGLSLShader gSolidColorProgram;
+
+
#endif
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 60a5962234..9ca3a23d52 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1414,6 +1414,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
void LLImageGL::deleteDeadTextures()
{
+ bool reset = false;
+
while (!sDeadTextureList.empty())
{
GLuint tex = sDeadTextureList.front();
@@ -1426,12 +1428,22 @@ void LLImageGL::deleteDeadTextures()
{
tex_unit->unbind(tex_unit->getCurrType());
stop_glerror();
+
+ if (i > 0)
+ {
+ reset = true;
+ }
}
}
glDeleteTextures(1, &tex);
stop_glerror();
}
+
+ if (reset)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
}
void LLImageGL::destroyGLTexture()
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 1d82dda30f..70df1dd1d1 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -46,6 +46,7 @@ S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 0;
+U32 LLTexUnit::sWhiteTexture = 0;
static const U32 LL_NUM_TEXTURE_LAYERS = 32;
static const U32 LL_NUM_LIGHT_UNITS = 8;
@@ -126,7 +127,8 @@ void LLTexUnit::refreshState(void)
// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
//
- bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+ bool enableDisable = !LLGLSLShader::sNoFixedFunction &&
+ (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
if (mCurrTexType != TT_NONE)
{
@@ -184,7 +186,8 @@ void LLTexUnit::enable(eTextureType type)
mCurrTexType = type;
gGL.flush();
- if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ if (!LLGLSLShader::sNoFixedFunction &&
+ type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
mIndex < gGLManager.mNumTextureUnits)
{
glEnable(sGLTextureType[type]);
@@ -201,7 +204,8 @@ void LLTexUnit::disable(void)
activate();
unbind(mCurrTexType);
gGL.flush();
- if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ if (!LLGLSLShader::sNoFixedFunction &&
+ mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
mIndex < gGLManager.mNumTextureUnits)
{
glDisable(sGLTextureType[mCurrTexType]);
@@ -403,7 +407,14 @@ void LLTexUnit::unbind(eTextureType type)
activate();
mCurrTexture = 0;
- glBindTexture(sGLTextureType[type], 0);
+ if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
+ {
+ glBindTexture(sGLTextureType[type], sWhiteTexture);
+ }
+ else
+ {
+ glBindTexture(sGLTextureType[type], 0);
+ }
stop_glerror();
}
}
@@ -474,6 +485,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
void LLTexUnit::setTextureBlendType(eTextureBlendType type)
{
+ if (LLGLSLShader::sNoFixedFunction)
+ { //texture blend type means nothing when using shaders
+ return;
+ }
+
if (mIndex < 0) return;
// Do nothing if it's already correctly set.
@@ -594,6 +610,11 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha)
{
+ if (LLGLSLShader::sNoFixedFunction)
+ { //register combiners do nothing when not using fixed function
+ return;
+ }
+
if (mIndex < 0) return;
activate();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 41e7b35341..9eedebe2ce 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -52,6 +52,8 @@ class LLTexUnit
{
friend class LLRender;
public:
+ static U32 sWhiteTexture;
+
typedef enum
{
TT_TEXTURE = 0, // Standard 2D Texture
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index b6463309e1..8c0d3592df 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -72,11 +72,11 @@ LLRenderTarget::~LLRenderTarget()
release();
}
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
+bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
stop_glerror();
-
release();
+ stop_glerror();
mResX = resx;
mResY = resy;
@@ -103,9 +103,11 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
{
if (depth)
{
- stop_glerror();
- allocateDepth();
- stop_glerror();
+ if (!allocateDepth())
+ {
+ llwarns << "Failed to allocate depth buffer for render target." << llendl;
+ return false;
+ }
}
glGenFramebuffers(1, (GLuint *) &mFBO);
@@ -131,14 +133,14 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
stop_glerror();
}
- addColorAttachment(color_fmt);
+ return addColorAttachment(color_fmt);
}
-void LLRenderTarget::addColorAttachment(U32 color_fmt)
+bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
if (color_fmt == 0)
{
- return;
+ return true;
}
U32 offset = mTex.size();
@@ -158,14 +160,26 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
#ifdef GL_ARB_texture_multisample
if (mSamples > 1)
{
+ clear_glerror();
glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ llwarns << "Could not allocate multisample color buffer for render target." << llendl;
+ return false;
+ }
}
else
#else
llassert_always(mSamples <= 1);
#endif
{
+ clear_glerror();
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ llwarns << "Could not allocate color buffer for render target." << llendl;
+ return false;
+ }
}
stop_glerror();
@@ -217,15 +231,18 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
flush();
}
+ return true;
}
-void LLRenderTarget::allocateDepth()
+bool LLRenderTarget::allocateDepth()
{
if (mStencil)
{
//use render buffers where stencil buffers are in play
glGenRenderbuffers(1, (GLuint *) &mDepth);
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
+ stop_glerror();
+ clear_glerror();
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
@@ -237,17 +254,29 @@ void LLRenderTarget::allocateDepth()
{
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+ clear_glerror();
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
#ifdef GL_ARB_texture_multisample
else
{
+ stop_glerror();
+ clear_glerror();
glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
}
#else
llassert_always(mSamples <= 1);
#endif
}
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ llwarns << "Unable to allocate depth buffer for render target." << llendl;
+ return false;
+ }
+
+ return true;
}
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 094b58b562..dea1de12d8 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -66,30 +66,30 @@ public:
static bool sUseFBO;
LLRenderTarget();
- virtual ~LLRenderTarget();
+ ~LLRenderTarget();
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
- void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
+ bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
//add color buffer attachment
//limit of 4 color attachments per render target
- virtual void addColorAttachment(U32 color_fmt);
+ bool addColorAttachment(U32 color_fmt);
//allocate a depth texture
- virtual void allocateDepth();
+ bool allocateDepth();
//share depth buffer with provided render target
- virtual void shareDepthBuffer(LLRenderTarget& target);
+ void shareDepthBuffer(LLRenderTarget& target);
//free any allocated resources
//safe to call redundantly
- virtual void release();
+ void release();
//bind target for rendering
//applies appropriate viewport
- virtual void bindTarget();
+ void bindTarget();
//unbind target for rendering
static void unbindTarget();
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index d5a7159ee3..b6a252e8fa 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -35,6 +35,8 @@
#include "llmemtype.h"
#include "llrender.h"
#include "llvector4a.h"
+#include "llglslshader.h"
+
//============================================================================
@@ -65,6 +67,60 @@ S32 LLVertexBuffer::sWeight4Loc = -1;
std::vector<U32> LLVertexBuffer::sDeleteList;
+const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms
+
+class LLGLSyncFence : public LLGLFence
+{
+public:
+#ifdef GL_ARB_sync
+ GLsync mSync;
+#endif
+
+ LLGLSyncFence()
+ {
+#ifdef GL_ARB_sync
+ mSync = 0;
+#endif
+ }
+
+ ~LLGLSyncFence()
+ {
+#ifdef GL_ARB_sync
+ if (mSync)
+ {
+ glDeleteSync(mSync);
+ }
+#endif
+ }
+
+ void placeFence()
+ {
+#ifdef GL_ARB_sync
+ if (mSync)
+ {
+ glDeleteSync(mSync);
+ }
+ mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+#endif
+ }
+
+ void wait()
+ {
+#ifdef GL_ARB_sync
+ if (mSync)
+ {
+ while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
+ { //track the number of times we've waited here
+ static S32 waits = 0;
+ waits++;
+ }
+ }
+#endif
+ }
+
+
+};
+
S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
sizeof(LLVector4), // TYPE_VERTEX,
@@ -310,6 +366,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
stop_glerror();
+ placeFence();
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
@@ -341,6 +398,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
stop_glerror();
+ placeFence();
}
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
@@ -366,6 +424,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
stop_glerror();
glDrawArrays(sGLMode[mode], first, count);
stop_glerror();
+ placeFence();
}
//static
@@ -445,9 +504,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mFilthy(FALSE),
mEmpty(TRUE),
mResized(FALSE),
- mDynamicSize(FALSE)
+ mDynamicSize(FALSE),
+ mFence(NULL)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
+ mFence = NULL;
if (!sEnableVBOs)
{
mUsage = 0 ;
@@ -528,9 +589,40 @@ LLVertexBuffer::~LLVertexBuffer()
destroyGLIndices();
sCount--;
+ if (mFence)
+ {
+ delete mFence;
+ }
+
+ mFence = NULL;
+
llassert_always(!mMappedData && !mMappedIndexData) ;
};
+void LLVertexBuffer::placeFence() const
+{
+ /*if (!mFence && useVBOs())
+ {
+ if (gGLManager.mHasSync)
+ {
+ mFence = new LLGLSyncFence();
+ }
+ }
+
+ if (mFence)
+ {
+ mFence->placeFence();
+ }*/
+}
+
+void LLVertexBuffer::waitFence() const
+{
+ /*if (mFence)
+ {
+ mFence->wait();
+ }*/
+}
+
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer()
@@ -893,17 +985,11 @@ BOOL LLVertexBuffer::useVBOs() const
{
//it's generally ineffective to use VBO for things that are streaming on apple
-#if LL_DARWIN
- if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
- {
- return FALSE;
- }
-#else
if (!mUsage)
{
return FALSE;
}
-#endif
+
return TRUE;
}
@@ -968,8 +1054,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
if (useVBOs())
{
-
- if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (count == -1)
{
@@ -1009,6 +1094,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
setBuffer(0, type);
mVertexLocked = TRUE;
+ sMappedCount++;
stop_glerror();
if(sDisableVBOMapping)
@@ -1019,29 +1105,50 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
else
{
U8* src = NULL;
-#ifdef GL_ARB_map_buffer_range
+ waitFence();
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
+#ifdef GL_ARB_map_buffer_range
S32 offset = mOffsets[type] + sTypeSize[type]*index;
S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length,
+ GL_MAP_WRITE_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ GL_MAP_INVALIDATE_RANGE_BIT);
+#endif
}
else
{
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+#ifdef GL_ARB_map_buffer_range
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize,
+ GL_MAP_WRITE_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT);
+#endif
+ }
+ }
+ else if (gGLManager.mHasFlushBufferRange)
+ {
+ if (map_range)
+ {
+ glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
+ glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+ src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+ else
+ {
+ src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
}
else
-#else
- llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
{
map_range = false;
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
+ llassert(src != NULL);
+
mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedOffset = mMappedData - src;
@@ -1083,7 +1190,6 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
llerrs << "memory allocation for vertex data failed." << llendl ;
}
}
- sMappedCount++;
}
}
else
@@ -1091,7 +1197,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
map_range = false;
}
- if (map_range && !sDisableVBOMapping)
+ if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
{
return mMappedData;
}
@@ -1115,7 +1221,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
if (useVBOs())
{
- if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (count == -1)
{
@@ -1153,6 +1259,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
setBuffer(0, TYPE_INDEX);
mIndexLocked = TRUE;
+ sMappedCount++;
stop_glerror();
if(sDisableVBOMapping)
@@ -1163,29 +1270,51 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
else
{
U8* src = NULL;
-#ifdef GL_ARB_map_buffer_range
+ waitFence();
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
+#ifdef GL_ARB_map_buffer_range
S32 offset = sizeof(U16)*index;
S32 length = sizeof(U16)*count;
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length,
+ GL_MAP_WRITE_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ GL_MAP_INVALIDATE_RANGE_BIT);
+#endif
+ }
+ else
+ {
+#ifdef GL_ARB_map_buffer_range
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices,
+ GL_MAP_WRITE_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT);
+#endif
+ }
+ }
+ else if (gGLManager.mHasFlushBufferRange)
+ {
+ if (map_range)
+ {
+ glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
+ glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+ src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
else
{
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
}
else
-#else
- llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
{
map_range = false;
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
+ llassert(src != NULL);
+
+
mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedIndexOffset = mMappedIndexData - src;
stop_glerror();
@@ -1212,15 +1341,13 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
llerrs << "memory allocation for Index data failed. " << llendl ;
}
}
-
- sMappedCount++;
}
else
{
map_range = false;
}
- if (map_range && !sDisableVBOMapping)
+ if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
{
return mMappedIndexData;
}
@@ -1269,8 +1396,7 @@ void LLVertexBuffer::unmapBuffer(S32 type)
}
else
{
-#ifdef GL_ARB_map_buffer_range
- if (gGLManager.mHasMapBufferRange)
+ if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (!mMappedVertexRegions.empty())
{
@@ -1280,16 +1406,22 @@ void LLVertexBuffer::unmapBuffer(S32 type)
const MappedRegion& region = mMappedVertexRegions[i];
S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
S32 length = sTypeSize[region.mType]*region.mCount;
- glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+ if (gGLManager.mHasMapBufferRange)
+ {
+#ifdef GL_ARB_map_buffer_range
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+#endif
+ }
+ else if (gGLManager.mHasFlushBufferRange)
+ {
+ glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
+ }
stop_glerror();
}
mMappedVertexRegions.clear();
}
}
-#else
- llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1327,8 +1459,7 @@ void LLVertexBuffer::unmapBuffer(S32 type)
}
else
{
-#ifdef GL_ARB_map_buffer_range
- if (gGLManager.mHasMapBufferRange)
+ if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (!mMappedIndexRegions.empty())
{
@@ -1337,16 +1468,24 @@ void LLVertexBuffer::unmapBuffer(S32 type)
const MappedRegion& region = mMappedIndexRegions[i];
S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
S32 length = sizeof(U16)*region.mCount;
- glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+ if (gGLManager.mHasMapBufferRange)
+ {
+#ifdef GL_ARB_map_buffer_range
+ glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+#endif
+ }
+ else if (gGLManager.mHasFlushBufferRange)
+ {
+#ifdef GL_APPLE_flush_buffer_range
+ glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+#endif
+ }
stop_glerror();
}
mMappedIndexRegions.clear();
}
}
-#else
- llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index aa5df305a6..cc5d11e1c2 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -70,6 +70,12 @@ protected:
}
};
+class LLGLFence
+{
+public:
+ virtual void placeFence() = 0;
+ virtual void wait() = 0;
+};
//============================================================================
// base class
@@ -270,6 +276,12 @@ protected:
std::vector<MappedRegion> mMappedVertexRegions;
std::vector<MappedRegion> mMappedIndexRegions;
+ mutable LLGLFence* mFence;
+
+ void placeFence() const;
+ void waitFence() const;
+
+
public:
static S32 sCount;
static S32 sGLCount;