diff --git a/.hgtags b/.hgtags
index 05ef9ce9bc..bff8f1ebeb 100644
--- a/.hgtags
+++ b/.hgtags
@@ -131,3 +131,4 @@ dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
0c4d0c24278074f219e5a32e72b449e78301d11b 2.7.1-beta1
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
+6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start
diff --git a/BuildParams b/BuildParams
index a311f9c467..2be4bb9fa9 100644
--- a/BuildParams
+++ b/BuildParams
@@ -102,6 +102,16 @@ mesh-development.build_debug_release_separately = true
mesh-development.build_CYGWIN_Debug = false
mesh-development.build_viewer_update_version_manager = false
+# ========================================
+# mesh-asset-deprecation
+# ========================================
+mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation"
+mesh-asset-deprecation.login_channel = "Project Viewer - Mesh Asset Deprecation"
+mesh-asset-deprecation.viewer_grid = aditi
+mesh-asset-deprecation.build_debug_release_separately = true
+mesh-asset-deprecation.build_CYGWIN_Debug = false
+mesh-asset-deprecation.build_viewer_update_version_manager = false
+
# ========================================
# viewer-mesh
# ========================================
diff --git a/autobuild.xml b/autobuild.xml
index ec52d6e331..63701dae79 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -18,9 +18,9 @@
archive
name
darwin
@@ -30,9 +30,9 @@
archive
name
linux
@@ -42,9 +42,9 @@
archive
name
windows
@@ -1290,9 +1290,9 @@
archive
name
linux
@@ -1524,7 +1524,7 @@
hash
bb0abe962b3b8208ed2dab0424aab33d
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-pcre/rev/228822/arch/Linux/installer/pcre-7.6-linux-20110504.tar.bz2
+ http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-pcre/rev/228822/arch/Linux/installer/pcre-7.6-linux-20110504.tar.bz2
name
linux
diff --git a/indra/llcommon/llaccountingquota.h b/indra/llcommon/llaccountingquota.h
index 3401cb57b6..140333de07 100644
--- a/indra/llcommon/llaccountingquota.h
+++ b/indra/llcommon/llaccountingquota.h
@@ -29,30 +29,38 @@
struct ParcelQuota
{
- ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
- F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
- F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
- F32 totalRenderCost, F32 totalPhysicsCost, F32 totalNetworkCost, F32 totalSimulationCost)
+ ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
+ F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
+ F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
+ F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost,
+ F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
+ F32 parcelCapacity )
: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost )
, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
- , mTotalRenderCost( totalRenderCost ), mTotalPhysicsCost( totalPhysicsCost )
- , mTotalNetworkCost( totalNetworkCost ), mTotalSimulationCost( totalSimulationCost )
+ , mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost )
+ , mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
+ , mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost )
+ , mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
+ , mParcelCapacity( parcelCapacity )
{
}
+
ParcelQuota(){}
F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
- F32 mTotalRenderCost, mTotalPhysicsCost, mTotalNetworkCost, mTotalSimulationCost;
+ F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost;
+ F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
+ F32 mParcelCapacity;
};
struct SelectionQuota
{
- SelectionQuota( S32 localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
+ SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
: mLocalId( localId)
, mRenderCost( renderCost )
, mPhysicsCost( physicsCost )
@@ -63,7 +71,7 @@ struct SelectionQuota
SelectionQuota() {}
F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;
- S32 mLocalId;
+ LLUUID mLocalId;
};
#endif
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 5be5ecc492..bf62600514 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2036,7 +2036,9 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
- llerrs << "WTF?" << llendl;
+ free(output);
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
}
have = CHUNK-strm.avail_out;
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 8ba97d7730..b2c495d093 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -737,7 +737,7 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
}
}
else
- { // WTF? Shouldn't have a NULL pointer in the map.
+ { // Shouldn't have a NULL pointer in the map.
llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
}
}
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index cfafbf0470..92cd9bd46a 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 7;
-const S32 LL_VERSION_PATCH = 4;
+const S32 LL_VERSION_PATCH = 5;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index fdfc24f8b7..e5ca47da69 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -35,12 +35,14 @@
#define OCT_ERRS LL_WARNS("OctreeErrors")
-#define LL_OCTREE_PARANOIA_CHECK 0
+
+extern U32 gOctreeMaxCapacity;
+/*#define LL_OCTREE_PARANOIA_CHECK 0
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
#else
#define LL_OCTREE_MAX_CAPACITY 128
-#endif
+#endif*/
template class LLOctreeNode;
@@ -74,6 +76,7 @@ template
class LLOctreeNode : public LLTreeNode
{
public:
+
typedef LLOctreeTraveler oct_traveler;
typedef LLTreeTraveler tree_traveler;
typedef typename std::set > element_list;
@@ -294,8 +297,8 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
- if ((getElementCount() < LL_OCTREE_MAX_CAPACITY && contains(data->getBinRadius()) ||
- (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
+ if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+ (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index c504215ee5..8c81f27784 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -100,7 +100,7 @@ void assert_aligned(void* ptr, uintptr_t alignment)
uintptr_t t = (uintptr_t) ptr;
if (t%alignment != 0)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Alignment check failed." << llendl;
}
#endif
}
@@ -361,7 +361,7 @@ public:
}
else
{
- llerrs << "WTF? Empty leaf" << llendl;
+ llerrs << "Empty leaf" << llendl;
}
for (S32 i = 0; i < branch->getChildCount(); ++i)
@@ -416,6 +416,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
return face;
}
+//static
+S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
+{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+ S32 np = 0;
+
+ // Generate an n-sided "circular" path.
+ // 0 is (1,0), and we go counter-clockwise along a circular path from there.
+ F32 t, t_step, t_first, t_fraction;
+
+ F32 begin = params.getBegin();
+ F32 end = params.getEnd();
+
+ t_step = 1.0f / sides;
+
+ t_first = floor(begin * sides) / (F32)sides;
+
+ // pt1 is the first point on the fractional face.
+ // Starting t and ang values for the first face
+ t = t_first;
+
+ // Increment to the next point.
+ // pt2 is the end point on the fractional face
+ t += t_step;
+
+ t_fraction = (begin - t_first)*sides;
+
+ // Only use if it's not almost exactly on an edge.
+ if (t_fraction < 0.9999f)
+ {
+ np++;
+ }
+
+ // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02
+ while (t < end)
+ {
+ // Iterate through all the integer steps of t.
+ np++;
+
+ t += t_step;
+ }
+
+ t_fraction = (end - (t - t_step))*sides;
+
+ // Find the fraction that we need to add to the end point.
+ t_fraction = (end - (t - t_step))*sides;
+ if (t_fraction > 0.0001f)
+ {
+ np++;
+ }
+
+ // If we're sliced, the profile is open.
+ if ((end - begin)*ang_scale < 0.99f)
+ {
+ if (params.getHollow() <= 0)
+ {
+ // put center point if not hollow.
+ np++;
+ }
+ }
+
+ return np;
+}
+
// What is the bevel parameter used for? - DJS 04/05/02
// Bevel parameter is currently unused but presumedly would support
// filleted and chamfered corners
@@ -672,6 +736,117 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
return face;
}
+//static
+S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
+ BOOL is_sculpted, S32 sculpt_size)
+{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+
+ if (detail < MIN_LOD)
+ {
+ detail = MIN_LOD;
+ }
+
+ // Generate the face data
+ F32 hollow = params.getHollow();
+
+ S32 np = 0;
+
+ switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
+ {
+ case LL_PCODE_PROFILE_SQUARE:
+ {
+ np = getNumNGonPoints(params, 4,-0.375, 0, 1, split);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_ISOTRI:
+ case LL_PCODE_PROFILE_RIGHTTRI:
+ case LL_PCODE_PROFILE_EQUALTRI:
+ {
+ np = getNumNGonPoints(params, 3,0, 0, 1, split);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_CIRCLE:
+ {
+ // If this has a square hollow, we should adjust the
+ // number of faces a bit so that the geometry lines up.
+ U8 hole_type=0;
+ F32 circle_detail = MIN_DETAIL_FACES * detail;
+ if (hollow)
+ {
+ hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
+ if (hole_type == LL_PCODE_HOLE_SQUARE)
+ {
+ // Snap to the next multiple of four sides,
+ // so that corners line up.
+ circle_detail = llceil(circle_detail / 4.0f) * 4.0f;
+ }
+ }
+
+ S32 sides = (S32)circle_detail;
+
+ if (is_sculpted)
+ sides = sculpt_size;
+
+ np = getNumNGonPoints(params, sides);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_CIRCLE_HALF:
+ {
+ // If this has a square hollow, we should adjust the
+ // number of faces a bit so that the geometry lines up.
+ U8 hole_type=0;
+ // Number of faces is cut in half because it's only a half-circle.
+ F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
+ if (hollow)
+ {
+ hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
+ if (hole_type == LL_PCODE_HOLE_SQUARE)
+ {
+ // Snap to the next multiple of four sides (div 2),
+ // so that corners line up.
+ circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
+ }
+ }
+ np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+
+ // Special case for openness of sphere
+ if ((params.getEnd() - params.getBegin()) < 1.f)
+ {
+ }
+ else if (!hollow)
+ {
+ np++;
+ }
+ }
+ break;
+ default:
+ break;
+ };
+
+
+ return np;
+}
BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
@@ -1133,6 +1308,32 @@ LLPath::~LLPath()
{
}
+S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
+{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added
+ S32 ret = 0;
+
+ F32 step= 1.0f / sides;
+ F32 t = params.getBegin();
+ ret = 1;
+
+ t+=step;
+
+ // Snap to a quantized parameter, so that cut does not
+ // affect most sample points.
+ t = ((S32)(t * sides)) / (F32)sides;
+
+ // Run through the non-cut dependent points.
+ while (t < params.getEnd())
+ {
+ ret++;
+ t+=step;
+ }
+
+ ret++;
+
+ return ret;
+}
+
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
@@ -1310,6 +1511,56 @@ const LLVector2 LLPathParams::getEndScale() const
return end_scale;
}
+S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail)
+{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+
+ if (detail < MIN_LOD)
+ {
+ detail = MIN_LOD;
+ }
+
+ S32 np = 2; // hardcode for line
+
+ // Is this 0xf0 mask really necessary? DK 03/02/05
+
+ switch (params.getCurveType() & 0xf0)
+ {
+ default:
+ case LL_PCODE_PATH_LINE:
+ {
+ // Take the begin/end twist into account for detail.
+ np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
+ }
+ break;
+
+ case LL_PCODE_PATH_CIRCLE:
+ {
+ // Increase the detail as the revolutions and twist increase.
+ F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
+
+ S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
+
+ np = sides;
+ }
+ break;
+
+ case LL_PCODE_PATH_CIRCLE2:
+ {
+ //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
+ np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail));
+ }
+ break;
+
+ case LL_PCODE_PATH_TEST:
+
+ np = 5;
+ break;
+ };
+
+ return np;
+}
+
BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{
@@ -2159,27 +2410,41 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 face_count = mdl.size();
if (face_count == 0)
- {
- llerrs << "WTF?" << llendl;
+ { //no faces unpacked, treat as failed decode
+ llwarns << "found no faces!" << llendl;
+ return false;
}
mVolumeFaces.resize(face_count);
for (U32 i = 0; i < face_count; ++i)
{
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ if (mdl[i].has("NoGeometry"))
+ { //face has no geometry, continue
+ face.resizeIndices(3);
+ face.resizeVertices(1);
+ memset(face.mPositions, 0, sizeof(LLVector4a));
+ memset(face.mNormals, 0, sizeof(LLVector4a));
+ memset(face.mTexCoords, 0, sizeof(LLVector2));
+ memset(face.mIndices, 0, sizeof(U16)*3);
+ continue;
+ }
+
LLSD::Binary pos = mdl[i]["Position"];
LLSD::Binary norm = mdl[i]["Normal"];
LLSD::Binary tc = mdl[i]["TexCoord0"];
LLSD::Binary idx = mdl[i]["TriangleList"];
- LLVolumeFace& face = mVolumeFaces[i];
+
//copy out indices
face.resizeIndices(idx.size()/2);
if (idx.empty() || face.mNumIndices < 3)
{ //why is there an empty index list?
- llerrs <<"WTF?" << llendl;
+ llwarns <<"Empty face present!" << llendl;
continue;
}
@@ -2377,14 +2642,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLVector4a& min = face.mExtents[0];
LLVector4a& max = face.mExtents[1];
- min.clear();
- max.clear();
- min = max = face.mPositions[0];
-
- for (S32 i = 1; i < face.mNumVertices; ++i)
+ if (face.mNumVertices < 3)
+ { //empty face, use a dummy 1cm (at 1m scale) bounding box
+ min.splat(-0.005f);
+ max.splat(0.005f);
+ }
+ else
{
- min.setMin(min, face.mPositions[i]);
- max.setMax(max, face.mPositions[i]);
+ min = max = face.mPositions[0];
+
+ for (S32 i = 1; i < face.mNumVertices; ++i)
+ {
+ min.setMin(min, face.mPositions[i]);
+ max.setMax(max, face.mPositions[i]);
+ }
}
}
}
@@ -2980,7 +3251,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
// don't test lowest LOD to support legacy content DEV-33670
if (mDetail > SCULPT_MIN_AREA_DETAIL)
{
- if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+ F32 area = sculptGetSurfaceArea();
+
+ const F32 SCULPT_MAX_AREA = 32.f;
+
+ if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
}
@@ -4064,6 +4339,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
return index;
}
+void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
+{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the
+ //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
+ F32 detail[] = {1.f, 1.5f, 2.5f, 4.f};
+ for (S32 i = 0; i < 4; i++)
+ {
+ S32 count = 0;
+ S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]);
+ S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]);
+
+ count = (profile_points-1)*2*(path_points-1);
+ count += profile_points*2;
+
+ counts[i] = count;
+ }
+}
+
S32 LLVolume::getNumTriangleIndices() const
{
BOOL profile_open = getProfile().isOpen();
@@ -5220,6 +5512,8 @@ LLVolumeFace::LLVolumeFace() :
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
+ mExtents[0].splat(-0.5f);
+ mExtents[1].splat(0.5f);
mCenter = mExtents+2;
}
@@ -5741,6 +6035,11 @@ void LLVolumeFace::cacheOptimize()
LLVCacheLRU cache;
+ if (mNumVertices < 3)
+ { //nothing to do
+ return;
+ }
+
//mapping of vertices to triangles and indices
std::vector vertex_data;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 01bfbd858b..f67f8f644d 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -690,6 +690,9 @@ public:
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
BOOL isOpen() const { return mOpen; }
void setDirty() { mDirty = TRUE; }
+
+ static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
+ BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isConcave() const { return mConcave; }
@@ -714,6 +717,7 @@ public:
protected:
void genNormals(const LLProfileParams& params);
+ static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
@@ -756,6 +760,9 @@ public:
virtual ~LLPath();
+ static S32 getNumPoints(const LLPathParams& params, F32 detail);
+ static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
+
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
@@ -981,6 +988,7 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
+ static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const;
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index f7615b5ccb..e33da51aee 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS
char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");
char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");
char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd");
+char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");
char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");
char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");
char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 44c7440436..b706ef8866 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;
extern char const* const _PREHASH_ObjectDeselect;
extern char const* const _PREHASH_NewAssetID;
extern char const* const _PREHASH_ObjectAdd;
+extern char const* const _PREHASH_SimulatorFeatures;
extern char const* const _PREHASH_RayEndIsIntersection;
extern char const* const _PREHASH_CompleteAuction;
extern char const* const _PREHASH_CircuitCode;
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 57ac7a143f..0463d5364b 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -50,7 +50,7 @@ std::string model_names[] =
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape"
+ "physics_mesh"
};
const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
@@ -84,7 +84,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
domInputLocal_Array& v_inp = vertices->getInput_array();
if (inputs[j]->getOffset() != 0)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Vertex array offset MUST be zero." << llendl;
}
for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -98,7 +98,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Vertex array stride MUST be three." << llendl;
}
domListOfFloats& v = src->getFloat_array()->getValue();
@@ -149,9 +149,10 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
}
}
-void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
+bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
{
+
idx_stride = 0;
for (U32 j = 0; j < inputs.getCount(); ++j)
@@ -163,7 +164,11 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
-
+ if ( !vertices )
+ {
+ return false;
+ }
+
domInputLocal_Array& v_inp = vertices->getInput_array();
@@ -207,6 +212,8 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
}
idx_stride += 1;
+
+ return true;
}
LLModel::EModelStatus load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri)
@@ -227,8 +234,12 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector& fa
S32 idx_stride = 0;
- get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+ if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
+ {
+ return LLModel::BAD_ELEMENT;
+ }
+
domPRef p = tri->getP();
domListOfUInts& idx = p->getValue();
@@ -367,7 +378,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector& fac
S32 idx_stride = 0;
- get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+ if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
+ {
+ return LLModel::BAD_ELEMENT;
+ }
LLVolumeFace face;
@@ -564,7 +578,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
-
+ if (!vertices)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
domInputLocal_Array& v_inp = vertices->getInput_array();
for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -574,6 +591,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
const domURIFragmentType& uri = v_inp[k]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
v = &(src->getFloat_array()->getValue());
}
}
@@ -585,6 +606,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
n = &(src->getFloat_array()->getValue());
}
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
@@ -593,6 +618,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
t = &(src->getFloat_array()->getValue());
}
}
@@ -667,11 +696,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
}
}
- if (cur_idx != vert_idx.size())
- {
- llerrs << "WTF?" << llendl;
- }
-
//build vertex array from map
std::vector new_verts;
new_verts.resize(vert_idx.size());
@@ -717,7 +741,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac
//static
std::string LLModel::getStatusString(U32 status)
{
- const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow"};
+ const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"};
if(status < INVALID_STATUS)
{
@@ -755,7 +779,6 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
for (U32 i = 0; i < polys.getCount(); ++i)
{
domPolylistRef& poly = polys.get(i);
-
mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@@ -765,12 +788,12 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
-
+
domPolygons_Array& polygons = mesh->getPolygons_array();
+
for (U32 i = 0; i < polygons.getCount(); ++i)
{
domPolygonsRef& poly = polygons.get(i);
-
mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@@ -780,7 +803,7 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
-
+
}
BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
@@ -926,11 +949,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVector4a min, max;
- if (mVolumeFaces[0].mNumVertices <= 0)
- {
- llerrs << "WTF?" << llendl;
- }
-
// For all of the volume faces
// in the model, loop over
// them and see what the extents
@@ -942,11 +960,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVolumeFace& face = mVolumeFaces[i];
- if (face.mNumVertices <= 0)
- {
- llerrs << "WTF?" << llendl;
- }
-
update_min_max(min, max, face.mExtents[0]);
update_min_max(min, max, face.mExtents[1]);
}
@@ -1289,11 +1302,6 @@ void LLModel::generateNormals(F32 angle_cutoff)
{
LLVector4a& n = iter->second[k].getNormal();
- if (!iter->second[k].getPosition().equals3(new_face.mPositions[i]))
- {
- llerrs << "WTF?" << llendl;
- }
-
F32 cur = n.dot3(ref_norm).getF32();
if (cur > best)
@@ -1410,7 +1418,11 @@ LLSD LLModel::writeModel(
if (!decomp.mBaseHull.empty() ||
!decomp.mHull.empty())
{
- mdl["decomposition"] = decomp.asLLSD();
+ mdl["physics_convex"] = decomp.asLLSD();
+ if (!decomp.mHull.empty())
+ { //convex decomposition exists, physics mesh will not be used
+ model[LLModel::LOD_PHYSICS] = NULL;
+ }
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@@ -1435,8 +1447,9 @@ LLSD LLModel::writeModel(
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
{ //for each face
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
- if (!face.mNumVertices)
+ if (face.mNumVertices < 3)
{ //don't export an empty face
+ mdl[model_names[idx]][i]["NoGeometry"] = true;
continue;
}
LLSD::Binary verts(face.mNumVertices*3*2);
@@ -1469,7 +1482,6 @@ LLSD LLModel::writeModel(
//position + normal
for (U32 k = 0; k < 3; ++k)
{ //for each component
-
//convert to 16-bit normalized across domain
U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
@@ -1513,7 +1525,6 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
-
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
@@ -1539,11 +1550,6 @@ LLSD LLModel::writeModel(
weight_list& weights = high->getJointInfluences(pos);
- if (weights.size() > 4)
- {
- llerrs << "WTF?" << llendl;
- }
-
S32 count = 0;
for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
{
@@ -1607,23 +1613,19 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
- else
- {
- llerrs << "WTF?" << llendl;
- }
}
std::string decomposition;
- if (mdl.has("decomposition"))
+ if (mdl.has("physics_convex"))
{ //write out convex decomposition
- decomposition = zip_llsd(mdl["decomposition"]);
+ decomposition = zip_llsd(mdl["physics_convex"]);
U32 size = decomposition.size();
if (size > 0)
{
- header["decomposition"]["offset"] = (LLSD::Integer) cur_offset;
- header["decomposition"]["size"] = (LLSD::Integer) size;
+ header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
+ header["physics_convex"]["size"] = (LLSD::Integer) size;
cur_offset += size;
bytes += size;
}
@@ -1644,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
- else
- {
- header[model_names[i]]["offset"] = -1;
- header[model_names[i]]["size"] = 0;
- }
}
if (!nowrite)
@@ -1662,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!decomposition.empty())
{ //write decomposition block
- ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger());
+ ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
}
for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@@ -1685,7 +1682,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
if ((iter->first - pos).magVec() > 0.1f)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Couldn't find weight list." << llendl;
}
return iter->second;
@@ -1778,7 +1775,7 @@ void LLModel::updateHullCenters()
if (mHullPoints > 0)
{
mCenterOfHullCenters *= 1.f / mHullPoints;
- llassert(mPhysics.asLLSD().has("HullList"));
+ llassert(mPhysics.hasHullList());
}
}
@@ -1801,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape",
+ "physics_mesh",
};
const S32 MODEL_LODS = 5;
@@ -1900,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
{
- S32 offset = header["decomposition"]["offset"].asInteger();
- S32 size = header["decomposition"]["size"].asInteger();
+ S32 offset = header["physics_convex"]["offset"].asInteger();
+ S32 size = header["physics_convex"]["size"].asInteger();
if (offset >= 0 && size > 0)
{
@@ -2041,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
- const LLSD::Binary& position = decomp["Position"].asBinary();
+ const LLSD::Binary& position = decomp["Positions"].asBinary();
U16* p = (U16*) &position[0];
@@ -2051,11 +2048,19 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
LLVector3 max;
LLVector3 range;
- min.setValue(decomp["Min"]);
- max.setValue(decomp["Max"]);
+ if (decomp.has("Min"))
+ {
+ min.setValue(decomp["Min"]);
+ max.setValue(decomp["Max"]);
+ }
+ else
+ {
+ min.set(-0.5f, -0.5f, -0.5f);
+ max.set(0.5f, 0.5f, 0.5f);
+ }
+
range = max-min;
-
for (U32 i = 0; i < hulls.size(); ++i)
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
@@ -2071,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
//point must be unique
//llassert(valid.find(test) == valid.end());
valid.insert(test);
+
mHull[i].push_back(LLVector3(
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
@@ -2085,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
}
}
- if (decomp.has("Hull"))
+ if (decomp.has("BoundingVerts"))
{
- const LLSD::Binary& position = decomp["Hull"].asBinary();
+ const LLSD::Binary& position = decomp["BoundingVerts"].asBinary();
U16* p = (U16*) &position[0];
@@ -2123,10 +2129,15 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
//empty base hull mesh to indicate decomposition has been loaded
//but contains no base hull
- mBaseHullMesh.clear();;
+ mBaseHullMesh.clear();
}
}
+bool LLModel::Decomposition::hasHullList() const
+{
+ return !mHull.empty() ;
+}
+
LLSD LLModel::Decomposition::asLLSD() const
{
LLSD ret;
@@ -2137,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const
}
//write decomposition block
- // ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
- // ["decomposition"]["PositionDomain"]["Min"/"Max"]
- // ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
- // ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
-
+ // ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
+ // ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
+ // ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
//get minimum and maximum
LLVector3 min;
@@ -2190,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2205,17 +2216,24 @@ LLSD LLModel::Decomposition::asLLSD() const
U64 test = 0;
for (U32 k = 0; k < 3; k++)
{
+ F32* src = (F32*) (mHull[i][j].mV);
+
+ llassert(src[k] <= 0.501f && src[k] >= -0.501f);
+
//convert to 16-bit normalized across domain
- U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+ U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
- switch (k)
+ if(valid.size() < 3)
{
- case 0: test = test | (U64) val; break;
- case 1: test = test | ((U64) val << 16); break;
- case 2: test = test | ((U64) val << 32); break;
- };
+ switch (k)
+ {
+ case 0: test = test | (U64) val; break;
+ case 1: test = test | ((U64) val << 16); break;
+ case 2: test = test | ((U64) val << 32); break;
+ };
- valid.insert(test);
+ valid.insert(test);
+ }
U8* buff = (U8*) &val;
//write to binary buffer
@@ -2227,17 +2245,21 @@ LLSD LLModel::Decomposition::asLLSD() const
}
}
- //must have at least 4 unique points
- llassert(valid.size() > 3);
+ //must have at least 3 unique points
+ llassert(valid.size() > 2);
}
- ret["Position"] = p;
+ ret["Positions"] = p;
}
+ //llassert(!mBaseHull.empty());
+
if (!mBaseHull.empty())
{
LLSD::Binary p(mBaseHull.size()*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2245,6 +2267,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
for (U32 k = 0; k < 3; k++)
{
+ llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
+
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
@@ -2255,12 +2279,12 @@ LLSD LLModel::Decomposition::asLLSD() const
if (vert_idx > p.size())
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Index out of bounds" << llendl;
}
}
}
- ret["Hull"] = p;
+ ret["BoundingVerts"] = p;
}
return ret;
@@ -2290,10 +2314,5 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
{ //take physics shape mesh from rhs
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
-
- if (!mHull.empty())
- { //verify
- llassert(asLLSD().has("HullList"));
- }
}
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 23f4b5cb42..cd9f76fcb7 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -73,6 +73,7 @@ public:
{
NO_ERRORS = 0,
VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535.
+ BAD_ELEMENT,
INVALID_STATUS
} ;
@@ -106,6 +107,7 @@ public:
Decomposition(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD() const;
+ bool hasHullList() const;
void merge(const Decomposition* rhs);
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index a460912e70..a3aed4dd8a 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -127,6 +127,11 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
+// GL_ARB_map_buffer_range
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
+
// vertex object prototypes
PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL;
@@ -178,6 +183,12 @@ PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
+//GL_ARB_texture_multisample
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+PFNGLSAMPLEMASKIPROC glSampleMaski;
+
// GL_EXT_blend_func_separate
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
@@ -321,9 +332,11 @@ LLGLManager::LLGLManager() :
mHasMipMapGeneration(FALSE),
mHasCompressedTextures(FALSE),
mHasFramebufferObject(FALSE),
+ mMaxSamples(0),
mHasBlendFuncSeparate(FALSE),
mHasVertexBufferObject(FALSE),
+ mHasMapBufferRange(FALSE),
mHasPBuffer(FALSE),
mHasShaderObjects(FALSE),
mHasVertexShader(FALSE),
@@ -334,6 +347,11 @@ LLGLManager::LLGLManager() :
mHasPointParameters(FALSE),
mHasDrawBuffers(FALSE),
mHasTextureRectangle(FALSE),
+ mHasTextureMultisample(FALSE),
+ mMaxSampleMaskWords(0),
+ mMaxColorTextureSamples(0),
+ mMaxDepthTextureSamples(0),
+ mMaxIntegerSamples(0),
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
@@ -539,7 +557,20 @@ bool LLGLManager::initGL()
{
GLint num_tex_image_units;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
- mNumTextureImageUnits = num_tex_image_units;
+ mNumTextureImageUnits = llmin(num_tex_image_units, 32);
+ }
+
+ if (mHasTextureMultisample)
+ {
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+ glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+ glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+ glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+ }
+
+ if (mHasFramebufferObject)
+ {
+ glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
}
setToDebugGPU();
@@ -648,6 +679,14 @@ std::string LLGLManager::getRawGLString()
return gl_string;
}
+U32 LLGLManager::getNumFBOFSAASamples(U32 samples)
+{
+ samples = llmin(samples, (U32) mMaxColorTextureSamples);
+ samples = llmin(samples, (U32) mMaxDepthTextureSamples);
+ samples = llmin(samples, (U32) 4);
+ return samples;
+}
+
void LLGLManager::shutdownGL()
{
if (mInited)
@@ -728,6 +767,7 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
+ mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
#ifdef GL_ARB_framebuffer_object
@@ -742,6 +782,7 @@ void LLGLManager::initExtensions()
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);
+ mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@@ -921,6 +962,11 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
+ if (mHasMapBufferRange)
+ {
+ glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
+ glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
+ }
if (mHasFramebufferObject)
{
llinfos << "initExtensions() FramebufferObject-related procs..." << llendl;
@@ -953,6 +999,13 @@ void LLGLManager::initExtensions()
{
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
}
+ if (mHasTextureMultisample)
+ {
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
+ glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
+ glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
+ glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
+ }
#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");
@@ -1370,10 +1423,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
}
}
- GLint maxTextureUnits = 0;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
- stop_glerror();
-
static const char* label[] =
{
"GL_TEXTURE_2D",
@@ -1384,7 +1433,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
"GL_TEXTURE_GEN_T",
"GL_TEXTURE_GEN_Q",
"GL_TEXTURE_GEN_R",
- "GL_TEXTURE_RECTANGLE_ARB"
+ "GL_TEXTURE_RECTANGLE_ARB",
+ "GL_TEXTURE_2D_MULTISAMPLE"
};
static GLint value[] =
@@ -1397,7 +1447,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
GL_TEXTURE_GEN_T,
GL_TEXTURE_GEN_Q,
GL_TEXTURE_GEN_R,
- GL_TEXTURE_RECTANGLE_ARB
+ GL_TEXTURE_RECTANGLE_ARB,
+ GL_TEXTURE_2D_MULTISAMPLE
};
GLint stackDepth = 0;
@@ -1406,68 +1457,96 @@ void LLGLState::checkTextureChannels(const std::string& msg)
glh::matrix4f identity;
identity.identity();
- for (GLint i = 1; i < maxTextureUnits; i++)
+ for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
- stop_glerror();
- if (stackDepth != 1)
+ if (i < gGLManager.mNumTextureUnits)
{
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+ glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
+ stop_glerror();
+ glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+ stop_glerror();
- if (gDebugSession)
- {
- gFailLog << "Texture matrix stack corrupted." << std::endl;
- }
- }
-
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
- stop_glerror();
-
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
- }
- }
-
-
- for (S32 j = (i == 0 ? 1 : 0);
- j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
- {
- if (glIsEnabled(value[j]))
+ if (stackDepth != 1)
{
error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+
if (gDebugSession)
{
- gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ gFailLog << "Texture matrix stack corrupted." << std::endl;
}
}
+
+ glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
stop_glerror();
+
+ if (mat != identity)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+ }
+ }
+
+ for (S32 j = (i == 0 ? 1 : 0);
+ j < 9; j++)
+ {
+ if (j == 8 && !gGLManager.mHasTextureRectangle ||
+ j == 9 && !gGLManager.mHasTextureMultisample)
+ {
+ continue;
+ }
+
+ if (glIsEnabled(value[j]))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ }
+ }
+ stop_glerror();
+ }
+
+ glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
+ stop_glerror();
+
+ if (mat != identity)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+ }
+ }
}
- glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
- stop_glerror();
-
- if (mat != identity)
{
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
- if (gDebugSession)
+ GLint tex = 0;
+ stop_glerror();
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
+ stop_glerror();
+
+ if (tex != 0)
{
- gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << llendl;
+
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
+ }
}
}
}
+ stop_glerror();
gGL.getTexUnit(0)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB);
stop_glerror();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 1d7ab188fc..d1bee00161 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -83,10 +83,12 @@ public:
BOOL mHasMipMapGeneration;
BOOL mHasCompressedTextures;
BOOL mHasFramebufferObject;
+ S32 mMaxSamples;
BOOL mHasBlendFuncSeparate;
-
+
// ARB Extensions
BOOL mHasVertexBufferObject;
+ BOOL mHasMapBufferRange;
BOOL mHasPBuffer;
BOOL mHasShaderObjects;
BOOL mHasVertexShader;
@@ -98,6 +100,11 @@ public:
BOOL mHasDrawBuffers;
BOOL mHasDepthClamp;
BOOL mHasTextureRectangle;
+ BOOL mHasTextureMultisample;
+ S32 mMaxSampleMaskWords;
+ S32 mMaxColorTextureSamples;
+ S32 mMaxDepthTextureSamples;
+ S32 mMaxIntegerSamples;
// Other extensions.
BOOL mHasAnisotropic;
@@ -139,6 +146,7 @@ public:
void printGLInfoString();
void getGLInfo(LLSD& info);
+ U32 getNumFBOFSAASamples(U32 desired_samples = 32);
// In ALL CAPS
std::string mGLVendor;
std::string mGLVendorShort;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index d8140a124d..f35f329f00 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -68,6 +68,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -306,6 +310,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -474,6 +482,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_WINDOWS
//----------------------------------------------------------------------------
@@ -506,6 +519,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -673,6 +690,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_DARWIN
//----------------------------------------------------------------------------
@@ -714,13 +736,55 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#ifndef GL_ARB_framebuffer_object
#define glGenerateMipmap glGenerateMipmapEXT
+#define GL_MAX_SAMPLES 0x8D57
#endif
+
// GL_ARB_draw_buffers
extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
#ifdef __cplusplus
extern "C" {
#endif
+
+//
+// Define map buffer range headers on Mac
+//
+#ifndef GL_ARB_map_buffer_range
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#endif
+
+//
+// Define multisample headers on Mac
+//
+#ifndef GL_ARB_texture_multisample
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#endif
+
//
// Define vertex buffer object headers on Mac
//
@@ -757,7 +821,7 @@ extern "C" {
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_DYNAMIC_COPY_ARB 0x88EA
#endif
-
+
#ifndef GL_ARB_vertex_buffer_object
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 257bcd9380..8e99f62de6 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -48,6 +48,8 @@ using std::pair;
using std::make_pair;
using std::string;
+GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
return v1 != v2;
@@ -56,7 +58,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
+hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false)
{
}
@@ -107,16 +109,11 @@ BOOL LLGLSLShader::createShader(vector * attributes,
// Create program
mProgramObject = glCreateProgramObjectARB();
- // Attach existing objects
- if (!LLShaderMgr::instance()->attachShaderFeatures(this))
- {
- return FALSE;
- }
-
+ //compile new source
vector< pair >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second);
+ GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle > 0)
{
@@ -128,6 +125,12 @@ BOOL LLGLSLShader::createShader(vector * attributes,
}
}
+ // Attach existing objects
+ if (!LLShaderMgr::instance()->attachShaderFeatures(this))
+ {
+ return FALSE;
+ }
+
// Map attributes and uniforms
if (success)
{
@@ -149,6 +152,29 @@ BOOL LLGLSLShader::createShader(vector * attributes,
return createShader(attributes,uniforms);
}
}
+ else if (mFeatures.mIndexedTextureChannels > 0)
+ { //override texture channels for indexed texture rendering
+ bind();
+ S32 channel_count = mFeatures.mIndexedTextureChannels;
+
+ for (S32 i = 0; i < channel_count; i++)
+ {
+ uniform1i(llformat("tex%d", i), i);
+ }
+
+ S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
+ for (U32 i = 0; i < mTexture.size(); i++)
+ {
+ if (mTexture[i] > -1 && mTexture[i] < channel_count)
+ {
+ llassert(cur_tex < gGLManager.mNumTextureImageUnits);
+ uniform1i(i, cur_tex);
+ mTexture[i] = cur_tex++;
+ }
+ }
+ unbind();
+ }
+
return success;
}
@@ -293,7 +319,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
- if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB)
+ if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
+ type == GL_SAMPLER_2D_MULTISAMPLE)
{ //this here is a texture
glUniform1iARB(location, mActiveTextureChannels);
LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
@@ -342,7 +369,7 @@ void LLGLSLShader::bind()
if (gGLManager.mHasShaderObjects)
{
glUseProgramObjectARB(mProgramObject);
-
+ sCurBoundShader = mProgramObject;
if (mUniformsDirty)
{
LLShaderMgr::instance()->updateShaderUniforms(this);
@@ -365,6 +392,7 @@ void LLGLSLShader::unbind()
}
}
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
stop_glerror();
}
}
@@ -372,6 +400,7 @@ void LLGLSLShader::unbind()
void LLGLSLShader::bindNoShader(void)
{
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
}
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index d46ddbbe18..4922eb6d67 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -45,6 +45,8 @@ public:
bool hasObjectSkinning;
bool hasAtmospherics;
bool hasGamma;
+ S32 mIndexedTextureChannels;
+ bool disableTextureIndex;
// char numLights;
@@ -64,6 +66,8 @@ public:
LLGLSLShader();
+ static GLhandleARB sCurBoundShader;
+
void unload();
BOOL createShader(std::vector * attributes,
std::vector * uniforms);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index d408077c68..60a5962234 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1083,12 +1083,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
}
// static
-void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
+void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
{
for (S32 i = 0; i < numTextures; i++)
{
sDeadTextureList.push_back(textures[i]);
}
+
+ if (immediate)
+ {
+ LLImageGL::deleteDeadTextures();
+ }
}
// static
@@ -1413,11 +1418,13 @@ void LLImageGL::deleteDeadTextures()
{
GLuint tex = sDeadTextureList.front();
sDeadTextureList.pop_front();
- for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
+ for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
{
- if (sCurrentBoundTextures[i] == tex)
+ LLTexUnit* tex_unit = gGL.getTexUnit(i);
+
+ if (tex_unit->getCurrTexture() == tex)
{
- gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
+ tex_unit->unbind(tex_unit->getCurrType());
stop_glerror();
}
}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6c980984c0..2cfb15b0d9 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -98,7 +98,7 @@ public:
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
// for tracking purposes and will be deprecated in the future
static void generateTextures(S32 numTextures, U32 *textures);
- static void deleteTextures(S32 numTextures, U32 *textures);
+ static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
BOOL createGLTexture() ;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index c37139ac4c..6a3f186531 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -30,6 +30,7 @@
#include "llvertexbuffer.h"
#include "llcubemap.h"
+#include "llglslshader.h"
#include "llimagegl.h"
#include "llrendertarget.h"
#include "lltexture.h"
@@ -46,14 +47,15 @@ S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 0;
-static const U32 LL_NUM_TEXTURE_LAYERS = 16;
+static const U32 LL_NUM_TEXTURE_LAYERS = 32;
static const U32 LL_NUM_LIGHT_UNITS = 8;
static GLenum sGLTextureType[] =
{
GL_TEXTURE_2D,
GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_CUBE_MAP_ARB
+ GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_2D_MULTISAMPLE
};
static GLint sGLAddressMode[] =
@@ -124,7 +126,7 @@ void LLTexUnit::refreshState(void)
// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
//
- bool enableDisable = (mIndex < gGLManager.mNumTextureUnits);
+ bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
if (mCurrTexType != TT_NONE)
{
@@ -182,8 +184,8 @@ void LLTexUnit::enable(eTextureType type)
mCurrTexType = type;
gGL.flush();
-
- if (mIndex < gGLManager.mNumTextureUnits)
+ if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
{
glEnable(sGLTextureType[type]);
}
@@ -199,8 +201,8 @@ void LLTexUnit::disable(void)
activate();
unbind(mCurrTexType);
gGL.flush();
-
- if (mIndex < gGLManager.mNumTextureUnits)
+ if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
{
glDisable(sGLTextureType[mCurrTexType]);
}
@@ -292,7 +294,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
texture->updateBindStats(texture->mTextureMemory);
mHasMipMaps = texture->mHasMipMaps;
- if (texture->mTexOptionsDirty)
+ if (mIndex == 0 && texture->mTexOptionsDirty)
{
texture->mTexOptionsDirty = false;
setTextureAddressMode(texture->mAddressMode);
@@ -402,6 +404,7 @@ void LLTexUnit::unbind(eTextureType type)
activate();
mCurrTexture = 0;
glBindTexture(sGLTextureType[type], 0);
+ stop_glerror();
}
}
@@ -423,7 +426,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- if (mIndex < 0 || mCurrTexture == 0) return;
+ if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
gGL.flush();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 7ba14f7b40..41e7b35341 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -57,6 +57,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_NONE // No texture type is currently enabled
} eTextureType;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index da1e94df64..b6463309e1 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -63,8 +63,7 @@ LLRenderTarget::LLRenderTarget() :
mUseDepth(false),
mRenderDepth(false),
mUsage(LLTexUnit::TT_TEXTURE),
- mSamples(0),
- mSampleBuffer(NULL)
+ mSamples(0)
{
}
@@ -73,23 +72,32 @@ LLRenderTarget::~LLRenderTarget()
release();
}
-
-void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
-{
- mSampleBuffer = buffer;
-}
-
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
stop_glerror();
+
+ release();
+
mResX = resx;
mResY = resy;
mStencil = stencil;
mUsage = usage;
mUseDepth = depth;
+ mSamples = samples;
- release();
+ mSamples = gGLManager.getNumFBOFSAASamples(mSamples);
+
+ if (mSamples > 1 && gGLManager.mHasTextureMultisample)
+ {
+ mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+ //no support for multisampled stencil targets yet
+ mStencil = false;
+ }
+ else
+ {
+ mSamples = 0;
+ }
if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
{
@@ -146,29 +154,51 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
stop_glerror();
- LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+#ifdef GL_ARB_texture_multisample
+ if (mSamples > 1)
+ {
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
+ }
+ else
+#else
+ llassert_always(mSamples <= 1);
+#endif
+ {
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+
stop_glerror();
- if (offset == 0)
- {
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- }
- else
- { //don't filter data attachments
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
- if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
- {
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
- }
- else
- {
- // ATI doesn't support mirrored repeat for rectangular textures.
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ if (mSamples == 0)
+ {
+ if (offset == 0)
+ { //use bilinear filtering on single texture render targets that aren't multisampled
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ stop_glerror();
+ }
+ else
+ { //don't filter data attachments
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+ }
+
+ if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+ {
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+ stop_glerror();
+ }
+ else
+ {
+ // ATI doesn't support mirrored repeat for rectangular textures.
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+ }
}
+
if (mFBO)
{
+ stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
LLTexUnit::getInternalType(mUsage), tex, 0);
@@ -181,6 +211,12 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
mTex.push_back(tex);
+ if (gDebugGL)
+ { //bind and unbind to validate target
+ bindTarget();
+ flush();
+ }
+
}
void LLRenderTarget::allocateDepth()
@@ -197,9 +233,20 @@ void LLRenderTarget::allocateDepth()
{
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
- U32 internal_type = LLTexUnit::getInternalType(mUsage);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ if (mSamples == 0)
+ {
+ U32 internal_type = LLTexUnit::getInternalType(mUsage);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ }
+#ifdef GL_ARB_texture_multisample
+ else
+ {
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
+ }
+#else
+ llassert_always(mSamples <= 1);
+#endif
}
}
@@ -239,6 +286,9 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
}
+
+ check_framebuffer_status();
+
glBindFramebuffer(GL_FRAMEBUFFER, 0);
target.mUseDepth = true;
@@ -256,7 +306,7 @@ void LLRenderTarget::release()
}
else
{
- LLImageGL::deleteTextures(1, &mDepth);
+ LLImageGL::deleteTextures(1, &mDepth, true);
stop_glerror();
}
mDepth = 0;
@@ -285,11 +335,12 @@ void LLRenderTarget::release()
if (mTex.size() > 0)
{
- LLImageGL::deleteTextures(mTex.size(), &mTex[0]);
+ LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
mTex.clear();
}
+
+ mResX = mResY = 0;
- mSampleBuffer = NULL;
sBoundTarget = NULL;
}
@@ -298,34 +349,27 @@ void LLRenderTarget::bindTarget()
if (mFBO)
{
stop_glerror();
- if (mSampleBuffer)
- {
- mSampleBuffer->bindTarget(this);
- stop_glerror();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ stop_glerror();
+ if (gGLManager.mHasDrawBuffers)
+ { //setup multiple render targets
+ GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3};
+ glDrawBuffersARB(mTex.size(), drawbuffers);
}
- else
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- stop_glerror();
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- glDrawBuffersARB(mTex.size(), drawbuffers);
- }
- if (mTex.empty())
- { //no color buffer to draw to
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
-
- check_framebuffer_status();
-
- stop_glerror();
+ if (mTex.empty())
+ { //no color buffer to draw to
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
}
+
+ check_framebuffer_status();
+
+ stop_glerror();
}
glViewport(0, 0, mResX, mResY);
@@ -407,50 +451,8 @@ void LLRenderTarget::flush(bool fetch_depth)
else
{
stop_glerror();
-
glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
stop_glerror();
-
- if (mSampleBuffer)
- {
- LLGLEnable multisample(GL_MULTISAMPLE);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
- check_framebuffer_status();
-
- stop_glerror();
- glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- stop_glerror();
-
- if (mTex.size() > 1)
- {
- for (U32 i = 1; i < mTex.size(); ++i)
- {
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- LLTexUnit::getInternalType(mUsage), mTex[i], 0);
- stop_glerror();
- glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
- stop_glerror();
- glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- stop_glerror();
- }
-
- for (U32 i = 0; i < mTex.size(); ++i)
- {
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
- LLTexUnit::getInternalType(mUsage), mTex[i], 0);
- stop_glerror();
- glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
- stop_glerror();
- }
- }
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
@@ -467,37 +469,36 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
}
- if (mSampleBuffer)
+
+ if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
{
- mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
+ check_framebuffer_status();
+ gGL.getTexUnit(0)->bind(this, true);
+ stop_glerror();
+ glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
+ stop_glerror();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ stop_glerror();
}
else
{
- if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
- {
- stop_glerror();
-
- glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
- gGL.getTexUnit(0)->bind(this, true);
- stop_glerror();
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
- else
- {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
+ stop_glerror();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
+ glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ stop_glerror();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ stop_glerror();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ stop_glerror();
}
}
@@ -540,179 +541,3 @@ void LLRenderTarget::getViewport(S32* viewport)
viewport[3] = mResY;
}
-//==================================================
-// LLMultisampleBuffer implementation
-//==================================================
-LLMultisampleBuffer::LLMultisampleBuffer()
-{
-
-}
-
-LLMultisampleBuffer::~LLMultisampleBuffer()
-{
- release();
-}
-
-void LLMultisampleBuffer::release()
-{
- if (mFBO)
- {
- glDeleteFramebuffers(1, (GLuint *) &mFBO);
- mFBO = 0;
- }
-
- if (mTex.size() > 0)
- {
- glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]);
- mTex.clear();
- }
-
- if (mDepth)
- {
- glDeleteRenderbuffers(1, (GLuint *) &mDepth);
- mDepth = 0;
- }
-}
-
-void LLMultisampleBuffer::bindTarget()
-{
- bindTarget(this);
-}
-
-void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
-{
- if (!ref)
- {
- ref = this;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- glDrawBuffersARB(ref->mTex.size(), drawbuffers);
- }
-
- check_framebuffer_status();
-
- glViewport(0, 0, mResX, mResY);
-
- sBoundTarget = this;
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo )
-{
- allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2);
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples )
-{
- stop_glerror();
- mResX = resx;
- mResY = resy;
-
- mUsage = usage;
- mUseDepth = depth;
- mStencil = stencil;
-
- release();
-
- mSamples = samples;
-
- if (mSamples <= 1)
- {
- llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
- }
-
- stop_glerror();
-
- if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
- {
-
- if (depth)
- {
- stop_glerror();
- allocateDepth();
- stop_glerror();
- }
-
- glGenFramebuffers(1, (GLuint *) &mFBO);
-
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
- if (mDepth)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- }
- }
-
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
-
- addColorAttachment(color_fmt);
-}
-
-void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
-{
- if (color_fmt == 0)
- {
- return;
- }
-
- U32 offset = mTex.size();
- if (offset >= 4 ||
- (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
- {
- llerrs << "Too many color attachments!" << llendl;
- }
-
- U32 tex;
- glGenRenderbuffers(1, &tex);
-
- glBindRenderbuffer(GL_RENDERBUFFER, tex);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY);
- stop_glerror();
-
- if (mFBO)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
- stop_glerror();
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- switch (status)
- {
- case GL_FRAMEBUFFER_COMPLETE:
- break;
- default:
- llerrs << "WTF? " << std::hex << status << llendl;
- break;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- }
-
- mTex.push_back(tex);
-}
-
-void LLMultisampleBuffer::allocateDepth()
-{
- glGenRenderbuffers(1, (GLuint* ) &mDepth);
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- if (mStencil)
- {
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
- }
- else
- {
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16, mResX, mResY);
- }
-}
-
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 12dd1c8b90..094b58b562 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -71,10 +71,7 @@ public:
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
- void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE);
-
- //provide this render target with a multisample resource.
- void setSampleBuffer(LLMultisampleBuffer* buffer);
+ void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
//add color buffer attachment
//limit of 4 color attachments per render target
@@ -141,7 +138,6 @@ public:
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
protected:
- friend class LLMultisampleBuffer;
U32 mResX;
U32 mResY;
std::vector mTex;
@@ -152,26 +148,8 @@ protected:
bool mRenderDepth;
LLTexUnit::eTextureType mUsage;
U32 mSamples;
- LLMultisampleBuffer* mSampleBuffer;
-
- static LLRenderTarget* sBoundTarget;
-};
-
-class LLMultisampleBuffer : public LLRenderTarget
-{
-public:
- LLMultisampleBuffer();
- virtual ~LLMultisampleBuffer();
-
- virtual void release();
-
- virtual void bindTarget();
- void bindTarget(LLRenderTarget* ref);
- virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo);
- void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples);
- virtual void addColorAttachment(U32 color_fmt);
- virtual void allocateDepth();
+ static LLRenderTarget* sBoundTarget;
};
#endif //!LL_MESA_HEADLESS
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 98a0a93084..bdc103b917 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -209,17 +209,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -230,32 +252,76 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->isShiny && features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->isShiny)
{
- if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -266,17 +332,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightShinyF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -315,12 +403,12 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
else
{
- LL_INFOS("ShaderLoading") << log << LL_ENDL;
+ LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
}
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
{
GLenum error = GL_NO_ERROR;
if (gDebugGL)
@@ -374,6 +462,106 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
GLcharARB* text[1024];
GLuint count = 0;
+ if (gGLManager.mGLVersion < 3.f)
+ {
+ //set version to 1.20
+ text[count++] = strdup("#version 120\n");
+ }
+ else
+ { //set version to 1.30
+ text[count++] = strdup("#version 130\n");
+ }
+
+ //copy preprocessor definitions into buffer
+ for (std::map::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
+ {
+ std::string define = "#define " + iter->first + " " + iter->second + "\n";
+ text[count++] = (GLcharARB *) strdup(define.c_str());
+ }
+
+ if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
+ {
+ //use specified number of texture channels for indexed texture rendering
+
+ /* prepend shader code that looks like this:
+
+ uniform sampler2D tex0;
+ uniform sampler2D tex1;
+ uniform sampler2D tex2;
+ .
+ .
+ .
+ uniform sampler2D texN;
+
+ varying float vary_texture_index;
+
+ vec4 diffuseLookup(vec2 texcoord)
+ {
+ switch (int(vary_texture_index+0.25))
+ {
+ case 0: return texture2D(tex0, texcoord);
+ case 1: return texture2D(tex1, texcoord);
+ case 2: return texture2D(tex2, texcoord);
+ .
+ .
+ .
+ case N: return texture2D(texN, texcoord);
+ }
+
+ return vec4(0,0,0,0);
+ }
+ */
+
+ //uniform declartion
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string decl = llformat("uniform sampler2D tex%d;\n", i);
+ text[count++] = strdup(decl.c_str());
+ }
+
+ text[count++] = strdup("varying float vary_texture_index;\n");
+ text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
+ text[count++] = strdup("{\n");
+
+
+ if (gGLManager.mGLVersion >= 3.f)
+ {
+ text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
+ text[count++] = strdup("\t{\n");
+
+ //switch body
+ 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);
+ text[count++] = strdup(case_str.c_str());
+ }
+
+ text[count++] = strdup("\t}\n");
+ }
+ else
+ {
+ //switches aren't supported, make block that looks like:
+ /*
+ int ti = int(vary_texture_index+0.25);
+ if (ti == 0) return texture2D(tex0, texcoord);
+ if (ti == 1) return texture2D(tex1, texcoord);
+ .
+ .
+ .
+ if (ti == N) return texture2D(texN, texcoord);
+ */
+
+ text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n");
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
+ text[count++] = strdup(if_str.c_str());
+ }
+ }
+
+ text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+ text[count++] = strdup("}\n");
+ }
//copy file into memory
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) )
@@ -457,7 +645,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
- return loadShaderFile(filename,shader_level,type);
+ return loadShaderFile(filename,shader_level,type,texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index c54c4608d7..2f30103811 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -43,7 +43,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@@ -60,6 +60,9 @@ public:
std::vector mReservedUniforms;
+ //preprocessor definitions (name/value)
+ std::map mDefinitions;
+
protected:
// our parameter manager singleton instance
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 8c9171ccf4..4a0b964e61 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -934,8 +934,26 @@ void LLVertexBuffer::allocateClientIndexBuffer()
}
}
+bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
+{
+ S32 end = index+count;
+ S32 region_end = region.mIndex+region.mCount;
+
+ if (end < region.mIndex ||
+ index > region_end)
+ { //gap exists, do not merge
+ return false;
+ }
+
+ S32 new_end = llmax(end, region_end);
+ S32 new_index = llmin(index, region.mIndex);
+ region.mIndex = new_index;
+ region.mCount = new_end-new_index;
+ return true;
+}
+
// Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
+U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@@ -947,8 +965,45 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
}
- if (!mVertexLocked && useVBOs())
+ if (useVBOs())
{
+
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ if (count == -1)
+ {
+ count = mNumVerts-index;
+ }
+
+ bool mapped = false;
+ //see if range is already mapped
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedVertexRegions[i];
+ if (region.mType == type)
+ {
+ if (expand_region(region, index, count))
+ {
+ mapped = true;
+ break;
+ }
+ }
+ }
+
+ if (!mapped)
+ {
+ //not already mapped, map new region
+ MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
+ mMappedVertexRegions.push_back(region);
+ }
+ }
+
+ if (mVertexLocked && map_range)
+ {
+ llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+ }
+
+ if (!mVertexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
setBuffer(0, type);
@@ -957,61 +1012,95 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientVertexBuffer() ;
}
else
{
- U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_range)
+ {
+ S32 offset = mOffsets[type] + sTypeSize[type]*index;
+ S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
mMappedData = LL_NEXT_ALIGNED_ADDRESS(src);
mAlignedOffset = mMappedData - src;
stop_glerror();
}
- }
-
-
- if (!mMappedData)
- {
- log_glerror();
+
+ if (!mMappedData)
+ {
+ log_glerror();
- //check the availability of memory
- U32 avail_phy_mem, avail_vir_mem;
- LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
- llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
- llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
+ //check the availability of memory
+ U32 avail_phy_mem, avail_vir_mem;
+ LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
+ llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
+ llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
- if(!sDisableVBOMapping)
- {
- //--------------------
- //print out more debug info before crash
- llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
- GLint size ;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
- llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
- //--------------------
+ if(!sDisableVBOMapping)
+ {
+ //--------------------
+ //print out more debug info before crash
+ llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
+ GLint size ;
+ glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
+ llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
+ //--------------------
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
- {
- llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
- }
+ GLint buff;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLBuffer)
+ {
+ llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ }
- llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
- }
- else
- {
- llerrs << "memory allocation for vertex data failed." << llendl ;
+ llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+ }
+ else
+ {
+ llerrs << "memory allocation for vertex data failed." << llendl ;
+ }
}
+ sMappedCount++;
}
- sMappedCount++;
+ }
+ else
+ {
+ map_range = false;
}
- return mMappedData;
+ if (map_range && !sDisableVBOMapping)
+ {
+ return mMappedData;
+ }
+ else
+ {
+ return mMappedData+mOffsets[type]+sTypeSize[type]*index;
+ }
}
-U8* LLVertexBuffer::mapIndexBuffer(S32 access)
+U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@@ -1023,8 +1112,41 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
}
- if (!mIndexLocked && useVBOs())
+ if (useVBOs())
{
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ if (count == -1)
+ {
+ count = mNumIndices-index;
+ }
+
+ bool mapped = false;
+ //see if range is already mapped
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedIndexRegions[i];
+ if (expand_region(region, index, count))
+ {
+ mapped = true;
+ break;
+ }
+ }
+
+ if (!mapped)
+ {
+ //not already mapped, map new region
+ MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
+ mMappedIndexRegions.push_back(region);
+ }
+ }
+
+ if (mIndexLocked && map_range)
+ {
+ llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+ }
+
+ if (!mIndexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
@@ -1034,12 +1156,36 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientIndexBuffer() ;
}
else
{
- U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS(src);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_range)
+ {
+ S32 offset = sizeof(U16)*index;
+ S32 length = sizeof(U16)*count;
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
+ mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS(src);
mAlignedIndexOffset = mMappedIndexData - src;
stop_glerror();
}
@@ -1068,31 +1214,81 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
sMappedCount++;
}
+ else
+ {
+ map_range = false;
+ }
- return mMappedIndexData ;
+ if (map_range && !sDisableVBOMapping)
+ {
+ return mMappedIndexData;
+ }
+ else
+ {
+ return mMappedIndexData + sizeof(U16)*index;
+ }
}
void LLVertexBuffer::unmapBuffer(S32 type)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
- if (!useVBOs())
+ if (!useVBOs() || type == -2)
{
return ; //nothing to unmap
}
bool updated_all = false ;
+
if (mMappedData && mVertexLocked && type != TYPE_INDEX)
{
updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
if(sDisableVBOMapping)
{
- stop_glerror();
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
- stop_glerror();
+ if (!mMappedVertexRegions.empty())
+ {
+ stop_glerror();
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedVertexRegions[i];
+ S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+ S32 length = sTypeSize[region.mType]*region.mCount;
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
+ stop_glerror();
+ }
+
+ mMappedVertexRegions.clear();
+ }
+ else
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+ stop_glerror();
+ }
}
else
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (!mMappedVertexRegions.empty())
+ {
+ stop_glerror();
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedVertexRegions[i];
+ S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+ S32 length = sTypeSize[region.mType]*region.mCount;
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedVertexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1103,17 +1299,53 @@ void LLVertexBuffer::unmapBuffer(S32 type)
mVertexLocked = FALSE ;
sMappedCount--;
}
-
- if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
+
+ if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
{
if(sDisableVBOMapping)
{
- stop_glerror();
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
- stop_glerror();
+ if (!mMappedIndexRegions.empty())
+ {
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+ S32 length = sizeof(U16)*region.mCount;
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
+ stop_glerror();
+ }
+
+ mMappedIndexRegions.clear();
+ }
+ else
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+ stop_glerror();
+ }
}
else
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (!mMappedIndexRegions.empty())
+ {
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+ S32 length = sizeof(U16)*region.mCount;
+ glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedIndexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1152,19 +1384,19 @@ template struct VertexBufferStrider
typedef LLStrider strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
- S32 index)
+ S32 index, S32 count, bool map_range)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
- S32 stride = sizeof(T);
+ U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
- if (vbo.mapIndexBuffer() == NULL)
+ if (ptr == NULL)
{
llwarns << "mapIndexBuffer failed!" << llendl;
return FALSE;
}
- strider = (T*)(vbo.getMappedIndices() + index*stride);
+ strider = (T*)ptr;
strider.setStride(0);
return TRUE;
}
@@ -1172,13 +1404,15 @@ template struct VertexBufferStrider
{
S32 stride = LLVertexBuffer::sTypeSize[type];
- if (vbo.mapVertexBuffer(type) == NULL)
+ U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+
+ if (ptr == NULL)
{
llwarns << "mapVertexBuffer failed!" << llendl;
return FALSE;
}
- strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride);
+ strider = (T*)ptr;
strider.setStride(stride);
return TRUE;
}
@@ -1190,55 +1424,48 @@ template struct VertexBufferStrider
}
};
-bool LLVertexBuffer::getVertexStrider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getVertexStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getIndexStrider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getIndexStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getTexCoord0Strider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getTexCoord0Strider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getTexCoord1Strider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getTexCoord1Strider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
-}
-/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
-}
-bool LLVertexBuffer::getTexCoord3Strider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
-}*/
-bool LLVertexBuffer::getNormalStrider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
-}
-bool LLVertexBuffer::getBinormalStrider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
-}
-bool LLVertexBuffer::getColorStrider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
-}
-bool LLVertexBuffer::getWeightStrider(LLStrider& strider, S32 index)
-{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getNormalStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
+}
+bool LLVertexBuffer::getBinormalStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
+}
+bool LLVertexBuffer::getColorStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
+}
+bool LLVertexBuffer::getWeightStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 index)
+bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider::get(*this, strider, index);
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
+}
+
+bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider::get(*this, strider, index, count, map_range);
}
//----------------------------------------------------------------------------
@@ -1497,17 +1724,16 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
}
if (data_mask & MAP_VERTEX)
{
- glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ if (data_mask & MAP_TEXTURE_INDEX)
+ {
+ glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ }
+ else
+ {
+ glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ }
}
llglassertok();
}
-void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
-{
- // TODO: use GL_APPLE_flush_buffer_range here
- /*if (useVBOs() && !mFilthy)
- {
-
- }*/
-}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index a9f22193f8..aa5df305a6 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -77,6 +77,18 @@ protected:
class LLVertexBuffer : public LLRefCount
{
public:
+ class MappedRegion
+ {
+ public:
+ S32 mType;
+ S32 mIndex;
+ S32 mCount;
+
+ MappedRegion(S32 type, S32 index, S32 count)
+ : mType(type), mIndex(index), mCount(count)
+ { }
+ };
+
LLVertexBuffer(const LLVertexBuffer& rhs)
{
*this = rhs;
@@ -130,6 +142,9 @@ public:
TYPE_CLOTHWEIGHT,
TYPE_MAX,
TYPE_INDEX,
+
+ //no actual additional data, but indicates position.w is texture index
+ TYPE_TEXTURE_INDEX,
};
enum {
MAP_VERTEX = (1<getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
- bool getVertexStrider(LLStrider& strider, S32 index=0);
- bool getIndexStrider(LLStrider& strider, S32 index=0);
- bool getTexCoord0Strider(LLStrider& strider, S32 index=0);
- bool getTexCoord1Strider(LLStrider& strider, S32 index=0);
- bool getNormalStrider(LLStrider& strider, S32 index=0);
- bool getBinormalStrider(LLStrider& strider, S32 index=0);
- bool getColorStrider(LLStrider& strider, S32 index=0);
- bool getWeightStrider(LLStrider& strider, S32 index=0);
- bool getWeight4Strider(LLStrider& strider, S32 index=0);
- bool getClothWeightStrider(LLStrider& strider, S32 index=0);
+ bool getVertexStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getIndexStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTexCoord0Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTexCoord1Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getNormalStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getBinormalStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getColorStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getWeight4Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getClothWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false);
BOOL isEmpty() const { return mEmpty; }
BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
@@ -218,8 +234,6 @@ public:
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
- void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
-
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
@@ -253,20 +267,8 @@ protected:
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
S32 mOffsets[TYPE_MAX];
- class DirtyRegion
- {
- public:
- U32 mIndex;
- U32 mCount;
- U32 mIndicesIndex;
- U32 mIndicesCount;
-
- DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
- : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
- { }
- };
-
- std::vector mDirtyRegions; //vector of dirty regions to rebuild
+ std::vector mMappedVertexRegions;
+ std::vector mMappedIndexRegions;
public:
static S32 sCount;
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 39385786bc..820e7cb26a 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)
char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
if ( new_locale_string == NULL)
{
- llwarns << "Failed to set locale " << locale_string << llendl;
+ LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;
setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
}
//else
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 6b4e9cf923..15a7438ec9 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
: label_width("label_width"),
decimal_digits("decimal_digits"),
allow_text_entry("allow_text_entry", true),
+ label_wrap("label_wrap", false),
text_enabled_color("text_enabled_color"),
text_disabled_color("text_disabled_color"),
up_button("up_button"),
@@ -80,6 +81,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
{
LLRect label_rect( 0, centered_top, label_width, centered_bottom );
LLTextBox::Params params;
+ params.wrap(p.label_wrap);
params.name("SpinCtrl Label");
params.rect(label_rect);
params.initial_value(p.label());
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 8960971594..d197084e38 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -44,6 +44,7 @@ public:
Optional label_width;
Optional decimal_digits;
Optional allow_text_entry;
+ Optional label_wrap;
Optional text_enabled_color;
Optional text_disabled_color;
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 937c4e4c6a..9f4e89691f 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -20,6 +20,7 @@
tags
AppInit
+ Capabilities
SystemInfo
TextureCache
AppCache
@@ -43,6 +44,7 @@
+ Capabilities
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ac6ea0f860..76fecdf05e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5589,10 +5589,10 @@
Value
0
- MeshUseWholeModelUpload
+ MeshUploadLogXML
+ MeshUploadFakeErrors
+
MigrateCacheDirectory
- RenderAnisotropic
+
+ OctreeMaxNodeCapacity
+
+
+ OctreeStaticObjectSizeFactor
+
+
+ OctreeAlphaDistanceFactor
+
+
+ OctreeAttachmentSizeFactor
+
+
+ OctreeDistanceFactor
+
+
+ RenderAnisotropic
RenderAvatarVP
+ RenderMaxTextureIndex
+
RenderDebugTextureBind
RenderMaxVBOSize
RenderUseStreamVBO
MeshThreadCount
- Free to join
+ 免費加入
L$[AMOUNT] to join
@@ -26,7 +26,7 @@ Fear the moose! Fear it! And the mongoose too!
L$123 to join
-
-
+
+
diff --git a/indra/newview/skins/default/xui/zh/inspect_object.xml b/indra/newview/skins/default/xui/zh/inspect_object.xml
index f1fe037087..58091b3aef 100644
--- a/indra/newview/skins/default/xui/zh/inspect_object.xml
+++ b/indra/newview/skins/default/xui/zh/inspect_object.xml
@@ -35,7 +35,7 @@ owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
http://www.superdupertest.com
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_attachment_other.xml b/indra/newview/skins/default/xui/zh/menu_attachment_other.xml
index cba82e7dce..a04d59bc81 100644
--- a/indra/newview/skins/default/xui/zh/menu_attachment_other.xml
+++ b/indra/newview/skins/default/xui/zh/menu_attachment_other.xml
@@ -12,6 +12,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_avatar_icon.xml b/indra/newview/skins/default/xui/zh/menu_avatar_icon.xml
index 1da583b3d0..ef0986a13b 100644
--- a/indra/newview/skins/default/xui/zh/menu_avatar_icon.xml
+++ b/indra/newview/skins/default/xui/zh/menu_avatar_icon.xml
@@ -3,5 +3,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_avatar_other.xml b/indra/newview/skins/default/xui/zh/menu_avatar_other.xml
index 283367708b..acf98dfdfa 100644
--- a/indra/newview/skins/default/xui/zh/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/zh/menu_avatar_other.xml
@@ -12,5 +12,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml b/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml
index 8e30a15562..e053eb2388 100644
--- a/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml
index bae7cf3f05..0f14057c07 100644
--- a/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml
@@ -16,6 +16,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/zh/menu_inspect_object_gear.xml
index dab95fcadc..94ab82b8a9 100644
--- a/indra/newview/skins/default/xui/zh/menu_inspect_object_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inspect_object_gear.xml
@@ -1,18 +1,18 @@
-
-
+
+
-
+
-
+
-
-
+
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_inventory.xml b/indra/newview/skins/default/xui/zh/menu_inventory.xml
index fd8f73e4ea..a93e8be149 100644
--- a/indra/newview/skins/default/xui/zh/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inventory.xml
@@ -28,17 +28,17 @@
-
-
-
-
+
+
+
+
-
+
-
+
@@ -46,19 +46,19 @@
-
-
+
+
-
+
-
+
@@ -66,11 +66,11 @@
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml
index 8c938222e7..f51b27d9ce 100644
--- a/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml
@@ -3,12 +3,12 @@
-
-
-
+
+
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_landmark.xml b/indra/newview/skins/default/xui/zh/menu_landmark.xml
index 5f7657db79..7372b223cf 100644
--- a/indra/newview/skins/default/xui/zh/menu_landmark.xml
+++ b/indra/newview/skins/default/xui/zh/menu_landmark.xml
@@ -2,6 +2,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_login.xml b/indra/newview/skins/default/xui/zh/menu_login.xml
index 27a0baf560..d6bf34c66e 100644
--- a/indra/newview/skins/default/xui/zh/menu_login.xml
+++ b/indra/newview/skins/default/xui/zh/menu_login.xml
@@ -11,15 +11,15 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
index 169dbf2187..cf47020bd9 100644
--- a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
@@ -18,10 +18,10 @@
-
-
-
-
+
+
+
+
diff --git a/indra/newview/skins/default/xui/zh/menu_participant_list.xml b/indra/newview/skins/default/xui/zh/menu_participant_list.xml
index 7b6f6f954e..3737e3d041 100644
--- a/indra/newview/skins/default/xui/zh/menu_participant_list.xml
+++ b/indra/newview/skins/default/xui/zh/menu_participant_list.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml
index 06247ab249..cf36507d74 100644
--- a/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml
+++ b/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_people_nearby.xml b/indra/newview/skins/default/xui/zh/menu_people_nearby.xml
index 73b754e059..49fa775424 100644
--- a/indra/newview/skins/default/xui/zh/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/zh/menu_people_nearby.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml
index 4ffbcaff83..c7aff48df4 100644
--- a/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml
+++ b/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml
@@ -5,6 +5,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_picks_plus.xml b/indra/newview/skins/default/xui/zh/menu_picks_plus.xml
index 9e55c633f9..e962bd90d5 100644
--- a/indra/newview/skins/default/xui/zh/menu_picks_plus.xml
+++ b/indra/newview/skins/default/xui/zh/menu_picks_plus.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_place.xml b/indra/newview/skins/default/xui/zh/menu_place.xml
index 6ffdf329df..3733baf119 100644
--- a/indra/newview/skins/default/xui/zh/menu_place.xml
+++ b/indra/newview/skins/default/xui/zh/menu_place.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/zh/menu_places_gear_folder.xml
index 7f1d091f44..7f4144d14d 100644
--- a/indra/newview/skins/default/xui/zh/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/zh/menu_places_gear_folder.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/zh/menu_places_gear_landmark.xml
index 8578751a28..f23d970b78 100644
--- a/indra/newview/skins/default/xui/zh/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/zh/menu_places_gear_landmark.xml
@@ -15,5 +15,5 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_profile_overflow.xml b/indra/newview/skins/default/xui/zh/menu_profile_overflow.xml
index c06b7dc039..ca637ae54d 100644
--- a/indra/newview/skins/default/xui/zh/menu_profile_overflow.xml
+++ b/indra/newview/skins/default/xui/zh/menu_profile_overflow.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml
index e7016dc663..6d70ac4c1f 100644
--- a/indra/newview/skins/default/xui/zh/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml
@@ -54,7 +54,7 @@
-
+
@@ -84,21 +84,21 @@
-
+
-
+
-
-
+
+
-
-
+
+
@@ -110,16 +110,16 @@
-
+
-
-
-
-
+
+
+
+
@@ -135,12 +135,12 @@
-
+
-
-
-
+
+
+
@@ -149,8 +149,8 @@
-
-
+
+
@@ -190,7 +190,7 @@
-
+
@@ -226,7 +226,7 @@
-
+
@@ -338,10 +338,10 @@
-
+
-
+
@@ -355,10 +355,10 @@
-
-
-
-
+
+
+
+
diff --git a/indra/newview/skins/default/xui/zh/mime_types.xml b/indra/newview/skins/default/xui/zh/mime_types.xml
index d2d1321c2a..3498942f9b 100644
--- a/indra/newview/skins/default/xui/zh/mime_types.xml
+++ b/indra/newview/skins/default/xui/zh/mime_types.xml
@@ -176,7 +176,7 @@
diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml
index 16d4965d5a..65bb8ce517 100644
--- a/indra/newview/skins/default/xui/zh/notifications.xml
+++ b/indra/newview/skins/default/xui/zh/notifications.xml
@@ -1242,7 +1242,7 @@ Replace texture [TEXTURE_NUM] with a 24-bit 512x512 or smaller image then click
You can only have [MAX_AGENTS] Allowed Residents.
- You can only have [MAX_BANNED] Banned Residents.
+ 你只可以有最多 [MAX_BANNED] 位被封鎖的居民。
Failure while attempting to add [NUM_ADDED] agents:
@@ -1253,10 +1253,10 @@ Exceeds the [MAX_AGENTS] [LIST_TYPE] limit by [NUM_EXCESS].
- You can only have [MAX_MANAGER] Estate Managers.
+ 你只可以有最多 [MAX_MANAGER] 位領地經理。
- Can't add estate owner to estate 'Banned Resident' list.
+ 無法添加領地擁有者到領地的 '被封鎖的居民' 名單中。
無法變更外觀,直到服裝與體形下載完畢。
@@ -1273,15 +1273,15 @@ Please set the object for sale and try again.
[DOWNLOAD_PATH].
- A new version of [APP_NAME] is available.
+ 一個新版本的 [APP_NAME] 已經可用。
[MESSAGE]
-You must download this update to use [APP_NAME].
+你必須下載這個更新以使用 [APP_NAME]。
- An updated version of [APP_NAME] is available.
+ 一個 [APP_NAME] 更新過的版本已經可用。
[MESSAGE]
-This update is not required, but we suggest you install it to improve performance and stability.
+這個更新並非強制更新,但我們建議你安裝以增強效能及穩定性。
@@ -1356,12 +1356,12 @@ or you can install it now.
We have downloaded an update to your [APP_NAME] installation.
Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update]
-
+
We have downloaded an update to your [APP_NAME] installation.
Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update]
-
+
We have downloaded a required software update.
@@ -1371,7 +1371,7 @@ We must restart [APP_NAME] to install the update.
- We must restart [APP_NAME] to install the update.
+ 我門必須重新啟動 [APP_NAME] 以安裝更新。
@@ -1569,17 +1569,17 @@ Please try again later.
瞬間傳送到 [PICK]?
-
+
瞬間傳送到 [CLASSIFIED]?
-
+
瞬間傳送到 [HISTORY_ENTRY]?
-
+
-
+
Type a short announcement which will be sent to everyone currently in your estate.
-
+
You are in Busy Mode, which means you will not receive any items offered in exchange for this payment.
Would you like to leave Busy Mode before completing this transaction?
diff --git a/indra/newview/skins/default/xui/zh/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/zh/panel_adhoc_control_panel.xml
index c9e47984e2..7d16ac4129 100644
--- a/indra/newview/skins/default/xui/zh/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/default/xui/zh/panel_adhoc_control_panel.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/zh/panel_avatar_list_item.xml
index 23b76eea9b..eccb938f15 100644
--- a/indra/newview/skins/default/xui/zh/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/zh/panel_avatar_list_item.xml
@@ -21,7 +21,7 @@
[COUNT]y
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_hair.xml b/indra/newview/skins/default/xui/zh/panel_edit_hair.xml
index 0578fe9ef1..d9ddafac3b 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_hair.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_hair.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_pants.xml b/indra/newview/skins/default/xui/zh/panel_edit_pants.xml
index b453fdc758..76560256f7 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_pants.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_pants.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_pick.xml b/indra/newview/skins/default/xui/zh/panel_edit_pick.xml
index 0f1f72ceb9..6ac7226185 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_pick.xml
@@ -1,16 +1,16 @@
-
+
- (will update after save)
+ (將在儲存後更新)
- Edit Pick
+ 編輯精選地點
- Title:
+ 標題:
描述:
@@ -21,13 +21,13 @@
載入中...
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_shape.xml b/indra/newview/skins/default/xui/zh/panel_edit_shape.xml
index da6049ea75..f249100786 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_shape.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_shape.xml
@@ -1,25 +1,25 @@
- Meters
+ 公尺
- Feet
+ 英呎
- Height:
+ 身高:
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_shirt.xml b/indra/newview/skins/default/xui/zh/panel_edit_shirt.xml
index 321fb68756..ecfc1e2fad 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_shirt.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_shirt.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_skirt.xml b/indra/newview/skins/default/xui/zh/panel_edit_skirt.xml
index 096a83c871..5c46f94fe9 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_skirt.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_skirt.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_socks.xml b/indra/newview/skins/default/xui/zh/panel_edit_socks.xml
index dab132bad2..09c888f226 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_socks.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_socks.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
index d183e6897d..946f8b22dc 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
index d741ed70df..936a2651ab 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
@@ -49,16 +49,16 @@
Editing Physics
- Shape:
+ 體形:
- Skin:
+ 皮膚:
- Hair:
+ 頭髮:
- Eyes:
+ 眼睛:
襯衫:
diff --git a/indra/newview/skins/default/xui/zh/panel_group_general.xml b/indra/newview/skins/default/xui/zh/panel_group_general.xml
index 1706541f2b..a97a35056b 100644
--- a/indra/newview/skins/default/xui/zh/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/zh/panel_group_general.xml
@@ -6,7 +6,7 @@
Hover your mouse over the options for more help.
- General group information has changed
+ 一般社團資訊已經被變更
Retrieving member data
@@ -17,7 +17,7 @@ Hover your mouse over the options for more help.
創辦人:
- Free
+ 免費
@@ -50,7 +50,7 @@ Hover your mouse over the options for more help.
- 選擇內容分級 -
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_group_invite.xml b/indra/newview/skins/default/xui/zh/panel_group_invite.xml
index 0a0a1f1941..a1395f454b 100644
--- a/indra/newview/skins/default/xui/zh/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/zh/panel_group_invite.xml
@@ -19,7 +19,7 @@
Choose what Role to assign them to:
-
+
社團邀請
diff --git a/indra/newview/skins/default/xui/zh/panel_group_land_money.xml b/indra/newview/skins/default/xui/zh/panel_group_land_money.xml
index 71f139a3e6..58022c2279 100644
--- a/indra/newview/skins/default/xui/zh/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/zh/panel_group_land_money.xml
@@ -22,9 +22,9 @@
-
-
-
+
+
+
Total contribution:
diff --git a/indra/newview/skins/default/xui/zh/panel_group_notices.xml b/indra/newview/skins/default/xui/zh/panel_group_notices.xml
index 5fed96dbd9..65c07e7137 100644
--- a/indra/newview/skins/default/xui/zh/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/zh/panel_group_notices.xml
@@ -6,11 +6,11 @@ Notices only go to group members in Roles with the ability to receive Notices.
You can turn off Notices on the General tab.
- There are no past notices
+ 沒有過去的通知
- Notices are kept for 14 days.
-Maximum 200 per group daily
+ 通知保留 14 天。
+每個社團一天最多 200 則
@@ -18,7 +18,7 @@ Maximum 200 per group daily
- None found
+ 沒發現。
@@ -39,16 +39,16 @@ Maximum 200 per group daily
將物品拖曳並丟於此處以添加為附件:
-
-
+
+
- Archived Notice
+ 存檔的通知
- To send a new notice, click the + button
+ 要送出一個新通知,點擊 + 按鈕
主旨:
diff --git a/indra/newview/skins/default/xui/zh/panel_group_roles.xml b/indra/newview/skins/default/xui/zh/panel_group_roles.xml
index 8947ab6e45..fff4383893 100644
--- a/indra/newview/skins/default/xui/zh/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/zh/panel_group_roles.xml
@@ -19,7 +19,7 @@ clicking on their names.
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_im_control_panel.xml b/indra/newview/skins/default/xui/zh/panel_im_control_panel.xml
index 881f8eac0b..703182e04d 100644
--- a/indra/newview/skins/default/xui/zh/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/zh/panel_im_control_panel.xml
@@ -14,7 +14,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_me.xml b/indra/newview/skins/default/xui/zh/panel_me.xml
index abdbfd7429..a236dfc17a 100644
--- a/indra/newview/skins/default/xui/zh/panel_me.xml
+++ b/indra/newview/skins/default/xui/zh/panel_me.xml
@@ -2,6 +2,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml b/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml
index f3163e3c19..059a78cf7d 100644
--- a/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml
+++ b/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml
@@ -11,7 +11,7 @@
預覽
- Current Page:
+ 目前頁面:
diff --git a/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml
index 6e2d47c09e..3645f471ce 100644
--- a/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml
+++ b/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml
@@ -1,18 +1,18 @@
- Controls:
+ 控制:
- Standard
+ 標準
- Mini
+ 迷你
- Owner
+ 擁有者
@@ -22,7 +22,7 @@
- Anyone
+ 任何人
diff --git a/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml
index 724cd54bf1..3cabfcfaba 100644
--- a/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml
+++ b/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/indra/newview/skins/default/xui/zh/panel_nearby_media.xml b/indra/newview/skins/default/xui/zh/panel_nearby_media.xml
index 0b8a7a5f42..5ab6837569 100644
--- a/indra/newview/skins/default/xui/zh/panel_nearby_media.xml
+++ b/indra/newview/skins/default/xui/zh/panel_nearby_media.xml
@@ -44,13 +44,13 @@
-
+
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_notify_textbox.xml b/indra/newview/skins/default/xui/zh/panel_notify_textbox.xml
index bdbc89f71c..01a8210338 100644
--- a/indra/newview/skins/default/xui/zh/panel_notify_textbox.xml
+++ b/indra/newview/skins/default/xui/zh/panel_notify_textbox.xml
@@ -1,11 +1,11 @@
-
+
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_outfit_edit.xml b/indra/newview/skins/default/xui/zh/panel_outfit_edit.xml
index 6ceaf447a7..263106d13a 100644
--- a/indra/newview/skins/default/xui/zh/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/zh/panel_outfit_edit.xml
@@ -15,7 +15,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_pick_info.xml b/indra/newview/skins/default/xui/zh/panel_pick_info.xml
index 44ae5703c6..cd4cdbf999 100644
--- a/indra/newview/skins/default/xui/zh/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/zh/panel_pick_info.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_picks.xml b/indra/newview/skins/default/xui/zh/panel_picks.xml
index 3b356967f9..a233092dc2 100644
--- a/indra/newview/skins/default/xui/zh/panel_picks.xml
+++ b/indra/newview/skins/default/xui/zh/panel_picks.xml
@@ -1,28 +1,28 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_place_profile.xml b/indra/newview/skins/default/xui/zh/panel_place_profile.xml
index b0919c9151..aa7b036398 100644
--- a/indra/newview/skins/default/xui/zh/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/zh/panel_place_profile.xml
@@ -11,7 +11,7 @@
-
+
@@ -60,11 +60,11 @@
-
+
-
+
-
+
@@ -78,7 +78,7 @@
-
+
@@ -103,7 +103,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml b/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml
index a39402c858..c691edb11c 100644
--- a/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml
@@ -33,7 +33,7 @@
Use machine translation while chatting (powered by Google)
- Translate chat into:
+ 聊天翻譯為:
diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_general.xml b/indra/newview/skins/default/xui/zh/panel_preferences_general.xml
index c7299ad8a9..b7449dad10 100644
--- a/indra/newview/skins/default/xui/zh/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/zh/panel_preferences_general.xml
@@ -17,10 +17,10 @@
- (Requires restart)
+ (須重新啟動)
- I want to access content rated:
+ 我想要能進出內容分級的地區為:
@@ -36,34 +36,34 @@
- Name tags:
+ 名稱標籤:
-
+
-
-
-
+
+
+
- Pressing letter keys:
+ 按下字母鍵:
-
-
+
+
- Away timeout:
+ 離開逾時設定:
-
-
-
-
-
-
+
+
+
+
+
+
忙碌模式回應:
diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_move.xml b/indra/newview/skins/default/xui/zh/panel_preferences_move.xml
index ff582d774b..de296f72f3 100644
--- a/indra/newview/skins/default/xui/zh/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/zh/panel_preferences_move.xml
@@ -13,9 +13,9 @@
Mouselook mouse sensitivity:
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml b/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml
index 2cab05e2ad..305d1e2ac9 100644
--- a/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml
@@ -10,29 +10,29 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
- Voice Chat Settings
+ 語音聊天設定
- Listen from:
+ 傾聽位置:
-
-
+
+
-
+
-
+
@@ -49,7 +49,7 @@
輸入
- My volume:
+ 我的音量:
diff --git a/indra/newview/skins/default/xui/zh/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/zh/panel_prim_media_controls.xml
index 71de9f861a..8d0e2a6355 100644
--- a/indra/newview/skins/default/xui/zh/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/zh/panel_prim_media_controls.xml
@@ -40,7 +40,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_profile.xml b/indra/newview/skins/default/xui/zh/panel_profile.xml
index 7536311daf..fcf7bb64db 100644
--- a/indra/newview/skins/default/xui/zh/panel_profile.xml
+++ b/indra/newview/skins/default/xui/zh/panel_profile.xml
@@ -32,7 +32,7 @@
-
+
@@ -59,7 +59,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_profile_view.xml b/indra/newview/skins/default/xui/zh/panel_profile_view.xml
index ac8c7cad3d..12fe776e45 100644
--- a/indra/newview/skins/default/xui/zh/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/zh/panel_profile_view.xml
@@ -14,7 +14,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_region_covenant.xml b/indra/newview/skins/default/xui/zh/panel_region_covenant.xml
index 2e52efb804..315bc0ac8e 100644
--- a/indra/newview/skins/default/xui/zh/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/zh/panel_region_covenant.xml
@@ -62,18 +62,18 @@
分級:
- Adult
+ 成人
- Resale:
+ 轉售:
- Land in this region may not be resold.
+ 這地區的土地不能轉售。
- Subdivide:
+ 分割:
- Land in this region may not be joined/subdivided.
+ 這地區的土地不能合併或分割。
diff --git a/indra/newview/skins/default/xui/zh/panel_region_debug.xml b/indra/newview/skins/default/xui/zh/panel_region_debug.xml
index 798831bc84..1ffbcbf8fd 100644
--- a/indra/newview/skins/default/xui/zh/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/zh/panel_region_debug.xml
@@ -11,24 +11,24 @@
- Object Return
+ 物件退回
- Resident:
+ 居民:
(無)
-
+
選項:
-
+
-
+
-
-
+
+
diff --git a/indra/newview/skins/default/xui/zh/panel_region_estate.xml b/indra/newview/skins/default/xui/zh/panel_region_estate.xml
index 899191c3f0..1f1676167b 100644
--- a/indra/newview/skins/default/xui/zh/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/zh/panel_region_estate.xml
@@ -27,7 +27,7 @@
-
+
領地管理員:
diff --git a/indra/newview/skins/default/xui/zh/panel_region_general.xml b/indra/newview/skins/default/xui/zh/panel_region_general.xml
index 71caaf1144..dce75c997d 100644
--- a/indra/newview/skins/default/xui/zh/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/zh/panel_region_general.xml
@@ -7,7 +7,7 @@
未知
- Version:
+ 版本:
未知
@@ -22,22 +22,22 @@
-
-
+
+
-
+
分級:
-
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_side_tray.xml b/indra/newview/skins/default/xui/zh/panel_side_tray.xml
index 85ac4613dd..625213e376 100644
--- a/indra/newview/skins/default/xui/zh/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/zh/panel_side_tray.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/panel_teleport_history.xml b/indra/newview/skins/default/xui/zh/panel_teleport_history.xml
index 6c81ede76c..a2a63db000 100644
--- a/indra/newview/skins/default/xui/zh/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/zh/panel_teleport_history.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/indra/newview/skins/default/xui/zh/sidepanel_appearance.xml b/indra/newview/skins/default/xui/zh/sidepanel_appearance.xml
index 6f8f19b26d..7d8a502594 100644
--- a/indra/newview/skins/default/xui/zh/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/zh/sidepanel_appearance.xml
@@ -8,7 +8,7 @@
- (Status)
+ (狀態)
MyOutfit With a really Long Name like MOOSE
diff --git a/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml b/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml
index de5a10ba51..f308f2d4d0 100644
--- a/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml
@@ -58,18 +58,18 @@
- Click to:
+ 點擊以:
-
-
-
-
-
+
+
+
+
+
- You can modify this object
+ 你能修改這個物件
任何人:
@@ -115,9 +115,9 @@
-
-
+
+
-
+
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index 211d91a707..986ab82523 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -5,19 +5,19 @@
that are returned from one component and may appear in many places-->
- Second Life
+ 第二人生
- Second Life
+ 第二人生
- SECOND LIFE
+ 第二人生
- Second Life Grid
+ 第二人生網格
- Second Life Support Portal
+ 第二人生支援入口
硬體偵測中...
@@ -131,10 +131,10 @@
http://join.secondlife.com/
- This region may be experiencing trouble. Please check your connection to the Internet.
+ 這個地區可能遭遇問題,請檢查你的網路連線。
- Saving your settings...
+ 你的設定儲存中...
登出中...
@@ -149,10 +149,10 @@
You were sent to an invalid region.
- Testing viewer disconnect
+ 測試瀏覽器斷線
- Person
+ 人
(no name)
@@ -173,41 +173,41 @@
Group Build
- No Build
+ 禁止建造
- Group Build
+ 社團建造
- Not Safe
+ 非安全
禁止飛行
- Group Scripts
+ 社團腳本
- No Scripts
+ 禁止腳本
土地:
- Only a single item can be dragged here
+ 只有一個物品可以被拖曳到此處
點擊以察看這個網頁
- Click to view this location's information
+ 點擊以察看這個位置資訊
- Click to view this Resident's profile
+ 點擊以察看這個居民檔案
- Learn more about this Resident
+ 瞭解更多有關這個居民
Click to mute this Resident
@@ -219,7 +219,7 @@
點擊開始 IM 這位居民
- Click to Pay this Resident
+ 點擊以支付這位居民
Click to offer a teleport request to this Resident
@@ -268,7 +268,7 @@
IM
- Pay
+ 支付
Offer Teleport to
@@ -286,7 +286,7 @@
關閉
- Restore
+ 還原
最小化
@@ -331,7 +331,7 @@
Avaline Caller [ORDER]
- No error
+ 無錯誤
Asset request: failed
@@ -361,13 +361,13 @@
Viewer and server do not agree on price
- Unknown status
+ 未知狀態
材質
- sound
+ 聲音
calling card
@@ -661,13 +661,13 @@
載入中...
- Offline
+ 離線
[AREA] m² L$[PRICE]
- None found.
+ 沒有發現。
確定
@@ -748,10 +748,10 @@
Moderate
- Adult
+ 成人
- Offline
+ 離線
未知
@@ -760,34 +760,34 @@
(未知)
- Estate / Full Region
+ 領地 / 完整地區
- Estate / Homestead
+ 領地 / 家園
- Mainland / Homestead
+ 大陸 / 家園
- Mainland / Full Region
+ 大陸 / 完整地區
全部檔案
- Sounds
+ 聲音
- Animations
+ 動作
圖像
- Save
+ 儲存
- Load
+ 載入
Targa 圖像
@@ -808,34 +808,34 @@
RAW File
- Compressed Images
+ 壓縮的圖像
- Load Files
+ 載入檔案
- Choose Directory
+ 選擇目錄
- Not Away
+ 非離開
- Away
+ 離開
- Not Busy
+ 非忙碌
- Busy
+ 忙碌
- Shape
+ 體形
- Skin
+ 皮膚
- Hair
+ 頭髮
眼睛
@@ -877,49 +877,49 @@
Physics
- invalid
+ 無效
無
- Shirt not worn
+ 襯衫未穿
- Pants not worn
+ 褲子未穿
- Shoes not worn
+ 鞋子未穿
- Socks not worn
+ 襪子未穿
- Jacket not worn
+ 夾克未穿
- Gloves not worn
+ 手套未穿
- Undershirt not worn
+ 內衣未穿
- Underpants not worn
+ 內褲未穿
- Skirt not worn
+ 裙子未穿
Alpha not worn
- Tattoo not worn
+ 刺青未穿
Physics not worn
- invalid
+ 無效
創造新體形
@@ -931,34 +931,34 @@
創造新頭髮
- 創耖新眼睛
+ 創造新眼睛
- Create new shirt
+ 創造新襯衫
- Create new pants
+ 創造新褲子
- Create new shoes
+ 創造新鞋子
- Create new socks
+ 創造新襪子
- Create new jacket
+ 創造新夾克
- Create new gloves
+ 創造新手套
- Create new undershirt
+ 創造新內衣
- Create new underpants
+ 創造新內褲
- Create new skirt
+ 創造新裙子
Create new alpha
@@ -970,13 +970,13 @@
Create new physics
- invalid
+ 無效
- New [WEARABLE_ITEM]
+ 新 [WEARABLE_ITEM]
- Next
+ 下一個
確定
@@ -988,7 +988,7 @@
社團通知
- Sent by
+ 送出由
Attached:
@@ -1006,16 +1006,16 @@
Teleport offering
- New notifications arrived while you were away.
+ 當你離開時有新的通知送達。
- You have %d more notification
+ 你有約 %d 通知
Right Arm
- Head
+ 頭部
Left Arm
@@ -1024,7 +1024,7 @@
Left Leg
- Torso
+ 軀幹
Right Leg
@@ -1175,7 +1175,7 @@
我的裝扮
- Accessories
+ 配件
朋友
@@ -1253,7 +1253,7 @@
嘴
- Chin
+ 下巴
左耳
@@ -1328,7 +1328,7 @@
[AGEDAYS] old
- 今日剛加入
+ 高日剛加入
[COUNT] 年
@@ -1469,7 +1469,7 @@
設為非執行中
- 編譯成功!
+ 編譯成功!!
編譯成功,儲存中...
@@ -1579,7 +1579,7 @@
Chest
- Head
+ 頭部
Left Shoulder
@@ -1609,7 +1609,7 @@
Mouth
- Chin
+ 下巴
Left Ear
@@ -1750,7 +1750,7 @@
You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.
- User has no picks or classifieds
+ 使用者無精選地點或個人廣告
載入中...
@@ -1955,7 +1955,7 @@
Linden Location
- Adult
+ 成人
Arts & Culture
@@ -2392,7 +2392,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Chest Size
- Chin Angle
+ 下巴角度
Chin Cleft
@@ -2629,7 +2629,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Glove Length
- Hair
+ 頭髮
Hair: Back
@@ -3577,13 +3577,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Health
- Adult Region
+ 成人地區
Moderate Region
- General Region
+ 一般地區
[APP_NAME] 更新
diff --git a/indra/newview/skins/default/xui/zh/teleport_strings.xml b/indra/newview/skins/default/xui/zh/teleport_strings.xml
index 9702832f44..b18eb4a390 100644
--- a/indra/newview/skins/default/xui/zh/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/zh/teleport_strings.xml
@@ -53,7 +53,7 @@ Try again in a moment.
Relaying to destination.
- 傳送家位置的要求。
+ 送出家位置的要求。
地標位置要求瞬間傳送中。
diff --git a/indra/newview/skins/minimal/xui/da/floater_media_browser.xml b/indra/newview/skins/minimal/xui/da/floater_media_browser.xml
index d3028c32f9..42fbdeaa9e 100644
--- a/indra/newview/skins/minimal/xui/da/floater_media_browser.xml
+++ b/indra/newview/skins/minimal/xui/da/floater_media_browser.xml
@@ -1,18 +1,29 @@
-
+
+
+ http://www.secondlife.com
+
+
+ http://support.secondlife.com
+
-
-
+
+
+
+
+
+
+
-
-
+
+
diff --git a/indra/newview/skins/minimal/xui/da/floater_web_content.xml b/indra/newview/skins/minimal/xui/da/floater_web_content.xml
index 74092e88ec..0410f74324 100644
--- a/indra/newview/skins/minimal/xui/da/floater_web_content.xml
+++ b/indra/newview/skins/minimal/xui/da/floater_web_content.xml
@@ -2,13 +2,13 @@
-
-
-
+
+
+
-
+
diff --git a/indra/newview/skins/minimal/xui/da/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/da/menu_people_nearby.xml
index 5470c32761..220ab8724f 100644
--- a/indra/newview/skins/minimal/xui/da/menu_people_nearby.xml
+++ b/indra/newview/skins/minimal/xui/da/menu_people_nearby.xml
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+
diff --git a/indra/newview/skins/minimal/xui/da/notifications.xml b/indra/newview/skins/minimal/xui/da/notifications.xml
index 0d2aaf45ce..e77eeee8df 100644
--- a/indra/newview/skins/minimal/xui/da/notifications.xml
+++ b/indra/newview/skins/minimal/xui/da/notifications.xml
@@ -1327,21 +1327,19 @@ Prøv igen om lidt.
No valid parcel could be found.
- Et object med navnet <nolink>[OBJECTFROMNAME]</nolink> ejet af [NAME_SLURL] har givet dig denne [OBJECTTYPE]:
-[ITEM_SLURL]
+ Et objekt ved navn <nolink>[OBJECTFROMNAME]</nolink> ejet af [NAME_SLURL] tilbyder dig [ITEM_SLURL]. For at bruge denne genstand skal du skifte til avanceret tilstand, hvor du kan finde genstanden i din beholdning. Ønsker du at logge ud for at skifte tilstand? Valg af tilstand findes på login skærmbilledet.
- [NAME_SLURL] har givet dig denne/dette [OBJECTTYPE]:
-[ITEM_SLURL]
+ [NAME_SLURL] tilbyder dig [ITEM_SLURL]. For at bruge denne genstand skal du skifte til avanceret tilstand, hvor du kan finde genstanden i din beholdning. Ønsker du at logge ud for at skifte tilstand? Valg af tilstand findes på login skærmbilledet.
diff --git a/indra/newview/skins/minimal/xui/da/panel_adhoc_control_panel.xml b/indra/newview/skins/minimal/xui/da/panel_adhoc_control_panel.xml
index 1953fad31f..14250453eb 100644
--- a/indra/newview/skins/minimal/xui/da/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_adhoc_control_panel.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/indra/newview/skins/minimal/xui/da/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/da/panel_bottomtray.xml
index 53a30136ae..bd20ece764 100644
--- a/indra/newview/skins/minimal/xui/da/panel_bottomtray.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_bottomtray.xml
@@ -4,26 +4,32 @@
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
+
diff --git a/indra/newview/skins/minimal/xui/da/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/da/panel_group_control_panel.xml
index 26fe4f6ebe..23a5e79e22 100644
--- a/indra/newview/skins/minimal/xui/da/panel_group_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_group_control_panel.xml
@@ -8,10 +8,10 @@
-
+
-
+
diff --git a/indra/newview/skins/minimal/xui/da/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/da/panel_im_control_panel.xml
index 5cecb93d40..b8a7ec0b34 100644
--- a/indra/newview/skins/minimal/xui/da/panel_im_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_im_control_panel.xml
@@ -20,7 +20,7 @@
-
+
diff --git a/indra/newview/skins/minimal/xui/da/panel_login.xml b/indra/newview/skins/minimal/xui/da/panel_login.xml
index fdcc550d82..2e0f726e1a 100644
--- a/indra/newview/skins/minimal/xui/da/panel_login.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_login.xml
@@ -21,7 +21,7 @@
Tilstand:
-
+
diff --git a/indra/newview/skins/minimal/xui/da/panel_people.xml b/indra/newview/skins/minimal/xui/da/panel_people.xml
index a540025343..49cd2c71f2 100644
--- a/indra/newview/skins/minimal/xui/da/panel_people.xml
+++ b/indra/newview/skins/minimal/xui/da/panel_people.xml
@@ -70,7 +70,7 @@ Leder du efter personer at være sammen med? Prøv destinationsknappen nedenfor.
-
+
diff --git a/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml
index fbc119c483..72ba7fe41d 100644
--- a/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml
+++ b/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml
@@ -3,6 +3,7 @@
+
diff --git a/indra/newview/skins/minimal/xui/de/panel_adhoc_control_panel.xml b/indra/newview/skins/minimal/xui/de/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..cc45f42169
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_adhoc_control_panel.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml
index a4d80921ec..2278bfb699 100644
--- a/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml
+++ b/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml
@@ -4,26 +4,32 @@
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
diff --git a/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml
index abf8011d9d..0ef2234fec 100644
--- a/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/indra/newview/skins/minimal/xui/de/panel_people.xml b/indra/newview/skins/minimal/xui/de/panel_people.xml
index c6253e17de..4f8f70ad17 100644
--- a/indra/newview/skins/minimal/xui/de/panel_people.xml
+++ b/indra/newview/skins/minimal/xui/de/panel_people.xml
@@ -51,6 +51,9 @@
+
+
+