This commit is contained in:
Lirusaito
2012-09-11 09:45:17 -04:00
36 changed files with 717 additions and 599 deletions

View File

@@ -182,6 +182,7 @@ std::string LLFastTimer::sLogName = "";
BOOL LLFastTimer::sMetricLog = FALSE; BOOL LLFastTimer::sMetricLog = FALSE;
LLMutex* LLFastTimer::sLogLock = NULL; LLMutex* LLFastTimer::sLogLock = NULL;
std::queue<LLSD> LLFastTimer::sLogQueue; std::queue<LLSD> LLFastTimer::sLogQueue;
const int LLFastTimer::NamedTimer::HISTORY_NUM = 300;
#if LL_WINDOWS #if LL_WINDOWS
#define USE_RDTSC 1 #define USE_RDTSC 1
@@ -435,16 +436,12 @@ LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
mFrameStateIndex = frame_state_list.size(); mFrameStateIndex = frame_state_list.size();
getFrameStateList().push_back(FrameState(this)); getFrameStateList().push_back(FrameState(this));
mCountHistory = new U32[HISTORY_NUM]; mCountHistory.resize(HISTORY_NUM);
memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM); mCallHistory.resize(HISTORY_NUM);
mCallHistory = new U32[HISTORY_NUM];
memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
} }
LLFastTimer::NamedTimer::~NamedTimer() LLFastTimer::NamedTimer::~NamedTimer()
{ {
delete[] mCountHistory;
delete[] mCallHistory;
} }
std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx) std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
@@ -637,10 +634,12 @@ void LLFastTimer::NamedTimer::accumulateTimings()
// update timer history // update timer history
int hidx = cur_frame % HISTORY_NUM; int hidx = cur_frame % HISTORY_NUM;
int weight = llmin(100, cur_frame);
timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter; timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1); timerp->mCountAverage = ((F64)timerp->mCountAverage * weight + (F64)timerp->mTotalTimeCounter) / (weight+1);
timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls; timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1); timerp->mCallAverage = ((F64)timerp->mCallAverage * weight + (F64)timerp->getFrameState().mCalls) / (weight+1);
} }
} }
} }
@@ -776,8 +775,10 @@ void LLFastTimer::NamedTimer::reset()
timer.mCountAverage = 0; timer.mCountAverage = 0;
timer.mCallAverage = 0; timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); timer.mCountHistory.clear();
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM); timer.mCountHistory.resize(HISTORY_NUM);
timer.mCallHistory.clear();
timer.mCallHistory.resize(HISTORY_NUM);
} }
} }
@@ -856,7 +857,8 @@ void LLFastTimer::nextFrame()
if (!sPauseHistory) if (!sPauseHistory)
{ {
NamedTimer::processTimes(); NamedTimer::processTimes();
sLastFrameIndex = sCurFrameIndex++; sLastFrameIndex = sCurFrameIndex;
++sCurFrameIndex;
} }
// get ready for next frame // get ready for next frame

View File

@@ -66,7 +66,7 @@ public:
public: public:
~NamedTimer(); ~NamedTimer();
enum { HISTORY_NUM = 300 }; static const int HISTORY_NUM;
const std::string& getName() const { return mName; } const std::string& getName() const { return mName; }
NamedTimer* getParent() const { return mParent; } NamedTimer* getParent() const { return mParent; }
@@ -82,8 +82,8 @@ public:
void setCollapsed(bool collapsed) { mCollapsed = collapsed; } void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
bool getCollapsed() const { return mCollapsed; } bool getCollapsed() const { return mCollapsed; }
U32 getCountAverage() const; //{ return mCountAverage } U32 getCountAverage() const;
U32 getCallAverage() const; //{ return mCallAverage } U32 getCallAverage() const;
U32 getHistoricalCount(S32 history_index = 0) const; U32 getHistoricalCount(S32 history_index = 0) const;
U32 getHistoricalCalls(S32 history_index = 0) const; U32 getHistoricalCalls(S32 history_index = 0) const;
@@ -122,11 +122,11 @@ public:
U32 mTotalTimeCounter; U32 mTotalTimeCounter;
U32 mCountAverage; F64 mCountAverage;
U32 mCallAverage; F64 mCallAverage;
U32* mCountHistory; std::vector<U32> mCountHistory;
U32* mCallHistory; std::vector<U32> mCallHistory;
// tree structure // tree structure
NamedTimer* mParent; // NamedTimer of caller(parent) NamedTimer* mParent; // NamedTimer of caller(parent)
@@ -258,11 +258,10 @@ public:
static CurTimerData sCurTimerData; static CurTimerData sCurTimerData;
static std::string sClockType; static std::string sClockType;
public: private:
static U32 getCPUClockCount32(); static U32 getCPUClockCount32();
static U64 getCPUClockCount64(); static U64 getCPUClockCount64();
private:
static S32 sCurFrameIndex; static S32 sCurFrameIndex;
static S32 sLastFrameIndex; static S32 sLastFrameIndex;
static U64 sLastFrameTime; static U64 sLastFrameTime;

View File

@@ -40,7 +40,7 @@ const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-hav
const F32 MIN_OBJECT_Z = -256.f; const F32 MIN_OBJECT_Z = -256.f;
const F32 DEFAULT_MAX_PRIM_SCALE = 256.f; const F32 DEFAULT_MAX_PRIM_SCALE = 256.f;
const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE; const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE;
const F32 MIN_PRIM_SCALE = 0.01f; //const F32 MIN_PRIM_SCALE = 0.01f;
const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
class LLXform class LLXform

View File

@@ -64,7 +64,7 @@ void LLFontBitmapCache::init(S32 num_components,
LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
{ {
if ((bitmap_num < 0) || (bitmap_num >= mImageRawVec.size())) if (bitmap_num >= mImageRawVec.size())
return NULL; return NULL;
return mImageRawVec[bitmap_num]; return mImageRawVec[bitmap_num];
@@ -72,7 +72,7 @@ LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const
{ {
if ((bitmap_num < 0) || (bitmap_num >= mImageGLVec.size())) if (bitmap_num >= mImageGLVec.size())
return NULL; return NULL;
return mImageGLVec[bitmap_num]; return mImageGLVec[bitmap_num];

View File

@@ -557,7 +557,7 @@ bool LLImageGL::checkSize(S32 width, S32 height)
return check_power_of_two(width) && check_power_of_two(height); return check_power_of_two(width) && check_power_of_two(height);
} }
void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
{ {
if (width != mWidth || height != mHeight || ncomponents != mComponents) if (width != mWidth || height != mHeight || ncomponents != mComponents)
{ {
@@ -590,6 +590,11 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
width >>= 1; width >>= 1;
height >>= 1; height >>= 1;
} }
if(discard_level > 0)
{
mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
}
} }
else else
{ {
@@ -1254,7 +1259,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
llassert(mCurrentDiscardLevel >= 0); llassert(mCurrentDiscardLevel >= 0);
discard_level = mCurrentDiscardLevel; discard_level = mCurrentDiscardLevel;
} }
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
// Actual image width/height = raw image width/height * 2^discard_level // Actual image width/height = raw image width/height * 2^discard_level
S32 raw_w = imageraw->getWidth() ; S32 raw_w = imageraw->getWidth() ;
@@ -1263,7 +1267,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
S32 h = raw_h << discard_level; S32 h = raw_h << discard_level;
// setSize may call destroyGLTexture if the size does not match // setSize may call destroyGLTexture if the size does not match
setSize(w, h, imageraw->getComponents()); setSize(w, h, imageraw->getComponents(), discard_level);
if( !mHasExplicitFormat ) if( !mHasExplicitFormat )
{ {
@@ -1323,7 +1327,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
llassert(mCurrentDiscardLevel >= 0); llassert(mCurrentDiscardLevel >= 0);
discard_level = mCurrentDiscardLevel; discard_level = mCurrentDiscardLevel;
} }
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
if (mTexName != 0 && discard_level == mCurrentDiscardLevel) if (mTexName != 0 && discard_level == mCurrentDiscardLevel)
{ {
@@ -1818,6 +1821,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
llassert(w%2 == 0); llassert(w%2 == 0);
llassert(h%2 == 0); llassert(h%2 == 0);
const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset; const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
for (U32 y = 0; y < h; y+=2) for (U32 y = 0; y < h; y+=2)
{ {
const GLubyte* current = rowstart; const GLubyte* current = rowstart;

View File

@@ -100,7 +100,7 @@ protected:
public: public:
virtual void dump(); // debugging info to llinfos virtual void dump(); // debugging info to llinfos
void setSize(S32 width, S32 height, S32 ncomponents); void setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
void setAllowCompression(bool allow) { mAllowCompression = allow; } void setAllowCompression(bool allow) { mAllowCompression = allow; }

View File

@@ -775,11 +775,8 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
//Restrict to valid sample count //Restrict to valid sample count
{ {
mSamples = samples; mSamples = samples;
mSamples = llmin(mSamples, (U32)4); //Cap to prevent memory bloat. //mSamples = llmin(mSamples, (U32)4); //Cap to prevent memory bloat.
mSamples = llmin(mSamples, (U32) gGLManager.mMaxIntegerSamples);//GL_RGBA mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples);
if(depth && !stencil)
mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples); //GL_DEPTH_COMPONENT16_ARB
} }
if (mSamples <= 1) if (mSamples <= 1)

View File

@@ -679,7 +679,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
vec4 diffuseLookup(vec2 texcoord) vec4 diffuseLookup(vec2 texcoord)
{ {
switch (vary_texture_index)) switch (vary_texture_index.r))
{ {
case 0: ret = texture2D(tex0, texcoord); break; case 0: ret = texture2D(tex0, texcoord); break;
case 1: ret = texture2D(tex1, texcoord); break; case 1: ret = texture2D(tex1, texcoord); break;
@@ -703,7 +703,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (texture_index_channels > 1) if (texture_index_channels > 1)
{ {
text[count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n");
} }
text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
@@ -721,7 +721,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{ //switches are unreliable on old drivers { //switches are unreliable on old drivers
for (S32 i = 0; i < texture_index_channels; ++i) for (S32 i = 0; i < texture_index_channels; ++i)
{ {
std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); std::string if_string = llformat("\t%sif (vary_texture_index.r == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);
text[count++] = strdup(if_string.c_str()); text[count++] = strdup(if_string.c_str());
} }
text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
@@ -730,13 +730,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
else else
{ {
text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n");
text[count++] = strdup("\tswitch (vary_texture_index)\n"); text[count++] = strdup("\tswitch (vary_texture_index.r)\n");
text[count++] = strdup("\t{\n"); text[count++] = strdup("\t{\n");
//switch body //switch body
for (S32 i = 0; i < texture_index_channels; ++i) for (S32 i = 0; i < texture_index_channels; ++i)
{ {
std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i);
text[count++] = strdup(case_str.c_str()); text[count++] = strdup(case_str.c_str());
} }

View File

@@ -1249,7 +1249,7 @@ void LLVertexBuffer::setupVertexArray()
1, //TYPE_WEIGHT, 1, //TYPE_WEIGHT,
4, //TYPE_WEIGHT4, 4, //TYPE_WEIGHT4,
4, //TYPE_CLOTHWEIGHT, 4, //TYPE_CLOTHWEIGHT,
1, //TYPE_TEXTURE_INDEX 4, //TYPE_TEXTURE_INDEX
}; };
U32 attrib_type[] = U32 attrib_type[] =
@@ -1266,7 +1266,7 @@ void LLVertexBuffer::setupVertexArray()
GL_FLOAT, //TYPE_WEIGHT, GL_FLOAT, //TYPE_WEIGHT,
GL_FLOAT, //TYPE_WEIGHT4, GL_FLOAT, //TYPE_WEIGHT4,
GL_FLOAT, //TYPE_CLOTHWEIGHT, GL_FLOAT, //TYPE_CLOTHWEIGHT,
GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX
}; };
bool attrib_integer[] = bool attrib_integer[] =
@@ -2313,7 +2313,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
#if !LL_DARWIN #if !LL_DARWIN
S32 loc = TYPE_TEXTURE_INDEX; S32 loc = TYPE_TEXTURE_INDEX;
void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
#endif #endif
} }
if (data_mask & MAP_VERTEX) if (data_mask & MAP_VERTEX)

View File

@@ -387,6 +387,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mhDC = NULL; mhDC = NULL;
mhRC = NULL; mhRC = NULL;
llinfos<<"Desired FSAA Samples = "<<mFSAASamples<<llendl;
// Initialize the keyboard // Initialize the keyboard
gKeyboard = new LLKeyboardWin32(); gKeyboard = new LLKeyboardWin32();
gKeyboard->setCallbacks(callbacks); gKeyboard->setCallbacks(callbacks);
@@ -1274,21 +1276,155 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
LL_INFOS("Window") << "pixel formats done." << llendl ; LL_INFOS("Window") << "pixel formats done." << llendl ;
S32 swap_method = 0; /*for(int i = 0; i <= num_formats-1; ++i)
S32 cur_format = num_formats-1;
GLint swap_query = WGL_SWAP_METHOD_ARB;
BOOL found_format = FALSE;
while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
{ {
if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0) GLint query[] = { WGL_SAMPLE_BUFFERS_ARB,
WGL_SAMPLES_ARB,
WGL_NUMBER_PIXEL_FORMATS_ARB,
WGL_DRAW_TO_WINDOW_ARB,
WGL_DRAW_TO_BITMAP_ARB,
WGL_ACCELERATION_ARB,
WGL_NEED_PALETTE_ARB,
WGL_NEED_SYSTEM_PALETTE_ARB,
WGL_SWAP_LAYER_BUFFERS_ARB,
WGL_SWAP_METHOD_ARB,
WGL_NUMBER_OVERLAYS_ARB,
WGL_NUMBER_UNDERLAYS_ARB,
WGL_TRANSPARENT_ARB,
WGL_TRANSPARENT_RED_VALUE_ARB,
WGL_TRANSPARENT_GREEN_VALUE_ARB,
WGL_TRANSPARENT_BLUE_VALUE_ARB,
WGL_TRANSPARENT_ALPHA_VALUE_ARB,
WGL_TRANSPARENT_INDEX_VALUE_ARB,
WGL_SHARE_DEPTH_ARB,
WGL_SHARE_STENCIL_ARB,
WGL_SHARE_ACCUM_ARB,
WGL_SUPPORT_GDI_ARB,
WGL_SUPPORT_OPENGL_ARB,
WGL_DOUBLE_BUFFER_ARB,
WGL_STEREO_ARB,
WGL_PIXEL_TYPE_ARB,
WGL_COLOR_BITS_ARB,
WGL_RED_BITS_ARB,
WGL_RED_SHIFT_ARB,
WGL_GREEN_BITS_ARB,
WGL_GREEN_SHIFT_ARB,
WGL_BLUE_BITS_ARB,
WGL_BLUE_SHIFT_ARB,
WGL_ALPHA_BITS_ARB,
WGL_ALPHA_SHIFT_ARB,
WGL_ACCUM_BITS_ARB,
WGL_ACCUM_RED_BITS_ARB,
WGL_ACCUM_GREEN_BITS_ARB,
WGL_ACCUM_BLUE_BITS_ARB,
WGL_ACCUM_ALPHA_BITS_ARB,
WGL_DEPTH_BITS_ARB,
WGL_STENCIL_BITS_ARB,
WGL_AUX_BUFFERS_ARB};
std::string names[] = { "WGL_SAMPLE_BUFFERS_ARB",
"WGL_SAMPLES_ARB",
"WGL_NUMBER_PIXEL_FORMATS_ARB",
"WGL_DRAW_TO_WINDOW_ARB",
"WGL_DRAW_TO_BITMAP_ARB",
"WGL_ACCELERATION_ARB",
"WGL_NEED_PALETTE_ARB",
"WGL_NEED_SYSTEM_PALETTE_ARB",
"WGL_SWAP_LAYER_BUFFERS_ARB",
"WGL_SWAP_METHOD_ARB",
"WGL_NUMBER_OVERLAYS_ARB",
"WGL_NUMBER_UNDERLAYS_ARB",
"WGL_TRANSPARENT_ARB",
"WGL_TRANSPARENT_RED_VALUE_ARB",
"WGL_TRANSPARENT_GREEN_VALUE_ARB",
"WGL_TRANSPARENT_BLUE_VALUE_ARB",
"WGL_TRANSPARENT_ALPHA_VALUE_ARB",
"WGL_TRANSPARENT_INDEX_VALUE_ARB",
"WGL_SHARE_DEPTH_ARB",
"WGL_SHARE_STENCIL_ARB",
"WGL_SHARE_ACCUM_ARB",
"WGL_SUPPORT_GDI_ARB",
"WGL_SUPPORT_OPENGL_ARB",
"WGL_DOUBLE_BUFFER_ARB",
"WGL_STEREO_ARB",
"WGL_PIXEL_TYPE_ARB",
"WGL_COLOR_BITS_ARB",
"WGL_RED_BITS_ARB",
"WGL_RED_SHIFT_ARB",
"WGL_GREEN_BITS_ARB",
"WGL_GREEN_SHIFT_ARB",
"WGL_BLUE_BITS_ARB",
"WGL_BLUE_SHIFT_ARB",
"WGL_ALPHA_BITS_ARB",
"WGL_ALPHA_SHIFT_ARB",
"WGL_ACCUM_BITS_ARB",
"WGL_ACCUM_RED_BITS_ARB",
"WGL_ACCUM_GREEN_BITS_ARB",
"WGL_ACCUM_BLUE_BITS_ARB",
"WGL_ACCUM_ALPHA_BITS_ARB",
"WGL_DEPTH_BITS_ARB",
"WGL_STENCIL_BITS_ARB",
"WGL_AUX_BUFFERS_ARB"};
S32 results[sizeof(query)/sizeof(query[0])]={0};
if(wglGetPixelFormatAttribivARB(mhDC, pixel_formats[i], 0, sizeof(query)/sizeof(query[0]), query, results))
{ {
llinfos << i << ":" << llendl;
for(int j = 0; j < sizeof(query)/sizeof(query[0]); ++j)
{
switch(results[j])
{
case WGL_NO_ACCELERATION_ARB:
llinfos << " " << names[j] << " = " << "WGL_NO_ACCELERATION_ARB" << llendl;
break;
case WGL_GENERIC_ACCELERATION_ARB:
llinfos << " " << names[j] << " = " << "WGL_GENERIC_ACCELERATION_ARB" << llendl;
break;
case WGL_FULL_ACCELERATION_ARB:
llinfos << " " << names[j] << " = " << "WGL_FULL_ACCELERATION_ARB" << llendl;
break;
case WGL_SWAP_EXCHANGE_ARB:
llinfos << " " << names[j] << " = " << "WGL_SWAP_EXCHANGE_ARB" << llendl;
break;
case WGL_SWAP_COPY_ARB:
llinfos << " " << names[j] << " = " << "WGL_SWAP_COPY_ARB" << llendl;
break;
case WGL_SWAP_UNDEFINED_ARB:
llinfos << " " << names[j] << " = " << "WGL_SWAP_UNDEFINED_ARB" << llendl;
break;
case WGL_TYPE_RGBA_ARB:
llinfos << " " << names[j] << " = " << "WGL_TYPE_RGBA_ARB" << llendl;
break;
case WGL_TYPE_COLORINDEX_ARB:
llinfos << " " << names[j] << " = " << "WGL_TYPE_COLORINDEX_ARB" << llendl;
break;
default:
llinfos << " " << names[j] << " = " << results[j] << llendl;
}
}
}
}*/
//Singu note: Reversed order of this loop. Generally, choosepixelformat returns an array with the closer matches towards the start.
S32 swap_method = 0;
S32 cur_format = 0;//num_formats-1;
GLint swap_query = WGL_SWAP_METHOD_ARB;
BOOL found_format = FALSE;
while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method))
{
if (swap_method == WGL_SWAP_UNDEFINED_ARB /*|| cur_format <= 0*/)
{
found_format = TRUE;
}
else if(cur_format >= num_formats-1)
{
cur_format = 0;
found_format = TRUE; found_format = TRUE;
} }
else else
{ {
--cur_format; //--cur_format;
++cur_format;
} }
} }
@@ -1495,6 +1631,10 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
swapBuffers(); swapBuffers();
} }
int buf = 0;
glGetIntegerv(GL_SAMPLES, &buf);
llinfos << "Acquired FSAA Samples = " << buf << llendl;
return TRUE; return TRUE;
} }

View File

@@ -23,9 +23,9 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
ATTRIBUTE int texture_index; ATTRIBUTE ivec4 texture_index;
VARYING_FLAT int vary_texture_index; VARYING_FLAT ivec4 vary_texture_index;
void passTextureIndex() void passTextureIndex()
{ {

View File

@@ -35,10 +35,12 @@ void HippoLimits::setOpenSimLimits()
mMaxHeight = 10000.0f; mMaxHeight = 10000.0f;
if (gHippoGridManager->getConnectedGrid()->isRenderCompat()) { if (gHippoGridManager->getConnectedGrid()->isRenderCompat()) {
llinfos << "Using rendering compatible OpenSim limits." << llendl; llinfos << "Using rendering compatible OpenSim limits." << llendl;
mMinPrimScale = 0.01f;
mMinHoleSize = 0.05f; mMinHoleSize = 0.05f;
mMaxHollow = 0.95f; mMaxHollow = 0.95f;
} else { } else {
llinfos << "Using Hippo OpenSim limits." << llendl; llinfos << "Using Hippo OpenSim limits." << llendl;
mMinPrimScale = 0.001f;
mMinHoleSize = 0.01f; mMinHoleSize = 0.01f;
mMaxHollow = 0.99f; mMaxHollow = 0.99f;
} }
@@ -57,6 +59,7 @@ void HippoLimits::setSecondLifeLimits()
mMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS; mMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS;
} }
mMinPrimScale = 0.01f;
mMaxHeight = 4096.0f; mMaxHeight = 4096.0f;
mMinHoleSize = 0.05f; mMinHoleSize = 0.05f;
mMaxHollow = 0.95f; mMaxHollow = 0.95f;

View File

@@ -13,6 +13,7 @@ public:
float getMinHoleSize() const { return mMinHoleSize; } float getMinHoleSize() const { return mMinHoleSize; }
float getMaxHollow() const { return mMaxHollow; } float getMaxHollow() const { return mMaxHollow; }
float getMaxPrimScale() const { return mMaxPrimScale; } float getMaxPrimScale() const { return mMaxPrimScale; }
float getMinPrimScale() const { return mMinPrimScale; }
void setLimits(); void setLimits();
@@ -22,6 +23,7 @@ private:
float mMinHoleSize; float mMinHoleSize;
float mMaxHollow; float mMaxHollow;
float mMaxPrimScale; float mMaxPrimScale;
float mMinPrimScale;
void setOpenSimLimits(); void setOpenSimLimits();
void setSecondLifeLimits(); void setSecondLifeLimits();

View File

@@ -494,11 +494,13 @@ void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
// Load region sky presets. // Load region sky presets.
LLWLParamManager::instance().refreshRegionPresets(); LLWLParamManager::instance().refreshRegionPresets();
// Not possible to assume M7WL should take precidence as OpenSim will send both bool bOverridden = M7WindlightInterface::getInstance()->hasOverride();
// bool bOverridden = M7WindlightInterface::getInstance()->hasOverride();
// If using server settings, update managers. // If using server settings, update managers.
if (getUseRegionSettings()) // if (getUseRegionSettings())
// [RLVa:KB] - Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a
if (!bOverridden && (getUseRegionSettings()) && (LLWLParamManager::getInstance()->mAnimator.getIsRunning()) )
// [/RLVa:KB]
{ {
updateManagersFromPrefs(mInterpNextChangeMessage); updateManagersFromPrefs(mInterpNextChangeMessage);
} }

View File

@@ -758,6 +758,9 @@ static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVect
bool less_than_max_mag(const LLVector4a& vec) bool less_than_max_mag(const LLVector4a& vec)
{ {
#if 1
return true;
#else
LLVector4a MAX_MAG; LLVector4a MAX_MAG;
MAX_MAG.splat(1024.f*1024.f); MAX_MAG.splat(1024.f*1024.f);
@@ -767,6 +770,7 @@ bool less_than_max_mag(const LLVector4a& vec)
S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
return lt == 0x7; return lt == 0x7;
#endif
} }
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
@@ -1635,8 +1639,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (!do_xform) if (!do_xform)
{ {
LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM);
S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size);
} }
else else
{ {
@@ -1857,12 +1860,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLVector4a texIdx; LLVector4a texIdx;
S32 index = mTextureIndex < 255 ? mTextureIndex : 0; U8 index = mTextureIndex < 255 ? mTextureIndex : 0;
F32 val = 0.f; F32 val = 0.f;
S32* vp = (S32*) &val; U8* vp = (U8*) &val;
*vp = index; vp[0] = index;
vp[1] = 0;
vp[2] = 0;
vp[3] = 0;
llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); llassert(index <= LLGLSLShader::sIndexedTextureChannels-1);
LLVector4Logical mask; LLVector4Logical mask;

View File

@@ -103,6 +103,10 @@ LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect)
FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount(); FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount();
mPrintStats = -1; mPrintStats = -1;
mAverageCyclesPerTimer = 0; mAverageCyclesPerTimer = 0;
// <FS:LO> Making the ledgend part of fast timers scrollable
mOverLegend = false;
mScrollOffset = 0;
// </FS:LO>
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_fast_timers.xml"); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_fast_timers.xml");
} }
@@ -258,6 +262,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
} }
mHoverTimer = NULL; mHoverTimer = NULL;
mHoverID = NULL; mHoverID = NULL;
mOverLegend = false; // <FS:LO> Making the ledgend part of fast timers scrollable
if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
{ {
@@ -311,6 +316,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{ {
mHoverID = timer_id; mHoverID = timer_id;
} }
mOverLegend = true; // <FS:LO> Making the ledgend part of fast timers scrollable
} }
return LLFloater::handleHover(x, y, mask); return LLFloater::handleHover(x, y, mask);
@@ -358,10 +364,36 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* stic
BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{ {
LLFastTimer::sPauseHistory = TRUE; //LLFastTimer::sPauseHistory = TRUE;
mScrollIndex = llclamp( mScrollIndex + clicks, //mScrollIndex = llclamp( mScrollIndex + clicks,
0, //0,
llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); //llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
// <FS:LO> Making the ledgend part of fast timers scrollable
if(mOverLegend)
{
mScrollOffset += clicks;
S32 count = 0;
for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
it != timer_tree_iterator_t();
++it)
{
count++;
LLFastTimer::NamedTimer* idp = (*it);
if (idp->getCollapsed())
{
it.skipDescendants();
}
}
mScrollOffset = llclamp(mScrollOffset,0,count-5);
}
else
{
LLFastTimer::sPauseHistory = TRUE;
mScrollIndex = llclamp( mScrollIndex + clicks,
0,
llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
}
// </FS:LO>
return TRUE; return TRUE;
} }
@@ -479,11 +511,23 @@ void LLFastTimerView::draw()
S32 cur_line = 0; S32 cur_line = 0;
ft_display_idx.clear(); ft_display_idx.clear();
std::map<LLFastTimer::NamedTimer*, S32> display_line; std::map<LLFastTimer::NamedTimer*, S32> display_line;
S32 mScrollOffset_tmp = mScrollOffset; // <FS:LO> Making the ledgend part of fast timers scrollable
for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
it != timer_tree_iterator_t(); it != timer_tree_iterator_t();
++it) ++it)
{ {
LLFastTimer::NamedTimer* idp = (*it); LLFastTimer::NamedTimer* idp = (*it);
// <FS:LO> Making the ledgend part of fast timers scrollable
if(mScrollOffset_tmp)
{
--mScrollOffset_tmp;
if (idp->getCollapsed())
{
it.skipDescendants();
}
continue;
}
// </FS:LO>
display_line[idp] = cur_line; display_line[idp] = cur_line;
ft_display_idx.push_back(idp); ft_display_idx.push_back(idp);
cur_line++; cur_line++;

View File

@@ -99,6 +99,11 @@ private:
S32 mPrintStats; S32 mPrintStats;
S32 mAverageCyclesPerTimer; S32 mAverageCyclesPerTimer;
LLRect mGraphRect; LLRect mGraphRect;
// <FS:LO> Making the ledgend part of fast timers scrollable
bool mOverLegend;
S32 mScrollOffset;
// </FS:LO>
}; };
#endif #endif

View File

@@ -758,9 +758,13 @@ BOOL LLImagePreviewAvatar::render()
// make sure alpha=0 shows avatar material color // make sure alpha=0 shows avatar material color
LLGLDisable no_blend(GL_BLEND); LLGLDisable no_blend(GL_BLEND);
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); LLFace* face = avatarp->mDrawable->getFace(0);
gPipeline.enableLightsPreview(); if (face)
avatarPoolp->renderAvatars(avatarp); // renders only one avatar {
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool();
gPipeline.enableLightsPreview();
avatarPoolp->renderAvatars(avatarp); // renders only one avatar
}
} }
gGL.color4f(1,1,1,1); gGL.color4f(1,1,1,1);

View File

@@ -94,13 +94,6 @@ const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] =
LLManip::LL_FACE_NEGZ LLManip::LL_FACE_NEGZ
}; };
F32 get_default_max_prim_scale(bool is_flora)
{
//CF: both scales are 256, so what?, I now use gridmanagersetting
return gHippoLimits->getMaxPrimScale();
}
// static // static
void LLManipScale::setUniform(BOOL b) void LLManipScale::setUniform(BOOL b)
{ {
@@ -966,8 +959,11 @@ void LLManipScale::dragCorner( S32 x, S32 y )
mInSnapRegime = FALSE; mInSnapRegime = FALSE;
} }
F32 max_scale_factor = get_default_max_prim_scale() / MIN_PRIM_SCALE; F32 max_prim_scale = gHippoLimits->getMaxPrimScale();
F32 min_scale_factor = MIN_PRIM_SCALE / get_default_max_prim_scale(); F32 min_prim_scale = gHippoLimits->getMinPrimScale();
F32 max_scale_factor = max_prim_scale / min_prim_scale;
F32 min_scale_factor = min_prim_scale / max_prim_scale;
// find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale // find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale
for (LLObjectSelection::iterator iter = mObjectSelection->begin(); for (LLObjectSelection::iterator iter = mObjectSelection->begin();
@@ -982,10 +978,10 @@ void LLManipScale::dragCorner( S32 x, S32 y )
{ {
const LLVector3& scale = selectNode->mSavedScale; const LLVector3& scale = selectNode->mSavedScale;
F32 cur_max_scale_factor = llmin( get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VX], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VY], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VZ] ); F32 cur_max_scale_factor = llmin( max_prim_scale / scale.mV[VX], max_prim_scale / scale.mV[VY], max_prim_scale / scale.mV[VZ] );
max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor ); max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor );
F32 cur_min_scale_factor = llmax( MIN_PRIM_SCALE / scale.mV[VX], MIN_PRIM_SCALE / scale.mV[VY], MIN_PRIM_SCALE / scale.mV[VZ] ); F32 cur_min_scale_factor = llmax( min_prim_scale / scale.mV[VX], min_prim_scale / scale.mV[VY], min_prim_scale / scale.mV[VZ] );
min_scale_factor = llmax( min_scale_factor, cur_min_scale_factor ); min_scale_factor = llmax( min_scale_factor, cur_min_scale_factor );
} }
} }
@@ -1288,7 +1284,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto
F32 denom = axis * dir_local; F32 denom = axis * dir_local;
F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom); // in meters F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom); // in meters
F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_PRIM_SCALE, get_default_max_prim_scale(LLPickInfo::isFlora(cur))); F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
// propagate scale constraint back to position offset // propagate scale constraint back to position offset
desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index]; // propagate constraint back to position desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index]; // propagate constraint back to position
@@ -1989,7 +1985,7 @@ F32 LLManipScale::partToMaxScale( S32 part, const LLBBox &bbox ) const
max_extent = bbox_extents.mV[i]; max_extent = bbox_extents.mV[i];
} }
} }
max_scale_factor = bbox_extents.magVec() * get_default_max_prim_scale() / max_extent; max_scale_factor = bbox_extents.magVec() * gHippoLimits->getMaxPrimScale() / max_extent;
if (getUniform()) if (getUniform())
{ {
@@ -2004,7 +2000,7 @@ F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const
{ {
LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox ); LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox );
bbox_extents.abs(); bbox_extents.abs();
F32 min_extent = get_default_max_prim_scale(); F32 min_extent = gHippoLimits->getMaxPrimScale();
for (U32 i = VX; i <= VZ; i++) for (U32 i = VX; i <= VZ; i++)
{ {
if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent) if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent)
@@ -2012,7 +2008,7 @@ F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const
min_extent = bbox_extents.mV[i]; min_extent = bbox_extents.mV[i];
} }
} }
F32 min_scale_factor = bbox_extents.magVec() * MIN_PRIM_SCALE / min_extent; F32 min_scale_factor = bbox_extents.magVec() * gHippoLimits->getMinPrimScale() / min_extent;
if (getUniform()) if (getUniform())
{ {

View File

@@ -46,8 +46,6 @@
#include "llbbox.h" #include "llbbox.h"
F32 get_default_max_prim_scale(bool is_flora = false);
class LLToolComposite; class LLToolComposite;
class LLColor4; class LLColor4;

View File

@@ -1104,19 +1104,24 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
mMeshHeader[mesh_id] = header; mMeshHeader[mesh_id] = header;
} }
LLMutexLock lock(mMutex); // <FS:ND/> FIRE-7182, make sure only one thread access mPendingLOD at the same time.
//check for pending requests //check for pending requests
pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
if (iter != mPendingLOD.end()) if (iter != mPendingLOD.end())
{ {
LLMutexLock lock(mMutex); // LLMutexLock lock(mMutex); <FS:ND/> FIRE-7182, lock was moved up, before calling mPendingLOD.find
for (U32 i = 0; i < iter->second.size(); ++i) for (U32 i = 0; i < iter->second.size(); ++i)
{ {
LODRequest req(mesh_params, iter->second[i]); LODRequest req(mesh_params, iter->second[i]);
mLODReqQ.push(req); mLODReqQ.push(req);
LLMeshRepository::sLODProcessing++; LLMeshRepository::sLODProcessing++;
} }
mPendingLOD.erase(iter); // <FS:ND/> FIRE-7182, only call erase if iter is really valid.
} }
mPendingLOD.erase(iter); // mPendingLOD.erase(iter); // <FS:ND/> avoid crash by moving erase up.
} }
return true; return true;

View File

@@ -876,6 +876,10 @@ void LLPanelDisplay::cancel()
void LLPanelDisplay::apply() void LLPanelDisplay::apply()
{ {
U32 fsaa_value = childGetValue("fsaa").asInteger();
bool apply_fsaa_change = !gSavedSettings.getBOOL("RenderUseFBO") && (mFSAASamples != fsaa_value);
gSavedSettings.setU32("RenderFSAASamples", fsaa_value);
applyResolution(); applyResolution();
// Only set window size if we're not in fullscreen mode // Only set window size if we're not in fullscreen mode
@@ -887,7 +891,7 @@ void LLPanelDisplay::apply()
// Hardware tab // Hardware tab
//Still do a bit of voodoo here. V2 forces restart to change FSAA with FBOs off. //Still do a bit of voodoo here. V2 forces restart to change FSAA with FBOs off.
//Let's not do that, and instead do pre-V2 FSAA change handling for that particular case //Let's not do that, and instead do pre-V2 FSAA change handling for that particular case
if(!LLRenderTarget::sUseFBO && (mFSAASamples != (U32)childGetValue("fsaa").asInteger())) if(apply_fsaa_change)
{ {
bool logged_in = (LLStartUp::getStartupState() >= STATE_STARTED); bool logged_in = (LLStartUp::getStartupState() >= STATE_STARTED);
LLWindow* window = gViewerWindow->getWindow(); LLWindow* window = gViewerWindow->getWindow();

View File

@@ -550,6 +550,9 @@ void LLPanelObject::getState( )
mCtrlScaleX->setMaxValue(gHippoLimits->getMaxPrimScale()); mCtrlScaleX->setMaxValue(gHippoLimits->getMaxPrimScale());
mCtrlScaleY->setMaxValue(gHippoLimits->getMaxPrimScale()); mCtrlScaleY->setMaxValue(gHippoLimits->getMaxPrimScale());
mCtrlScaleZ->setMaxValue(gHippoLimits->getMaxPrimScale()); mCtrlScaleZ->setMaxValue(gHippoLimits->getMaxPrimScale());
mCtrlScaleX->setMinValue(gHippoLimits->getMinPrimScale());
mCtrlScaleY->setMinValue(gHippoLimits->getMinPrimScale());
mCtrlScaleZ->setMinValue(gHippoLimits->getMinPrimScale());
LLQuaternion object_rot = objectp->getRotationEdit(); LLQuaternion object_rot = objectp->getRotationEdit();
object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ])); object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ]));
@@ -2537,9 +2540,9 @@ void LLPanelObject::onPasteSize(void* user_data)
LLPanelObject* self = (LLPanelObject*) user_data; LLPanelObject* self = (LLPanelObject*) user_data;
LLCalc* calcp = LLCalc::getInstance(); LLCalc* calcp = LLCalc::getInstance();
mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
self->mCtrlScaleX->set( mClipboardSize.mV[VX] ); self->mCtrlScaleX->set( mClipboardSize.mV[VX] );
self->mCtrlScaleY->set( mClipboardSize.mV[VY] ); self->mCtrlScaleY->set( mClipboardSize.mV[VY] );
@@ -2620,9 +2623,9 @@ void LLPanelObject::onPasteSizeClip(void* user_data)
std::string stringVec = wstring_to_utf8str(temp_string); std::string stringVec = wstring_to_utf8str(temp_string);
if(!getvectorfromclip(stringVec, &mClipboardSize)) return; if(!getvectorfromclip(stringVec, &mClipboardSize)) return;
mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], 0.01f, gHippoLimits->getMaxPrimScale()); mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], gHippoLimits->getMinPrimScale(), gHippoLimits->getMaxPrimScale());
self->mCtrlScaleX->set( mClipboardSize.mV[VX] ); self->mCtrlScaleX->set( mClipboardSize.mV[VX] );
self->mCtrlScaleY->set( mClipboardSize.mV[VY] ); self->mCtrlScaleY->set( mClipboardSize.mV[VY] );

View File

@@ -389,7 +389,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj,
// don't include an avatar. // don't include an avatar.
LLViewerObject* root = obj; LLViewerObject* root = obj;
while(!root->isAvatar() && root->getParent() && !root->isJointChild()) while(!root->isAvatar() && root->getParent())
{ {
LLViewerObject* parent = (LLViewerObject*)root->getParent(); LLViewerObject* parent = (LLViewerObject*)root->getParent();
if (parent->isAvatar()) if (parent->isAvatar())
@@ -704,7 +704,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s
// don't include an avatar. // don't include an avatar.
LLViewerObject* root = object; LLViewerObject* root = object;
while(!root->isAvatar() && root->getParent() && !root->isJointChild()) while(!root->isAvatar() && root->getParent())
{ {
LLViewerObject* parent = (LLViewerObject*)root->getParent(); LLViewerObject* parent = (LLViewerObject*)root->getParent();
if (parent->isAvatar()) if (parent->isAvatar())
@@ -1419,7 +1419,7 @@ void LLSelectMgr::promoteSelectionToRoot()
} }
LLViewerObject* parentp = object; LLViewerObject* parentp = object;
while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild())) while(parentp->getParent() && !(parentp->isRootEdit()))
{ {
parentp = (LLViewerObject*)parentp->getParent(); parentp = (LLViewerObject*)parentp->getParent();
} }
@@ -4468,8 +4468,7 @@ struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor
virtual bool apply(LLViewerObject* object) virtual bool apply(LLViewerObject* object)
{ {
if ( object->permModify() && // preemptive permissions check if ( object->permModify() && // preemptive permissions check
object->isRoot() && // don't send for child objects object->isRoot()) // don't send for child objects
!object->isJointChild())
{ {
object->setFlags( mFlags, mState); object->setFlags( mFlags, mState);
} }
@@ -6302,8 +6301,6 @@ void LLSelectMgr::updateSelectionCenter()
// matches the root prim's (affecting the orientation of the manipulators). // matches the root prim's (affecting the orientation of the manipulators).
bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() ); bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() );
std::vector < LLViewerObject *> jointed_objects;
for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
iter != mSelectedObjects->end(); iter++) iter != mSelectedObjects->end(); iter++)
{ {
@@ -6321,17 +6318,11 @@ void LLSelectMgr::updateSelectionCenter()
} }
bbox.addBBoxAgent( object->getBoundingBoxAgent() ); bbox.addBBoxAgent( object->getBoundingBoxAgent() );
if (object->isJointChild())
{
jointed_objects.push_back(object);
}
} }
LLVector3 bbox_center_agent = bbox.getCenterAgent(); LLVector3 bbox_center_agent = bbox.getCenterAgent();
mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent);
mSelectionBBox = bbox; mSelectionBBox = bbox;
} }
if ( !(gAgentID == LLUUID::null)) if ( !(gAgentID == LLUUID::null))
@@ -6625,19 +6616,19 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
bool LLObjectSelection::is_root::operator()(LLSelectNode *node) bool LLObjectSelection::is_root::operator()(LLSelectNode *node)
{ {
LLViewerObject* object = node->getObject(); LLViewerObject* object = node->getObject();
return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit());
} }
bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node) bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)
{ {
LLViewerObject* object = node->getObject(); LLViewerObject* object = node->getObject();
return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit());
} }
bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node) bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)
{ {
LLViewerObject* object = node->getObject(); LLViewerObject* object = node->getObject();
return (object != NULL) && (object->isRootEdit() || object->isJointChild()); return (object != NULL) && (object->isRootEdit());
} }
LLObjectSelection::LLObjectSelection() : LLObjectSelection::LLObjectSelection() :

View File

@@ -245,7 +245,8 @@ BOOL LLVisualParamHint::render()
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
if (gAgentAvatarp->mDrawable.notNull()) if (gAgentAvatarp->mDrawable.notNull() &&
gAgentAvatarp->mDrawable->getFace(0))
{ {
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool();
LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);

View File

@@ -951,9 +951,47 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
{ {
LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
LLCachedControl<bool> render_depth_pre_pass("RenderDepthPrePass", false); static LLCachedControl<bool> render_ui_occlusion("RenderUIOcclusion", false);
if(render_ui_occlusion && LLGLSLShader::sNoFixedFunction)
{
LLFloater* floaterp = gFloaterView->getFrontmost();
if(floaterp && floaterp->getVisible() && floaterp->isBackgroundVisible() && floaterp->isBackgroundOpaque())
{
LLGLDepthTest depth(GL_TRUE, GL_TRUE);
gGL.setColorMask(false, false);
gOcclusionProgram.bind();
LLRect rect = floaterp->calcScreenRect();
rect.stretch(-1);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadIdentity();
gGL.ortho(0.0f, gViewerWindow->getWindowWidth(), 0.0f, gViewerWindow->getWindowHeight(), 0.f, 1.0f);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
gGL.loadIdentity();
gGL.color4fv( LLColor4::white.mV );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin( LLRender::QUADS );
gGL.vertex3f(rect.mLeft, rect.mTop,0.f);
gGL.vertex3f(rect.mLeft, rect.mBottom,0.f);
gGL.vertex3f(rect.mRight, rect.mBottom,0.f);
gGL.vertex3f(rect.mRight, rect.mTop,0.f);
gGL.end();
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
gOcclusionProgram.unbind();
}
}
static LLCachedControl<bool> render_depth_pre_pass("RenderDepthPrePass", false);
if (render_depth_pre_pass && LLGLSLShader::sNoFixedFunction) if (render_depth_pre_pass && LLGLSLShader::sNoFixedFunction)
{ {
LLGLDepthTest depth(GL_TRUE, GL_TRUE);
LLGLEnable cull_face(GL_CULL_FACE);
gGL.setColorMask(false, false); gGL.setColorMask(false, false);
U32 types[] = { U32 types[] = {
@@ -968,11 +1006,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
{ {
gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
} }
gOcclusionProgram.unbind(); gOcclusionProgram.unbind();
} }
gGL.setColorMask(true, false); gGL.setColorMask(true, false);
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{ {

View File

@@ -241,7 +241,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mNumFaces(0), mNumFaces(0),
mTimeDilation(1.f), mTimeDilation(1.f),
mRotTime(0.f), mRotTime(0.f),
mJointInfo(NULL), mAngularVelocityRot(),
mState(0), mState(0),
mMedia(NULL), mMedia(NULL),
mClickAction(0), mClickAction(0),
@@ -271,6 +271,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
{ {
mPositionAgent = mRegionp->getOriginAgent(); mPositionAgent = mRegionp->getOriginAgent();
} }
resetRot();
LLViewerObject::sNumObjects++; LLViewerObject::sNumObjects++;
} }
@@ -286,12 +287,6 @@ LLViewerObject::~LLViewerObject()
mInventory = NULL; mInventory = NULL;
} }
if (mJointInfo)
{
delete mJointInfo;
mJointInfo = NULL;
}
if (mPartSourcep) if (mPartSourcep)
{ {
mPartSourcep->setDead(); mPartSourcep->setDead();
@@ -345,9 +340,6 @@ void LLViewerObject::markDead()
if (getParent()) if (getParent())
{ {
((LLViewerObject *)getParent())->removeChild(this); ((LLViewerObject *)getParent())->removeChild(this);
// go ahead and delete any jointinfo's that we find
delete mJointInfo;
mJointInfo = NULL;
} }
// Mark itself as dead // Mark itself as dead
@@ -764,7 +756,7 @@ void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& ob
iter != mChildList.end(); ++iter) iter != mChildList.end(); ++iter)
{ {
LLViewerObject* child = *iter; LLViewerObject* child = *iter;
if ( (!child->isAvatar()) && (!child->isJointChild())) if ( (!child->isAvatar()))
{ {
child->addThisAndNonJointChildren(objects); child->addThisAndNonJointChildren(objects);
} }
@@ -1326,27 +1318,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
parameterChanged(iter->first, iter->second->data, FALSE, false); parameterChanged(iter->first, iter->second->data, FALSE, false);
} }
} }
U8 joint_type = 0;
mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num);
if (joint_type)
{
// create new joint info
if (!mJointInfo)
{
mJointInfo = new LLVOJointInfo;
}
mJointInfo->mJointType = (EHavokJointType) joint_type;
mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num);
mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num);
}
else if (mJointInfo)
{
// this joint info is no longer needed
delete mJointInfo;
mJointInfo = NULL;
}
break; break;
} }
@@ -2035,14 +2006,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
cur_parentp->removeChild(this); cur_parentp->removeChild(this);
if (mJointInfo && !parent_id)
{
// since this object is no longer parent-relative
// we make sure we delete any joint info
delete mJointInfo;
mJointInfo = NULL;
}
setChanged(MOVED | SILHOUETTE); setChanged(MOVED | SILHOUETTE);
if (mDrawable.notNull()) if (mDrawable.notNull())
@@ -2144,14 +2107,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (new_rot != getRotation() if (new_rot != getRotation()
|| new_angv != old_angv) || new_angv != old_angv)
{ {
if (new_rot != getRotation()) if (new_angv != old_angv)
{ {
setRotation(new_rot); resetRot();
} }
// Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega)
setRotation(new_rot * mAngularVelocityRot);
setChanged(ROTATED | SILHOUETTE); setChanged(ROTATED | SILHOUETTE);
resetRot();
} }
@@ -2264,85 +2227,9 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
F32 dt = mTimeDilation * dt_raw; F32 dt = mTimeDilation * dt_raw;
if (!mJointInfo) applyAngularVelocity(dt);
{
applyAngularVelocity(dt);
}
LLViewerObject *parentp = (LLViewerObject *) getParent(); if (isAttachment())
if (mJointInfo)
{
if (parentp)
{
// do parent-relative stuff
LLVector3 ang_vel = getAngularVelocity();
F32 omega = ang_vel.magVecSquared();
F32 angle = 0.0f;
LLQuaternion dQ;
if (omega > 0.00001f)
{
omega = sqrt(omega);
angle = omega * dt;
dQ.setQuat(angle, ang_vel);
}
LLVector3 pos = getPosition();
if (HJT_HINGE == mJointInfo->mJointType)
{
// hinge = uniform circular motion
LLVector3 parent_pivot = getVelocity();
LLVector3 parent_axis = getAcceleration();
angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
dQ.setQuat(angle, mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
LLVector3 pivot_offset = pos - mJointInfo->mPivot; // pos in pivot-frame
pivot_offset = pivot_offset * dQ; // new rotated pivot-frame pos
pos = mJointInfo->mPivot + pivot_offset; // parent-frame
LLViewerObject::setPosition(pos);
LLQuaternion Q_PC = getRotation();
setRotation(Q_PC * dQ);
mLastInterpUpdateSecs = time;
}
else if (HJT_POINT == mJointInfo->mJointType)
// || HJT_LPOINT == mJointInfo->mJointType)
{
// point-to-point = spin about axis and uniform circular motion
// of axis about the pivot point
//
// NOTE: this interpolation scheme is not quite good enough to
// reduce the bandwidth -- needs a gravitational correction.
// Similarly for hinges with axes that deviate from vertical.
LLQuaternion Q_PC = getRotation();
Q_PC = Q_PC * dQ;
setRotation(Q_PC);
LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor; // AxisOrAnchor = anchor
pos = mJointInfo->mPivot + pivot_to_child * Q_PC;
LLViewerObject::setPosition(pos);
mLastInterpUpdateSecs = time;
}
/* else if (HJT_WHEEL == mJointInfo->mJointInfo)
{
// wheel = uniform rotation about axis, with linear
// velocity interpolation (if any)
LLVector3 parent_axis = getAcceleration(); // HACK -- accel stores the parent-axis (parent-frame)
LLQuaternion Q_PC = getRotation();
angle = dt * (parent_axis * ang_vel);
dQ.setQuat(angle, parent_axis);
Q_PC = Q_PC * dQ;
setRotation(Q_PC);
pos = getPosition() + dt * getVelocity();
LLViewerObject::setPosition(pos);
mLastInterpUpdateSecs = time;
}*/
}
}
else if (isAttachment())
{ {
mLastInterpUpdateSecs = time; mLastInterpUpdateSecs = time;
return TRUE; return TRUE;
@@ -3951,15 +3838,6 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset); ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);
updateDrawable(damped); updateDrawable(damped);
} }
else if (isJointChild())
{
// compute new parent-relative position
LLViewerObject *parent = (LLViewerObject *) getParent();
LLQuaternion inv_parent_rot = parent->getRotation();
inv_parent_rot.transQuat();
LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot;
LLViewerObject::setPosition(pos_parent, damped);
}
else else
{ {
LLViewerObject::setPosition(pos_edit, damped); LLViewerObject::setPosition(pos_edit, damped);
@@ -3973,8 +3851,7 @@ LLViewerObject* LLViewerObject::getRootEdit() const
{ {
const LLViewerObject* root = this; const LLViewerObject* root = this;
while (root->mParent while (root->mParent
&& !(root->mJointInfo && !((LLViewerObject*)root->mParent)->isAvatar())
|| ((LLViewerObject*)root->mParent)->isAvatar()) )
{ {
root = (LLViewerObject*)root->mParent; root = (LLViewerObject*)root->mParent;
} }
@@ -4710,19 +4587,11 @@ void LLViewerObject::clearIcon()
LLViewerObject* LLViewerObject::getSubParent() LLViewerObject* LLViewerObject::getSubParent()
{ {
if (isJointChild())
{
return this;
}
return (LLViewerObject*) getParent(); return (LLViewerObject*) getParent();
} }
const LLViewerObject* LLViewerObject::getSubParent() const const LLViewerObject* LLViewerObject::getSubParent() const
{ {
if (isJointChild())
{
return this;
}
return (const LLViewerObject*) getParent(); return (const LLViewerObject*) getParent();
} }
@@ -5631,8 +5500,13 @@ void LLViewerObject::applyAngularVelocity(F32 dt)
ang_vel *= 1.f/omega; ang_vel *= 1.f/omega;
// calculate the delta increment based on the object's angular velocity
dQ.setQuat(angle, ang_vel); dQ.setQuat(angle, ang_vel);
// accumulate the angular velocity rotations to re-apply in the case of an object update
mAngularVelocityRot *= dQ;
// Just apply the delta increment to the current rotation
setRotation(getRotation()*dQ); setRotation(getRotation()*dQ);
setChanged(MOVED | SILHOUETTE); setChanged(MOVED | SILHOUETTE);
} }
@@ -5641,6 +5515,9 @@ void LLViewerObject::applyAngularVelocity(F32 dt)
void LLViewerObject::resetRot() void LLViewerObject::resetRot()
{ {
mRotTime = 0.0f; mRotTime = 0.0f;
// Reset the accumulated angular velocity rotation
mAngularVelocityRot.loadIdentity();
} }
U32 LLViewerObject::getPartitionType() const U32 LLViewerObject::getPartitionType() const

View File

@@ -93,18 +93,6 @@ typedef void (*inventory_callback)(LLViewerObject*,
S32 serial_num, S32 serial_num,
void*); void*);
// a small struct for keeping track of joints
struct LLVOJointInfo
{
EHavokJointType mJointType;
LLVector3 mPivot; // parent-frame
// whether the below an axis or anchor (and thus its frame)
// depends on the joint type:
// HINGE ==> axis=parent-frame
// P2P ==> anchor=child-frame
LLVector3 mAxisOrAnchor;
};
// for exporting textured materials from SL // for exporting textured materials from SL
struct LLMaterialExportInfo struct LLMaterialExportInfo
{ {
@@ -192,8 +180,6 @@ public:
virtual void updateRadius() {}; virtual void updateRadius() {};
virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius()
BOOL isJointChild() const { return mJointInfo ? TRUE : FALSE; }
EHavokJointType getJointType() const { return mJointInfo ? mJointInfo->mJointType : HJT_INVALID; }
// for jointed and other parent-relative hacks // for jointed and other parent-relative hacks
LLViewerObject* getSubParent(); LLViewerObject* getSubParent();
const LLViewerObject* getSubParent() const; const LLViewerObject* getSubParent() const;
@@ -750,8 +736,8 @@ protected:
F32 mTimeDilation; // Time dilation sent with the object. F32 mTimeDilation; // Time dilation sent with the object.
F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)
LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations
LLVOJointInfo* mJointInfo;
U8 mState; // legacy U8 mState; // legacy
LLViewerObjectMedia* mMedia; // NULL if no media associated LLViewerObjectMedia* mMedia; // NULL if no media associated
U8 mClickAction; U8 mClickAction;

View File

@@ -1113,7 +1113,7 @@ LLVoiceClient::LLVoiceClient()
gVoiceClient = this; gVoiceClient = this;
mWriteInProgress = false; mWriteInProgress = false;
mAreaVoiceDisabled = false; mAreaVoiceDisabled = false;
mPTT = true; mPTT = false;
mUserPTTState = false; mUserPTTState = false;
mMuteMic = false; mMuteMic = false;
mSessionTerminateRequested = false; mSessionTerminateRequested = false;

View File

@@ -1044,9 +1044,9 @@ BOOL LLVOVolume::calcLOD()
F32 radius; F32 radius;
F32 distance; F32 distance;
if (mDrawable->isState(LLDrawable::RIGGED) && getAvatar()) if (mDrawable->isState(LLDrawable::RIGGED) && getAvatar() && getAvatar()->mDrawable)
{ {
LLVOAvatar* avatar = getAvatar(); LLVOAvatar* avatar = getAvatar();
distance = avatar->mDrawable->mDistanceWRTCamera; distance = avatar->mDrawable->mDistanceWRTCamera;
radius = avatar->getBinRadius(); radius = avatar->getBinRadius();
} }

View File

@@ -45,6 +45,22 @@ void M7WindlightInterface::receiveMessage(LLMessageSystem* msg)
_PREHASH_ParamList, _PREHASH_Parameter, _PREHASH_ParamList, _PREHASH_Parameter,
buf, size, i, 249); buf, size, i, 249);
#if 0
std::ostringstream wldump;
char hex []= "0123456789abcdefRRRR";
for (int i = 0; i<250; ++i){
wldump << "\\x" << hex[((U8)buf[i]&0xF0)>>4] << hex[(U8)buf[i]&0x0F];
}
llinfos << "Received LightShare data: " << wldump.str() << llendl;
#endif
char default_windlight[] = "\x00\x00\x80\x40\x00\x00\x18\x42\x00\x00\x80\x42\x00\x00\x80\x40\x00\x00\x80\x3e\x00\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x40\xcd\xcc\xcc\x3e\x00\x00\x00\x3f\x8f\xc2\xf5\x3c\xcd\xcc\x4c\x3e\x0a\xd7\x23\x3d\x66\x66\x86\x3f\x3d\x0a\xd7\xbe\x7b\x14\x8e\x3f\xe1\x7a\x94\xbf\x82\x2d\xed\x49\x9a\x6c\xf6\x1c\xcb\x89\x6d\xf5\x4f\x42\xcd\xf4\x00\x00\x80\x3e\x00\x00\x80\x3e\x0a\xd7\xa3\x3e\x0a\xd7\xa3\x3e\x5c\x8f\x42\x3e\x8f\xc2\xf5\x3d\xae\x47\x61\x3e\x5c\x8f\xc2\x3e\x5c\x8f\xc2\x3e\x33\x33\x33\x3f\xec\x51\x38\x3e\xcd\xcc\x4c\x3f\x8f\xc2\x75\x3e\xb8\x1e\x85\x3e\x9a\x99\x99\x3e\x9a\x99\x99\x3e\xd3\x4d\xa2\x3e\x33\x33\xb3\x3e\x33\x33\xb3\x3e\x33\x33\xb3\x3e\x33\x33\xb3\x3e\x00\x00\x00\x00\xcd\xcc\xcc\x3d\x00\x00\xe0\x3f\x00\x00\x80\x3f\x00\x00\x00\x00\x85\xeb\xd1\x3e\x85\xeb\xd1\x3e\x85\xeb\xd1\x3e\x85\xeb\xd1\x3e\x00\x00\x80\x3f\x14\xae\x07\x3f\x00\x00\x80\x3f\x71\x3d\x8a\x3e\x3d\x0a\xd7\x3e\x00\x00\x80\x3f\x14\xae\x07\x3f\x8f\xc2\xf5\x3d\xcd\xcc\x4c\x3e\x0a\xd7\x23\x3c\x45\x06\x00";
if(!memcmp(default_windlight, buf, sizeof(default_windlight)))
{
llinfos << "LightShare matches default" << llendl;
receiveReset();
return;
}
LLWaterParamManager::getInstance()->getParamSet("Default", mWater); LLWaterParamManager::getInstance()->getParamSet("Default", mWater);
Meta7WindlightPacket* wl = (Meta7WindlightPacket*)buf; Meta7WindlightPacket* wl = (Meta7WindlightPacket*)buf;
@@ -120,6 +136,7 @@ void M7WindlightInterface::receiveMessage(LLMessageSystem* msg)
void M7WindlightInterface::receiveReset() void M7WindlightInterface::receiveReset()
{ {
llinfos << "Received LightShare reset" << llendl;
mHasOverride = false; mHasOverride = false;
LLEnvManagerNew::getInstance()->usePrefs(); LLEnvManagerNew::getInstance()->usePrefs();
} }

View File

@@ -31,6 +31,9 @@
#include "linden_common.h" #include "linden_common.h"
#pragma pack(push)
#pragma pack(1)
struct M7Color3{ struct M7Color3{
M7Color3(){}; M7Color3(){};
M7Color3(F32 pRed, F32 pGreen, F32 pBlue) M7Color3(F32 pRed, F32 pGreen, F32 pBlue)
@@ -124,8 +127,8 @@ struct Meta7WindlightPacket {
char cloudScrollXLock; char cloudScrollXLock;
char cloudScrollYLock; char cloudScrollYLock;
char drawClassicClouds; char drawClassicClouds;
}; };
#pragma pack(pop)
#endif #endif

View File

@@ -6571,15 +6571,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
} }
else else
{ {
LLViewerObject* obj = gAgentCamera.getFocusObject(); //focus on alt-zoom target
if (obj) focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
{ //focus on alt-zoom target
focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
}
else
{ //focus on your avatar
focus_point = gAgent.getPositionAgent();
}
} }
} }

View File

@@ -112,7 +112,7 @@
<panel border="true" bottom="-400" height="244" left="50" name="Hardware" label="Hardware" width="500"> <panel border="true" bottom="-400" height="244" left="50" name="Hardware" label="Hardware" width="500">
<check_box bottom="-22" control_name="RenderAnisotropic" height="16" initial_value="false" label="Anisotropic Filtering (slower when enabled)" left="5" name="ani" width="256"/> <check_box bottom="-22" control_name="RenderAnisotropic" height="16" initial_value="false" label="Anisotropic Filtering (slower when enabled)" left="5" name="ani" width="256"/>
<text bottom="-37" height="12" left="10" name="Antialiasing:" width="128">Antialiasing:</text> <text bottom="-37" height="12" left="10" name="Antialiasing:" width="128">Antialiasing:</text>
<combo_box bottom="-41" control_name="RenderFSAASamples" height="16" initial_value="false" label="Antialiasing" left="148" name="fsaa" width="64"> <combo_box bottom="-41" height="16" initial_value="false" label="Antialiasing" left="148" name="fsaa" width="64">
<combo_item name="FSAADisabled" value="0">Disabled</combo_item> <combo_item name="FSAADisabled" value="0">Disabled</combo_item>
<combo_item name="2x" value="2">2x</combo_item> <combo_item name="2x" value="2">2x</combo_item>
<combo_item name="4x" value="4">4x</combo_item> <combo_item name="4x" value="4">4x</combo_item>

View File

@@ -44,35 +44,35 @@ extern LLControlGroup gSavedSettings;
// Local variables. // Local variables.
namespace { namespace {
struct QueueElementComp; struct QueueElementComp;
class QueueElement { class QueueElement {
private: private:
AIStateMachine* mStateMachine; AIStateMachine* mStateMachine;
U64 mRuntime; U64 mRuntime;
public: public:
QueueElement(AIStateMachine* statemachine) : mStateMachine(statemachine), mRuntime(0) { } QueueElement(AIStateMachine* statemachine) : mStateMachine(statemachine), mRuntime(0) { }
friend bool operator==(QueueElement const& e1, QueueElement const& e2) { return e1.mStateMachine == e2.mStateMachine; } friend bool operator==(QueueElement const& e1, QueueElement const& e2) { return e1.mStateMachine == e2.mStateMachine; }
friend struct QueueElementComp; friend struct QueueElementComp;
AIStateMachine& statemachine(void) const { return *mStateMachine; } AIStateMachine& statemachine(void) const { return *mStateMachine; }
void add(U64 count) { mRuntime += count; } void add(U64 count) { mRuntime += count; }
}; };
struct QueueElementComp { struct QueueElementComp {
bool operator()(QueueElement const& e1, QueueElement const& e2) const { return e1.mRuntime < e2.mRuntime; } bool operator()(QueueElement const& e1, QueueElement const& e2) const { return e1.mRuntime < e2.mRuntime; }
}; };
typedef std::vector<QueueElement> active_statemachines_type; typedef std::vector<QueueElement> active_statemachines_type;
active_statemachines_type active_statemachines; active_statemachines_type active_statemachines;
typedef std::vector<AIStateMachine*> continued_statemachines_type; typedef std::vector<AIStateMachine*> continued_statemachines_type;
struct cscm_type struct cscm_type
{ {
continued_statemachines_type continued_statemachines; continued_statemachines_type continued_statemachines;
bool calling_mainloop; bool calling_mainloop;
}; };
AIThreadSafeDC<cscm_type> continued_statemachines_and_calling_mainloop; AIThreadSafeDC<cscm_type> continued_statemachines_and_calling_mainloop;
} }
// static // static
@@ -80,8 +80,8 @@ AIThreadSafeSimpleDC<U64> AIStateMachine::sMaxCount;
void AIStateMachine::updateSettings(void) void AIStateMachine::updateSettings(void)
{ {
Dout(dc::statemachine, "Initializing AIStateMachine::sMaxCount"); Dout(dc::statemachine, "Initializing AIStateMachine::sMaxCount");
*AIAccess<U64>(sMaxCount) = calc_clock_frequency() * gSavedSettings.getU32("StateMachineMaxTime") / 1000; *AIAccess<U64>(sMaxCount) = calc_clock_frequency() * gSavedSettings.getU32("StateMachineMaxTime") / 1000;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -91,70 +91,70 @@ void AIStateMachine::updateSettings(void)
void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent) void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::run(" << (void*)parent << ", " << (parent ? parent->state_str(new_parent_state) : "NA") << ", " << abort_parent << ") [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::run(" << (void*)parent << ", " << (parent ? parent->state_str(new_parent_state) : "NA") << ", " << abort_parent << ") [" << (void*)this << "]");
// Must be the first time we're being run, or we must be called from a callback function. // Must be the first time we're being run, or we must be called from a callback function.
llassert(!mParent || mState == bs_callback); llassert(!mParent || mState == bs_callback);
llassert(!mCallback || mState == bs_callback); llassert(!mCallback || mState == bs_callback);
// Can only be run when in this state. // Can only be run when in this state.
llassert(mState == bs_initialize || mState == bs_callback); llassert(mState == bs_initialize || mState == bs_callback);
// Allow NULL to be passed as parent to signal that we want to reuse the old one. // Allow NULL to be passed as parent to signal that we want to reuse the old one.
if (parent) if (parent)
{ {
mParent = parent; mParent = parent;
// In that case remove any old callback! // In that case remove any old callback!
if (mCallback) if (mCallback)
{ {
delete mCallback; delete mCallback;
mCallback = NULL; mCallback = NULL;
} }
mNewParentState = new_parent_state; mNewParentState = new_parent_state;
mAbortParent = abort_parent; mAbortParent = abort_parent;
} }
// If abort_parent is requested then a parent must be provided. // If abort_parent is requested then a parent must be provided.
llassert(!abort_parent || mParent); llassert(!abort_parent || mParent);
// If a parent is provided, it must be running. // If a parent is provided, it must be running.
llassert(!mParent || mParent->mState == bs_run); llassert(!mParent || mParent->mState == bs_run);
// Mark that run() has been called, in case we're being called from a callback function. // Mark that run() has been called, in case we're being called from a callback function.
mState = bs_initialize; mState = bs_initialize;
cont(); cont();
} }
void AIStateMachine::run(callback_type::signal_type::slot_type const& slot) void AIStateMachine::run(callback_type::signal_type::slot_type const& slot)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::run(<slot>) [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::run(<slot>) [" << (void*)this << "]");
// Must be the first time we're being run, or we must be called from a callback function. // Must be the first time we're being run, or we must be called from a callback function.
llassert(!mParent || mState == bs_callback); llassert(!mParent || mState == bs_callback);
llassert(!mCallback || mState == bs_callback); llassert(!mCallback || mState == bs_callback);
// Can only be run when in this state. // Can only be run when in this state.
llassert(mState == bs_initialize || mState == bs_callback); llassert(mState == bs_initialize || mState == bs_callback);
// Clean up any old callbacks. // Clean up any old callbacks.
mParent = NULL; mParent = NULL;
if (mCallback) if (mCallback)
{ {
delete mCallback; delete mCallback;
mCallback = NULL; mCallback = NULL;
} }
mCallback = new callback_type(slot); mCallback = new callback_type(slot);
// Mark that run() has been called, in case we're being called from a callback function. // Mark that run() has been called, in case we're being called from a callback function.
mState = bs_initialize; mState = bs_initialize;
cont(); cont();
} }
void AIStateMachine::idle(void) void AIStateMachine::idle(void)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::idle() [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::idle() [" << (void*)this << "]");
llassert(!mIdle); llassert(!mIdle);
mIdle = true; mIdle = true;
mSleep = 0; mSleep = 0;
} }
// About thread safeness: // About thread safeness:
@@ -168,149 +168,149 @@ void AIStateMachine::idle(void)
void AIStateMachine::cont(void) void AIStateMachine::cont(void)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]");
llassert(mIdle); llassert(mIdle);
// Atomic test mActive and change mIdle. // Atomic test mActive and change mIdle.
mIdleActive.lock(); mIdleActive.lock();
mIdle = false; mIdle = false;
bool not_active = mActive == as_idle; bool not_active = mActive == as_idle;
mIdleActive.unlock(); mIdleActive.unlock();
if (not_active) if (not_active)
{ {
AIWriteAccess<cscm_type> cscm_w(continued_statemachines_and_calling_mainloop); AIWriteAccess<cscm_type> cscm_w(continued_statemachines_and_calling_mainloop);
// We only get here when the statemachine was idle (set by the main thread), // We only get here when the statemachine was idle (set by the main thread),
// see first assertion. Hence, the main thread is not changing this, as the // see first assertion. Hence, the main thread is not changing this, as the
// statemachine is not running. Thus, mActive can have changed when a THIRD // statemachine is not running. Thus, mActive can have changed when a THIRD
// thread called cont(), which is not allowed: if two threads can call cont() // thread called cont(), which is not allowed: if two threads can call cont()
// at any moment then the first assertion can't hold. // at any moment then the first assertion can't hold.
llassert_always(mActive == as_idle); llassert_always(mActive == as_idle);
cscm_w->continued_statemachines.push_back(this); cscm_w->continued_statemachines.push_back(this);
if (!cscm_w->calling_mainloop) if (!cscm_w->calling_mainloop)
{ {
Dout(dc::statemachine, "Adding AIStateMachine::mainloop to gIdleCallbacks"); Dout(dc::statemachine, "Adding AIStateMachine::mainloop to gIdleCallbacks");
cscm_w->calling_mainloop = true; cscm_w->calling_mainloop = true;
gIdleCallbacks.addFunction(&AIStateMachine::mainloop); gIdleCallbacks.addFunction(&AIStateMachine::mainloop);
} }
mActive = as_queued; mActive = as_queued;
llassert_always(!mIdle); // It should never happen that one thread calls cont() while another calls idle() concurrently. llassert_always(!mIdle); // It should never happen that one thread calls cont() while another calls idle() concurrently.
} }
} }
void AIStateMachine::set_state(state_type state) void AIStateMachine::set_state(state_type state)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::set_state(" << state_str(state) << ") [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::set_state(" << state_str(state) << ") [" << (void*)this << "]");
llassert(mState == bs_run); llassert(mState == bs_run);
if (mRunState != state) if (mRunState != state)
{ {
mRunState = state; mRunState = state;
Dout(dc::statemachine, "mRunState set to " << state_str(mRunState)); Dout(dc::statemachine, "mRunState set to " << state_str(mRunState));
} }
if (mIdle) if (mIdle)
cont(); cont();
} }
void AIStateMachine::abort(void) void AIStateMachine::abort(void)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::abort() [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::abort() [" << (void*)this << "]");
llassert(mState == bs_run); llassert(mState == bs_run);
mState = bs_abort; mState = bs_abort;
abort_impl(); abort_impl();
mAborted = true; mAborted = true;
finish(); finish();
} }
void AIStateMachine::finish(void) void AIStateMachine::finish(void)
{ {
DoutEntering(dc::statemachine, "AIStateMachine::finish() [" << (void*)this << "]"); DoutEntering(dc::statemachine, "AIStateMachine::finish() [" << (void*)this << "]");
llassert(mState == bs_run || mState == bs_abort); llassert(mState == bs_run || mState == bs_abort);
// It is possible that mIdle is true when abort or finish was called from // It is possible that mIdle is true when abort or finish was called from
// outside multiplex_impl. However, that only may be done by the main thread. // outside multiplex_impl. However, that only may be done by the main thread.
llassert(!mIdle || is_main_thread()); llassert(!mIdle || is_main_thread());
if (!mIdle) if (!mIdle)
idle(); idle();
mState = bs_finish; mState = bs_finish;
finish_impl(); finish_impl();
// Did finish_impl call kill()? Then that is only the default. Remember it. // Did finish_impl call kill()? Then that is only the default. Remember it.
bool default_delete = (mState == bs_killed); bool default_delete = (mState == bs_killed);
mState = bs_finish; mState = bs_finish;
if (mParent) if (mParent)
{ {
// It is possible that the parent is not running when the parent is in fact aborting and called // It is possible that the parent is not running when the parent is in fact aborting and called
// abort on this object from it's abort_impl function. It that case we don't want to recursively // abort on this object from it's abort_impl function. It that case we don't want to recursively
// call abort again (or change it's state). // call abort again (or change it's state).
if (mParent->running()) if (mParent->running())
{ {
if (mAborted && mAbortParent) if (mAborted && mAbortParent)
{ {
mParent->abort(); mParent->abort();
mParent = NULL; mParent = NULL;
} }
else else
{ {
mParent->set_state(mNewParentState); mParent->set_state(mNewParentState);
} }
} }
} }
// After this (bool)*this evaluates to true and we can call the callback, which then is allowed to call run(). // After this (bool)*this evaluates to true and we can call the callback, which then is allowed to call run().
mState = bs_callback; mState = bs_callback;
if (mCallback) if (mCallback)
{ {
// This can/may call kill() that sets mState to bs_kill and in which case the whole AIStateMachine // This can/may call kill() that sets mState to bs_kill and in which case the whole AIStateMachine
// will be deleted from the mainloop, or it may call run() that sets mState is set to bs_initialize // will be deleted from the mainloop, or it may call run() that sets mState is set to bs_initialize
// and might change or reuse mCallback or mParent. // and might change or reuse mCallback or mParent.
mCallback->callback(!mAborted); mCallback->callback(!mAborted);
if (mState != bs_initialize) if (mState != bs_initialize)
{ {
delete mCallback; delete mCallback;
mCallback = NULL; mCallback = NULL;
mParent = NULL; mParent = NULL;
} }
} }
else else
{ {
// Not restarted by callback. Allow run() to be called later on. // Not restarted by callback. Allow run() to be called later on.
mParent = NULL; mParent = NULL;
} }
// Fix the final state. // Fix the final state.
if (mState == bs_callback) if (mState == bs_callback)
mState = default_delete ? bs_killed : bs_initialize; mState = default_delete ? bs_killed : bs_initialize;
if (mState == bs_killed && mActive == as_idle) if (mState == bs_killed && mActive == as_idle)
{ {
// Bump the statemachine onto the active statemachine list, or else it won't be deleted. // Bump the statemachine onto the active statemachine list, or else it won't be deleted.
cont(); cont();
idle(); idle();
} }
} }
void AIStateMachine::kill(void) void AIStateMachine::kill(void)
{ {
// Should only be called from finish() (or when not running (bs_initialize)). // Should only be called from finish() (or when not running (bs_initialize)).
llassert(mIdle && (mState == bs_callback || mState == bs_finish || mState == bs_initialize)); llassert(mIdle && (mState == bs_callback || mState == bs_finish || mState == bs_initialize));
base_state_type prev_state = mState; base_state_type prev_state = mState;
mState = bs_killed; mState = bs_killed;
if (prev_state == bs_initialize) if (prev_state == bs_initialize)
{ {
// We're not running (ie being deleted by a parent statemachine), delete it immediately. // We're not running (ie being deleted by a parent statemachine), delete it immediately.
delete this; delete this;
} }
} }
// Return stringified 'state'. // Return stringified 'state'.
char const* AIStateMachine::state_str(state_type state) char const* AIStateMachine::state_str(state_type state)
{ {
if (state >= min_state && state < max_state) if (state >= min_state && state < max_state)
{ {
switch (state) switch (state)
{ {
AI_CASE_RETURN(bs_initialize); AI_CASE_RETURN(bs_initialize);
AI_CASE_RETURN(bs_run); AI_CASE_RETURN(bs_run);
AI_CASE_RETURN(bs_abort); AI_CASE_RETURN(bs_abort);
AI_CASE_RETURN(bs_finish); AI_CASE_RETURN(bs_finish);
AI_CASE_RETURN(bs_callback); AI_CASE_RETURN(bs_callback);
AI_CASE_RETURN(bs_killed); AI_CASE_RETURN(bs_killed);
} }
} }
return state_str_impl(state); return state_str_impl(state);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -320,135 +320,135 @@ char const* AIStateMachine::state_str(state_type state)
void AIStateMachine::multiplex(U64 current_time) void AIStateMachine::multiplex(U64 current_time)
{ {
// Return immediately when this state machine is sleeping. // Return immediately when this state machine is sleeping.
// A negative value of mSleep means we're counting frames, // A negative value of mSleep means we're counting frames,
// a positive value means we're waiting till a certain // a positive value means we're waiting till a certain
// amount of time has passed. // amount of time has passed.
if (mSleep != 0) if (mSleep != 0)
{ {
if (mSleep < 0) if (mSleep < 0)
{ {
if (++mSleep) if (++mSleep)
return; return;
} }
else else
{ {
if (current_time < (U64)mSleep) if (current_time < (U64)mSleep)
return; return;
mSleep = 0; mSleep = 0;
} }
} }
DoutEntering(dc::statemachine, "AIStateMachine::multiplex() [" << (void*)this << "] [with state: " << state_str(mState == bs_run ? mRunState : mState) << "]"); DoutEntering(dc::statemachine, "AIStateMachine::multiplex() [" << (void*)this << "] [with state: " << state_str(mState == bs_run ? mRunState : mState) << "]");
llassert(mState == bs_initialize || mState == bs_run); llassert(mState == bs_initialize || mState == bs_run);
// Real state machine starts here. // Real state machine starts here.
if (mState == bs_initialize) if (mState == bs_initialize)
{ {
mAborted = false; mAborted = false;
mState = bs_run; mState = bs_run;
initialize_impl(); initialize_impl();
if (mAborted || mState != bs_run) if (mAborted || mState != bs_run)
return; return;
} }
multiplex_impl(); multiplex_impl();
} }
static LLFastTimer::DeclareTimer FTM_STATEMACHINE("State Machine"); static LLFastTimer::DeclareTimer FTM_STATEMACHINE("State Machine");
// static // static
void AIStateMachine::mainloop(void*) void AIStateMachine::mainloop(void*)
{ {
LLFastTimer t(FTM_STATEMACHINE); LLFastTimer t(FTM_STATEMACHINE);
// Add continued state machines. // Add continued state machines.
{ {
AIReadAccess<cscm_type> cscm_r(continued_statemachines_and_calling_mainloop); AIReadAccess<cscm_type> cscm_r(continued_statemachines_and_calling_mainloop);
bool nonempty = false; bool nonempty = false;
for (continued_statemachines_type::const_iterator iter = cscm_r->continued_statemachines.begin(); iter != cscm_r->continued_statemachines.end(); ++iter) for (continued_statemachines_type::const_iterator iter = cscm_r->continued_statemachines.begin(); iter != cscm_r->continued_statemachines.end(); ++iter)
{ {
nonempty = true; nonempty = true;
active_statemachines.push_back(QueueElement(*iter)); active_statemachines.push_back(QueueElement(*iter));
Dout(dc::statemachine, "Adding " << (void*)*iter << " to active_statemachines"); Dout(dc::statemachine, "Adding " << (void*)*iter << " to active_statemachines");
(*iter)->mActive = as_active; (*iter)->mActive = as_active;
} }
if (nonempty) if (nonempty)
AIWriteAccess<cscm_type>(cscm_r)->continued_statemachines.clear(); AIWriteAccess<cscm_type>(cscm_r)->continued_statemachines.clear();
} }
llassert(!active_statemachines.empty()); llassert(!active_statemachines.empty());
// Run one or more state machines. // Run one or more state machines.
U64 total_clocks = 0; U64 total_clocks = 0;
U64 max_count = *AIAccess<U64>(sMaxCount); U64 max_count = *AIAccess<U64>(sMaxCount);
for (active_statemachines_type::iterator iter = active_statemachines.begin(); iter != active_statemachines.end(); ++iter) for (active_statemachines_type::iterator iter = active_statemachines.begin(); iter != active_statemachines.end(); ++iter)
{ {
AIStateMachine& statemachine(iter->statemachine()); AIStateMachine& statemachine(iter->statemachine());
if (!statemachine.mIdle) if (!statemachine.mIdle)
{ {
U64 start = LLFastTimer::getCPUClockCount64(); U64 start = get_clock_count();
// This might call idle() and then pass the statemachine to another thread who then may call cont(). // This might call idle() and then pass the statemachine to another thread who then may call cont().
// Hence, after this isn't not sure what mIdle is, and it can change from true to false at any moment, // Hence, after this isn't not sure what mIdle is, and it can change from true to false at any moment,
// if it is true after this function returns. // if it is true after this function returns.
iter->statemachine().multiplex(start); iter->statemachine().multiplex(start);
U64 delta = LLFastTimer::getCPUClockCount64() - start; U64 delta = get_clock_count() - start;
iter->add(delta); iter->add(delta);
total_clocks += delta; total_clocks += delta;
if (total_clocks >= max_count) if (total_clocks >= max_count)
{ {
#ifndef LL_RELEASE_FOR_DOWNLOAD #ifndef LL_RELEASE_FOR_DOWNLOAD
llwarns << "AIStateMachine::mainloop did run for " << (total_clocks * 1000 / calc_clock_frequency()) << " ms." << llendl; llwarns << "AIStateMachine::mainloop did run for " << (total_clocks * 1000 / calc_clock_frequency()) << " ms." << llendl;
#endif #endif
std::sort(active_statemachines.begin(), active_statemachines.end(), QueueElementComp()); std::sort(active_statemachines.begin(), active_statemachines.end(), QueueElementComp());
break; break;
} }
}
} }
} // Remove idle state machines from the loop.
// Remove idle state machines from the loop. active_statemachines_type::iterator iter = active_statemachines.begin();
active_statemachines_type::iterator iter = active_statemachines.begin(); while (iter != active_statemachines.end())
while (iter != active_statemachines.end())
{
AIStateMachine& statemachine(iter->statemachine());
// Atomic test mIdle and change mActive.
bool locked = statemachine.mIdleActive.tryLock();
// If the lock failed, then another thread is in the middle of calling cont(),
// thus mIdle will end up false. So, there is no reason to block here; just
// treat mIdle as false already.
if (locked && statemachine.mIdle)
{ {
// Without the lock, it would be possible that another thread called cont() right here, AIStateMachine& statemachine(iter->statemachine());
// changing mIdle to false again but NOT adding the statemachine to continued_statemachines, // Atomic test mIdle and change mActive.
// thinking it is in active_statemachines (and it is), while immediately below it is bool locked = statemachine.mIdleActive.tryLock();
// erased from active_statemachines. // If the lock failed, then another thread is in the middle of calling cont(),
statemachine.mActive = as_idle; // thus mIdle will end up false. So, there is no reason to block here; just
// Now, calling cont() is ok -- as that will cause the statemachine to be added to // treat mIdle as false already.
// continued_statemachines, so it's fine in that case-- even necessary-- to remove it from if (locked && statemachine.mIdle)
// active_statemachines regardless, and we can release the lock here. {
statemachine.mIdleActive.unlock(); // Without the lock, it would be possible that another thread called cont() right here,
Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines"); // changing mIdle to false again but NOT adding the statemachine to continued_statemachines,
iter = active_statemachines.erase(iter); // thinking it is in active_statemachines (and it is), while immediately below it is
if (statemachine.mState == bs_killed) // erased from active_statemachines.
{ statemachine.mActive = as_idle;
Dout(dc::statemachine, "Deleting " << (void*)&statemachine); // Now, calling cont() is ok -- as that will cause the statemachine to be added to
delete &statemachine; // continued_statemachines, so it's fine in that case-- even necessary-- to remove it from
} // active_statemachines regardless, and we can release the lock here.
statemachine.mIdleActive.unlock();
Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines");
iter = active_statemachines.erase(iter);
if (statemachine.mState == bs_killed)
{
Dout(dc::statemachine, "Deleting " << (void*)&statemachine);
delete &statemachine;
}
}
else
{
if (locked)
{
statemachine.mIdleActive.unlock();
}
llassert(statemachine.mActive == as_active); // It should not be possible that another thread called cont() and changed this when we are we are not idle.
llassert(statemachine.mState == bs_run || statemachine.mState == bs_initialize);
++iter;
}
} }
else if (active_statemachines.empty())
{ {
if (locked) // If this was the last state machine, remove mainloop from the IdleCallbacks.
{ AIReadAccess<cscm_type> cscm_r(continued_statemachines_and_calling_mainloop);
statemachine.mIdleActive.unlock(); if (cscm_r->continued_statemachines.empty() && cscm_r->calling_mainloop)
} {
llassert(statemachine.mActive == as_active); // It should not be possible that another thread called cont() and changed this when we are we are not idle. Dout(dc::statemachine, "Removing AIStateMachine::mainloop from gIdleCallbacks");
llassert(statemachine.mState == bs_run || statemachine.mState == bs_initialize); AIWriteAccess<cscm_type>(cscm_r)->calling_mainloop = false;
++iter; gIdleCallbacks.deleteFunction(&AIStateMachine::mainloop);
}
} }
}
if (active_statemachines.empty())
{
// If this was the last state machine, remove mainloop from the IdleCallbacks.
AIReadAccess<cscm_type> cscm_r(continued_statemachines_and_calling_mainloop);
if (cscm_r->continued_statemachines.empty() && cscm_r->calling_mainloop)
{
Dout(dc::statemachine, "Removing AIStateMachine::mainloop from gIdleCallbacks");
AIWriteAccess<cscm_type>(cscm_r)->calling_mainloop = false;
gIdleCallbacks.deleteFunction(&AIStateMachine::mainloop);
}
}
} }

View File

@@ -32,7 +32,7 @@
#define AISTATEMACHINE_H #define AISTATEMACHINE_H
#include "aithreadsafe.h" #include "aithreadsafe.h"
#include "llfasttimer.h" #include "lltimer.h"
#include <boost/signals2.hpp> #include <boost/signals2.hpp>
//! //!
@@ -247,7 +247,7 @@ class AIStateMachine {
void yield_frame(unsigned int frames) { mSleep = -(S64)frames; } void yield_frame(unsigned int frames) { mSleep = -(S64)frames; }
//! Temporarily halt the state machine. //! Temporarily halt the state machine.
void yield_ms(unsigned int ms) { mSleep = LLFastTimer::getCPUClockCount64() + LLFastTimer::countsPerSecond() * ms / 1000; } void yield_ms(unsigned int ms) { mSleep = get_clock_count() + calc_clock_frequency() * ms / 1000; }
//! Continue running after calling idle. //! Continue running after calling idle.
void cont(void); void cont(void);