added a toggle "LLGLManager::mDebugGPU" for debugging certain CPUs.
added more debug code for EXT-6791: [crashhunters] Intel 965 Crash in glCopyTexSubImage2Dmeow-7.2.2
parent
ebab718f32
commit
f263ee0444
|
|
@ -185,9 +185,6 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT =
|
|||
// GL_EXT_framebuffer_blit
|
||||
PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL;
|
||||
|
||||
// GL_EXT_blend_func_separate
|
||||
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
|
||||
|
||||
// GL_ARB_draw_buffers
|
||||
PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
|
||||
|
||||
|
|
@ -327,7 +324,6 @@ LLGLManager::LLGLManager() :
|
|||
mHasCompressedTextures(FALSE),
|
||||
mHasFramebufferObject(FALSE),
|
||||
mHasFramebufferMultisample(FALSE),
|
||||
mHasBlendFuncSeparate(FALSE),
|
||||
|
||||
mHasVertexBufferObject(FALSE),
|
||||
mHasPBuffer(FALSE),
|
||||
|
|
@ -356,6 +352,8 @@ LLGLManager::LLGLManager() :
|
|||
|
||||
mHasSeparateSpecularColor(FALSE),
|
||||
|
||||
mDebugGPU(FALSE),
|
||||
|
||||
mDriverVersionMajor(1),
|
||||
mDriverVersionMinor(0),
|
||||
mDriverVersionRelease(0),
|
||||
|
|
@ -523,11 +521,23 @@ bool LLGLManager::initGL()
|
|||
return false;
|
||||
}
|
||||
|
||||
setToDebugGPU();
|
||||
|
||||
initGLStates();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLGLManager::setToDebugGPU()
|
||||
{
|
||||
//"MOBILE INTEL(R) 965 EXPRESS CHIP",
|
||||
if (mGLRenderer.find("INTEL") != std::string::npos && mGLRenderer.find("965") != std::string::npos)
|
||||
{
|
||||
mDebugGPU = TRUE ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void LLGLManager::getGLInfo(LLSD& info)
|
||||
{
|
||||
info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
|
||||
|
|
@ -636,11 +646,6 @@ void LLGLManager::initExtensions()
|
|||
mHasDrawBuffers = TRUE;
|
||||
#else
|
||||
mHasDrawBuffers = FALSE;
|
||||
# endif
|
||||
# if GL_EXT_blend_func_separate
|
||||
mHasBlendFuncSeparate = TRUE;
|
||||
#else
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
# endif
|
||||
mHasMipMapGeneration = FALSE;
|
||||
mHasSeparateSpecularColor = FALSE;
|
||||
|
|
@ -668,7 +673,6 @@ void LLGLManager::initExtensions()
|
|||
&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
|
||||
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
|
||||
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
|
||||
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
|
||||
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
|
||||
#if !LL_DARWIN
|
||||
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
|
||||
|
|
@ -692,7 +696,6 @@ void LLGLManager::initExtensions()
|
|||
mHasFramebufferObject = FALSE;
|
||||
mHasFramebufferMultisample = FALSE;
|
||||
mHasDrawBuffers = FALSE;
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
mHasMipMapGeneration = FALSE;
|
||||
mHasSeparateSpecularColor = FALSE;
|
||||
mHasAnisotropic = FALSE;
|
||||
|
|
@ -717,7 +720,6 @@ void LLGLManager::initExtensions()
|
|||
mHasShaderObjects = FALSE;
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
|
||||
}
|
||||
if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */
|
||||
|
|
@ -746,8 +748,7 @@ void LLGLManager::initExtensions()
|
|||
if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
|
||||
if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;
|
||||
if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE;
|
||||
if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S
|
||||
|
||||
|
||||
}
|
||||
#endif // LL_LINUX || LL_SOLARIS
|
||||
|
||||
|
|
@ -795,14 +796,6 @@ void LLGLManager::initExtensions()
|
|||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL;
|
||||
}
|
||||
if (!mHasBlendFuncSeparate)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL;
|
||||
}
|
||||
if (!mHasDrawBuffers)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Disable certain things due to known bugs
|
||||
if (mIsIntel && mHasMipMapGeneration)
|
||||
|
|
@ -873,10 +866,6 @@ void LLGLManager::initExtensions()
|
|||
{
|
||||
glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB");
|
||||
}
|
||||
if (mHasBlendFuncSeparate)
|
||||
{
|
||||
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
|
||||
}
|
||||
#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
|
||||
// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
|
||||
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
|
||||
|
|
@ -1039,9 +1028,24 @@ void flush_glerror()
|
|||
glGetError();
|
||||
}
|
||||
|
||||
void do_assert_glerror()
|
||||
void assert_glerror()
|
||||
{
|
||||
if (LL_UNLIKELY(!gGLManager.mInited))
|
||||
if (!gGLActive)
|
||||
{
|
||||
//llwarns << "GL used while not active!" << llendl;
|
||||
|
||||
if (gDebugSession)
|
||||
{
|
||||
//ll_fail("GL used while not active");
|
||||
}
|
||||
}
|
||||
|
||||
if (gNoRender || !gDebugGL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gGLManager.mInited)
|
||||
{
|
||||
LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;
|
||||
}
|
||||
|
|
@ -1049,9 +1053,10 @@ void do_assert_glerror()
|
|||
GLenum error;
|
||||
error = glGetError();
|
||||
BOOL quit = FALSE;
|
||||
while (LL_UNLIKELY(error))
|
||||
while (error)
|
||||
{
|
||||
quit = TRUE;
|
||||
#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well.
|
||||
GLubyte const * gl_error_msg = gluErrorString(error);
|
||||
if (NULL != gl_error_msg)
|
||||
{
|
||||
|
|
@ -1075,6 +1080,7 @@ void do_assert_glerror()
|
|||
}
|
||||
}
|
||||
error = glGetError();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (quit)
|
||||
|
|
@ -1090,25 +1096,6 @@ void do_assert_glerror()
|
|||
}
|
||||
}
|
||||
|
||||
void assert_glerror()
|
||||
{
|
||||
if (!gGLActive)
|
||||
{
|
||||
//llwarns << "GL used while not active!" << llendl;
|
||||
|
||||
if (gDebugSession)
|
||||
{
|
||||
//ll_fail("GL used while not active");
|
||||
}
|
||||
}
|
||||
|
||||
if (!gNoRender && gDebugGL)
|
||||
{
|
||||
do_assert_glerror();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clear_glerror()
|
||||
{
|
||||
// Create or update texture to be used with this data
|
||||
|
|
@ -1122,7 +1109,7 @@ void clear_glerror()
|
|||
//
|
||||
|
||||
// Static members
|
||||
boost::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
|
||||
std::map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
|
||||
|
||||
GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default
|
||||
GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default
|
||||
|
|
@ -1170,7 +1157,7 @@ void LLGLState::resetTextureStates()
|
|||
void LLGLState::dumpStates()
|
||||
{
|
||||
LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
|
||||
for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
|
||||
for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
|
||||
iter != sStateMap.end(); ++iter)
|
||||
{
|
||||
LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"TRUE":"FALSE") << LL_ENDL;
|
||||
|
|
@ -1206,7 +1193,7 @@ void LLGLState::checkStates(const std::string& msg)
|
|||
}
|
||||
}
|
||||
|
||||
for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
|
||||
for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
|
||||
iter != sStateMap.end(); ++iter)
|
||||
{
|
||||
LLGLenum state = iter->first;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
// This file contains various stuff for handling gl extensions and other gl related stuff.
|
||||
|
||||
#include <string>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "llerror.h"
|
||||
|
|
@ -87,7 +87,6 @@ public:
|
|||
BOOL mHasCompressedTextures;
|
||||
BOOL mHasFramebufferObject;
|
||||
BOOL mHasFramebufferMultisample;
|
||||
BOOL mHasBlendFuncSeparate;
|
||||
|
||||
// ARB Extensions
|
||||
BOOL mHasVertexBufferObject;
|
||||
|
|
@ -120,6 +119,9 @@ public:
|
|||
|
||||
// Misc extensions
|
||||
BOOL mHasSeparateSpecularColor;
|
||||
|
||||
//whether this GPU is in the debug list.
|
||||
BOOL mDebugGPU;
|
||||
|
||||
S32 mDriverVersionMajor;
|
||||
S32 mDriverVersionMinor;
|
||||
|
|
@ -148,6 +150,7 @@ private:
|
|||
void initExtensions();
|
||||
void initGLStates();
|
||||
void initGLImages();
|
||||
void setToDebugGPU();
|
||||
};
|
||||
|
||||
extern LLGLManager gGLManager;
|
||||
|
|
@ -241,7 +244,7 @@ public:
|
|||
static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0x0001);
|
||||
|
||||
protected:
|
||||
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
|
||||
static std::map<LLGLenum, LLGLboolean> sStateMap;
|
||||
|
||||
public:
|
||||
enum { CURRENT_STATE = -2 };
|
||||
|
|
|
|||
|
|
@ -150,12 +150,12 @@ void LLImageGL::checkTexSize(bool forced) const
|
|||
if (gDebugSession)
|
||||
{
|
||||
gFailLog << "wrong texture size and discard level!" <<
|
||||
mWidth << " Height: " << mHeight << " Current Level: " << mCurrentDiscardLevel << std::endl;
|
||||
mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "wrong texture size and discard level: width: " <<
|
||||
mWidth << " Height: " << mHeight << " Current Level: " << mCurrentDiscardLevel << llendl ;
|
||||
mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << llendl ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1057,8 +1057,12 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
|
|||
{
|
||||
if (gGL.getTexUnit(0)->bind(this, false, true))
|
||||
{
|
||||
checkTexSize(true) ;
|
||||
llcallstacks << fb_x << " : " << fb_y << " : " << x_pos << " : " << y_pos << " : " << width << " : " << height << llcallstacksendl ;
|
||||
if(gGLManager.mDebugGPU)
|
||||
{
|
||||
llinfos << "Calling glCopyTexSubImage2D(...)" << llendl ;
|
||||
checkTexSize(true) ;
|
||||
llcallstacks << fb_x << " : " << fb_y << " : " << x_pos << " : " << y_pos << " : " << width << " : " << height << llcallstacksendl ;
|
||||
}
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
|
||||
mGLTextureCreated = true;
|
||||
|
|
@ -1654,7 +1658,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
|
|||
}
|
||||
}
|
||||
|
||||
void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
||||
void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
|
||||
{
|
||||
if(!mNeedsAlphaAndPickMask)
|
||||
{
|
||||
|
|
@ -1662,91 +1666,26 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
|||
}
|
||||
|
||||
U32 length = w * h;
|
||||
U32 alphatotal = 0;
|
||||
const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ;
|
||||
|
||||
U32 sample[16];
|
||||
memset(sample, 0, sizeof(U32)*16);
|
||||
S32 sample[16];
|
||||
memset(sample, 0, sizeof(S32)*16);
|
||||
|
||||
// generate histogram of quantized alpha.
|
||||
// also add-in the histogram of a 2x2 box-sampled version. The idea is
|
||||
// this will mid-skew the data (and thus increase the chances of not
|
||||
// being used as a mask) from high-frequency alpha maps which
|
||||
// suffer the worst from aliasing when used as alpha masks.
|
||||
if (w >= 2 && h >= 2)
|
||||
for (U32 i = 0; i < length; i++)
|
||||
{
|
||||
llassert(w%2 == 0);
|
||||
llassert(h%2 == 0);
|
||||
const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
|
||||
for (U32 y = 0; y < h; y+=2)
|
||||
{
|
||||
const GLubyte* current = rowstart;
|
||||
for (U32 x = 0; x < w; x+=2)
|
||||
{
|
||||
const U32 s1 = current[0];
|
||||
alphatotal += s1;
|
||||
const U32 s2 = current[w * mAlphaStride];
|
||||
alphatotal += s2;
|
||||
current += mAlphaStride;
|
||||
const U32 s3 = current[0];
|
||||
alphatotal += s3;
|
||||
const U32 s4 = current[w * mAlphaStride];
|
||||
alphatotal += s4;
|
||||
current += mAlphaStride;
|
||||
|
||||
++sample[s1/16];
|
||||
++sample[s2/16];
|
||||
++sample[s3/16];
|
||||
++sample[s4/16];
|
||||
|
||||
const U32 asum = (s1+s2+s3+s4);
|
||||
alphatotal += asum;
|
||||
sample[asum/(16*4)] += 4;
|
||||
}
|
||||
|
||||
rowstart += 2 * w * mAlphaStride;
|
||||
}
|
||||
length *= 2; // we sampled everything twice, essentially
|
||||
++sample[*current/16];
|
||||
current += mAlphaStride ;
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;
|
||||
for (U32 i = 0; i < length; i++)
|
||||
{
|
||||
const U32 s1 = *current;
|
||||
alphatotal += s1;
|
||||
++sample[s1/16];
|
||||
current += mAlphaStride;
|
||||
}
|
||||
}
|
||||
|
||||
// if more than 1/16th of alpha samples are mid-range, this
|
||||
// shouldn't be treated as a 1-bit mask
|
||||
|
||||
// also, if all of the alpha samples are clumped on one half
|
||||
// of the range (but not at an absolute extreme), then consider
|
||||
// this to be an intentional effect and don't treat as a mask.
|
||||
|
||||
U32 midrangetotal = 0;
|
||||
U32 total = 0;
|
||||
for (U32 i = 4; i < 11; i++)
|
||||
{
|
||||
midrangetotal += sample[i];
|
||||
}
|
||||
U32 lowerhalftotal = 0;
|
||||
for (U32 i = 0; i < 8; i++)
|
||||
{
|
||||
lowerhalftotal += sample[i];
|
||||
}
|
||||
U32 upperhalftotal = 0;
|
||||
for (U32 i = 8; i < 16; i++)
|
||||
{
|
||||
upperhalftotal += sample[i];
|
||||
total += sample[i];
|
||||
}
|
||||
|
||||
if (midrangetotal > length/16 || // lots of midrange, or
|
||||
(lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or
|
||||
(upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque
|
||||
if (total > length/16)
|
||||
{
|
||||
mIsMask = FALSE; // not suitable for masking
|
||||
mIsMask = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -170,9 +170,12 @@ void LLViewerDynamicTexture::postRender(BOOL success)
|
|||
if(!mGLTexturep->getHasGLTexture())
|
||||
{
|
||||
generateGLTexture() ;
|
||||
}
|
||||
llcallstacks << "class type: " << (S32)getType() << llcallstacksendl ;
|
||||
}
|
||||
|
||||
if(gGLManager.mDebugGPU)
|
||||
{
|
||||
LLGLState::dumpStates() ;
|
||||
}
|
||||
success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
|
||||
}
|
||||
}
|
||||
|
|
@ -211,11 +214,16 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
|
|||
{
|
||||
LLViewerDynamicTexture *dynamicTexture = *iter;
|
||||
if (dynamicTexture->needsRender())
|
||||
{
|
||||
{
|
||||
if(gGLManager.mDebugGPU)
|
||||
{
|
||||
llinfos << "class type: " << (S32)dynamicTexture->getType() << llendl;
|
||||
LLGLState::dumpStates() ;
|
||||
}
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
gDepthDirty = TRUE;
|
||||
|
||||
|
||||
|
||||
gGL.color4f(1,1,1,1);
|
||||
dynamicTexture->preRender(); // Must be called outside of startRender()
|
||||
result = FALSE;
|
||||
|
|
|
|||
Loading…
Reference in New Issue