added a toggle "LLGLManager::mDebugGPU" for debugging certain CPUs.

added more debug code for EXT-6791: [crashhunters] Intel 965 Crash in glCopyTexSubImage2D
meow-7.2.2
Xiaohong Bao 2010-08-23 11:32:58 -06:00
parent ebab718f32
commit f263ee0444
4 changed files with 76 additions and 139 deletions

View File

@ -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;

View File

@ -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 };

View File

@ -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
{

View File

@ -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;