summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/LICENSE-logos.txt11
-rw-r--r--indra/llaudio/llaudiodecodemgr.cpp378
-rw-r--r--indra/llaudio/llaudiodecodemgr.h12
-rw-r--r--indra/llcharacter/llcharacter.cpp28
-rw-r--r--indra/llcharacter/llcharacter.h5
-rw-r--r--indra/llcharacter/lljoint.cpp87
-rw-r--r--indra/llcharacter/lljoint.h3
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp24
-rw-r--r--indra/llcommon/imageids.h2
-rw-r--r--indra/llcommon/llapr.cpp174
-rw-r--r--indra/llcommon/llapr.h18
-rw-r--r--indra/llcommon/llcommon.cpp1
-rw-r--r--indra/llcommon/llcommon.h1
-rw-r--r--indra/llcommon/llerror.cpp1
-rw-r--r--indra/llcommon/llevent.h1
-rw-r--r--indra/llcommon/llfasttimer.h25
-rw-r--r--indra/llcommon/llfile.cpp13
-rw-r--r--indra/llcommon/llfile.h1
-rw-r--r--indra/llcommon/llmemory.cpp38
-rw-r--r--indra/llcommon/llmemory.h51
-rw-r--r--indra/llcommon/llmemtype.h1
-rw-r--r--indra/llcommon/llqueuedthread.cpp195
-rw-r--r--indra/llcommon/llqueuedthread.h56
-rw-r--r--indra/llcommon/llsecondlifeurls.h9
-rw-r--r--indra/llcommon/llstrider.h1
-rw-r--r--indra/llcommon/llthread.cpp63
-rw-r--r--indra/llcommon/llthread.h75
-rw-r--r--indra/llcommon/llworkerthread.cpp325
-rw-r--r--indra/llcommon/llworkerthread.h85
-rw-r--r--indra/llimage/llimage.cpp251
-rw-r--r--indra/llimage/llimage.h41
-rw-r--r--indra/llimage/llimagedxt.cpp9
-rw-r--r--indra/llimage/llimagedxt.h5
-rw-r--r--indra/llimage/llimagej2c.cpp28
-rw-r--r--indra/llimage/llimagej2c.h2
-rw-r--r--indra/llimage/llimageworker.cpp165
-rw-r--r--indra/llimage/llimageworker.h57
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp2
-rw-r--r--indra/llinventory/llinventory.h1
-rw-r--r--indra/llmath/lloctree.h79
-rw-r--r--indra/llmath/lltreenode.h5
-rw-r--r--indra/llmath/llvolume.cpp159
-rw-r--r--indra/llmath/llvolume.h3
-rw-r--r--indra/llmath/m3math.cpp95
-rw-r--r--indra/llmath/m3math.h9
-rw-r--r--indra/llmath/m4math.h9
-rw-r--r--indra/llmath/v2math.h15
-rw-r--r--indra/llmath/v3math.cpp4
-rw-r--r--indra/llmath/v3math.h14
-rw-r--r--indra/llmath/v4math.h11
-rw-r--r--indra/llmessage/llcurl.cpp343
-rw-r--r--indra/llmessage/llcurl.h118
-rw-r--r--indra/llmessage/llpartdata.cpp14
-rw-r--r--indra/llmessage/llpartdata.h3
-rw-r--r--indra/llmessage/llpumpio.cpp2
-rw-r--r--indra/llmessage/lltransfermanager.cpp7
-rw-r--r--indra/llmessage/lltransfertargetvfile.cpp58
-rw-r--r--indra/llmessage/lltransfertargetvfile.h2
-rw-r--r--indra/llmessage/message.h1
-rw-r--r--indra/llprimitive/llvolumemessage.cpp51
-rw-r--r--indra/llrender/llfontgl.cpp1
-rw-r--r--indra/llrender/llimagegl.cpp32
-rw-r--r--indra/llrender/llimagegl.h3
-rw-r--r--indra/llrender/llvertexbuffer.cpp918
-rw-r--r--indra/llrender/llvertexbuffer.h179
-rw-r--r--indra/llui/llcombobox.cpp10
-rw-r--r--indra/llui/llcombobox.h3
-rw-r--r--indra/llui/llpanel.h1
-rw-r--r--indra/llui/llscrolllistctrl.cpp2
-rw-r--r--indra/llui/lltexteditor.cpp2
-rw-r--r--indra/llui/lluictrl.h1
-rw-r--r--indra/llui/lluictrlfactory.cpp10
-rw-r--r--indra/llui/lluictrlfactory.h2
-rw-r--r--indra/llvfs/lldir.cpp76
-rw-r--r--indra/llvfs/lldir.h4
-rw-r--r--indra/llvfs/lllfsthread.cpp233
-rw-r--r--indra/llvfs/lllfsthread.h54
-rw-r--r--indra/llvfs/llvfile.cpp14
-rw-r--r--indra/llvfs/llvfs.cpp17
-rw-r--r--indra/llvfs/llvfsthread.cpp64
-rw-r--r--indra/llvfs/llvfsthread.h21
-rw-r--r--indra/llwindow/llwindow.h1
-rw-r--r--indra/llwindow/llwindowmacosx.cpp17
-rw-r--r--indra/llwindow/llwindowwin32.cpp87
-rw-r--r--indra/llwindow/llwindowwin32.h1
-rw-r--r--indra/llxml/llcontrol.cpp65
-rw-r--r--indra/llxml/llxmlnode.h1
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyV.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightF.glsl2
-rw-r--r--indra/newview/app_settings/viewerart.xml390
-rw-r--r--indra/newview/featuretable.txt23
-rw-r--r--indra/newview/featuretable_mac.txt14
-rw-r--r--indra/newview/gpu_table.txt16
-rwxr-xr-xindra/newview/linux_tools/wrapper.sh5
-rw-r--r--indra/newview/llagent.cpp35
-rw-r--r--indra/newview/llcloud.cpp27
-rw-r--r--indra/newview/llcloud.h4
-rw-r--r--indra/newview/llcolorswatch.h1
-rw-r--r--indra/newview/llcylinder.cpp108
-rw-r--r--indra/newview/llcylinder.h23
-rw-r--r--indra/newview/lldrawable.cpp631
-rw-r--r--indra/newview/lldrawable.h36
-rw-r--r--indra/newview/lldrawpool.cpp1261
-rw-r--r--indra/newview/lldrawpool.h335
-rw-r--r--indra/newview/lldrawpoolalpha.cpp649
-rw-r--r--indra/newview/lldrawpoolalpha.h58
-rw-r--r--indra/newview/lldrawpoolavatar.cpp631
-rw-r--r--indra/newview/lldrawpoolavatar.h33
-rw-r--r--indra/newview/lldrawpoolbump.cpp653
-rw-r--r--indra/newview/lldrawpoolbump.h62
-rw-r--r--indra/newview/lldrawpoolclouds.cpp21
-rw-r--r--indra/newview/lldrawpoolclouds.h10
-rw-r--r--indra/newview/lldrawpoolground.cpp35
-rw-r--r--indra/newview/lldrawpoolground.h10
-rw-r--r--indra/newview/lldrawpoolsimple.cpp211
-rw-r--r--indra/newview/lldrawpoolsimple.h56
-rw-r--r--indra/newview/lldrawpoolsky.cpp32
-rw-r--r--indra/newview/lldrawpoolsky.h14
-rw-r--r--indra/newview/lldrawpoolterrain.cpp98
-rw-r--r--indra/newview/lldrawpoolterrain.h16
-rw-r--r--indra/newview/lldrawpooltree.cpp125
-rw-r--r--indra/newview/lldrawpooltree.h12
-rw-r--r--indra/newview/lldrawpoolwater.cpp114
-rw-r--r--indra/newview/lldrawpoolwater.h14
-rw-r--r--indra/newview/lldynamictexture.cpp15
-rw-r--r--indra/newview/llface.cpp1457
-rw-r--r--indra/newview/llface.h193
-rw-r--r--indra/newview/llfasttimerview.cpp77
-rw-r--r--indra/newview/llfasttimerview.h4
-rw-r--r--indra/newview/llfeaturemanager.cpp323
-rw-r--r--indra/newview/llfeaturemanager.h3
-rw-r--r--indra/newview/llfilepicker.cpp20
-rw-r--r--indra/newview/llfilepicker.h1
-rw-r--r--indra/newview/llflexibleobject.cpp316
-rw-r--r--indra/newview/llflexibleobject.h36
-rw-r--r--indra/newview/llfloateranimpreview.cpp14
-rw-r--r--indra/newview/llfloaterimagepreview.cpp14
-rw-r--r--indra/newview/llfloatersnapshot.cpp4
-rw-r--r--indra/newview/llglsandbox.cpp136
-rw-r--r--indra/newview/llhudeffecttrail.cpp20
-rw-r--r--indra/newview/llhudicon.cpp1
-rw-r--r--indra/newview/llinventorybridge.cpp2
-rw-r--r--indra/newview/lljoystickbutton.h1
-rw-r--r--indra/newview/llmaniprotate.cpp50
-rw-r--r--indra/newview/llmanipscale.cpp60
-rw-r--r--indra/newview/llmaniptranslate.cpp186
-rw-r--r--indra/newview/llmaniptranslate.h4
-rw-r--r--indra/newview/llmemoryview.cpp2
-rw-r--r--indra/newview/llpanelpick.cpp5
-rw-r--r--indra/newview/llpolymesh.cpp6
-rw-r--r--indra/newview/llpolymesh.h1
-rw-r--r--indra/newview/llpreviewscript.cpp2
-rw-r--r--indra/newview/llpreviewtexture.cpp114
-rw-r--r--indra/newview/llprogressview.cpp8
-rw-r--r--indra/newview/llselectmgr.cpp113
-rw-r--r--indra/newview/llselectmgr.h4
-rw-r--r--indra/newview/llsky.cpp10
-rw-r--r--indra/newview/llspatialpartition.cpp1882
-rw-r--r--indra/newview/llspatialpartition.h327
-rw-r--r--indra/newview/llsprite.cpp42
-rw-r--r--indra/newview/llstartup.cpp74
-rw-r--r--indra/newview/llstartup.h4
-rw-r--r--indra/newview/llsurface.cpp46
-rw-r--r--indra/newview/llsurface.h5
-rw-r--r--indra/newview/llsurfacepatch.cpp2
-rw-r--r--indra/newview/lltexturecache.cpp1365
-rw-r--r--indra/newview/lltexturecache.h149
-rw-r--r--indra/newview/lltexturefetch.cpp1951
-rw-r--r--indra/newview/lltexturefetch.h69
-rw-r--r--indra/newview/lltextureview.cpp580
-rw-r--r--indra/newview/lltextureview.h9
-rw-r--r--indra/newview/lltoolcomp.cpp2
-rw-r--r--indra/newview/lltoolfocus.cpp10
-rw-r--r--indra/newview/lltoolmorph.cpp5
-rw-r--r--indra/newview/lltoolpie.cpp5
-rw-r--r--indra/newview/lltoolplacer.cpp1
-rw-r--r--indra/newview/lltoolplacer.h1
-rw-r--r--indra/newview/llviewercamera.cpp68
-rw-r--r--indra/newview/llviewercamera.h2
-rw-r--r--indra/newview/llviewercontrol.h1
-rw-r--r--indra/newview/llviewerdisplay.cpp204
-rw-r--r--indra/newview/llviewerjoint.cpp150
-rw-r--r--indra/newview/llviewerjoint.h12
-rw-r--r--indra/newview/llviewerjointattachment.cpp39
-rw-r--r--indra/newview/llviewerjointattachment.h4
-rw-r--r--indra/newview/llviewerjointmesh.cpp824
-rw-r--r--indra/newview/llviewerjointmesh.h5
-rw-r--r--indra/newview/llviewermenu.cpp255
-rw-r--r--indra/newview/llviewermessage.cpp6
-rw-r--r--indra/newview/llviewerobject.cpp141
-rw-r--r--indra/newview/llviewerobject.h45
-rw-r--r--indra/newview/llviewerobjectlist.cpp66
-rw-r--r--indra/newview/llviewerobjectlist.h1
-rw-r--r--indra/newview/llviewerparcelmgr.cpp14
-rw-r--r--indra/newview/llviewerparceloverlay.cpp21
-rw-r--r--indra/newview/llviewerpartsim.cpp305
-rw-r--r--indra/newview/llviewerpartsim.h34
-rw-r--r--indra/newview/llviewerpartsource.cpp180
-rw-r--r--indra/newview/llviewerpartsource.h9
-rw-r--r--indra/newview/llviewerregion.cpp15
-rw-r--r--indra/newview/llviewerregion.h2
-rw-r--r--indra/newview/llviewerstats.cpp8
-rw-r--r--indra/newview/llviewerstats.h2
-rw-r--r--indra/newview/llviewerthrottle.cpp6
-rw-r--r--indra/newview/llviewerwindow.cpp149
-rw-r--r--indra/newview/llviewerwindow.h2
-rw-r--r--indra/newview/llvoavatar.cpp620
-rw-r--r--indra/newview/llvoavatar.h50
-rw-r--r--indra/newview/llvoclouds.cpp177
-rw-r--r--indra/newview/llvoclouds.h17
-rw-r--r--indra/newview/llvograss.cpp207
-rw-r--r--indra/newview/llvograss.h16
-rw-r--r--indra/newview/llvoground.cpp84
-rw-r--r--indra/newview/llvoground.h2
-rw-r--r--indra/newview/llvopartgroup.cpp404
-rw-r--r--indra/newview/llvopartgroup.h28
-rw-r--r--indra/newview/llvosky.cpp186
-rw-r--r--indra/newview/llvosky.h9
-rw-r--r--indra/newview/llvosurfacepatch.cpp280
-rw-r--r--indra/newview/llvosurfacepatch.h38
-rw-r--r--indra/newview/llvotextbubble.cpp80
-rw-r--r--indra/newview/llvotextbubble.h12
-rw-r--r--indra/newview/llvotree.cpp102
-rw-r--r--indra/newview/llvotree.h13
-rw-r--r--indra/newview/llvovolume.cpp1480
-rw-r--r--indra/newview/llvovolume.h44
-rw-r--r--indra/newview/llvowater.cpp830
-rw-r--r--indra/newview/llvowater.h199
-rw-r--r--indra/newview/llworld.cpp27
-rw-r--r--indra/newview/llworld.h3
-rw-r--r--indra/newview/llworldmapview.cpp40
-rw-r--r--indra/newview/llworldmapview.h3
-rw-r--r--indra/newview/macview_Prefix.h4
-rw-r--r--indra/newview/pipeline.cpp3457
-rw-r--r--indra/newview/pipeline.h239
-rwxr-xr-xindra/newview/viewer_manifest.py6
238 files changed, 17290 insertions, 14541 deletions
diff --git a/doc/LICENSE-logos.txt b/doc/LICENSE-logos.txt
index 53b417cab6..0ca7dfd491 100644
--- a/doc/LICENSE-logos.txt
+++ b/doc/LICENSE-logos.txt
@@ -6,7 +6,12 @@ Research, Inc. Other trademarks include (but are not limited to): the
names Linden and Linden Research, as well as the Linden Lab Hexagon
Design and the Second Life Hand Design logos.
-Use of logos and trademarks are subject to the Linden Lab trademark
-policy, available at:
-
+The copyrightable materials in this file that are owned by Linden Lab
+are "Work" licensed under Creative Commons license Attribution-Share
+Alike 2.5 (summarized at
+http://creativecommons.org/licenses/by-sa/2.5/ , full text of license
+at http://creativecommons.org/licenses/by-sa/2.5/legalcode); provided
+however that all trademarks of Linden Lab are subject to the Linden
+Lab trademark policy, available at
http://secondlife.com/corporate/trademark/
+
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index a2a594f2eb..9d8d91a58e 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -33,9 +33,25 @@ LLAudioDecodeMgr *gAudioDecodeMgrp = NULL;
static const S32 WAV_HEADER_SIZE = 44;
-class LLVorbisDecodeState
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+class LLVorbisDecodeState : public LLRefCount
{
public:
+ class WriteResponder : public LLLFSThread::Responder
+ {
+ public:
+ WriteResponder(LLVorbisDecodeState* decoder) : mDecoder(decoder) {}
+ ~WriteResponder() {}
+ void completed(S32 bytes)
+ {
+ mDecoder->ioComplete(bytes);
+ }
+ LLPointer<LLVorbisDecodeState> mDecoder;
+ };
+
LLVorbisDecodeState(const LLUUID &uuid, const LLString &out_filename);
virtual ~LLVorbisDecodeState();
@@ -45,12 +61,14 @@ public:
void flushBadFile();
+ void ioComplete(S32 bytes) { mBytesRead = bytes; }
BOOL isValid() const { return mValid; }
BOOL isDone() const { return mDone; }
const LLUUID &getUUID() const { return mUUID; }
protected:
BOOL mValid;
BOOL mDone;
+ LLAtomicS32 mBytesRead;
LLUUID mUUID;
std::vector<U8> mWAVBuffer;
@@ -64,172 +82,6 @@ protected:
S32 mCurrentSection;
};
-void LLVorbisDecodeState::flushBadFile()
-{
- if (mInFilep)
- {
- llwarns << "Flushing bad vorbis file from VFS for " << mUUID << llendl;
- mInFilep->remove();
- }
-}
-
-
-LLAudioDecodeMgr::LLAudioDecodeMgr()
-{
- mCurrentDecodep = NULL;
-}
-
-LLAudioDecodeMgr::~LLAudioDecodeMgr()
-{
- delete mCurrentDecodep;
- mCurrentDecodep = NULL;
-}
-
-
-void LLAudioDecodeMgr::processQueue(const F32 num_secs)
-{
- LLUUID uuid;
-
- LLTimer decode_timer;
-
- BOOL done = FALSE;
- while (!done)
- {
- if (mCurrentDecodep)
- {
- BOOL res;
-
- // Decode in a loop until we're done or have run out of time.
- while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs))
- {
- // decodeSection does all of the work above
- }
-
- if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid())
- {
- // We had an error when decoding, abort.
- llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl;
- mCurrentDecodep->flushBadFile();
- LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
- adp->setHasValidData(FALSE);
- delete mCurrentDecodep;
- mCurrentDecodep = NULL;
- done = TRUE;
- }
-
- if (!res)
- {
- // We've used up out time slice, bail...
- done = TRUE;
- }
- else if (mCurrentDecodep)
- {
- if (mCurrentDecodep->finishDecode())
- {
- // We finished!
- if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
- {
- LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
- adp->setHasDecodedData(TRUE);
- adp->setHasValidData(TRUE);
-
- // At this point, we could see if anyone needs this sound immediately, but
- // I'm not sure that there's a reason to - we need to poll all of the playing
- // sounds anyway.
- //llinfos << "Finished the vorbis decode, now what?" << llendl;
- }
- else
- {
- llinfos << "Vorbis decode failed!!!" << llendl;
- }
- delete mCurrentDecodep;
- mCurrentDecodep = NULL;
- }
- done = TRUE; // done for now
- }
- }
-
- if (!done)
- {
- if (!mDecodeQueue.getLength())
- {
- // Nothing else on the queue.
- done = TRUE;
- }
- else
- {
- LLUUID uuid;
- mDecodeQueue.pop(uuid);
- if (gAudiop->hasDecodedFile(uuid))
- {
- // This file has already been decoded, don't decode it again.
- continue;
- }
-
- lldebugs << "Decoding " << uuid << " from audio queue!" << llendl;
-
- char uuid_str[64]; /*Flawfinder: ignore*/
- char d_path[LL_MAX_PATH]; /*Flawfinder: ignore*/
-
- LLTimer timer;
- timer.reset();
-
- uuid.toString(uuid_str);
- snprintf(d_path, LL_MAX_PATH, "%s.dsf", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str()); /*Flawfinder: ignore*/
-
- mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path);
- if (!mCurrentDecodep->initDecode())
- {
- delete mCurrentDecodep;
- mCurrentDecodep = NULL;
- }
- }
- }
- }
-}
-
-
-BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
-{
- if (gAudiop->hasDecodedFile(uuid))
- {
- // Already have a decoded version, don't need to decode it.
- return TRUE;
- }
-
- if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
- {
- // Just put it on the decode queue.
- gAudioDecodeMgrp->mDecodeQueue.push(uuid);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-S32 LLAudioDecodeMgr::getRequestCount()
-{
- /*
- S32 count = 0;
- if (mCurrentTransfer.notNull())
- {
- count++;
- }
-
- count += mRequestQueue.getLength();
- return count;
- */
- return 0;
-}
-
-
-
-
-
-
-
-
size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
{
LLVFile *file = (LLVFile *)datasource;
@@ -284,26 +136,21 @@ int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
int vfs_close (void *datasource)
{
LLVFile *file = (LLVFile *)datasource;
-
delete file;
-
return 0;
}
long vfs_tell (void *datasource)
{
LLVFile *file = (LLVFile *)datasource;
-
return file->tell();
}
-
-
-
LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const LLString &out_filename)
{
mDone = FALSE;
mValid = FALSE;
+ mBytesRead = -1;
mUUID = uuid;
mInFilep = NULL;
mCurrentSection = 0;
@@ -575,32 +422,27 @@ BOOL LLVorbisDecodeState::finishDecode()
return TRUE; // we've finished
}
#if !defined(USE_WAV_VFILE)
- mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, data_length);
+ mBytesRead = -1;
+ mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, data_length,
+ new WriteResponder(this));
#endif
}
if (mFileHandle != LLLFSThread::nullHandle())
{
- LLLFSThread::status_t s = LLLFSThread::sLocal->getRequestStatus(mFileHandle);
- if (s != LLLFSThread::STATUS_COMPLETE)
- {
- if (s != LLLFSThread::STATUS_QUEUED && s != LLLFSThread::STATUS_INPROGRESS)
- {
- llerrs << "Bad file status in LLVorbisDecodeState::finishDecode: " << s << llendl;
- }
- return FALSE; // not finished
- }
- else
+ if (mBytesRead >= 0)
{
- LLLFSThread::Request* req = (LLLFSThread::Request*)LLLFSThread::sLocal->getRequest(mFileHandle);
- if (req->getBytesRead() == 0) //!= req->getBytes() // should be safe, but needs testing
+ if (mBytesRead == 0)
{
llwarns << "Unable to write file in LLVorbisDecodeState::finishDecode" << llendl;
mValid = FALSE;
return TRUE; // we've finished
}
}
- LLLFSThread::sLocal->completeRequest(mFileHandle);
+ else
+ {
+ return FALSE; // not done
+ }
}
mDone = TRUE;
@@ -614,3 +456,165 @@ BOOL LLVorbisDecodeState::finishDecode()
return TRUE;
}
+
+void LLVorbisDecodeState::flushBadFile()
+{
+ if (mInFilep)
+ {
+ llwarns << "Flushing bad vorbis file from VFS for " << mUUID << llendl;
+ mInFilep->remove();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class LLAudioDecodeMgr::Impl
+{
+ friend class LLAudioDecodeMgr;
+public:
+ Impl() {};
+ ~Impl() {};
+
+ void processQueue(const F32 num_secs = 0.005);
+
+protected:
+ LLLinkedQueue<LLUUID> mDecodeQueue;
+ LLPointer<LLVorbisDecodeState> mCurrentDecodep;
+};
+
+
+void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
+{
+ LLUUID uuid;
+
+ LLTimer decode_timer;
+
+ BOOL done = FALSE;
+ while (!done)
+ {
+ if (mCurrentDecodep)
+ {
+ BOOL res;
+
+ // Decode in a loop until we're done or have run out of time.
+ while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs))
+ {
+ // decodeSection does all of the work above
+ }
+
+ if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid())
+ {
+ // We had an error when decoding, abort.
+ llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl;
+ mCurrentDecodep->flushBadFile();
+ LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
+ adp->setHasValidData(FALSE);
+ mCurrentDecodep = NULL;
+ done = TRUE;
+ }
+
+ if (!res)
+ {
+ // We've used up out time slice, bail...
+ done = TRUE;
+ }
+ else if (mCurrentDecodep)
+ {
+ if (mCurrentDecodep->finishDecode())
+ {
+ // We finished!
+ if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
+ {
+ LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
+ adp->setHasDecodedData(TRUE);
+ adp->setHasValidData(TRUE);
+
+ // At this point, we could see if anyone needs this sound immediately, but
+ // I'm not sure that there's a reason to - we need to poll all of the playing
+ // sounds anyway.
+ //llinfos << "Finished the vorbis decode, now what?" << llendl;
+ }
+ else
+ {
+ llinfos << "Vorbis decode failed!!!" << llendl;
+ }
+ mCurrentDecodep = NULL;
+ }
+ done = TRUE; // done for now
+ }
+ }
+
+ if (!done)
+ {
+ if (!mDecodeQueue.getLength())
+ {
+ // Nothing else on the queue.
+ done = TRUE;
+ }
+ else
+ {
+ LLUUID uuid;
+ mDecodeQueue.pop(uuid);
+ if (gAudiop->hasDecodedFile(uuid))
+ {
+ // This file has already been decoded, don't decode it again.
+ continue;
+ }
+
+ lldebugs << "Decoding " << uuid << " from audio queue!" << llendl;
+
+ char uuid_str[64]; /*Flawfinder: ignore*/
+ char d_path[LL_MAX_PATH]; /*Flawfinder: ignore*/
+
+ LLTimer timer;
+ timer.reset();
+
+ uuid.toString(uuid_str);
+ snprintf(d_path, LL_MAX_PATH, "%s.dsf", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str()); /*Flawfinder: ignore*/
+
+ mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path);
+ if (!mCurrentDecodep->initDecode())
+ {
+ mCurrentDecodep = NULL;
+ }
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLAudioDecodeMgr::LLAudioDecodeMgr()
+{
+ mImpl = new Impl;
+}
+
+LLAudioDecodeMgr::~LLAudioDecodeMgr()
+{
+ delete mImpl;
+}
+
+void LLAudioDecodeMgr::processQueue(const F32 num_secs)
+{
+ mImpl->processQueue(num_secs);
+}
+
+BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
+{
+ if (gAudiop->hasDecodedFile(uuid))
+ {
+ // Already have a decoded version, don't need to decode it.
+ return TRUE;
+ }
+
+ if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
+ {
+ // Just put it on the decode queue.
+ mImpl->mDecodeQueue.push(uuid);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
diff --git a/indra/llaudio/llaudiodecodemgr.h b/indra/llaudio/llaudiodecodemgr.h
index ea1358b8e9..a72d63a228 100644
--- a/indra/llaudio/llaudiodecodemgr.h
+++ b/indra/llaudio/llaudiodecodemgr.h
@@ -19,7 +19,6 @@
class LLVFS;
class LLVorbisDecodeState;
-
class LLAudioDecodeMgr
{
public:
@@ -27,19 +26,12 @@ public:
~LLAudioDecodeMgr();
void processQueue(const F32 num_secs = 0.005);
-
- LLLinkedQueue<LLUUID> mDecodeQueue;
-
- LLVorbisDecodeState *mCurrentDecodep;
-
BOOL addDecodeRequest(const LLUUID &uuid);
void addAudioRequest(const LLUUID &uuid);
-
- S32 getRequestCount();
protected:
- LLLinkedQueue<LLUUID> mDownloadQueue;
- LLFrameTimer mCurrentTransferAge;
+ class Impl;
+ Impl* mImpl;
};
extern LLAudioDecodeMgr *gAudioDecodeMgrp;
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index ecca9a2526..583f01cf91 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -19,13 +19,7 @@
LLStringTable LLCharacter::sVisualParamNames(1024);
-// helper functions
-BOOL larger_screen_area( LLCharacter* data_new, LLCharacter* data_tested )
-{
- return data_new->getPixelArea() > data_tested->getPixelArea();
-}
-
-LLLinkedList< LLCharacter > LLCharacter::sInstances( larger_screen_area );
+std::vector< LLCharacter* > LLCharacter::sInstances;
//-----------------------------------------------------------------------------
@@ -40,7 +34,7 @@ LLCharacter::LLCharacter()
mSkeletonSerialNum( 0 )
{
mMotionController.setCharacter( this );
- sInstances.addData(this);
+ sInstances.push_back(this);
mPauseRequest = new LLPauseRequestHandle();
}
@@ -57,7 +51,11 @@ LLCharacter::~LLCharacter()
{
delete param;
}
- sInstances.removeData(this);
+ std::vector<LLCharacter*>::iterator iter = std::find(sInstances.begin(), sInstances.end(), this);
+ if (iter != sInstances.end())
+ {
+ sInstances.erase(iter);
+ }
}
@@ -66,7 +64,7 @@ LLCharacter::~LLCharacter()
//-----------------------------------------------------------------------------
LLJoint *LLCharacter::getJoint( const std::string &name )
{
- LLJoint *joint = NULL;
+ LLJoint* joint = NULL;
LLJoint *root = getRootJoint();
if (root)
@@ -183,7 +181,7 @@ void LLCharacter::flushAllMotions()
//-----------------------------------------------------------------------------
// dumpCharacter()
//-----------------------------------------------------------------------------
-void LLCharacter::dumpCharacter( LLJoint *joint )
+void LLCharacter::dumpCharacter( LLJoint* joint )
{
// handle top level entry into recursion
if (joint == NULL)
@@ -198,11 +196,11 @@ void LLCharacter::dumpCharacter( LLJoint *joint )
llinfos << "DEBUG: " << joint->getName() << " (" << (joint->getParent()?joint->getParent()->getName():std::string("ROOT")) << ")" << llendl;
// recurse
- for ( LLJoint *j = joint->mChildren.getFirstData();
- j != NULL;
- j = joint->mChildren.getNextData() )
+ for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+ iter != joint->mChildren.end(); ++iter)
{
- dumpCharacter(j);
+ LLJoint* child_joint = *iter;
+ dumpCharacter(child_joint);
}
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index f2f106f360..0ed22f81f7 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -21,6 +21,7 @@
#include "linked_lists.h"
#include "string_table.h"
#include "llmemory.h"
+#include "llthread.h"
class LLPolyMesh;
@@ -90,7 +91,7 @@ public:
virtual F32 getTimeDilation() = 0;
// gets current pixel area of this character
- virtual F32 getPixelArea() = 0;
+ virtual F32 getPixelArea() const = 0;
// gets the head mesh of the character
virtual LLPolyMesh* getHeadMesh() = 0;
@@ -223,7 +224,7 @@ public:
U32 getSkeletonSerialNum() const { return mSkeletonSerialNum; }
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
- static LLLinkedList< LLCharacter > sInstances;
+ static std::vector< LLCharacter* > sInstances;
protected:
LLMotionController mMotionController;
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 3924c06adc..3797b06aa1 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -50,8 +50,9 @@ LLJoint::LLJoint(const std::string &name, LLJoint *parent)
setName(name);
if (parent)
+ {
parent->addChild( this );
-
+ }
touch();
}
@@ -61,6 +62,10 @@ LLJoint::LLJoint(const std::string &name, LLJoint *parent)
//-----------------------------------------------------------------------------
LLJoint::~LLJoint()
{
+ if (mParent)
+ {
+ mParent->removeChild( this );
+ }
removeAllChildren();
}
@@ -72,7 +77,9 @@ void LLJoint::setup(const std::string &name, LLJoint *parent)
{
setName(name);
if (parent)
+ {
parent->addChild( this );
+ }
}
//-----------------------------------------------------------------------------
@@ -90,11 +97,11 @@ void LLJoint::touch(U32 flags)
{
child_flags |= POSITION_DIRTY;
}
-
- for ( LLJoint *joint = mChildren.getFirstData();
- joint != NULL;
- joint = mChildren.getNextData() )
+
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLJoint* joint = *iter;
joint->touch(child_flags);
}
}
@@ -121,13 +128,15 @@ LLJoint *LLJoint::findJoint( const std::string &name )
if (name == getName())
return this;
- for ( LLJoint *j = mChildren.getFirstData();
- j != NULL;
- j = mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
- LLJoint *found = j->findJoint(name);
+ LLJoint* joint = *iter;
+ LLJoint *found = joint->findJoint(name);
if (found)
+ {
return found;
+ }
}
return NULL;
@@ -137,12 +146,12 @@ LLJoint *LLJoint::findJoint( const std::string &name )
//--------------------------------------------------------------------
// addChild()
//--------------------------------------------------------------------
-void LLJoint::addChild(LLJoint *joint)
+void LLJoint::addChild(LLJoint* joint)
{
if (joint->mParent)
joint->mParent->removeChild(joint);
- mChildren.addDataAtEnd(joint);
+ mChildren.push_back(joint);
joint->mXform.setParent(&mXform);
joint->mParent = this;
joint->touch();
@@ -152,9 +161,13 @@ void LLJoint::addChild(LLJoint *joint)
//--------------------------------------------------------------------
// removeChild()
//--------------------------------------------------------------------
-void LLJoint::removeChild(LLJoint *joint)
+void LLJoint::removeChild(LLJoint* joint)
{
- this->mChildren.removeData(joint);
+ child_list_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
+ if (iter != mChildren.end())
+ {
+ this->mChildren.erase(iter);
+ }
joint->mXform.setParent(NULL);
joint->mParent = NULL;
joint->touch();
@@ -166,11 +179,15 @@ void LLJoint::removeChild(LLJoint *joint)
//--------------------------------------------------------------------
void LLJoint::removeAllChildren()
{
- for ( LLJoint *joint = mChildren.getFirstData();
- joint != NULL;
- joint = mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end();)
{
- removeChild(joint);
+ child_list_t::iterator curiter = iter++;
+ LLJoint* joint = *curiter;
+ mChildren.erase(curiter);
+ joint->mXform.setParent(NULL);
+ joint->mParent = NULL;
+ joint->touch();
}
}
@@ -189,8 +206,11 @@ const LLVector3& LLJoint::getPosition()
//--------------------------------------------------------------------
void LLJoint::setPosition( const LLVector3& pos )
{
- mXform.setPosition(pos);
- touch(MATRIX_DIRTY | POSITION_DIRTY);
+// if (mXform.getPosition() != pos)
+ {
+ mXform.setPosition(pos);
+ touch(MATRIX_DIRTY | POSITION_DIRTY);
+ }
}
@@ -257,8 +277,11 @@ void LLJoint::setRotation( const LLQuaternion& rot )
{
if (rot.isFinite())
{
- mXform.setRotation(rot);
- touch(MATRIX_DIRTY | ROTATION_DIRTY);
+ // if (mXform.getRotation() != rot)
+ {
+ mXform.setRotation(rot);
+ touch(MATRIX_DIRTY | ROTATION_DIRTY);
+ }
}
}
@@ -320,8 +343,12 @@ const LLVector3& LLJoint::getScale()
//--------------------------------------------------------------------
void LLJoint::setScale( const LLVector3& scale )
{
- mXform.setScale(scale);
- touch();
+// if (mXform.getScale() != scale)
+ {
+ mXform.setScale(scale);
+ touch();
+ }
+
}
@@ -393,14 +420,18 @@ void LLJoint::updateWorldPRSParent()
// updateWorldMatrixChildren()
//-----------------------------------------------------------------------------
void LLJoint::updateWorldMatrixChildren()
-{
+{
+ if (!this->mUpdateXform) return;
+
if (mDirtyFlags & MATRIX_DIRTY)
{
updateWorldMatrix();
}
- for (LLJoint *child = mChildren.getFirstData(); child; child = mChildren.getNextData())
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
- child->updateWorldMatrixChildren();
+ LLJoint* joint = *iter;
+ joint->updateWorldMatrixChildren();
}
}
@@ -475,8 +506,10 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
{
LLVector3 main_axis(1.f, 0.f, 0.f);
- for (LLJoint* joint = mChildren.getFirstData(); joint; joint = mChildren.getNextData())
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLJoint* joint = *iter;
if (joint->isAnimatable())
{
main_axis = joint->getPosition();
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 2fc86e87df..6399d0a429 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -76,7 +76,8 @@ public:
LLDynamicArray<LLVector3> mConstraintSilhouette;
// child joints
- LLLinkedList<LLJoint> mChildren;
+ typedef std::list<LLJoint*> child_list_t;
+ child_list_t mChildren;
// debug statics
static S32 sNumTouches;
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index bfa4b637e1..ea77126aca 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -1892,28 +1892,26 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
void* user_data, S32 status)
{
LLUUID* id = (LLUUID*)user_data;
+
+ std::vector<LLCharacter* >::iterator char_iter = LLCharacter::sInstances.begin();
- LLCharacter* character = NULL;
+ while(char_iter != LLCharacter::sInstances.end() &&
+ (*char_iter)->getID() != *id)
+ {
+ ++char_iter;
+ }
- for(character = LLCharacter::sInstances.getFirstData();
- character;
- character = LLCharacter::sInstances.getNextData())
- {
- if (character->getID() == *id)
- {
- break;
- }
- }
-
delete id;
- if (!character)
+ if (char_iter == LLCharacter::sInstances.end())
{
return;
}
+ LLCharacter* character = *char_iter;
+
// create an instance of this motion (it may or may not already exist)
- LLKeyframeMotion* motionp = (LLKeyframeMotion*)character->createMotion(asset_uuid);
+ LLKeyframeMotion* motionp = (LLKeyframeMotion*) character->createMotion(asset_uuid);
if (0 == status && motionp)
{
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
index 8147183bec..9f57ec84c2 100644
--- a/indra/llcommon/imageids.h
+++ b/indra/llcommon/imageids.h
@@ -31,7 +31,7 @@
const LLUUID IMG_CLEAR ("11ee27f5-43c0-414e-afd5-d7f5688c351f"); // VIEWER
const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
-const LLUUID IMG_DEFAULT ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
+const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
//const LLUUID IMG_SAND ("0ff70ead-4562-45f9-9e8a-52b1a3286868"); // VIEWER 1.5k
//const LLUUID IMG_GRASS ("5ab48dd5-05d0-4f1a-ace6-efd4e2fb3508"); // VIEWER 1.2k
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index a7fc6a40a7..bf6a4d1b21 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -103,11 +103,13 @@ void ll_apr_assert_status(apr_status_t status)
llassert(ll_apr_warn_status(status) == false);
}
-apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep)
+// File I/O
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool)
{
apr_file_t* apr_file;
apr_status_t s;
- s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS)
{
if (sizep)
@@ -123,6 +125,7 @@ apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* s
apr_off_t offset = 0;
if (apr_file_seek(apr_file, APR_END, &offset) == APR_SUCCESS)
{
+ llassert_always(offset <= 0x7fffffff);
file_size = (S32)offset;
offset = 0;
apr_file_seek(apr_file, APR_SET, &offset);
@@ -132,6 +135,18 @@ apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* s
return apr_file;
}
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep)
+{
+ return ll_apr_file_open(filename, flags, sizep, NULL);
+}
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, apr_pool_t* pool)
+{
+ return ll_apr_file_open(filename, flags, NULL, pool);
+}
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags)
+{
+ return ll_apr_file_open(filename, flags, NULL, NULL);
+}
S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes)
{
@@ -143,10 +158,37 @@ S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes)
}
else
{
+ llassert_always(sz <= 0x7fffffff);
return (S32)sz;
}
}
+S32 ll_apr_file_read_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes)
+{
+ if (pool == NULL) pool = gAPRPoolp;
+ apr_file_t* filep = ll_apr_file_open(filename, APR_READ|APR_BINARY, pool);
+ if (!filep)
+ {
+ return 0;
+ }
+ S32 off;
+ if (offset < 0)
+ off = ll_apr_file_seek(filep, APR_END, 0);
+ else
+ off = ll_apr_file_seek(filep, APR_SET, offset);
+ S32 bytes_read;
+ if (off < 0)
+ {
+ bytes_read = 0;
+ }
+ else
+ {
+ bytes_read = ll_apr_file_read(filep, buf, nbytes );
+ }
+ apr_file_close(filep);
+
+ return bytes_read;
+}
S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes)
{
@@ -158,28 +200,73 @@ S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes)
}
else
{
+ llassert_always(sz <= 0x7fffffff);
return (S32)sz;
}
}
+S32 ll_apr_file_write_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes)
+{
+ if (pool == NULL) pool = gAPRPoolp;
+ apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
+ if (offset < 0)
+ {
+ flags |= APR_APPEND;
+ offset = 0;
+ }
+ apr_file_t* filep = ll_apr_file_open(filename, flags, pool);
+ if (!filep)
+ {
+ return 0;
+ }
+ if (offset > 0)
+ {
+ offset = ll_apr_file_seek(filep, APR_SET, offset);
+ }
+ S32 bytes_written;
+ if (offset < 0)
+ {
+ bytes_written = 0;
+ }
+ else
+ {
+ bytes_written = ll_apr_file_write(filep, buf, nbytes );
+ }
+ apr_file_close(filep);
+
+ return bytes_written;
+}
+
S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset)
{
- apr_off_t apr_offset = offset;
- apr_status_t s = apr_file_seek(apr_file, where, &apr_offset);
+ apr_status_t s;
+ apr_off_t apr_offset;
+ if (offset >= 0)
+ {
+ apr_offset = (apr_off_t)offset;
+ s = apr_file_seek(apr_file, where, &apr_offset);
+ }
+ else
+ {
+ apr_offset = 0;
+ s = apr_file_seek(apr_file, APR_END, &apr_offset);
+ }
if (s != APR_SUCCESS)
{
return -1;
}
else
{
+ llassert_always(apr_offset <= 0x7fffffff);
return (S32)apr_offset;
}
}
-bool ll_apr_file_remove(const LLString& filename)
+bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool)
{
apr_status_t s;
- s = apr_file_remove(filename.c_str(), gAPRPoolp);
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_remove(filename.c_str(), pool);
if (s != APR_SUCCESS)
{
llwarns << "ll_apr_file_remove failed on file: " << filename << llendl;
@@ -188,10 +275,11 @@ bool ll_apr_file_remove(const LLString& filename)
return true;
}
-bool ll_apr_file_rename(const LLString& filename, const LLString& newname)
+bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_pool_t* pool)
{
apr_status_t s;
- s = apr_file_rename(filename.c_str(), newname.c_str(), gAPRPoolp);
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
if (s != APR_SUCCESS)
{
llwarns << "ll_apr_file_rename failed on file: " << filename << llendl;
@@ -199,3 +287,73 @@ bool ll_apr_file_rename(const LLString& filename, const LLString& newname)
}
return true;
}
+
+bool ll_apr_file_exists(const LLString& filename, apr_pool_t* pool)
+{
+ apr_file_t* apr_file;
+ apr_status_t s;
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
+ if (s != APR_SUCCESS || !apr_file)
+ {
+ return false;
+ }
+ else
+ {
+ apr_file_close(apr_file);
+ return true;
+ }
+}
+
+S32 ll_apr_file_size(const LLString& filename, apr_pool_t* pool)
+{
+ apr_file_t* apr_file;
+ apr_finfo_t info;
+ apr_status_t s;
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
+ if (s != APR_SUCCESS || !apr_file)
+ {
+ return 0;
+ }
+ else
+ {
+ apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
+ apr_file_close(apr_file);
+ if (s == APR_SUCCESS)
+ {
+ return (S32)info.size;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool)
+{
+ apr_status_t s;
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
+ if (s != APR_SUCCESS)
+ {
+ llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl;
+ return false;
+ }
+ return true;
+}
+
+bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool)
+{
+ apr_status_t s;
+ if (pool == NULL) pool = gAPRPoolp;
+ s = apr_file_remove(dirname.c_str(), pool);
+ if (s != APR_SUCCESS)
+ {
+ llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl;
+ return false;
+ }
+ return true;
+}
+
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 1e9e944eef..e89912279e 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -106,14 +106,24 @@ typedef LLAtomic32<S32> LLAtomicS32;
#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb"
#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b"
#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b"
-apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep = NULL);
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool);
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep);
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, apr_pool_t* pool);
+apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags);
// Returns actual offset, -1 if seek fails
S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset);
-// Returns bytes read/written, 0 if read/write fails
+// Returns bytes read/written, 0 if read/write fails:
S32 ll_apr_file_read(apr_file_t* apr_file, void* buf, S32 nbytes);
+S32 ll_apr_file_read_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes);
S32 ll_apr_file_write(apr_file_t* apr_file, const void* buf, S32 nbytes);
-bool ll_apr_file_remove(const LLString& filename);
-bool ll_apr_file_rename(const LLString& filename, const LLString& newname);
+S32 ll_apr_file_write_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes);
+// returns false if failure:
+bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool = NULL);
+bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_pool_t* pool = NULL);
+bool ll_apr_file_exists(const LLString& filename, apr_pool_t* pool = NULL);
+S32 ll_apr_file_size(const LLString& filename, apr_pool_t* pool = NULL);
+bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool = NULL);
+bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool = NULL);
/**
* @brief Function which approprately logs error or remains quiet on
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index ff810abfa9..52fcaa3c19 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -8,6 +8,7 @@
#include "linden_common.h"
#include "llcommon.h"
+#include "llthread.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h
index c37d479ba9..e7fb5b84e4 100644
--- a/indra/llcommon/llcommon.h
+++ b/indra/llcommon/llcommon.h
@@ -12,7 +12,6 @@
#include "llapr.h"
// #include "llframecallbackmanager.h"
#include "lltimer.h"
-#include "llworkerthread.h"
#include "llfile.h"
class LLCommon
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 1ed25a0d17..bbff363f54 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -12,6 +12,7 @@
#include "llerror.h"
#include "llerrorcontrol.h"
+#include "llapp.h"
#include "llapr.h"
extern apr_thread_mutex_t *gLogMutexp;
#include "llfile.h"
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 283f40f923..a3f6b0e942 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -12,6 +12,7 @@
#include "llsd.h"
#include "llmemory.h"
+#include "llthread.h"
class LLEventListener;
class LLEvent;
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2fde728eaf..1a7e60656c 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -37,13 +37,22 @@ public:
FTM_UPDATE_TERRAIN,
FTM_UPDATE_PRIMITIVES,
FTM_UPDATE_PARTICLES,
+ FTM_SIMULATE_PARTICLES,
FTM_UPDATE_SKY,
FTM_UPDATE_TEXTURES,
+ FTM_UPDATE_WATER,
+ FTM_UPDATE_CLOUDS,
+ FTM_UPDATE_GRASS,
+ FTM_UPDATE_TREE,
+ FTM_UPDATE_AVATAR,
// common render components
FTM_RENDER_GEOMETRY,
FTM_RENDER_TERRAIN,
FTM_RENDER_SIMPLE,
+ FTM_RENDER_FULLBRIGHT,
+ FTM_RENDER_GRASS,
+ FTM_RENDER_INVISIBLE,
FTM_RENDER_SHINY,
FTM_RENDER_BUMP,
FTM_RENDER_TREES,
@@ -62,6 +71,20 @@ public:
FTM_MESSAGES,
FTM_REBUILD,
FTM_STATESORT,
+ FTM_STATESORT_DRAWABLE,
+ FTM_STATESORT_POSTSORT,
+ FTM_REBUILD_VBO,
+ FTM_REBUILD_VOLUME_VB,
+ FTM_REBUILD_BRIDGE_VB,
+ FTM_REBUILD_HUD_VB,
+ FTM_REBUILD_TERRAIN_VB,
+ FTM_REBUILD_WATER_VB,
+ FTM_REBUILD_TREE_VB,
+ FTM_REBUILD_PARTICLE_VB,
+ FTM_REBUILD_CLOUD_VB,
+ FTM_REBUILD_GRASS_VB,
+ FTM_REBUILD_NONE_VB,
+ FTM_REBUILD_OCCLUSION_VB,
FTM_POOLS,
FTM_POOLRENDER,
FTM_IDLE_CB,
@@ -71,6 +94,7 @@ public:
FTM_UPDATE_LIGHTS,
FTM_CULL,
FTM_CULL_REBOUND,
+ FTM_FRUSTUM_CULL,
FTM_GEO_UPDATE,
FTM_GEO_RESERVE,
FTM_GEO_LIGHT,
@@ -97,6 +121,7 @@ public:
FTM_IMAGE_UPDATE,
FTM_IMAGE_CREATE,
FTM_IMAGE_DECODE,
+ FTM_IMAGE_MARK_DIRTY,
FTM_PIPELINE,
FTM_VFILE_WAIT,
FTM_FLEXIBLE_UPDATE,
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 4acd94f943..f43e57f467 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -29,6 +29,19 @@ int LLFile::mkdir(const char* dirname, int perms)
}
// static
+int LLFile::rmdir(const char* dirname)
+{
+#if LL_WINDOWS
+ // permissions are ignored on Windows
+ std::string utf8dirname = dirname;
+ llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
+ return _wrmdir(utf16dirname.c_str());
+#else
+ return ::rmdir(dirname);
+#endif
+}
+
+// static
LLFILE* LLFile::fopen(const char* filename, const char* mode) /* Flawfinder: ignore */
{
#if LL_WINDOWS
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 2899f51a60..605918cd29 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -50,6 +50,7 @@ public:
// be overridden by the user's umask. It is ignored on Windows.
static int mkdir(const char* filename, int perms = 0700);
+ static int rmdir(const char* filename);
static int remove(const char* filename);
static int rename(const char* filename,const char* newname);
static int stat(const char* filename,llstat* file_status);
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 0a21c3a2a7..1063de5a8c 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -9,6 +9,7 @@
#include "linden_common.h"
#include "llmemory.h"
+#include "llmemtype.h"
// not defining nullfunc will currently crash when trying to use a LLHandle
template< typename _Ty >
@@ -244,43 +245,6 @@ void operator delete[] (void *p)
//----------------------------------------------------------------------------
-//static
-LLMutex* LLThreadSafeRefCount::sMutex = 0;
-
-//static
-void LLThreadSafeRefCount::initClass()
-{
- if (!sMutex)
- {
- sMutex = new LLMutex(0);
- }
-}
-
-//static
-void LLThreadSafeRefCount::cleanupClass()
-{
- delete sMutex;
- sMutex = NULL;
-}
-
-
-//----------------------------------------------------------------------------
-
-LLThreadSafeRefCount::LLThreadSafeRefCount() :
- mRef(0)
-{
-}
-
-LLThreadSafeRefCount::~LLThreadSafeRefCount()
-{
- if (mRef != 0)
- {
- llerrs << "deleting non-zero reference" << llendl;
- }
-}
-
-//----------------------------------------------------------------------------
-
LLRefCount::LLRefCount() :
mRef(0)
{
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 962a4aa5d5..d543d023ff 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -12,8 +12,6 @@
#include <cstdlib>
#include "llerror.h"
-#include "llthread.h"
-#include "llmemtype.h"
extern S32 gTotalDAlloc;
extern S32 gTotalDAUse;
@@ -42,53 +40,7 @@ private:
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
// x->instantiate(); // does stuff like place x into an update queue
-class LLThreadSafeRefCount
-{
-public:
- static void initClass(); // creates sMutex
- static void cleanupClass(); // destroys sMutex
-
-private:
- static LLMutex* sMutex;
-
-private:
- LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
- LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
-
-protected:
- virtual ~LLThreadSafeRefCount(); // use unref()
-
-public:
- LLThreadSafeRefCount();
-
- void ref()
- {
- if (sMutex) sMutex->lock();
- mRef++;
- if (sMutex) sMutex->unlock();
- }
-
- S32 unref()
- {
- llassert(mRef >= 1);
- if (sMutex) sMutex->lock();
- S32 res = --mRef;
- if (sMutex) sMutex->unlock();
- if (0 == res)
- {
- delete this;
- res = 0;
- }
- return res;
- }
- S32 getNumRefs() const
- {
- return mRef;
- }
-
-private:
- S32 mRef;
-};
+// see llthread.h for LLThreadSafeRefCount
//----------------------------------------------------------------------------
@@ -132,6 +84,7 @@ private:
//----------------------------------------------------------------------------
+// Note: relies on Type having ref() and unref() methods
template <class Type> class LLPointer
{
public:
diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h
index 17afaa6a8a..53f7f66285 100644
--- a/indra/llcommon/llmemtype.h
+++ b/indra/llcommon/llmemtype.h
@@ -52,6 +52,7 @@ public:
MTYPE_DRAWABLE,
MTYPE_OBJECT,
+ MTYPE_VERTEX_DATA,
MTYPE_SPACE_PARTITION,
MTYPE_PIPELINE,
MTYPE_AVATAR,
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index bc41927d38..e6ac9ac11d 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -12,10 +12,9 @@
//============================================================================
// MAIN THREAD
-LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool runalways) :
+LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
LLThread(name),
mThreaded(threaded),
- mRunAlways(runalways),
mIdleThread(TRUE),
mNextHandle(0)
{
@@ -28,6 +27,12 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool runa
// MAIN THREAD
LLQueuedThread::~LLQueuedThread()
{
+ shutdown();
+ // ~LLThread() will be called here
+}
+
+void LLQueuedThread::shutdown()
+{
setQuitting();
unpause(); // MAIN THREAD
@@ -54,61 +59,69 @@ LLQueuedThread::~LLQueuedThread()
}
QueuedRequest* req;
+ S32 active_count = 0;
while ( (req = (QueuedRequest*)mRequestHash.pop_element()) )
{
+ if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
+ {
+ ++active_count;
+ }
req->deleteRequest();
}
-
- // ~LLThread() will be called here
+ if (active_count)
+ {
+ llwarns << "~LLQueuedThread() called with active requests: " << active_count << llendl;
+ }
}
//----------------------------------------------------------------------------
// MAIN THREAD
-void LLQueuedThread::update(U32 ms_elapsed)
+// virtual
+S32 LLQueuedThread::update(U32 max_time_ms)
{
- updateQueue(0);
+ return updateQueue(max_time_ms);
}
-void LLQueuedThread::updateQueue(S32 inc)
+S32 LLQueuedThread::updateQueue(U32 max_time_ms)
{
- // If mRunAlways == TRUE, unpause the thread whenever we put something into the queue.
- // If mRunAlways == FALSE, we only unpause the thread when updateQueue() is called from the main loop (i.e. between rendered frames)
-
- if (inc == 0) // Frame Update
+ F64 max_time = (F64)max_time_ms * .001;
+ LLTimer timer;
+ S32 pending = 1;
+
+ // Frame Update
+ if (mThreaded)
{
- if (mThreaded)
- {
- unpause();
- wake(); // Wake the thread up if necessary.
- }
- else
+ pending = getPending();
+ unpause();
+ }
+ else
+ {
+ while (pending > 0)
{
- while (processNextRequest() > 0)
- ;
+ pending = processNextRequest();
+ if (max_time && timer.getElapsedTimeF64() > max_time)
+ break;
}
}
- else
+ return pending;
+}
+
+void LLQueuedThread::incQueue()
+{
+ // Something has been added to the queue
+ if (!isPaused())
{
- // Something has been added to the queue
- if (mRunAlways)
+ if (mThreaded)
{
- if (mThreaded)
- {
- wake(); // Wake the thread up if necessary.
- }
- else
- {
- while(processNextRequest() > 0)
- ;
- }
+ wake(); // Wake the thread up if necessary.
}
}
}
//virtual
// May be called from any thread
-S32 LLQueuedThread::getPending(bool child_thread)
+S32 LLQueuedThread::getPending()
{
S32 res;
lockData();
@@ -122,7 +135,7 @@ void LLQueuedThread::waitOnPending()
{
while(1)
{
- updateQueue(0);
+ update(0);
if (mIdleThread)
{
@@ -181,7 +194,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
#endif
unlockData();
- updateQueue(1);
+ incQueue();
return true;
}
@@ -195,7 +208,7 @@ bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_co
bool done = false;
while(!done)
{
- updateQueue(0); // unpauses
+ update(0); // unpauses
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (!req)
@@ -253,51 +266,47 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)
return res;
}
-LLQueuedThread::status_t LLQueuedThread::abortRequest(handle_t handle, U32 flags)
+void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)
{
- status_t res = STATUS_EXPIRED;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (req)
{
- res = req->abortRequest(flags);
- if ((flags & AUTO_COMPLETE) && (res == STATUS_COMPLETE))
- {
- mRequestHash.erase(handle);
- req->deleteRequest();
-// check();
- }
-#if _DEBUG
-// llinfos << llformat("LLQueuedThread::Aborted req [%08d]",handle) << llendl;
-#endif
+ req->setFlags(FLAG_ABORT | (autocomplete ? FLAG_AUTO_COMPLETE : 0));
}
unlockData();
- return res;
}
// MAIN thread
-LLQueuedThread::status_t LLQueuedThread::setFlags(handle_t handle, U32 flags)
+void LLQueuedThread::setFlags(handle_t handle, U32 flags)
{
- status_t res = STATUS_EXPIRED;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (req)
{
- res = req->setFlags(flags);
+ req->setFlags(flags);
}
unlockData();
- return res;
}
void LLQueuedThread::setPriority(handle_t handle, U32 priority)
{
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req && (req->getStatus() == STATUS_QUEUED))
+ if (req)
{
- llverify(mRequestQueue.erase(req) == 1);
- req->setPriority(priority);
- mRequestQueue.insert(req);
+ if(req->getStatus() == STATUS_INPROGRESS)
+ {
+ // not in list
+ req->setPriority(priority);
+ }
+ else if(req->getStatus() == STATUS_QUEUED)
+ {
+ // remove from list then re-insert
+ llverify(mRequestQueue.erase(req) == 1);
+ req->setPriority(priority);
+ mRequestQueue.insert(req);
+ }
}
unlockData();
}
@@ -309,9 +318,10 @@ bool LLQueuedThread::completeRequest(handle_t handle)
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (req)
{
- llassert(req->getStatus() != STATUS_QUEUED && req->getStatus() != STATUS_ABORT);
+ llassert_always(req->getStatus() != STATUS_QUEUED);
+ llassert_always(req->getStatus() != STATUS_INPROGRESS);
#if _DEBUG
-// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
+// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
#endif
mRequestHash.erase(handle);
req->deleteRequest();
@@ -345,28 +355,34 @@ bool LLQueuedThread::check()
//============================================================================
// Runs on its OWN thread
-int LLQueuedThread::processNextRequest()
+S32 LLQueuedThread::processNextRequest()
{
- QueuedRequest *req = 0;
+ QueuedRequest *req;
// Get next request from pool
lockData();
while(1)
{
- if (!mRequestQueue.empty())
+ req = NULL;
+ if (mRequestQueue.empty())
{
- req = *mRequestQueue.begin();
- mRequestQueue.erase(mRequestQueue.begin());
+ break;
}
- if (req && req->getStatus() == STATUS_ABORT)
+ req = *mRequestQueue.begin();
+ mRequestQueue.erase(mRequestQueue.begin());
+ if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
{
req->setStatus(STATUS_ABORTED);
- req = 0;
- }
- else
- {
- llassert (!req || req->getStatus() == STATUS_QUEUED)
- break;
+ req->finishRequest(false);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
+ {
+ mRequestHash.erase(req);
+ req->deleteRequest();
+// check();
+ }
+ continue;
}
+ llassert_always(req->getStatus() == STATUS_QUEUED);
+ break;
}
if (req)
{
@@ -374,22 +390,22 @@ int LLQueuedThread::processNextRequest()
}
unlockData();
- // This is the only place we will cal req->setStatus() after
+ // This is the only place we will call req->setStatus() after
// it has initially been seet to STATUS_QUEUED, so it is
// safe to access req.
if (req)
{
// process request
- bool complete = processRequest(req);
+ bool complete = req->processRequest();
if (complete)
{
lockData();
req->setStatus(STATUS_COMPLETE);
- req->finishRequest();
- if (req->getFlags() & AUTO_COMPLETE)
+ req->finishRequest(true);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
- llverify(mRequestHash.erase(req))
+ mRequestHash.erase(req);
req->deleteRequest();
// check();
}
@@ -400,12 +416,18 @@ int LLQueuedThread::processNextRequest()
lockData();
req->setStatus(STATUS_QUEUED);
mRequestQueue.insert(req);
+ U32 priority = req->getPriority();
unlockData();
+ if (priority < PRIORITY_NORMAL)
+ {
+ ms_sleep(1); // sleep the thread a little
+ }
}
}
- int res;
- if (getPending(true) == 0)
+ S32 res;
+ S32 pending = getPending();
+ if (pending == 0)
{
if (isQuitting())
{
@@ -418,7 +440,7 @@ int LLQueuedThread::processNextRequest()
}
else
{
- res = 1;
+ res = pending;
}
return res;
}
@@ -426,13 +448,14 @@ int LLQueuedThread::processNextRequest()
bool LLQueuedThread::runCondition()
{
// mRunCondition must be locked here
- return (mRequestQueue.empty() && mIdleThread) ? FALSE : TRUE;
+ if (mRequestQueue.empty() && mIdleThread)
+ return false;
+ else
+ return true;
}
void LLQueuedThread::run()
{
- llinfos << "QUEUED THREAD STARTING" << llendl;
-
while (1)
{
// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
@@ -455,6 +478,8 @@ void LLQueuedThread::run()
{
break;
}
+
+ //LLThread::yield(); // thread should yield after each request
}
llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl;
@@ -472,20 +497,18 @@ LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U3
LLQueuedThread::QueuedRequest::~QueuedRequest()
{
- if (mStatus != STATUS_DELETE)
- {
- llerrs << "Attemt to directly delete a LLQueuedThread::QueuedRequest; use deleteRequest()" << llendl;
- }
+ llassert_always(mStatus == STATUS_DELETE);
}
//virtual
-void LLQueuedThread::QueuedRequest::finishRequest()
+void LLQueuedThread::QueuedRequest::finishRequest(bool completed)
{
}
//virtual
void LLQueuedThread::QueuedRequest::deleteRequest()
{
+ llassert_always(mStatus != STATUS_INPROGRESS);
setStatus(STATUS_DELETE);
delete this;
}
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index beff473f52..8b6a658333 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -33,7 +33,8 @@ public:
PRIORITY_HIGH = 0x30000000,
PRIORITY_NORMAL = 0x20000000,
PRIORITY_LOW = 0x10000000,
- PRIORITY_LOWBITS = 0x0FFFFFFF
+ PRIORITY_LOWBITS = 0x0FFFFFFF,
+ PRIORITY_HIGHBITS = 0x70000000
};
enum status_t {
STATUS_EXPIRED = -1,
@@ -41,13 +42,13 @@ public:
STATUS_QUEUED = 1,
STATUS_INPROGRESS = 2,
STATUS_COMPLETE = 3,
- STATUS_ABORT = 4,
- STATUS_ABORTED = 5,
- STATUS_DELETE = 6
+ STATUS_ABORTED = 4,
+ STATUS_DELETE = 5
};
enum flags_t {
- AUTO_COMPLETE = 1,
- AUTO_DELETE = 2 // child-class dependent
+ FLAG_AUTO_COMPLETE = 1,
+ FLAG_AUTO_DELETE = 2, // child-class dependent
+ FLAG_ABORT = 4
};
typedef U32 handle_t;
@@ -60,7 +61,7 @@ public:
friend class LLQueuedThread;
protected:
- ~QueuedRequest(); // use deleteRequest()
+ virtual ~QueuedRequest(); // use deleteRequest()
public:
QueuedRequest(handle_t handle, U32 priority, U32 flags = 0);
@@ -92,26 +93,14 @@ public:
mStatus = newstatus;
return oldstatus;
}
- status_t abortRequest(U32 flags)
+ void setFlags(U32 flags)
{
// NOTE: flags are |'d
- if (mStatus == STATUS_QUEUED)
- {
- setStatus(STATUS_ABORT);
- }
mFlags |= flags;
- status_t status = mStatus;
- return status;
- }
- status_t setFlags(U32 flags)
- {
- // NOTE: flags are |'d
- mFlags |= flags;
- status_t status = mStatus;
- return status;
}
- virtual void finishRequest(); // Always called when after has been processed
+ virtual bool processRequest() = 0; // Return true when request has completed
+ virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
virtual void deleteRequest(); // Only method to delete a request
void setPriority(U32 pri)
@@ -141,9 +130,10 @@ public:
static handle_t nullHandle() { return handle_t(0); }
public:
- LLQueuedThread(const std::string& name, bool threaded = TRUE, bool runalways = TRUE);
+ LLQueuedThread(const std::string& name, bool threaded = true);
virtual ~LLQueuedThread();
-
+ virtual void shutdown();
+
private:
// No copy constructor or copy assignment
LLQueuedThread(const LLQueuedThread&);
@@ -155,26 +145,25 @@ private:
protected:
handle_t generateHandle();
bool addRequest(QueuedRequest* req);
- int processNextRequest(void);
+ S32 processNextRequest(void);
+ void incQueue();
- virtual bool processRequest(QueuedRequest* req) = 0;
-
public:
bool waitForResult(handle_t handle, bool auto_complete = true);
- void update(U32 ms_elapsed);
- void updateQueue(S32 inc);
+ virtual S32 update(U32 max_time_ms);
+ S32 updateQueue(U32 max_time_ms);
+
void waitOnPending();
void printQueueStats();
- S32 getPending(bool child_thread = false);
+ S32 getPending();
bool getThreaded() { return mThreaded ? true : false; }
- bool getRunAlways() { return mRunAlways ? true : false; }
// Request accessors
status_t getRequestStatus(handle_t handle);
- status_t abortRequest(handle_t handle, U32 flags = 0);
- status_t setFlags(handle_t handle, U32 flags);
+ void abortRequest(handle_t handle, bool autocomplete);
+ void setFlags(handle_t handle, U32 flags);
void setPriority(handle_t handle, U32 priority);
bool completeRequest(handle_t handle);
// This is public for support classes like LLWorkerThread,
@@ -186,7 +175,6 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
- BOOL mRunAlways; // if false, only wake the threads when updateClass() is called
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h
index b07c18eb72..cbea60034f 100644
--- a/indra/llcommon/llsecondlifeurls.h
+++ b/indra/llcommon/llsecondlifeurls.h
@@ -31,18 +31,9 @@ extern const char UPGRADE_TO_PREMIUM_URL[];
// How to get DirectX 9
extern const char DIRECTX_9_URL[];
-// On AMD with bad AGP controller
-extern const char AMD_AGP_URL[];
-
// Out of date VIA chipset
extern const char VIA_URL[];
-// Out of date intel chipset driver
-extern const char INTEL_CHIPSET_URL[];
-
-// Out of date SiS chipset driver
-extern const char SIS_CHIPSET_URL[];
-
// Linden Blogs page
extern const char BLOGS_URL[];
diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h
index 0688e43940..c5fbf1282a 100644
--- a/indra/llcommon/llstrider.h
+++ b/indra/llcommon/llstrider.h
@@ -32,6 +32,7 @@ public:
Object* operator->() { return mObjectp; }
Object& operator *() { return *mObjectp; }
Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; }
+ Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; }
Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); }
};
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index bd2dd7c8f5..a92d553148 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -81,6 +81,11 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
LLThread::~LLThread()
{
+ shutdown();
+}
+
+void LLThread::shutdown()
+{
// Warning! If you somehow call the thread destructor from itself,
// the thread will die in an unclean fashion!
if (mAPRThreadp)
@@ -186,18 +191,6 @@ void LLThread::checkPause()
//============================================================================
-bool LLThread::isQuitting() const
-{
- return (QUITTING == mStatus);
-}
-
-
-bool LLThread::isStopped() const
-{
- return (STOPPED == mStatus);
-}
-
-
void LLThread::setQuitting()
{
mRunCondition->lock();
@@ -328,3 +321,49 @@ void LLCondition::broadcast()
apr_thread_cond_broadcast(mAPRCondp);
}
+//============================================================================
+
+//----------------------------------------------------------------------------
+
+//static
+LLMutex* LLThreadSafeRefCount::sMutex = 0;
+
+//static
+void LLThreadSafeRefCount::initClass()
+{
+ if (!sMutex)
+ {
+ sMutex = new LLMutex(0);
+ }
+}
+
+//static
+void LLThreadSafeRefCount::cleanupClass()
+{
+ delete sMutex;
+ sMutex = NULL;
+}
+
+
+//----------------------------------------------------------------------------
+
+LLThreadSafeRefCount::LLThreadSafeRefCount() :
+ mRef(0)
+{
+}
+
+LLThreadSafeRefCount::~LLThreadSafeRefCount()
+{
+ if (mRef != 0)
+ {
+ llerrs << "deleting non-zero reference" << llendl;
+ }
+}
+
+//============================================================================
+
+LLResponder::~LLResponder()
+{
+}
+
+//============================================================================
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index f6f6bd210a..ce5daa938c 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -11,6 +11,7 @@
#include "llapr.h"
#include "llapp.h"
+#include "llmemory.h"
#include "apr-1/apr_thread_cond.h"
@@ -30,19 +31,20 @@ public:
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
-
+ virtual void shutdown(); // stops the thread
+
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
- bool isQuitting() const;
- bool isStopped() const;
+ bool isQuitting() const { return (QUITTING == mStatus); }
+ bool isStopped() const { return (STOPPED == mStatus); }
// PAUSE / RESUME functionality. See source code for important usage notes.
public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return mPaused ? true : false; }
+ bool isPaused() { return isStopped() || mPaused == TRUE; }
// Cause the thread to wake up and check its condition
void wake();
@@ -60,7 +62,7 @@ public:
private:
BOOL mPaused;
-
+
// static function passed to APR thread creation routine
static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
@@ -161,4 +163,67 @@ void LLThread::unlockData()
//============================================================================
+// see llmemory.h for LLPointer<> definition
+
+class LLThreadSafeRefCount
+{
+public:
+ static void initClass(); // creates sMutex
+ static void cleanupClass(); // destroys sMutex
+
+private:
+ static LLMutex* sMutex;
+
+private:
+ LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
+ LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
+
+protected:
+ virtual ~LLThreadSafeRefCount(); // use unref()
+
+public:
+ LLThreadSafeRefCount();
+
+ void ref()
+ {
+ if (sMutex) sMutex->lock();
+ mRef++;
+ if (sMutex) sMutex->unlock();
+ }
+
+ S32 unref()
+ {
+ llassert(mRef >= 1);
+ if (sMutex) sMutex->lock();
+ S32 res = --mRef;
+ if (sMutex) sMutex->unlock();
+ if (0 == res)
+ {
+ delete this;
+ res = 0;
+ }
+ return res;
+ }
+ S32 getNumRefs() const
+ {
+ return mRef;
+ }
+
+private:
+ S32 mRef;
+};
+
+//============================================================================
+
+// Simple responder for self destructing callbacks
+// Pure virtual class
+class LLResponder : public LLThreadSafeRefCount
+{
+public:
+ virtual ~LLResponder();
+ virtual void completed(bool success) = 0;
+};
+
+//============================================================================
+
#endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index a9370c8f6d..31f5c1cfcd 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -14,98 +14,86 @@
#endif
//============================================================================
-
-/*static*/ LLWorkerThread* LLWorkerThread::sLocal = NULL;
-/*static*/ std::set<LLWorkerThread*> LLWorkerThread::sThreadList;
-
-//============================================================================
// Run on MAIN thread
-//static
-void LLWorkerThread::initClass(bool local_is_threaded, bool local_run_always)
+LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
+ LLQueuedThread(name, threaded),
+ mWorkerAPRPoolp(NULL)
{
- if (!sLocal)
- {
- sLocal = new LLWorkerThread(local_is_threaded, local_run_always);
- }
+ apr_pool_create(&mWorkerAPRPoolp, NULL);
+ mDeleteMutex = new LLMutex(getAPRPool());
}
-//static
-void LLWorkerThread::cleanupClass()
+LLWorkerThread::~LLWorkerThread()
{
- if (sLocal)
+ // Delete any workers in the delete queue (should be safe - had better be!)
+ if (!mDeleteList.empty())
{
- while (sLocal->getPending())
- {
- sLocal->update(0);
- }
- delete sLocal;
- sLocal = NULL;
- llassert(sThreadList.size() == 0);
+ llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << llendl;
}
-}
-//static
-S32 LLWorkerThread::updateClass(U32 ms_elapsed)
-{
- for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++)
- {
- (*iter)->update(ms_elapsed);
- }
- return getAllPending();
+ delete mDeleteMutex;
+
+ // ~LLQueuedThread() will be called here
}
-//static
-S32 LLWorkerThread::getAllPending()
+// virtual
+S32 LLWorkerThread::update(U32 max_time_ms)
{
- S32 res = 0;
- for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++)
+ S32 res = LLQueuedThread::update(max_time_ms);
+ // Delete scheduled workers
+ std::vector<LLWorkerClass*> delete_list;
+ std::vector<LLWorkerClass*> abort_list;
+ mDeleteMutex->lock();
+ for (delete_list_t::iterator iter = mDeleteList.begin();
+ iter != mDeleteList.end(); )
{
- res += (*iter)->getPending();
+ delete_list_t::iterator curiter = iter++;
+ LLWorkerClass* worker = *curiter;
+ if (worker->deleteOK())
+ {
+ if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
+ {
+ delete_list.push_back(worker);
+ mDeleteList.erase(curiter);
+ }
+ else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
+ {
+ abort_list.push_back(worker);
+ }
+ }
}
- return res;
-}
-
-//static
-void LLWorkerThread::pauseAll()
-{
- for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++)
+ mDeleteMutex->unlock();
+ // abort and delete after releasing mutex
+ for (std::vector<LLWorkerClass*>::iterator iter = abort_list.begin();
+ iter != abort_list.end(); ++iter)
{
- (*iter)->pause();
+ (*iter)->abortWork(false);
}
-}
-
-//static
-void LLWorkerThread::waitOnAllPending()
-{
- for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++)
+ for (std::vector<LLWorkerClass*>::iterator iter = delete_list.begin();
+ iter != delete_list.end(); ++iter)
{
- (*iter)->waitOnPending();
+ LLWorkerClass* worker = *iter;
+ if (worker->mRequestHandle)
+ {
+ // Finished but not completed
+ completeRequest(worker->mRequestHandle);
+ worker->mRequestHandle = LLWorkerThread::nullHandle();
+ worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ }
+ delete *iter;
}
+ return res;
}
//----------------------------------------------------------------------------
-LLWorkerThread::LLWorkerThread(bool threaded, bool runalways) :
- LLQueuedThread("Worker", threaded, runalways)
-{
- sThreadList.insert(this);
-}
-
-LLWorkerThread::~LLWorkerThread()
-{
- llverify(sThreadList.erase(this) == 1);
- // ~LLQueuedThread() will be called here
-}
-
-//----------------------------------------------------------------------------
-
-
-LLWorkerThread::handle_t LLWorkerThread::add(LLWorkerClass* workerclass, S32 param, U32 priority)
+LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority)
{
handle_t handle = generateHandle();
- Request* req = new Request(handle, priority, workerclass, param);
+ WorkRequest* req = new WorkRequest(handle, priority, workerclass, param);
bool res = addRequest(req);
if (!res)
@@ -118,63 +106,80 @@ LLWorkerThread::handle_t LLWorkerThread::add(LLWorkerClass* workerclass, S32 par
return handle;
}
-//============================================================================
-// Runs on its OWN thread
-
-bool LLWorkerThread::processRequest(QueuedRequest* qreq)
+void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
{
- Request *req = (Request*)qreq;
-
- req->getWorkerClass()->setWorking(true);
-
- bool complete = req->getWorkerClass()->doWork(req->getParam());
-
- req->getWorkerClass()->setWorking(false);
-
- LLThread::yield(); // worker thread should yield after each request
-
- return complete;
+ mDeleteMutex->lock();
+ mDeleteList.push_back(workerclass);
+ mDeleteMutex->unlock();
}
//============================================================================
+// Runs on its OWN thread
-LLWorkerThread::Request::Request(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) :
+LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) :
LLQueuedThread::QueuedRequest(handle, priority),
mWorkerClass(workerclass),
mParam(param)
{
}
-void LLWorkerThread::Request::deleteRequest()
+LLWorkerThread::WorkRequest::~WorkRequest()
+{
+}
+
+// virtual (required for access by LLWorkerThread)
+void LLWorkerThread::WorkRequest::deleteRequest()
{
LLQueuedThread::QueuedRequest::deleteRequest();
}
+// virtual
+bool LLWorkerThread::WorkRequest::processRequest()
+{
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->setWorking(true);
+ bool complete = workerclass->doWork(getParam());
+ workerclass->setWorking(false);
+ return complete;
+}
+
+// virtual
+void LLWorkerThread::WorkRequest::finishRequest(bool completed)
+{
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->finishWork(getParam(), completed);
+ U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
+ workerclass->setFlags(flags);
+}
+
//============================================================================
// LLWorkerClass:: operates in main thread
LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name)
: mWorkerThread(workerthread),
mWorkerClassName(name),
- mWorkHandle(LLWorkerThread::nullHandle()),
+ mRequestHandle(LLWorkerThread::nullHandle()),
+ mMutex(workerthread->getWorkerAPRPool()),
mWorkFlags(0)
{
if (!mWorkerThread)
{
- mWorkerThread = LLWorkerThread::sLocal;
+ llerrs << "LLWorkerClass() called with NULL workerthread: " << name << llendl;
}
}
+
LLWorkerClass::~LLWorkerClass()
{
- if (mWorkHandle != LLWorkerThread::nullHandle())
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
+ if (mRequestHandle != LLWorkerThread::nullHandle())
{
- LLWorkerThread::Request* workreq = (LLWorkerThread::Request*)mWorkerThread->getRequest(mWorkHandle);
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
if (!workreq)
{
llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
}
- if (workreq->getStatus() != LLWorkerThread::STATUS_ABORT &&
- workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
+ if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
{
llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
@@ -184,21 +189,58 @@ LLWorkerClass::~LLWorkerClass()
void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread)
{
- if (mWorkHandle != LLWorkerThread::nullHandle())
+ mMutex.lock();
+ if (mRequestHandle != LLWorkerThread::nullHandle())
{
llerrs << "LLWorkerClass attempt to change WorkerThread with active worker!" << llendl;
}
mWorkerThread = workerthread;
+ mMutex.unlock();
+}
+
+//----------------------------------------------------------------------------
+
+//virtual
+void LLWorkerClass::finishWork(S32 param, bool success)
+{
+}
+
+//virtual
+bool LLWorkerClass::deleteOK()
+{
+ return true; // default always OK
+}
+
+//----------------------------------------------------------------------------
+
+// Called from worker thread
+void LLWorkerClass::setWorking(bool working)
+{
+ mMutex.lock();
+ if (working)
+ {
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ setFlags(WCF_WORKING);
+ }
+ else
+ {
+ llassert_always((mWorkFlags & WCF_WORKING));
+ clearFlags(WCF_WORKING);
+ }
+ mMutex.unlock();
}
//----------------------------------------------------------------------------
bool LLWorkerClass::yield()
{
- llassert(mWorkFlags & WCF_WORKING);
LLThread::yield();
mWorkerThread->checkPause();
- return (getFlags() & WCF_ABORT_REQUESTED) ? true : false;
+ bool res;
+ mMutex.lock();
+ res = (getFlags() & WCF_ABORT_REQUESTED) ? true : false;
+ mMutex.unlock();
+ return res;
}
//----------------------------------------------------------------------------
@@ -206,7 +248,9 @@ bool LLWorkerClass::yield()
// calls startWork, adds doWork() to queue
void LLWorkerClass::addWork(S32 param, U32 priority)
{
- if (mWorkHandle != LLWorkerThread::nullHandle())
+ mMutex.lock();
+ llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
+ if (mRequestHandle != LLWorkerThread::nullHandle())
{
llerrs << "LLWorkerClass attempt to add work with active worker!" << llendl;
}
@@ -214,70 +258,93 @@ void LLWorkerClass::addWork(S32 param, U32 priority)
// llinfos << "addWork: " << mWorkerClassName << " Param: " << param << llendl;
#endif
startWork(param);
- mWorkHandle = mWorkerThread->add(this, param, priority);
+ clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
+ setFlags(WCF_HAVE_WORK);
+ mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority);
+ mMutex.unlock();
}
-void LLWorkerClass::abortWork()
+void LLWorkerClass::abortWork(bool autocomplete)
{
+ mMutex.lock();
#if _DEBUG
-// LLWorkerThread::Request* workreq = mWorkerThread->getRequest(mWorkHandle);
+// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
// if (workreq)
// llinfos << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl;
#endif
- mWorkerThread->abortRequest(mWorkHandle);
- setFlags(WCF_ABORT_REQUESTED);
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ mWorkerThread->abortRequest(mRequestHandle, autocomplete);
+ mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE);
+ setFlags(WCF_ABORT_REQUESTED);
+ }
+ mMutex.unlock();
}
// if doWork is complete or aborted, call endWork() and return true
-bool LLWorkerClass::checkWork()
+bool LLWorkerClass::checkWork(bool aborting)
{
+ LLMutexLock lock(&mMutex);
bool complete = false, abort = false;
- LLWorkerThread::Request* workreq = (LLWorkerThread::Request*)mWorkerThread->getRequest(mWorkHandle);
- llassert(workreq);
- if (getFlags(WCF_ABORT_REQUESTED) || workreq->getStatus() == LLWorkerThread::STATUS_ABORTED)
+ if (mRequestHandle != LLWorkerThread::nullHandle())
{
- complete = true;
- abort = true;
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
+ llassert_always(workreq);
+ LLQueuedThread::status_t status = workreq->getStatus();
+ if (status == LLWorkerThread::STATUS_ABORTED)
+ {
+ complete = true;
+ abort = true;
+ }
+ else if (status == LLWorkerThread::STATUS_COMPLETE)
+ {
+ complete = true;
+ }
+ else
+ {
+ llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT));
+ }
+ if (complete)
+ {
+ llassert_always(!(getFlags(WCF_WORKING)));
+ endWork(workreq->getParam(), abort);
+ mWorkerThread->completeRequest(mRequestHandle);
+ mRequestHandle = LLWorkerThread::nullHandle();
+ clearFlags(WCF_HAVE_WORK);
+ }
}
- else if (workreq->getStatus() == LLWorkerThread::STATUS_COMPLETE)
+ else
{
complete = true;
}
- if (complete)
- {
-#if _DEBUG
-// llinfos << "endWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl;
-#endif
- endWork(workreq->getParam(), abort);
- mWorkerThread->completeRequest(mWorkHandle);
- mWorkHandle = LLWorkerThread::nullHandle();
- }
return complete;
}
-void LLWorkerClass::killWork()
+void LLWorkerClass::scheduleDelete()
{
- if (haveWork())
+ bool do_delete = false;
+ mMutex.lock();
+ if (!(getFlags(WCF_DELETE_REQUESTED)))
{
- abortWork();
- bool paused = mWorkerThread->isPaused();
- while (!checkWork())
- {
- mWorkerThread->updateQueue(0);
- }
- if (paused)
- {
- mWorkerThread->pause();
- }
+ setFlags(WCF_DELETE_REQUESTED);
+ do_delete = true;
+ }
+ mMutex.unlock();
+ if (do_delete)
+ {
+ mWorkerThread->deleteWorker(this);
}
}
void LLWorkerClass::setPriority(U32 priority)
{
- if (haveWork())
+ mMutex.lock();
+ if (mRequestHandle != LLWorkerThread::nullHandle())
{
- mWorkerThread->setPriority(mWorkHandle, priority);
+ mRequestPriority = priority;
+ mWorkerThread->setPriority(mRequestHandle, priority);
}
+ mMutex.unlock();
}
//============================================================================
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index bf5887e797..d466c35786 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -28,13 +28,13 @@ class LLWorkerClass;
class LLWorkerThread : public LLQueuedThread
{
public:
- class Request : public LLQueuedThread::QueuedRequest
+ class WorkRequest : public LLQueuedThread::QueuedRequest
{
protected:
- ~Request() {}; // use deleteRequest()
+ virtual ~WorkRequest(); // use deleteRequest()
public:
- Request(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param);
+ WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param);
S32 getParam()
{
@@ -45,6 +45,8 @@ public:
return mWorkerClass;
}
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
/*virtual*/ void deleteRequest();
private:
@@ -52,26 +54,24 @@ public:
S32 mParam;
};
-public:
- LLWorkerThread(bool threaded = true, bool runalways = true);
- ~LLWorkerThread();
-
-protected:
- /*virtual*/ bool processRequest(QueuedRequest* req);
+private:
+ typedef std::list<LLWorkerClass*> delete_list_t;
+ delete_list_t mDeleteList;
+ LLMutex* mDeleteMutex;
+ apr_pool_t* mWorkerAPRPoolp;
public:
- handle_t add(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
-
- static void initClass(bool local_is_threaded = true, bool local_run_always = true); // Setup sLocal
- static S32 updateClass(U32 ms_elapsed);
- static S32 getAllPending();
- static void pauseAll();
- static void waitOnAllPending();
- static void cleanupClass(); // Delete sLocal
+ LLWorkerThread(const std::string& name, bool threaded = true);
+ ~LLWorkerThread();
-public:
- static LLWorkerThread* sLocal; // Default worker thread
- static std::set<LLWorkerThread*> sThreadList; // array of threads (includes sLocal)
+ apr_pool_t* getWorkerAPRPool() { return mWorkerAPRPoolp; }
+
+ /*virtual*/ S32 update(U32 max_time_ms);
+
+ handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
+
+ void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
+ S32 getNumDeletes() { return mDeleteList.size(); } // debug
};
//============================================================================
@@ -93,11 +93,17 @@ public:
class LLWorkerClass
{
+ friend class LLWorkerThread;
+ friend class LLWorkerThread::WorkRequest;
public:
typedef LLWorkerThread::handle_t handle_t;
enum FLAGS
{
- WCF_WORKING = 0x01,
+ WCF_HAVE_WORK = 0x01,
+ WCF_WORKING = 0x02,
+ WCF_WORK_FINISHED = 0x10,
+ WCF_WORK_ABORTED = 0x20,
+ WCF_DELETE_REQUESTED = 0x40,
WCF_ABORT_REQUESTED = 0x80
};
@@ -106,17 +112,29 @@ public:
virtual ~LLWorkerClass();
// pure virtual, called from WORKER THREAD, returns TRUE if done
- virtual bool doWork(S32 param)=0; // Called from LLWorkerThread::processRequest()
-
- // called from WORKER THREAD
- void setWorking(bool working) { working ? setFlags(WCF_WORKING) : clearFlags(WCF_WORKING); }
+ virtual bool doWork(S32 param)=0; // Called from WorkRequest::processRequest()
+ // virtual, called from finishRequest() after completed or aborted
+ virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
+ // virtual, returns true if safe to delete the worker
+ virtual bool deleteOK(); // called from update() (WORK THREAD)
+ // schedlueDelete(): schedules deletion once aborted or completed
+ void scheduleDelete();
+
+ bool haveWork() { return getFlags(WCF_HAVE_WORK); } // may still be true if aborted
bool isWorking() { return getFlags(WCF_WORKING); }
bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
+
+ // setPriority(): changes the priority of a request
+ void setPriority(U32 priority);
+ U32 getPriority() { return mRequestPriority; }
const std::string& getName() const { return mWorkerClassName; }
protected:
+ // called from WORKER THREAD
+ void setWorking(bool working);
+
// Call from doWork only to avoid eating up cpu time.
// Returns true if work has been aborted
// yields the current thread and calls mWorkerThread->checkPause()
@@ -128,20 +146,11 @@ protected:
void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL);
// abortWork(): requests that work be aborted
- void abortWork();
+ void abortWork(bool autocomplete);
// checkWork(): if doWork is complete or aborted, call endWork() and return true
- bool checkWork();
+ bool checkWork(bool aborting = false);
- // haveWork(): return true if mWorkHandle != null
- bool haveWork() { return mWorkHandle != LLWorkerThread::nullHandle(); }
-
- // killWork(): aborts work and waits for the abort to process
- void killWork();
-
- // setPriority(): changes the priority of a request
- void setPriority(U32 priority);
-
private:
void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; }
void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; }
@@ -156,9 +165,11 @@ private:
protected:
LLWorkerThread* mWorkerThread;
std::string mWorkerClassName;
- handle_t mWorkHandle;
+ handle_t mRequestHandle;
+ U32 mRequestPriority; // last priority set
private:
+ LLMutex mMutex;
LLAtomicU32 mWorkFlags;
};
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index dc864aaf53..9b37cdade5 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -17,7 +17,7 @@
#include "llmath.h"
#include "stdtypes.h"
#include "v4coloru.h"
-#include "llmemory.h"
+#include "llmemtype.h"
#include "llimage.h"
#include "llimagebmp.h"
@@ -114,7 +114,7 @@ U8* LLImageBase::allocateData(S32 size)
llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
}
}
- else if ((size <= 0 || size > 4096*4096*16) && sSizeOverride == FALSE)
+ else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
{
llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
}
@@ -197,7 +197,8 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
: LLImageBase()
{
mMemType = LLMemType::MTYPE_IMAGERAW;
- copyData(data, width, height, components);
+ allocateDataSize(width, height, components);
+ memcpy(getData(), data, width*height*components);
++sRawImageCount;
}
@@ -239,20 +240,6 @@ void LLImageRaw::deleteData()
LLImageBase::deleteData();
}
-BOOL LLImageRaw::copyData(U8 *data, U16 width, U16 height, S8 components)
-{
- if (!resize(width, height, components))
- {
- return FALSE;
- }
- if (getData() == NULL || data == NULL)
- {
- return FALSE;
- }
- memcpy(getData(), data, width*height*components); /* Flawfinder: ignore */
- return TRUE;
-}
-
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@@ -1243,25 +1230,8 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
//static
S32 LLImageFormatted::sGlobalFormattedMemory = 0;
-//static
-LLWorkerThread* LLImageFormatted::sWorkerThread = NULL;
-
-//static
-void LLImageFormatted::initClass(bool threaded, bool run_always)
-{
- sWorkerThread = new LLWorkerThread(threaded, run_always);
-}
-
-//static
-void LLImageFormatted::cleanupClass()
-{
- delete sWorkerThread;
- sWorkerThread = NULL;
-}
-
-
LLImageFormatted::LLImageFormatted(S8 codec)
- : LLImageBase(), LLWorkerClass(sWorkerThread, "ImageFormatted"),
+ : LLImageBase(),
mCodec(codec),
mDecoding(0),
mDecoded(0),
@@ -1276,64 +1246,14 @@ LLImageFormatted::~LLImageFormatted()
// NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
// NOT LLImageFormatted::deleteData()
deleteData();
- releaseDecodedData();
-}
-
-//----------------------------------------------------------------------------
-
-//virtual
-void LLImageFormatted::startWork(S32 param)
-{
- if (mDecoding) llerrs << "WTF?" << llendl;
-}
-
-bool LLImageFormatted::doWork(S32 param)
-{
- if (!(isWorking())) llerrs << "WTF?" << llendl;
- llassert(mDecodedImage.notNull());
- if (param == 0)
- {
- // Decode primary channels
- mDecoded = decode(mDecodedImage, .001f); // 1ms
- }
- else
- {
- // Decode aux channel
- mDecoded = decode(mDecodedImage, .001f, param, param); // 1ms
- }
- if (mDecoded)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void LLImageFormatted::endWork(S32 param, bool aborted)
-{
- if (mDecoding) llerrs << "WTF?" << llendl;
- if (!mDecoded) llerrs << "WTF?" << llendl;
}
//----------------------------------------------------------------------------
// static
-LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
+LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
{
- LLString exten;
- size_t dotidx = instring.rfind('.');
- if (dotidx != LLString::npos)
- {
- exten = instring.substr(dotidx+1);
- }
- else
- {
- exten = instring;
- }
- S8 codec = get_codec(exten);
- LLPointer<LLImageFormatted> image;
+ LLImageFormatted* image;
switch(codec)
{
case IMG_CODEC_BMP:
@@ -1354,10 +1274,28 @@ LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring
image = new LLImageDXT();
break;
default:
+ image = NULL;
break;
}
return image;
}
+
+// static
+LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
+{
+ LLString exten;
+ size_t dotidx = instring.rfind('.');
+ if (dotidx != LLString::npos)
+ {
+ exten = instring.substr(dotidx+1);
+ }
+ else
+ {
+ exten = instring;
+ }
+ S8 codec = get_codec(exten);
+ return createFromType(codec);
+}
//----------------------------------------------------------------------------
// virtual
@@ -1374,15 +1312,6 @@ void LLImageFormatted::dump()
//----------------------------------------------------------------------------
-void LLImageFormatted::readHeader(U8* data, S32 size)
-{
- if (size <= 0)
- {
- size = calcHeaderSize();
- }
- copyData(data, size); // calls updateData()
-}
-
S32 LLImageFormatted::calcDataSize(S32 discard_level)
{
if (discard_level < 0)
@@ -1426,82 +1355,6 @@ BOOL LLImageFormatted::decode(LLImageRaw* raw_image,F32 decode_time, S32 first_
return decode( raw_image, decode_time ); // Loads first 4 channels by default.
}
-// virtual
-BOOL LLImageFormatted::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
-{
- llassert(getData() && getDataSize());
- // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
- if (discard >= 0 && discard != mDiscardLevel)
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- if (haveWork())
- {
- checkWork();
- }
- if (!mDecoded)
- {
- if (!haveWork())
- {
- llassert(!mDecoding);
- mDecodedImage = new LLImageRaw(getWidth(), getHeight(), getComponents());
- addWork(0);
- }
- return FALSE;
- }
- else
- {
- llassert(mDecodedImage.notNull());
- llassert(!mDecoding);
- raw = mDecodedImage;
- return TRUE;
- }
-}
-
-BOOL LLImageFormatted::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
- S32 discard, F32 decode_time)
-{
- llassert(getData() && getDataSize());
- // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
- if (discard >= 0 && discard != mDiscardLevel)
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- if (haveWork())
- {
- checkWork();
- }
- if (!mDecoded)
- {
- if (!haveWork())
- {
- llassert(!mDecoding);
- mDecodedImage = new LLImageRaw(getWidth(), getHeight(), 1);
- addWork(channel);
- }
- return FALSE;
- }
- else
- {
- llassert(mDecodedImage.notNull());
- llassert(!mDecoding);
- raw = mDecodedImage;
- return TRUE;
- }
-}
-
-
-// virtual
-void LLImageFormatted::releaseDecodedData()
-{
- if (mDecoded || mDecoding)
- {
- mDecodedImage = NULL; // deletes image
- mDecoded = FALSE;
- mDecoding = FALSE;
- }
-}
-
//----------------------------------------------------------------------------
// virtual
@@ -1549,52 +1402,42 @@ void LLImageFormatted::sanityCheck()
BOOL LLImageFormatted::copyData(U8 *data, S32 size)
{
- if (data && data != getData())
+ if ( (data && data != getData()) || (size != getDataSize()) )
{
deleteData();
allocateData(size);
memcpy(getData(), data, size); /* Flawfinder: ignore */
}
- updateData(); // virtual
-
return TRUE;
}
-BOOL LLImageFormatted::appendData(U8 *data, S32 size)
+// LLImageFormatted becomes the owner of data
+void LLImageFormatted::setData(U8 *data, S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
- S32 old_size = getDataSize();
- U8* old_data = getData();
- S32 new_size = old_size + size;
- U8* new_data = new U8[new_size];
- if (!new_data)
- {
- llerrs << "Out of memory in LLImageFormatted::appendData(U8 *data, S32 size)" << llendl;
- return FALSE;
- }
- // resize the image
- setDataAndSize(new_data, new_size);
- // copy the old data and delete it
- memcpy(new_data, old_data, old_size); /* Flawfinder: ignore */
- delete old_data;
- // if we have new data, copy it and call updateData()
- if (data)
+ if (data && data != getData())
{
- memcpy(new_data + old_size, data, size); /* Flawfinder: ignore */
- updateData(); // virtual
+ deleteData();
+ setDataAndSize(data, size); // Access private LLImageBase members
+ sGlobalFormattedMemory += getDataSize();
}
- return TRUE;
}
-BOOL LLImageFormatted::setData(U8 *data, S32 size)
+void LLImageFormatted::appendData(U8 *data, S32 size)
{
- if (data && data != getData())
+ if (data)
{
- deleteData();
- setDataAndSize(data, size); // Access private LLImageBase members
- sGlobalFormattedMemory += getDataSize();
+ if (!getData())
+ {
+ setData(data, size);
+ }
+ else
+ {
+ S32 cursize = getDataSize();
+ S32 newsize = cursize + size;
+ reallocateData(newsize);
+ memcpy(getData() + cursize, data, size);
+ }
}
- return updateData(); // virtual
}
//----------------------------------------------------------------------------
@@ -1667,8 +1510,6 @@ S8 LLImageFormatted::getCodec() const
//============================================================================
-//----------------------------------------------------------------------------
-
static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
{
dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
@@ -1794,3 +1635,5 @@ F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S3
return w_priority;
}
+
+//============================================================================
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 13ea916654..0e007c2c86 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -13,7 +13,7 @@
#include "lluuid.h"
#include "llstring.h"
#include "llmemory.h"
-#include "llworkerthread.h"
+#include "llthread.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
@@ -135,8 +135,6 @@ public:
/*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size);
- BOOL copyData(U8 *data, U16 width, U16 height, S8 components);
-
BOOL resize(U16 width, U16 height, S8 components);
U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
@@ -206,11 +204,10 @@ public:
// Compressed representation of image.
// Subclass from this class for the different representations (J2C, bmp)
-class LLImageFormatted : public LLImageBase, public LLWorkerClass
+class LLImageFormatted : public LLImageBase
{
public:
- static void initClass(bool threaded = true, bool run_always = true);
- static void cleanupClass();
+ static LLImageFormatted* createFromType(S8 codec);
static LLImageFormatted* createFromExtension(const LLString& instring);
protected:
@@ -228,22 +225,11 @@ public:
/*virtual*/ void dump();
/*virtual*/ void sanityCheck();
- // LLWorkerThread
-public:
- // called from WORKER THREAD, returns TRUE if done
- /*virtual*/ bool doWork(S32 param);
-private:
- // called from MAIN THREAD
- /*virtual*/ void startWork(S32 param); // called from addWork()
- /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
-
// New methods
public:
// calcHeaderSize() returns the maximum size of header;
// 0 indicates we don't know have a header and have to lead the entire file
virtual S32 calcHeaderSize() { return 0; };
- // readHeader() reads size bytes into mData, and sets width/height/ncomponents
- virtual void readHeader(U8* data, S32 size);
// calcDataSize() returns how many bytes to read to load discard_level (including header)
virtual S32 calcDataSize(S32 discard_level);
// calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
@@ -253,27 +239,16 @@ public:
BOOL load(const LLString& filename);
BOOL save(const LLString& filename);
-// BOOL save(LLVFS *vfs, const LLUUID &uuid, const LLAssetType::EType type);
-// Depricated to remove VFS dependency (see .cpp for replacement):
virtual BOOL updateData() = 0; // pure virtual
- BOOL copyData(U8 *data, S32 size); // calls updateData()
- BOOL setData(U8 *data, S32 size); // calls updateData()
- BOOL appendData(U8 *data, S32 size); // use if some data (e.g header) is already loaded, calls updateData()
+ void setData(U8 *data, S32 size);
+ void appendData(U8 *data, S32 size);
// Loads first 4 channels.
virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0) = 0;
// Subclasses that can handle more than 4 channels should override this function.
virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
- // Decode methods to return a pointer to raw data for purposes of passing to
- // opengl or such. This class tracks the decoded data and keeps it alive until
- // destroyed or releaseDecodedData() is called.
- virtual BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1, F32 decode_time=0.0);
- virtual BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
- S32 discard = -1, F32 decode_time=0.0);
- virtual void releaseDecodedData();
-
virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0) = 0;
S8 getCodec() const;
@@ -283,16 +258,16 @@ public:
S8 getDiscardLevel() const { return mDiscardLevel; }
protected:
+ BOOL copyData(U8 *data, S32 size); // calls updateData()
+
+protected:
S8 mCodec;
S8 mDecoding;
S8 mDecoded;
S8 mDiscardLevel;
- LLPointer<LLImageRaw> mDecodedImage;
-
public:
static S32 sGlobalFormattedMemory;
- static LLWorkerThread* sWorkerThread;
};
#endif
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index dfb5b957d3..1b6ce65274 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -265,8 +265,7 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
return TRUE;
}
-// virtual
-BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
+BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
{
if (discard < 0)
{
@@ -283,11 +282,6 @@ BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32
return TRUE;
}
-void LLImageDXT::releaseDecodedData()
-{
- // nothing to do
-}
-
BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
{
llassert_always(raw_image);
@@ -426,6 +420,7 @@ bool LLImageDXT::convertToDXR()
dxtfile_header_t* header = (dxtfile_header_t*)newdata;
header->pixel_fmt.fourcc = getFourCC(newformat);
setData(newdata, total_bytes);
+ updateData();
return true;
}
diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h
index 88d28a2958..e286d03e1e 100644
--- a/indra/llimage/llimagedxt.h
+++ b/indra/llimage/llimagedxt.h
@@ -82,12 +82,11 @@ public:
BOOL encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips);
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
- /*virtual*/ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard=-1, F32 decode_time=0.0);
- /*virtual*/ void releaseDecodedData();
-
/*virtual*/ S32 calcHeaderSize();
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
+ BOOL getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
+
void setFormat();
S32 getMipOffset(S32 discard);
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 32a8c60fac..398e7c9e32 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -11,7 +11,7 @@
#include "lldir.h"
#include "llimagej2c.h"
-#include "llmemory.h"
+#include "llmemtype.h"
typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -224,7 +224,22 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_chann
// Update the raw discard level
updateRawDiscardLevel();
- return mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ mDecoding = TRUE;
+ BOOL res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ if (res)
+ {
+ if (!mDecoding)
+ {
+ // Failed
+ raw_imagep->deleteData();
+ }
+ else
+ {
+ mDecoding = FALSE;
+ }
+ return TRUE; // done
+ }
+ return FALSE;
}
@@ -334,7 +349,7 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
U8 *data = new U8[file_size];
apr_size_t bytes_read = file_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
- if (s != APR_SUCCESS || bytes_read != file_size)
+ if (s != APR_SUCCESS || (S32)bytes_read != file_size)
{
delete[] data;
setLastError("Unable to read entire file");
@@ -349,9 +364,9 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
{
LLMemType mt1((LLMemType::EMemType)mMemType);
- // Taken from setData()
- BOOL res = LLImageFormatted::setData(data, file_size);
+ setData(data, file_size);
+ BOOL res = updateData();
if ( !res )
{
return FALSE;
@@ -367,10 +382,9 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
return mImpl->getMetadata(*this);
}
-void LLImageJ2C::setDecodingDone(BOOL complete)
+void LLImageJ2C::decodeFailed()
{
mDecoding = FALSE;
- mDecoded = complete;
}
void LLImageJ2C::updateRawDiscardLevel()
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 4a3b017a55..1181ae2bb8 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -53,7 +53,7 @@ protected:
friend class LLImageJ2CImpl;
friend class LLImageJ2COJ;
friend class LLImageJ2CKDU;
- void setDecodingDone(BOOL complete = TRUE);
+ void decodeFailed();
void updateRawDiscardLevel();
S32 mMaxBytes; // Maximum number of bytes of data to use...
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
new file mode 100644
index 0000000000..b44bf19227
--- /dev/null
+++ b/indra/llimage/llimageworker.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file llimage.cpp
+ * @brief Base class for images.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llimageworker.h"
+#include "llimagedxt.h"
+
+//----------------------------------------------------------------------------
+
+//static
+LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
+S32 LLImageWorker::sCount = 0;
+
+//static
+void LLImageWorker::initClass(LLWorkerThread* workerthread)
+{
+ sWorkerThread = workerthread;
+}
+
+//static
+void LLImageWorker::cleanupClass()
+{
+}
+
+//----------------------------------------------------------------------------
+
+LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder)
+ : LLWorkerClass(sWorkerThread, "Image"),
+ mFormattedImage(image),
+ mDecodedType(-1),
+ mDiscardLevel(discard),
+ mPriority(priority),
+ mResponder(responder)
+{
+ ++sCount;
+}
+
+LLImageWorker::~LLImageWorker()
+{
+ mDecodedImage = NULL;
+ mFormattedImage = NULL;
+ --sCount;
+}
+
+//----------------------------------------------------------------------------
+
+//virtual, main thread
+void LLImageWorker::startWork(S32 param)
+{
+ llassert_always(mDecodedImage.isNull());
+ mDecodedType = -1;
+}
+
+bool LLImageWorker::doWork(S32 param)
+{
+ bool decoded = false;
+ if(mDecodedImage.isNull())
+ {
+ if (!mFormattedImage->updateData())
+ {
+ mDecodedType = -2; // failed
+ return true;
+ }
+ if (mDiscardLevel >= 0)
+ {
+ mFormattedImage->setDiscardLevel(mDiscardLevel);
+ }
+ if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ {
+ decoded = true; // failed
+ }
+ else
+ {
+ S32 nc = param ? 1 : mFormattedImage->getComponents();
+ mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ nc);
+ }
+ }
+ if (!decoded)
+ {
+ if (param == 0)
+ {
+ // Decode primary channels
+ decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
+ }
+ else
+ {
+ // Decode aux channel
+ decoded = mFormattedImage->decode(mDecodedImage, .1f, param, param); // 1ms
+ }
+ }
+ if (decoded)
+ {
+ // Call the callback immediately; endWork doesn't get called until ckeckWork
+ if (mResponder.notNull())
+ {
+ bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
+ mResponder->completed(success);
+ }
+ }
+ return decoded;
+}
+
+void LLImageWorker::endWork(S32 param, bool aborted)
+{
+ if (mDecodedType != -2)
+ {
+ mDecodedType = aborted ? -2 : param;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+
+BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
+{
+ // For most codecs, only mDiscardLevel data is available.
+ // (see LLImageDXT for exception)
+ if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
+ {
+ llerrs << "Request for invalid discard level" << llendl;
+ }
+ checkWork();
+ if (mDecodedType == -2)
+ {
+ return TRUE; // aborted, done
+ }
+ if (mDecodedType != channel)
+ {
+ if (!haveWork())
+ {
+ addWork(channel, mPriority);
+ }
+ return FALSE;
+ }
+ else
+ {
+ llassert_always(!haveWork());
+ llassert_always(mDecodedType == channel);
+ raw = mDecodedImage; // smart pointer acquires ownership of data
+ mDecodedImage = NULL;
+ return TRUE;
+ }
+}
+
+BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
+{
+ if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
+ {
+ // special case
+ LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
+ return imagedxt->getMipData(raw, discard);
+ }
+ else
+ {
+ return requestDecodedAuxData(raw, 0, discard);
+ }
+}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
new file mode 100644
index 0000000000..cdd30417ce
--- /dev/null
+++ b/indra/llimage/llimageworker.h
@@ -0,0 +1,57 @@
+/**
+ * @file llimageworker.h
+ * @brief Object for managing images and their textures.
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLIMAGEWORKER_H
+#define LL_LLIMAGEWORKER_H
+
+#include "llimage.h"
+#include "llworkerthread.h"
+
+class LLImageWorker : public LLWorkerClass
+{
+public:
+ static void initClass(LLWorkerThread* workerthread);
+ static void cleanupClass();
+ static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
+
+ // LLWorkerThread
+public:
+ LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder = NULL);
+ ~LLImageWorker();
+
+ // called from WORKER THREAD, returns TRUE if done
+ /*virtual*/ bool doWork(S32 param);
+
+ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
+ BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
+ void releaseDecodedData();
+ void cancelDecode();
+
+private:
+ // called from MAIN THREAD
+ /*virtual*/ void startWork(S32 param); // called from addWork()
+ /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
+
+protected:
+ LLPointer<LLImageFormatted> mFormattedImage;
+ LLPointer<LLImageRaw> mDecodedImage;
+ S32 mDecodedType;
+ S32 mDiscardLevel;
+
+private:
+ U32 mPriority;
+ LLPointer<LLResponder> mResponder;
+
+protected:
+ static LLWorkerThread* sWorkerThread;
+
+public:
+ static S32 sCount;
+};
+
+#endif
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 823d2a8dd4..a6c7c623f3 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -151,7 +151,6 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
/* free image data structure */
opj_image_destroy(image);
- base.setDecodingDone();
return TRUE;
}
@@ -262,6 +261,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
codestream_length = cio_tell(cio);
base.copyData(cio->buffer, codestream_length);
+ base.updateData(); // set width, height
/* close and free the byte stream */
opj_cio_close(cio);
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 9f750c46b2..8a6fdfd0ad 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -13,6 +13,7 @@
#include "llassetstorage.h"
#include "lldarray.h"
+#include "llmemtype.h"
#include "llpermissions.h"
#include "llsaleinfo.h"
#include "llsd.h"
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index bea21e22c6..e5b2a5f312 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -21,6 +21,7 @@
#endif
#define LL_OCTREE_PARANOIA_CHECK 0
+#define LL_OCTREE_MAX_CAPACITY 256
template <class T> class LLOctreeState;
template <class T> class LLOctreeNode;
@@ -88,7 +89,8 @@ public:
virtual void removeByAddress(T* data) { getOctState()->removeByAddress(data); }
virtual bool hasLeafState() const { return getOctState()->isLeaf(); }
virtual void destroy() { getOctState()->destroy(); }
- virtual oct_node* getNodeAt(T* data) { return getOctState()->getNodeAt(data); }
+ virtual oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
+ virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); }
virtual U8 getOctant() const { return mOctant; }
virtual void setOctant(U8 octant) { mOctant = octant; }
virtual const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; }
@@ -117,9 +119,14 @@ public:
return ret;
}
+ virtual bool isInside(const LLVector3d& pos, const F64& rad) const
+ {
+ return rad <= mSize.mdV[0]*2.0 && isInside(pos);
+ }
+
virtual bool isInside(T* data) const
{
- return data->getBinRadius() <= mSize.mdV[0]*2.0 && isInside(data->getPositionGroup());
+ return isInside(data->getPositionGroup(), data->getBinRadius());
}
virtual bool isInside(const LLVector3d& pos) const
@@ -155,6 +162,11 @@ public:
bool contains(T* xform)
{
+ return contains(xform->getBinRadius());
+ }
+
+ bool contains(F64 radius)
+ {
if (mParent == NULL)
{ //root node contains nothing
return false;
@@ -162,7 +174,6 @@ public:
F64 size = mSize.mdV[0];
F64 p_size = size * 2.0;
- F64 radius = xform->getBinRadius();
return (radius <= 0.001 && size <= 0.001) ||
(radius <= p_size && radius > size);
@@ -247,11 +258,15 @@ public:
oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); }
virtual oct_node* getNodeAt(T* data)
+ {
+ return getNodeAt(data->getPositionGroup(), data->getBinRadius());
+ }
+
+ virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
{
- const LLVector3d& pos = data->getPositionGroup();
LLOctreeNode<T>* node = getOctNode();
- if (node->isInside(data))
+ if (node->isInside(pos, rad))
{
//do a quick search by octant
U8 octant = node->getOctant(pos.mdV);
@@ -261,7 +276,7 @@ public:
//at the appropriate octant or is smaller than the object.
//by definition, that node is the smallest node that contains
// the data
- while (keep_going && node->getSize().mdV[0] >= data->getBinRadius())
+ while (keep_going && node->getSize().mdV[0] >= rad)
{
keep_going = FALSE;
for (U32 i = 0; i < node->getChildCount() && !keep_going; i++)
@@ -275,9 +290,9 @@ public:
}
}
}
- else if (!node->contains(data) && node->getParent())
+ else if (!node->contains(rad) && node->getParent())
{ //if we got here, data does not exist in this node
- return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(data);
+ return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(pos, rad);
}
return node;
@@ -291,22 +306,15 @@ public:
return false;
}
LLOctreeNode<T>* node = getOctNode();
+ LLOctreeNode<T>* parent = node->getOctParent();
- if (data->getBinRadius() <= node->getSize().mdV[0])
- {
- oct_node* dest = getNodeAt(data);
-
- if (dest != node)
- {
- dest->insert(data);
- return false;
- }
- }
-
- //no kid found, is it even here?
- if (node->isInside(data))
+ //is it here?
+ if (node->isInside(data->getPositionGroup()))
{
- if (node->contains(data))
+ if (getElementCount() < LL_OCTREE_MAX_CAPACITY &&
+ (node->contains(data->getBinRadius()) ||
+ (data->getBinRadius() > node->getSize().mdV[0] &&
+ parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
{ //it belongs here
if (data == NULL)
{
@@ -327,7 +335,19 @@ public:
return true;
}
else
- {
+ {
+ //find a child to give it to
+ oct_node* child = NULL;
+ for (U32 i = 0; i < getChildCount(); i++)
+ {
+ child = getChild(i);
+ if (child->isInside(data->getPositionGroup()))
+ {
+ child->insert(data);
+ return false;
+ }
+ }
+
//it's here, but no kids are in the right place, make a new kid
LLVector3d center(node->getCenter());
LLVector3d size(node->getSize()*0.5);
@@ -359,7 +379,7 @@ public:
//make the new kid
LLOctreeState<T>* newstate = new LLOctreeState<T>();
- oct_node* child = new LLOctreeNode<T>(center, size, newstate, node);
+ child = new LLOctreeNode<T>(center, size, newstate, node);
addChild(child);
child->insert(data);
@@ -367,8 +387,15 @@ public:
}
else
{
- //it's not in here, give it to the parent
- node->getOctParent()->insert(data);
+ //it's not in here, give it to the root
+ LLOctreeNode<T>* parent = node->getOctParent();
+ while (parent)
+ {
+ node = parent;
+ parent = node->getOctParent();
+ }
+
+ node->insert(data);
}
return false;
diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h
index dd0c73c00c..cdc52cf90a 100644
--- a/indra/llmath/lltreenode.h
+++ b/indra/llmath/lltreenode.h
@@ -22,7 +22,6 @@ class LLTreeState
public:
LLTreeState(LLTreeNode<T>* node) { setNode(node); }
virtual ~LLTreeState() { };
-
virtual bool insert(T* data) = 0;
virtual bool remove(T* data) = 0;
virtual void setNode(LLTreeNode<T>* node);
@@ -35,7 +34,7 @@ private:
};
template <class T>
-class LLTreeListener
+class LLTreeListener: public LLRefCount
{
public:
virtual ~LLTreeListener() { };
@@ -75,7 +74,7 @@ protected:
LLTreeState<T>* mState;
public:
- std::vector<LLTreeListener<T>*> mListeners;
+ std::vector<LLPointer<LLTreeListener<T> > > mListeners;
};
template <class T>
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 75e4042f07..5354de783c 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1765,9 +1765,6 @@ void LLVolume::createVolumeFaces()
mVolumeFaces[i].create();
}
}
-
- mBounds[1] = LLVector3(0,0,0);
- mBounds[0] = LLVector3(512,512,512);
}
@@ -1812,21 +1809,28 @@ void LLVolumeParams::copyParams(const LLVolumeParams &params)
mPathParams.copyParams(params.mPathParams);
}
+// Less restricitve approx 0 for volumes
+const F32 APPROXIMATELY_ZERO = 0.001f;
+bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO)
+{
+ return (f >= -tolerance) && (f <= tolerance);
+}
+
// return true if in range (or nearly so)
-static bool limit_range(F32& v, F32 min, F32 max)
+static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO)
{
F32 min_delta = v - min;
if (min_delta < 0.f)
{
v = min;
- if (!is_approx_zero(min_delta))
+ if (!approx_zero(min_delta, tolerance))
return false;
}
F32 max_delta = max - v;
if (max_delta < 0.f)
{
v = max;
- if (!is_approx_zero(max_delta))
+ if (!approx_zero(max_delta, tolerance))
return false;
}
return true;
@@ -1841,9 +1845,10 @@ bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e)
valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA);
F32 end = e;
+ if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error
valid &= limit_range(end, MIN_CUT_DELTA, 1.f);
- valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA);
+ valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f);
// Now set them.
mProfileParams.setBegin(begin);
@@ -1863,7 +1868,7 @@ bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e)
F32 end = e;
valid &= limit_range(end, MIN_CUT_DELTA, 1.f);
- valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA);
+ valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f);
// Now set them.
mPathParams.setBegin(begin);
@@ -2020,7 +2025,7 @@ bool LLVolumeParams::setRadiusOffset(const F32 offset)
{
radius_offset = max_radius_mag;
}
- valid = is_approx_zero(delta);
+ valid = approx_zero(delta, .1f);
}
mPathParams.setRadiusOffset(radius_offset);
@@ -2054,7 +2059,7 @@ bool LLVolumeParams::setSkew(const F32 skew_value)
{
skew = min_skew_mag;
}
- valid = is_approx_zero(delta);
+ valid = approx_zero(delta);
}
mPathParams.setSkew(skew);
@@ -2980,10 +2985,15 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
S32 v2 = face.mIndices[j*3+((k+1)%3)];
vertices.push_back(face.mVertices[v1].mPosition*mat);
- normals.push_back(face.mVertices[v1].mNormal*norm_mat);
+ LLVector3 norm1 = face.mVertices[v1].mNormal * norm_mat;
+ norm1.normVec();
+ normals.push_back(norm1);
vertices.push_back(face.mVertices[v2].mPosition*mat);
- normals.push_back(face.mVertices[v2].mNormal*norm_mat);
+ LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat;
+ norm2.normVec();
+ normals.push_back(norm2);
+
segments.push_back(vertices.size());
}
}
@@ -3747,6 +3757,9 @@ BOOL LLVolumeFace::createUnCutCubeCap()
num_vertices = (grid_size+1)*(grid_size+1);
num_indices = quad_count * 4;
+ LLVector3& min = mExtents[0];
+ LLVector3& max = mExtents[1];
+
S32 offset = 0;
if (mTypeMask & TOP_MASK)
offset = (max_t-1) * max_s;
@@ -3786,32 +3799,6 @@ BOOL LLVolumeFace::createUnCutCubeCap()
}
S32 vtop = mVertices.size();
-// S32 itop = mIndices.size();
-/// vector_append(mVertices,4);
-// vector_append(mIndices,4);
-// LLVector3 new_pt = lerp(pt1, pt2, t_fraction);
-#if 0
- for(int t=0;t<4;t++){
- VertexData vd;
- vd.mPosition = corners[t].mPosition;
- vd.mNormal =
- ((corners[(t+1)%4].mPosition-corners[t].mPosition)%
- (corners[(t+2)%4].mPosition-corners[(t+1)%4].mPosition));
- vd.mNormal.normVec();
-
- if (mTypeMask & TOP_MASK)
- vd.mNormal *= -1.0f;
- vd.mBinormal = vd.mNormal;
- vd.mTexCoord = corners[t].mTexCoord;
- mVertices.push_back(vd);
- }
- int idxs[] = {0,1,2,2,3,0};
- if (mTypeMask & TOP_MASK){
- for(int i=0;i<6;i++)mIndices.push_back(vtop+idxs[i]);
- }else{
- for(int i=5;i>=0;i--)mIndices.push_back(vtop+idxs[i]);
- }
-#else
for(int gx = 0;gx<grid_size+1;gx++){
for(int gy = 0;gy<grid_size+1;gy++){
VertexData newVert;
@@ -3823,8 +3810,20 @@ BOOL LLVolumeFace::createUnCutCubeCap()
(F32)gx/(F32)grid_size,
(F32)gy/(F32)grid_size);
mVertices.push_back(newVert);
+
+ if (gx == 0 && gy == 0)
+ {
+ min = max = newVert.mPosition;
+ }
+ else
+ {
+ update_min_max(min,max,newVert.mPosition);
+ }
}
}
+
+ mCenter = (min + max) * 0.5f;
+
int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
for(int gx = 0;gx<grid_size;gx++){
for(int gy = 0;gy<grid_size;gy++){
@@ -3835,7 +3834,7 @@ BOOL LLVolumeFace::createUnCutCubeCap()
}
}
}
-#endif
+
return TRUE;
}
@@ -3882,12 +3881,15 @@ BOOL LLVolumeFace::createCap()
// Figure out the normal, assume all caps are flat faces.
// Cross product to get normals.
- LLVector2 cuv = LLVector2(0,0);
-
+ LLVector2 cuv;
+ LLVector2 min_uv, max_uv;
+
+ LLVector3& min = mExtents[0];
+ LLVector3& max = mExtents[1];
+
// Copy the vertices into the array
for (i = 0; i < num_vertices; i++)
{
-
if (mTypeMask & TOP_MASK)
{
mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f;
@@ -3900,17 +3902,22 @@ BOOL LLVolumeFace::createCap()
mVertices[i].mTexCoord.mV[1] = 0.5f - profile[i].mV[1];
}
- if(i){
- //Dont include the first point of the profile in the average
- cuv += mVertices[i].mTexCoord;
- mCenter += mVertices[i].mPosition = mesh[i + offset].mPos;
+ mVertices[i].mPosition = mesh[i + offset].mPos;
+
+ if (i == 0)
+ {
+ min = max = mVertices[i].mPosition;
+ min_uv = max_uv = mVertices[i].mTexCoord;
+ }
+ else
+ {
+ update_min_max(min,max, mVertices[i].mPosition);
+ update_min_max(min_uv, max_uv, mVertices[i].mTexCoord);
}
- else mVertices[i].mPosition = mesh[i + offset].mPos;
- //mVertices[i].mNormal = normal;
}
- mCenter /= (F32)(num_vertices-1);
- cuv /= (F32)(num_vertices-1);
+ mCenter = (min+max)*0.5f;
+ cuv = (min_uv + max_uv)*0.5f;
LLVector3 binormal = calc_binormal_from_triangle(
mCenter, cuv,
@@ -4215,13 +4222,11 @@ BOOL LLVolumeFace::createCap()
return TRUE;
}
-
BOOL LLVolumeFace::createSide()
{
BOOL flat = mTypeMask & FLAT_MASK;
S32 num_vertices, num_indices;
-
const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
const std::vector<LLPath::PathPt>& path_data = mVolumep->getPath().mPath;
@@ -4237,6 +4242,9 @@ BOOL LLVolumeFace::createSide()
vector_append(mIndices,num_indices);
vector_append(mEdge, num_indices);
+ LLVector3& face_min = mExtents[0];
+ LLVector3& face_max = mExtents[1];
+
mCenter.clearVec();
S32 begin_stex = llfloor( profile[mBeginS].mV[2] );
@@ -4284,17 +4292,26 @@ BOOL LLVolumeFace::createSide()
i = mBeginS + s + max_s*t;
}
- mCenter += mVertices[cur_vertex].mPosition = mesh[i].mPos;
+ mVertices[cur_vertex].mPosition = mesh[i].mPos;
mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
+ if (cur_vertex == 0)
+ {
+ face_min = face_max = mesh[i].mPos;
+ }
+ else
+ {
+ update_min_max(face_min, face_max, mesh[i].mPos);
+ }
+
cur_vertex++;
if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0)
{
- mCenter += mVertices[cur_vertex].mPosition = mesh[i].mPos;
+ mVertices[cur_vertex].mPosition = mesh[i].mPos;
mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
@@ -4316,15 +4333,19 @@ BOOL LLVolumeFace::createSide()
i = mBeginS + s + max_s*t;
ss = profile[mBeginS + s].mV[2] - begin_stex;
- mCenter += mVertices[cur_vertex].mPosition = mesh[i].mPos;
+ mVertices[cur_vertex].mPosition = mesh[i].mPos;
mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
+
+ update_min_max(face_min,face_max,mesh[i].mPos);
+
cur_vertex++;
}
}
- mCenter /= (F32)num_vertices;
+
+ mCenter = (face_min + face_max) * 0.5f;
S32 cur_index = 0;
S32 cur_edge = 0;
@@ -4448,32 +4469,14 @@ BOOL LLVolumeFace::createSide()
}
}
- //this loop would LOVE OpenMP
- LLVector3 min = mVolumep->mBounds[0] - mVolumep->mBounds[1];
- LLVector3 max = mVolumep->mBounds[0] + mVolumep->mBounds[1];
-
- if (min == max && min == LLVector3(512,512,512))
+ //normalize normals and binormals here so the meshes that reference
+ //this volume data don't have to
+ for (U32 i = 0; i < mVertices.size(); i++)
{
- min = max = mVertices[0].mPosition;
- }
-
- for (U32 i = 0; i < mVertices.size(); i++) {
mVertices[i].mNormal.normVec();
mVertices[i].mBinormal.normVec();
-
- for (U32 j = 0; j < 3; j++) {
- if (mVertices[i].mPosition.mV[j] > max.mV[j]) {
- max.mV[j] = mVertices[i].mPosition.mV[j];
- }
- if (mVertices[i].mPosition.mV[j] < min.mV[j]) {
- min.mV[j] = mVertices[i].mPosition.mV[j];
- }
- }
}
- mVolumep->mBounds[0] = (min + max) * 0.5f; //center
- mVolumep->mBounds[1] = (max - min) * 0.5f; //half-height
-
return TRUE;
}
@@ -4572,7 +4575,7 @@ LLVector3 calc_binormal_from_triangle(
-r0.mV[VZ] / r0.mV[VX],
-r1.mV[VZ] / r1.mV[VX],
-r2.mV[VZ] / r2.mV[VX]);
- //binormal.normVec();
+ // binormal.normVec();
return binormal;
}
else
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index cf9ae00f21..97aeeb9589 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -756,6 +756,8 @@ public:
S32 mNumS;
S32 mNumT;
+ LLVector3 mExtents[2]; //minimum and maximum point of face
+
std::vector<VertexData> mVertices;
std::vector<S32> mIndices;
std::vector<S32> mEdge;
@@ -849,7 +851,6 @@ public:
const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
U32 mFaceMask; // bit array of which faces exist in this volume
- LLVector3 mBounds[2]; // bounding box (center, half-height)
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
protected:
diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp
index 523acb4dcf..6483f2adbe 100644
--- a/indra/llmath/m3math.cpp
+++ b/indra/llmath/m3math.cpp
@@ -33,14 +33,14 @@
LLMatrix3::LLMatrix3(const LLQuaternion &q)
{
- *this = q.getMatrix3();
+ setRot(q);
}
LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec)
{
LLQuaternion quat(angle, vec);
- *this = setRot(quat);
+ setRot(quat);
}
LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec)
@@ -48,60 +48,25 @@ LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec)
LLVector3 vec_f;
vec_f.setVec(vec);
LLQuaternion quat(angle, vec_f);
- *this = setRot(quat);
+ setRot(quat);
}
LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
{
LLQuaternion quat(angle, vec);
- *this = setRot(quat);
+ setRot(quat);
}
LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
{
LLVector3 vec(x, y, z);
LLQuaternion quat(angle, vec);
- *this = setRot(quat);
+ setRot(quat);
}
LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
{
- // Rotates RH about x-axis by 'roll' then
- // rotates RH about the old y-axis by 'pitch' then
- // rotates RH about the original z-axis by 'yaw'.
- // .
- // /|\ yaw axis
- // | __.
- // ._ ___| /| pitch axis
- // _||\ \\ |-. /
- // \|| \_______\_|__\_/_______
- // | _ _ o o o_o_o_o o /_\_ ________\ roll axis
- // // /_______/ /__________> /
- // /_,-' // /
- // /__,-'
-
- F32 cx, sx, cy, sy, cz, sz;
- F32 cxsy, sxsy;
-
- cx = (F32)cos(roll); //A
- sx = (F32)sin(roll); //B
- cy = (F32)cos(pitch); //C
- sy = (F32)sin(pitch); //D
- cz = (F32)cos(yaw); //E
- sz = (F32)sin(yaw); //F
-
- cxsy = cx * sy; //AD
- sxsy = sx * sy; //BD
-
- mMatrix[0][0] = cy * cz;
- mMatrix[1][0] = -cy * sz;
- mMatrix[2][0] = sy;
- mMatrix[0][1] = sxsy * cz + cx * sz;
- mMatrix[1][1] = -sxsy * sz + cx * cz;
- mMatrix[2][1] = -sx * cy;
- mMatrix[0][2] = -cxsy * cz + sx * sz;
- mMatrix[1][2] = cxsy * sz + sx * cz;
- mMatrix[2][2] = cx * cy;
+ setRot(roll,pitch,yaw);
}
// From Matrix and Quaternion FAQ
@@ -288,34 +253,64 @@ LLQuaternion LLMatrix3::quaternion() const
// These functions take Rotation arguments
const LLMatrix3& LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
{
- LLMatrix3 mat(angle, x, y, z);
- *this = mat;
+ setRot(LLQuaternion(angle,x,y,z));
return *this;
}
const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
{
- LLMatrix3 mat(angle, vec);
- *this = mat;
+ setRot(LLQuaternion(angle, vec));
return *this;
}
const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw)
{
- LLMatrix3 mat(roll, pitch, yaw);
- *this = mat;
+ // Rotates RH about x-axis by 'roll' then
+ // rotates RH about the old y-axis by 'pitch' then
+ // rotates RH about the original z-axis by 'yaw'.
+ // .
+ // /|\ yaw axis
+ // | __.
+ // ._ ___| /| pitch axis
+ // _||\ \\ |-. /
+ // \|| \_______\_|__\_/_______
+ // | _ _ o o o_o_o_o o /_\_ ________\ roll axis
+ // // /_______/ /__________> /
+ // /_,-' // /
+ // /__,-'
+
+ F32 cx, sx, cy, sy, cz, sz;
+ F32 cxsy, sxsy;
+
+ cx = (F32)cos(roll); //A
+ sx = (F32)sin(roll); //B
+ cy = (F32)cos(pitch); //C
+ sy = (F32)sin(pitch); //D
+ cz = (F32)cos(yaw); //E
+ sz = (F32)sin(yaw); //F
+
+ cxsy = cx * sy; //AD
+ sxsy = sx * sy; //BD
+
+ mMatrix[0][0] = cy * cz;
+ mMatrix[1][0] = -cy * sz;
+ mMatrix[2][0] = sy;
+ mMatrix[0][1] = sxsy * cz + cx * sz;
+ mMatrix[1][1] = -sxsy * sz + cx * cz;
+ mMatrix[2][1] = -sx * cy;
+ mMatrix[0][2] = -cxsy * cz + sx * sz;
+ mMatrix[1][2] = cxsy * sz + sx * cz;
+ mMatrix[2][2] = cx * cy;
return *this;
}
const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q)
{
- LLMatrix3 mat(q);
- *this = mat;
+ *this = q.getMatrix3();
return *this;
}
-
const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up)
{
mMatrix[0][0] = fwd.mV[0];
diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h
index ac93ed86fb..c3798fca73 100644
--- a/indra/llmath/m3math.h
+++ b/indra/llmath/m3math.h
@@ -32,9 +32,6 @@ class LLQuaternion;
static const U32 NUM_VALUES_IN_MAT3 = 3;
-#if LL_WINDOWS
-__declspec( align(16) )
-#endif
class LLMatrix3
{
public:
@@ -119,11 +116,7 @@ class LLMatrix3
friend const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b); // Return a * b
friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a
-}
-#if LL_DARWIN
-__attribute__ ((aligned (16)))
-#endif
-;
+};
inline LLMatrix3::LLMatrix3(void)
{
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index 4f26d875ff..69463d7718 100644
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -73,9 +73,6 @@ class LLQuaternion;
static const U32 NUM_VALUES_IN_MAT4 = 4;
-#if LL_WINDOWS
-__declspec(align(16))
-#endif
class LLMatrix4
{
public:
@@ -218,11 +215,7 @@ public:
friend const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b); // Return a * b
friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a
-}
-#if LL_DARWIN
-__attribute__ ((aligned (16)))
-#endif
-;
+};
inline LLMatrix4::LLMatrix4()
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index c94333e2a9..863318551e 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -298,6 +298,21 @@ inline LLVector2 operator-(const LLVector2 &a)
return LLVector2( -a.mV[0], -a.mV[1] );
}
+inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos)
+{
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (min.mV[i] > pos.mV[i])
+ {
+ min.mV[i] = pos.mV[i];
+ }
+ if (max.mV[i] < pos.mV[i])
+ {
+ max.mV[i] = pos.mV[i];
+ }
+ }
+}
+
inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }";
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 9e6084565e..c68e72bb97 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -118,7 +118,7 @@ const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec)
{
if ( !vec.isExactlyZero() && angle )
{
- *this = *this * LLMatrix3(angle, vec);
+ *this = *this * LLQuaternion(angle, vec);
}
return *this;
}
@@ -128,7 +128,7 @@ const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
LLVector3 vec(x, y, z);
if ( !vec.isExactlyZero() && angle )
{
- *this = *this * LLMatrix3(angle, vec);
+ *this = *this * LLQuaternion(angle, vec);
}
return *this;
}
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index 72372c07e9..f787fa2ac1 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -396,6 +396,20 @@ inline BOOL LLVector3::isNull() const
return FALSE;
}
+inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
+{
+ for (U32 i = 0; i < 3; i++)
+ {
+ if (min.mV[i] > pos.mV[i])
+ {
+ min.mV[i] = pos.mV[i];
+ }
+ if (max.mV[i] < pos.mV[i])
+ {
+ max.mV[i] = pos.mV[i];
+ }
+ }
+}
inline F32 angle_between(const LLVector3& a, const LLVector3& b)
{
diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h
index abdc66e0b1..e9b8d5b71f 100644
--- a/indra/llmath/v4math.h
+++ b/indra/llmath/v4math.h
@@ -21,10 +21,6 @@ class LLQuaternion;
static const U32 LENGTHOFVECTOR4 = 4;
-#if LL_WINDOWS
-__declspec( align(16) )
-#endif
-
class LLVector4
{
public:
@@ -95,12 +91,7 @@ class LLVector4
friend const LLVector4& operator/=(LLVector4 &a, F32 k); // Return a divided by scaler k
friend LLVector4 operator-(const LLVector4 &a); // Return vector -a
-}
-#if LL_DARWIN
-__attribute__ ((aligned (16)))
-#endif
-;
-
+};
// Non-member functions
F32 angle_between(const LLVector4 &a, const LLVector4 &b); // Returns angle (radians) between a and b
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
new file mode 100644
index 0000000000..886697ed41
--- /dev/null
+++ b/indra/llmessage/llcurl.cpp
@@ -0,0 +1,343 @@
+/*
+ * llcurl.cpp
+ * MacTester
+ *
+ * Created by Zero Linden on 10/15/06.
+ * Copyright 2006 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "llcurl.h"
+
+#include <iomanip>
+
+#include "llsdserialize.h"
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ The trick to getting curl to do keep-alives is to reuse the
+ same easy handle for the requests. It appears that curl
+ keeps a pool of connections alive for each easy handle, but
+ doesn't share them between easy handles. Therefore it is
+ important to keep a pool of easy handles and reuse them,
+ rather than create and destroy them with each request. This
+ code does this.
+
+ Furthermore, it would behoove us to keep track of which
+ hosts an easy handle was used for and pick an easy handle
+ that matches the next request. This code does not current
+ do this.
+ */
+
+using namespace std;
+
+LLCurl::Responder::Responder()
+ : mReferenceCount(0)
+{
+}
+LLCurl::Responder::~Responder()
+{
+}
+
+// virtual
+void LLCurl::Responder::error(U32 status, const std::stringstream& content)
+{
+ llinfos << "LLCurl::Responder::error " << status << ": " << content.str() << llendl;
+}
+
+// virtual
+void LLCurl::Responder::result(const std::stringstream& content)
+{
+}
+
+// virtual
+void LLCurl::Responder::completed(U32 status, const std::stringstream& content)
+{
+ if (200 <= status && status < 300)
+ {
+ result(content);
+ }
+ else
+ {
+ error(status, content);
+ }
+}
+
+
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLCurl::Responder* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLCurl::Responder* p)
+ {
+ if(0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+size_t
+curlOutputCallback(void* data, size_t size, size_t nmemb, void* user_data)
+{
+ stringstream& output = *(stringstream*)user_data;
+
+ size_t n = size * nmemb;
+ output.write((const char*)data, n);
+ if (!((istream&)output).good()) {
+ std::cerr << "WHAT!?!?!? istream side bad" << std::endl;
+ }
+ if (!((ostream&)output).good()) {
+ std::cerr << "WHAT!?!?!? ostream side bad" << std::endl;
+ }
+
+ return n;
+}
+
+// Only used if request contained a body (post or put), Not currently implemented.
+// size_t
+// curlRequestCallback(void* data, size_t size, size_t nmemb, void* user_data)
+// {
+// stringstream& request = *(stringstream*)user_data;
+
+// size_t n = size * nmemb;
+// request.read((char*)data, n);
+// return request.gcount();
+// }
+
+
+
+
+
+LLCurl::Easy::Easy()
+{
+ mHeaders = 0;
+ mHeaders = curl_slist_append(mHeaders, "Connection: keep-alive");
+ mHeaders = curl_slist_append(mHeaders, "Keep-alive: 300");
+ mHeaders = curl_slist_append(mHeaders, "Content-Type: application/xml");
+ // FIXME: shouldn't be there for GET/DELETE
+ // FIXME: should have ACCEPT headers
+
+ mHandle = curl_easy_init();
+}
+
+LLCurl::Easy::~Easy()
+{
+ curl_easy_cleanup(mHandle);
+ curl_slist_free_all(mHeaders);
+}
+
+void
+LLCurl::Easy::get(const string& url, ResponderPtr responder)
+{
+ prep(url, responder);
+ curl_easy_setopt(mHandle, CURLOPT_HTTPGET, 1);
+}
+
+void
+LLCurl::Easy::getByteRange(const string& url, S32 offset, S32 length, ResponderPtr responder)
+{
+ mRange = llformat("Range: bytes=%d-%d", offset,offset+length-1);
+ mHeaders = curl_slist_append(mHeaders, mRange.c_str());
+ prep(url, responder);
+ curl_easy_setopt(mHandle, CURLOPT_HTTPGET, 1);
+}
+
+void
+LLCurl::Easy::perform()
+{
+ report(curl_easy_perform(mHandle));
+}
+
+void
+LLCurl::Easy::prep(const std::string& url, ResponderPtr responder)
+{
+#if !LL_DARWIN
+ curl_easy_reset(mHandle); // SJB: doesn't exisit on OSX 10.3.9
+#else
+ // SJB: equivalent? fast?
+ curl_easy_cleanup(mHandle);
+ mHandle = curl_easy_init();
+#endif
+
+ curl_easy_setopt(mHandle, CURLOPT_PRIVATE, this);
+
+// curl_easy_setopt(mHandle, CURLOPT_VERBOSE, 1); // usefull for debugging
+ curl_easy_setopt(mHandle, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(mHandle, CURLOPT_WRITEFUNCTION, &curlOutputCallback);
+ curl_easy_setopt(mHandle, CURLOPT_WRITEDATA, &mOutput);
+#if 1 // For debug
+ curl_easy_setopt(mHandle, CURLOPT_HEADERFUNCTION, &curlOutputCallback);
+ curl_easy_setopt(mHandle, CURLOPT_HEADERDATA, &mHeaderOutput);
+#endif
+ curl_easy_setopt(mHandle, CURLOPT_ERRORBUFFER, &mErrorBuffer);
+ curl_easy_setopt(mHandle, CURLOPT_ENCODING, "");
+ curl_easy_setopt(mHandle, CURLOPT_SSL_VERIFYPEER, false);
+ curl_easy_setopt(mHandle, CURLOPT_HTTPHEADER, mHeaders);
+
+ mOutput.str("");
+ if (!((istream&)mOutput).good()) {
+ std::cerr << "WHAT!?!?!? istream side bad" << std::endl;
+ }
+ if (!((ostream&)mOutput).good()) {
+ std::cerr << "WHAT!?!?!? ostream side bad" << std::endl;
+ }
+
+ mURL = url;
+ curl_easy_setopt(mHandle, CURLOPT_URL, mURL.c_str());
+
+ mResponder = responder;
+}
+
+void
+LLCurl::Easy::report(CURLcode code)
+{
+ if (!mResponder) return;
+
+ long responseCode;
+
+ if (code == CURLE_OK)
+ {
+ curl_easy_getinfo(mHandle, CURLINFO_RESPONSE_CODE, &responseCode);
+ }
+ else
+ {
+ responseCode = 499;
+ }
+
+ mResponder->completed(responseCode, mOutput);
+ mResponder = NULL;
+}
+
+
+
+
+
+
+LLCurl::Multi::Multi()
+{
+ mHandle = curl_multi_init();
+}
+
+LLCurl::Multi::~Multi()
+{
+ // FIXME: should clean up excess handles in mFreeEasy
+ curl_multi_cleanup(mHandle);
+}
+
+
+void
+LLCurl::Multi::get(const std::string& url, ResponderPtr responder)
+{
+ LLCurl::Easy* easy = easyAlloc();
+ easy->get(url, responder);
+ curl_multi_add_handle(mHandle, easy->mHandle);
+}
+
+void
+LLCurl::Multi::getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder)
+{
+ LLCurl::Easy* easy = easyAlloc();
+ easy->getByteRange(url, offset, length, responder);
+ curl_multi_add_handle(mHandle, easy->mHandle);
+}
+
+void
+LLCurl::Multi::process()
+{
+ int count;
+ for (int call_count = 0; call_count < 5; call_count += 1)
+ {
+ if (CURLM_CALL_MULTI_PERFORM != curl_multi_perform(mHandle, &count))
+ {
+ break;
+ }
+ }
+
+ CURLMsg* msg;
+ int msgs_in_queue;
+ while ((msg = curl_multi_info_read(mHandle, &msgs_in_queue)))
+ {
+ if (msg->msg != CURLMSG_DONE) continue;
+ Easy* easy = 0;
+ curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &easy);
+ if (!easy) continue;
+ easy->report(msg->data.result);
+
+ curl_multi_remove_handle(mHandle, easy->mHandle);
+ easyFree(easy);
+ }
+}
+
+
+
+LLCurl::Easy*
+LLCurl::Multi::easyAlloc()
+{
+ Easy* easy = 0;
+
+ if (mFreeEasy.empty())
+ {
+ easy = new Easy();
+ }
+ else
+ {
+ easy = mFreeEasy.back();
+ mFreeEasy.pop_back();
+ }
+
+ return easy;
+}
+
+void
+LLCurl::Multi::easyFree(Easy* easy)
+{
+ if (mFreeEasy.size() < 5)
+ {
+ mFreeEasy.push_back(easy);
+ }
+ else
+ {
+ delete easy;
+ }
+}
+
+
+
+namespace
+{
+ static LLCurl::Multi* sMainMulti = 0;
+
+ LLCurl::Multi*
+ mainMulti()
+ {
+ if (!sMainMulti) {
+ sMainMulti = new LLCurl::Multi();
+ }
+ return sMainMulti;
+ }
+}
+
+void
+LLCurl::get(const std::string& url, ResponderPtr responder)
+{
+ mainMulti()->get(url, responder);
+}
+
+void
+LLCurl::getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder)
+{
+ mainMulti()->getByteRange(url, offset, length, responder);
+}
+
+void
+LLCurl::process()
+{
+ mainMulti()->process();
+}
+
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
new file mode 100644
index 0000000000..4f1b5e6031
--- /dev/null
+++ b/indra/llmessage/llcurl.h
@@ -0,0 +1,118 @@
+/*
+ * llcurl.h
+ * MacTester
+ *
+ * Created by Zero Linden on 10/15/06.
+ * Copyright 2006 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef LL_LLCURL_H
+#define LL_LLCURL_H
+
+#include "linden_common.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/intrusive_ptr.hpp>
+#include <curl/curl.h>
+
+// #include "llhttpclient.h"
+
+class LLCurl
+{
+public:
+ class Multi;
+
+ class Responder
+ {
+ public:
+ Responder();
+ virtual ~Responder();
+
+ virtual void error(U32 status, const std::stringstream& content); // called with bad status codes
+
+ virtual void result(const std::stringstream& content);
+
+ virtual void completed(U32 status, const std::stringstream& content);
+ /**< The default implemetnation calls
+ either:
+ * result(), or
+ * error()
+ */
+
+ public: /* but not really -- don't touch this */
+ U32 mReferenceCount;
+ };
+ typedef boost::intrusive_ptr<Responder> ResponderPtr;
+
+ class Easy
+ {
+ public:
+ Easy();
+ ~Easy();
+
+ void get(const std::string& url, ResponderPtr);
+ void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr);
+
+ void perform();
+
+ private:
+ void prep(const std::string& url, ResponderPtr);
+ void report(CURLcode);
+
+ CURL* mHandle;
+ struct curl_slist* mHeaders;
+
+ std::string mURL;
+ std::string mRange;
+ std::stringstream mRequest;
+
+ std::stringstream mOutput;
+ char mErrorBuffer[CURL_ERROR_SIZE];
+
+ std::stringstream mHeaderOutput; // Debug
+
+ ResponderPtr mResponder;
+
+ friend class Multi;
+ };
+
+
+ class Multi
+ {
+ public:
+ Multi();
+ ~Multi();
+
+ void get(const std::string& url, ResponderPtr);
+ void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr);
+
+ void process();
+
+ private:
+ Easy* easyAlloc();
+ void easyFree(Easy*);
+
+ CURLM* mHandle;
+
+ typedef std::vector<Easy*> EasyList;
+ EasyList mFreeEasy;
+ };
+
+
+ static void get(const std::string& url, ResponderPtr);
+ static void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder);
+
+ static void process();
+};
+
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLCurl::Responder* p);
+ void intrusive_ptr_release(LLCurl::Responder* p);
+};
+
+#endif // LL_LLCURL_H
diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp
index 4ce7bc1fcd..6fc2af2cb2 100644
--- a/indra/llmessage/llpartdata.cpp
+++ b/indra/llmessage/llpartdata.cpp
@@ -212,6 +212,20 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)
return TRUE;
}
+std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
+{
+ s << "Flags: " << std::hex << data.mFlags;
+ s << " Pattern: " << std::hex << (U32) data.mPattern << "\n";
+ s << "Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
+ s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
+ s << "Burst Rate: " << data.mBurstRate << "\n";
+ s << "Burst Radius: " << data.mBurstRadius << "\n";
+ s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
+ s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
+ s << "Angular Velocity: " << data.mAngularVelocity << "\n";
+ s << "Accel: " << data.mPartAccel;
+ return s;
+}
BOOL LLPartSysData::isNullPS(const S32 block_num)
{
diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h
index ba3bdaf9b6..662d635a08 100644
--- a/indra/llmessage/llpartdata.h
+++ b/indra/llmessage/llpartdata.h
@@ -167,6 +167,9 @@ public:
// a combination of multiple parameters, we
// need to clamp it using a separate method instead of an accessor.
void clampSourceParticleRate();
+
+ friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a
+
public:
// Public because I'm lazy....
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 5abc63fad0..320719072c 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -868,7 +868,7 @@ void LLPumpIO::processChain(LLChainInfo& chain)
PUMP_DEBUG;
if(LLIOPipe::isError(status))
{
- llinfos << "Pump generated pipe error: '"
+ llinfos << "Pump generated pipe err: '"
#if LL_DEBUG_PIPE_TYPE_IN_PUMP
<< typeid(*((*it).mPipe)).name() << "':'"
#endif
diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp
index 4eea7418af..bddd79367a 100644
--- a/indra/llmessage/lltransfermanager.cpp
+++ b/indra/llmessage/lltransfermanager.cpp
@@ -335,7 +335,7 @@ void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
{
// Perhaps this stuff should be inside a method in LLTransferPacket?
// I'm too lazy to do it now, though.
- llinfos << "Playing back delayed packet " << packet_id << llendl;
+// llinfos << "Playing back delayed packet " << packet_id << llendl;
LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
// This is somewhat inefficient, but avoids us having to duplicate
@@ -455,6 +455,8 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
ttcp->deleteTransfer(ttp);
return;
}
+#if 0
+ // Spammy!
const S32 LL_TRANSFER_WARN_GAP = 10;
if(!ttp->gotInfo())
{
@@ -468,6 +470,7 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
<< " from " << msgp->getSender() << ", got " << packet_id
<< " expecting " << ttp->getNextPacketID() << llendl;
}
+#endif
return;
}
@@ -508,7 +511,7 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
{
// Perhaps this stuff should be inside a method in LLTransferPacket?
// I'm too lazy to do it now, though.
- llinfos << "Playing back delayed packet " << packet_id << llendl;
+// llinfos << "Playing back delayed packet " << packet_id << llendl;
LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
// This is somewhat inefficient, but avoids us having to duplicate
diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp
index b8c138886a..6714185d3f 100644
--- a/indra/llmessage/lltransfertargetvfile.cpp
+++ b/indra/llmessage/lltransfertargetvfile.cpp
@@ -15,33 +15,8 @@
#include "llvfile.h"
//static
-std::list<LLTransferTargetParamsVFile*> LLTransferTargetVFile::sCallbackQueue;
-
-//static
void LLTransferTargetVFile::updateQueue(bool shutdown)
{
- for(std::list<LLTransferTargetParamsVFile*>::iterator iter = sCallbackQueue.begin();
- iter != sCallbackQueue.end(); )
- {
- std::list<LLTransferTargetParamsVFile*>::iterator curiter = iter++;
- LLTransferTargetParamsVFile* params = *curiter;
- LLVFSThread::status_t s = LLVFile::getVFSThread()->getRequestStatus(params->mHandle);
- if (s == LLVFSThread::STATUS_COMPLETE || s == LLVFSThread::STATUS_EXPIRED)
- {
- params->mCompleteCallback(
- params->mErrCode,
- params->getAssetID(),
- params->getAssetType(),
- params->mUserDatap);
- delete params;
- iter = sCallbackQueue.erase(curiter);
- }
- else if (shutdown)
- {
- delete params;
- iter = sCallbackQueue.erase(curiter);
- }
- }
}
@@ -50,8 +25,7 @@ LLTransferTargetParamsVFile::LLTransferTargetParamsVFile() :
mAssetType(LLAssetType::AT_NONE),
mCompleteCallback(NULL),
mUserDatap(NULL),
- mErrCode(0),
- mHandle(LLVFSThread::nullHandle())
+ mErrCode(0)
{
}
@@ -166,7 +140,6 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
llwarns << "Aborting vfile transfer after asset storage shut down!" << llendl;
return;
}
- LLVFSThread::handle_t handle = LLVFSThread::nullHandle();
// Still need to gracefully handle error conditions.
S32 err_code = 0;
@@ -175,11 +148,11 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
case LLTS_DONE:
if (!mNeedsCreate)
{
- handle = LLVFile::getVFSThread()->rename(
- gAssetStorage->mVFS,
- mTempID, mParams.getAssetType(),
- mParams.getAssetID(), mParams.getAssetType(),
- LLVFSThread::AUTO_DELETE);
+ LLVFile file(gAssetStorage->mVFS, mTempID, mParams.getAssetType(), LLVFile::WRITE);
+ if (!file.rename(mParams.getAssetID(), mParams.getAssetType()))
+ {
+ llerrs << "LLTransferTargetVFile: rename failed" << llendl;
+ }
}
err_code = LL_ERR_NOERR;
lldebugs << "LLTransferTargetVFile::completionCallback for "
@@ -219,20 +192,9 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
}
if (mParams.mCompleteCallback)
{
- if (handle != LLVFSThread::nullHandle())
- {
- LLTransferTargetParamsVFile* params = new LLTransferTargetParamsVFile(mParams);
- params->mErrCode = err_code;
- params->mHandle = handle;
- sCallbackQueue.push_back(params);
- }
- else
- {
- mParams.mCompleteCallback(
- err_code,
- mParams.getAssetID(),
- mParams.getAssetType(),
- mParams.mUserDatap);
- }
+ mParams.mCompleteCallback(err_code,
+ mParams.getAssetID(),
+ mParams.getAssetType(),
+ mParams.mUserDatap);
}
}
diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h
index 57eaeca378..e9d5fa0c00 100644
--- a/indra/llmessage/lltransfertargetvfile.h
+++ b/indra/llmessage/lltransfertargetvfile.h
@@ -71,8 +71,6 @@ protected:
BOOL mNeedsCreate;
LLUUID mTempID;
-
- static std::list<LLTransferTargetParamsVFile*> sCallbackQueue;
};
#endif // LL_LLTRANSFERTARGETFILE_H
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 48d950e377..3f9dfa08d6 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -421,6 +421,7 @@ public:
void addStringFast( const char* varname, const std::string& s); // typed, checks storage space
void addString( const char* varname, const std::string& s); // typed, checks storage space
+ TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; }
S32 getCurrentSendTotal() const { return mCurrentSendTotal; }
// This method checks for current send total and returns true if
diff --git a/indra/llprimitive/llvolumemessage.cpp b/indra/llprimitive/llvolumemessage.cpp
index d2f1e12526..a43aa19cab 100644
--- a/indra/llprimitive/llvolumemessage.cpp
+++ b/indra/llprimitive/llvolumemessage.cpp
@@ -429,41 +429,36 @@ bool LLVolumeMessage::unpackPathParams(LLPathParams* params, LLDataPacker &dp)
// static
bool LLVolumeMessage::constrainVolumeParams(LLVolumeParams& params)
{
- bool ok = true;
+ U32 bad = 0;
// This is called immediately after an unpack. feed the raw data
// through the checked setters to constraint it to a valid set of
// volume params.
- ok &= params.setType(
- params.getProfileParams().getCurveType(),
- params.getPathParams().getCurveType());
- ok &= params.setBeginAndEndS(
- params.getProfileParams().getBegin(),
- params.getProfileParams().getEnd());
- ok &= params.setBeginAndEndT(
- params.getPathParams().getBegin(),
- params.getPathParams().getEnd());
- ok &= params.setHollow(params.getProfileParams().getHollow());
- ok &= params.setTwistBegin(params.getPathParams().getTwistBegin());
- ok &= params.setTwistEnd(params.getPathParams().getTwistEnd());
- ok &= params.setRatio(
- params.getPathParams().getScaleX(),
- params.getPathParams().getScaleY());
- ok &= params.setShear(
- params.getPathParams().getShearX(),
- params.getPathParams().getShearY());
- ok &= params.setTaper(
- params.getPathParams().getTaperX(),
- params.getPathParams().getTaperY());
- ok &= params.setRevolutions(params.getPathParams().getRevolutions());
- ok &= params.setRadiusOffset(params.getPathParams().getRadiusOffset());
- ok &= params.setSkew(params.getPathParams().getSkew());
- if(!ok)
+ bad |= params.setType(params.getProfileParams().getCurveType(),
+ params.getPathParams().getCurveType()) ? 0 : 1;
+ bad |= params.setBeginAndEndS(params.getProfileParams().getBegin(),
+ params.getProfileParams().getEnd()) ? 0 : 2;
+ bad |= params.setBeginAndEndT(params.getPathParams().getBegin(),
+ params.getPathParams().getEnd()) ? 0 : 4;
+ bad |= params.setHollow(params.getProfileParams().getHollow()) ? 0 : 8;
+ bad |= params.setTwistBegin(params.getPathParams().getTwistBegin()) ? 0 : 0x10;
+ bad |= params.setTwistEnd(params.getPathParams().getTwistEnd()) ? 0 : 0x20;
+ bad |= params.setRatio(params.getPathParams().getScaleX(),
+ params.getPathParams().getScaleY()) ? 0 : 0x40;
+ bad |= params.setShear(params.getPathParams().getShearX(),
+ params.getPathParams().getShearY()) ? 0 : 0x80;
+ bad |= params.setTaper(params.getPathParams().getTaperX(),
+ params.getPathParams().getTaperY()) ? 0 : 0x100;
+ bad |= params.setRevolutions(params.getPathParams().getRevolutions()) ? 0 : 0x200;
+ bad |= params.setRadiusOffset(params.getPathParams().getRadiusOffset()) ? 0 : 0x400;
+ bad |= params.setSkew(params.getPathParams().getSkew()) ? 0 : 0x800;
+ if(bad)
{
llwarns << "LLVolumeMessage::constrainVolumeParams() - "
- << "forced to constrain incoming volume params." << llendl;
+ << "forced to constrain incoming volume params: "
+ << llformat("0x%04x",bad) << llendl;
}
- return ok;
+ return bad ? false : true;
}
bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLMessageSystem *mesgsys)
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index f42122b0ee..1fc040c7d6 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -14,6 +14,7 @@
#include "llfontgl.h"
#include "llgl.h"
#include "v4color.h"
+#include "llstl.h"
const S32 BOLD_OFFSET = 1;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index b4edd3d365..9c1178b9f7 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -115,6 +115,15 @@ void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
sCurrentBoundTextures[stage] = 0;
}
+// static (duplicated for speed and to avoid GL_TEXTURE_2D default argument which requires GL header dependency)
+void LLImageGL::unbindTexture(S32 stage)
+{
+ glActiveTextureARB(GL_TEXTURE0_ARB + stage);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ sCurrentBoundTextures[stage] = 0;
+}
+
// static
void LLImageGL::updateStats(F32 current_time)
{
@@ -371,13 +380,8 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
llwarns << "Trying to bind a texture while GL is disabled!" << llendl;
}
- stop_glerror();
-
glActiveTextureARB(GL_TEXTURE0_ARB + stage);
- //glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
-
- stop_glerror();
-
+
if (sCurrentBoundTextures[stage] && sCurrentBoundTextures[stage] == mTexName)
{
// already set!
@@ -392,7 +396,6 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
glBindTexture(mBindTarget, mTexName);
sCurrentBoundTextures[stage] = mTexName;
- stop_glerror();
if (mLastBindTime != sLastFrameTime)
{
@@ -631,6 +634,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
mHasMipMaps = FALSE;
}
+ glFlush();
stop_glerror();
}
@@ -645,6 +649,11 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
llwarns << "Setting subimage on image without GL texture" << llendl;
return FALSE;
}
+ if (datap == NULL)
+ {
+ llwarns << "Setting subimage on image with NULL datap" << llendl;
+ return FALSE;
+ }
if (x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight())
{
@@ -657,7 +666,9 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
dump();
llerrs << "setSubImage called with mipmapped image (not supported)" << llendl;
}
- llassert(mCurrentDiscardLevel == 0);
+ llassert_always(mCurrentDiscardLevel == 0);
+ llassert_always(x_pos >= 0 && y_pos >= 0);
+
if (((x_pos + width) > getWidth()) ||
(y_pos + height) > getHeight())
{
@@ -698,7 +709,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
datap += (y_pos * data_width + x_pos) * getComponents();
// Update the GL texture
- llverify(bindTextureInternal(0));
+ BOOL res = bindTextureInternal(0);
+ if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl;
stop_glerror();
glTexSubImage2D(mTarget, 0, x_pos, y_pos,
@@ -714,7 +726,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
stop_glerror();
}
-
+ glFlush();
return TRUE;
}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 4f6a11c2d9..1586a837b4 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -17,7 +17,7 @@
//============================================================================
-class LLImageGL : public LLThreadSafeRefCount
+class LLImageGL : public LLRefCount
{
public:
// Size calculation
@@ -29,6 +29,7 @@ public:
// Usually you want stage = 0 and bind_target = GL_TEXTURE_2D
static void bindExternalTexture( LLGLuint gl_name, S32 stage, LLGLenum bind_target);
static void unbindTexture(S32 stage, LLGLenum target);
+ static void unbindTexture(S32 stage); // Uses GL_TEXTURE_2D (not a default arg to avoid gl.h dependency)
// needs to be called every frame
static void updateStats(F32 current_time);
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
new file mode 100644
index 0000000000..d6477d69ec
--- /dev/null
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -0,0 +1,918 @@
+#include "linden_common.h"
+
+#include "llvertexbuffer.h"
+// #include "llrender.h"
+#include "llglheaders.h"
+#include "llmemory.h"
+#include "llmemtype.h"
+
+//============================================================================
+
+//static
+S32 LLVertexBuffer::sCount = 0;
+S32 LLVertexBuffer::sGLCount = 0;
+BOOL LLVertexBuffer::sEnableVBOs = TRUE;
+S32 LLVertexBuffer::sGLRenderBuffer = 0;
+S32 LLVertexBuffer::sGLRenderIndices = 0;
+U32 LLVertexBuffer::sLastMask = 0;
+BOOL LLVertexBuffer::sVBOActive = FALSE;
+BOOL LLVertexBuffer::sIBOActive = FALSE;
+U32 LLVertexBuffer::sAllocatedBytes = 0;
+BOOL LLVertexBuffer::sRenderActive = FALSE;
+
+std::vector<U32> LLVertexBuffer::sDeleteList;
+LLVertexBuffer::buffer_list_t LLVertexBuffer::sLockedList;
+
+S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
+{
+ sizeof(LLVector3), // TYPE_VERTEX,
+ sizeof(LLVector3), // TYPE_NORMAL,
+ sizeof(LLVector2), // TYPE_TEXCOORD,
+ sizeof(LLVector2), // TYPE_TEXCOORD2,
+ sizeof(LLColor4U), // TYPE_COLOR,
+ sizeof(LLVector3), // TYPE_BINORMAL,
+ sizeof(F32), // TYPE_WEIGHT,
+ sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
+};
+
+//static
+void LLVertexBuffer::initClass(bool use_vbo)
+{
+ sEnableVBOs = use_vbo;
+}
+
+//static
+void LLVertexBuffer::unbind()
+{
+ if (sVBOActive)
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ sVBOActive = FALSE;
+ }
+ if (sIBOActive)
+ {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ sIBOActive = FALSE;
+ }
+
+ sGLRenderBuffer = 0;
+ sGLRenderIndices = 0;
+}
+
+//static
+void LLVertexBuffer::cleanupClass()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ sLockedList.clear();
+ startRender();
+ stopRender();
+ clientCopy(); // deletes GL buffers
+}
+
+//static, call before rendering VBOs
+void LLVertexBuffer::startRender()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (sEnableVBOs)
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ sVBOActive = FALSE;
+ sIBOActive = FALSE;
+ }
+
+ sRenderActive = TRUE;
+ sGLRenderBuffer = 0;
+ sGLRenderIndices = 0;
+ sLastMask = 0;
+}
+
+void LLVertexBuffer::stopRender()
+{
+ sRenderActive = FALSE;
+}
+
+void LLVertexBuffer::clientCopy()
+{
+ if (!sDeleteList.empty())
+ {
+ size_t num = sDeleteList.size();
+ glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
+ sDeleteList.clear();
+ sGLCount -= num;
+ }
+
+ if (sEnableVBOs)
+ {
+ LLTimer timer;
+ BOOL reset = TRUE;
+ buffer_list_t::iterator iter = sLockedList.begin();
+ while(iter != sLockedList.end())
+ {
+ LLVertexBuffer* buffer = *iter;
+ if (buffer->isLocked() && buffer->useVBOs())
+ {
+ buffer->setBuffer(0);
+ }
+ ++iter;
+ if (reset)
+ {
+ reset = FALSE;
+ timer.reset(); //skip first copy (don't count pipeline stall)
+ }
+ else
+ {
+ if (timer.getElapsedTimeF64() > 0.005)
+ {
+ break;
+ }
+ }
+
+ }
+
+ sLockedList.erase(sLockedList.begin(), iter);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+// For debugging
+struct VTNC /// Simple
+{
+ F32 v1,v2,v3;
+ F32 n1,n2,n3;
+ F32 t1,t2;
+ U32 c;
+};
+static VTNC dbg_vtnc;
+
+struct VTUNCB // Simple + Bump
+{
+ F32 v1,v2,v3;
+ F32 n1,n2,n3;
+ F32 t1,t2;
+ F32 u1,u2;
+ F32 b1,b2,b3;
+ U32 c;
+};
+static VTUNCB dbg_vtuncb;
+
+struct VTUNC // Surfacepatch
+{
+ F32 v1,v2,v3;
+ F32 n1,n2,n3;
+ F32 t1,t2;
+ F32 u1,u2;
+ U32 c;
+};
+static VTUNC dbg_vtunc;
+
+struct VTNW /// Avatar
+{
+ F32 v1,v2,v3;
+ F32 n1,n2,n3;
+ F32 t1,t2;
+ F32 w;
+};
+static VTNW dbg_vtnw;
+
+struct VTNPAD /// Avatar Output
+{
+ F32 v1,v2,v3,p1;
+ F32 n1,n2,n3,p2;
+ F32 t1,t2,p3,p4;
+};
+static VTNPAD dbg_vtnpad;
+
+//----------------------------------------------------------------------------
+
+LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
+ LLRefCount(),
+ mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
+ mMappedData(NULL),
+ mMappedIndexData(NULL), mLocked(FALSE),
+ mResized(FALSE), mEmpty(TRUE), mFinal(FALSE), mFilthy(FALSE)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (!sEnableVBOs)
+ {
+ mUsage = GL_STREAM_DRAW_ARB;
+ }
+
+ S32 stride = 0;
+ for (S32 i=0; i<TYPE_MAX; i++)
+ {
+ U32 mask = 1<<i;
+ if (typemask & mask)
+ {
+ mOffsets[i] = stride;
+ stride += sTypeOffsets[i];
+ }
+ }
+ mTypeMask = typemask;
+ mStride = stride;
+ sCount++;
+}
+
+// protected, use unref()
+//virtual
+LLVertexBuffer::~LLVertexBuffer()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ destroyGLBuffer();
+ destroyGLIndices();
+ sCount--;
+
+ if (mLocked)
+ {
+ //pull off of locked list
+ for (buffer_list_t::iterator i = sLockedList.begin(); i != sLockedList.end(); ++i)
+ {
+ if (*i == this)
+ {
+ sLockedList.erase(i);
+ break;
+ }
+ }
+ }
+};
+
+//----------------------------------------------------------------------------
+
+void LLVertexBuffer::createGLBuffer()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+
+ U32 size = getSize();
+ if (mGLBuffer)
+ {
+ destroyGLBuffer();
+ }
+
+ if (size == 0)
+ {
+ return;
+ }
+
+ mMappedData = new U8[size];
+ memset(mMappedData, 0, size);
+ mEmpty = TRUE;
+
+ if (useVBOs())
+ {
+ glGenBuffersARB(1, (GLuint*) &mGLBuffer);
+ mResized = TRUE;
+ sGLCount++;
+ }
+ else
+ {
+ static int gl_buffer_idx = 0;
+ mGLBuffer = ++gl_buffer_idx;
+ }
+}
+
+void LLVertexBuffer::createGLIndices()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ U32 size = getIndicesSize();
+
+ if (mGLIndices)
+ {
+ destroyGLIndices();
+ }
+
+ if (size == 0)
+ {
+ return;
+ }
+
+ mMappedIndexData = new U8[size];
+ memset(mMappedIndexData, 0, size);
+ mEmpty = TRUE;
+
+ if (useVBOs())
+ {
+ glGenBuffersARB(1, (GLuint*) &mGLIndices);
+ mResized = TRUE;
+ sGLCount++;
+ }
+ else
+ {
+ static int gl_buffer_idx = 0;
+ mGLIndices = ++gl_buffer_idx;
+ }
+}
+
+void LLVertexBuffer::destroyGLBuffer()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (mGLBuffer)
+ {
+ if (useVBOs())
+ {
+ sDeleteList.push_back(mGLBuffer);
+ }
+
+ delete [] mMappedData;
+ mMappedData = NULL;
+ mEmpty = TRUE;
+ sAllocatedBytes -= getSize();
+ }
+
+ mGLBuffer = 0;
+}
+
+void LLVertexBuffer::destroyGLIndices()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (mGLIndices)
+ {
+ if (useVBOs())
+ {
+ sDeleteList.push_back(mGLIndices);
+ }
+
+ delete [] mMappedIndexData;
+ mMappedIndexData = NULL;
+ mEmpty = TRUE;
+ sAllocatedBytes -= getIndicesSize();
+ }
+
+ mGLIndices = 0;
+}
+
+void LLVertexBuffer::updateNumVerts(S32 nverts)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (!mDynamicSize)
+ {
+ mNumVerts = nverts;
+ }
+ else if (mUsage == GL_STATIC_DRAW_ARB ||
+ nverts > mNumVerts ||
+ nverts < mNumVerts/2)
+ {
+ if (mUsage != GL_STATIC_DRAW_ARB)
+ {
+ nverts += nverts/4;
+ }
+
+ mNumVerts = nverts;
+ }
+}
+
+void LLVertexBuffer::updateNumIndices(S32 nindices)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (!mDynamicSize)
+ {
+ mNumIndices = nindices;
+ }
+ else if (mUsage == GL_STATIC_DRAW_ARB ||
+ nindices > mNumIndices ||
+ nindices < mNumIndices/2)
+ {
+ if (mUsage != GL_STATIC_DRAW_ARB)
+ {
+ nindices += nindices/4;
+ }
+
+ mNumIndices = nindices;
+ }
+}
+
+void LLVertexBuffer::makeStatic()
+{
+ if (!sEnableVBOs)
+ {
+ return;
+ }
+
+ if (sRenderActive)
+ {
+ llerrs << "Make static called during render." << llendl;
+ }
+
+ if (mUsage != GL_STATIC_DRAW_ARB)
+ {
+ if (useVBOs())
+ {
+ if (mGLBuffer)
+ {
+ sDeleteList.push_back(mGLBuffer);
+ }
+ if (mGLIndices)
+ {
+ sDeleteList.push_back(mGLIndices);
+ }
+ }
+
+ if (mGLBuffer)
+ {
+ sGLCount++;
+ glGenBuffersARB(1, (GLuint*) &mGLBuffer);
+ }
+ if (mGLIndices)
+ {
+ sGLCount++;
+ glGenBuffersARB(1, (GLuint*) &mGLIndices);
+ }
+
+ mUsage = GL_STATIC_DRAW_ARB;
+ mResized = TRUE;
+
+ if (!mLocked)
+ {
+ mLocked = TRUE;
+ sLockedList.push_back(this);
+ }
+ }
+}
+
+void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+
+ updateNumVerts(nverts);
+ updateNumIndices(nindices);
+
+ if (mMappedData)
+ {
+ llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl;
+ }
+ if (create && (nverts || nindices))
+ {
+ createGLBuffer();
+ createGLIndices();
+ }
+
+ sAllocatedBytes += getSize() + getIndicesSize();
+}
+
+void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ mDynamicSize = TRUE;
+ if (mUsage == GL_STATIC_DRAW_ARB)
+ { //always delete/allocate static buffers on resize
+ destroyGLBuffer();
+ destroyGLIndices();
+ allocateBuffer(newnverts, newnindices, TRUE);
+ mFinal = FALSE;
+ }
+ else if (newnverts > mNumVerts || newnindices > mNumIndices ||
+ newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
+ {
+ sAllocatedBytes -= getSize() + getIndicesSize();
+
+ S32 oldsize = getSize();
+ S32 old_index_size = getIndicesSize();
+
+ updateNumVerts(newnverts);
+ updateNumIndices(newnindices);
+
+ S32 newsize = getSize();
+ S32 new_index_size = getIndicesSize();
+
+ sAllocatedBytes += newsize + new_index_size;
+
+ if (newsize)
+ {
+ if (!mGLBuffer)
+ { //no buffer exists, create a new one
+ createGLBuffer();
+ }
+ else
+ {
+ //delete old buffer, keep GL buffer for now
+ U8* old = mMappedData;
+ mMappedData = new U8[newsize];
+ if (old)
+ {
+ memcpy(mMappedData, old, llmin(newsize, oldsize));
+ if (newsize > oldsize)
+ {
+ memset(mMappedData+oldsize, 0, newsize-oldsize);
+ }
+
+ delete [] old;
+ }
+ else
+ {
+ memset(mMappedData, 0, newsize);
+ mEmpty = TRUE;
+ }
+ mResized = TRUE;
+ }
+ }
+ else if (mGLBuffer)
+ {
+ destroyGLBuffer();
+ }
+
+ if (new_index_size)
+ {
+ if (!mGLIndices)
+ {
+ createGLIndices();
+ }
+ else
+ {
+ //delete old buffer, keep GL buffer for now
+ U8* old = mMappedIndexData;
+ mMappedIndexData = new U8[new_index_size];
+ if (old)
+ {
+ memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
+ if (new_index_size > old_index_size)
+ {
+ memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
+ }
+ delete [] old;
+ }
+ else
+ {
+ memset(mMappedIndexData, 0, new_index_size);
+ mEmpty = TRUE;
+ }
+ mResized = TRUE;
+ }
+ }
+ else if (mGLIndices)
+ {
+ destroyGLIndices();
+ }
+ }
+}
+
+BOOL LLVertexBuffer::useVBOs() const
+{
+ //it's generally ineffective to use VBO for things that are streaming
+ //when we already have a client buffer around
+ if (mUsage == GL_STREAM_DRAW_ARB)
+ {
+ return FALSE;
+ }
+
+ return sEnableVBOs && (!sRenderActive || !mLocked);
+}
+
+//----------------------------------------------------------------------------
+
+// Map for data access
+U8* LLVertexBuffer::mapBuffer(S32 access)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (sRenderActive)
+ {
+ llwarns << "Buffer mapped during render frame!" << llendl;
+ }
+ if (!mGLBuffer && !mGLIndices)
+ {
+ llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl;
+ }
+ if (mFinal)
+ {
+ llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
+ }
+ if (!mMappedData && !mMappedIndexData)
+ {
+ llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
+ }
+
+ if (!mLocked && useVBOs())
+ {
+ mLocked = TRUE;
+ sLockedList.push_back(this);
+ }
+
+ return mMappedData;
+}
+
+void LLVertexBuffer::unmapBuffer()
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (mMappedData || mMappedIndexData)
+ {
+ if (useVBOs() && mLocked)
+ {
+ if (mGLBuffer)
+ {
+ if (mResized)
+ {
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage);
+ }
+ else
+ {
+ if (mEmpty || mDirtyRegions.empty())
+ {
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+ }
+ else
+ {
+ for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
+ {
+ DirtyRegion& region = *i;
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride);
+ glFlush();
+ }
+ }
+ }
+ }
+
+ if (mGLIndices)
+ {
+ if (mResized)
+ {
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage);
+ }
+ else
+ {
+ if (mEmpty || mDirtyRegions.empty())
+ {
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+ }
+ else
+ {
+ for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
+ {
+ DirtyRegion& region = *i;
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32),
+ region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32));
+ glFlush();
+ }
+ }
+ }
+ }
+
+ mDirtyRegions.clear();
+ mFilthy = FALSE;
+ mResized = FALSE;
+
+ if (mUsage == GL_STATIC_DRAW_ARB)
+ { //static draw buffers can only be mapped a single time
+ //throw out client data (we won't be using it again)
+ delete [] mMappedData;
+ delete [] mMappedIndexData;
+ mMappedIndexData = NULL;
+ mMappedData = NULL;
+ mEmpty = TRUE;
+ mFinal = TRUE;
+ }
+ else
+ {
+ mEmpty = FALSE;
+ }
+
+ mLocked = FALSE;
+
+ glFlush();
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+template <class T,S32 type> struct VertexBufferStrider
+{
+ typedef LLStrider<T> strider_t;
+ static bool get(LLVertexBuffer& vbo,
+ strider_t& strider,
+ S32 index)
+ {
+ vbo.mapBuffer();
+ if (type == LLVertexBuffer::TYPE_INDEX)
+ {
+ S32 stride = sizeof(T);
+ strider = (T*)(vbo.getMappedIndices() + index*stride);
+ strider.setStride(0);
+ return TRUE;
+ }
+ else if (vbo.hasDataType(type))
+ {
+ S32 stride = vbo.getStride();
+ strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride);
+ strider.setStride(stride);
+ return TRUE;
+ }
+ else
+ {
+ llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
+ }
+ return FALSE;
+ }
+};
+
+
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getIndexStrider(LLStrider<U32>& strider, S32 index)
+{
+ return VertexBufferStrider<U32,TYPE_INDEX>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
+{
+ return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
+{
+ return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
+}
+bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
+}
+
+void LLVertexBuffer::setStride(S32 type, S32 new_stride)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ if (mNumVerts)
+ {
+ llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
+ }
+ // This code assumes that setStride() will only be called once per VBO per type.
+ S32 delta = new_stride - sTypeOffsets[type];
+ for (S32 i=type+1; i<TYPE_MAX; i++)
+ {
+ if (mTypeMask & (1<<i))
+ {
+ mOffsets[i] += delta;
+ }
+ }
+ mStride += delta;
+}
+
+//----------------------------------------------------------------------------
+
+// Set for rendering
+void LLVertexBuffer::setBuffer(U32 data_mask)
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ //set up pointers if the data mask is different ...
+ BOOL setup = (sLastMask != data_mask);
+
+ if (useVBOs())
+ {
+ if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
+ sVBOActive = TRUE;
+ setup = TRUE; // ... or the bound buffer changed
+ }
+ if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
+ {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
+ sIBOActive = TRUE;
+ }
+
+ unmapBuffer();
+ }
+ else
+ {
+ if (!mDirtyRegions.empty())
+ {
+ mFilthy = TRUE;
+ mDirtyRegions.clear();
+ }
+
+ if (mGLBuffer)
+ {
+ if (sEnableVBOs && sVBOActive)
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ sVBOActive = FALSE;
+ setup = TRUE; // ... or a VBO is deactivated
+ }
+ if (sGLRenderBuffer != mGLBuffer)
+ {
+ setup = TRUE; // ... or a client memory pointer changed
+ }
+ }
+ if (sEnableVBOs && mGLIndices && sIBOActive)
+ {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ sIBOActive = FALSE;
+ }
+ }
+
+ if (mGLIndices)
+ {
+ sGLRenderIndices = mGLIndices;
+ }
+ if (mGLBuffer)
+ {
+ sGLRenderBuffer = mGLBuffer;
+ if (data_mask && setup)
+ {
+ if (!sRenderActive)
+ {
+ llwarns << "Vertex buffer set for rendering outside of render frame." << llendl;
+ }
+ setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
+ sLastMask = data_mask;
+ }
+ }
+}
+
+// virtual (default)
+void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
+{
+ LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ stop_glerror();
+ U8* base = useVBOs() ? NULL : mMappedData;
+ S32 stride = mStride;
+
+ if ((data_mask & mTypeMask) != data_mask)
+ {
+ llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
+ }
+
+ if (data_mask & MAP_VERTEX)
+ {
+ glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
+ }
+ if (data_mask & MAP_NORMAL)
+ {
+ glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL]));
+ }
+ if (data_mask & MAP_TEXCOORD2)
+ {
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ }
+ if (data_mask & MAP_TEXCOORD)
+ {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
+ }
+ if (data_mask & MAP_COLOR)
+ {
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR]));
+ }
+ if (data_mask & MAP_BINORMAL)
+ {
+ glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL]));
+ }
+ if (data_mask & MAP_WEIGHT)
+ {
+ glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));
+ }
+ if (data_mask & MAP_CLOTHWEIGHT)
+ {
+ glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
+ }
+
+ llglassertok();
+}
+
+void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
+{
+ if (useVBOs() && !mFilthy)
+ {
+ if (!mDirtyRegions.empty())
+ {
+ DirtyRegion& region = *(mDirtyRegions.rbegin());
+ if (region.mIndex + region.mCount == vert_index &&
+ region.mIndicesIndex + region.mIndicesCount == indices_index)
+ {
+ region.mCount += vert_count;
+ region.mIndicesCount += indices_count;
+ return;
+ }
+ }
+
+ mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count));
+ }
+}
+
+void LLVertexBuffer::markClean()
+{
+ if (!mResized && !mEmpty && !mFilthy)
+ {
+ buffer_list_t::reverse_iterator iter = sLockedList.rbegin();
+ if (*iter == this)
+ {
+ mLocked = FALSE;
+ sLockedList.pop_back();
+ }
+ }
+}
+
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
new file mode 100644
index 0000000000..e672321e76
--- /dev/null
+++ b/indra/llrender/llvertexbuffer.h
@@ -0,0 +1,179 @@
+#ifndef LL_LLVERTEXBUFFER_H
+#define LL_LLVERTEXBUFFER_H
+
+#include "llgl.h"
+#include "v2math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "v4coloru.h"
+#include "llstrider.h"
+#include "llmemory.h"
+#include <set>
+#include <vector>
+
+//============================================================================
+// NOTES
+// Threading:
+// All constructors should take an 'create' paramater which should only be
+// 'true' when called from the main thread. Otherwise createGLBuffer() will
+// be called as soon as getVertexPointer(), etc is called (which MUST ONLY be
+// called from the main (i.e OpenGL) thread)
+
+//============================================================================
+// base class
+
+class LLVertexBuffer : public LLRefCount
+{
+public:
+ static void initClass(bool use_vbo);
+ static void cleanupClass();
+ static void startRender(); //between start and stop render, no client copies will occur
+ static void stopRender(); //any buffer not copied to GL will be rendered from client memory
+ static void clientCopy(); //copy data from client to GL
+ static void unbind(); //unbind any bound vertex buffer
+
+ enum {
+ TYPE_VERTEX,
+ TYPE_NORMAL,
+ TYPE_TEXCOORD,
+ TYPE_TEXCOORD2,
+ TYPE_COLOR,
+ // These use VertexAttribPointer and should possibly be made generic
+ TYPE_BINORMAL,
+ TYPE_WEIGHT,
+ TYPE_CLOTHWEIGHT,
+ TYPE_MAX,
+ TYPE_INDEX,
+ };
+ enum {
+ MAP_VERTEX = (1<<TYPE_VERTEX),
+ MAP_NORMAL = (1<<TYPE_NORMAL),
+ MAP_TEXCOORD = (1<<TYPE_TEXCOORD),
+ MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
+ MAP_COLOR = (1<<TYPE_COLOR),
+ // These use VertexAttribPointer and should possibly be made generic
+ MAP_BINORMAL = (1<<TYPE_BINORMAL),
+ MAP_WEIGHT = (1<<TYPE_WEIGHT),
+ MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
+ MAP_DRAW = 0x2000, // Buffer is in draw (read-only) mode
+ MAP_MAPPED = 0x4000, // Indicates that buffer has been mapped, but not to any type of data
+ MAP_UNMAPPED = 0x8000 // Indicates that buffer has been logically un-mapped
+ };
+
+protected:
+ virtual ~LLVertexBuffer(); // use unref()
+
+ virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer()
+
+ void createGLBuffer();
+ void createGLIndices();
+ void destroyGLBuffer();
+ void destroyGLIndices();
+ void updateNumVerts(S32 nverts);
+ void updateNumIndices(S32 nindices);
+ virtual BOOL useVBOs() const;
+ void unmapBuffer();
+
+public:
+ LLVertexBuffer(U32 typemask, S32 usage);
+
+ // map for data access
+ U8* mapBuffer(S32 access = -1);
+ // set for rendering
+ virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
+ // allocate buffer
+ void allocateBuffer(S32 nverts, S32 nindices, bool create);
+ virtual void resizeBuffer(S32 newnverts, S32 newnindices);
+ void makeStatic();
+
+ // Only call each getVertexPointer, etc, once before calling unmapBuffer()
+ // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
+ // example:
+ // vb->getVertexBuffer(verts);
+ // vb->getNormalStrider(norms);
+ // setVertsNorms(verts, norms);
+ // vb->unmapBuffer();
+ bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getIndexStrider(LLStrider<U32>& strider, S32 index=0);
+ bool getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index=0);
+ bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
+ bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
+
+ BOOL isEmpty() const { return mEmpty; }
+ BOOL isLocked() const { return mLocked; }
+ S32 getNumVerts() const { return mNumVerts; }
+ S32 getNumIndices() const { return mNumIndices; }
+ U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; }
+ U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; }
+ S32 getStride() const { return mStride; }
+ S32 getTypeMask() const { return mTypeMask; }
+ BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; }
+ S32 getSize() const { return mNumVerts*mStride; }
+ S32 getIndicesSize() const { return mNumIndices * sizeof(U32); }
+ U8* getMappedData() const { return mMappedData; }
+ U8* getMappedIndices() const { return mMappedIndexData; }
+ S32 getOffset(S32 type) const { return mOffsets[type]; }
+ S32 getUsage() const { return mUsage; }
+
+ void setStride(S32 type, S32 new_stride);
+
+ void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
+ void markClean();
+
+protected:
+ S32 mNumVerts; // Number of vertices
+ S32 mNumIndices; // Number of indices
+ S32 mStride;
+ U32 mTypeMask;
+ S32 mUsage; // GL usage
+ U32 mGLBuffer; // GL VBO handle
+ U32 mGLIndices; // GL IBO handle
+ U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
+ BOOL mLocked; // if TRUE, buffer is being or has been written to in client memory
+ BOOL mFinal; // if TRUE, buffer can not be mapped again
+ BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags)
+ BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded.
+ S32 mOffsets[TYPE_MAX];
+ BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not
+ BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
+
+ 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<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
+
+public:
+ static BOOL sRenderActive;
+ static S32 sCount;
+ static S32 sGLCount;
+ static std::vector<U32> sDeleteList;
+ typedef std::list<LLVertexBuffer*> buffer_list_t;
+ static buffer_list_t sLockedList;
+
+ static BOOL sEnableVBOs;
+ static S32 sTypeOffsets[TYPE_MAX];
+ static S32 sGLRenderBuffer;
+ static S32 sGLRenderIndices;
+ static BOOL sVBOActive;
+ static BOOL sIBOActive;
+ static U32 sLastMask;
+ static U32 sAllocatedBytes;
+};
+
+
+#endif // LL_LLVERTEXBUFFER_H
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index fc7a29887b..667985c699 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -43,6 +43,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
mDrawButton(TRUE),
mTextEntry(NULL),
mArrowImage(NULL),
+ mArrowImageWidth(8),
mAllowTextEntry(FALSE),
mMaxChars(20),
mTextEntryTentative(TRUE),
@@ -99,6 +100,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id);
+ mArrowImageWidth = llmax(8,mArrowImage->getWidth()); // In case image hasn't loaded yet
}
@@ -502,7 +504,7 @@ void LLComboBox::setButtonVisible(BOOL visible)
LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
if (visible)
{
- text_entry_rect.mRight -= mArrowImage->getWidth() + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
+ text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
}
//mTextEntry->setRect(text_entry_rect);
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
@@ -525,7 +527,7 @@ void LLComboBox::draw()
// Paste the graphic on the right edge
if (!mArrowImage.isNull())
{
- S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton");
+ S32 left = mRect.getWidth() - mArrowImageWidth - LLUI::sConfigGroup->getS32("DropShadowButton");
gl_draw_image( left, 0, mArrowImage,
LLColor4::white);
@@ -825,7 +827,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
if (allow && !mAllowTextEntry)
{
S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
- mButton->setRect(LLRect( mRect.getWidth() - mArrowImage->getWidth() - 2 * shadow_size,
+ mButton->setRect(LLRect( mRect.getWidth() - mArrowImageWidth - 2 * shadow_size,
rect.mTop, rect.mRight, rect.mBottom));
mButton->setTabStop(FALSE);
@@ -835,7 +837,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
if (!mTextEntry)
{
LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
- text_entry_rect.mRight -= mArrowImage->getWidth() + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
+ text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
mTextEntry = new LLLineEditor("combo_text_entry",
text_entry_rect,
"",
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 1ec31ec1c0..faf99937c9 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -167,8 +167,9 @@ protected:
BOOL mDrawButton;
LLLineEditor* mTextEntry;
LLPointer<LLImageGL> mArrowImage;
+ S32 mArrowImageWidth;
BOOL mAllowTextEntry;
- S32 mMaxChars;
+ S32 mMaxChars;
BOOL mTextEntryTentative;
void (*mPrearrangeCallback)(LLUICtrl*,void*);
void (*mTextEntryCallback)(LLLineEditor*, void*);
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 59922994c1..fdf4a117d4 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -17,6 +17,7 @@
#include "llviewborder.h"
#include "v4color.h"
#include <list>
+#include <queue>
const S32 LLPANEL_BORDER_WIDTH = 1;
const BOOL BORDER_YES = TRUE;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index c168bbe5a8..f2ae318dca 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -2720,7 +2720,7 @@ void LLScrollListCtrl::setFocus(BOOL b)
if (!getFirstSelected())
{
selectFirstItem();
- onCommit();
+ //onCommit(); // SJB: selectFirstItem() will call onCommit() if appropriate
}
LLUICtrl::setFocus(b);
}
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 710e333796..de34aabb1f 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -3934,6 +3934,8 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const
node->createChild("word_wrap", TRUE)->setBoolValue(mWordWrap);
+ node->createChild("hide_scrollbar", TRUE)->setBoolValue(mHideScrollbarForShortDocs);
+
addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor");
addColorXML(node, mFgColor, "text_color", "TextFgColor");
addColorXML(node, mReadOnlyFgColor, "text_readonly_color", "TextFgReadOnlyColor");
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index f58b7d6e16..1418151201 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -17,7 +17,6 @@
//
// Classes
//
-class LLViewerImage;
class LLFontGL;
class LLButton;
class LLTextBox;
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 8ae9fd0284..21278455da 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -191,12 +191,18 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator<LLMenuBarGL>::registerCreator(LL_MENU_BAR_GL_TAG, this);
LLUICtrlCreator<LLScrollingPanelList>::registerCreator(LL_SCROLLING_PANEL_LIST_TAG, this);
+ setupPaths();
+}
+
+void LLUICtrlFactory::setupPaths()
+{
LLString filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml");
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(filename, root, NULL);
-
+ mXUIPaths.clear();
+
if (!success)
{
LLString slash = gDirUtilp->getDirDelimiter();
@@ -220,7 +226,7 @@ LLUICtrlFactory::LLUICtrlFactory()
path_val_ui.setArg("[Language]", language);
LLString fullpath = app_dir + path_val_ui.getString();
- if (mXUIPaths.empty() || (find(mXUIPaths.begin(), mXUIPaths.end(), fullpath) == mXUIPaths.end()) )
+ if (std::find(mXUIPaths.begin(), mXUIPaths.end(), fullpath) == mXUIPaths.end())
{
mXUIPaths.push_back(app_dir + path_val_ui.getString());
}
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index b3bd5c9020..cb6864bafd 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -55,6 +55,8 @@ public:
// do not call! needs to be public so run-time can clean up the singleton
virtual ~LLUICtrlFactory();
+ void setupPaths();
+
void buildFloater(LLFloater* floaterp, const LLString &filename,
const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE);
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 9f8d6c08d5..d8d77e6a23 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -183,6 +183,27 @@ const std::string &LLDir::getTempDir() const
return mTempDir;
}
+const std::string LLDir::getCacheDir(bool get_default) const
+{
+ if (mCacheDir.empty() || get_default)
+ {
+ std::string res;
+ if (getOSUserAppDir().empty())
+ {
+ res = "data";
+ }
+ else
+ {
+ res = getOSUserAppDir() + mDirDelimiter + "cache";
+ }
+ return res;
+ }
+ else
+ {
+ return mCacheDir;
+ }
+}
+
const std::string &LLDir::getCAFile() const
{
return mCAFile;
@@ -198,7 +219,12 @@ const std::string &LLDir::getSkinDir() const
return mSkinDir;
}
-std::string LLDir::getExpandedFilename(ELLPath location, const std::string &filename) const
+std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
+{
+ return getExpandedFilename(location, "", filename);
+}
+
+std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& in_filename) const
{
std::string prefix;
switch (location)
@@ -230,16 +256,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string &file
break;
case LL_PATH_CACHE:
- if (getOSUserAppDir().empty())
- {
- prefix = "data";
- }
- else
- {
- prefix = getOSUserAppDir();
- prefix += mDirDelimiter;
- prefix += "cache";
- }
+ prefix = getCacheDir();
break;
case LL_PATH_USER_SETTINGS:
@@ -290,6 +307,16 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string &file
llassert(0);
}
+ std::string filename = in_filename;
+ if (!subdir.empty())
+ {
+ filename = subdir + mDirDelimiter + in_filename;
+ }
+ else
+ {
+ filename = in_filename;
+ }
+
std::string expanded_filename;
if (!filename.empty())
{
@@ -304,8 +331,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string &file
expanded_filename = filename;
}
}
- else
- if (!prefix.empty())
+ else if (!prefix.empty())
{
// Directory only, no file name.
expanded_filename = prefix;
@@ -405,6 +431,30 @@ void LLDir::setSkinFolder(const std::string &skin_folder)
mSkinDir += skin_folder;
}
+bool LLDir::setCacheDir(const std::string &path)
+{
+ if (path.empty() )
+ {
+ // reset to default
+ mCacheDir = "";
+ return true;
+ }
+ else
+ {
+ LLFile::mkdir(path.c_str());
+ std::string tempname = path + mDirDelimiter + "temp";
+ LLFILE* file = LLFile::fopen(tempname.c_str(),"wt");
+ if (file)
+ {
+ fclose(file);
+ LLFile::remove(tempname.c_str());
+ mCacheDir = path;
+ return true;
+ }
+ return false;
+ }
+}
+
void LLDir::dumpCurrentDirectories()
{
llinfos << "Current Directories:" << llendl;
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 710dcd1ae3..5389378def 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -60,12 +60,14 @@ class LLDir
const std::string &getChatLogsDir() const; // Location of the chat logs dir.
const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
const std::string &getTempDir() const; // Common temporary directory
+ const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
const std::string &getCAFile() const; // File containing TLS certificate authorities
const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':')
const std::string &getSkinDir() const; // User-specified skin folder.
// Expanded filename
std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
// random filename in common temporary directory
std::string getTempFilename() const;
@@ -74,6 +76,7 @@ class LLDir
virtual void setPerAccountChatLogsDir(const std::string &first, const std::string &last); // Set the per user chat log directory.
virtual void setLindenUserDir(const std::string &first, const std::string &last); // Set the linden user dir to this user's dir
virtual void setSkinFolder(const std::string &skin_folder);
+ virtual bool setCacheDir(const std::string &path);
virtual void dumpCurrentDirectories();
@@ -91,6 +94,7 @@ protected:
std::string mChatLogsDir; // Location for chat logs.
std::string mCAFile; // Location of the TLS certificate authority PEM file.
std::string mTempDir;
+ std::string mCacheDir;
std::string mDirDelimiter;
std::string mSkinDir; // Location for u ser-specified skin info.
};
diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp
index 6af638fd12..598de1d370 100644
--- a/indra/llvfs/lllfsthread.cpp
+++ b/indra/llvfs/lllfsthread.cpp
@@ -19,10 +19,10 @@
//============================================================================
// Run on MAIN thread
//static
-void LLLFSThread::initClass(bool local_is_threaded, bool local_run_always)
+void LLLFSThread::initClass(bool local_is_threaded)
{
llassert(sLocal == NULL);
- sLocal = new LLLFSThread(local_is_threaded, local_run_always);
+ sLocal = new LLLFSThread(local_is_threaded);
}
//static
@@ -46,8 +46,9 @@ void LLLFSThread::cleanupClass()
//----------------------------------------------------------------------------
-LLLFSThread::LLLFSThread(bool threaded, bool runalways) :
- LLQueuedThread("LFS", threaded, runalways)
+LLLFSThread::LLLFSThread(bool threaded) :
+ LLQueuedThread("LFS", threaded),
+ mPriorityCounter(PRIORITY_LOWBITS)
{
}
@@ -59,250 +60,164 @@ LLLFSThread::~LLLFSThread()
//----------------------------------------------------------------------------
LLLFSThread::handle_t LLLFSThread::read(const LLString& filename, /* Flawfinder: ignore */
- U8* buffer, S32 offset, S32 numbytes, U32 priority, U32 flags)
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder, U32 priority)
{
handle_t handle = generateHandle();
- priority = llmax(priority, (U32)PRIORITY_LOW); // All reads are at least PRIORITY_LOW
- Request* req = new Request(handle, priority, flags,
+ if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
+ else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
+
+ Request* req = new Request(this, handle, priority,
FILE_READ, filename,
- buffer, offset, numbytes);
+ buffer, offset, numbytes,
+ responder);
bool res = addRequest(req);
if (!res)
{
llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- handle = nullHandle();
}
return handle;
}
-S32 LLLFSThread::readImmediate(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes)
-{
- handle_t handle = generateHandle();
-
- Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0,
- FILE_READ, filename,
- buffer, offset, numbytes);
-
- S32 res = addRequest(req) ? 1 : 0;
- if (res == 0)
- {
- llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- }
- else
- {
- llverify(waitForResult(handle, false) == true);
- res = req->getBytesRead();
- completeRequest(handle);
- }
- return res;
-}
-
LLLFSThread::handle_t LLLFSThread::write(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes, U32 flags)
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder, U32 priority)
{
handle_t handle = generateHandle();
- Request* req = new Request(handle, 0, flags,
- FILE_WRITE, filename,
- buffer, offset, numbytes);
-
- bool res = addRequest(req);
- if (!res)
- {
- llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- handle = nullHandle();
- }
+ if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
- return handle;
-}
-
-S32 LLLFSThread::writeImmediate(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes)
-{
- handle_t handle = generateHandle();
-
- Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0,
+ Request* req = new Request(this, handle, priority,
FILE_WRITE, filename,
- buffer, offset, numbytes);
-
- S32 res = addRequest(req) ? 1 : 0;
- if (res == 0)
- {
- llerrs << "LLLFSThread::write called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- }
- else
- {
- llverify(waitForResult(handle, false) == true);
- res = req->getBytesRead();
- completeRequest(handle);
- }
- return res;
-}
-
-
-LLLFSThread::handle_t LLLFSThread::rename(const LLString& filename, const LLString& newname, U32 flags)
-{
- handle_t handle = generateHandle();
-
- LLString* new_name_str = new LLString(newname); // deleted with Request
- Request* req = new Request(handle, 0, flags,
- FILE_RENAME, filename,
- (U8*)new_name_str, 0, 0);
-
- bool res = addRequest(req);
- if (!res)
- {
- llerrs << "LLLFSThread::rename called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- handle = nullHandle();
- }
-
- return handle;
-}
-
-LLLFSThread::handle_t LLLFSThread::remove(const LLString& filename, U32 flags)
-{
- handle_t handle = generateHandle();
-
- Request* req = new Request(handle, 0, flags,
- FILE_RENAME, filename,
- NULL, 0, 0);
+ buffer, offset, numbytes,
+ responder);
bool res = addRequest(req);
if (!res)
{
- llerrs << "LLLFSThread::remove called after LLLFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- handle = nullHandle();
+ llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
}
return handle;
}
//============================================================================
-// Runs on its OWN thread
-
-bool LLLFSThread::processRequest(QueuedRequest* qreq)
-{
- Request *req = (Request*)qreq;
-
- bool complete = req->processIO();
-
- return complete;
-}
-
-//============================================================================
-LLLFSThread::Request::Request(handle_t handle, U32 priority, U32 flags,
+LLLFSThread::Request::Request(LLLFSThread* thread,
+ handle_t handle, U32 priority,
operation_t op, const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes) :
- QueuedRequest(handle, priority, flags),
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder) :
+ QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
+ mThread(thread),
mOperation(op),
mFileName(filename),
mBuffer(buffer),
mOffset(offset),
mBytes(numbytes),
- mBytesRead(0)
+ mBytesRead(0),
+ mResponder(responder)
{
- llassert(mBuffer);
-
- if (numbytes <= 0 && mOperation != FILE_RENAME && mOperation != FILE_REMOVE)
+ if (numbytes <= 0)
{
llwarns << "LLLFSThread: Request with numbytes = " << numbytes << llendl;
}
}
-void LLLFSThread::Request::finishRequest()
+LLLFSThread::Request::~Request()
{
}
+// virtual, called from own thread
+void LLLFSThread::Request::finishRequest(bool completed)
+{
+ if (mResponder.notNull())
+ {
+ mResponder->completed(completed ? mBytesRead : 0);
+ mResponder = NULL;
+ }
+}
+
void LLLFSThread::Request::deleteRequest()
{
- if (getStatus() == STATUS_QUEUED || getStatus() == STATUS_ABORT)
+ if (getStatus() == STATUS_QUEUED)
{
llerrs << "Attempt to delete a queued LLLFSThread::Request!" << llendl;
}
- if (mOperation == FILE_WRITE)
- {
- if (mFlags & AUTO_DELETE)
- {
- delete mBuffer;
- }
- }
- else if (mOperation == FILE_RENAME)
+ if (mResponder.notNull())
{
- LLString* new_name = (LLString*)mBuffer;
- delete new_name;
+ mResponder->completed(0);
+ mResponder = NULL;
}
LLQueuedThread::QueuedRequest::deleteRequest();
}
-bool LLLFSThread::Request::processIO()
+bool LLLFSThread::Request::processRequest()
{
bool complete = false;
if (mOperation == FILE_READ)
{
llassert(mOffset >= 0);
- apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB);
+ apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB, mThread->mAPRPoolp);
if (!filep)
{
llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
mBytesRead = 0; // fail
return true;
}
+ S32 off;
if (mOffset < 0)
- ll_apr_file_seek(filep, APR_END, 0);
+ off = ll_apr_file_seek(filep, APR_END, 0);
else
- ll_apr_file_seek(filep, APR_SET, mOffset);
+ off = ll_apr_file_seek(filep, APR_SET, mOffset);
+ llassert_always(off >= 0);
mBytesRead = ll_apr_file_read(filep, mBuffer, mBytes );
apr_file_close(filep);
complete = true;
- //llinfos << llformat("LLLFSThread::READ '%s': %d bytes",mFileName.c_str(),mBytesRead) << llendl;
+// llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl;
}
else if (mOperation == FILE_WRITE)
{
- apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_WB);
+ apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
+ if (mOffset < 0)
+ flags |= APR_APPEND;
+ apr_file_t* filep = ll_apr_file_open(mFileName, flags, mThread->mAPRPoolp);
if (!filep)
{
llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
mBytesRead = 0; // fail
return true;
}
- if (mOffset < 0)
- ll_apr_file_seek(filep, APR_END, 0);
- else
- ll_apr_file_seek(filep, APR_SET, mOffset);
+ if (mOffset >= 0)
+ {
+ S32 seek = ll_apr_file_seek(filep, APR_SET, mOffset);
+ if (seek < 0)
+ {
+ apr_file_close(filep);
+ llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
+ mBytesRead = 0; // fail
+ return true;
+ }
+ }
mBytesRead = ll_apr_file_write(filep, mBuffer, mBytes );
complete = true;
apr_file_close(filep);
- //llinfos << llformat("LLLFSThread::WRITE '%s': %d bytes",mFileName.c_str(),mBytesRead) << llendl;
- }
- else if (mOperation == FILE_RENAME)
- {
- LLString* new_name = (LLString*)mBuffer;
- ll_apr_file_rename(mFileName, *new_name);
- complete = true;
- //llinfos << llformat("LLLFSThread::RENAME '%s': '%s'",mFileName.c_str(),new_name->c_str()) << llendl;
- }
- else if (mOperation == FILE_REMOVE)
- {
- ll_apr_file_remove(mFileName);
- complete = true;
- //llinfos << llformat("LLLFSThread::REMOVE '%s'",mFileName.c_str()) << llendl;
+// llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
}
else
{
- llerrs << llformat("LLLFSThread::unknown operation: %d", mOperation) << llendl;
+ llerrs << "LLLFSThread::unknown operation: " << (S32)mOperation << llendl;
}
return complete;
}
//============================================================================
+
+LLLFSThread::Responder::~Responder()
+{
+}
+
+//============================================================================
diff --git a/indra/llvfs/lllfsthread.h b/indra/llvfs/lllfsthread.h
index 37a6e8bae5..74fd0ffd4d 100644
--- a/indra/llvfs/lllfsthread.h
+++ b/indra/llvfs/lllfsthread.h
@@ -36,15 +36,24 @@ public:
//------------------------------------------------------------------------
public:
+ class Responder : public LLThreadSafeRefCount
+ {
+ public:
+ virtual ~Responder();
+ virtual void completed(S32 bytes) = 0;
+ };
+
class Request : public QueuedRequest
{
protected:
- ~Request() {}; // use deleteRequest()
+ virtual ~Request(); // use deleteRequest()
public:
- Request(handle_t handle, U32 priority, U32 flags,
+ Request(LLLFSThread* thread,
+ handle_t handle, U32 priority,
operation_t op, const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes);
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder);
S32 getBytes()
{
@@ -67,12 +76,12 @@ public:
return mFileName;
}
- /*virtual*/ void finishRequest();
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
/*virtual*/ void deleteRequest();
-
- bool processIO();
private:
+ LLLFSThread* mThread;
operation_t mOperation;
LLString mFileName;
@@ -80,35 +89,36 @@ public:
U8* mBuffer; // dest for reads, source for writes, new UUID for rename
S32 mOffset; // offset into file, -1 = append (WRITE only)
S32 mBytes; // bytes to read from file, -1 = all
- S32 mBytesRead; // bytes read from file
+ S32 mBytesRead; // bytes read from file
+
+ LLPointer<Responder> mResponder;
};
//------------------------------------------------------------------------
public:
- LLLFSThread(bool threaded = TRUE, bool runalways = TRUE);
+ LLLFSThread(bool threaded = TRUE);
~LLLFSThread();
// Return a Request handle
handle_t read(const LLString& filename, /* Flawfinder: ignore */
- U8* buffer, S32 offset, S32 numbytes, U32 pri=PRIORITY_NORMAL, U32 flags = 0);
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder, U32 pri=0);
handle_t write(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes, U32 flags = 0);
- handle_t rename(const LLString& filename, const LLString& newname, U32 flags = 0);
- handle_t remove(const LLString& filename, U32 flags = 0);
+ U8* buffer, S32 offset, S32 numbytes,
+ Responder* responder, U32 pri=0);
- // Return number of bytes read
- S32 readImmediate(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes);
- S32 writeImmediate(const LLString& filename,
- U8* buffer, S32 offset, S32 numbytes);
-
- static void initClass(bool local_is_threaded = TRUE, bool run_always = TRUE); // Setup sLocal
+ // Misc
+ U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations
+
+ // static initializers
+ static void initClass(bool local_is_threaded = TRUE); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static void cleanupClass(); // Delete sLocal
-protected:
- /*virtual*/ bool processRequest(QueuedRequest* req);
-
+
+private:
+ U32 mPriorityCounter;
+
public:
static LLLFSThread* sLocal; // Default local file thread
};
diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp
index a4612233d3..ae45c8fe42 100644
--- a/indra/llvfs/llvfile.cpp
+++ b/indra/llvfs/llvfile.cpp
@@ -51,12 +51,12 @@ LLVFile::~LLVFile()
{
if (!(mMode & LLVFile::WRITE))
{
- // llwarns << "Destroying LLVFile with pending async read/write, aborting..." << llendl;
- sVFSThread->abortRequest(mHandle, LLVFSThread::AUTO_COMPLETE);
+ //llwarns << "Destroying LLVFile with pending async read/write, aborting..." << llendl;
+ sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_ABORT);
}
else // WRITE
{
- sVFSThread->setFlags(mHandle, LLVFSThread::AUTO_COMPLETE);
+ sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE);
}
}
}
@@ -194,8 +194,8 @@ BOOL LLVFile::write(const U8 *buffer, S32 bytes)
S32 offset = -1;
mHandle = sVFSThread->write(mVFS, mFileID, mFileType,
writebuf, offset, bytes,
- LLVFSThread::AUTO_COMPLETE | LLVFSThread::AUTO_DELETE);
- mHandle = LLVFSThread::nullHandle(); // AUTO_COMPLETE means we don't track this
+ LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_AUTO_DELETE);
+ mHandle = LLVFSThread::nullHandle(); // FLAG_AUTO_COMPLETE means we don't track this
}
else
{
@@ -304,7 +304,7 @@ BOOL LLVFile::setMaxSize(S32 size)
}
if (sVFSThread->isPaused())
{
- sVFSThread->updateQueue(0);
+ sVFSThread->update(0);
}
ms_sleep(10);
}
@@ -408,7 +408,7 @@ void LLVFile::waitForLock(EVFSLock lock)
{
if (sVFSThread->isPaused())
{
- sVFSThread->updateQueue(0);
+ sVFSThread->update(0);
}
ms_sleep(1);
}
diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index 592f74dd02..e4749041ee 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -771,12 +771,17 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
}
// round all sizes upward to KB increments
- if (max_size & FILE_BLOCK_MASK)
+ // SJB: Need to not round for the new texture-pipeline code so we know the correct
+ // max file size. Need to investigate the potential problems with this...
+ if (file_type != LLAssetType::AT_TEXTURE)
{
- max_size += FILE_BLOCK_MASK;
- max_size &= ~FILE_BLOCK_MASK;
- }
-
+ if (max_size & FILE_BLOCK_MASK)
+ {
+ max_size += FILE_BLOCK_MASK;
+ max_size &= ~FILE_BLOCK_MASK;
+ }
+ }
+
if (block && block->mLength > 0)
{
block->mAccessTime = (U32)time(NULL);
@@ -1998,7 +2003,7 @@ LLString get_extension(LLAssetType::EType type)
switch(type)
{
case LLAssetType::AT_TEXTURE:
- extension = ".jp2"; // ".j2c"; // IrfanView recognizes .jp2 -sjb
+ extension = ".j2c";
break;
case LLAssetType::AT_SOUND:
extension = ".ogg";
diff --git a/indra/llvfs/llvfsthread.cpp b/indra/llvfs/llvfsthread.cpp
index 619c1b9bb3..57cdb7626e 100644
--- a/indra/llvfs/llvfsthread.cpp
+++ b/indra/llvfs/llvfsthread.cpp
@@ -20,10 +20,10 @@
//============================================================================
// Run on MAIN thread
//static
-void LLVFSThread::initClass(bool local_is_threaded, bool local_run_always)
+void LLVFSThread::initClass(bool local_is_threaded)
{
llassert(sLocal == NULL);
- sLocal = new LLVFSThread(local_is_threaded, local_run_always);
+ sLocal = new LLVFSThread(local_is_threaded);
}
//static
@@ -47,8 +47,8 @@ void LLVFSThread::cleanupClass()
//----------------------------------------------------------------------------
-LLVFSThread::LLVFSThread(bool threaded, bool runalways) :
- LLQueuedThread("VFS", threaded, runalways)
+LLVFSThread::LLVFSThread(bool threaded) :
+ LLQueuedThread("VFS", threaded)
{
}
@@ -145,38 +145,26 @@ S32 LLVFSThread::writeImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAsset
}
-LLVFSThread::handle_t LLVFSThread::rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
- const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags)
-{
- handle_t handle = generateHandle();
+// LLVFSThread::handle_t LLVFSThread::rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
+// const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags)
+// {
+// handle_t handle = generateHandle();
- LLUUID* new_idp = new LLUUID(new_id); // deleted with Request
- // new_type is passed as "numbytes"
- Request* req = new Request(handle, 0, flags, FILE_RENAME, vfs, file_id, file_type,
- (U8*)new_idp, 0, (S32)new_type);
+// LLUUID* new_idp = new LLUUID(new_id); // deleted with Request
+// // new_type is passed as "numbytes"
+// Request* req = new Request(handle, 0, flags, FILE_RENAME, vfs, file_id, file_type,
+// (U8*)new_idp, 0, (S32)new_type);
- bool res = addRequest(req);
- if (!res)
- {
- llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
- req->deleteRequest();
- handle = nullHandle();
- }
+// bool res = addRequest(req);
+// if (!res)
+// {
+// llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
+// req->deleteRequest();
+// handle = nullHandle();
+// }
- return handle;
-}
-
-//============================================================================
-// Runs on its OWN thread
-
-bool LLVFSThread::processRequest(QueuedRequest* qreq)
-{
- Request *req = (Request*)qreq;
-
- bool complete = req->processIO();
-
- return complete;
-}
+// return handle;
+// }
//============================================================================
@@ -223,7 +211,7 @@ LLVFSThread::Request::Request(handle_t handle, U32 priority, U32 flags,
}
// dec locks as soon as a request finishes
-void LLVFSThread::Request::finishRequest()
+void LLVFSThread::Request::finishRequest(bool completed)
{
if (mOperation == FILE_WRITE)
{
@@ -241,13 +229,13 @@ void LLVFSThread::Request::finishRequest()
void LLVFSThread::Request::deleteRequest()
{
- if (getStatus() == STATUS_QUEUED || getStatus() == STATUS_ABORT)
+ if (getStatus() == STATUS_QUEUED)
{
llerrs << "Attempt to delete a queued LLVFSThread::Request!" << llendl;
}
if (mOperation == FILE_WRITE)
{
- if (mFlags & AUTO_DELETE)
+ if (mFlags & FLAG_AUTO_DELETE)
{
delete [] mBuffer;
}
@@ -260,7 +248,7 @@ void LLVFSThread::Request::deleteRequest()
LLQueuedThread::QueuedRequest::deleteRequest();
}
-bool LLVFSThread::Request::processIO()
+bool LLVFSThread::Request::processRequest()
{
bool complete = false;
if (mOperation == FILE_READ)
@@ -283,7 +271,7 @@ bool LLVFSThread::Request::processIO()
mVFS->renameFile(mFileID, mFileType, *new_idp, new_type);
mFileID = *new_idp;
complete = true;
- //llinfos << llformat("LLVFSThread::WRITE '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
+ //llinfos << llformat("LLVFSThread::RENAME '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
}
else
{
diff --git a/indra/llvfs/llvfsthread.h b/indra/llvfs/llvfsthread.h
index 6839338813..ea7c5123b0 100644
--- a/indra/llvfs/llvfsthread.h
+++ b/indra/llvfs/llvfsthread.h
@@ -69,10 +69,9 @@ public:
return std::string(tbuf);
}
- /*virtual*/ void finishRequest();
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
/*virtual*/ void deleteRequest();
-
- bool processIO();
private:
operation_t mOperation;
@@ -90,10 +89,10 @@ public:
//------------------------------------------------------------------------
public:
static std::string sDataPath;
- static void setDataPath(const std::string& path) { sDataPath = path; }
+ static LLVFSThread* sLocal; // Default worker thread
public:
- LLVFSThread(bool threaded = TRUE, bool runalways = TRUE);
+ LLVFSThread(bool threaded = TRUE);
~LLVFSThread();
// Return a Request handle
@@ -101,8 +100,9 @@ public:
U8* buffer, S32 offset, S32 numbytes, U32 pri=PRIORITY_NORMAL, U32 flags = 0);
handle_t write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes, U32 flags);
- handle_t rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
- const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags);
+ // SJB: rename seems to have issues, especially when threaded
+// handle_t rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
+// const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags);
// Return number of bytes read
S32 readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes);
@@ -111,12 +111,11 @@ public:
/*virtual*/ bool processRequest(QueuedRequest* req);
- static void initClass(bool local_is_threaded = TRUE, bool run_always = TRUE); // Setup sLocal
+public:
+ static void initClass(bool local_is_threaded = TRUE); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static void cleanupClass(); // Delete sLocal
-
-public:
- static LLVFSThread* sLocal; // Default worker thread
+ static void setDataPath(const std::string& path) { sDataPath = path; }
};
//============================================================================
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 442f4c9667..bbe530c906 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -298,6 +298,7 @@ public:
//
// helper funcs
//
+extern BOOL gDebugWindowProc;
// Protocols, like "http" and "https" we support in URLs
extern const S32 gURLProtocolWhitelistCount;
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index a32013a5ee..c18e72b706 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -11,6 +11,7 @@
#include "linden_common.h"
#include <Carbon/Carbon.h>
+#include <OpenGL/OpenGL.h>
#include "llwindowmacosx.h"
#include "llkeyboardmacosx.h"
@@ -719,6 +720,22 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
}
aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
+#if 0 // SJB: Got a compile error. Plus I don't want to test this along with everything else ; save it for later
+ //enable multi-threaded OpenGL
+ CGLError cgl_err;
+ CGLContextObj ctx = CGLGetCurrentContext();
+
+ cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
+
+ if (cgl_err != kCGLNoError )
+ {
+ llinfos << "Multi-threaded OpenGL not available." << llendl;
+ }
+ else
+ {
+ llinfos << "Multi-threaded OpenGL enabled." << llendl;
+ }
+#endif
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
return TRUE;
}
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index c79a39c513..4efa173fc4 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -55,61 +55,6 @@ void show_window_creation_error(const char* title)
{
llwarns << title << llendl;
shell_open( "help/window_creation_error.html");
- /*
- OSMessageBox(
- "Second Life is unable to run because it can't set up your display.\n"
- "We need to be able to make a 32-bit color window at 1024x768, with\n"
- "an 8 bit alpha channel.\n"
- "\n"
- "First, be sure your monitor is set to True Color (32-bit) in\n"
- "Start -> Control Panels -> Display -> Settings.\n"
- "\n"
- "Otherwise, this may be due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "ATI drivers are available at http://www.ati.com/\n"
- "nVidia drivers are available at http://www.nvidia.com/\n"
- "\n"
- "If you continue to receive this message, contact customer service.",
- title,
- OSMB_OK);
- */
-}
-
-BOOL check_for_card(const char* RENDERER, const char* bad_card)
-{
- if(bad_card == NULL)
- {
- return FALSE;
- }
- if (!strnicmp(RENDERER, bad_card, strlen(bad_card))) /* Flawfinder: ignore */
- {
- char buffer[1024]; /* Flawfinder: ignore */
- snprintf(buffer, sizeof(buffer), /* Flawfinder: ignore */
- "Your video card appears to be a %s, which Second Life does not support.\n"
- "\n"
- "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
- "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
- "and ATI Radeon 8500 or better.\n"
- "\n"
- "If you own a supported card and continue to receive this message, try \n"
- "updating to the latest video card drivers. Otherwise look in the\n"
- "secondlife.com support section or e-mail technical support\n"
- "\n"
- "You can try to run Second Life, but it will probably crash or run\n"
- "very slowly. Try anyway?",
- bad_card);
- S32 button = OSMessageBox(buffer, "Unsupported video card", OSMB_YESNO);
- if (OSBTN_YES == button)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
- }
-
- return FALSE;
}
//static
@@ -132,6 +77,7 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
BOOL ignore_pixel_depth)
: LLWindow(fullscreen, flags)
{
+ S32 i = 0;
mIconResource = gIconResource;
mOverrideAspectRatio = 0.f;
mNativeAspectRatio = 0.f;
@@ -500,37 +446,6 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
return;
}
- // Check for some explicitly unsupported cards.
- const char* RENDERER = (const char*) glGetString(GL_RENDERER);
-
- const char* CARD_LIST[] =
- { "RAGE 128",
- "RIVA TNT2",
- "Intel 810",
- "3Dfx/Voodoo3",
- "Radeon 7000",
- "Radeon 7200",
- "Radeon 7500",
- "Radeon DDR",
- "Radeon VE",
- "GDI Generic" };
- const S32 CARD_COUNT = sizeof(CARD_LIST)/sizeof(char*);
-
- // Future candidates:
- // ProSavage/Twister
- // SuperSavage
-
- S32 i;
- for (i = 0; i < CARD_COUNT; i++)
- {
- if (check_for_card(RENDERER, CARD_LIST[i]))
- {
- close();
- shell_open( "help/unsupported_card.html" );
- return;
- }
- }
-
gGLManager.initWGL();
if (gGLManager.mHasWGLARBPixelFormat && (wglChoosePixelFormatARB != NULL))
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 0b6fd5157a..ba944ca900 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -182,6 +182,7 @@ private:
};
extern LLW32MsgCallback gAsyncMsgCallback;
+extern LPWSTR gIconResource;
static void handleMessage( const MSG& msg );
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index da6302b27c..2af28f7d2c 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -113,7 +113,8 @@ void LLControlGroup::cleanup()
LLControlBase* LLControlGroup::getControl(const LLString& name)
{
- return mNameTable[name];
+ ctrl_name_table_t::iterator iter = mNameTable.find(name);
+ return iter == mNameTable.end() ? NULL : (LLControlBase*)iter->second;
}
BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist)
@@ -124,9 +125,11 @@ BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, con
LLControl* control = new LLControl(name, type, initial_val, comment, persist);
mNameTable[name] = control;
return TRUE;
- } else
+ }
+ else
{
llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl;
+ mNameTable.erase(name);
return FALSE;
}
}
@@ -188,7 +191,7 @@ BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial
LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener)
{
- LLControlBase *control = mNameTable[name];
+ LLControlBase *control = getControl(name);
if (control)
{
return control->registerListener(listener);
@@ -198,7 +201,7 @@ LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObse
BOOL LLControlGroup::getBOOL(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_BOOLEAN))
return control->get().asBoolean();
@@ -211,7 +214,7 @@ BOOL LLControlGroup::getBOOL(const LLString& name)
S32 LLControlGroup::getS32(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_S32))
return control->get().asInteger();
@@ -224,7 +227,7 @@ S32 LLControlGroup::getS32(const LLString& name)
U32 LLControlGroup::getU32(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_U32))
return control->get().asInteger();
@@ -237,7 +240,7 @@ U32 LLControlGroup::getU32(const LLString& name)
F32 LLControlGroup::getF32(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_F32))
return (F32) control->get().asReal();
@@ -250,7 +253,7 @@ F32 LLControlGroup::getF32(const LLString& name)
LLString LLControlGroup::findString(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_STRING))
return control->get().asString();
@@ -259,7 +262,7 @@ LLString LLControlGroup::findString(const LLString& name)
LLString LLControlGroup::getString(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_STRING))
return control->get().asString();
@@ -285,7 +288,7 @@ LLString LLControlGroup::getText(const LLString& name)
LLVector3 LLControlGroup::getVector3(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_VEC3))
return control->get();
@@ -298,7 +301,7 @@ LLVector3 LLControlGroup::getVector3(const LLString& name)
LLVector3d LLControlGroup::getVector3d(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_VEC3D))
return control->get();
@@ -311,7 +314,7 @@ LLVector3d LLControlGroup::getVector3d(const LLString& name)
LLRect LLControlGroup::getRect(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_RECT))
return control->get();
@@ -357,7 +360,7 @@ LLColor4 LLControlGroup::getColor(const LLString& name)
LLColor4U LLControlGroup::getColor4U(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_COL4U))
return control->get();
@@ -370,7 +373,7 @@ LLColor4U LLControlGroup::getColor4U(const LLString& name)
LLColor4 LLControlGroup::getColor4(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_COL4))
return control->get();
@@ -383,7 +386,7 @@ LLColor4 LLControlGroup::getColor4(const LLString& name)
LLColor3 LLControlGroup::getColor3(const LLString& name)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_COL3))
return control->get();
@@ -396,9 +399,8 @@ LLColor3 LLControlGroup::getColor3(const LLString& name)
BOOL LLControlGroup::controlExists(const LLString& name)
{
- void *control = mNameTable[name];
-
- return (control != 0);
+ ctrl_name_table_t::iterator iter = mNameTable.find(name);
+ return iter != mNameTable.end();
}
//-------------------------------------------------------------------
@@ -407,7 +409,7 @@ BOOL LLControlGroup::controlExists(const LLString& name)
void LLControlGroup::setBOOL(const LLString& name, BOOL val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_BOOLEAN))
{
@@ -422,7 +424,7 @@ void LLControlGroup::setBOOL(const LLString& name, BOOL val)
void LLControlGroup::setS32(const LLString& name, S32 val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_S32))
{
@@ -437,7 +439,7 @@ void LLControlGroup::setS32(const LLString& name, S32 val)
void LLControlGroup::setF32(const LLString& name, F32 val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_F32))
{
@@ -452,7 +454,7 @@ void LLControlGroup::setF32(const LLString& name, F32 val)
void LLControlGroup::setU32(const LLString& name, U32 val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_U32))
{
@@ -467,7 +469,7 @@ void LLControlGroup::setU32(const LLString& name, U32 val)
void LLControlGroup::setString(const LLString& name, const LLString &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_STRING))
{
@@ -482,7 +484,7 @@ void LLControlGroup::setString(const LLString& name, const LLString &val)
void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_VEC3))
{
@@ -496,7 +498,7 @@ void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)
void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_VEC3D))
{
@@ -510,7 +512,7 @@ void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)
void LLControlGroup::setRect(const LLString& name, const LLRect &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_RECT))
{
@@ -524,7 +526,7 @@ void LLControlGroup::setRect(const LLString& name, const LLRect &val)
void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_COL4U))
{
@@ -538,7 +540,7 @@ void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)
void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val)
{
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control && control->isType(TYPE_COL4))
{
@@ -557,7 +559,7 @@ void LLControlGroup::setValue(const LLString& name, const LLSD& val)
return;
}
- LLControlBase* control = mNameTable[name];
+ LLControlBase* control = getControl(name);
if (control)
{
@@ -839,7 +841,7 @@ U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declarat
{
name = child_nodep->getName();
- BOOL declared = (mNameTable[name].notNull());
+ BOOL declared = controlExists(name);
if (require_declaration && !declared)
{
@@ -1026,8 +1028,7 @@ U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
break;
}
- LLControlBase* control = (LLControlBase *)mNameTable[name];
-
+ LLControlBase* control = (LLControlBase *)iter->second;
if (!control)
{
llwarns << "Tried to save invalid control: " << name << llendl;
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index ca8c1d176f..ae16a9d800 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -15,6 +15,7 @@
#include "indra_constants.h"
#include "llmemory.h"
+#include "llthread.h"
#include "llstring.h"
#include "llstringtable.h"
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
index b2a6d67621..c169fceb88 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
@@ -5,7 +5,7 @@ uniform sampler2D diffuseMap;
void default_lighting()
{
vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
- applyScatter(color.rgb);
+ //applyScatter(color.rgb);
gl_FragColor = color;
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
new file mode 100644
index 0000000000..12c99a6567
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
@@ -0,0 +1,13 @@
+void applyScatter(inout vec3 col);
+
+uniform samplerCube environmentMap;
+
+void main()
+{
+ vec3 ref = textureCube(environmentMap, gl_TexCoord[0].xyz).rgb;
+
+ applyScatter(ref);
+
+ gl_FragColor.rgb = ref;
+ gl_FragColor.a = gl_Color.a;
+}
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
new file mode 100644
index 0000000000..621ff6b5b7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
@@ -0,0 +1,27 @@
+void default_scatter(vec3 viewVec, vec3 lightDir);
+
+uniform vec4 origin;
+
+void main()
+{
+ //transform vertex
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ vec3 pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+ vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+
+ gl_FrontColor = gl_Color;
+
+ vec3 ref = reflect(pos, norm);
+
+ vec3 d = pos - origin.xyz;
+ float dist = dot(normalize(d), ref);
+ vec3 e = d + (ref * max(origin.w-dist, 0.0));
+
+ ref = e - origin.xyz;
+
+ gl_TexCoord[0] = gl_TextureMatrix[0]*vec4(ref,1.0);
+
+ default_scatter(pos.xyz, gl_LightSource[0].position.xyz);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
index 0ef1129253..6f732ed731 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
@@ -5,7 +5,7 @@ uniform sampler2D diffuseMap;
void default_lighting()
{
vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
- applyScatter(color.rgb);
+ //applyScatter(color.rgb);
gl_FragColor = color;
}
diff --git a/indra/newview/app_settings/viewerart.xml b/indra/newview/app_settings/viewerart.xml
index dbd22278a7..1ae2010002 100644
--- a/indra/newview/app_settings/viewerart.xml
+++ b/indra/newview/app_settings/viewerart.xml
@@ -1,282 +1,4 @@
<settings version = "101">
- <closebox.tga value="47a8c844-cd2a-4b1a-be01-df8b1612fe5d"/>
- <close_in_blue.tga value="e5821134-23c0-4bd0-af06-7fa95b9fb01a"/>
- <tearoffbox.tga value="74e1a96f-4833-a24d-a1bb-1bce1468b0e7"/>
- <tearoff_pressed.tga value="d2524c13-4ba6-af7c-e305-8ac6cc18d86a"/>
- <resize_handle_bottom_right_blue.tga value="e3690e25-9690-4f6c-a745-e7dcd885285a"/>
- <scrollbutton_up_out_blue.tga value="dad084d7-9a46-452a-b0ff-4b9f1cefdde9"/>
- <scrollbutton_up_in_blue.tga value="a93abdf3-27b5-4e22-a8fa-c48216cd2e3a"/>
- <scrollbutton_down_out_blue.tga value="b4ecdecf-5c8d-44e7-b882-17a77e88ed55"/>
- <scrollbutton_down_in_blue.tga value="d2421bab-2eaf-4863-b8f6-5e4c52519247"/>
- <scrollbutton_left_out_blue.tga value="43773e8d-49aa-48e0-80f3-a04715f4677a"/>
- <scrollbutton_left_in_blue.tga value="ea137a32-6718-4d05-9c22-7d570d27b2cd"/>
- <scrollbutton_right_out_blue.tga value="3d700d19-e708-465d-87f2-46c8c0ee7938"/>
- <scrollbutton_right_in_blue.tga value="b749de64-e903-4c3c-ac0b-25fb6fa39cb5"/>
- <spin_up_out_blue.tga value="56576e6e-6710-4e66-89f9-471b59122794"/>
- <spin_up_in_blue.tga value="c8450082-96a0-4319-8090-d3ff900b4954"/>
- <spin_down_out_blue.tga value="b6d240dd-5602-426f-b606-bbb49a30726d"/>
- <spin_down_in_blue.tga value="a985ac71-052f-48e6-9c33-d931c813ac92"/>
- <radio_active_false.tga value="7a1ba9b8-1047-4d1e-9cfc-bc478c80b63f"/>
- <radio_active_true.tga value="52f09e07-5816-4052-953c-94c6c10479b7"/>
- <radio_inactive_false.tga value="90688481-67ff-4af0-be69-4aa084bcad1e"/>
- <radio_inactive_true.tga value="1975db39-aa29-4251-aea0-409ac09d414d"/>
- <checkbox_enabled_false.tga value="05bb64ee-96fd-4243-b74e-f40a41bc53ba"/>
- <checkbox_enabled_true.tga value="cf4a2ed7-1533-4686-9dde-df9a37ddca55"/>
- <checkbox_disabled_false.tga value="7d94cb59-32a2-49bf-a516-9e5a2045f9d9"/>
- <checkbox_disabled_true.tga value="c817c642-9abd-4236-9287-ae0513fe7d2b"/>
- <tab_top_blue.tga value="1ed83f57-41cf-4052-a3b4-2e8bb78d8191"/>
- <tab_top_selected_blue.tga value="16d032e8-817b-4368-8a4e-b7b947ae3889"/>
- <tab_bottom_blue.tga value="bf0a8779-689b-48c3-bb9a-6af546366ef4"/>
- <tab_bottom_selected_blue.tga value="c001d8fd-a869-4b6f-86a1-fdcb106df9c7"/>
- <tab_left.tga value="1097dcb3-aef9-8152-f471-431d840ea89e"/>
- <tab_left_selected.tga value="bea77041-5835-1661-f298-47e2d32b7a70"/>
- <crosshairs.tga value="6e1a3980-bf2d-4274-8970-91e60d85fb52"/>
- <move_backward_in.tga value="db11d956-5e7d-4aa5-b39d-7774d339fc5c"/>
- <move_backward_out.tga value="3ae8bb18-ed97-4cd3-ae5c-d54bc8479fe7"/>
- <move_down_in.tga value="b92a70b9-c841-4c94-b4b3-cee9eb460d48"/>
- <move_down_out.tga value="b5abc9fa-9e62-4e03-bc33-82c4c1b6b689"/>
- <move_forward_in.tga value="54197a61-f5d1-4c29-95d2-c071d08849cb"/>
- <move_forward_out.tga value="a0eb4021-1b20-4a53-892d-8faa9265a6f5"/>
- <move_left_in.tga value="724996f5-b956-46f6-9844-4fcfce1d5e83"/>
- <move_left_out.tga value="82476321-0374-4c26-9567-521535ab4cd7"/>
- <move_right_in.tga value="7eeb57d2-3f37-454d-a729-8b217b8be443"/>
- <move_right_out.tga value="1fbe4e60-0607-44d1-a50a-032eff56ae75"/>
- <move_turn_left_in.tga value="95463c78-aaa6-464d-892d-3a805b6bb7bf"/>
- <move_turn_left_out.tga value="13a93910-6b44-45eb-ad3a-4d1324c59bac"/>
- <move_turn_right_in.tga value="5e616d0d-4335-476f-9977-560bccd009da"/>
- <move_turn_right_out.tga value="5a44fd04-f52b-4c30-8b00-4a31e27614bd"/>
- <move_up_out.tga value="f887146d-829f-4e39-9211-cf872b78f97c"/>
- <move_up_in.tga value="49b4b357-e430-4b56-b9e0-05b8759c3c82"/>
- <cam_rotate_out.tga value="88745b46-da05-11d5-8ac0-0003477c4611"/>
- <cam_rotate_in.tga value="70bf2262-3eed-4996-88ac-076907e8921d"/>
- <cam_zoom_out.tga value="bb02e941-cb3b-4dd3-892a-6841b5de6e45"/>
- <cam_zoom_plus_in.tga value="c7aefd32-ce13-4242-82cc-2631d44ff9d3"/>
- <cam_zoom_minus_in.tga value="deed3f4b-93e9-4183-a3b0-a5a98a6de1bb"/>
- <cam_tracking_out.tga value="95c4ea0e-e3c2-4904-b847-7d7676139ebb"/>
- <cam_tracking_in.tga value="fe2fc73b-5a64-4a8e-aacc-46fa81faf96a"/>
- <direction_arrow.tga value="586383e8-4d9b-4fba-9196-2b5938e79c2c"/>
- <minimize.tga value="34c9398d-bb78-4643-9633-46a2fa3e9637"/>
- <minimize_inactive.tga value="6e72abba-1378-437f-bf7a-f0c15f3e99a3"/>
- <minimize_pressed.tga value="39801651-26cb-4926-af57-7af9352c273c"/>
- <restore.tga value="111b39de-8928-4690-b7b2-e17d5c960277"/>
- <restore_inactive.tga value="0eafa471-70af-4882-b8c1-40a310929744"/>
- <restore_pressed.tga value="90a0ed5c-2e7b-4845-9958-a64a1b30f312"/>
- <combobox_arrow.tga value="b31c1335-0e9c-4927-bc90-53277777d9c1"/>
- <white.tga value="5748decc-f629-461c-9a36-a35a221fe21f"/>
- <darkgray.tga value="267e26d3-e0e1-41b8-91b1-3b337102928d"/>
- <lightgray.tga value="c520bf46-cc5d-412b-a60b-9f1bd245189f"/>
- <eyes.tga value="6522e74d-1660-4e7f-b601-6f48c1659a77"/>
- <hair.tga value="7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"/>
- <black.tga value="e2244626-f22f-4839-8123-1e7baddeb659"/>
- <close_inactive_blue.tga value="779e4fa3-9b13-f74a-fba9-3886fe9c86ba"/>
- <button_disabled_32x128.tga value="f8124d60-2875-c358-7847-2acb63e5400c"/>
- <button_enabled_32x128.tga value="d8faf8cb-ee6e-b0b5-abd9-bde873ad3461"/>
- <button_enabled_selected_32x128.tga value="1eddba75-b682-110a-104e-6cdcce616a25"/>
- <button_anim_play_selected.tga value="119c37bb-24af-45fe-ae11-3a6bc3c85138"/>
- <button_anim_pause_selected.tga value="ad65d67a-777b-fbfa-693d-4bdcfca2acca"/>
- <button_anim_pause.tga value="db2d9c2d-0bbd-21e2-e83a-103ea2def7a8"/>
- <button_anim_play.tga value="2a7f6738-5d82-2ff3-d419-30ed09cbb72b"/>
- <button_anim_stop.tga value="e10c9e36-d9f6-c8b4-de96-557dccce9205"/>
- <button_anim_stop_selected.tga value="b8c0e0aa-2771-439e-c919-d2f5dad69a1c"/>
- <rounded_square.tga value="38ce8b3c-fb30-5c59-9926-bd643613f606"/>
- <rounded_square_soft.tga value="4c95e6bc-fe77-9cb4-b58a-909848042c1e"/>
- <badge_ok.tga value="211035a7-c313-378d-478c-e80bbd0fde63"/>
- <badge_note.tga value="13f6e639-b3f9-28da-a1e6-e990a43052b6"/>
- <badge_warn.tga value="0992d4bc-7af8-4a1f-f2e6-e6c4083b066e"/>
- <badge_error.tga value="00c50485-8491-ab70-2ea8-43f26fd028e2"/>
- <status_money.tga value="5863eb7a-1546-6501-533a-6061f73a36b7"/>
- <status_health.tga value="4330e8ce-b39b-1eb8-c2ec-a97c0b3947b5"/>
- <status_fly.tga value="0e058115-5b8f-c3d7-dcaa-9623d92885d1"/>
- <status_build.tga value="175a6b75-45c9-c2c2-4765-bf37a3909b53"/>
- <status_busy.tga value="beb0d821-6725-abdf-032d-1f70cdabde82"/>
- <status_scripts.tga value="4cc1afcd-04dd-178f-e074-0f9dc730ab45"/>
- <status_buy_currency.tga value="f43a535a-59ac-26e3-84bc-c786735fabe4"/>
- <status_buy_currency_pressed.tga value="bfa5be70-37c7-8126-fecd-df55390954d5"/>
- <status_buy_land.tga value="1a0edac5-3e50-fc9b-2752-70c1f69cb959"/>
- <status_buy_land_pressed.tga value="257647b7-199f-99ff-8be9-f6753289a3aa"/>
- <terrain_dirt.tga value="b8d3965a-ad78-bf43-699b-bff8eca6c975"/>
- <terrain_grass.tga value="abb783e6-3e93-26c0-248a-247666855da3"/>
- <terrain_mountain.tga value="179cdabd-398a-9b6b-1391-4dc333ba321f"/>
- <terrain_rock.tga value="beb169c7-11ea-fff2-efe5-0f24dc881df2"/>
- <terrain_dirt_detail.tga value="0bc58228-74a0-7e83-89bc-5c23464bcec5"/>
- <terrain_grass_detail.tga value="63338ede-0037-c4fd-855b-015d77112fc8"/>
- <terrain_mountain_detail.tga value="303cd381-8560-7579-23f1-f0a880799740"/>
- <terrain_rock_detail.tga value="53a2f406-4895-1d13-d541-d2e3b86bc19c"/>
- <square_btn_32x128.tga value="b28df901-6b8d-d31c-7903-4eb9676d4bfc"/>
- <square_btn_selected_32x128.tga value="c48c9e95-191b-96d3-08b2-6e8ada58b651"/>
- <tree_pine_1.tga value="0187babf-6c0d-5891-ebed-4ecab1426683"/>
- <tree_oak.tga value="8a515889-eac9-fb55-8eba-d2dc09eb32c8"/>
- <tree_tropical_1.tga value="5bc11cd6-2f40-071e-a8da-0903394204f9"/>
- <tree_palm_1.tga value="ca4e8c27-473c-eb1c-2f5d-50ee3f07d85c"/>
- <tree_dogwood.tga value="64367bd1-697e-b3e6-0b65-3f862a577366"/>
- <tree_tropical_2.tga value="cdd9a9fc-6d0b-f90d-8416-c72b6019bca8"/>
- <tree_palm_2.tga value="2d784476-d0db-9979-0cff-9408745a7cf3"/>
- <tree_cypress_1.tga value="fb2ae204-3fd1-df33-594f-c9f882830e66"/>
- <tree_cypress_2.tga value="30047cec-269d-408e-0c30-b2603b887268"/>
- <tree_pine_2.tga value="d691a01c-13b7-578d-57c0-5caef0b4e7e1"/>
- <tree_plumeria.tga value="6de37e4e-7029-61f5-54b8-f5e63f983f58"/>
- <winter_tree_aspen.tga value="7c0cf89b-44b1-1ce2-dd74-07102a98ac2a"/>
- <winter_tree_pine_1.tga value="10d2a01a-0818-84b9-4b96-c2eb63256519"/>
- <winter_tree_pine_2.tga value="67931331-0c02-4876-1255-28770896c6a2"/>
- <tree_eucalyptus.tga value="a6162133-724b-54df-a12f-51cd070ad6f3"/>
- <tree_fern.tga value="8872f2b8-31db-42d8-580a-b3e4a91262de"/>
- <tree_eelgrass.tga value="96b4de31-f4fa-337d-ec78-451e3609769e"/>
- <tree_sea_sword.tga value="5894e2e7-ab8d-edfa-e61c-18cf16854ba3"/>
- <tree_kelp_1.tga value="2caf1179-7861-6ff3-4b7d-46e17780bdfa"/>
- <tree_kelp_2.tga value="2a4880b6-b7a3-690a-2049-bfbe38eafb9f"/>
- <tree_beach_grass_1.tga value="18fb888b-e8f1-dce7-7da7-321d651ea6b0"/>
- <tool_dozer.tga value="d2a0d4d4-54eb-4d16-be4b-4eae43845c74"/>
- <tool_dozer_active.tga value="d4afdbbe-1550-4b7d-91de-95731f47e8e3"/>
- <tool_land.tga value="86fe4df4-0ecb-4382-b9ae-475925a92388"/>
- <tool_land_active.tga value="34e60587-0791-4a07-8918-f5995fcc22a3"/>
- <tool_zoom.tga value="27eb8829-fe65-45ed-a49a-73aac42f4b38"/>
- <tool_zoom_active.tga value="69445f58-5c8e-44e0-9d2e-47408bb43b39"/>
- <tool_orbit.tga value="06964fe4-033f-448a-95c9-30dc41d1be8b"/>
- <tool_orbit_active.tga value="ee4e07db-3f72-4098-bd4c-aef34515a7bc"/>
- <tool_pan.tga value="a32aa302-0a15-48d2-b2b1-4d69f1161173"/>
- <tool_pan_active.tga value="24d9ad33-0b42-4eb5-99a3-659d838bc5c0"/>
- <inv_folder_texture.tga value="743f035b-a049-43f4-16c7-7ec8daa2c481"/>
- <inv_folder_sound.tga value="e10cb910-1e71-da47-bd12-8c53f7793714"/>
- <inv_folder_callingcard.tga value="a3735971-e2b2-d78a-580d-d265cd8f2484"/>
- <inv_folder_landmark.tga value="9f921155-7c8c-e276-d5ec-03ac9340584d"/>
- <inv_folder_script.tga value="baa5c310-6a6d-cc48-51eb-65196ba31d77"/>
- <inv_folder_object.tga value="113e5133-fd0d-ee51-4a59-9d67ca10e8a7"/>
- <inv_folder_notecard.tga value="a9e75d84-5073-9cb7-10a9-1ca68ef5c7ba"/>
- <inv_folder_clothing.tga value="f1427d3d-b2e8-97c4-69ab-1f36d4c0e8f0"/>
- <inv_folder_bodypart.tga value="1fe05580-1d2f-0345-b28b-52b6e3a20e5d"/>
- <inv_folder_trash.tga value="88ad072e-ea0b-aabd-5ac0-b37862a6eb66"/>
- <inv_folder_plain_closed.tga value="86f00960-c3e9-9680-145d-3beffd743e9c"/>
- <inv_folder_plain_open.tga value="d15dc243-2d0b-47af-0ce1-ec376464bdc8"/>
- <inv_folder_snapshot.tga value="6efe85e7-800f-1843-296c-a5b7adffe091"/>
- <inv_folder_lostandfound.tga value="9a371a04-297d-bacf-0d16-5f49753efe1d"/>
- <inv_folder_animation.tga value="4d59b3ee-f29d-b912-2bcc-9bb1f8a07ec6"/>
- <inv_folder_gesture.tga value="4de9129a-9fc1-d759-d739-364293906ba2"/>
- <inv_item_texture.tga value="19f452d7-4eee-9f46-76cc-5497d17f1dd9"/>
- <inv_item_sound.tga value="eb414d69-c77d-d4e7-66e6-6c2e6f6c1976"/>
- <inv_item_callingcard_online.tga value="672cc53e-8dc0-ba91-2a4e-574104cf071c"/>
- <inv_item_callingcard_offline.tga value="d0afe86b-2489-7600-55b7-6abb0a63d9f9"/>
- <inv_item_landmark.tga value="bf25a2a0-85da-7fa0-0993-e461768d0221"/>
- <inv_item_landmark_visited.tga value="229fac85-5428-4ab7-adeb-eb8389e91092"/>
- <inv_item_script.tga value="59a3df81-ed76-06c9-7264-6dada535e7a3"/>
- <inv_item_clothing.tga value="34dfe476-8e26-0e3a-11cf-76cc4a7126ce"/>
- <inv_item_object.tga value="0f0780a0-89c4-742a-ef28-26405a41cf85"/>
- <inv_item_notecard.tga value="23ce8a2c-9ea2-d863-6572-806f0645b0c7"/>
- <inv_item_bodypart.tga value="d2a5362d-5c55-57dd-a9e9-5c814d1ddc16"/>
- <inv_item_attach.tga value="5bcae41e-aa5d-02f8-edf1-605ebdd875ab"/>
- <inv_item_snapshot.tga value="3810d584-b092-7caa-57e0-010f192b9659"/>
- <inv_item_eyes.tga value="eaa5fd96-5c25-06ef-2280-7ef20203e167"/>
- <inv_item_gloves.tga value="117b11cb-c04e-5081-13da-1a8846070fd0"/>
- <inv_item_hair.tga value="6bca3bf4-ed6d-d438-63a0-2a7066d03a0b"/>
- <inv_item_jacket.tga value="8df59386-56e0-c811-0443-840da3acb3a5"/>
- <inv_item_pants.tga value="a87a58ca-f857-63b1-0acf-072711ed1bdb"/>
- <inv_item_shape.tga value="4463e433-4db5-79ef-c1b0-4821b03ddb07"/>
- <inv_item_shirt.tga value="e2ffb62b-6abc-22d6-952d-764759b4d636"/>
- <inv_item_shoes.tga value="cf384fa5-1edd-c37c-2134-283dd4fe3396"/>
- <inv_item_skirt.tga value="0b43f826-2abc-2944-7d72-10777a51d19b"/>
- <inv_item_socks.tga value="22137c6d-6ec5-6eee-9a2e-2d7a9e6cbcd4"/>
- <inv_item_underpants.tga value="2f15dc09-4385-526c-aa5d-d9d516ec7d99"/>
- <inv_item_undershirt.tga value="f72ab629-a3ab-de0c-35c0-5285e27478ce"/>
- <inv_item_animation.tga value="b5cda0d6-d196-ce48-63db-d04323ef8931"/>
- <inv_item_gesture.tga value="5579245d-d5bf-5f13-46b0-8624490de24c"/>
- <pixiesmall.tga value="168e6813-096e-07ea-97ae-fd416826f627"/>
- <legend.tga value="ca7609c6-6ec6-32d9-332e-0d8f437ef644"/>
- <propertyline.tga value="e3548c46-8d5e-03da-fcab-4fc36ad818bb"/>
- <startup_logo.tga value="66864f3c-e095-d9c8-058d-d6575e6ed1b8"/>
- <grass_texture_1.tga value="79504bf5-c3ec-0763-6563-d843de66d0a1"/>
- <grass_texture_2.tga value="6c4727b8-ac79-ba44-3b81-f9aa887b47eb"/>
- <grass_texture_3.tga value="99bd60a2-3250-efc9-2e39-2fbcadefbecc"/>
- <grass_texture_4.tga value="7a2b3a4a-53c2-53ac-5716-aac7d743c020"/>
- <undergrowth_1.tga value="8f458549-173b-23ff-d4ff-bfaa5ea2371b"/>
- <silhouette.tga value="da5d4079-7819-6b53-d2a4-dc9929381d7d"/>
- <avatar_thumb_bkgrnd.tga value="3a7f4f0d-be14-ee78-29e3-fc8b0b2a68d3"/>
- <missing_asset.tga value="32dfd1c8-7ff6-5909-d983-6d4adfb4255d"/>
- <alpha_gradient.tga value="e97cf410-8e61-7005-ec06-629eba4cd1fb"/>
- <alpha_gradient_2d.tga value="38b86f85-2575-52a9-a531-23108d8da837"/>
- <alpha_noise.tga value="b9e1cf8a-9660-c020-0c69-18f1ea27268a"/>
- <alpha_sizzle.tga value="e121e2fc-7573-740f-edfd-0d45a9ba486e"/>
- <bump_woodgrain.tga value="058c75c0-a0d5-f2f8-43f3-e9699a89c2fc"/>
- <bump_bark.tga value="6c9fa78a-1c69-2168-325b-3e03ffa348ce"/>
- <bump_bricks.tga value="b8eed5f0-64b7-6e12-b67f-43fa8e773440"/>
- <bump_checker.tga value="9deab416-9c63-78d6-d558-9a156f12044c"/>
- <bump_concrete.tga value="db9d39ec-a896-c287-1ced-64566217021e"/>
- <bump_crustytile.tga value="f2d7b6f6-4200-1e9a-fd5b-96459e950f94"/>
- <bump_cutstone.tga value="d9258671-868f-7511-c321-7baef9e948a4"/>
- <bump_discs.tga value="d21e44ca-ff1c-a96e-b2ef-c0753426b7d9"/>
- <bump_gravel.tga value="4726f13e-bd07-f2fb-feb0-bfa2ac58ab61"/>
- <bump_petridish.tga value="e569711a-27c2-aad4-9246-0c910239a179"/>
- <bump_siding.tga value="073c9723-540c-5449-cdd4-0e87fdc159e3"/>
- <bump_stonetile.tga value="ae874d1a-93ef-54fb-5fd3-eb0cb156afc0"/>
- <bump_stucco.tga value="92e66e00-f56f-598a-7997-048aa64cde18"/>
- <bump_suction.tga value="83b77fc6-10b4-63ec-4de7-f40629f238c5"/>
- <bump_weave.tga value="735198cf-6ea0-2550-e222-21d3c6a341ae"/>
- <icon_avatar_online.tga value="529ed15b-3d41-dcc1-79de-90bf21770b5b"/>
- <icon_avatar_offline.tga value="34648c67-5bfb-5790-e05e-8bd6600fd087"/>
- <icon_event.tga value="be235ae0-53cf-1d68-b3ae-cf375ed1fb58"/>
- <icon_event_mature.tga value="cc090999-1b3e-2e97-7a38-c9f4afd10297"/>
- <icon_group.tga value="04237108-a879-5a95-9b0c-b18fd09bc447"/>
- <icon_place.tga value="ba0bac4e-815e-14e1-2895-5065b8c703b3"/>
- <icon_top_pick.tga value="77ca91a2-4431-aeaf-6249-3dd99c7dd86d"/>
- <icon_popular.tga value="bdd47da5-5b5b-c906-37ad-16aaa64f096f"/>
- <icon_for_sale.tga value="f20728fd-1670-3771-2293-e0dd3f0bcaab"/>
- <icon_auction.tga value="96abf5b1-335c-6b76-61e3-74ada07f3cb8"/>
- <icon_land_for_landless.tga value="c421ddf2-b9d7-b373-503c-f4c423f37f1c"/>
- <icon_day_cycle.tga value="5b30a285-f1e3-92b1-dcd3-0d07366ced3e"/>
- <icon_lock.tga value="9beb8cdd-3dce-53c2-b28e-e1f3bc2ec0a4"/>
- <noentrylines.tga value="5d3e196b-fd4d-ada7-e4c1-99f8e9f1cfbf"/>
- <noentrypasslines.tga value="ac8f8627-6a30-8da8-d4bd-958668eea7a0"/>
- <notify_tip_icon.tga value="74ba3584-58ea-9984-5b76-62d37942ab77"/>
- <notify_box_icon.tga value="b2ef2d31-9714-a07b-6ca7-31638166364b"/>
- <notify_next.tga value="07d0ea4c-af0c-aad1-dbbf-c24020ff2b80"/>
- <map_avatar_you_8.tga value="02fbdc40-5e07-a6e1-228b-58e10f8335b7"/>
- <map_avatar_8.tga value="0be58a91-8065-c02b-7a12-2cc14dddbc37"/>
- <map_avatar_16.tga value="db0dadd5-026a-88cf-f5c1-523a0a2daa3e"/>
- <map_telehub.tga value="bf1b2bb0-13b1-40ae-3354-b1b93761bdb4"/>
- <map_infohub.tga value="85b1a79a-7f6c-9df3-4d6c-17b1a4efb55a"/>
- <map_home.tga value="ae9b8f5f-03a1-2e71-db77-6eb27a1ba181"/>
- <map_event.tga value="6008be5e-9267-2a3a-9798-e81b076c22ca"/>
- <map_event_mature.tga value="f9cdba28-a227-d613-2f16-ce06209314ae"/>
- <map_track_8.tga value="bfdc7bf6-e2ee-1754-f4df-cc25887714ad"/>
- <map_track_16.tga value="a3878395-ef00-a0e6-ee9a-f45ed6b9ce59"/>
- <object_cone.tga value="c2b8c90a-7dca-26e3-1a63-7aa4a0389cf9"/>
- <object_cone_active.tga value="cf69c64b-f19e-e1f3-a586-42fef31a23be"/>
- <object_cube.tga value="70c747ac-1de3-a8b9-514d-101753ca6ccb"/>
- <object_cube_active.tga value="f9c5e213-1076-7a7d-7889-52388aad2c1a"/>
- <object_cylinder.tga value="13e35d95-5f6c-9a91-1766-49dedf9b1267"/>
- <object_cylinder_active.tga value="3f3e4932-8412-e2a7-cfe9-92caf5978b1b"/>
- <object_grass.tga value="7ca8e672-920b-4653-3970-1abc91abef58"/>
- <object_grass_active.tga value="d0fc7cc9-646a-6860-cf7c-1d9e58cd6dab"/>
- <object_hemi_cone.tga value="69d5e60c-739a-40b1-b526-84072121e394"/>
- <object_hemi_cone_active.tga value="2e0c5435-95bb-1c0d-5da1-42336fb1cfc0"/>
- <object_hemi_cylinder.tga value="f4be3e06-24a8-f86e-acc7-7daefc0572b7"/>
- <object_hemi_cylinder_active.tga value="67279486-cfc1-3633-de42-85db65db373c"/>
- <object_hemi_sphere.tga value="b67251ab-1716-b9fb-f911-967ba3fe027b"/>
- <object_hemi_sphere_active.tga value="6c489466-3058-6475-6b1b-e5fc1d49f1f3"/>
- <object_pyramid.tga value="9dde8b56-2cc4-a932-b63a-38c3a83221ad"/>
- <object_pyramid_active.tga value="e7217b1a-e3d8-e339-d28a-d7714d0b5bee"/>
- <object_sphere.tga value="7fa122c0-b994-460e-8636-cdc451d67268"/>
- <object_sphere_active.tga value="f2c3bcbc-2904-41a5-1c22-688f176fd1ee"/>
- <object_tetrahedron.tga value="e17db404-9fc5-9534-1038-777c82b2771f"/>
- <object_tetrahedron_active.tga value="2792ea3b-c052-85fe-d168-a62b2f4e9d7c"/>
- <object_tree.tga value="710d1bec-fb33-28f1-e77e-ddbb5b51f5ed"/>
- <object_tree_active.tga value="da4835c7-b12a-41dd-11db-dae452f040c2"/>
- <object_prism.tga value="02935f3a-dcda-3b42-1874-da89d4c12870"/>
- <object_prism_active.tga value="223aac97-bd2f-ec2e-ad45-5641b77c78f9"/>
- <object_torus.tga value="19e1f4c9-6aa6-4414-981d-59a1343a6472"/>
- <object_torus_active.tga value="ef2bca77-5004-4547-b00a-3b96e463f89f"/>
- <object_tube.tga value="7ce81316-a478-480f-961c-435fcbdecaf0"/>
- <object_tube_active.tga value="55c3e4d1-cfdc-48a8-af32-a34844b91832"/>
- <object_ring_active.tga value="2c955a73-fa31-237b-a4a1-5c8ede3bae50"/>
- <object_ring.tga value="a7610e41-4647-16d8-0e0e-85a1211c1596"/>
- <container_animation.tga value="c4e657a1-4c86-0159-2da0-32ff948484e6"/>
- <container_bodypart.tga value="770cb2df-758d-34d5-36c7-e3de06db5b5d"/>
- <container_clothing.tga value="dd90406f-4c8f-a3f9-41df-d562f94f09e0"/>
- <container_gesture.tga value="59cd31c0-2791-3c48-f740-f0a36c68653e"/>
- <container_landmark.tga value="24c63386-04f7-ce6f-4ff2-dfb215d2e21f"/>
- <container_many_things.tga value="849d3292-d9fa-7186-5465-dd7b5fc1ec48"/>
- <container_object.tga value="ad887ae1-2bee-f2c9-6786-5599de3c95c4"/>
- <container_script.tga value="b93bd494-c4bd-bcdf-4a59-35a9497d03f3"/>
- <container_sound.tga value="5ddea031-cfa3-2776-43e3-c7146c1b4cd6"/>
- <container_texture.tga value="b3f95caf-bd62-bef3-0ded-dea752920629"/>
<avatar_aim_l_bow.bvh value="46bb4359-de38-4ed8-6a22-f1f52fe8f506"/>
<avatar_aim_r_bazooka.bvh value="b5b4a67d-0aee-30d2-72cd-77b333e932ef"/>
<avatar_aim_r_handgun.bvh value="3147d815-6338-b932-f011-16b56d9ac18b"/>
@@ -391,114 +113,4 @@
<avatar_yes_happy.bvh value="b8c8b2a3-9008-1771-3bfc-90924955ab2d"/>
<avatar_yes_head.bvh value="15dd911d-be82-2856-26db-27659b142875"/>
<avatar_yoga_float.bvh value="42ecd00b-9947-a97c-400a-bbc9174c7aeb"/>
- <fringe.tga value="8ac54e9d-ec09-d804-60ab-47404a9b4a36"/>
- <foot_shadow.tga value="14e8a47d-1055-0a68-5d55-eafd9ad3da5b"/>
- <img_smoke_poof.tga value="c734da52-f2ba-f0ba-d59e-15ea49f3d5e9"/>
- <img_shot.tga value="173b05c7-53a9-4cf8-ce6b-5eec21c5c63f"/>
- <folder_arrow.tga value="09a324a8-acc1-d9cd-2cbd-7465d90d3a98"/>
- <color_swatch_alpha.tga value="f13db22f-c55c-8bdf-7b1c-221e56fde253"/>
- <script_error.tga value="e5a0ec29-f59e-d29e-2c59-ed66c187c26c"/>
- <status_script_debug.tga value="7775b5cc-93a5-6efd-0d9b-4e079afac217"/>
- <water_normal.tga value="822ded49-9a6c-f61c-cb89-6df54f42cdf4"/>
- <icon_groupnotice.tga value="21579c81-a85e-f11c-2d80-33a4c007d88c"/>
- <icon_groupnoticeinventory.tga value="8fcca699-08e7-3d58-2f05-86c9d52bbe82"/>
- <tab_background_lightgrey.tga value="c769e547-c307-43ca-2b6a-51cad6d1c527"/>
- <tab_background_purple.tga value="0ae8a2e9-aff4-249c-fc4a-0f41f89847dd"/>
- <tab_background_darkpurple.tga value="38ff4f7e-3078-a749-8302-d6cc94b404c4"/>
- <smicon_warn.tga value="f47c17a3-8bfb-3c9f-22b8-77923de7eed9"/>
- <uv_test1.tga value="f43b75f5-9aa5-18ec-d5d9-e6d1b8442613"/>
- <uv_test2.tga value="300ce95f-3d3f-7c1a-3a22-3fc48f873fb9"/>
- <eye_button_active.tga value="2b42b375-f9b4-788e-46c7-7ef38762d0ba"/>
- <eye_button_inactive.tga value="be1b7225-98b5-eb2a-2c86-ddaae3328a6e"/>
- <account_id_blue.tga value="6ab9179a-7308-58db-6c9d-893d3b52bece"/>
- <account_id_orange.tga value="fbe89371-1251-4e77-d2d8-8eeccffe3ca8"/>
- <account_id_green.tga value="3bf64d5a-38d3-b752-cf52-3d9f8fca353a"/>
- <status_push.tga value="07d1f523-e327-4d10-20d6-8bc22a6e8f56"/>
- <ff_visible_online.tga value="d609a41f-34c0-7aae-b2c6-2fc3ab26d916"/>
- <ff_visible_map.tga value="20b52706-c1ab-414a-9dea-1cb788ad5689"/>
- <ff_edit_mine.tga value="1baee0b9-4b89-39eb-8815-866d82300ab5"/>
- <ff_edit_theirs.tga value="32e981cd-4700-da5a-7fc7-d573ec3742f4"/>
- <inv_item_script_dangerous.tga value="0b502db8-6fcd-c442-ecfe-483a0dce875e"/>
- <ff_visible_map_button.tga value="c1079bef-5cf9-90f3-6dcd-48989851c252"/>
- <ff_visible_online_button.tga value="36749b47-93d6-2c5e-7ebd-d38d30311163"/>
- <ff_edit_theirs_button.tga value="ca229f65-d7e0-133e-1bc2-674abc33f3d5"/>
- <ff_edit_mine_button.tga value="57f05b46-63d8-c3d5-66d6-8b915746b956"/>
- <ff_online_status_button.tga value="3b1b6a53-9c8c-568a-22c5-2a8f3e5286f5"/>
- <oi_hud_cen_0_0.tga value="3c650257-9caf-7cad-b26c-84c9eca560f1"/>
- <oi_hud_intro.tga value="7611fb3d-9ff2-abd3-d98f-805c1c87e757"/>
- <oi_hud_underwater.tga value="cde61aea-83c2-3001-d598-6b348f7a8e0b"/>
- <oi_hud_got_passport.tga value="1271838d-d777-b811-7c4c-2a00308bd80a"/>
- <oi_hud_texture_off_edge.tga value="852be205-b1ea-6356-58c8-8c5ee5a841a6"/>
- <oi_hud_texture_on_edge.tga value="ab11e6ff-a732-be70-67df-c43131274562"/>
- <oi_hud_flyingabovewater.tga value="c9d150d6-2739-5f8b-cce6-3cf98242920a"/>
- <oi_hud_walkingabovewater.tga value="78284eeb-05f3-ff25-11a0-3cc9dbb30f0c"/>
- <oi_hud_landmark.tga value="6cd9c221-9d42-a283-256b-09a113a87271"/>
- <oi_hud_cus_5_3.tga value="7c12f4fb-f502-26d1-a2f3-cdb6aff61663"/>
- <oi_hud_cus_5_2.tga value="c52c9c94-adc0-0f4e-6658-ed33d6ea8829"/>
- <oi_hud_cus_5_1.tga value="9f6d5d11-6ca9-608c-e8a6-b77989350292"/>
- <oi_hud_cus_5_0.tga value="2000cff1-119f-2023-66c0-ac5630d2f96e"/>
- <oi_hud_cus_4_5.tga value="f302a935-ccd1-e2f5-3a38-e185cc262f3a"/>
- <oi_hud_cus_4_3.tga value="af8d5b3c-b40f-cea5-b0b2-440fbd84a11a"/>
- <oi_hud_cus_4_2.tga value="11b26901-8207-12bc-5224-10a12ac4c651"/>
- <oi_hud_cus_4_1.tga value="41baadb7-1b94-907e-9443-54e92bba77cd"/>
- <oi_hud_cus_4_0.tga value="9d627f8e-092c-5d32-6c12-ef76ab81cedc"/>
- <oi_hud_cus_3_4.tga value="b196486e-d0d2-4fd7-529a-c84b4495fc74"/>
- <oi_hud_cus_3_2.tga value="0b81c4bb-de33-e493-7bcb-e7221d97e5e7"/>
- <oi_hud_cus_3_1.tga value="436dab74-25ae-8b60-c648-50663b7faa1d"/>
- <oi_hud_cus_3_0.tga value="6c1594de-1e66-273c-a2ab-8f0ffa8b4633"/>
- <oi_hud_cus_2_4.tga value="bb31fe48-8566-eec0-e96b-64025f832b63"/>
- <oi_hud_cus_2_2.tga value="c946959a-26ae-eb66-efa0-20154057789d"/>
- <oi_hud_cus_2_1.tga value="c946959a-26ae-eb66-efa0-20154057789d"/>
- <oi_hud_cus_2_0.tga value="d7833106-b4a8-7666-bde1-64886de289f9"/>
- <oi_hud_cus_1_0.tga value="811ded22-5940-940c-4821-6fbbfb6611d6"/>
- <oi_hud_cus_1_1.tga value="eda8513b-a343-5109-1fd6-f1c7ad89b703"/>
- <oi_hud_cus_1_2.tga value="7a4ce18c-e715-34d4-dfee-704c270a8ac8"/>
- <oi_hud_cus_1_4.tga value="d3771c15-ac03-b762-b992-d9fd2fedf38a"/>
- <oi_hud_com_4_4.tga value="d9e1e90d-3cc3-6269-128e-67f7a2b32d26"/>
- <oi_hud_com_4_2.tga value="0f649a26-6fdb-c73b-ffac-e50fc311d5ce"/>
- <oi_hud_com_4_1.tga value="ae5b1ce6-a2d2-22d2-f532-6280b3bc6adb"/>
- <oi_hud_com_4_0.tga value="12cda3a0-58c7-dfa8-7f9b-380e5bb8baf9"/>
- <oi_hud_com_3_4.tga value="ff326257-0530-356a-e0f8-be535044e540"/>
- <oi_hud_com_3_2.tga value="66740ddb-1d56-89f9-f0c9-ae5eb7bb9537"/>
- <oi_hud_com_3_1.tga value="55d662f4-6a28-6388-7c75-af1c9fd33055"/>
- <oi_hud_com_3_0.tga value="de9d318f-b69e-82f9-0c61-43b868c5ca6b"/>
- <oi_hud_com_2_4.tga value="01d47e68-400a-d0e1-afb7-d6806d1d477e"/>
- <oi_hud_com_2_0.tga value="09c98850-27d4-6a12-abae-4af4bba23b6b"/>
- <oi_hud_com_1_3.tga value="5c2049b9-f797-6608-ca71-758f3716aa90"/>
- <oi_hud_com_1_1.tga value="1116ff68-cdc4-1cfc-e137-30f8426afeda"/>
- <oi_hud_com_1_0.tga value="bd847d31-f5af-95f7-2b9c-af47d8ba53bd"/>
- <oi_hud_nav_4_5.tga value="66194280-b087-db94-35d9-41e8f7518515"/>
- <oi_hud_nav_4_4.tga value="180c4241-e309-4c05-13ee-9080ab69498d"/>
- <oi_hud_nav_4_3.tga value="e98a6ba6-99c6-fa15-84b6-9afadea6c467"/>
- <oi_hud_nav_4_2.tga value="2e19f352-1893-59a9-949b-4d2cfd3a8222"/>
- <oi_hud_nav_4_1.tga value="13a1675b-fb5a-19b3-b5a3-74b0a6765f7d"/>
- <oi_hud_nav_4_0.tga value="e7526e8d-b085-b26c-b0ae-2708ec231401"/>
- <oi_hud_nav_3_5.tga value="5e67b0d0-29a2-6a08-c85e-b12d59e53d6e"/>
- <oi_hud_nav_3_4.tga value="2ed8fbc2-5c4d-53c2-b289-88baffceab1a"/>
- <oi_hud_nav_3_3.tga value="e0a72f1a-282e-1c1a-2cb7-6423feb41759"/>
- <oi_hud_nav_3_2.tga value="4bcebb23-da5e-47d9-eac1-e4453f762c8c"/>
- <oi_hud_nav_3_1.tga value="6ac87575-330e-3a2d-3b80-a34e7b277e50"/>
- <oi_hud_nav_3_0.tga value="f1451e8e-7310-9152-47d5-5d037c28fef3"/>
- <oi_hud_nav_2_6.tga value="c60b42ff-ee60-98e4-e603-ca2470141d4b"/>
- <oi_hud_nav_2_5.tga value="a02b5a1a-bbdb-5556-ae5b-a2e68494755a"/>
- <oi_hud_nav_2_4.tga value="625535ab-8abf-b3e7-48fb-43f728b77c79"/>
- <oi_hud_nav_2_3.tga value="00a609c3-5750-3b5a-3ce3-458bdf632203"/>
- <oi_hud_nav_2_2.tga value="94903387-d37f-092c-e4d2-c190f68577b8"/>
- <oi_hud_nav_2_1.tga value="ee0cd82c-6ce8-8e73-307b-6d0dc77b19e8"/>
- <oi_hud_nav_2_0.tga value="3e10b379-ed2c-7424-1fe7-bef3558c7536"/>
- <oi_hud_nav_1_4.tga value="bf8d0be8-2012-1664-3ea5-e69a71c206e9"/>
- <oi_hud_nav_1_2.tga value="72100f87-18a7-fc4a-4793-de281e8b02cc"/>
- <oi_hud_nav_1_1.tga value="b048faf3-60ce-c3a2-d034-36613449d377"/>
- <oi_hud_nav_1_0.tga value="0ad45106-3b26-6448-0b90-feae8bd46c38"/>
- <oi_hud_mov_4_5.tga value="7c4a45c2-37dd-312c-c6ab-20896dd0a5a6"/>
- <oi_hud_mov_4_3.tga value="8a88da1c-3735-c71e-d48a-016df0798de4"/>
- <oi_hud_mov_4_2.tga value="f55ae4d3-7d6a-e6ac-4cf7-03014ce14390"/>
- <oi_hud_mov_4_1.tga value="1cc3fcf1-35c0-e222-27d2-6905cf5c4cee"/>
- <oi_hud_mov_4_0.tga value="1ae592dc-46f4-616e-b7c6-0dff3e6f40e5"/>
- <oi_hud_mov_3_4.tga value="831b39be-99fc-45bd-ba85-708f9dc93bfd"/>
- <oi_hud_mov_3_2.tga value="9f7e7373-92a9-d66a-ad5a-afb55ca6ac1f"/>
- <oi_hud_mov_3_1.tga value="ab37ed0d-7e66-1f77-3acf-b0fe4b74dbe8"/>
- <oi_hud_mov_3_0.tga value="f5ff1f08-4c92-8606-1854-cc5b9d3e445c"/>
- <oi_hud_mov_1_2.tga value="1e3abeed-e893-c44e-1f9d-5ecc76d21e5d"/>
- <oi_hud_mov_1_0.tga value="e300fc95-aa94-8e31-c501-ce903cac8b7c"/>
-</settings> \ No newline at end of file
+</settings>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 3675fc3618..59e816d61b 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 9
+version 10
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -23,7 +23,7 @@ version 9
// NOTE: All settings are set to the MIN of applied values, including 'all'!
//
list all
-RenderAGP 1 1
+RenderVBO 1 1
RenderAniso 1 0
RenderAvatarMode 1 2
RenderAvatarVP 1 1
@@ -40,6 +40,7 @@ VertexShaderEnable 1 1
//
list Class0
VertexShaderEnable 1 0
+RenderVBO 1 1
RenderDistance 1 64
RenderAvatarVP 1 0
RenderAvatarMode 1 0
@@ -52,6 +53,7 @@ RenderRippleWater 1 0
//
list Class1
VertexShaderEnable 1 0
+RenderVBO 1 1
RenderDistance 1 96
RenderAvatarVP 1 1
RenderAvatarMode 1 0
@@ -99,7 +101,7 @@ RenderAvatarVP 0 0
// "Default" setups for safe, low, medium, high
//
list safe
-RenderAGP 1 0
+RenderVBO 1 0
RenderAniso 1 0
RenderAvatarVP 0 0
RenderLighting 1 0
@@ -108,7 +110,7 @@ RenderTerrainDetail 1 0
list low
-RenderAGP 1 1
+RenderVBO 1 0
RenderAniso 1 0
RenderLighting 1 0
@@ -135,12 +137,17 @@ RenderObjectBump 0 0
//
// Graphics card based feature masks
//
-list Brookdale
+list OpenGLPre15
+RenderVBO 1 0
+
+list Intel
+RenderVBO 1 0
RenderAniso 1 0
RenderLighting 1 0
RenderTerrainDetail 1 0
list GeForce2
+RenderVBO 1 1
RenderAniso 1 0
RenderLighting 1 0
RenderParticleCount 1 2048
@@ -150,10 +157,7 @@ list GeForce3
list ATI
-// Hacked to be paranoid "safe"
-// Disable AGP entirely, in Catalyst 4.3 it's at least 50% slower
list Radeon8500
-RenderAGP 0 0
RenderLighting 1 0
RenderParticleCount 1 4096
@@ -162,9 +166,8 @@ list Radeon9700
RenderParticleCount 1 4096
// Hacked to be paranoid "safe"
-// Disable AGP entirely, in Catalyst 4.3 it's at least 50% slower
list MobilityRadeon9000
-RenderLighting 1 0
+RenderLighting 1 0
RenderParticleCount 1 4096
list GeForceFX
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 25228fc999..568a260034 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -24,7 +24,7 @@ version 9
//
// Mac specific: RenderAvatarVP not enabled at all
list all
-RenderAGP 1 1
+RenderVBO 1 1
RenderAniso 1 0
RenderAvatarMode 1 2
RenderAvatarVP 1 0
@@ -99,7 +99,7 @@ RenderAvatarVP 0 0
// "Default" setups for safe, low, medium, high
//
list safe
-RenderAGP 1 0
+RenderVBO 1 0
RenderAniso 1 0
RenderAvatarVP 0 0
RenderDistance 1 64
@@ -109,7 +109,7 @@ RenderTerrainDetail 1 0
list low
-RenderAGP 1 1
+RenderVBO 1 0
RenderAniso 1 0
RenderDistance 1 96
RenderLighting 1 0
@@ -135,6 +135,12 @@ list RAM256MB
RenderDistance 1 96
RenderObjectBump 0 0
+//
+// Graphics card based feature masks
+//
+list OpenGLPre15
+RenderVBO 1 0
+
// nVidia settings
list NVIDIA
@@ -146,6 +152,6 @@ RenderParticleCount 1 2048
RenderTerrainDetail 1 0
//
-// ATI and AGP now work okay.
+// ATI settings
//
list ATI
diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt
index fae089486e..92f9b446f8 100644
--- a/indra/newview/gpu_table.txt
+++ b/indra/newview/gpu_table.txt
@@ -17,11 +17,14 @@
3Dfx .*3Dfx.* 0
3Dlabs .*3Dlabs.* 0
ATI All-in-Wonder PCI-E .*ATI.*All-in-Wonder.*PCI-E.* 1
+ATI All-in-Wonder X800 .*ATI.*All-in-Wonder X8.* 2
ATI All-in-Wonder X1800 .*ATI.*All-in-Wonder X18.* 3
ATI All-in-Wonder X1900 .*ATI.*All-in-Wonder X19.* 3
-ATI ASUS X1300 .*ATI.*ASUS X13.* 3
-ATI ASUS X1600 .*ATI.*ASUS X16.* 3
-ATI Diamond X1300 .*ATI.*Diamond X13.* 3
+ATI ASUS X1xxx .*ASUS X1.* 3
+ATI Mobility Radeon X1xxx .*ATI.*Mobility.*X1.* 2
+ATI Radeon OpenGL .*ATI.*Radeon OpenGL.* 3
+ATI Diamond X1xxx .*ATI.*Diamond.*X1.* 3
+ATI FireGL 5xxx .*ATI.*FireGL V5.* 3
ATI FireGL .*ATI.*Fire.*GL.* 0
ATI FireMV .*ATI.*FireMV.* 0
ATI Generic .*ATI.*Generic.* 0
@@ -35,14 +38,19 @@ ATI Radeon 9600 .*ATI.*Radeon 96.* 1
ATI Radeon 9700 .*ATI.*Radeon 97.* 1
ATI Radeon 9800 .*ATI.*Radeon 98.* 1
ATI Radeon X1300 .*ATI.*Radeon X13.* 3
+ATI Radeon X1400 .*ATI.*Radeon X14.* 3
+ATI Radeon X1500 .*ATI.*Radeon X15.* 3
ATI Radeon X1600 .*ATI.*Radeon X16.* 3
+ATI Radeon X1700 .*ATI.*Radeon X17.* 3
ATI Radeon X1800 .*ATI.*Radeon X18.* 3
ATI Radeon X1900 .*ATI.*Radeon X19.* 3
ATI Radeon X300 .*ATI.*Radeon X3.* 2
+ATI Radeon X400 .*ATI.*Radeon X4.* 2
ATI Radeon X500 .*ATI.*Radeon X5.* 2
ATI Radeon X600 .*ATI.*Radeon X6.* 2
ATI Radeon X700 .*ATI.*Radeon X7.* 2
ATI Radeon X800 .*ATI.*Radeon X8.* 2
+ATI Radeon X900 .*ATI.*Radeon X9.* 2
ATI Radeon Xpress .*ATI.*Radeon Xpress.* 1
ATI Rage 128 .*ATI.*Rage 128.* 0
Intel 830M .*Intel.*830M 0
@@ -91,7 +99,6 @@ NVIDIA GeForce FX Go5600 .*NVIDIA.*GeForce FX Go56.* 1
NVIDIA GeForce FX Go5700 .*NVIDIA.*GeForce FX Go57.* 1
NVIDIA GeForce FX Go5800 .*NVIDIA.*GeForce FX Go58.* 1
NVIDIA GeForce FX Go5900 .*NVIDIA.*GeForce FX Go59.* 1
-NVIDIA GeForce Go 6 .*GeForce Go 6.* 2
NVIDIA GeForce Go 6100 .*NVIDIA.*GeForce Go 61.* 2
NVIDIA GeForce Go 6200 .*NVIDIA.*GeForce Go 62.* 2
NVIDIA GeForce Go 6500 .*NVIDIA.*GeForce Go 65.* 2
@@ -103,6 +110,7 @@ NVIDIA GeForce Go 7400 .*NVIDIA.*GeForce Go 74.* 3
NVIDIA GeForce Go 7600 .*NVIDIA.*GeForce Go 76.* 3
NVIDIA GeForce Go 7800 .*NVIDIA.*GeForce Go 78.* 3
NVIDIA GeForce Go 7900 .*NVIDIA.*GeForce Go 79.* 3
+NVIDIA GeForce Go 6 .*GeForce Go 6.* 2
NVIDIA GeForce PCX .*GeForce PCX.* 1
NVIDIA Generic .*NVIDIA.*NV.* 0
NVIDIA Generic .*NVIDIA.*Unknown.* 0
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index fd571cacfd..3fd59eb87c 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -13,8 +13,9 @@
#export LL_BAD_ALSA=x
## - Avoids the optional OpenGL extensions which have proven most problematic
-## on some hardware. Disabling this option may cause crashes and hangs on
-## some unstable combinations of drivers and hardware.
+## on some hardware. Disabling this option may cause BETTER PERFORMANCE but
+## may also cause CRASHES and hangs on some unstable combinations of drivers
+## and hardware.
export LL_GL_BASICEXT=x
## - Avoids *all* optional OpenGL extensions. This is the safest and least-
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 8951d0ef33..07daf89f1c 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -103,7 +103,6 @@
// end Ventrella
extern LLMenuBarGL* gMenuBarView;
-extern F32 gMinObjectDistance;
extern U8 gLastPickAlpha;
extern F32 gFrameDTClamped;
@@ -3322,7 +3321,7 @@ void LLAgent::updateCamera()
attachment;
attachment = mAvatarObject->mAttachmentPoints.getNextData())
{
- LLViewerObject *attached_object = attachment->getObject(0);
+ LLViewerObject *attached_object = attachment->getObject();
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
{
// clear any existing "early" movements of attachment
@@ -3432,21 +3431,26 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal()
{
LLDrawable* drawablep = mFocusObject->mDrawable;
- if (mTrackFocusObject && drawablep && drawablep->isActive())
+ if (mTrackFocusObject &&
+ drawablep &&
+ drawablep->isActive())
{
- if (mFocusObject->isSelected())
+ if (!mFocusObject->isAvatar())
{
- gPipeline.updateMoveNormalAsync(drawablep);
- }
- else
- {
- if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
+ if (mFocusObject->isSelected())
{
gPipeline.updateMoveNormalAsync(drawablep);
}
else
{
- gPipeline.updateMoveDampedAsync(drawablep);
+ if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
+ {
+ gPipeline.updateMoveNormalAsync(drawablep);
+ }
+ else
+ {
+ gPipeline.updateMoveDampedAsync(drawablep);
+ }
}
}
}
@@ -3457,11 +3461,6 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal()
}
LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset;
mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent));
- // *FIX: get camera pointat behavior working
- //if (mTrackFocusObject)
- //{
- // mCameraFocusOffset = gAgent.getPosGlobalFromAgent(gCamera->getOrigin()) - mFocusTargetGlobal;
- //}
}
return mFocusTargetGlobal;
}
@@ -3826,8 +3825,6 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground)
{
camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground;
-
- gMinObjectDistance = MIN_NEAR_PLANE;
isConstrained = TRUE;
}
@@ -6572,7 +6569,7 @@ void LLAgent::makeNewOutfit(
S32 attachment_pt = attachments_to_include[i];
LLViewerJointAttachment* attachment = mAvatarObject->mAttachmentPoints.getIfThere( attachment_pt );
if(!attachment) continue;
- LLViewerObject* attached_object = attachment->getObject(0);
+ LLViewerObject* attached_object = attachment->getObject();
if(!attached_object) continue;
const LLUUID& item_id = attachment->getItemID();
if(item_id.isNull()) continue;
@@ -7195,7 +7192,7 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
attachment;
attachment = avatarp->mAttachmentPoints.getNextData())
{
- LLViewerObject* objectp = attachment->getObject(0);
+ LLViewerObject* objectp = attachment->getObject();
if (objectp)
{
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp
index cdba49c40d..4548adae91 100644
--- a/indra/newview/llcloud.cpp
+++ b/indra/newview/llcloud.cpp
@@ -97,16 +97,14 @@ void LLCloudGroup::updatePuffs(const F32 dt)
mVOCloudsp->setPositionRegion(mCenterRegion);
mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
- CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT));
+ CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f);
gPipeline.addObject(mVOCloudsp);
}
- S32 i;
-
LLVector3 velocity;
LLVector3d vel_d;
// Update the positions of all of the clouds
- for (i = 0; i < mCloudPuffs.count(); i++)
+ for (U32 i = 0; i < mCloudPuffs.size(); i++)
{
LLCloudPuff &puff = mCloudPuffs[i];
velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal));
@@ -121,8 +119,8 @@ void LLCloudGroup::updatePuffs(const F32 dt)
void LLCloudGroup::updatePuffOwnership()
{
- S32 i = 0;
- while (i < mCloudPuffs.count())
+ U32 i = 0;
+ while (i < mCloudPuffs.size())
{
if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING)
{
@@ -146,10 +144,11 @@ void LLCloudGroup::updatePuffOwnership()
continue;
}
//llinfos << "Puff handed off!" << llendl;
- LLCloudPuff *puffp = new_cgp->mCloudPuffs.reserve_block(1);
- puffp->mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
- puffp->mAlpha = mCloudPuffs[i].mAlpha;
- mCloudPuffs.remove(i);
+ LLCloudPuff puff;
+ puff.mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
+ puff.mAlpha = mCloudPuffs[i].mAlpha;
+ mCloudPuffs.erase(mCloudPuffs.begin() + i);
+ new_cgp->mCloudPuffs.push_back(puff);
}
//llinfos << "Puff count: " << LLCloudPuff::sPuffCount << llendl;
@@ -165,7 +164,7 @@ void LLCloudGroup::updatePuffCount()
S32 target_puff_count = llround(CLOUD_DENSITY * mDensity);
target_puff_count = llmax(0, target_puff_count);
target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count);
- S32 current_puff_count = mCloudPuffs.count();
+ S32 current_puff_count = (S32) mCloudPuffs.size();
// Create a new cloud if we need one
if (current_puff_count < target_puff_count)
{
@@ -186,7 +185,7 @@ void LLCloudGroup::updatePuffCount()
// Count the number of live puffs
S32 live_puff_count = 0;
- for (i = 0; i < mCloudPuffs.count(); i++)
+ for (i = 0; i < (S32) mCloudPuffs.size(); i++)
{
if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
{
@@ -212,12 +211,12 @@ void LLCloudGroup::updatePuffCount()
// Remove fully dead puffs
i = 0;
- while (i < mCloudPuffs.count())
+ while (i < (S32) mCloudPuffs.size())
{
if (mCloudPuffs[i].isDead())
{
//llinfos << "Removing dead puff!" << llendl;
- mCloudPuffs.remove(i);
+ mCloudPuffs.erase(mCloudPuffs.begin() + i);
LLCloudPuff::sPuffCount--;
}
else
diff --git a/indra/newview/llcloud.h b/indra/newview/llcloud.h
index 06c2b5c9ff..3bb06c818b 100644
--- a/indra/newview/llcloud.h
+++ b/indra/newview/llcloud.h
@@ -110,7 +110,7 @@ public:
BOOL inGroup(const LLCloudPuff &puff) const;
F32 getDensity() const { return mDensity; }
- S32 getNumPuffs() const { return mCloudPuffs.count(); }
+ S32 getNumPuffs() const { return (S32) mCloudPuffs.size(); }
const LLCloudPuff &getPuff(const S32 i) { return mCloudPuffs[i]; }
protected:
LLCloudLayer *mCloudLayerp;
@@ -118,7 +118,7 @@ protected:
F32 mDensity;
S32 mTargetPuffCount;
- LLDynamicArray<LLCloudPuff> mCloudPuffs;
+ std::vector<LLCloudPuff> mCloudPuffs;
LLPointer<LLVOClouds> mVOCloudsp;
};
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index 020f700dfb..999dce1296 100644
--- a/indra/newview/llcolorswatch.h
+++ b/indra/newview/llcolorswatch.h
@@ -12,6 +12,7 @@
#include "lluictrl.h"
#include "v4color.h"
#include "llfloater.h"
+#include "llviewerimage.h"
//
// Classes
diff --git a/indra/newview/llcylinder.cpp b/indra/newview/llcylinder.cpp
index 1774ff4ccf..579fd61daa 100644
--- a/indra/newview/llcylinder.cpp
+++ b/indra/newview/llcylinder.cpp
@@ -15,7 +15,7 @@
#include "llmath.h"
#include "noise.h"
#include "v3math.h"
-
+#include "llvertexbuffer.h"
#include "llgl.h"
#include "llglheaders.h"
@@ -24,6 +24,10 @@ LLCone gCone;
GLUquadricObj* gQuadObj = NULL;
+static const GLint SLICES[] = { 30, 20, 12, 6 }; // same as sphere slices
+static const GLint STACKS = 2;
+static const GLfloat RADIUS = 0.5f;
+
// draws a cylinder or cone
// returns approximate number of triangles required
U32 draw_cylinder_side(GLint slices, GLint stacks, GLfloat base_radius, GLfloat top_radius)
@@ -87,46 +91,27 @@ U32 draw_cylinder_cap(GLint slices, GLfloat base_radius, BOOL is_top)
return triangles;
}
+void LLCylinder::drawSide(S32 detail)
+{
+ draw_cylinder_side(SLICES[detail], STACKS, RADIUS, RADIUS);
+}
-void LLCylinder::prerender()
+void LLCylinder::drawTop(S32 detail)
{
- GLint stacks = 2;
- GLfloat radius = 0.5f;
- GLint slices[CYLINDER_LEVELS_OF_DETAIL] = { 30, 20, 12, 6 }; // same as sphere slices
+ draw_cylinder_cap(SLICES[detail], RADIUS, TOP);
+}
- for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++)
- {
- mTriangleCount[detail] = 0;
-
- mDisplayListSide[detail] = glGenLists(1);
- glNewList(mDisplayListSide[detail], GL_COMPILE);
- mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, radius );
- glEndList();
-
- mDisplayListTop[detail] = glGenLists(1);
- glNewList( mDisplayListTop[detail], GL_COMPILE);
- mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, TOP );
- glEndList();
-
- mDisplayListBottom[detail] = glGenLists(1);
- glNewList( mDisplayListBottom[detail], GL_COMPILE);
- mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM );
- glEndList();
- }
+void LLCylinder::drawBottom(S32 detail)
+{
+ draw_cylinder_cap(SLICES[detail], RADIUS, BOTTOM);
}
-void LLCylinder::cleanupGL()
+void LLCylinder::prerender()
{
- for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++)
- {
- glDeleteLists(mDisplayListSide[detail], 1);
- mDisplayListSide[detail] = 0;
- glDeleteLists(mDisplayListTop[detail], 1);
- mDisplayListTop[detail] = 0;
- glDeleteLists(mDisplayListBottom[detail], 1);
- mDisplayListBottom[detail] = 0;
- }
+}
+void LLCylinder::cleanupGL()
+{
if (gQuadObj)
{
gluDeleteQuadric(gQuadObj);
@@ -178,19 +163,21 @@ void LLCylinder::renderface(F32 pixel_area, S32 face)
return;
}
+ LLVertexBuffer::unbind();
+
switch(face)
{
case 0:
glTranslatef(0.f, 0.f, -0.5f);
- glCallList(mDisplayListSide[level_of_detail]);
+ drawSide(level_of_detail);
break;
case 1:
glTranslatef(0.0f, 0.f, 0.5f);
- glCallList(mDisplayListTop[level_of_detail]);
+ drawTop(level_of_detail);
break;
case 2:
glTranslatef(0.0f, 0.f, -0.5f);
- glCallList(mDisplayListBottom[level_of_detail]);
+ drawBottom(level_of_detail);
break;
default:
llerror("LLCylinder::renderface() fell out of switch", 0);
@@ -208,37 +195,10 @@ void LLCylinder::renderface(F32 pixel_area, S32 face)
void LLCone::prerender()
{
- GLint stacks = 2;
- GLfloat radius = 0.5f;
- GLint slices[CONE_LEVELS_OF_DETAIL] = { 32, 18, 12, 6 };
-
- for (S32 detail = 0; detail < CONE_LEVELS_OF_DETAIL; detail++)
- {
- mTriangleCount[detail] = 0;
-
- mDisplayListSide[detail] = glGenLists(1);
- glNewList(mDisplayListSide[detail], GL_COMPILE);
- mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, 0.f );
- glEndList();
-
- mDisplayListBottom[detail] = glGenLists(1);
- glNewList( mDisplayListBottom[detail], GL_COMPILE);
- mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM );
- glEndList();
- }
}
void LLCone::cleanupGL()
{
- for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++)
- {
- glDeleteLists(mDisplayListSide[detail], 1);
- mDisplayListSide[detail] = 0;
-
- glDeleteLists(mDisplayListBottom[detail], 1);
- mDisplayListBottom[detail] = 0;
- }
-
if (gQuadObj)
{
gluDeleteQuadric(gQuadObj);
@@ -246,6 +206,15 @@ void LLCone::cleanupGL()
}
}
+void LLCone::drawSide(S32 detail)
+{
+ draw_cylinder_side( SLICES[detail], STACKS, RADIUS, 0.f );
+}
+
+void LLCone::drawBottom(S32 detail)
+{
+ draw_cylinder_cap( SLICES[detail], RADIUS, BOTTOM );
+}
void LLCone::render(S32 level_of_detail)
{
@@ -263,8 +232,9 @@ void LLCone::render(S32 level_of_detail)
// center object at 0
glTranslatef(0.f, 0.f, - height / 2.0f);
- glCallList(mDisplayListSide[level_of_detail]);
- glCallList(mDisplayListBottom[level_of_detail]);
+ LLVertexBuffer::unbind();
+ drawSide(level_of_detail);
+ drawBottom(level_of_detail);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
@@ -288,15 +258,17 @@ void LLCone::renderface(S32 level_of_detail, S32 face)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
+ LLVertexBuffer::unbind();
+
switch(face)
{
case 0:
glTranslatef(0.f, 0.f, -0.5f);
- glCallList(mDisplayListSide[level_of_detail]);
+ drawSide(level_of_detail);
break;
case 1:
glTranslatef(0.f, 0.f, -0.5f);
- glCallList(mDisplayListBottom[level_of_detail]);
+ drawBottom(level_of_detail);
break;
default:
llerror("LLCylinder::renderface() fell out of switch", 0);
diff --git a/indra/newview/llcylinder.h b/indra/newview/llcylinder.h
index 9150db4fb1..94f3219607 100644
--- a/indra/newview/llcylinder.h
+++ b/indra/newview/llcylinder.h
@@ -20,20 +20,15 @@ const S32 CYLINDER_FACES = 3;
class LLCylinder
{
-protected:
- U32 mDisplayListSide[CYLINDER_LEVELS_OF_DETAIL];
- U32 mDisplayListTop[CYLINDER_LEVELS_OF_DETAIL];
- U32 mDisplayListBottom[CYLINDER_LEVELS_OF_DETAIL];
- U32 mTriangleCount[CYLINDER_LEVELS_OF_DETAIL];
-
public:
void prerender();
+ void drawTop(S32 detail);
+ void drawSide(S32 detail);
+ void drawBottom(S32 detail);
void cleanupGL();
void render(F32 pixel_area);
void renderface(F32 pixel_area, S32 face);
-
- U32 getTriangleCount(S32 level_of_detail) { return mTriangleCount[level_of_detail]; }
};
@@ -46,20 +41,14 @@ const S32 CONE_LEVELS_OF_DETAIL = 4;
const S32 CONE_FACES = 2;
class LLCone
-{
-protected:
- U32 mDisplayListSide[CONE_LEVELS_OF_DETAIL];
- U32 mDisplayListBottom[CONE_LEVELS_OF_DETAIL];
- U32 mTriangleCount[CONE_LEVELS_OF_DETAIL];
-
+{
public:
void prerender();
void cleanupGL();
-
+ void drawSide(S32 detail);
+ void drawBottom(S32 detail);
void render(S32 level_of_detail);
void renderface(S32 level_of_detail, S32 face);
-
- U32 getTriangleCount(S32 level_of_detail) { return mTriangleCount[level_of_detail]; }
};
extern LLCylinder gCylinder;
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index c4ee6acb8c..868d61942d 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -14,8 +14,6 @@
#include "material_codes.h"
// viewer includes
-#include "llagparray.h"
-#include "llagparray.inl"
#include "llcriticaldamp.h"
#include "llface.h"
#include "lllightconstants.h"
@@ -58,6 +56,8 @@ U32 LLDrawable::sNumZombieDrawables = 0;
F32 LLDrawable::sCurPixelAngle = 0;
LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList;
+#define FORCE_INVISIBLE_AREA 16.f
+
// static
void LLDrawable::incrementVisible()
{
@@ -108,12 +108,11 @@ void LLDrawable::destroy()
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
mFaces.clear();
- /*
- if (!(sNumZombieDrawables % 10))
+
+ /*if (!(sNumZombieDrawables % 10))
{
llinfos << "- Zombie drawables: " << sNumZombieDrawables << llendl;
- }
- */
+ }*/
}
void LLDrawable::markDead()
@@ -250,7 +249,7 @@ void LLDrawable::removeFace(const S32 i)
}
#endif
-LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BOOL shared_geom)
+LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep)
{
LLMemType mt(LLMemType::MTYPE_DRAWABLE);
@@ -259,16 +258,12 @@ LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BO
if (face)
{
mFaces.push_back(face);
- face->setPool(poolp, texturep);
- if (shared_geom)
+ if (poolp)
{
- face->setState(LLFace::SHARED_GEOM);
- }
- else if (!isVisible())
- {
- face->setState(LLFace::BACKLIST);
+ face->setPool(poolp, texturep);
}
+
if (isState(UNLIT))
{
face->setState(LLFace::FULLBRIGHT);
@@ -277,7 +272,27 @@ LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BO
return face;
}
-void LLDrawable::setNumFaces(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep)
+LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerImage *texturep)
+{
+ LLMemType mt(LLMemType::MTYPE_DRAWABLE);
+
+ LLFace *face = new LLFace(this, mVObjp);
+
+ face->setTEOffset(mFaces.size());
+ face->setTexture(texturep);
+ face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep));
+ mFaces.push_back(face);
+
+ if (isState(UNLIT))
+ {
+ face->setState(LLFace::FULLBRIGHT);
+ }
+
+ return face;
+
+}
+
+void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
{
if (newFaces == (S32)mFaces.size())
{
@@ -298,7 +313,7 @@ void LLDrawable::setNumFaces(const S32 newFaces, LLDrawPool *poolp, LLViewerImag
}
}
-void LLDrawable::setNumFacesFast(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep)
+void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
{
if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2)
{
@@ -353,21 +368,43 @@ void LLDrawable::updateMaterial()
void LLDrawable::makeActive()
{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if (mVObjp.notNull())
+ {
+ U32 pcode = mVObjp->getPCode();
+ if (pcode == LLViewerObject::LL_VO_WATER ||
+ pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
+ pcode == LLViewerObject::LL_VO_PART_GROUP ||
+ pcode == LLViewerObject::LL_VO_CLOUDS ||
+ pcode == LLViewerObject::LL_VO_STARS ||
+ pcode == LLViewerObject::LL_VO_GROUND ||
+ pcode == LLViewerObject::LL_VO_SKY)
+ {
+ llerrs << "Static viewer object has active drawable!" << llendl;
+ }
+ }
+#endif
+
if (!isState(ACTIVE)) // && mGeneration > 0)
{
setState(ACTIVE);
+ //parent must be made active first
if (!isRoot() && !mParent->isActive())
{
mParent->makeActive();
}
-
+
gPipeline.setActive(this, TRUE);
//all child objects must also be active
for (U32 i = 0; i < getChildCount(); i++)
{
- getChild(i)->makeActive();
+ LLDrawable* drawable = getChild(i);
+ if (drawable)
+ {
+ drawable->makeActive();
+ }
}
if (mVObjp->getPCode() == LL_PCODE_VOLUME)
@@ -384,7 +421,15 @@ void LLDrawable::makeActive()
gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);
}
}
- mQuietCount = 0;
+ updatePartition();
+ if (isRoot())
+ {
+ mQuietCount = 0;
+ }
+ else
+ {
+ getParent()->mQuietCount = 0;
+ }
}
@@ -397,7 +442,7 @@ void LLDrawable::makeStatic()
if (mParent.notNull() && mParent->isActive())
{
- llerrs << "Drawable became static with active parent!" << llendl;
+ llwarns << "Drawable becamse static with active parent!" << llendl;
}
S32 child_count = mVObjp->mChildList.size();
@@ -406,6 +451,10 @@ void LLDrawable::makeStatic()
LLDrawable* child_drawable = mVObjp->mChildList[child_num]->mDrawable;
if (child_drawable)
{
+ if (child_drawable->getParent() != this)
+ {
+ llwarns << "Child drawable has unknown parent." << llendl;
+ }
child_drawable->makeStatic();
}
}
@@ -422,6 +471,7 @@ void LLDrawable::makeStatic()
setSpatialBridge(NULL);
}
}
+ updatePartition();
}
// Returns "distance" between target destination and resulting xfrom
@@ -480,9 +530,8 @@ F32 LLDrawable::updateXform(BOOL undamped)
if (scaled >= MIN_INTERPOLATE_DISTANCE_SQUARED)
{
//scaling requires an immediate rebuild
- gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);
+ gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
}
-
}
else
{
@@ -498,20 +547,6 @@ F32 LLDrawable::updateXform(BOOL undamped)
mXform.updateMatrix();
mCurrentScale = target_scale;
-
- if (!getVOVolume())
- {
- movePartition();
- }
- else if (mSpatialBridge)
- {
- gPipeline.markMoved(mSpatialBridge, FALSE);
- }
- else
- {
- //a child prim moved and needs its verts regenerated
- gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);
- }
return dist_squared;
}
@@ -521,11 +556,6 @@ void LLDrawable::setRadius(F32 radius)
if (mRadius != radius)
{
mRadius = radius;
- updateBinRadius();
- if (!getVOVolume())
- {
- movePartition();
- }
}
}
@@ -554,13 +584,10 @@ void LLDrawable::moveUpdatePipeline(BOOL moved)
void LLDrawable::movePartition()
{
- if (getSpatialGroup() || getVOVolume())
+ LLSpatialPartition* part = getSpatialPartition();
+ if (part)
{
- LLSpatialPartition* part = getSpatialPartition();
- if (part)
- {
- part->move(this, getSpatialGroup());
- }
+ part->move(this, getSpatialGroup());
}
}
@@ -606,10 +633,27 @@ BOOL LLDrawable::updateMoveUndamped()
}
mVObjp->clearChanged(LLXform::MOVED);
-
+
return TRUE;
}
+void LLDrawable::updatePartition()
+{
+ if (!getVOVolume())
+ {
+ movePartition();
+ }
+ else if (mSpatialBridge)
+ {
+ gPipeline.markMoved(mSpatialBridge, FALSE);
+ }
+ else
+ {
+ //a child prim moved and needs its verts regenerated
+ gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
+ }
+}
+
BOOL LLDrawable::updateMoveDamped()
{
F32 dist_squared = updateXform(FALSE);
@@ -635,25 +679,42 @@ BOOL LLDrawable::updateMoveDamped()
void LLDrawable::updateDistance(LLCamera& camera)
{
- if (mVObjp->isHUDAttachment())
- {
- mDistanceWRTCamera = 1.0f;
- if (sCurVisible % 16 == 0)
- {
- mVObjp->updateLOD();
- }
- return;
- }
-
- LLVector3 pos(getPositionGroup());
-
- pos -= camera.getOrigin();
- mDistanceWRTCamera = pos.magVec();
-
//switch LOD with the spatial group to avoid artifacts
LLSpatialGroup* sg = getSpatialGroup();
+
+ LLVector3 pos;
+
if (!sg || sg->changeLOD())
{
+ LLVOVolume* volume = getVOVolume();
+ if (volume)
+ {
+ volume->updateRelativeXform();
+ pos = LLVector3(0,0,0) * volume->getRelativeXform();
+
+ for (S32 i = 0; i < getNumFaces(); i++)
+ {
+ LLFace* facep = getFace(i);
+ if (facep->getPoolType() == LLDrawPool::POOL_ALPHA)
+ {
+ LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
+ LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
+ LLVector3 at = camera.getAtAxis();
+ for (U32 j = 0; j < 3; j++)
+ {
+ v.mV[j] -= box.mV[j] * at.mV[j];
+ }
+ facep->mDistance = v * camera.getAtAxis();
+ }
+ }
+ }
+ else
+ {
+ pos = LLVector3(getPositionGroup());
+ }
+
+ pos -= camera.getOrigin();
+ mDistanceWRTCamera = llround(pos.magVec(), 0.01f);
mVObjp->updateLOD();
}
}
@@ -668,67 +729,33 @@ void LLDrawable::updateTexture()
return;
}
- // *FIX: this updates textures on all faces in this drawable, not
- // just the viewer object we care about
- if (mVObjp->getNumTEs())
+ if (getNumFaces() != mVObjp->getNumTEs())
+ { //drawable is transitioning its face count
+ return;
+ }
+
+ if (getVOVolume())
{
- // For each face in this drawable, change the drawpool if necessary.
- for (S32 i = 0; i < getNumFaces(); i++)
+ if (!isActive())
+ {
+ gPipeline.markMoved(this);
+ }
+ else
{
- LLFace *facep = mFaces[i];
- U32 pool_type = facep->getPool()->getType();
-
- if ((pool_type == LLDrawPool::POOL_SIMPLE) ||
- (pool_type == LLDrawPool::POOL_ALPHA) ||
- (pool_type == LLDrawPool::POOL_HUD) ||
- (pool_type == LLDrawPool::POOL_MEDIA) ||
- (pool_type == LLDrawPool::POOL_BUMP))
+ if (isRoot())
{
- LLViewerObject* objp = facep->getViewerObject();
- S32 te_offset = facep->getTEOffset();
-
- if (te_offset >= objp->getNumTEs()) // Shouldn't happen
- {
- llwarns << "TE offsets don't match!" << llendl;
- facep->setTEOffset(-1);
- continue;
- }
-
- LLDrawPool* poolp = NULL;
- LLViewerImage* imagep = (te_offset >= 0) ? objp->getTEImage(te_offset) : facep->getTexture();
- if (facep->isState(LLFace::HUD_RENDER))
- {
- poolp = gPipeline.getPool(LLDrawPool::POOL_HUD);
- }
- else if (te_offset >= 0)
- {
- // This face actually uses texture entries...
- const LLTextureEntry* te = facep->getTextureEntry();
- poolp = LLPipeline::getPoolFromTE(te, imagep);
- }
- else
- {
- // No texture entry for this face.
- if (!imagep)
- {
- poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, NULL);
- }
- else if ((imagep->getComponents() == 4) || (imagep->getComponents() == 2))
- {
- poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
- }
- else
- {
- poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep);
- }
- }
- facep->setPool(poolp, imagep);
+ mQuietCount = 0;
+ }
+ else
+ {
+ getParent()->mQuietCount = 0;
}
}
+
+ gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE);
}
}
-
BOOL LLDrawable::updateGeometry(BOOL priority)
{
llassert(mVObjp.notNull());
@@ -769,12 +796,9 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector)
mXform.setScale(1,1,1);
mXform.updateMatrix();
- if (isStatic() || // *FIX: don't know why this is happening, but
- // some terrain patches are becoming active
- // (earth quake, maybe?) DP
- getRenderType() == LLPipeline::RENDER_TYPE_TERRAIN)
+ if (isStatic())
{
- LLStrider<LLVector3> verticesp;
+ gPipeline.markRebuild(this, LLDrawable::REBUILD_GEOMETRY, TRUE);
for (S32 i = 0; i < getNumFaces(); i++)
{
@@ -783,34 +807,13 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector)
facep->mExtents[0] += shift_vector;
facep->mExtents[1] += shift_vector;
- if (facep->hasGeometry() && !facep->isState(LLFace::SHARED_GEOM))
+ if (facep->hasGeometry())
{
- S32 index = facep->getVertices(verticesp);
- if (index >= 0)
- {
- S32 vertex_count = facep->getGeomCount();
- for (S32 j = 0; j < vertex_count; j++)
- {
- *verticesp += shift_vector;
- verticesp++;
- }
- }
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
}
}
- }
- else
- {
- // Update the face centers.
- for (S32 i = 0; i < getNumFaces(); i++)
- {
- LLFace *facep = getFace(i);
- facep->mCenterAgent += shift_vector;
- }
- }
-
- //update spatial extents
- if (!getVOVolume() || isStatic())
- {
+
mExtents[0] += shift_vector;
mExtents[1] += shift_vector;
mPositionGroup += LLVector3d(shift_vector);
@@ -855,6 +858,8 @@ void LLDrawable::updateSpatialExtents()
mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]);
}
+ updateBinRadius();
+
if (mSpatialBridge.notNull())
{
mPositionGroup.setVec(0,0,0);
@@ -864,11 +869,14 @@ void LLDrawable::updateSpatialExtents()
void LLDrawable::updateBinRadius()
{
- S32 binLOD = mVObjp ? mVObjp->getLOD() : 2;
- static F64 detail_bins[] = { 8, 4, 2, 1 };
- F32 radius = getVOVolume() && isStatic() ?
- (mExtents[1]-mExtents[0]).magVec() : getRadius();
- mBinRadius = detail_bins[binLOD] * llmax((F64) radius, (3-binLOD)*0.25);
+ if (mVObjp.notNull())
+ {
+ mBinRadius = mVObjp->getBinRadius();
+ }
+ else
+ {
+ mBinRadius = getRadius()*4.f;
+ }
}
void LLDrawable::updateLightSet()
@@ -879,6 +887,7 @@ void LLDrawable::updateLightSet()
return;
}
+ LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME);
LLVOVolume* light = getVOVolume();
if (isLight() && light)
{
@@ -888,7 +897,7 @@ void LLDrawable::updateLightSet()
gPipeline.markRelight(*iter);
}
mLightSet.clear();
- gPipeline.mObjectPartition->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet);
+ part->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet);
for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++)
{
gPipeline.markRelight(*iter);
@@ -898,8 +907,8 @@ void LLDrawable::updateLightSet()
{
// mLightSet points to nearby lights
mLightSet.clear();
- gPipeline.mObjectPartition->getLights(getPositionAgent(), getRadius(), mLightSet);
- const U32 max_lights = 16;
+ part->getLights(getPositionAgent(), getRadius(), mLightSet);
+ const S32 max_lights = 16;
if (mLightSet.size() > max_lights)
{
typedef std::set<std::pair<F32,LLPointer<LLDrawable> > > sorted_pair_set_t;
@@ -1034,28 +1043,28 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
{
LLSpatialPartition* retval = NULL;
- if (mVObjp->isHUDAttachment())
- { //HUD attachments don't get space partitioned
- return NULL;
- }
-
if (!mVObjp ||
!getVOVolume() ||
isStatic())
{
- retval = gPipeline.mObjectPartition;
+ retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp);
}
-
- //must be an active volume
- if (!retval && isRoot())
- {
+ else if (isRoot())
+ { //must be an active volume
if (!mSpatialBridge)
{
- setSpatialBridge(new LLSpatialBridge(this));
+ if (mVObjp->isHUDAttachment())
+ {
+ setSpatialBridge(new LLHUDBridge(this));
+ }
+ else
+ {
+ setSpatialBridge(new LLVolumeBridge(this));
+ }
}
return mSpatialBridge->asPartition();
}
- else if (!retval)
+ else
{
retval = getParent()->getSpatialPartition();
}
@@ -1069,27 +1078,73 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
return retval;
}
+
+BOOL LLDrawable::isVisible() const
+{
+ if (mVisible == sCurVisible)
+ {
+ return TRUE;
+ }
+
+ if (isActive())
+ {
+ if (isRoot())
+ {
+ LLSpatialGroup* group = mSpatialBridge.notNull() ? mSpatialBridge->getSpatialGroup() :
+ getSpatialGroup();
+ if (!group || group->isVisible())
+ {
+ mVisible = sCurVisible;
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (getParent()->isVisible())
+ {
+ mVisible = sCurVisible;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ LLSpatialGroup* group = getSpatialGroup();
+ if (!group || group->isVisible())
+ {
+ mVisible = sCurVisible;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
//=======================================
// Spatial Partition Bridging Drawable
//=======================================
-LLSpatialBridge::LLSpatialBridge(LLDrawable* root)
+LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask)
+: LLSpatialPartition(data_mask, FALSE)
{
mDrawable = root;
root->setSpatialBridge(this);
- mRenderType = mDrawable->mRenderType; //w00! magic!
-
+ mRenderType = mDrawable->mRenderType;
+ mDrawableType = mDrawable->mRenderType;
+
+ mPartitionType = LLPipeline::PARTITION_VOLUME;
+
mOctree->balance();
- gPipeline.mObjectPartition->put(this);
+ gPipeline.getSpatialPartition(mPartitionType)->put(this);
}
LLSpatialBridge::~LLSpatialBridge()
{
if (getSpatialGroup())
{
- gPipeline.mObjectPartition->remove(this, getSpatialGroup());
+ gPipeline.getSpatialPartition(mPartitionType)->remove(this, getSpatialGroup());
}
}
@@ -1097,7 +1152,6 @@ void LLSpatialBridge::updateSpatialExtents()
{
LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
- if (mOctree->getChildCount() > 0)
{
LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
root->rebound();
@@ -1145,6 +1199,9 @@ void LLSpatialBridge::updateSpatialExtents()
}
}
}
+
+ LLVector3 diagonal = newMax - newMin;
+ mRadius = diagonal.magVec() * 0.5f;
mPositionGroup.setVec((newMin + newMax) * 0.5f);
updateBinRadius();
@@ -1152,9 +1209,7 @@ void LLSpatialBridge::updateSpatialExtents()
void LLSpatialBridge::updateBinRadius()
{
- F32 rad = ((mExtents[1]-mExtents[0])*0.5f).magVec();
- mBinRadius = llmax(rad, 2.f);
- mRadius = rad;
+ mBinRadius = llmin((F32) mOctree->getSize().mdV[0]*0.5f, 256.f);
}
LLCamera LLSpatialBridge::transformCamera(LLCamera& camera)
@@ -1162,39 +1217,123 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera)
LLCamera ret = camera;
LLXformMatrix* mat = mDrawable->getXform();
LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix();
- //LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix());
+ LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix());
- //ret.rotate(~mat->getRotation());
LLVector3 delta = ret.getOrigin() - center;
- delta *= ~mat->getRotation();
- ret.setOrigin(delta);
+ LLQuaternion rot = ~mat->getRotation();
+
+ delta *= rot;
+ LLVector3 lookAt = ret.getAtAxis();
+ LLVector3 up_axis = ret.getUpAxis();
+ LLVector3 left_axis = ret.getLeftAxis();
+ lookAt *= rot;
+ up_axis *= rot;
+ left_axis *= rot;
+
+ ret.setOrigin(delta);
+ ret.setAxes(lookAt, left_axis, up_axis);
+
return ret;
}
void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select)
{
mVisible = sCurVisible;
+
+#if 0 && !LL_RELEASE_FOR_DOWNLOAD
+ //crazy paranoid rules checking
+ if (getVOVolume())
+ {
+ if (!isRoot())
+ {
+ if (isActive() && !mParent->isActive())
+ {
+ llerrs << "Active drawable has static parent!" << llendl;
+ }
+
+ if (isStatic() && !mParent->isStatic())
+ {
+ llerrs << "Static drawable has active parent!" << llendl;
+ }
+
+ if (mSpatialBridge)
+ {
+ llerrs << "Child drawable has spatial bridge!" << llendl;
+ }
+ }
+ else if (isActive() && !mSpatialBridge)
+ {
+ llerrs << "Active root drawable has no spatial bridge!" << llendl;
+ }
+ else if (isStatic() && mSpatialBridge.notNull())
+ {
+ llerrs << "Static drawable has spatial bridge!" << llendl;
+ }
+ }
+#endif
}
+class LLOctreeMarkNotCulled: public LLOctreeTraveler<LLDrawable>
+{
+public:
+ LLCamera* mCamera;
+
+ LLOctreeMarkNotCulled(LLCamera* camera_in) : mCamera(camera_in) { }
+
+ virtual void traverse(const LLOctreeNode<LLDrawable>* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+ group->clearState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED);
+ LLOctreeTraveler<LLDrawable>::traverse(node);
+ }
+
+ void visit(const LLOctreeState<LLDrawable>* branch)
+ {
+ gPipeline.markNotCulled((LLSpatialGroup*) branch->getListener(0), *mCamera, TRUE);
+ }
+};
+
void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results, BOOL for_select)
{
+ if (!gPipeline.hasRenderType(mDrawableType))
+ {
+ return;
+ }
+
+ LLViewerObject *vobj = mDrawable->getVObj();
+ if (vobj && vobj->isAttachment() && !vobj->isHUDAttachment())
+ {
+ LLVOAvatar* av;
+ LLDrawable* parent = mDrawable->getParent();
+
+ if (parent)
+ {
+ av = (LLVOAvatar*) parent->getVObj();
+
+ if (!av->isVisible())
+ {
+ return;
+ }
+ }
+ }
+
+
+ LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
+ group->rebound();
+
LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f;
LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f;
if (camera_in.AABBInFrustum(center, size))
{
- LLVector3 lookAt = center - camera_in.getOrigin();
- F32 distSqr = lookAt.magVecSquared();
- F32 objRad = size.magVecSquared();
-
- if (objRad/distSqr < SG_MIN_DIST_RATIO*4)
+ if (LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
{
return;
}
LLDrawable::setVisible(camera_in);
-
+
if (for_select)
{
results->push_back(mDrawable);
@@ -1203,42 +1342,36 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
results->push_back(mDrawable->getChild(i));
}
}
- else
+ else
{
- const LLVector3* extents = mDrawable->getSpatialExtents();
- objRad = mDrawable->getRadius();
- objRad *= objRad;
-
- if (objRad/distSqr > SG_MIN_DIST_RATIO)
- {
- gPipeline.markNotCulled(mDrawable, camera_in);
- }
-
- for (U32 i = 0; i < mDrawable->getChildCount(); i++)
- {
- LLDrawable* child = mDrawable->getChild(i);
- extents = child->getSpatialExtents();
- objRad = child->getRadius();
- objRad *= objRad;
-
- if (objRad/distSqr > SG_MIN_DIST_RATIO)
- {
- gPipeline.markNotCulled(mDrawable->getChild(i), camera_in);
- }
- }
- }
+ LLCamera trans_camera = transformCamera(camera_in);
+ LLOctreeMarkNotCulled culler(&trans_camera);
+ culler.traverse(mOctree);
+ }
}
}
void LLSpatialBridge::updateDistance(LLCamera& camera_in)
{
+ if (mDrawable == NULL)
+ {
+ markDead();
+ return;
+ }
+
LLCamera camera = transformCamera(camera_in);
mDrawable->updateDistance(camera);
for (U32 i = 0; i < mDrawable->getChildCount(); ++i)
{
- mDrawable->getChild(i)->updateDistance(camera);
+ LLDrawable* child = mDrawable->getChild(i);
+ if (!child)
+ {
+ llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl;
+ continue;
+ }
+ child->updateDistance(camera);
}
}
@@ -1261,7 +1394,7 @@ void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL imm
BOOL LLSpatialBridge::updateMove()
{
mOctree->balance();
- gPipeline.mObjectPartition->move(this, getSpatialGroup(), TRUE);
+ gPipeline.getSpatialPartition(mPartitionType)->move(this, getSpatialGroup(), TRUE);
return TRUE;
}
@@ -1319,3 +1452,81 @@ const LLVector3 LLDrawable::getPositionAgent() const
}
}
+BOOL LLDrawable::isAnimating() const
+{
+ if (!getVObj())
+ {
+ return TRUE;
+ }
+
+ if (getScale() != mVObjp->getScale())
+ {
+ return TRUE;
+ }
+
+ if (mVObjp->isFlexible())
+ {
+ return TRUE;
+ }
+
+ if (mVObjp->getPCode() == LLViewerObject::LL_VO_PART_GROUP)
+ {
+ return TRUE;
+ }
+
+ if (mVObjp->getPCode() == LLViewerObject::LL_VO_CLOUDS)
+ {
+ return TRUE;
+ }
+
+ LLVOVolume* vol = getVOVolume();
+ if (vol && vol->mTextureAnimp)
+ {
+ return TRUE;
+ }
+
+ if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero())
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void LLDrawable::updateFaceSize(S32 idx)
+{
+ if (mVObjp.notNull())
+ {
+ mVObjp->updateFaceSize(idx);
+ }
+}
+
+LLBridgePartition::LLBridgePartition()
+: LLSpatialPartition(0, TRUE)
+{
+ mRenderByGroup = FALSE;
+ mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+ mPartitionType = LLPipeline::PARTITION_BRIDGE;
+ mLODPeriod = 1;
+ mSlopRatio = 0.f;
+}
+
+LLHUDBridge::LLHUDBridge(LLDrawable* drawablep)
+: LLVolumeBridge(drawablep)
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_HUD;
+ mPartitionType = LLPipeline::PARTITION_HUD;
+ mSlopRatio = 0.0f;
+}
+
+F32 LLHUDBridge::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
+{
+ return 1024.f;
+}
+
+
+void LLHUDBridge::shiftPos(const LLVector3& vec)
+{
+ //don't shift hud bridges on region crossing
+}
+
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index cb9f970106..fef8b02ad5 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -19,8 +19,8 @@
#include "v4coloru.h"
#include "llquaternion.h"
#include "xform.h"
+#include "llmemtype.h"
#include "llprimitive.h"
-#include "llviewerimage.h"
#include "lldarray.h"
#include "llstat.h"
#include "llviewerobject.h"
@@ -33,6 +33,7 @@ class LLSpatialGroup;
class LLSpatialBridge;
class LLSpatialPartition;
class LLVOVolume;
+class LLViewerImage;
extern F32 gFrameTimeSeconds;
@@ -55,7 +56,7 @@ public:
BOOL isLight() const;
- BOOL isVisible() const { return (mVisible == sCurVisible); }
+ BOOL isVisible() const;
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
@@ -102,10 +103,11 @@ public:
inline S32 getNumFaces() const;
//void removeFace(const S32 i); // SJB: Avoid using this, it's slow
- LLFace* addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BOOL shared_geom = FALSE);
+ LLFace* addFace(LLFacePool *poolp, LLViewerImage *texturep);
+ LLFace* addFace(const LLTextureEntry *te, LLViewerImage *texturep);
void deleteFaces(S32 offset, S32 count);
- void setNumFaces(const S32 numFaces, LLDrawPool *poolp, LLViewerImage *texturep);
- void setNumFacesFast(const S32 numFaces, LLDrawPool *poolp, LLViewerImage *texturep);
+ void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep);
+ void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep);
void mergeFaces(LLDrawable* src);
void init();
@@ -119,6 +121,8 @@ public:
BOOL isActive() const { return isState(ACTIVE); }
BOOL isStatic() const { return !isActive(); }
+ BOOL isAnimating() const;
+
virtual BOOL updateMove();
virtual void movePartition();
@@ -127,6 +131,7 @@ public:
virtual void updateDistance(LLCamera& camera);
BOOL updateGeometry(BOOL priority);
BOOL updateLighting(BOOL priority);
+ void updateFaceSize(S32 idx);
void updateLightSet();
F32 getSunShadowFactor() const { return mSunShadowFactor; }
@@ -176,6 +181,7 @@ public:
protected:
virtual ~LLDrawable() { destroy(); }
void moveUpdatePipeline(BOOL moved);
+ void updatePartition();
BOOL updateMoveDamped();
BOOL updateMoveUndamped();
@@ -187,6 +193,7 @@ public:
typedef std::set<LLPointer<LLDrawable> > drawable_set_t;
typedef std::vector<LLPointer<LLDrawable> > drawable_vector_t;
typedef std::list<LLPointer<LLDrawable> > drawable_list_t;
+ typedef std::queue<LLPointer<LLDrawable> > drawable_queue_t;
struct CompareDistanceGreater
{
@@ -227,11 +234,14 @@ public:
UNLIT = 0x00000200,
LIGHT = 0x00000400,
LIGHTING_BUILT = 0x00000800,
- REBUILD_VOLUME = 0x00001000,
- REBUILD_TCOORD = 0x00002000,
- REBUILD_GEOMETRY= REBUILD_VOLUME|REBUILD_TCOORD,
- REBUILD_LIGHTING= 0x00008000,
- REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_LIGHTING,
+ REBUILD_VOLUME = 0x00001000, //volume changed LOD or parameters, or vertex buffer changed
+ REBUILD_TCOORD = 0x00002000, //texture coordinates changed
+ REBUILD_COLOR = 0x00004000, //color changed
+ REBUILD_LIGHTING= 0x00008000, //lighting information changed
+ REBUILD_POSITION= 0x00010000, //vertex positions/normals changed
+ REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR,
+ REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR,
+ REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_LIGHTING|REBUILD_VOLUME,
ON_SHIFT_LIST = 0x00100000,
// NO_INTERP_COLOR = 0x00200000,
BLOCKER = 0x00400000,
@@ -266,6 +276,8 @@ public:
void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; }
+ static F32 sCurPixelAngle; //current pixels per radian
+
protected:
typedef std::vector<LLFace*> face_list_t;
@@ -277,7 +289,7 @@ protected:
LLPointer<LLDrawable> mSpatialBridge;
S32 mSpatialGroupOffset;
- U32 mVisible;
+ mutable U32 mVisible;
F32 mRadius;
LLVector3 mExtents[2];
LLVector3d mPositionGroup;
@@ -289,7 +301,6 @@ protected:
LLVector3 mCurrentScale;
static U32 sCurVisible; // Counter for what value of mVisible means currently visible
- static F32 sCurPixelAngle; //current pixels per radian
static U32 sNumZombieDrawables;
static LLDynamicArrayPtr<LLPointer<LLDrawable> > sDeadList;
@@ -299,6 +310,7 @@ protected:
inline LLFace* LLDrawable::getFace(const S32 i) const
{
llassert((U32)i < mFaces.size());
+ llassert(mFaces[i]);
return mFaces[i];
}
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 899d49f380..9ab6c700ab 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -13,7 +13,6 @@
#include "llfasttimer.h"
#include "llviewercontrol.h"
-#include "llagparray.h"
#include "lldrawable.h"
#include "lldrawpoolalpha.h"
#include "lldrawpoolavatar.h"
@@ -24,53 +23,38 @@
#include "lldrawpoolsky.h"
#include "lldrawpoolstars.h"
#include "lldrawpooltree.h"
-#include "lldrawpooltreenew.h"
#include "lldrawpoolterrain.h"
#include "lldrawpoolwater.h"
-#include "lldrawpoolhud.h"
#include "llface.h"
#include "llviewerobjectlist.h" // For debug listing.
-#include "llvotreenew.h"
#include "pipeline.h"
-#include "llagparray.inl"
-
-U32 LLDrawPool::sDataSizes[LLDrawPool::DATA_MAX_TYPES] =
-{
- 12, // DATA_VERTICES
- 8, // DATA_TEX_COORDS0
- 8, // DATA_TEX_COORDS1
- 8, // DATA_TEX_COORDS2
- 8, // DATA_TEX_COORDS3
- 12, // DATA_NORMALS
- 4, // DATA_VERTEX_WEIGHTS,
- 16, // DATA_CLOTHING_WEIGHTS
- 12, // DATA_BINORMALS
- 4, // DATA_COLORS
-};
-
S32 LLDrawPool::sNumDrawPools = 0;
+
+//=============================
+// Draw Pool Implementation
+//=============================
LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
{
LLDrawPool *poolp = NULL;
switch (type)
{
case POOL_SIMPLE:
- poolp = new LLDrawPoolSimple(tex0);
+ poolp = new LLDrawPoolSimple();
break;
case POOL_ALPHA:
poolp = new LLDrawPoolAlpha();
break;
+ case POOL_ALPHA_POST_WATER:
+ poolp = new LLDrawPoolAlphaPostWater();
+ break;
case POOL_AVATAR:
poolp = new LLDrawPoolAvatar();
break;
case POOL_TREE:
poolp = new LLDrawPoolTree(tex0);
break;
- case POOL_TREE_NEW:
- poolp = new LLDrawPoolTreeNew(tex0);
- break;
case POOL_TERRAIN:
poolp = new LLDrawPoolTerrain(tex0);
break;
@@ -80,9 +64,6 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
case POOL_STARS:
poolp = new LLDrawPoolStars();
break;
- case POOL_CLOUDS:
- poolp = new LLDrawPoolClouds();
- break;
case POOL_WATER:
poolp = new LLDrawPoolWater();
break;
@@ -90,10 +71,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
poolp = new LLDrawPoolGround();
break;
case POOL_BUMP:
- poolp = new LLDrawPoolBump(tex0);
- break;
- case POOL_HUD:
- poolp = new LLDrawPoolHUD();
+ poolp = new LLDrawPoolBump();
break;
default:
llerrs << "Unknown draw pool type!" << llendl;
@@ -104,183 +82,86 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
return poolp;
}
-LLDrawPool::LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil)
+LLDrawPool::LLDrawPool(const U32 type)
{
- llassert(data_mask_il & DATA_VERTICES_MASK);
- S32 i;
mType = type;
sNumDrawPools++;
mId = sNumDrawPools;
-
- mDataMaskIL = data_mask_il;
- mDataMaskNIL = data_mask_nil;
-
- U32 cur_mask = 0x01;
- U32 cur_offset = 0;
- for (i = 0; i < DATA_MAX_TYPES; i++)
- {
- mDataOffsets[i] = cur_offset;
- if (cur_mask & mDataMaskIL)
- {
- cur_offset += sDataSizes[i];
- }
- cur_mask <<= 1;
- }
-
- mStride = cur_offset;
-
- mCleanupUnused = FALSE;
+ mVertexShaderLevel = 0;
mIndicesDrawn = 0;
- mRebuildFreq = 128 + rand() % 5;
- mRebuildTime = 0;
- mGeneration = 1;
- mSkippedVertices = 0;
-
- resetDrawOrders();
- resetVertexData(0);
-
- if (gGLManager.mHasATIVAO && !gGLManager.mIsRadeon9700)
- {
- // ATI 8500 doesn't like indices > 15 bit.
- mMaxVertices = DEFAULT_MAX_VERTICES/2;
- }
- else
- {
- mMaxVertices = DEFAULT_MAX_VERTICES;
- }
+}
- // JC: This must happen last, as setUseAGP reads many of the
- // above variables.
- mUseAGP = FALSE;
- setUseAGP(gPipeline.usingAGP());
+LLDrawPool::~LLDrawPool()
+{
- for (i=0; i<NUM_BUCKETS; i++)
- {
- mFreeListGeomHead[i] = -1;
- mFreeListIndHead[i] = -1;
- }
- mVertexShaderLevel = 0;
}
-void LLDrawPool::destroy()
+LLViewerImage *LLDrawPool::getDebugTexture()
{
- if (!mReferences.empty())
- {
- llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl;
- }
+ return NULL;
}
-
-LLDrawPool::~LLDrawPool()
+//virtual
+void LLDrawPool::beginRenderPass( S32 pass )
{
- destroy();
-
- llassert( gPipeline.findPool( getType(), getTexture() ) == NULL );
}
-BOOL LLDrawPool::setUseAGP(BOOL use_agp)
+//virtual
+void LLDrawPool::endRenderPass( S32 pass )
{
- BOOL ok = TRUE;
- S32 vertex_count = mMemory.count() / mStride;
- if (vertex_count > mMaxVertices && use_agp)
- {
-#ifdef DEBUG_AGP
- llwarns << "Allocating " << vertex_count << " vertices in pool type " << getType() << ", disabling AGP!" << llendl
-#endif
- use_agp = FALSE;
- ok = FALSE;
- }
-
- if (mUseAGP != use_agp)
- {
- mUseAGP = use_agp;
-
- BOOL ok = TRUE;
- ok &= mMemory.setUseAGP(use_agp);
-
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
- {
- ok &= mWeights.setUseAGP(use_agp);
- }
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
- {
- ok &= mClothingWeights.setUseAGP(use_agp);
- }
-
- if (!ok)
- {
- // Disable AGP if any one of these doesn't have AGP, we don't want to try
- // mixing AGP and non-agp arrays in a single pool.
-#ifdef DEBUG_AGP
- llinfos << "Aborting using AGP because set failed on a mem block!" << llendl;
-#endif
- setUseAGP(FALSE);
- ok = FALSE;
- }
- }
- return ok;
+ glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
+ glDisableClientState ( GL_COLOR_ARRAY );
+ glDisableClientState ( GL_NORMAL_ARRAY );
}
-void LLDrawPool::flushAGP()
+U32 LLDrawPool::getTrianglesDrawn() const
{
- mMemory.flushAGP();
-
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
- {
- mWeights.flushAGP();
- }
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
- {
- mClothingWeights.flushAGP();
- }
+ return mIndicesDrawn / 3;
}
-void LLDrawPool::syncAGP()
+void LLDrawPool::resetTrianglesDrawn()
{
- if (!getVertexCount())
- {
- return;
- }
- setUseAGP(gPipeline.usingAGP());
+ mIndicesDrawn = 0;
+}
- BOOL all_agp_on = TRUE;
- mMemory.sync();
- all_agp_on &= mMemory.isAGP();
+void LLDrawPool::addIndicesDrawn(const U32 indices)
+{
+ mIndicesDrawn += indices;
+}
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
- {
- mWeights.sync();
- all_agp_on &= mWeights.isAGP();
- }
+//=============================
+// Face Pool Implementation
+//=============================
+LLFacePool::LLFacePool(const U32 type)
+: LLDrawPool(type)
+{
+ resetDrawOrders();
+}
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
- {
- mClothingWeights.sync();
- all_agp_on &= mClothingWeights.isAGP();
- }
+LLFacePool::~LLFacePool()
+{
+ destroy();
+}
- // Since sometimes AGP allocation is done during syncs, we need
- // to make sure that if AGP allocation fails, we fallback to non-agp.
- if (mUseAGP && !all_agp_on)
+void LLFacePool::destroy()
+{
+ if (!mReferences.empty())
{
-#ifdef DEBUG_AGP
- llinfos << "setUseAGP false because of AGP sync failure!" << llendl;
-#endif
- setUseAGP(FALSE);
+ llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl;
}
}
-void LLDrawPool::dirtyTexture(const LLViewerImage *imagep)
+void LLFacePool::dirtyTextures(const std::set<LLViewerImage*>& textures)
{
}
-BOOL LLDrawPool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data)
+BOOL LLFacePool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data)
{
return TRUE;
}
// static
-S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array)
+S32 LLFacePool::drawLoop(face_array_t& face_list)
{
S32 res = 0;
if (!face_list.empty())
@@ -289,19 +170,15 @@ S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array)
iter != face_list.end(); iter++)
{
LLFace *facep = *iter;
- if (facep->mSkipRender)
- {
- continue;
- }
- facep->enableLights();
- res += facep->renderIndexed(index_array);
+ //facep->enableLights();
+ res += facep->renderIndexed();
}
}
return res;
}
// static
-S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage)
+S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage)
{
S32 res = 0;
if (!face_list.empty())
@@ -310,117 +187,30 @@ S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array,
iter != face_list.end(); iter++)
{
LLFace *facep = *iter;
- if (facep->mSkipRender)
- {
- continue;
- }
facep->bindTexture(stage);
facep->enableLights();
- res += facep->renderIndexed(index_array);
+ res += facep->renderIndexed();
}
}
return res;
}
-void LLDrawPool::drawLoop()
+void LLFacePool::drawLoop()
{
- const U32* index_array = getRawIndices();
if (!mDrawFace.empty())
{
- mIndicesDrawn += drawLoop(mDrawFace, index_array);
+ mIndicesDrawn += drawLoop(mDrawFace);
}
}
-BOOL LLDrawPool::getVertexStrider(LLStrider<LLVector3> &vertices, const U32 index)
-{
- llassert(mDataMaskIL & LLDrawPool::DATA_VERTICES_MASK);
- vertices = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride);
- vertices.setStride(mStride);
- return TRUE;
-}
-
-BOOL LLDrawPool::getTexCoordStrider(LLStrider<LLVector2> &tex_coords, const U32 index, const U32 pass)
-{
- llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass));
- tex_coords = (LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride);
- tex_coords.setStride(mStride);
- return TRUE;
-}
-
-
-BOOL LLDrawPool::getVertexWeightStrider(LLStrider<F32> &vertex_weights, const U32 index)
-{
- llassert(mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK);
-
- vertex_weights = &mWeights[index];
- vertex_weights.setStride( 0 );
- return TRUE;
-}
-
-BOOL LLDrawPool::getClothingWeightStrider(LLStrider<LLVector4> &clothing_weights, const U32 index)
-{
- llassert(mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK);
-
- clothing_weights= &mClothingWeights[index];
- clothing_weights.setStride( 0 );
-
- return TRUE;
-}
-
-BOOL LLDrawPool::getNormalStrider(LLStrider<LLVector3> &normals, const U32 index)
-{
- llassert((mDataMaskIL) & LLDrawPool::DATA_NORMALS_MASK);
-
- normals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride);
-
- normals.setStride( mStride );
-
- return TRUE;
-}
-
-
-BOOL LLDrawPool::getBinormalStrider(LLStrider<LLVector3> &binormals, const U32 index)
-{
- llassert((mDataMaskIL) & LLDrawPool::DATA_BINORMALS_MASK);
-
- binormals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride);
-
- binormals.setStride( mStride );
-
- return TRUE;
-}
-
-BOOL LLDrawPool::getColorStrider(LLStrider<LLColor4U> &colors, const U32 index)
-{
- llassert((mDataMaskIL) & LLDrawPool::DATA_COLORS_MASK);
-
- colors = (LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride);
-
- colors.setStride( mStride );
-
- return TRUE;
-}
-
-//virtual
-void LLDrawPool::beginRenderPass( S32 pass )
-{
-}
-
-//virtual
-void LLDrawPool::endRenderPass( S32 pass )
-{
- glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
- glDisableClientState ( GL_COLOR_ARRAY );
- glDisableClientState ( GL_NORMAL_ARRAY );
-}
-void LLDrawPool::renderFaceSelected(LLFace *facep,
+void LLFacePool::renderFaceSelected(LLFace *facep,
LLImageGL *image,
const LLColor4 &color,
const S32 index_offset, const S32 index_count)
{
}
-void LLDrawPool::renderVisibility()
+void LLFacePool::renderVisibility()
{
if (mDrawFace.empty())
{
@@ -506,893 +296,284 @@ void LLDrawPool::renderVisibility()
}
-void LLDrawPool::enqueue(LLFace* facep)
-{
- if (facep->isState(LLFace::BACKLIST))
- {
- mMoveFace.put(facep);
- }
- else
- {
-#if ENABLE_FACE_LINKING
- facep->mSkipRender = FALSE;
- facep->mNextFace = NULL;
-
- if (mDrawFace.size() > 0)
- {
- LLFace* last_face = mDrawFace[mDrawFace.size()-1];
- if (match(last_face, facep))
- {
- last_face->link(facep);
- }
- }
-#endif
- mDrawFace.put(facep);
- }
-}
-
-void LLDrawPool::bindGLVertexPointer()
-{
- mMemory.bindGLVertexPointer(getStride(DATA_VERTICES), mDataOffsets[DATA_VERTICES]);
-}
-
-void LLDrawPool::bindGLTexCoordPointer(const U32 pass)
-{
- mMemory.bindGLTexCoordPointer(getStride(DATA_TEX_COORDS0+pass), mDataOffsets[DATA_TEX_COORDS0+pass]);
-}
-
-void LLDrawPool::bindGLNormalPointer()
-{
- mMemory.bindGLNormalPointer(getStride(DATA_NORMALS), mDataOffsets[DATA_NORMALS]);
-}
-
-void LLDrawPool::bindGLBinormalPointer(S32 index)
-{
- mMemory.bindGLBinormalPointer(index, getStride(DATA_BINORMALS), mDataOffsets[DATA_BINORMALS]);
-}
-
-void LLDrawPool::bindGLColorPointer()
+void LLFacePool::enqueue(LLFace* facep)
{
- mMemory.bindGLColorPointer(getStride(DATA_COLORS), mDataOffsets[DATA_COLORS]);
+ mDrawFace.push_back(facep);
}
-void LLDrawPool::bindGLVertexWeightPointer(S32 index)
-{
- mWeights.bindGLVertexWeightPointer(index, 0, 0);
-}
-
-void LLDrawPool::bindGLVertexClothingWeightPointer(S32 index)
-{
- mClothingWeights.bindGLVertexClothingWeightPointer(index, 0, 0);
-}
-
-
-U32* LLDrawPool::getIndices(S32 index)
-{
- return &mIndices[index];
-}
-
-const LLVector3& LLDrawPool::getVertex(const S32 index)
-{
- llassert(mDataMaskIL & DATA_VERTICES_MASK);
- llassert(index < mMemory.count());
- llassert(mMemory.getMem());
- return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride);
-}
-
-const LLVector2& LLDrawPool::getTexCoord(const S32 index, const U32 pass)
+// virtual
+BOOL LLFacePool::addFace(LLFace *facep)
{
- llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass));
- llassert(index < mMemory.count());
- return *(LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride);
+ addFaceReference(facep);
+ return TRUE;
}
-const LLVector3& LLDrawPool::getNormal(const S32 index)
+// virtual
+BOOL LLFacePool::removeFace(LLFace *facep)
{
- llassert(mDataMaskIL & DATA_NORMALS_MASK);
- llassert(index < mMemory.count());
- return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride);
-}
+ removeFaceReference(facep);
-const LLVector3& LLDrawPool::getBinormal(const S32 index)
-{
- llassert(mDataMaskIL & DATA_BINORMALS_MASK);
- llassert(index < mMemory.count());
- return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride);
-}
+ vector_replace_with_last(mDrawFace, facep);
-const LLColor4U& LLDrawPool::getColor(const S32 index)
-{
- llassert(mDataMaskIL & DATA_COLORS_MASK);
- llassert(index < mMemory.count());
- return *(LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride);
+ return TRUE;
}
-const F32& LLDrawPool::getVertexWeight(const S32 index)
+// Not absolutely sure if we should be resetting all of the chained pools as well - djs
+void LLFacePool::resetDrawOrders()
{
- llassert(mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK);
- llassert(index < mWeights.count());
- llassert(mWeights.getMem());
- return mWeights[index];
+ mDrawFace.resize(0);
}
-const LLVector4& LLDrawPool::getClothingWeight(const S32 index)
+LLViewerImage *LLFacePool::getTexture()
{
- llassert(mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK);
- llassert(index < mClothingWeights.count());
- llassert(mClothingWeights.getMem());
- return mClothingWeights[index];
+ return NULL;
}
-//////////////////////////////////////////////////////////////////////////////
-
-#define USE_FREE_LIST 0
-#define DEBUG_FREELIST 0
-
-struct tFreeListNode
+void LLFacePool::removeFaceReference(LLFace *facep)
{
- U32 count;
- S32 next;
-};
-
-#if DEBUG_FREELIST
-static void check_list(U8 *pool, S32 stride, S32 head, S32 max)
-{
- int count = 0;
-
- while (head >= 0)
+ if (facep->getReferenceIndex() != -1)
{
- tFreeListNode *node = (tFreeListNode *)(pool + head*stride);
- count++;
- if ((count > max) || ((node->count>>20) != 0xabc) || ((node->count&0xfffff) < 2))
- llerrs << "Bad Ind List" << llendl;
- head = node->next;
+ if (facep->getReferenceIndex() != (S32)mReferences.size())
+ {
+ LLFace *back = mReferences.back();
+ mReferences[facep->getReferenceIndex()] = back;
+ back->setReferenceIndex(facep->getReferenceIndex());
+ }
+ mReferences.pop_back();
}
+ facep->setReferenceIndex(-1);
}
-#define CHECK_LIST(x) check_list##x
-#else
-#define CHECK_LIST(x)
-#endif
-// DEBUG!
-void LLDrawPool::CheckIntegrity()
+void LLFacePool::addFaceReference(LLFace *facep)
{
-#if DEBUG_FREELIST
- int bucket;
- for (bucket=0; bucket<NUM_BUCKETS; bucket++)
+ if (-1 == facep->getReferenceIndex())
{
- CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[bucket], mMemory.count() / mStride));
- CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[bucket], mIndices.count()));
+ facep->setReferenceIndex(mReferences.size());
+ mReferences.push_back(facep);
}
-#endif
}
-int LLDrawPool::freeListBucket(U32 count)
+BOOL LLFacePool::verify() const
{
- int bucket;
-
- // llassert(NUM_BUCKETS == 8)
+ BOOL ok = TRUE;
- if (count & ~511) // >= 512
- bucket = 7;
- else if (count & 256) // 256-511
- bucket = 6;
- else if (count & 128)
- bucket = 5;
- else if (count & 64)
- bucket = 4;
- else if (count & 32)
- bucket = 3;
- else if (count & 16)
- bucket = 2;
- else if (count & 8) // 8-15
- bucket = 1;
- else // 0-7
- bucket = 0;
- return bucket;
-}
-
-void remove_node(int nodeidx, int pidx, U8 *membase, int stride, int *head)
-{
- LLDrawPool::FreeListNode *node = (LLDrawPool::FreeListNode *)(membase + nodeidx*stride);
- if (pidx >= 0)
- {
- LLDrawPool::FreeListNode *pnode = (LLDrawPool::FreeListNode *)(membase + pidx*stride);
- pnode->next = node->next;
- }
- else
- {
- *head = node->next;
- }
-}
-
-void LLDrawPool::freeListAddGeom(S32 index, U32 count)
-{
-#if USE_FREE_LIST
- int i;
- U8 *membase = (U8*)mMemory.getMem();
- // See if next block or previous block is free, if so combine them
- for (i=0; i<NUM_BUCKETS; i++)
- {
- int pidx = -1;
- int nodeidx = mFreeListGeomHead[i];
- while(nodeidx >= 0)
- {
- int change = 0;
- FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride);
- int nodecount = node->count & 0xffff;
- // Check for prev block
- if (nodeidx + nodecount == index)
- {
- remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
- // Combine nodes
- index = nodeidx;
- count += nodecount;
- i = 0; // start over ; i = NUM_BUCKETS // done
- change = 1;
- //break;
- }
- // Check for next block
- if (nodeidx == index + count)
- {
- remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
- // Combine nodes
- count += nodecount;
- i = 0; // start over ; i = NUM_BUCKETS // done
- change = 1;
- //break;
- }
- if (change)
- break;
- pidx = nodeidx;
- nodeidx = node->next;
- }
- }
- // Add (extended) block to free list
- if (count >= 2) // need 2 words to store free list (theoreticly mStride could = 4)
+ for (std::vector<LLFace*>::const_iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
{
- CheckIntegrity();
- if ((index + count)*mStride >= mMemory.count())
+ const LLFace* facep = *iter;
+ if (facep->getPool() != this)
{
- mMemory.shrinkTo(index*mStride);
+ llinfos << "Face in wrong pool!" << llendl;
+ facep->printDebugInfo();
+ ok = FALSE;
}
- else
+ else if (!facep->verify())
{
- int bucket = freeListBucket(count);
- FreeListNode *node = (FreeListNode *)(membase + index*mStride);
- node->count = count | (0xabc<<20);
- node->next = mFreeListGeomHead[bucket];
- mFreeListGeomHead[bucket] = index;
+ ok = FALSE;
}
- CheckIntegrity();
}
-#endif
-}
-void LLDrawPool::freeListAddInd(S32 index, U32 count)
-{
-#if USE_FREE_LIST
- int i;
- const U32 *membase = mIndices.getMem();
- // See if next block or previous block is free, if so combine them
- for (i=0; i<NUM_BUCKETS; i++)
- {
- int pidx = -1;
- int nodeidx = mFreeListIndHead[i];
- while(nodeidx >= 0)
- {
- int change = 0;
- FreeListNode *node = (FreeListNode *)(membase + nodeidx);
- int nodecount = node->count & 0xffff;
- // Check for prev block
- if (nodeidx + nodecount == index)
- {
- remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
- // Combine nodes
- index = nodeidx;
- count += nodecount;
- i = 0; // start over ; i = NUM_BUCKETS // done
- change = 1;
- //break;
- }
- // Check for next block
- if (nodeidx == index + count)
- {
- remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
- // Combine nodes
- count += nodecount;
- i = 0; // start over ; i = NUM_BUCKETS // done
- change = 1;
- //break;
- }
- if (change)
- break;
- pidx = nodeidx;
- nodeidx = node->next;
- }
- }
- // Add (extended) block to free list
- if (count >= 2) // need 2 words to store free list
- {
- CheckIntegrity();
- if (index + count >= mIndices.count())
- {
- mIndices.shrinkTo(index);
- }
- else
- {
- int bucket = freeListBucket(count);
- FreeListNode *node = (FreeListNode *)(membase + index);
- node->count = count | (0xabc<<20);
- node->next = mFreeListIndHead[bucket];
- mFreeListIndHead[bucket] = index;
- }
- CheckIntegrity();
- }
-#endif
+ return ok;
}
-S32 LLDrawPool::freeListFindGeom(U32 count)
+void LLFacePool::printDebugInfo() const
{
-#if USE_FREE_LIST
- int i, nodeidx, pidx;
- int firstbucket = freeListBucket(count);
- U8 *membase = (U8*)mMemory.getMem();
- for (i=firstbucket; i<NUM_BUCKETS; i++)
- {
- pidx = -1;
- nodeidx = mFreeListGeomHead[i];
- CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[i], mMemory.count() / mStride));
- while(nodeidx >= 0)
- {
- FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride);
- int nodecount = node->count & 0xffff;
- llassert((node->count>>20) == 0xabc);
- if (nodecount >= count)
- {
- remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
-#if 1
- if (nodecount > count)
- {
- int leftover = nodecount - count;
- freeListAddGeom(nodeidx + count, leftover);
- }
-#endif
- return nodeidx;
- }
- pidx = nodeidx;
- nodeidx = node->next;
- }
- }
-#endif // USE_FREE_LIST
- return -1;
+ llinfos << "Pool " << this << " Type: " << getType() << llendl;
}
-S32 LLDrawPool::freeListFindInd(U32 count)
+BOOL LLFacePool::LLOverrideFaceColor::sOverrideFaceColor = FALSE;
+
+void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4& color)
{
-#if USE_FREE_LIST
- int i, nodeidx, pidx;
- int firstbucket = freeListBucket(count);
- U32 *membase = (U32 *)mIndices.getMem();
- for (i=firstbucket; i<NUM_BUCKETS; i++)
+ if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0)
{
- pidx = -1;
- nodeidx = mFreeListIndHead[i];
- CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[i], mIndices.count()));
- while(nodeidx >= 0)
- {
- FreeListNode *node = (FreeListNode *)(membase + nodeidx);
- int nodecount = node->count & 0xffff;
- llassert((node->count>>20) == 0xabc);
- if (nodecount >= count)
- {
- remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
-#if 1
- if (nodecount > count)
- {
- int leftover = nodecount - count;
- freeListAddInd(nodeidx + count, leftover);
- }
-#endif
- return nodeidx;
- }
- pidx = nodeidx;
- nodeidx = node->next;
- }
+ glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV);
}
-#endif // USE_FREE_LIST
- return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-S32 LLDrawPool::reserveGeom(const U32 geom_count)
-{
- LLFastTimer t(LLFastTimer::FTM_GEO_RESERVE);
-
- S32 index;
- index = freeListFindGeom(geom_count);
- if (index < 0)
+ else
{
- index = mMemory.count() / mStride;
- if (!geom_count)
- {
- llwarns << "Attempting to reserve zero bytes!" << llendl;
- return index;
- }
-
- S32 bytes = geom_count * mStride;
-
- if ((index + (S32)geom_count) > (S32)mMaxVertices)
- {
- //
- // Various drivers have issues with the number of indices being greater than a certain number.
- // if you're using AGP. Disable AGP if we've got more vertices than in the pool.
- //
-#ifdef DEBUG_AGP
- llinfos << "setUseAGP false because of large vertex count in reserveGeom" << llendl;
-#endif
- setUseAGP(FALSE);
- }
-
- mMemory.reserve_block(bytes);
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
- {
- mWeights.reserve_block(geom_count);
- }
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
- {
- mClothingWeights.reserve_block(geom_count);
- }
+ glColor4fv(color.mV);
}
- CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[0], mMemory.count() / mStride));
- return index;
}
-S32 LLDrawPool::reserveInd(U32 indCount)
+void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4U& color)
{
- S32 index;
- index = freeListFindInd(indCount);
- if (index < 0)
+ if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0)
{
- index = mIndices.count();
-
- if (indCount)
- {
- mIndices.reserve_block(indCount);
- }
+ glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV);
}
- for (U32 i=0;i<indCount;i++)
+ else
{
- mIndices[index+i]=0;
+ glColor4ubv(color.mV);
}
- CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[0], mIndices.count()));
- return index;
}
-S32 LLDrawPool::unReserveGeom(const S32 index, const U32 count)
+void LLFacePool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a)
{
- if (index < 0 || count == 0)
- return -1;
-
- freeListAddGeom(index, count);
-
-#if 0
- int i;
- S32 bytes,words;
- U32 *memp;
- // Fill mem with bad data (for testing only)
- bytes = count * mStride;
- bytes -= sizeof(FreeListNode);
- memp = (U32*)(mMemory.getMem() + index * mStride);
- memp += sizeof(FreeListNode)>>2;
- words = bytes >> 2;
- for (i=0; i<words; i++)
- *memp++ = 0xffffffff;
-
- words = count; // (sizeof each array is a word)
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
+ if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0)
{
- memp = (U32*)(&mWeights[index]);
- for (i=0; i<words; i++)
- *memp++ = 0xffffffff;
+ glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a);
}
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
+ else
{
- memp = (U32*)(&mClothingWeights[index]);
- for (i=0; i<count; i++)
- *memp++ = 0xffffffff;
+ glColor4f(r,g,b,a);
}
-#endif
- return -1;
}
-S32 LLDrawPool::unReserveInd(const S32 index, const U32 count)
-{
- if (index < 0 || count == 0)
- return -1;
- freeListAddInd(index, count);
-
-#if 0
- int i;
- U32 *memp = &mIndices[index];
- for (i=0; i<count; i++)
- *memp++ = 0xffffffff;
-#endif
- return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-const U32 LLDrawPool::getIndexCount() const
+//=============================
+// Render Pass Implementation
+//=============================
+LLRenderPass::LLRenderPass(const U32 type)
+: LLDrawPool(type)
{
- return mIndices.count();
-}
-const U32 LLDrawPool::getVertexCount() const
-{
- return mMemory.count() / mStride;
}
-const U32 LLDrawPool::getTexCoordCount(U32 pass) const
+LLRenderPass::~LLRenderPass()
{
- return mMemory.count() / mStride;
-}
-
-const U32 LLDrawPool::getNormalCount() const
-{
- return mMemory.count() / mStride;
}
-
-const U32 LLDrawPool::getBinormalCount() const
+LLDrawPool* LLRenderPass::instancePool()
{
- return mMemory.count() / mStride;
-}
-
-const U32 LLDrawPool::getColorCount() const
-{
- return mMemory.count() / mStride;
-}
-
-const U32 LLDrawPool::getVertexWeightCount() const
-{
- return mWeights.count();
+#if LL_RELEASE_FOR_DOWNLOAD
+ llwarns << "Attempting to instance a render pass. Invalid operation." << llendl;
+#else
+ llerrs << "Attempting to instance a render pass. Invalid operation." << llendl;
+#endif
+ return NULL;
}
-// virtual
-BOOL LLDrawPool::addFace(LLFace *facep)
-{
- addFaceReference(facep);
- return TRUE;
+void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
+{
+ std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[type];
+
+ for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k)
+ {
+ LLDrawInfo& params = **k;
+ pushBatch(params, mask, texture);
+ }
}
-// virtual
-BOOL LLDrawPool::removeFace(LLFace *facep)
+void LLRenderPass::renderInvisible(U32 mask)
{
- removeFaceReference(facep);
-
- vector_replace_with_last(mDrawFace, facep);
-
- facep->unReserve();
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
- return TRUE;
-}
+ std::vector<LLDrawInfo*>& draw_info = gPipeline.mRenderMap[LLRenderPass::PASS_INVISIBLE];
-// Not absolutely sure if we should be resetting all of the chained pools as well - djs
-void LLDrawPool::resetDrawOrders()
-{
- mDrawFace.resize(0);
+ U32* indices_pointer = NULL;
+ for (std::vector<LLDrawInfo*>::iterator i = draw_info.begin(); i != draw_info.end(); ++i)
+ {
+ LLDrawInfo& params = **i;
+ params.mVertexBuffer->setBuffer(mask);
+ indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+ gPipeline.mTrianglesDrawn += params.mCount/3;
+ }
}
-void LLDrawPool::resetIndices(S32 indices_count)
+void LLRenderPass::renderTexture(U32 type, U32 mask)
{
- mIndices.reset(indices_count);
- for (S32 i=0; i<NUM_BUCKETS; i++)
- mFreeListIndHead[i] = -1;
-}
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
-void LLDrawPool::resetVertexData(S32 reserve_count)
-{
- mMemory.reset(reserve_count*mStride);
-
- for (S32 i=0; i<NUM_BUCKETS; i++)
- {
- mFreeListGeomHead[i] = -1;
- }
- if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
- {
- mWeights.reset(reserve_count);
- }
+ std::vector<LLDrawInfo*>& draw_info = gPipeline.mRenderMap[type];
- if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
+ for (std::vector<LLDrawInfo*>::iterator i = draw_info.begin(); i != draw_info.end(); ++i)
{
- mClothingWeights.reset(reserve_count);
+ LLDrawInfo& params = **i;
+ pushBatch(params, mask, TRUE);
}
}
-void LLDrawPool::resetAll()
-{
- resetDrawOrders();
- resetVertexData(0);
- mGeneration++;
-
-}
-
-S32 LLDrawPool::rebuild()
+void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
- mRebuildTime++;
-
- BOOL needs_rebuild = FALSE;
- S32 rebuild_cost = 0;
-
- if (mUseAGP)
- {
- if (getVertexCount() > 0.75f*DEFAULT_MAX_VERTICES)
- {
- if (mRebuildTime > 8)
- {
- needs_rebuild = TRUE;
- }
-#ifdef DEBUG_AGP
- llwarns << "More than " << DEFAULT_MAX_VERTICES << " in pool type " << (S32)mType << " at rebuild!" << llendl;
-#endif
- }
- }
-
- // rebuild de-allocates 'stale' objects, so we still need to do a rebuild periodically
- if (mRebuildFreq > 0 && mRebuildTime >= mRebuildFreq)
+ if (params.mVertexBuffer.isNull())
{
- needs_rebuild = TRUE;
+ return;
}
- if (needs_rebuild)
+ if (texture)
{
- mGeneration++;
-
- if (mReferences.empty())
+ if (params.mTexture.notNull())
{
- resetIndices(0);
- resetVertexData(0);
- }
- else
- {
- for (std::vector<LLFace*>::iterator iter = mReferences.begin();
- iter != mReferences.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->hasGeometry() && !facep->isState(LLFace::BACKLIST | LLFace::SHARED_GEOM))
- {
- facep->backup();
- }
- }
- S32 tot_verts = 0;
- S32 tot_indices = 0;
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->isState(LLFace::BACKLIST))
- {
- tot_verts += facep->getGeomCount();
- tot_indices += facep->getIndicesCount();
- }
- }
- for (std::vector<LLFace*>::iterator iter = mMoveFace.begin();
- iter != mMoveFace.end(); iter++)
+ params.mTexture->bind();
+ if (params.mTextureMatrix)
{
- LLFace *facep = *iter;
- if (facep->isState(LLFace::BACKLIST))
- {
- tot_verts += facep->getGeomCount();
- tot_indices += facep->getIndicesCount();
- }
- }
-
- resetIndices(tot_indices);
- flushAGP();
- resetVertexData(tot_verts);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *facep = *iter;
- llassert(facep->getPool() == this);
- facep->restore();
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
}
+ params.mTexture->addTextureStats(params.mVSize);
}
- mRebuildTime = 0;
- setDirty();
- }
-
- if (!mMoveFace.empty())
- {
- for (std::vector<LLFace*>::iterator iter = mMoveFace.begin();
- iter != mMoveFace.end(); iter++)
- {
- LLFace *facep = *iter;
- facep->restore();
- enqueue(facep);
- }
- setDirty();
- mMoveFace.reset();
- rebuild_cost++;
- }
- return rebuild_cost;
-}
-
-LLViewerImage *LLDrawPool::getTexture()
-{
- return NULL;
-}
-
-LLViewerImage *LLDrawPool::getDebugTexture()
-{
- return NULL;
-}
-
-void LLDrawPool::removeFaceReference(LLFace *facep)
-{
- if (facep->getReferenceIndex() != -1)
- {
- if (facep->getReferenceIndex() != (S32)mReferences.size())
+ else
{
- LLFace *back = mReferences.back();
- mReferences[facep->getReferenceIndex()] = back;
- back->setReferenceIndex(facep->getReferenceIndex());
+ LLImageGL::unbindTexture(0);
}
- mReferences.pop_back();
}
- facep->setReferenceIndex(-1);
-}
+
+ params.mVertexBuffer->setBuffer(mask);
+ U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+ gPipeline.mTrianglesDrawn += params.mCount/3;
-void LLDrawPool::addFaceReference(LLFace *facep)
-{
- if (-1 == facep->getReferenceIndex())
+ if (params.mTextureMatrix && texture && params.mTexture.notNull())
{
- facep->setReferenceIndex(mReferences.size());
- mReferences.push_back(facep);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
}
}
-U32 LLDrawPool::getTrianglesDrawn() const
+void LLRenderPass::renderActive(U32 type, U32 mask, BOOL texture)
{
- return mIndicesDrawn / 3;
-}
-
-void LLDrawPool::resetTrianglesDrawn()
-{
- mIndicesDrawn = 0;
-}
-
-void LLDrawPool::addIndicesDrawn(const U32 indices)
-{
- mIndicesDrawn += indices;
-}
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
-BOOL LLDrawPool::verify() const
-{
- BOOL ok = TRUE;
- // Verify all indices in the pool are in the right range
- const U32 *indicesp = getRawIndices();
- for (U32 i = 0; i < getIndexCount(); i++)
+ LLSpatialBridge* last_bridge = NULL;
+ glPushMatrix();
+
+ for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i)
{
- if (indicesp[i] > getVertexCount())
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
{
- ok = FALSE;
- llinfos << "Bad index in tree pool!" << llendl;
- }
- }
+ LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition;
+ if (bridge != last_bridge)
+ {
+ glPopMatrix();
+ glPushMatrix();
+ glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
+ last_bridge = bridge;
+ }
- for (std::vector<LLFace*>::const_iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- const LLFace* facep = *iter;
- if (facep->getPool() != this)
- {
- llinfos << "Face in wrong pool!" << llendl;
- facep->printDebugInfo();
- ok = FALSE;
- }
- else if (!facep->verify())
- {
- ok = FALSE;
+ renderGroup(group,type,mask,texture);
}
}
-
- return ok;
-}
-
-void LLDrawPool::printDebugInfo() const
-{
- llinfos << "Pool " << this << " Type: " << getType() << llendl;
- llinfos << "--------------------" << llendl;
- llinfos << "Vertex count: " << getVertexCount() << llendl;
- llinfos << "Normal count: " << getNormalCount() << llendl;
- llinfos << "Indices count: " << getIndexCount() << llendl;
- llinfos << llendl;
-}
-
-
-S32 LLDrawPool::getMemUsage(const BOOL print)
-{
- S32 mem_usage = 0;
-
- mem_usage += sizeof(this);
-
- // Usage beyond the pipeline allocated data (color and mMemory)
- mem_usage += mIndices.getMax() * sizeof(U32);
- mem_usage += mDrawFace.capacity() * sizeof(LLFace *);
- mem_usage += mMoveFace.capacity() * sizeof(LLFace *);
- mem_usage += mReferences.capacity() * sizeof(LLFace *);
-
- mem_usage += mMemory.getSysMemUsage();
- mem_usage += mWeights.getSysMemUsage();
- mem_usage += mClothingWeights.getSysMemUsage();
-
- return mem_usage;
-}
-
-LLColor3 LLDrawPool::getDebugColor() const
-{
- return LLColor3(0.f, 0.f, 0.f);
-}
-
-void LLDrawPool::setDirty()
-{
- mMemory.setDirty();
- mWeights.setDirty();
- mClothingWeights.setDirty();
-}
-
-BOOL LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor = FALSE;
-
-void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4& color)
-{
- if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
- {
- glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV);
- }
- else
- {
- glColor4fv(color.mV);
- }
+
+ glPopMatrix();
}
-void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4U& color)
+void LLRenderPass::renderStatic(U32 type, U32 mask, BOOL texture)
{
- if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
- {
- glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV);
- }
- else
- {
- glColor4ubv(color.mV);
- }
-}
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
-void LLDrawPool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a)
-{
- if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
- {
- glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a);
- }
- else
+ for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mVisibleGroups.begin(); i != gPipeline.mVisibleGroups.end(); ++i)
{
- glColor4f(r,g,b,a);
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
+ {
+ renderGroup(group,type,mask,texture);
+ }
}
}
-
-// virtual
-void LLDrawPool::enableShade()
-{ }
-
-// virtual
-void LLDrawPool::disableShade()
-{ }
-
-// virtual
-void LLDrawPool::setShade(F32 shade)
-{ }
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index c00cbf14e4..007c0a2de3 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -9,270 +9,167 @@
#ifndef LL_LLDRAWPOOL_H
#define LL_LLDRAWPOOL_H
-#include "llagparray.h"
-#include "lldarray.h"
-#include "lldlinked.h"
-#include "llstrider.h"
-#include "llviewerimage.h"
#include "v4coloru.h"
#include "v2math.h"
#include "v3math.h"
-#include "llstrider.h"
+#include "llvertexbuffer.h"
class LLFace;
class LLImageGL;
class LLViewerImage;
+class LLSpatialGroup;
+class LLDrawInfo;
#define DEFAULT_MAX_VERTICES 65535
class LLDrawPool
{
public:
- typedef LLDynamicArray<LLFace*, 128> face_array_t;
-
+ static S32 sNumDrawPools;
+
enum
{
- SHADER_LEVEL_SCATTERING = 2
+ // Correspond to LLPipeline render type
+ POOL_SKY = 1,
+ POOL_STARS,
+ POOL_GROUND,
+ POOL_TERRAIN,
+ POOL_SIMPLE,
+ POOL_BUMP,
+ POOL_AVATAR,
+ POOL_TREE,
+ POOL_ALPHA,
+ POOL_WATER,
+ POOL_ALPHA_POST_WATER,
+ NUM_POOL_TYPES,
};
-
-public:
- LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil);
+
+ LLDrawPool(const U32 type);
virtual ~LLDrawPool();
- static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL);
+ virtual BOOL isDead() = 0;
- void flushAGP(); // Flush the AGP buffers so they can be repacked and reallocated.
- void syncAGP();
+ S32 getId() const { return mId; }
+ U32 getType() const { return mType; }
- virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool.
+ virtual LLViewerImage *getDebugTexture();
virtual void beginRenderPass( S32 pass );
virtual void endRenderPass( S32 pass );
virtual S32 getNumPasses() { return 1; }
virtual void render(S32 pass = 0) = 0;
+ virtual void prerender() = 0;
+ virtual S32 getMaterialAttribIndex() = 0;
+ virtual U32 getVertexDataMask() = 0;
+ virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
+ virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
+
+ static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL);
+ virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool.
+ virtual LLViewerImage* getTexture() = 0;
+ virtual BOOL isFacePool() { return FALSE; }
+ virtual void resetDrawOrders() = 0;
+
+ U32 getTrianglesDrawn() const;
+ void resetTrianglesDrawn();
+ void addIndicesDrawn(const U32 indices);
+
+protected:
+ S32 mVertexShaderLevel;
+ S32 mId;
+ U32 mType; // Type of draw pool
+ S32 mIndicesDrawn;
+};
+
+class LLRenderPass : public LLDrawPool
+{
+public:
+ enum
+ {
+ PASS_SIMPLE = NUM_POOL_TYPES,
+ PASS_FULLBRIGHT,
+ PASS_INVISIBLE,
+ PASS_SHINY,
+ PASS_BUMP,
+ PASS_GRASS,
+ PASS_ALPHA,
+ NUM_RENDER_TYPES,
+ };
+
+ LLRenderPass(const U32 type);
+ virtual ~LLRenderPass();
+ /*virtual*/ LLDrawPool* instancePool();
+ /*vritual*/ S32 getMaterialAttribIndex() { return -1; }
+ /*virtual*/ LLViewerImage* getDebugTexture() { return NULL; }
+ LLViewerImage* getTexture() { return NULL; }
+ BOOL isDead() { return FALSE; }
+ void resetDrawOrders() { }
+
+ virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+ virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
+ virtual void renderStatic(U32 type, U32 mask, BOOL texture = TRUE);
+ virtual void renderActive(U32 type, U32 mask, BOOL texture = TRUE);
+ virtual void renderInvisible(U32 mask);
+ virtual void renderTexture(U32 type, U32 mask);
+
+};
+
+class LLFacePool : public LLDrawPool
+{
+public:
+ typedef std::vector<LLFace*> face_array_t;
+
+ enum
+ {
+ SHADER_LEVEL_SCATTERING = 2
+ };
+
+public:
+ LLFacePool(const U32 type);
+ virtual ~LLFacePool();
+
virtual void renderForSelect() = 0;
- virtual BOOL match(LLFace* last_face, LLFace* facep) { return FALSE; }
+ BOOL isDead() { return mReferences.empty(); }
virtual void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color,
const S32 index_offset = 0, const S32 index_count = 0);
- virtual void prerender() = 0;
- virtual S32 rebuild();
-
- virtual S32 getMaterialAttribIndex() = 0;
-
virtual LLViewerImage *getTexture();
- virtual LLViewerImage *getDebugTexture();
- virtual void dirtyTexture(const LLViewerImage* texturep);
+ virtual void dirtyTextures(const std::set<LLViewerImage*>& textures);
virtual void enqueue(LLFace *face);
virtual BOOL addFace(LLFace *face);
virtual BOOL removeFace(LLFace *face);
virtual BOOL verify() const; // Verify that all data in the draw pool is correct!
- virtual LLColor3 getDebugColor() const; // For AGP debug display
-
+
virtual void resetDrawOrders();
- virtual void resetVertexData(S32 reserve_count);
- virtual void resetIndices(S32 num_indices);
void resetAll();
BOOL moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data = FALSE);
-
- S32 getId() const { return mId; }
- U32 getType() const { return mType; }
-
- const U32 getStride() const;
- inline const U32 getStride(const U32 data_type) const;
- inline const U32 getOffset(const U32 data_type) const;
-
- S32 reserveGeom(U32 count);
- S32 reserveInd (U32 count);
- S32 unReserveGeom(const S32 index, const U32 count);
- S32 unReserveInd(const S32 index, const U32 count);
-
- void bindGLVertexPointer();
- void bindGLTexCoordPointer(const U32 pass=0);
- void bindGLNormalPointer();
- void bindGLBinormalPointer(S32 index);
- void bindGLColorPointer();
- void bindGLVertexWeightPointer(S32 index);
- void bindGLVertexClothingWeightPointer(S32 index);
-
- const U32 getIndexCount() const;
- const U32 getTexCoordCount(const U32 pass=0) const;
- const U32 getVertexCount() const;
- const U32 getNormalCount() const;
- const U32 getBinormalCount() const;
- const U32 getColorCount() const;
- const U32 getVertexWeightCount() const;
-
- void setDirty();
- void setDirtyMemory() { mMemory.setDirty(); }
- void setDirtyWeights() { mWeights.setDirty(); }
-
- const U32* getRawIndices() const { return mIndices.getMem(); }
-
- U32 getIndex(const S32 index) { return mIndices[index]; } // Use to get one index
- U32 *getIndices(const S32 index); // Used to get an array of indices for reading/writing
- void CheckIntegrity(); // DEBUG
-
- const LLVector3& getVertex(const S32 index);
- const LLVector2& getTexCoord(const S32 index, const U32 pass);
- const LLVector3& getNormal(const S32 index);
- const LLVector3& getBinormal(const S32 index);
- const LLColor4U& getColor(const S32 index);
- const F32& getVertexWeight(const S32 index);
- const LLVector4& getClothingWeight(const S32 index);
-
- void setRebuild(const BOOL rebuild);
-
void destroy();
void buildEdges();
- static S32 drawLoop(face_array_t& face_list, const U32* index_array);
- static S32 drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage);
+ static S32 drawLoop(face_array_t& face_list);
+ static S32 drawLoopSetTex(face_array_t& face_list, S32 stage);
void drawLoop();
void renderVisibility();
void addFaceReference(LLFace *facep);
void removeFaceReference(LLFace *facep);
- U32 getTrianglesDrawn() const;
- void resetTrianglesDrawn();
- void addIndicesDrawn(const U32 indices);
void printDebugInfo() const;
- S32 getMemUsage(const BOOL print = FALSE);
- BOOL setUseAGP(BOOL use_agp);
- BOOL canUseAGP() const { return mMemory.isAGP(); } // Return TRUE if this pool can use AGP
+ BOOL isFacePool() { return TRUE; }
- S32 getMaxVertices() const { return mMaxVertices; }
- S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
-
friend class LLFace;
friend class LLPipeline;
public:
-
- enum
- {
- // Correspond to LLPipeline render type
- POOL_SKY = 1,
- POOL_STARS,
- POOL_GROUND,
- POOL_TERRAIN,
- POOL_SIMPLE,
- POOL_MEDIA, // unused
- POOL_BUMP,
- POOL_AVATAR,
- POOL_TREE,
- POOL_TREE_NEW,
- POOL_WATER,
- POOL_CLOUDS,
- POOL_ALPHA,
- POOL_HUD,
- };
-
-
- // If you change the order or add params to these, you also need to adjust the sizes in the
- // mDataSizes array defined in lldrawpool.cpp
- typedef enum e_data_type
- {
- DATA_VERTICES = 0,
- DATA_TEX_COORDS0 = 1,
- DATA_TEX_COORDS1 = 2,
- DATA_TEX_COORDS2 = 3,
- DATA_TEX_COORDS3 = 4,
- DATA_NORMALS = 5,
- DATA_VERTEX_WEIGHTS = 6,
- DATA_CLOTHING_WEIGHTS = 7,
- DATA_BINORMALS = 8,
- DATA_COLORS = 9,
- DATA_MAX_TYPES = 10
- } EDataType;
-
- typedef enum e_data_mask
- {
- DATA_VERTICES_MASK = 1 << DATA_VERTICES,
- DATA_TEX_COORDS0_MASK = 1 << DATA_TEX_COORDS0,
- DATA_TEX_COORDS1_MASK = 1 << DATA_TEX_COORDS1,
- DATA_TEX_COORDS2_MASK = 1 << DATA_TEX_COORDS2,
- DATA_TEX_COORDS3_MASK = 1 << DATA_TEX_COORDS3,
- DATA_NORMALS_MASK = 1 << DATA_NORMALS,
- DATA_VERTEX_WEIGHTS_MASK = 1 << DATA_VERTEX_WEIGHTS,
- DATA_CLOTHING_WEIGHTS_MASK = 1 << DATA_CLOTHING_WEIGHTS,
- DATA_BINORMALS_MASK = 1 << DATA_BINORMALS,
- DATA_COLORS_MASK = 1 << DATA_COLORS,
-
- // Masks for standard types.
- // IL for interleaved, NIL for non-interleaved.
- DATA_SIMPLE_IL_MASK = DATA_VERTICES_MASK | DATA_TEX_COORDS0_MASK | DATA_NORMALS_MASK,
- DATA_SIMPLE_NIL_MASK = 0,
- DATA_BUMP_IL_MASK = DATA_SIMPLE_IL_MASK | DATA_BINORMALS_MASK | DATA_TEX_COORDS1_MASK,
- } EDataMask;
-
face_array_t mDrawFace;
face_array_t mMoveFace;
face_array_t mReferences;
- U32 mDataMaskIL; // Interleaved data
- U32 mDataMaskNIL; // Non-interleaved data
- U32 mDataOffsets[DATA_MAX_TYPES];
- S32 mStride;
-
- S32 mRebuildFreq;
- S32 mRebuildTime;
- S32 mGeneration;
-
-
- S32 mSkippedVertices;
-
- static U32 sDataSizes[DATA_MAX_TYPES];
- static S32 sNumDrawPools;
-
-protected:
- LLAGPArray<U8> mMemory;
- LLAGPArray<F32> mWeights;
- LLAGPArray<LLVector4> mClothingWeights;
- LLAGPArray<U32> mIndices;
-
-public:
-
- BOOL getVertexStrider (LLStrider<LLVector3> &vertices, const U32 index = 0);
- BOOL getTexCoordStrider (LLStrider<LLVector2> &tex_coords, const U32 index = 0, const U32 pass=0);
- BOOL getNormalStrider (LLStrider<LLVector3> &normals, const U32 index = 0);
- BOOL getBinormalStrider (LLStrider<LLVector3> &binormals, const U32 index = 0);
- BOOL getColorStrider (LLStrider<LLColor4U> &colors, const U32 index = 0);
- BOOL getVertexWeightStrider(LLStrider<F32> &vertex_weights, const U32 index = 0);
- BOOL getClothingWeightStrider(LLStrider<LLVector4> &clothing_weights, const U32 index = 0);
-
-public:
- enum { NUM_BUCKETS = 8 }; // Need to change freeListBucket() if NUM_BUCKETS changes
- struct FreeListNode
- {
- U32 count;
- S32 next;
- };
-protected:
- int freeListBucket(U32 count);
- void freeListAddGeom(S32 index, U32 count);
- void freeListAddInd(S32 index, U32 count);
- S32 freeListFindGeom(U32 count);
- S32 freeListFindInd(U32 count);
-
-protected:
- BOOL mUseAGP;
- S32 mVertexShaderLevel;
- S32 mId;
- U32 mType; // Type of draw pool
- S32 mMaxVertices;
- S32 mIndicesDrawn;
- BOOL mCleanupUnused; // Cleanup unused data when too full
-
- S32 mFreeListGeomHead[8];
- S32 mFreeListIndHead[8];
-
public:
class LLOverrideFaceColor
{
@@ -311,38 +208,6 @@ public:
LLDrawPool* mPool;
static BOOL sOverrideFaceColor;
};
-
- virtual void enableShade();
- virtual void disableShade();
- virtual void setShade(F32 shade);
-
};
-inline const U32 LLDrawPool::getStride() const
-{
- return mStride;
-}
-
-inline const U32 LLDrawPool::getOffset(const U32 data_type) const
-{
- return mDataOffsets[data_type];
-}
-
-inline const U32 LLDrawPool::getStride(const U32 data_type) const
-{
- if (mDataMaskIL & (1 << data_type))
- {
- return mStride;
- }
- else if (mDataMaskNIL & (1 << data_type))
- {
- return 0;
- }
- else
- {
- llerrs << "Getting stride for unsupported data type " << data_type << llendl;
- return 0;
- }
-}
-
#endif //LL_LLDRAWPOOL_H
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 8c520f6638..5cb914c37e 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -10,11 +10,11 @@
#include "lldrawpoolalpha.h"
+#include "llglheaders.h"
#include "llviewercontrol.h"
#include "llcriticaldamp.h"
#include "llfasttimer.h"
-#include "llagparray.h"
#include "llcubemap.h"
#include "llsky.h"
#include "llagent.h"
@@ -25,104 +25,25 @@
#include "llviewerobjectlist.h" // For debugging
#include "llviewerwindow.h"
#include "pipeline.h"
-
-const F32 MAX_DIST = 512.f;
-const F32 ALPHA_FALLOFF_START_DISTANCE = 0.8f;
+#include "llviewerregion.h"
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
-LLDrawPoolAlpha::LLDrawPoolAlpha() :
- LLDrawPool(POOL_ALPHA,
- DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK,
- DATA_SIMPLE_NIL_MASK)
+LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
+ LLRenderPass(type)
{
- mRebuiltLastFrame = FALSE;
- mMinDistance = 0.f;
- mMaxDistance = MAX_DIST;
- mInvBinSize = NUM_ALPHA_BINS/(mMaxDistance - mMinDistance);
- mCleanupUnused = TRUE;
- //mRebuildFreq = -1 ; // Only rebuild if nearly full
-
-// for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
-// {
-// mDistanceBins[i].realloc(200);
-// }
-}
-LLDrawPoolAlpha::~LLDrawPoolAlpha()
-{
}
-LLDrawPool *LLDrawPoolAlpha::instancePool()
+LLDrawPoolAlphaPostWater::LLDrawPoolAlphaPostWater()
+: LLDrawPoolAlpha(POOL_ALPHA_POST_WATER)
{
- llerrs << "Should never be calling instancePool on an alpha pool!" << llendl;
- return NULL;
}
-void LLDrawPoolAlpha::enqueue(LLFace *facep)
+LLDrawPoolAlpha::~LLDrawPoolAlpha()
{
- if (!facep->isState(LLFace::GLOBAL))
- {
- facep->mCenterAgent = facep->mCenterLocal * facep->getRenderMatrix();
- }
- facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis();
-
- if (facep->isState(LLFace::BACKLIST))
- {
- mMoveFace.put(facep);
- }
- else
- {
- mDrawFace.put(facep);
- }
-
- {
- S32 dist_bin = lltrunc( (mMaxDistance - (facep->mDistance+32))*mInvBinSize );
-
- if (dist_bin >= NUM_ALPHA_BINS)
- {
- mDistanceBins[NUM_ALPHA_BINS-1].put(facep);
- //mDistanceBins[NUM_ALPHA_BINS-1].push(facep, (U32)(void*)facep->getTexture());
- }
- else if (dist_bin > 0)
- {
- mDistanceBins[dist_bin].put(facep);
- //mDistanceBins[dist_bin].push(facep, (U32)(void*)facep->getTexture());
- }
- else
- {
- mDistanceBins[0].put(facep);
- //mDistanceBins[0].push(facep, (U32)(void*)facep->getTexture());
- }
- }
}
-BOOL LLDrawPoolAlpha::removeFace(LLFace *facep)
-{
- BOOL removed = FALSE;
-
- LLDrawPool::removeFace(facep);
-
- {
- for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
- {
- if (mDistanceBins[i].removeObj(facep) != -1)
- {
- if (removed)
- {
- llerrs << "Warning! " << "Face in multiple distance bins on removal" << llendl;
- }
- removed = TRUE;
- }
- }
- }
- if (removed)
- {
- return TRUE;
- }
-
- return FALSE;
-}
void LLDrawPoolAlpha::prerender()
{
@@ -131,442 +52,270 @@ void LLDrawPoolAlpha::prerender()
void LLDrawPoolAlpha::beginRenderPass(S32 pass)
{
- if (mDrawFace.empty())
- {
- // No alpha objects, early exit.
- return;
- }
-
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- if (gPipeline.getLightingDetail() >= 2)
- {
- glEnableClientState(GL_COLOR_ARRAY);
- }
+ glEnableClientState(GL_COLOR_ARRAY);
}
-
-void LLDrawPoolAlpha::render(S32 pass)
+void setup_clip_plane(BOOL pre_water)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+ F32 height = gAgent.getRegion()->getWaterHeight();
+ BOOL above = gCamera->getOrigin().mV[2] > height ? TRUE : FALSE;
- if (mDrawFace.empty())
- {
- // No alpha objects, early exit.
- return;
- }
-
- GLfloat shiny[4] =
- {
- 0.00f,
- 0.25f,
- 0.5f,
- 0.75f
- };
-
- GLint specularIndex = (mVertexShaderLevel > 0) ?
- gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR] : 0;
+ F64 plane[4];
+
+ plane[0] = 0;
+ plane[1] = 0;
+ plane[2] = above == pre_water ? -1.0 : 1.0;
+ plane[3] = -plane[2] * height;
+
+ glClipPlane(GL_CLIP_PLANE0, plane);
+}
- S32 diffTex = 0;
- S32 envTex = -1;
+void LLDrawPoolAlphaPostWater::render(S32 pass)
+{
+ LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
- if (mVertexShaderLevel > 0) //alpha pass uses same shader as shiny/bump
+ if (gPipeline.hasRenderType(LLDrawPool::POOL_ALPHA))
{
- envTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
- if (envTex >= 0 && cube_map)
- {
- cube_map->bind();
- cube_map->setMatrix(1);
- }
-
- if (specularIndex > 0)
- {
- glVertexAttrib4fARB(specularIndex, 0, 0, 0, 0);
- }
-
- S32 scatterTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
-
- diffTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
+ LLGLEnable clip(GL_CLIP_PLANE0);
+ setup_clip_plane(FALSE);
+ LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater);
}
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
- bindGLNormalPointer();
- if (gPipeline.getLightingDetail() >= 2)
+ else
{
- bindGLColorPointer();
+ LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater);
}
+}
- S32 i, j;
- glAlphaFunc(GL_GREATER,0.01f);
- // This needs to be turned off or there will be lots of artifacting with the clouds - djs
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+void LLDrawPoolAlpha::render(S32 pass)
+{
+ LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+
+ LLGLEnable clip(GL_CLIP_PLANE0);
+ setup_clip_plane(TRUE);
+ render(gPipeline.mAlphaGroups);
+}
+void LLDrawPoolAlpha::render(std::vector<LLSpatialGroup*>& groups)
+{
+ LLGLDepthTest gls_depth(GL_TRUE);
LLGLSPipelineAlpha gls_pipeline_alpha;
- LLDynamicArray<LLFace*>* distance_bins;
- distance_bins = mDistanceBins;
+ gPipeline.enableLightsDynamic(1.f);
+ renderAlpha(getVertexDataMask(), groups);
- S32 num_bins_no_alpha_test = ((gPickAlphaThreshold != 0.f) && gUsePickAlpha) ?
- (NUM_ALPHA_BINS - llmax(2, (S32)(ALPHA_FALLOFF_START_DISTANCE * mInvBinSize))) :
- NUM_ALPHA_BINS;
-
- typedef std::vector<LLFace*> face_list_t;
-
- for (i = 0; i < num_bins_no_alpha_test; i++)
+ if (sShowDebugAlpha)
{
- S32 obj_count = distance_bins[i].count();
-
- if (!obj_count)
- {
- continue;
- }
- else if (i > (NUM_ALPHA_BINS / 2) && obj_count < 100)
- {
- face_list_t pri_queue;
- pri_queue.reserve(distance_bins[i].count());
- for (j = 0; j < distance_bins[i].count(); j++)
- {
- pri_queue.push_back(distance_bins[i][j]);
- }
- std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
-
- for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++)
- {
- const LLFace &face = *(*iter);
- face.enableLights();
- face.bindTexture(diffTex);
- if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
- {
- U8 s = face.getTextureEntry()->getShiny();
- glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
- }
- face.renderIndexed(getRawIndices());
- mIndicesDrawn += face.getIndicesCount();
- }
- }
- else
- {
- S32 count = distance_bins[i].count();
- for (j = 0; j < count; j++)
- {
- const LLFace &face = *distance_bins[i][j];
- face.enableLights();
- face.bindTexture(diffTex);
- if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
- {
- U8 s = face.getTextureEntry()->getShiny();
- glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
- }
- face.renderIndexed(getRawIndices());
- mIndicesDrawn += face.getIndicesCount();
- }
- }
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ glColor4f(1,0,0,1);
+ LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f);
+ LLViewerImage::sSmokeImagep->bind();
+ renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD, groups);
}
+}
- GLfloat ogl_matrix[16];
- gCamera->getOpenGLTransform(ogl_matrix);
+void LLDrawPoolAlpha::renderAlpha(U32 mask, std::vector<LLSpatialGroup*>& groups)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
- for (i = num_bins_no_alpha_test; i < NUM_ALPHA_BINS; i++)
- {
- BOOL use_pri_queue = distance_bins[i].count() < 100;
+ LLSpatialBridge* last_bridge = NULL;
+ LLSpatialPartition* last_part = NULL;
+ glPushMatrix();
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- face_list_t pri_queue;
-
- if (use_pri_queue)
- {
- pri_queue.reserve(distance_bins[i].count());
- for (j = 0; j < distance_bins[i].count(); j++)
- {
- pri_queue.push_back(distance_bins[i][j]);
- }
- std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
- }
-
- S32 count = distance_bins[i].count();
- for (j = 0; j < count; j++)
+ for (std::vector<LLSpatialGroup*>::iterator i = groups.begin(); i != groups.end(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (group->mSpatialPartition->mRenderByGroup &&
+ !group->isDead())
{
- const LLFace &face = use_pri_queue ? *pri_queue[j] : *distance_bins[i][j];
- F32 fade_value = face.mAlphaFade * gPickAlphaThreshold;
-
- face.enableLights();
-
- if (fade_value < 1.f)
+ LLSpatialPartition* part = group->mSpatialPartition;
+ if (part != last_part)
{
+ LLSpatialBridge* bridge = part->asBridge();
+ if (bridge != last_bridge)
{
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
- glAlphaFunc(GL_LESS, fade_value);
- glBlendFunc(GL_ZERO, GL_ONE);
- LLViewerImage::bindTexture(gPipeline.mAlphaSizzleImagep, diffTex);
- LLVector4 s_params(ogl_matrix[2], ogl_matrix[6], ogl_matrix[10], ogl_matrix[14]);
- LLVector4 t_params(ogl_matrix[1], ogl_matrix[5], ogl_matrix[9], ogl_matrix[13]);
-
- LLGLEnable gls_texgen_s(GL_TEXTURE_GEN_S);
- LLGLEnable gls_texgen_t(GL_TEXTURE_GEN_T);
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGenfv(GL_S, GL_OBJECT_PLANE, s_params.mV);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, t_params.mV);
- if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
+ glPopMatrix();
+ glPushMatrix();
+ if (bridge)
{
- U8 s = face.getTextureEntry()->getShiny();
- glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
+ glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
}
- face.renderIndexed(getRawIndices());
+ last_bridge = bridge;
}
- {
- // should get GL_GREATER to work, as it's faster
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LESS);
- glAlphaFunc(GL_GEQUAL, fade_value);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- face.bindTexture(diffTex);
- if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
- {
- U8 s = face.getTextureEntry()->getShiny();
- glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
- }
- face.renderIndexed(getRawIndices());
- }
+// if (!last_part || part->mDepthMask != last_part->mDepthMask)
+// {
+// glDepthMask(part->mDepthMask);
+// }
+ last_part = part;
}
- // render opaque portion of actual texture
- glAlphaFunc(GL_GREATER, 0.98f);
-
- face.bindTexture(diffTex);
- face.renderIndexed(getRawIndices());
-
- glAlphaFunc(GL_GREATER, 0.01f);
-
- mIndicesDrawn += face.getIndicesCount();
+ renderGroupAlpha(group,LLRenderPass::PASS_ALPHA,mask,TRUE);
}
}
+
+ glPopMatrix();
+}
- if (mVertexShaderLevel > 0) //single pass shader driven shiny/bump
- {
- gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
- if (envTex >= 0 && cube_map)
- {
- cube_map->restoreMatrix();
- }
- gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
-
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
- }
+void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask, std::vector<LLSpatialGroup*>& groups)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
- if (sShowDebugAlpha)
+ LLSpatialBridge* last_bridge = NULL;
+ LLSpatialPartition* last_part = NULL;
+ glPushMatrix();
+
+ for (std::vector<LLSpatialGroup*>::iterator i = groups.begin(); i != groups.end(); ++i)
{
- gPipeline.disableLights();
- if ((mVertexShaderLevel > 0))
+ LLSpatialGroup* group = *i;
+ if (group->mSpatialPartition->mRenderByGroup &&
+ !group->isDead())
{
- gPipeline.mHighlightProgram.bind();
- }
-
- LLViewerImage::sSmokeImagep->bind();
- LLOverrideFaceColor override_color(this, 1.f, 0.f, 0.f, 1.f);
- glColor4f(1.f, 0.f, 0.f, 1.f); // in case vertex shaders are enabled
- glDisableClientState(GL_COLOR_ARRAY);
-
- for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
- {
- if (distance_bins[i].count() < 100)
+ LLSpatialPartition* part = group->mSpatialPartition;
+ if (part != last_part)
{
- face_list_t pri_queue;
- pri_queue.reserve(distance_bins[i].count());
- for (j = 0; j < distance_bins[i].count(); j++)
- {
- pri_queue.push_back(distance_bins[i][j]);
- }
- std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
-
- for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++)
+ LLSpatialBridge* bridge = part->asBridge();
+ if (bridge != last_bridge)
{
- const LLFace &face = *(*iter);
- face.renderIndexed(getRawIndices());
- mIndicesDrawn += face.getIndicesCount();
+ glPopMatrix();
+ glPushMatrix();
+ if (bridge)
+ {
+ glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
+ }
+ last_bridge = bridge;
}
+
+ last_part = part;
}
- else
+
+ std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
+
+ for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
- for (j = 0; j < distance_bins[i].count(); j++)
+ LLDrawInfo& params = **k;
+
+ if (params.mParticle)
{
- const LLFace &face = *distance_bins[i][j];
- face.renderIndexed(getRawIndices());
- mIndicesDrawn += face.getIndicesCount();
+ continue;
}
+ params.mVertexBuffer->setBuffer(mask);
+ U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+
+ addIndicesDrawn(params.mCount);
}
}
-
- if ((mVertexShaderLevel > 0))
- {
- gPipeline.mHighlightProgram.unbind();
- }
-
}
-
+ glPopMatrix();
}
-void LLDrawPoolAlpha::renderForSelect()
-{
- if (mDrawFace.empty() || !mMemory.count())
- {
- return;
- }
-
- // force faces on focus object to proper alpha cutoff based on object bbox distance
- if (gAgent.getFocusObject())
- {
- LLDrawable* drawablep = gAgent.getFocusObject()->mDrawable;
-
- if (drawablep)
- {
- const S32 num_faces = drawablep->getNumFaces();
-
- for (S32 f = 0; f < num_faces; f++)
- {
- LLFace* facep = drawablep->getFace(f);
- facep->mDistance = gAgent.getFocusObjectDist();
- }
- }
- }
+void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
+{
+ BOOL light_enabled = TRUE;
- glEnableClientState (GL_VERTEX_ARRAY);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[type];
+
+ U32 prim_type = GL_TRIANGLES;
- LLGLSObjectSelectAlpha gls_alpha;
+ //F32 width = (F32) gViewerWindow->getWindowDisplayWidth();
- glBlendFunc(GL_ONE, GL_ZERO);
- if (gPickTransparent)
+ //F32 view = gCamera->getView();
+
+ if (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CLOUDS)
{
- glAlphaFunc(GL_GEQUAL, 0.f);
+ glAlphaFunc(GL_GREATER, 0.f);
}
else
{
- glAlphaFunc(GL_GEQUAL, gPickAlphaThreshold);
+ glAlphaFunc(GL_GREATER, 0.01f);
}
- bindGLVertexPointer();
- bindGLTexCoordPointer();
-
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
+ /*LLGLEnable point_sprite(GL_POINT_SPRITE_ARB);
- LLDynamicArray<LLFace*>* distance_bins;
- distance_bins = mDistanceBins;
-
- S32 i;
- S32 j;
+ if (gGLManager.mHasPointParameters)
+ {
+ glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
+ glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 0.f);
+ glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, width*16.f);
+ glPointSize(width/(view*view));
+ }*/
- for (i = 0; i < NUM_ALPHA_BINS; i++)
+ for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
- S32 distance_bin_size = distance_bins[i].count();
- if (distance_bin_size)
+ LLDrawInfo& params = **k;
+ if (texture && params.mTexture.notNull())
{
- for (j = 0; j < distance_bin_size; j++)
+ params.mTexture->bind();
+ params.mTexture->addTextureStats(params.mVSize);
+ if (params.mTextureMatrix)
{
- const LLFace &face = *distance_bins[i][j];
-
- if (face.getDrawable() && !face.getDrawable()->isDead() && (face.getViewerObject()->mGLName))
- {
- face.bindTexture();
- face.renderForSelect();
- }
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
}
}
- }
-
- glAlphaFunc(GL_GREATER, 0.01f);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-}
-
-
-void LLDrawPoolAlpha::renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset, const S32 index_count)
-{
- facep->renderSelected(image, color, index_offset, index_count);
-}
-
-
-void LLDrawPoolAlpha::resetDrawOrders()
-{
- LLDrawPool::resetDrawOrders();
-
- for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
- {
- mDistanceBins[i].resize(0);
- }
-}
-
-BOOL LLDrawPoolAlpha::verify() const
-{
- S32 i, j;
- BOOL ok;
- ok = LLDrawPool::verify();
- for (i = 0; i < NUM_ALPHA_BINS; i++)
- {
- for (j = 0; j < mDistanceBins[i].count(); j++)
+
+ if (params.mFullbright)
{
- const LLFace &face = *mDistanceBins[i][j];
- if (!face.verify())
+ if (light_enabled)
{
- ok = FALSE;
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ light_enabled = FALSE;
}
}
- }
- return ok;
-}
-
-LLViewerImage *LLDrawPoolAlpha::getDebugTexture()
-{
- return LLViewerImage::sSmokeImagep;
-}
+ else if (!light_enabled)
+ {
+ gPipeline.enableLightsDynamic(1.f);
+ light_enabled = TRUE;
+ }
+ /*if (params.mParticle)
+ {
+ F32 size = params.mPartSize;
+ size *= size;
+ float param[] = { 0, 0, 0.01f/size*view*view };
+ prim_type = GL_POINTS;
+ glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param);
+ }
+ else*/
+ {
+ prim_type = GL_TRIANGLES;
+ }
-LLColor3 LLDrawPoolAlpha::getDebugColor() const
-{
- return LLColor3(1.f, 0.f, 0.f);
-}
+ params.mVertexBuffer->setBuffer(mask);
+ U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(prim_type, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+
+ addIndicesDrawn(params.mCount);
-S32 LLDrawPoolAlpha::getMaterialAttribIndex()
-{
- return gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
-}
+ if (params.mTextureMatrix && texture && params.mTexture.notNull())
+ {
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ }
-// virtual
-void LLDrawPoolAlpha::enableShade()
-{
- glDisableClientState(GL_COLOR_ARRAY);
-}
+ if (!light_enabled)
+ {
+ gPipeline.enableLightsDynamic(1.f);
+ }
-// virtual
-void LLDrawPoolAlpha::disableShade()
-{
- glEnableClientState(GL_COLOR_ARRAY);
-}
+ /*glPointSize(1.f);
-// virtual
-void LLDrawPoolAlpha::setShade(F32 shade)
-{
- glColor4f(0,0,0,shade);
-}
+ if (gGLManager.mHasPointParameters)
+ {
+ float param[] = {1, 0, 0 };
+ glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param);
+ }*/
+}
diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h
index 6f24959e50..e33bbacd82 100644
--- a/indra/newview/lldrawpoolalpha.h
+++ b/indra/newview/lldrawpoolalpha.h
@@ -10,55 +10,43 @@
#define LL_LLDRAWPOOLALPHA_H
#include "lldrawpool.h"
-#include "llviewerimage.h"
#include "llframetimer.h"
class LLFace;
class LLColor4;
-class LLDrawPoolAlpha: public LLDrawPool
+class LLDrawPoolAlpha: public LLRenderPass
{
public:
- LLDrawPoolAlpha();
- /*virtual*/ ~LLDrawPoolAlpha();
-
- /*virtual*/ LLDrawPool *instancePool();
-
- /*virtual*/ void beginRenderPass(S32 pass = 0);
- /*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color,
- const S32 index_offset = 0, const S32 index_count = 0);
- /*virtual*/ void prerender();
- /*virtual*/ void renderForSelect();
-
- /*virtual*/ void enqueue(LLFace *face);
- /*virtual*/ BOOL removeFace(LLFace *face);
- /*virtual*/ void resetDrawOrders();
-
- /*virtual*/ void enableShade();
- /*virtual*/ void disableShade();
- /*virtual*/ void setShade(F32 shade);
-
-
- virtual S32 getMaterialAttribIndex();
-
- BOOL mRebuiltLastFrame;
enum
{
- NUM_ALPHA_BINS = 1024
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_COLOR |
+ LLVertexBuffer::MAP_TEXCOORD
};
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+ LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA);
+ /*virtual*/ ~LLDrawPoolAlpha();
- /*virtual*/ BOOL verify() const;
- /*virtual*/ LLViewerImage *getDebugTexture();
- /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
+ /*virtual*/ void beginRenderPass(S32 pass = 0);
+ virtual void render(S32 pass = 0);
+ void render(std::vector<LLSpatialGroup*>& groups);
+ /*virtual*/ void prerender();
+ void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
+ void renderAlpha(U32 mask, std::vector<LLSpatialGroup*>& groups);
+ void renderAlphaHighlight(U32 mask, std::vector<LLSpatialGroup*>& groups);
+
static BOOL sShowDebugAlpha;
-protected:
- F32 mMinDistance;
- F32 mMaxDistance;
- F32 mInvBinSize;
+};
- LLDynamicArray<LLFace*> mDistanceBins[NUM_ALPHA_BINS];
+class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha
+{
+public:
+ LLDrawPoolAlphaPostWater();
+ virtual void render(S32 pass = 0);
};
#endif // LL_LLDRAWPOOLALPHA_H
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index dfe75084b5..9b9825deff 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -13,7 +13,6 @@
#include "llvoavatar.h"
#include "m3math.h"
-#include "llagparray.h"
#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
@@ -23,6 +22,11 @@
#include "noise.h"
#include "pipeline.h"
+static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
+static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
+static U32 sShaderLevel = 0;
+static LLGLSLShader* sVertexProgram = NULL;
+
extern F32 gFrameDTClamped;
extern BOOL gUseGLPick;
@@ -56,53 +60,13 @@ S32 AVATAR_VERTEX_BYTES = 48;
BOOL gAvatarEmbossBumpMap = FALSE;
+static BOOL sRenderingSkinned = FALSE;
LLDrawPoolAvatar::LLDrawPoolAvatar() :
-LLDrawPool(POOL_AVATAR,
- DATA_SIMPLE_IL_MASK,
- DATA_VERTEX_WEIGHTS_MASK | DATA_CLOTHING_WEIGHTS_MASK )
+LLFacePool(POOL_AVATAR)
{
- mCleanupUnused = FALSE;
-
- // Overide the data layout
- mDataMaskIL = 0;
- mStride = 0;
- for (S32 i = 0; i < DATA_MAX_TYPES; i++)
- {
- mDataOffsets[i] = 0;
- }
-
- // Note: padding is to speed up SSE code
- mDataMaskIL |= DATA_VERTICES_MASK;
- mDataOffsets[DATA_VERTICES] = mStride;
- mStride += sDataSizes[DATA_VERTICES];
-
- mStride += 4;
-
- mDataMaskIL |= DATA_NORMALS_MASK;
- mDataOffsets[DATA_NORMALS] = mStride;
- mStride += sDataSizes[DATA_NORMALS];
-
- mStride += 4;
-
- // Note: binormals are stripped off in software blending
- mDataMaskIL |= DATA_BINORMALS_MASK;
- mDataOffsets[DATA_BINORMALS] = mStride;
- mStride += sDataSizes[DATA_BINORMALS];
-
- mStride += 4; // To keep the structure 16-byte aligned (for SSE happiness)
-
- mDataMaskIL |= DATA_TEX_COORDS0_MASK;
- mDataOffsets[DATA_TEX_COORDS0] = mStride;
- mStride += sDataSizes[DATA_TEX_COORDS0];
-
- mDataMaskIL |= DATA_TEX_COORDS1_MASK;
- mDataOffsets[DATA_TEX_COORDS1] = mStride;
- mStride += sDataSizes[DATA_TEX_COORDS1];
-
//LLDebugVarMessageBox::show("acceleration", &CLOTHING_ACCEL_FORCE_FACTOR, 10.f, 0.1f);
- //LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f);
-
+ //LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f);
}
//-----------------------------------------------------------------------------
@@ -113,41 +77,194 @@ LLDrawPool *LLDrawPoolAvatar::instancePool()
return new LLDrawPoolAvatar();
}
+BOOL gRenderAvatar = TRUE;
+static LLMatrix4 sModelViewMatrix = LLMatrix4();
-S32 LLDrawPoolAvatar::rebuild()
+S32 LLDrawPoolAvatar::getVertexShaderLevel() const
{
- mRebuildTime++;
- if (mRebuildTime > mRebuildFreq)
- {
- flushAGP();
-
- mRebuildTime = 0;
- }
-
- return 0;
+ return (S32) gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR);
}
-BOOL gRenderAvatar = TRUE;
-
void LLDrawPoolAvatar::prerender()
{
mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR);
+ sShaderLevel = mVertexShaderLevel;
+
+ if (sShaderLevel > 0)
+ {
+ sBufferUsage = GL_STATIC_DRAW_ARB;
+ }
+ else
+ {
+ sBufferUsage = GL_STREAM_DRAW_ARB;
+ }
+}
+
+LLMatrix4& LLDrawPoolAvatar::getModelView()
+{
+ return sModelViewMatrix;
}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
+
+S32 LLDrawPoolAvatar::getNumPasses()
+{
+ return 3;
+}
+
void LLDrawPoolAvatar::render(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
- renderAvatars(NULL); // render all avatars
+ renderAvatars(NULL, pass); // render all avatars
+}
+
+void LLDrawPoolAvatar::beginRenderPass(S32 pass)
+{
+ //reset vertex buffer mappings
+ LLVertexBuffer::unbind();
+
+ switch (pass)
+ {
+ case 0:
+ beginFootShadow();
+ break;
+ case 1:
+ glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) sModelViewMatrix.mMatrix);
+ beginRigid();
+ break;
+ case 2:
+ beginSkinned();
+ break;
+ }
+}
+
+void LLDrawPoolAvatar::endRenderPass(S32 pass)
+{
+ switch (pass)
+ {
+ case 0:
+ endFootShadow();
+ break;
+ case 1:
+ endRigid();
+ break;
+ case 2:
+ endSkinned();
+ }
+}
+
+void LLDrawPoolAvatar::beginFootShadow()
+{
+ glDepthMask(GL_FALSE);
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void LLDrawPoolAvatar::endFootShadow()
+{
+ gPipeline.enableLightsDynamic(1.f);
+ glDepthMask(GL_TRUE);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void LLDrawPoolAvatar::beginRigid()
+{
+ sVertexProgram = &gPipeline.mAvatarEyeballProgram;
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ if (sShaderLevel > 0)
+ { //eyeballs render with the specular shader
+ gPipeline.mAvatarEyeballProgram.bind();
+ gPipeline.mMaterialIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
+ gPipeline.mSpecularIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR];
+ }
+}
+
+void LLDrawPoolAvatar::endRigid()
+{
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void LLDrawPoolAvatar::beginSkinned()
+{
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ sVertexProgram = &gPipeline.mAvatarProgram;
+
+ if (sShaderLevel > 0) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ if (sShaderLevel >= SHADER_LEVEL_BUMP)
+ {
+ gPipeline.mMaterialIndex = sVertexProgram->mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
+ gPipeline.mSpecularIndex = sVertexProgram->mAttribute[LLPipeline::GLSL_SPECULAR_COLOR];
+ }
+ sVertexProgram->bind();
+ if (sShaderLevel >= SHADER_LEVEL_CLOTH)
+ {
+ enable_cloth_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]);
+ }
+ enable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
+
+ if (sShaderLevel >= SHADER_LEVEL_BUMP)
+ {
+ enable_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL]);
+ }
+
+ sVertexProgram->enableTexture(LLPipeline::GLSL_BUMP_MAP);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ }
}
-void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders)
+void LLDrawPoolAvatar::endSkinned()
{
- if (no_shaders)
+ // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
+ if (sShaderLevel > 0)
{
- mVertexShaderLevel = 0;
+ sRenderingSkinned = FALSE;
+ sVertexProgram->disableTexture(LLPipeline::GLSL_BUMP_MAP);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ disable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
+ if (sShaderLevel >= SHADER_LEVEL_BUMP)
+ {
+ disable_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL]);
+ }
+ if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
+ {
+ disable_cloth_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]);
+ }
+
+ sVertexProgram->unbind();
+ }
+
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+
+void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
+{
+ if (pass == -1)
+ {
+ for (S32 i = 1; i < getNumPasses(); i++)
+ { //skip foot shadows
+ prerender();
+ beginRenderPass(i);
+ renderAvatars(single_avatar, i);
+ endRenderPass(i);
+ }
+
+ return;
}
if (!gRenderAvatar)
@@ -176,13 +293,95 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders)
avatarp = (LLVOAvatar *)(facep->getDrawable()->getVObj());
}
- if (avatarp->isDead() || avatarp->mDrawable.isNull())
+ if (avatarp->isDead() || avatarp->mDrawable.isNull())
{
return;
}
LLOverrideFaceColor color(this, 1.0f, 1.0f, 1.0f, 1.0f);
+ if (pass == 0)
+ {
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS))
+ {
+ mIndicesDrawn += avatarp->renderFootShadows();
+ }
+ return;
+ }
+
+ if (avatarp->mSpecialRenderMode == 0) // normal
+ {
+ gPipeline.enableLightsAvatar(avatarp->mDrawable->getSunShadowFactor());
+ }
+ else if (avatarp->mSpecialRenderMode == 1) // anim preview
+ {
+ gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
+ }
+ else // 2=image preview, 3=morph view
+ {
+ gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
+ }
+
+ if (pass == 1)
+ {
+ // render rigid meshes (eyeballs) first
+ mIndicesDrawn += avatarp->renderRigid();
+
+ if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest)
+ {
+ LLVector3 orig_pos_root = avatarp->mRoot.getPosition();
+ LLVector3 next_pos_root = orig_pos_root;
+ for (S32 i = 0; i < NUM_TEST_AVATARS; i++)
+ {
+ next_pos_root.mV[VX] += 1.f;
+ if (i % 5 == 0)
+ {
+ next_pos_root.mV[VY] += 1.f;
+ next_pos_root.mV[VX] = orig_pos_root.mV[VX];
+ }
+
+ avatarp->mRoot.setPosition(next_pos_root); // avatar load test
+ avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test
+
+ mIndicesDrawn += avatarp->renderRigid();
+ }
+ avatarp->mRoot.setPosition(orig_pos_root); // avatar load test
+ avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test
+ }
+ return;
+ }
+
+
+ if (sShaderLevel > 0)
+ {
+ gPipeline.mAvatarMatrixParam = sVertexProgram->mUniform[LLPipeline::GLSL_AVATAR_MATRIX];
+ }
+
+ if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
+ {
+ LLMatrix4 rot_mat;
+ gCamera->getMatrixToLocal(rot_mat);
+ LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
+ rot_mat *= cfr;
+
+ LLVector4 wind;
+ wind.setVec(avatarp->mWindVec);
+ wind.mV[VW] = 0;
+ wind = wind * rot_mat;
+ wind.mV[VW] = avatarp->mWindVec.mV[VW];
+
+ sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_WIND, wind.mV);
+ F32 phase = -1.f * (avatarp->mRipplePhase);
+
+ F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
+ LLVector4 sin_params(freq, freq, freq, phase);
+ sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_SINWAVE, sin_params.mV);
+
+ LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
+ gravity = gravity * rot_mat;
+ sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_GRAVITY, gravity.mV);
+ }
+
if( !single_avatar || (avatarp == single_avatar) )
{
if (LLVOAvatar::sShowCollisionVolumes)
@@ -191,8 +390,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders)
avatarp->renderCollisionVolumes();
}
- LLGLEnable normalize(GL_NORMALIZE);
-
if (avatarp->mIsSelf && LLAgent::sDebugDisplayTarget)
{
LLGLSNoTexture gls_no_texture;
@@ -248,171 +445,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders)
color.setColor(1.0f, 1.0f, 1.0f, 1.0f);
}
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- LLGLSLShader* vertex_program = &gPipeline.mAvatarProgram;
- if (mVertexShaderLevel > 0)
- {
- gPipeline.mAvatarMatrixParam = vertex_program->mUniform[LLPipeline::GLSL_AVATAR_MATRIX];
- }
-
- //--------------------------------------------------------------------------------
- // this is where we first hit the software blending path
- // if enabled, we need to set up the proper buffers and avoid setting other state
- //--------------------------------------------------------------------------------
- if (!(mVertexShaderLevel > 0))
- {
-
- // performance could be increased by better utilizing the buffers, for example, only using 1k buffers for lo-res
- // avatars. But the only problem with using fewer buffers is that we're more likely to wait for a fence to complete
-
- // vertex format:
- // vertices 12
- // texcoords 8
- // normals 12
- // binormals 12
- // padding 4
- // total 48
-
- // Rotate to the next buffer, round-robin.
- gPipeline.bufferRotate();
-
- // Wait until the hardware is done reading the last set of vertices from the buffer before writing the next set.
- gPipeline.bufferWaitFence();
-
- // Need to do this because we may be rendering without AGP even in AGP mode
- U8* buffer_offset_start = gPipeline.bufferGetScratchMemory();
- glVertexPointer( 3, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_POS);
- glTexCoordPointer(2, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_TEX0);
- glNormalPointer( GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_NORMAL);
-
- }
-
- if ((mVertexShaderLevel > 0)) // for hardware blending
- {
- bindGLVertexPointer();
- bindGLNormalPointer();
- bindGLTexCoordPointer(0);
- }
-
- if ((mVertexShaderLevel > 0))
- { //eyeballs render with the specular shader
- gPipeline.mAvatarEyeballProgram.bind();
- gPipeline.mMaterialIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
- gPipeline.mSpecularIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR];
-
- S32 index = gPipeline.mAvatarEyeballProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gSky.mVOSkyp->getScatterMap()->bind(index);
-
- glActiveTextureARB(GL_TEXTURE0_ARB);
- }
-
- if (avatarp->mSpecialRenderMode == 0) // normal
- {
- gPipeline.enableLightsAvatar(avatarp->mDrawable->getSunShadowFactor());
- }
- else if (avatarp->mSpecialRenderMode == 1) // anim preview
- {
- gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
- }
- else // 2=image preview, 3=morph view
- {
- gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
- }
-
- // render rigid meshes (eyeballs) first
- mIndicesDrawn += avatarp->renderRigid();
-
- if ((mVertexShaderLevel > 0))
- {
- gPipeline.mAvatarEyeballProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- }
-
- if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest)
- {
- LLVector3 orig_pos_root = avatarp->mRoot.getPosition();
- LLVector3 next_pos_root = orig_pos_root;
- for (S32 i = 0; i < NUM_TEST_AVATARS; i++)
- {
- next_pos_root.mV[VX] += 1.f;
- if (i % 5 == 0)
- {
- next_pos_root.mV[VY] += 1.f;
- next_pos_root.mV[VX] = orig_pos_root.mV[VX];
- }
-
- avatarp->mRoot.setPosition(next_pos_root); // avatar load test
- avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test
-
- mIndicesDrawn += avatarp->renderRigid();
- }
- avatarp->mRoot.setPosition(orig_pos_root); // avatar load test
- avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test
- }
-
- if ((mVertexShaderLevel > 0)) // for hardware blending
- {
- glClientActiveTextureARB(GL_TEXTURE1_ARB);
- if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP))
- {
- bindGLTexCoordPointer(1);
-
- bindGLBinormalPointer(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]);
- gPipeline.mMaterialIndex = vertex_program->mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
- gPipeline.mSpecularIndex = vertex_program->mAttribute[LLPipeline::GLSL_SPECULAR_COLOR];
- }
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- bindGLTexCoordPointer(0);
- vertex_program->bind();
- bindGLVertexWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
- if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH))
- {
- bindGLVertexClothingWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]);
- enable_cloth_weights(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]);
- }
- enable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
-
- if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP))
- {
- enable_binormals(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]);
- }
-
- vertex_program->enableTexture(LLPipeline::GLSL_BUMP_MAP);
- S32 index = vertex_program->enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gSky.mVOSkyp->getScatterMap()->bind(index);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- }
-
- if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH))
- {
- LLMatrix4 rot_mat;
- gCamera->getMatrixToLocal(rot_mat);
- LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
- rot_mat *= cfr;
-
- LLVector4 wind;
- wind.setVec(avatarp->mWindVec);
- wind.mV[VW] = 0;
- wind = wind * rot_mat;
- wind.mV[VW] = avatarp->mWindVec.mV[VW];
-
- vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_WIND, wind.mV);
- F32 phase = -1.f * (avatarp->mRipplePhase);
-
- F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
- LLVector4 sin_params(freq, freq, freq, phase);
- vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_SINWAVE, sin_params.mV);
-
- LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
- gravity = gravity * rot_mat;
- vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_GRAVITY, gravity.mV);
- }
-
mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
-
+
if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest)
{
LLVector3 orig_pos_root = avatarp->mRoot.getPosition();
@@ -434,31 +468,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders)
avatarp->mRoot.setPosition(orig_pos_root); // avatar load test
avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test
}
-
- // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
- if (!(mVertexShaderLevel > 0))
- {
- // want for the previously bound fence to finish
- gPipeline.bufferSendFence();
- }
- else
- {
- vertex_program->disableTexture(LLPipeline::GLSL_BUMP_MAP);
- vertex_program->disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- disable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
- if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP))
- {
- disable_binormals(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]);
- }
- if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH))
- {
- disable_cloth_weights(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]);
- }
-
- vertex_program->unbind();
- }
}
}
@@ -471,14 +480,13 @@ void LLDrawPoolAvatar::renderForSelect()
{
return;
}
- //gGLSObjectSelectDepthAlpha.set();
-
+
if (!gRenderAvatar)
{
return;
}
- if (mDrawFace.empty() || !mMemory.count())
+ if (mDrawFace.empty())
{
return;
}
@@ -498,80 +506,38 @@ void LLDrawPoolAvatar::renderForSelect()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- LLGLSLShader* vertex_program = &gPipeline.mAvatarPickProgram;
- if (mVertexShaderLevel > 0)
+ glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) sModelViewMatrix.mMatrix);
+ sVertexProgram = &gPipeline.mAvatarPickProgram;
+ if (sShaderLevel > 0)
{
- gPipeline.mAvatarMatrixParam = vertex_program->mUniform[LLPipeline::GLSL_AVATAR_MATRIX];
+ gPipeline.mAvatarMatrixParam = sVertexProgram->mUniform[LLPipeline::GLSL_AVATAR_MATRIX];
}
glAlphaFunc(GL_GEQUAL, 0.2f);
glBlendFunc(GL_ONE, GL_ZERO);
- //--------------------------------------------------------------------------------
- // this is where we first hit the software blending path
- // if enabled, we need to set up the proper buffers and avoid setting other state
- //--------------------------------------------------------------------------------
- if (!(mVertexShaderLevel > 0) || gUseGLPick)
- {
-
- // Rotate to the next buffer, round-robin.
- gPipeline.bufferRotate();
-
- // Wait until the hardware is done reading the last set of vertices from the buffer before writing the next set.
- gPipeline.bufferWaitFence();
-
- // Need to do this because we may be rendering without AGP even in AGP mode
- U8* buffer_offset_start = gPipeline.bufferGetScratchMemory();
- glVertexPointer( 3, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_POS);
- glTexCoordPointer(2, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_TEX0);
- glNormalPointer( GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_NORMAL);
- }
-
S32 name = avatarp->mDrawable->getVObj()->mGLName;
LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name);
glColor4ubv(color.mV);
- if ((mVertexShaderLevel > 0) && !gUseGLPick) // for hardware blending
- {
- bindGLVertexPointer();
- bindGLNormalPointer();
- bindGLTexCoordPointer(0);
- }
-
// render rigid meshes (eyeballs) first
- mIndicesDrawn += avatarp->renderRigid();
+ //mIndicesDrawn += avatarp->renderRigid();
- if ((mVertexShaderLevel > 0) && !gUseGLPick) // for hardware blending
+ if ((sShaderLevel > 0) && !gUseGLPick) // for hardware blending
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
- bindGLTexCoordPointer(0);
- vertex_program->bind();
- bindGLVertexWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
- /*if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH))
- {
- bindGLVertexClothingWeightPointer();
- enable_cloth_weights();
- }*/
- enable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ enable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
}
-
+
mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
- if (!(mVertexShaderLevel > 0) || gUseGLPick)
+ if ((sShaderLevel > 0) && !gUseGLPick)
{
- // want for the previously bound fence to finish
- gPipeline.bufferSendFence();
- }
- else
- {
- vertex_program->unbind();
- disable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
-
- /*if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH))
- {
- disable_cloth_weights();
- }*/
+ sRenderingSkinned = FALSE;
+ sVertexProgram->unbind();
+ disable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]);
}
glAlphaFunc(GL_GREATER, 0.01f);
@@ -608,3 +574,46 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
{
return LLColor3(0.f, 1.f, 0.f);
}
+
+LLVertexBufferAvatar::LLVertexBufferAvatar()
+: LLVertexBuffer(sDataMask,
+ gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR) > 0 ?
+ GL_STATIC_DRAW_ARB :
+ GL_STREAM_DRAW_ARB)
+{
+
+}
+
+
+void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const
+{
+ if (sRenderingSkinned)
+ {
+ U8* base = useVBOs() ? NULL : mMappedData;
+
+ glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0));
+ glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL]));
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
+
+ set_vertex_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT]));
+
+ if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP)
+ {
+ set_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
+ }
+
+ if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)
+ {
+ set_vertex_clothing_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
+ }
+ }
+ else
+ {
+ LLVertexBuffer::setupVertexBuffer(data_mask);
+ }
+}
+
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 0d706b012b..e0b1f2098d 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -13,7 +13,7 @@
class LLVOAvatar;
-class LLDrawPoolAvatar : public LLDrawPool
+class LLDrawPoolAvatar : public LLFacePool
{
protected:
S32 mNumFaces;
@@ -24,21 +24,48 @@ public:
SHADER_LEVEL_CLOTH = 3
};
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD |
+ LLVertexBuffer::MAP_WEIGHT |
+ LLVertexBuffer::MAP_CLOTHWEIGHT |
+ LLVertexBuffer::MAP_BINORMAL
+
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+ virtual S32 getVertexShaderLevel() const;
+
LLDrawPoolAvatar();
+ static LLMatrix4& getModelView();
+
/*virtual*/ LLDrawPool *instancePool();
+ /*virtual*/ S32 getNumPasses();
+ /*virtual*/ void beginRenderPass(S32 pass);
+ /*virtual*/ void endRenderPass(S32 pass);
/*virtual*/ void prerender();
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void renderForSelect();
- /*virtual*/ S32 rebuild();
+ void beginRigid();
+ void beginFootShadow();
+ void beginSkinned();
+
+ void endRigid();
+ void endFootShadow();
+ void endSkinned();
+
/*virtual*/ LLViewerImage *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
virtual S32 getMaterialAttribIndex() { return 0; }
- void renderAvatars(LLVOAvatar *single_avatar, BOOL no_shaders = FALSE); // renders only one avatar if single_avatar is not null.
+ void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null.
};
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 68fa88c456..377dbea2d0 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -18,12 +18,10 @@
#include "m4math.h"
#include "llagent.h"
-#include "llagparray.h"
#include "llcubemap.h"
#include "lldrawable.h"
#include "lldrawpoolsimple.h"
#include "llface.h"
-#include "llgl.h"
#include "llsky.h"
#include "lltextureentry.h"
#include "llviewercamera.h"
@@ -45,9 +43,11 @@ LLBumpImageList gBumpImageList;
const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
-S32 LLDrawPoolBump::sBumpTex = -1;
-S32 LLDrawPoolBump::sDiffTex = -1;
-S32 LLDrawPoolBump::sEnvTex = -1;
+const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
+const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2;
+
+U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
+static LLCubeMap* sCubeMap = NULL;
// static
void LLStandardBumpmap::init()
@@ -109,7 +109,7 @@ void LLStandardBumpmap::restoreGL()
return;
}
- llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
+// llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImage( LLUUID(gViewerArt.getString(bump_file)) );
LLStandardBumpmap::sStandardBumpmapCount++;
@@ -133,15 +133,9 @@ void LLStandardBumpmap::destroyGL()
////////////////////////////////////////////////////////////////
-LLDrawPoolBump::LLDrawPoolBump(LLViewerImage *texturep) :
- LLDrawPool(POOL_BUMP, DATA_BUMP_IL_MASK | DATA_COLORS_MASK, DATA_SIMPLE_NIL_MASK),
- mTexturep(texturep)
-{
-}
-
-LLDrawPool *LLDrawPoolBump::instancePool()
+LLDrawPoolBump::LLDrawPoolBump()
+: LLRenderPass(LLDrawPool::POOL_BUMP)
{
- return new LLDrawPoolBump(mTexturep);
}
@@ -150,51 +144,16 @@ void LLDrawPoolBump::prerender()
mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT);
}
-BOOL LLDrawPoolBump::match(LLFace* last_face, LLFace* facep)
-{
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES) &&
- !last_face->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
- !facep->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
- facep->getIndicesStart() == last_face->getIndicesStart()+last_face->getIndicesCount() &&
- facep->getRenderColor() == last_face->getRenderColor() &&
- facep->getTextureEntry()->getShiny() == last_face->getTextureEntry()->getShiny() &&
- facep->getTextureEntry()->getBumpmap() == last_face->getTextureEntry()->getBumpmap())
- {
- if (facep->isState(LLFace::GLOBAL))
- {
- if (last_face->isState(LLFace::GLOBAL))
- {
- return TRUE;
- }
- }
- else
- {
- if (!last_face->isState(LLFace::GLOBAL))
- {
- if (last_face->getRenderMatrix() == facep->getRenderMatrix())
- {
- return TRUE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
// static
S32 LLDrawPoolBump::numBumpPasses()
{
- if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0)
+ if (gSavedSettings.getBOOL("RenderObjectBump"))
{
- return 1; // single pass for shaders
+ return 2;
}
- else
+ else
{
- if (gSavedSettings.getBOOL("RenderObjectBump"))
- return 3;
- else
- return 1;
+ return 0;
}
}
@@ -208,13 +167,10 @@ void LLDrawPoolBump::beginRenderPass(S32 pass)
switch( pass )
{
case 0:
- beginPass0(this);
+ beginShiny();
break;
case 1:
- beginPass1();
- break;
- case 2:
- beginPass2();
+ beginBump();
break;
default:
llassert(0);
@@ -225,66 +181,17 @@ void LLDrawPoolBump::beginRenderPass(S32 pass)
void LLDrawPoolBump::render(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
- if (!mTexturep)
- {
- return;
- }
-
- if (mDrawFace.empty())
- {
- return;
- }
-
- const U32* index_array = getRawIndices();
- S32 indices = 0;
switch( pass )
{
case 0:
{
- stop_glerror();
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
- bindGLNormalPointer();
- if (gPipeline.getLightingDetail() >= 2)
- {
- bindGLColorPointer();
- }
-
- stop_glerror();
-
- LLGLState alpha_test(GL_ALPHA_TEST, FALSE);
- LLGLState blend(GL_BLEND, FALSE);
- LLViewerImage* tex = getTexture();
- if (tex && tex->getPrimaryFormat() == GL_ALPHA)
- {
- // Enable Invisibility Hack
- alpha_test.enable();
- blend.enable();
- }
- indices += renderPass0(this, mDrawFace, index_array, mTexturep);
+ renderShiny();
break;
}
case 1:
{
- bindGLVertexPointer();
- bindGLNormalPointer();
- indices += renderPass1(mDrawFace, index_array, mTexturep);
- break;
- }
- case 2:
- {
- bindGLVertexPointer();
- // Texture unit 0
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- bindGLTexCoordPointer();
- // Texture unit 1
- glActiveTextureARB(GL_TEXTURE1_ARB);
- glClientActiveTextureARB(GL_TEXTURE1_ARB);
- bindGLTexCoordPointer(1);
- indices += renderPass2(mDrawFace, index_array, mTexturep);
+ renderBump();
break;
}
default:
@@ -293,7 +200,6 @@ void LLDrawPoolBump::render(S32 pass)
break;
}
}
- mIndicesDrawn += indices;
}
void LLDrawPoolBump::endRenderPass(S32 pass)
@@ -301,13 +207,10 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
switch( pass )
{
case 0:
- endPass0(this);
+ endShiny();
break;
case 1:
- endPass1();
- break;
- case 2:
- endPass2();
+ endBump();
break;
default:
llassert(0);
@@ -316,252 +219,171 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
}
//static
-void LLDrawPoolBump::beginPass0(LLDrawPool* pool)
+void LLDrawPoolBump::beginShiny()
{
- stop_glerror();
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ sVertexMask = VERTEX_MASK_SHINY;
+ // Second pass: environment map
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- if (gPipeline.getLightingDetail() >= 2)
- {
- glEnableClientState(GL_COLOR_ARRAY);
- }
+ glEnableClientState(GL_COLOR_ARRAY);
- if (pool->getVertexShaderLevel() > 0)
+ LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
+ if( cube_map )
{
- enable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
+ cube_map->enable(0);
+ cube_map->setMatrix(0);
+ cube_map->bind();
- sEnvTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
- if (sEnvTex >= 0 && cube_map)
+ if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0)
{
- cube_map->bind();
- cube_map->setMatrix(1);
+ LLMatrix4 mat;
+ glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) mat.mMatrix);
+ gPipeline.mObjectShinyProgram.bind();
+ LLVector3 vec = LLVector3(gPipeline.mShinyOrigin) * mat;
+ LLVector4 vec4(vec, gPipeline.mShinyOrigin.mV[3]);
+ glUniform4fvARB(gPipeline.mObjectShinyProgram.mUniform[LLPipeline::GLSL_SHINY_ORIGIN], 1,
+ vec4.mV);
+ }
+ else
+ {
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+
+ //use RGB from texture
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+
+ // use alpha from color
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
-
- sBumpTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP);
- sDiffTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- S32 scatterTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
}
- stop_glerror();
}
-//static
-S32 LLDrawPoolBump::renderPass0(LLDrawPool* pool, face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
+void LLDrawPoolBump::renderShiny()
{
- if (!tex)
- {
- return 0;
- }
+ LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
- if (face_list.empty())
+ sCubeMap = NULL;
+
+ if( gSky.mVOSkyp->getCubeMap() )
{
- return 0;
+ LLGLEnable blend_enable(GL_BLEND);
+ renderStatic(LLRenderPass::PASS_SHINY, sVertexMask);
+ renderActive(LLRenderPass::PASS_SHINY, sVertexMask);
}
+}
- stop_glerror();
+void LLDrawPoolBump::renderActive(U32 type, U32 mask, BOOL texture)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
- S32 res = 0;
- if (pool->getVertexShaderLevel() > 0)
+ LLSpatialBridge* last_bridge = NULL;
+ glPushMatrix();
+
+ for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
- pool->bindGLBinormalPointer(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
-
- LLViewerImage::bindTexture(tex, sDiffTex);
-
- //single pass shader driven shiny/bump
- LLGLDisable(GL_ALPHA_TEST);
-
- LLViewerImage::sWhiteImagep->bind(sBumpTex);
-
- GLfloat alpha[4] =
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
{
- 0.00f,
- 0.25f,
- 0.5f,
- 0.75f
- };
-
- LLImageGL* last_bump = NULL;
-
- for (std::vector<LLFace*>::iterator iter = face_list.begin();
- iter != face_list.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->mSkipRender)
- {
- continue;
- }
-
- const LLTextureEntry* te = facep->getTextureEntry();
- if (te)
+ LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition;
+ if (bridge != last_bridge)
{
- U8 index = te->getShiny();
- LLColor4 col = te->getColor();
-
- gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR,
- col.mV[0], col.mV[1], col.mV[2], alpha[index]);
- gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_SPECULAR_COLOR,
- alpha[index], alpha[index], alpha[index], alpha[index]);
-
- LLImageGL* bump = getBumpMap(te, tex);
- if (bump != last_bump)
+ glPopMatrix();
+ glPushMatrix();
+ glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
+ last_bridge = bridge;
+
+ if (LLPipeline::sDynamicReflections)
{
- if (bump)
+ LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME);
+ LLSpatialGroup::OctreeNode* node = part->mOctree->getNodeAt(LLVector3d(bridge->mDrawable->getPositionAgent()), 32.0);
+ if (node)
{
- bump->bind(sBumpTex);
- }
- else
- {
- LLViewerImage::sWhiteImagep->bind(sBumpTex);
+ sCubeMap = ((LLSpatialGroup*) node->getListener(0))->mReflectionMap;
}
}
- last_bump = bump;
-
- // Draw the geometry
- facep->enableLights();
- res += facep->renderIndexed(index_array);
- stop_glerror();
- }
- else
- {
- llwarns << "DrawPoolBump has face with invalid texture entry." << llendl;
}
- }
- }
- else
- {
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
- LLViewerImage::bindTexture(tex);
- res = LLDrawPool::drawLoop(face_list, index_array);
- }
- return res;
-}
-
-//static
-void LLDrawPoolBump::endPass0(LLDrawPool* pool)
-{
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- if (pool->getVertexShaderLevel() > 0)
- {
- gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
- if (sEnvTex >= 0 && cube_map)
- {
- cube_map->restoreMatrix();
+ renderGroup(group,type,mask,texture);
}
-
- gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP);
- gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
-
- disable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
-
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
}
+
+ glPopMatrix();
}
-//static
-void LLDrawPoolBump::beginPass1()
-{
- // Second pass: environment map
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
- if( cube_map )
- {
- cube_map->enable(0);
- cube_map->setMatrix(0);
- cube_map->bind();
- }
-}
-
-//static
-S32 LLDrawPoolBump::renderPass1(face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
-{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
- if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0
- {
- return 0;
- }
-
- S32 res = 0;
- if( gSky.mVOSkyp->getCubeMap() )
+void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
+{
+ std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[type];
+
+ for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
- //LLGLSPipelineAlpha gls;
- //LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL);
- LLGLEnable blend_enable(GL_BLEND);
-
- GLfloat alpha[4] =
+ LLDrawInfo& params = **k;
+ if (LLPipeline::sDynamicReflections)
{
- 0.00f,
- 0.25f,
- 0.5f,
- 0.75f
- };
-
- for (std::vector<LLFace*>::iterator iter = face_list.begin();
- iter != face_list.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->mSkipRender)
+ if (params.mReflectionMap.notNull())
{
- continue;
+ params.mReflectionMap->bind();
}
-
- const LLTextureEntry* te = facep->getTextureEntry();
- if (te)
+ else
{
- U8 index = te->getShiny();
- if( index > 0 )
+ if (sCubeMap)
{
- LLOverrideFaceColor override_color(facep->getPool(), 1, 1, 1, alpha[index]);
-
- // Draw the geometry
- facep->enableLights();
- res += facep->renderIndexed(index_array);
- stop_glerror();
+ sCubeMap->bind();
+ }
+ else
+ {
+ gSky.mVOSkyp->getCubeMap()->bind();
}
- }
- else
- {
- llwarns << "DrawPoolBump has face with invalid texture entry." << llendl;
}
}
+
+ params.mVertexBuffer->setBuffer(mask);
+ U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+ gPipeline.mTrianglesDrawn += params.mCount/3;
}
- return res;
}
-//static
-void LLDrawPoolBump::endPass1()
+void LLDrawPoolBump::endShiny()
{
LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
if( cube_map )
{
cube_map->disable();
cube_map->restoreMatrix();
+
+ if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0)
+ {
+ gPipeline.mObjectShinyProgram.unbind();
+ }
+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
}
// static
-LLImageGL* LLDrawPoolBump::getBumpMap(const LLTextureEntry* te, LLViewerImage* tex)
+BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params)
{
- U32 bump_code = te->getBumpmap();
LLImageGL* bump = NULL;
+ U8 bump_code = params.mBump;
+ LLViewerImage* tex = params.mTexture;
+
switch( bump_code )
{
case BE_NO_BUMP:
@@ -579,28 +401,33 @@ LLImageGL* LLDrawPoolBump::getBumpMap(const LLTextureEntry* te, LLViewerImage* t
if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
{
bump = gStandardBumpmapList[bump_code].mImage;
+ gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize, 1, 1);
}
break;
}
- return bump;
+ if (bump)
+ {
+ bump->bind(1);
+ bump->bind(0);
+ return TRUE;
+ }
+ return FALSE;
}
//static
-void LLDrawPoolBump::beginPass2()
+void LLDrawPoolBump::beginBump()
{
+ sVertexMask = VERTEX_MASK_BUMP;
LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
- // Optional third pass: emboss bump map
+ // Optional second pass: emboss bump map
stop_glerror();
// TEXTURE UNIT 0
// Output.rgb = texture at texture coord 0
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
-
- glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
@@ -613,14 +440,10 @@ void LLDrawPoolBump::beginPass2()
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
-
// TEXTURE UNIT 1
glActiveTextureARB(GL_TEXTURE1_ARB);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
-
- glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_TEXTURE_2D); // Texture unit 1
@@ -650,68 +473,25 @@ void LLDrawPoolBump::beginPass2()
// = dst.rgb + dst.rgb * (bump0 - bump1)
glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
// glBlendFunc(GL_ONE, GL_ZERO); // temp
-
+ glActiveTextureARB(GL_TEXTURE0_ARB);
stop_glerror();
}
//static
-S32 LLDrawPoolBump::renderPass2(face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
+void LLDrawPoolBump::renderBump()
{
- if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0
- {
- return 0;
- }
-
+ LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
LLGLDisable fog(GL_FOG);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL);
LLGLEnable tex2d(GL_TEXTURE_2D);
LLGLEnable blend(GL_BLEND);
- S32 res = 0;
-
- LLImageGL* last_bump = NULL;
-
- for (std::vector<LLFace*>::iterator iter = face_list.begin();
- iter != face_list.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->mSkipRender)
- {
- continue;
- }
- LLOverrideFaceColor override_color(facep->getPool(), 1,1,1,1);
-
- const LLTextureEntry* te = facep->getTextureEntry();
- LLImageGL* bump = getBumpMap(te, tex);
-
- if( bump )
- {
- if( bump != last_bump )
- {
- last_bump = bump;
-
- // Texture unit 0
- bump->bind(0);
- stop_glerror();
-
- // Texture unit 1
- bump->bind(1);
- stop_glerror();
- }
-
- // Draw the geometry
- res += facep->renderIndexed(index_array);
- stop_glerror();
- }
- else
- {
-// llwarns << "Skipping invalid bump code " << (S32) te->getBumpmap() << llendl;
- }
- }
- return res;
+ glColor4f(1,1,1,1);
+ renderBump(LLRenderPass::PASS_BUMP, sVertexMask);
+ renderBumpActive(LLRenderPass::PASS_BUMP, sVertexMask);
}
//static
-void LLDrawPoolBump::endPass2()
+void LLDrawPoolBump::endBump()
{
// Disable texture unit 1
glActiveTextureARB(GL_TEXTURE1_ARB);
@@ -729,67 +509,6 @@ void LLDrawPoolBump::endPass2()
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
-
-void LLDrawPoolBump::renderForSelect()
-{
- if (mDrawFace.empty() || !mMemory.count())
- {
- return;
- }
-
- glEnableClientState ( GL_VERTEX_ARRAY );
-
- bindGLVertexPointer();
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *facep = *iter;
- if (facep->getDrawable() && !facep->getDrawable()->isDead() && (facep->getViewerObject()->mGLName))
- {
- facep->renderForSelect();
- }
- }
-}
-
-
-void LLDrawPoolBump::renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset, const S32 index_count)
-{
- facep->renderSelected(image, color, index_offset, index_count);
-}
-
-
-void LLDrawPoolBump::dirtyTexture(const LLViewerImage *texturep)
-{
- if (mTexturep == texturep)
- {
- for (std::vector<LLFace*>::iterator iter = mReferences.begin();
- iter != mReferences.end(); iter++)
- {
- LLFace *facep = *iter;
- gPipeline.markTextured(facep->getDrawable());
- }
- }
-}
-
-LLViewerImage *LLDrawPoolBump::getTexture()
-{
- return mTexturep;
-}
-
-LLViewerImage *LLDrawPoolBump::getDebugTexture()
-{
- return mTexturep;
-}
-
-LLColor3 LLDrawPoolBump::getDebugColor() const
-{
- return LLColor3(1.f, 1.f, 0.f);
-}
-
////////////////////////////////////////////////////////////////
// List of one-component bump-maps created from other texures.
@@ -1113,25 +832,93 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma
}
}
-S32 LLDrawPoolBump::getMaterialAttribIndex()
+void LLDrawPoolBump::renderBumpActive(U32 type, U32 mask)
{
- return gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
+
+ LLSpatialBridge* last_bridge = NULL;
+ glPushMatrix();
+
+ for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ group->mSpatialPartition->mRenderByGroup &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
+ {
+ LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition;
+ if (bridge != last_bridge)
+ {
+ glPopMatrix();
+ glPushMatrix();
+ glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
+ last_bridge = bridge;
+ }
+
+ renderGroupBump(group,type,mask);
+ }
+ }
+
+ glPopMatrix();
}
-// virtual
-void LLDrawPoolBump::enableShade()
-{
- glDisableClientState(GL_COLOR_ARRAY);
+void LLDrawPoolBump::renderBump(U32 type, U32 mask)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(mask);
+#endif
+
+ std::vector<LLDrawInfo*>& draw_info = gPipeline.mRenderMap[type];
+
+ for (std::vector<LLDrawInfo*>::iterator i = draw_info.begin(); i != draw_info.end(); ++i)
+ {
+ LLDrawInfo& params = **i;
+
+ if (LLDrawPoolBump::bindBumpMap(params))
+ {
+ pushBatch(params, mask, FALSE);
+ }
+ }
}
-// virtual
-void LLDrawPoolBump::disableShade()
-{
- glEnableClientState(GL_COLOR_ARRAY);
+void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask)
+{
+ const std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[type];
+
+ for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k)
+ {
+ LLDrawInfo& params = **k;
+
+ if (LLDrawPoolBump::bindBumpMap(params))
+ {
+ pushBatch(params, mask, FALSE);
+ }
+ }
}
-// virtual
-void LLDrawPoolBump::setShade(F32 shade)
+void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
- glColor4f(0,0,0,shade);
+ if (params.mTextureMatrix)
+ {
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ }
+ params.mVertexBuffer->setBuffer(mask);
+ U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
+ GL_UNSIGNED_INT, indices_pointer+params.mOffset);
+ gPipeline.mTrianglesDrawn += params.mCount/3;
+ if (params.mTextureMatrix)
+ {
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glLoadIdentity();
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index b74acb4561..6376dd8d33 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -15,57 +15,41 @@
#include "lluuid.h"
class LLImageRaw;
+class LLSpatialGroup;
+class LLDrawInfo;
-class LLDrawPoolBump : public LLDrawPool
+class LLDrawPoolBump : public LLRenderPass
{
-protected:
- LLPointer<LLViewerImage> mTexturep; // The primary texture, not the bump texture
-
public:
- LLDrawPoolBump(LLViewerImage *texturep);
+ static U32 sVertexMask;
+
+ virtual U32 getVertexDataMask() { return sVertexMask; }
- /*virtual*/ LLDrawPool *instancePool();
+ LLDrawPoolBump();
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void beginRenderPass( S32 pass );
/*virtual*/ void endRenderPass( S32 pass );
/*virtual*/ S32 getNumPasses();
- /*virtual*/ void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color,
- const S32 index_offset = 0, const S32 index_count = 0);
/*virtual*/ void prerender();
- /*virtual*/ void renderForSelect();
- /*virtual*/ void dirtyTexture(const LLViewerImage *texturep);
- /*virtual*/ LLViewerImage *getTexture();
- /*virtual*/ LLViewerImage *getDebugTexture();
- /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
- /*virtual*/ BOOL match(LLFace* last_face, LLFace* facep);
+ /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+
+ void renderBump(U32 type, U32 mask);
+ void renderBumpActive(U32 type, U32 mask);
+ void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture);
+ void renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask);
- virtual S32 getMaterialAttribIndex();
- static S32 numBumpPasses();
+ S32 numBumpPasses();
- static void beginPass0(LLDrawPool* pool);
- static S32 renderPass0(LLDrawPool* pool, face_array_t& face_list, const U32* index_array, LLViewerImage* tex);
- static void endPass0(LLDrawPool* pool);
-
- static void beginPass1();
- static S32 renderPass1(face_array_t& face_list, const U32* index_array, LLViewerImage* tex);
- static void endPass1();
-
- static void beginPass2();
- static S32 renderPass2(face_array_t& face_list, const U32* index_array, LLViewerImage* tex);
- static void endPass2();
-
- /*virtual*/ void enableShade();
- /*virtual*/ void disableShade();
- /*virtual*/ void setShade(F32 shade);
-
-protected:
- static LLImageGL* getBumpMap(const LLTextureEntry* te, LLViewerImage* tex);
-
-public:
- static S32 sBumpTex;
- static S32 sDiffTex;
- static S32 sEnvTex;
+ void beginShiny();
+ void renderShiny();
+ void endShiny();
+ void renderActive(U32 type, U32 mask, BOOL texture = TRUE);
+
+ void beginBump();
+ void renderBump();
+ void endBump();
+ BOOL bindBumpMap(LLDrawInfo& params);
};
enum EBumpEffect
diff --git a/indra/newview/lldrawpoolclouds.cpp b/indra/newview/lldrawpoolclouds.cpp
index c279f085d5..d611338248 100644
--- a/indra/newview/lldrawpoolclouds.cpp
+++ b/indra/newview/lldrawpoolclouds.cpp
@@ -17,7 +17,7 @@
#include "pipeline.h"
LLDrawPoolClouds::LLDrawPoolClouds() :
- LLDrawPool(POOL_CLOUDS, DATA_SIMPLE_IL_MASK, 0)
+ LLDrawPool(POOL_CLOUDS)
{
}
@@ -26,16 +26,15 @@ LLDrawPool *LLDrawPoolClouds::instancePool()
return new LLDrawPoolClouds();
}
+BOOL LLDrawPoolClouds::addFace(LLFace* face)
+{
+ llerrs << "WTF?" << llendl;
+ return FALSE;
+}
+
void LLDrawPoolClouds::enqueue(LLFace *facep)
{
- if (facep->isState(LLFace::BACKLIST))
- {
- mMoveFace.put(facep);
- }
- else
- {
- mDrawFace.push_back(facep);
- }
+ mDrawFace.push_back(facep);
facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis();
}
@@ -71,10 +70,6 @@ void LLDrawPoolClouds::render(S32 pass)
gPipeline.enableLightsFullbright(LLColor4(1.f,1.f,1.f));
mDrawFace[0]->bindTexture();
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
- bindGLNormalPointer();
std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
diff --git a/indra/newview/lldrawpoolclouds.h b/indra/newview/lldrawpoolclouds.h
index d333444400..fd04f3b2ec 100644
--- a/indra/newview/lldrawpoolclouds.h
+++ b/indra/newview/lldrawpoolclouds.h
@@ -14,6 +14,16 @@
class LLDrawPoolClouds : public LLDrawPool
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD
+ };
+
+ BOOL addFace(LLFace* face);
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
LLDrawPoolClouds();
/*virtual*/ void prerender();
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index 91e92bab6e..edbb11ad79 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -12,7 +12,6 @@
#include "llviewercontrol.h"
-#include "llagparray.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -20,9 +19,11 @@
#include "llviewerwindow.h"
#include "llworld.h"
#include "pipeline.h"
+#include "llagent.h"
+#include "llviewerregion.h"
LLDrawPoolGround::LLDrawPoolGround() :
- LLDrawPool(POOL_GROUND, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK)
+ LLFacePool(POOL_GROUND)
{
}
@@ -41,42 +42,38 @@ void LLDrawPoolGround::render(S32 pass)
if (mDrawFace.empty())
{
return;
- }
-
+ }
+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
LLGLSPipelineSkyBox gls_skybox;
+ LLGLDisable tex(GL_TEXTURE_2D);
LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
glMatrixMode( GL_PROJECTION );
-
+
glPushMatrix();
- gViewerWindow->setup3DRender();
+ //gViewerWindow->setup3DRender();
glMatrixMode(GL_MODELVIEW);
- LLGLState tex2d(GL_TEXTURE_2D, (mVertexShaderLevel > 0) ? TRUE : FALSE);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), 0);
+ F32 water_height = gAgent.getRegion()->getWaterHeight();
+ glPushMatrix();
+ LLVector3 origin = gCamera->getOrigin();
+ glTranslatef(origin.mV[0], origin.mV[1], llmax(origin.mV[2], water_height));
LLFace *facep = mDrawFace[0];
- if (!(mVertexShaderLevel > 0))
- {
- gPipeline.disableLights();
- }
-
- glColor4fv(facep->getFaceColor().mV);
+ gPipeline.disableLights();
- facep->renderIndexed(getRawIndices());
+ LLOverrideFaceColor col(this, gSky.mVOSkyp->getGLFogColor());
+ facep->renderIndexed();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
}
void LLDrawPoolGround::renderForSelect()
diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h
index 8b2dbf4353..3436b9aabd 100644
--- a/indra/newview/lldrawpoolground.h
+++ b/indra/newview/lldrawpoolground.h
@@ -12,9 +12,17 @@
#include "lldrawpool.h"
-class LLDrawPoolGround : public LLDrawPool
+class LLDrawPoolGround : public LLFacePool
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
LLDrawPoolGround();
/*virtual*/ LLDrawPool *instancePool();
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 600e4b1fc6..fcd466bfc4 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -11,57 +11,16 @@
#include "lldrawpoolsimple.h"
#include "llagent.h"
-#include "llagparray.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
#include "pipeline.h"
-S32 LLDrawPoolSimple::sDiffTex = 0;
-
-LLDrawPoolSimple::LLDrawPoolSimple(LLViewerImage *texturep) :
- LLDrawPool(POOL_SIMPLE,
- DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK,
- DATA_SIMPLE_NIL_MASK), // ady temp
- mTexturep(texturep)
+LLDrawPoolSimple::LLDrawPoolSimple() :
+ LLRenderPass(POOL_SIMPLE)
{
}
-LLDrawPool *LLDrawPoolSimple::instancePool()
-{
- return new LLDrawPoolSimple(mTexturep);
-}
-
-BOOL LLDrawPoolSimple::match(LLFace* last_face, LLFace* facep)
-{
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES) &&
- !last_face->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
- !facep->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
- facep->getIndicesStart() == last_face->getIndicesStart()+last_face->getIndicesCount() &&
- facep->getRenderColor() == last_face->getRenderColor())
- {
- if (facep->isState(LLFace::GLOBAL))
- {
- if (last_face->isState(LLFace::GLOBAL))
- {
- return TRUE;
- }
- }
- else
- {
- if (!last_face->isState(LLFace::GLOBAL))
- {
- if (last_face->getRenderMatrix() == facep->getRenderMatrix())
- {
- return TRUE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
void LLDrawPoolSimple::prerender()
{
mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT);
@@ -72,156 +31,50 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- if (gPipeline.getLightingDetail() >= 2)
- {
- glEnableClientState(GL_COLOR_ARRAY);
- }
-
- if (mVertexShaderLevel > 0)
- {
- S32 scatterTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
- sDiffTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- }
+ glEnableClientState(GL_COLOR_ARRAY);
}
-
void LLDrawPoolSimple::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
- if (mDrawFace.empty())
- {
- return;
- }
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
- bindGLNormalPointer();
- if (gPipeline.getLightingDetail() >= 2)
- {
- bindGLColorPointer();
- }
-
- LLViewerImage* tex = getTexture();
- LLGLState alpha_test(GL_ALPHA_TEST, FALSE);
- LLGLState blend(GL_BLEND, FALSE);
-
- if (tex)
- {
- LLViewerImage::bindTexture(tex,sDiffTex);
- if (tex->getPrimaryFormat() == GL_ALPHA)
- {
- // Enable Invisibility Hack
- alpha_test.enable();
- blend.enable();
- }
- }
- else
- {
- LLImageGL::unbindTexture(sDiffTex, GL_TEXTURE_2D);
- }
-
- drawLoop();
-}
-
-void LLDrawPoolSimple::endRenderPass(S32 pass)
-{
- if (mVertexShaderLevel > 0)
- {
- gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
- }
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable alpha_test(GL_ALPHA_TEST);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- if (gPipeline.getLightingDetail() >= 2)
{
- glDisableClientState(GL_COLOR_ARRAY);
+ LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ gPipeline.enableLightsDynamic(1.f);
+ renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
+ renderActive(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
}
-}
-void LLDrawPoolSimple::renderForSelect()
-{
- if (mDrawFace.empty() || !mMemory.count())
{
- return;
+ LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLGLEnable blend(GL_BLEND);
+ LLGLEnable alpha_test(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.5f);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ //render grass
+ LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask());
+ glAlphaFunc(GL_GREATER, 0.01f);
}
-
- glEnableClientState ( GL_VERTEX_ARRAY );
-
- bindGLVertexPointer();
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
+
{
- LLFace *facep = *iter;
- LLDrawable *drawable = facep->getDrawable();
- if (drawable && !drawable->isDead() && (facep->getViewerObject()->mGLName))
- {
- facep->renderForSelect();
- }
+ LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT);
+ U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR;
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ glDisableClientState(GL_NORMAL_ARRAY);
+ renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
+ renderActive(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
}
-}
-
-
-void LLDrawPoolSimple::renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset, const S32 index_count)
-{
- facep->renderSelected(image, color, index_offset, index_count);
-}
-
-void LLDrawPoolSimple::dirtyTexture(const LLViewerImage *texturep)
-{
- if (mTexturep == texturep)
{
- for (std::vector<LLFace*>::iterator iter = mReferences.begin();
- iter != mReferences.end(); iter++)
- {
- LLFace *facep = *iter;
- gPipeline.markTextured(facep->getDrawable());
- }
+ LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE);
+ U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ renderInvisible(invisi_mask);
+ renderActive(LLRenderPass::PASS_INVISIBLE, invisi_mask);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
-LLViewerImage *LLDrawPoolSimple::getTexture()
-{
- return mTexturep;
-}
-
-LLViewerImage *LLDrawPoolSimple::getDebugTexture()
-{
- return mTexturep;
-}
-
-LLColor3 LLDrawPoolSimple::getDebugColor() const
-{
- return LLColor3(1.f, 1.f, 1.f);
-}
-
-S32 LLDrawPoolSimple::getMaterialAttribIndex()
-{
- return gPipeline.mObjectSimpleProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
-}
-
-// virtual
-void LLDrawPoolSimple::enableShade()
-{
- glDisableClientState(GL_COLOR_ARRAY);
-}
-
-// virtual
-void LLDrawPoolSimple::disableShade()
-{
- glEnableClientState(GL_COLOR_ARRAY);
-}
-
-// virtual
-void LLDrawPoolSimple::setShade(F32 shade)
-{
- glColor4f(0,0,0,shade);
-}
diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h
index 41c4580cea..f89230d866 100644
--- a/indra/newview/lldrawpoolsimple.h
+++ b/indra/newview/lldrawpoolsimple.h
@@ -11,64 +11,24 @@
#include "lldrawpool.h"
-class LLFRInfo
+class LLDrawPoolSimple : public LLRenderPass
{
public:
- U32 mPrimType;
- U32 mGeomIndex;
- U32 mGeomIndexEnd;
- U32 mNumIndices;
- U32 mIndicesStart;
-
- LLFRInfo()
- {
- }
-
- LLFRInfo(const U32 pt, const U32 gi, const U32 gc, const U32 ni, const U32 is) :
- mPrimType(pt),
- mGeomIndex(gi),
- mGeomIndexEnd(gi+gc),
- mNumIndices(ni),
- mIndicesStart(is)
- {
- }
-};
-
-class LLDrawPoolSimple : public LLDrawPool
-{
- LLPointer<LLViewerImage> mTexturep;
-public:
enum
{
- SHADER_LEVEL_LOCAL_LIGHTS = 2
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD |
+ LLVertexBuffer::MAP_COLOR
};
-
- LLDrawPoolSimple(LLViewerImage *texturep);
-
- /*virtual*/ LLDrawPool *instancePool();
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+ LLDrawPoolSimple();
+
/*virtual*/ void beginRenderPass(S32 pass);
- /*virtual*/ void endRenderPass(S32 pass);
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset = 0, const S32 index_count = 0);
/*virtual*/ void prerender();
- /*virtual*/ void renderForSelect();
- /*virtual*/ void dirtyTexture(const LLViewerImage *texturep);
- /*virtual*/ LLViewerImage *getTexture();
- /*virtual*/ LLViewerImage *getDebugTexture();
- /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
- /*virtual*/ BOOL match(LLFace* last_face, LLFace* facep);
-
- /*virtual*/ void enableShade();
- /*virtual*/ void disableShade();
- /*virtual*/ void setShade(F32 shade);
-
- virtual S32 getMaterialAttribIndex();
- static S32 sDiffTex;
};
#endif // LL_LLDRAWPOOLSIMPLE_H
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 96eb8ea721..80340f63b9 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -12,7 +12,6 @@
#include "imageids.h"
-#include "llagparray.h"
#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
@@ -26,7 +25,7 @@
#include "pipeline.h"
LLDrawPoolSky::LLDrawPoolSky() :
- LLDrawPool(POOL_SKY, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK)
+ LLFacePool(POOL_SKY)
{
}
@@ -62,15 +61,17 @@ void LLDrawPoolSky::render(S32 pass)
glMatrixMode( GL_PROJECTION );
glPushMatrix();
- gViewerWindow->setup3DRender();
+ //gViewerWindow->setup3DRender();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ LLVector3 origin = gCamera->getOrigin();
+ glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLTexCoordPointer();
-
S32 face_count = (S32)mDrawFace.size();
for (S32 i = 0; i < llmin(6, face_count); ++i)
@@ -78,13 +79,13 @@ void LLDrawPoolSky::render(S32 pass)
renderSkyCubeFace(i);
}
- const LLFace *hbfaces[3];
+ LLFace *hbfaces[3];
hbfaces[0] = NULL;
hbfaces[1] = NULL;
hbfaces[2] = NULL;
for (S32 curr_face = 0; curr_face < face_count; curr_face++)
{
- const LLFace* facep = mDrawFace[curr_face];
+ LLFace* facep = mDrawFace[curr_face];
if (voskyp->isSameFace(LLVOSky::FACE_SUN, facep))
{
hbfaces[0] = facep;
@@ -118,11 +119,12 @@ void LLDrawPoolSky::render(S32 pass)
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
}
void LLDrawPoolSky::renderSkyCubeFace(U8 side)
{
- const LLFace &face = *mDrawFace[LLVOSky::FACE_SIDE0 + side];
+ LLFace &face = *mDrawFace[LLVOSky::FACE_SIDE0 + side];
if (!face.getGeomCount())
{
return;
@@ -130,20 +132,20 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side)
mSkyTex[side].bindTexture(TRUE);
- face.renderIndexed(getRawIndices());
+ face.renderIndexed();
if (LLSkyTex::doInterpolate())
{
LLGLEnable blend(GL_BLEND);
mSkyTex[side].bindTexture(FALSE);
glColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled
- face.renderIndexed(getRawIndices());
+ face.renderIndexed();
}
mIndicesDrawn += face.getIndicesCount();
}
-void LLDrawPoolSky::renderHeavenlyBody(U8 hb, const LLFace* face)
+void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face)
{
if ( !mHB[hb]->getDraw() ) return;
if (! face->getGeomCount()) return;
@@ -152,13 +154,13 @@ void LLDrawPoolSky::renderHeavenlyBody(U8 hb, const LLFace* face)
tex->bind();
LLColor4 color(mHB[hb]->getInterpColor());
LLOverrideFaceColor override(this, color);
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
-void LLDrawPoolSky::renderSunHalo(const LLFace* face)
+void LLDrawPoolSky::renderSunHalo(LLFace* face)
{
if (! mHB[0]->getDraw()) return;
if (! face->getGeomCount()) return;
@@ -169,7 +171,7 @@ void LLDrawPoolSky::renderSunHalo(const LLFace* face)
color.mV[3] = llclamp(mHB[0]->getHaloBrighness(), 0.f, 1.f);
LLOverrideFaceColor override(this, color);
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index 881ce6d542..88d1ce03d0 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -14,13 +14,21 @@
class LLSkyTex;
class LLHeavenBody;
-class LLDrawPoolSky : public LLDrawPool
+class LLDrawPoolSky : public LLFacePool
{
private:
LLSkyTex *mSkyTex;
LLHeavenBody *mHB[2]; // Sun and Moon
public:
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
LLDrawPoolSky();
/*virtual*/ LLDrawPool *instancePool();
@@ -33,8 +41,8 @@ public:
void setMoon(LLHeavenBody* moon) { mHB[1] = moon; }
void renderSkyCubeFace(U8 side);
- void renderHeavenlyBody(U8 hb, const LLFace* face);
- void renderSunHalo(const LLFace* face);
+ void renderHeavenlyBody(U8 hb, LLFace* face);
+ void renderSunHalo(LLFace* face);
virtual S32 getMaterialAttribIndex() { return 0; }
};
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 3e6ae7bf85..8c5c2e177a 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -13,7 +13,6 @@
#include "llfasttimer.h"
#include "llagent.h"
-#include "llagparray.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
#include "llface.h"
@@ -37,7 +36,7 @@ S32 LLDrawPoolTerrain::sDetailMode = 1;
F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE;
LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) :
- LLDrawPool(POOL_TERRAIN, DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK | DATA_TEX_COORDS1_MASK, DATA_SIMPLE_NIL_MASK),
+ LLFacePool(POOL_TERRAIN),
mTexturep(texturep)
{
// Hack!
@@ -75,6 +74,13 @@ void LLDrawPoolTerrain::prerender()
#if 0 // 1.9.2
mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT);
#endif
+ sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
+}
+
+//static
+S32 LLDrawPoolTerrain::getDetailMode()
+{
+ return sDetailMode;
}
void LLDrawPoolTerrain::render(S32 pass)
@@ -86,6 +92,15 @@ void LLDrawPoolTerrain::render(S32 pass)
return;
}
+ // Hack! Get the region that this draw pool is rendering from!
+ LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
+ LLVLComposition *compp = regionp->getComposition();
+ for (S32 i = 0; i < 4; i++)
+ {
+ compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+ }
+
if (!gGLManager.mHasMultitexture)
{
// No mulititexture, render simple land.
@@ -152,25 +167,16 @@ void LLDrawPoolTerrain::renderFull4TUShader()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
if (gPipeline.getLightingDetail() >= 2)
{
glEnableClientState(GL_COLOR_ARRAY);
- bindGLColorPointer();
}
-
+
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- for (S32 i = 0; i < 4; i++)
- {
- compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
- compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
- }
-
LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
@@ -200,8 +206,7 @@ void LLDrawPoolTerrain::renderFull4TUShader()
S32 detailTex0 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0);
S32 detailTex1 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1);
S32 rampTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP);
- S32 scatterTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
-
+
LLViewerImage::bindTexture(detail_texture0p,detailTex0);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
@@ -222,7 +227,6 @@ void LLDrawPoolTerrain::renderFull4TUShader()
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
//
// Stage 2: Interpolate detail1 with existing based on ramp
@@ -239,9 +243,6 @@ void LLDrawPoolTerrain::renderFull4TUShader()
glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
- // Stage 4: Haze
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
-
//
// Stage 3: Modulate with primary color for lighting
//
@@ -278,7 +279,6 @@ void LLDrawPoolTerrain::renderFull4TUShader()
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
- bindGLTexCoordPointer(1);
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
@@ -310,7 +310,6 @@ void LLDrawPoolTerrain::renderFull4TUShader()
glClientActiveTextureARB(GL_TEXTURE3_ARB);
glActiveTextureARB(GL_TEXTURE3_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
@@ -323,7 +322,6 @@ void LLDrawPoolTerrain::renderFull4TUShader()
}
// Disable multitexture
- gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP);
gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0);
gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1);
@@ -377,18 +375,9 @@ void LLDrawPoolTerrain::renderFull4TU()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
-
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- for (S32 i = 0; i < 4; i++)
- {
- compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
- compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
- }
-
LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
@@ -411,6 +400,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 0: detail texture 0
//
+ glActiveTextureARB(GL_TEXTURE0_ARB);
LLViewerImage::bindTexture(detail_texture0p,0);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
@@ -432,12 +422,12 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 1: Generate alpha ramp for detail0/detail1 transition
//
+ glActiveTextureARB(GL_TEXTURE1_ARB);
LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
glEnable(GL_TEXTURE_2D); // Texture unit 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Care about alpha only
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@@ -452,6 +442,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 2: Interpolate detail1 with existing based on ramp
//
+ glActiveTextureARB(GL_TEXTURE2_ARB);
LLViewerImage::bindTexture(detail_texture1p,2);
glEnable(GL_TEXTURE_2D); // Texture unit 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
@@ -477,6 +468,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 3: Modulate with primary (vertex) color for lighting
//
+ glActiveTextureARB(GL_TEXTURE3_ARB);
LLViewerImage::bindTexture(detail_texture1p,3); // bind any texture
glEnable(GL_TEXTURE_2D); // Texture unit 3
glClientActiveTextureARB(GL_TEXTURE3_ARB);
@@ -498,6 +490,7 @@ void LLDrawPoolTerrain::renderFull4TU()
// Stage 0: Write detail3 into base
//
+ glActiveTextureARB(GL_TEXTURE0_ARB);
LLViewerImage::bindTexture(detail_texture3p,0);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
@@ -519,14 +512,13 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 1: Generate alpha ramp for detail2/detail3 transition
//
+ glActiveTextureARB(GL_TEXTURE1_ARB);
LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
glEnable(GL_TEXTURE_2D); // Texture unit 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
-
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
@@ -547,6 +539,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 2: Interpolate detail2 with existing based on ramp
//
+ glActiveTextureARB(GL_TEXTURE2_ARB);
LLViewerImage::bindTexture(detail_texture2p,2);
glEnable(GL_TEXTURE_2D); // Texture unit 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
@@ -573,19 +566,19 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 3: Generate alpha ramp for detail1/detail2 transition
//
+ glActiveTextureARB(GL_TEXTURE3_ARB);
LLViewerImage::bindTexture(m2DAlphaRampImagep,3);
glEnable(GL_TEXTURE_2D); // Texture unit 3
glClientActiveTextureARB(GL_TEXTURE3_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(-1.f, 0.f, 0.f);
-
+
// Set alpha texture and do lighting modulation
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
@@ -656,18 +649,9 @@ void LLDrawPoolTerrain::renderFull2TU()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
-
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- for (S32 i = 0; i < 4; i++)
- {
- compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
- compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
- }
-
LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
@@ -724,7 +708,6 @@ void LLDrawPoolTerrain::renderFull2TU()
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Care about alpha only
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@@ -781,7 +764,6 @@ void LLDrawPoolTerrain::renderFull2TU()
glTranslatef(-1.f, 0.f, 0.f);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Care about alpha only
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@@ -839,7 +821,6 @@ void LLDrawPoolTerrain::renderFull2TU()
glTranslatef(-2.f, 0.f, 0.f);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- bindGLTexCoordPointer(1);
// Care about alpha only
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@@ -919,9 +900,6 @@ void LLDrawPoolTerrain::renderSimple()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
-
LLVector4 tp0, tp1;
//----------------------------------------------------------------------------
@@ -999,9 +977,6 @@ void LLDrawPoolTerrain::renderOwnership()
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLTexCoordPointer(0);
-
LLViewerImage::bindTexture(texturep);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
@@ -1017,12 +992,12 @@ void LLDrawPoolTerrain::renderOwnership()
const F32 TEXTURE_FUDGE = 257.f / 256.f;
glScalef( TEXTURE_FUDGE, TEXTURE_FUDGE, 1.f );
- const U32* index_array = getRawIndices();
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
{
LLFace *facep = *iter;
- facep->renderIndexed(index_array);
+ facep->renderIndexed(LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD);
}
glMatrixMode(GL_TEXTURE);
@@ -1036,14 +1011,13 @@ void LLDrawPoolTerrain::renderOwnership()
void LLDrawPoolTerrain::renderForSelect()
{
- if (mDrawFace.empty() || !mMemory.count())
+ if (mDrawFace.empty())
{
return;
}
- glEnableClientState ( GL_VERTEX_ARRAY );
-
- bindGLVertexPointer();
+
+ LLImageGL::unbindTexture(0);
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
@@ -1051,14 +1025,14 @@ void LLDrawPoolTerrain::renderForSelect()
LLFace *facep = *iter;
if (!facep->getDrawable()->isDead() && (facep->getDrawable()->getVObj()->mGLName))
{
- facep->renderForSelect();
+ facep->renderForSelect(LLVertexBuffer::MAP_VERTEX);
}
}
}
-void LLDrawPoolTerrain::dirtyTexture(const LLViewerImage *texturep)
+void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerImage*>& textures)
{
- if (mTexturep == texturep)
+ if (textures.find(mTexturep) != textures.end())
{
for (std::vector<LLFace*>::iterator iter = mReferences.begin();
iter != mReferences.end(); iter++)
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index b5fe0a30fd..4882532e8a 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -11,10 +11,22 @@
#include "lldrawpool.h"
-class LLDrawPoolTerrain : public LLDrawPool
+class LLDrawPoolTerrain : public LLFacePool
{
LLPointer<LLViewerImage> mTexturep;
public:
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD |
+ LLVertexBuffer::MAP_TEXCOORD2 |
+ LLVertexBuffer::MAP_COLOR
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+ static S32 getDetailMode();
+
LLDrawPoolTerrain(LLViewerImage *texturep);
virtual ~LLDrawPoolTerrain();
@@ -24,7 +36,7 @@ public:
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void prerender();
/*virtual*/ void renderForSelect();
- /*virtual*/ void dirtyTexture(const LLViewerImage *texturep);
+ /*virtual*/ void dirtyTextures(const std::set<LLViewerImage*>& textures);
/*virtual*/ LLViewerImage *getTexture();
/*virtual*/ LLViewerImage *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index c41ceedac7..170669955c 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -10,7 +10,6 @@
#include "lldrawpooltree.h"
-#include "llagparray.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -22,7 +21,7 @@
S32 LLDrawPoolTree::sDiffTex = 0;
LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) :
- LLDrawPool(POOL_TREE, DATA_SIMPLE_IL_MASK, 0),
+ LLFacePool(POOL_TREE),
mTexturep(texturep)
{
mTexturep->bind(0);
@@ -36,7 +35,7 @@ LLDrawPool *LLDrawPoolTree::instancePool()
void LLDrawPoolTree::prerender()
{
- mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT);
+ mVertexShaderLevel = 0;
}
void LLDrawPoolTree::beginRenderPass(S32 pass)
@@ -44,13 +43,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- if ((mVertexShaderLevel > 0))
- {
- S32 scatterTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
- sDiffTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- }
+ glAlphaFunc(GL_GREATER, 0.5f);
}
void LLDrawPoolTree::render(S32 pass)
@@ -64,34 +57,21 @@ void LLDrawPoolTree::render(S32 pass)
gPipeline.enableLightsDynamic(1.f);
LLGLSPipelineAlpha gls_pipeline_alpha;
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
- bindGLNormalPointer();
-
LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f);
renderTree();
-
}
void LLDrawPoolTree::endRenderPass(S32 pass)
{
- if ((mVertexShaderLevel > 0))
- {
- gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
- gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
- }
-
+ glAlphaFunc(GL_GREATER, 0.01f);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void LLDrawPoolTree::renderForSelect()
{
- if (mDrawFace.empty() || !mMemory.count())
+ if (mDrawFace.empty())
{
return;
}
@@ -104,10 +84,7 @@ void LLDrawPoolTree::renderForSelect()
LLGLSObjectSelectAlpha gls_alpha;
glBlendFunc(GL_ONE, GL_ZERO);
- glAlphaFunc(gPickTransparent ? GL_GEQUAL : GL_GREATER, 0.f);
-
- bindGLVertexPointer();
- bindGLTexCoordPointer();
+ glAlphaFunc(GL_GREATER, 0.5f);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
@@ -147,6 +124,8 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
}
}
+ U32 indices_drawn = 0;
+
glMatrixMode(GL_MODELVIEW);
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
@@ -155,11 +134,14 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
LLFace *face = *iter;
LLDrawable *drawablep = face->getDrawable();
- if (drawablep->isDead())
+ if (drawablep->isDead() || face->mVertexBuffer.isNull())
{
continue;
}
+ face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
+ U32* indicesp = (U32*) face->mVertexBuffer->getIndicesPointer();
+
// Render each of the trees
LLVOTree *treep = (LLVOTree *)drawablep->getVObj();
@@ -217,55 +199,26 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
}
}
- if (app_angle > (THRESH_ANGLE_FOR_BILLBOARD + BLEND_RANGE_FOR_BILLBOARD))
- {
- //
- // Draw only the full geometry tree
- //
- //stop_depth = (app_angle < THRESH_ANGLE_FOR_RECURSION_REDUCTION);
- glAlphaFunc(GL_GREATER, 0.5f);
- LLDrawPool::LLOverrideFaceColor clr(this, color);
- treep->drawBranchPipeline(this, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
- }
- else if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD))
+ if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD))
{
//
// Draw only the billboard
//
// Only the billboard, can use closer to normal alpha func.
stop_depth = -1;
- glAlphaFunc(GL_GREATER, 0.4f);
- LLDrawPool::LLOverrideFaceColor clr(this, color);
- treep->drawBranchPipeline(this, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
+ LLFacePool::LLOverrideFaceColor clr(this, color);
+ indices_drawn += treep->drawBranchPipeline(indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
}
- else
+ else // if (app_angle > (THRESH_ANGLE_FOR_BILLBOARD + BLEND_RANGE_FOR_BILLBOARD))
{
//
- // Draw a blended version including both billboard and full tree
- //
- alpha = (app_angle - THRESH_ANGLE_FOR_BILLBOARD)/BLEND_RANGE_FOR_BILLBOARD;
- BOOL billboard_depth = TRUE; // billboard gets alpha
- if (alpha > 0.5f)
- {
- billboard_depth = FALSE;
- }
- alpha = alpha/2.f + 0.5f;
-
- glAlphaFunc(GL_GREATER, alpha*0.5f);
- {
- LLGLDepthTest gls_depth(GL_TRUE, billboard_depth ? GL_FALSE : GL_TRUE);
- color.mV[3] = (U8) (llclamp(alpha, 0.0f, 1.0f) * 255);
- LLDrawPool::LLOverrideFaceColor clr(this, color);
- treep->drawBranchPipeline(this, trunk_LOD, 0, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
- }
- {
- LLGLDepthTest gls_depth(GL_TRUE, billboard_depth ? GL_TRUE : GL_FALSE);
- glAlphaFunc(GL_GREATER, (1.f - alpha)*0.1f);
- color.mV[3] = (U8) (llclamp(1.f-alpha, 0.0f, 1.0f) * 255);
- LLDrawPool::LLOverrideFaceColor clr(this, color);
- treep->drawBranchPipeline(this, trunk_LOD, -1, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, 1.f - alpha);
- }
+ // Draw only the full geometry tree
+ //
+ //stop_depth = (app_angle < THRESH_ANGLE_FOR_RECURSION_REDUCTION);
+ LLFacePool::LLOverrideFaceColor clr(this, color);
+ indices_drawn += treep->drawBranchPipeline(indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
}
+
glPopMatrix();
}
}
@@ -279,45 +232,21 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
- glAlphaFunc(GL_GREATER, 0.01f);
-}
-
-
-S32 LLDrawPoolTree::rebuild()
-{
- mRebuildTime++;
- if (mRebuildTime > mRebuildFreq)
- {
- // Flush AGP to force an AGP realloc and reduce AGP fragmentation
- flushAGP();
- mRebuildTime = 0;
- }
- return 0;
+ addIndicesDrawn(indices_drawn);
}
BOOL LLDrawPoolTree::verify() const
{
- BOOL ok = TRUE;
-
- // shared geometry. Just verify that it's there and correct.
+/* BOOL ok = TRUE;
- // Verify all indices in the pool are in the right range
- const U32 *indicesp = getRawIndices();
- for (U32 i = 0; i < getIndexCount(); i++)
- {
- if (indicesp[i] > getVertexCount())
- {
- ok = FALSE;
- llinfos << "Bad index in tree pool!" << llendl;
- }
- }
-
if (!ok)
{
printDebugInfo();
}
- return ok;
+ return ok;*/
+
+ return TRUE;
}
LLViewerImage *LLDrawPoolTree::getTexture()
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index 228b11a981..5b937cf688 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -11,10 +11,19 @@
#include "lldrawpool.h"
-class LLDrawPoolTree : public LLDrawPool
+class LLDrawPoolTree : public LLFacePool
{
LLPointer<LLViewerImage> mTexturep;
public:
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
LLDrawPoolTree(LLViewerImage *texturep);
/*virtual*/ LLDrawPool *instancePool();
@@ -24,7 +33,6 @@ public:
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void endRenderPass( S32 pass );
/*virtual*/ void renderForSelect();
- /*virtual*/ S32 rebuild();
/*virtual*/ BOOL verify() const;
/*virtual*/ LLViewerImage *getTexture();
/*virtual*/ LLViewerImage *getDebugTexture();
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 108048efbc..db5debc079 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -16,7 +16,6 @@
#include "m3math.h"
#include "llagent.h" // for gAgent for getRegion for getWaterHeight
-#include "llagparray.h"
#include "llcubemap.h"
#include "lldrawable.h"
#include "llface.h"
@@ -44,11 +43,11 @@ int nhpo2(int v)
}
static GLuint sScreenTex = 0;
+BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
LLDrawPoolWater::LLDrawPoolWater() :
- LLDrawPool(POOL_WATER, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK)
+ LLFacePool(POOL_WATER)
{
- mCleanupUnused = TRUE;
mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE);
mHBTex[0]->bind();
mHBTex[0]->setClamp(TRUE, TRUE);
@@ -116,11 +115,21 @@ extern LLColor4U MAX_WATER_COLOR;
void LLDrawPoolWater::render(S32 pass)
{
LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER);
- if (mDrawFace.empty())
+ if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1)
{
return;
}
+ //do a quick 'n dirty depth sort
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace* facep = *iter;
+ facep->mDistance = -facep->mCenterLocal.mV[2];
+ }
+
+ std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
+
LLGLSPipelineAlpha alphaState;
if ((mVertexShaderLevel >= SHADER_LEVEL_RIPPLE))
@@ -145,7 +154,7 @@ void LLDrawPoolWater::render(S32 pass)
return;
}
- const LLFace* refl_face = voskyp->getReflFace();
+ LLFace* refl_face = voskyp->getReflFace();
gPipeline.disableLights();
@@ -157,10 +166,6 @@ void LLDrawPoolWater::render(S32 pass)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
- bindGLTexCoordPointer();
-
// Set up second pass first
glActiveTextureARB(GL_TEXTURE1_ARB);
mWaterImagep->addTextureStats(1024.f*1024.f);
@@ -227,7 +232,7 @@ void LLDrawPoolWater::render(S32 pass)
continue;
}
face->bindTexture();
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
@@ -288,7 +293,7 @@ void LLDrawPoolWater::render(S32 pass)
if (face->getGeomCount() > 0)
{
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
}
@@ -335,7 +340,7 @@ void LLDrawPoolWater::renderShaderSimple()
return;
}
- const LLFace* refl_face = voskyp->getReflFace();
+ LLFace* refl_face = voskyp->getReflFace();
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
@@ -345,10 +350,6 @@ void LLDrawPoolWater::renderShaderSimple()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
- bindGLVertexPointer();
- bindGLNormalPointer();
- bindGLTexCoordPointer();
-
// Set up second pass first
S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP);
mWaterImagep->addTextureStats(1024.f*1024.f);
@@ -413,9 +414,6 @@ void LLDrawPoolWater::renderShaderSimple()
glMatrixMode(GL_MODELVIEW);
}
- S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
-
S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
gPipeline.mWaterProgram.bind();
@@ -429,7 +427,7 @@ void LLDrawPoolWater::renderShaderSimple()
continue;
}
face->bindTexture(diffTex);
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
@@ -450,8 +448,7 @@ void LLDrawPoolWater::renderShaderSimple()
glDisable(GL_TEXTURE_GEN_T); //texture unit 1
gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
- gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
-
+
// Disable texture coordinate and color arrays
LLImageGL::unbindTexture(diffTex, GL_TEXTURE_2D);
@@ -477,7 +474,7 @@ void LLDrawPoolWater::renderShaderSimple()
glDisableClientState(GL_NORMAL_ARRAY);
}
-void LLDrawPoolWater::renderReflection(const LLFace* face)
+void LLDrawPoolWater::renderReflection(LLFace* face)
{
LLVOSky *voskyp = gSky.mVOSkyp;
@@ -505,7 +502,7 @@ void LLDrawPoolWater::renderReflection(const LLFace* face)
LLViewerImage::bindTexture(mHBTex[dr]);
LLOverrideFaceColor override(this, face->getFaceColor().mV);
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -513,36 +510,44 @@ void LLDrawPoolWater::renderReflection(const LLFace* face)
void bindScreenToTexture()
{
- GLint viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
- GLuint resX = nhpo2(viewport[2]);
- GLuint resY = nhpo2(viewport[3]);
-
- glBindTexture(GL_TEXTURE_2D, sScreenTex);
- GLint cResX;
- GLint cResY;
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
-
- if (cResX != (GLint)resX || cResY != (GLint)resY)
+ if (LLDrawPoolWater::sSkipScreenCopy)
{
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
- gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
+ else
+ {
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]);
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ GLuint resX = nhpo2(viewport[2]);
+ GLuint resY = nhpo2(viewport[3]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, sScreenTex);
+ GLint cResX;
+ GLint cResY;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
+
+ if (cResX != (GLint)resX || cResY != (GLint)resY)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
+ gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+ }
- float scale[2];
- scale[0] = (float) viewport[2]/resX;
- scale[1] = (float) viewport[3]/resY;
- glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]);
- LLImageGL::sBoundTextureMemory += resX * resY * 3;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ float scale[2];
+ scale[0] = (float) viewport[2]/resX;
+ scale[1] = (float) viewport[3]/resY;
+ glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale);
+
+ LLImageGL::sBoundTextureMemory += resX * resY * 3;
+ }
}
void LLDrawPoolWater::shade()
@@ -577,9 +582,6 @@ void LLDrawPoolWater::shade()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
LLGLDisable blend(GL_BLEND);
- bindGLVertexPointer();
- bindGLNormalPointer();
- bindGLTexCoordPointer();
LLColor3 light_diffuse(0,0,0);
F32 light_exp = 0.0f;
@@ -630,9 +632,6 @@ void LLDrawPoolWater::shade()
bindScreenToTexture();
- S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
- LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
-
S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
@@ -678,7 +677,7 @@ void LLDrawPoolWater::shade()
}
face->bindTexture(diffTex);
- face->renderIndexed(getRawIndices());
+ face->renderIndexed();
mIndicesDrawn += face->getIndicesCount();
}
}
@@ -686,7 +685,6 @@ void LLDrawPoolWater::shade()
gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_WATER_SCREENTEX);
gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP);
- gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
glActiveTextureARB(GL_TEXTURE0_ARB);
@@ -695,10 +693,6 @@ void LLDrawPoolWater::shade()
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- /*glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);*/
}
void LLDrawPoolWater::renderForSelect()
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 7e661b3718..fafacf4d34 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -16,7 +16,7 @@ class LLFace;
class LLHeavenBody;
class LLWaterSurface;
-class LLDrawPoolWater: public LLDrawPool
+class LLDrawPoolWater: public LLFacePool
{
protected:
LLPointer<LLViewerImage> mHBTex[2];
@@ -25,6 +25,16 @@ protected:
const LLWaterSurface *mWaterSurface;
public:
+ static BOOL sSkipScreenCopy;
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD
+ };
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
enum
{
SHADER_LEVEL_RIPPLE = 2,
@@ -45,7 +55,7 @@ public:
/*virtual*/ LLViewerImage *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
- void renderReflection(const LLFace* face);
+ void renderReflection(LLFace* face);
void shade();
void renderShaderSimple();
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 0f0a9d9bda..f2981625f7 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -16,6 +16,8 @@
#include "llviewercamera.h"
#include "llviewercontrol.h"
#include "llviewerimage.h"
+#include "llvertexbuffer.h"
+
// static
LLLinkedList<LLDynamicTexture> LLDynamicTexture::sInstances[ LLDynamicTexture::ORDER_COUNT ];
@@ -174,6 +176,8 @@ BOOL LLDynamicTexture::updateAllInstances()
return TRUE;
}
+ BOOL started = FALSE;
+
BOOL result = FALSE;
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
@@ -183,6 +187,12 @@ BOOL LLDynamicTexture::updateAllInstances()
{
if (dynamicTexture->needsRender())
{
+ if (!started)
+ {
+ started = TRUE;
+ LLVertexBuffer::startRender();
+ }
+
dynamicTexture->preRender();
if (dynamicTexture->render())
{
@@ -194,6 +204,11 @@ BOOL LLDynamicTexture::updateAllInstances()
}
}
+ if (started)
+ {
+ LLVertexBuffer::stopRender();
+ }
+
return result;
}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index cd24454caf..64edcecdc6 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -10,13 +10,13 @@
#include "lldrawable.h" // lldrawable needs to be included before llface
#include "llface.h"
+#include "llviewertextureanim.h"
#include "llviewercontrol.h"
#include "llvolume.h"
#include "m3math.h"
#include "v3color.h"
-#include "llagparray.h"
#include "lldrawpoolsimple.h"
#include "lldrawpoolbump.h"
#include "llgl.h"
@@ -28,8 +28,6 @@
#include "llvovolume.h"
#include "pipeline.h"
-#include "llagparray.inl"
-
#define LL_MAX_INDICES_COUNT 1000000
extern BOOL gPickFaces;
@@ -118,25 +116,23 @@ void cylindricalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, co
void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
{
- mGeneration = DIRTY;
+ mLastUpdateTime = gFrameTimeSeconds;
+ mVSize = 0.f;
+ mPixelArea = 1024.f;
mState = GLOBAL;
mDrawPoolp = NULL;
+ mPoolType = 0;
mGeomIndex = -1;
- mSkipRender = FALSE;
- mNextFace = NULL;
// mCenterLocal
// mCenterAgent
mDistance = 0.f;
- mPrimType = LLTriangles;
mGeomCount = 0;
mIndicesCount = 0;
mIndicesIndex = -1;
mTexture = NULL;
mTEOffset = -1;
- mBackupMem = NULL;
-
setDrawable(drawablep);
mVObjp = objp;
@@ -144,6 +140,12 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mAlphaFade = 0.f;
mFaceColor = LLColor4(1,0,0,1);
+
+ mLastVertexBuffer = mVertexBuffer;
+ mLastGeomCount = mGeomCount;
+ mLastGeomIndex = mGeomIndex;
+ mLastIndicesCount = mIndicesCount;
+ mLastIndicesIndex = mIndicesIndex;
}
@@ -157,11 +159,6 @@ void LLFace::destroy()
mDrawPoolp->removeFace(this);
mDrawPoolp = NULL;
}
-
- // Remove light and blocker list references
-
- delete[] mBackupMem;
- mBackupMem = NULL;
}
@@ -175,13 +172,7 @@ void LLFace::setWorldMatrix(const LLMatrix4 &mat)
llerrs << "Faces on this drawable are not independently modifiable\n" << llendl;
}
-
-void LLFace::setDirty()
-{
- mGeneration = DIRTY;
-}
-
-void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep)
+void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
@@ -196,22 +187,12 @@ void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep)
if (mDrawPoolp)
{
mDrawPoolp->removeFace(this);
- mSkipRender = FALSE;
- mNextFace = NULL;
- // Invalidate geometry (will get rebuilt next frame)
- setDirty();
if (mDrawablep)
{
gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL, TRUE);
}
}
- if (isState(BACKLIST))
- {
- delete[] mBackupMem;
- mBackupMem = NULL;
- clearState(BACKLIST);
- }
mGeomIndex = -1;
// Add to new pool
@@ -220,7 +201,6 @@ void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep)
new_pool->addFace(this);
}
mDrawPoolp = new_pool;
-
}
mTexture = texturep;
}
@@ -249,91 +229,12 @@ void LLFace::setDrawable(LLDrawable *drawable)
mXform = &drawable->mXform;
}
-S32 LLFace::allocBackupMem()
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- S32 size = 0;
- size += mIndicesCount * 4;
- size += mGeomCount * mDrawPoolp->getStride();
-
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK)
- {
- size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_VERTEX_WEIGHTS];
- }
-
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK)
- {
- size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_CLOTHING_WEIGHTS];
- }
-
- delete[] mBackupMem;
- mBackupMem = new U8[size];
- return size;
-}
-
-
void LLFace::setSize(const S32 num_vertices, const S32 num_indices)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
- if (getState() & SHARED_GEOM)
- {
- mGeomCount = num_vertices;
- mIndicesCount = num_indices;
- return; // Shared, don't allocate or do anything with memory
- }
- if (num_vertices != (S32)mGeomCount || num_indices != (S32)mIndicesCount)
- {
- setDirty();
-
- delete[] mBackupMem;
- mBackupMem = NULL;
- clearState(BACKLIST);
-
- mGeomCount = num_vertices;
- mIndicesCount = num_indices;
- }
-
-}
-
-BOOL LLFace::reserveIfNeeded()
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (getDirty())
- {
- if (isState(BACKLIST))
- {
- llwarns << "Reserve on backlisted object!" << llendl;
- }
-
- if (0 == mGeomCount)
- {
- //llwarns << "Reserving zero bytes for face!" << llendl;
- mGeomCount = 0;
- mIndicesCount = 0;
- return FALSE;
- }
-
- mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount);
- // (reserveGeom() always returns a valid index)
- mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount);
- mGeneration = mDrawPoolp->mGeneration;
- }
-
- return TRUE;
-}
-
-void LLFace::unReserve()
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (!(isState(SHARED_GEOM)))
- {
- mGeomIndex = mDrawPoolp->unReserveGeom(mGeomIndex, mGeomCount);
- mIndicesIndex = mDrawPoolp->unReserveInd(mIndicesIndex, mIndicesCount);
- }
+ mGeomCount = num_vertices;
+ mIndicesCount = num_indices;
}
//============================================================================
@@ -347,55 +248,22 @@ S32 LLFace::getGeometryAvatar(
LLStrider<LLVector4> &clothing_weights)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (mGeomCount <= 0)
- {
- return -1;
- }
-
- if (isState(BACKLIST))
- {
- if (!mBackupMem)
- {
- llerrs << "No backup memory for backlist" << llendl;
- }
-
- vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]);
- normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]);
- binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]);
- tex_coords = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]);
- clothing_weights = (LLVector4*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_CLOTHING_WEIGHTS]);
- vertex_weights = (F32*)(mBackupMem + (4 * mIndicesCount) + (mGeomCount * mDrawPoolp->getStride()));
- tex_coords.setStride( mDrawPoolp->getStride());
- vertices.setStride( mDrawPoolp->getStride());
- normals.setStride( mDrawPoolp->getStride());
- binormals.setStride( mDrawPoolp->getStride());
- clothing_weights.setStride( mDrawPoolp->getStride());
- return 0;
+ if (mVertexBuffer.notNull())
+ {
+ mVertexBuffer->getVertexStrider (vertices, mGeomIndex);
+ mVertexBuffer->getNormalStrider (normals, mGeomIndex);
+ mVertexBuffer->getBinormalStrider (binormals, mGeomIndex);
+ mVertexBuffer->getTexCoordStrider (tex_coords, mGeomIndex);
+ mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex);
+ mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex);
}
else
{
- if (!reserveIfNeeded())
- {
- return -1;
- }
-
- llassert(mGeomIndex >= 0);
- llassert(mIndicesIndex >= 0);
-
- mDrawPoolp->getVertexStrider (vertices, mGeomIndex);
- mDrawPoolp->getNormalStrider (normals, mGeomIndex);
- mDrawPoolp->getBinormalStrider (binormals, mGeomIndex);
- mDrawPoolp->getTexCoordStrider (tex_coords, mGeomIndex);
- mDrawPoolp->getVertexWeightStrider(vertex_weights, mGeomIndex);
- mDrawPoolp->getClothingWeightStrider(clothing_weights, mGeomIndex);
-
- mDrawPoolp->setDirty();
-
- llassert(mGeomIndex >= 0);
- return mGeomIndex;
+ mGeomIndex = -1;
}
+
+ return mGeomIndex;
}
S32 LLFace::getGeometryTerrain(
@@ -404,64 +272,29 @@ S32 LLFace::getGeometryTerrain(
LLStrider<LLColor4U> &colors,
LLStrider<LLVector2> &texcoords0,
LLStrider<LLVector2> &texcoords1,
- U32 *&indicesp)
+ LLStrider<U32> &indicesp)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
- if (mGeomCount <= 0)
+ if (mVertexBuffer.notNull())
{
- return -1;
- }
-
- if (isState(BACKLIST))
- {
- if (!mBackupMem)
- {
- printDebugInfo();
- llerrs << "No backup memory for face" << llendl;
- }
- vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]);
- normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]);
- colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]);
- texcoords0= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]);
- texcoords1= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]);
- texcoords0.setStride(mDrawPoolp->getStride());
- texcoords1.setStride(mDrawPoolp->getStride());
- vertices.setStride( mDrawPoolp->getStride());
- normals.setStride( mDrawPoolp->getStride());
- colors.setStride( mDrawPoolp->getStride());
- indicesp = (U32*)mBackupMem;
-
- return 0;
+ mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
+ mVertexBuffer->getNormalStrider(normals, mGeomIndex);
+ mVertexBuffer->getColorStrider(colors, mGeomIndex);
+ mVertexBuffer->getTexCoordStrider(texcoords0, mGeomIndex);
+ mVertexBuffer->getTexCoord2Strider(texcoords1, mGeomIndex);
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
}
else
{
- if (!reserveIfNeeded())
- {
- llinfos << "Get geometry failed!" << llendl;
- return -1;
- }
-
- llassert(mGeomIndex >= 0);
- llassert(mIndicesIndex >= 0);
-
- mDrawPoolp->getVertexStrider(vertices, mGeomIndex);
- mDrawPoolp->getNormalStrider(normals, mGeomIndex);
- mDrawPoolp->getColorStrider(colors, mGeomIndex);
- mDrawPoolp->getTexCoordStrider(texcoords0, mGeomIndex, 0);
- mDrawPoolp->getTexCoordStrider(texcoords1, mGeomIndex, 1);
-
- indicesp = mDrawPoolp->getIndices(mIndicesIndex);
-
- mDrawPoolp->setDirty();
-
- llassert(mGeomIndex >= 0);
- return mGeomIndex;
+ mGeomIndex = -1;
}
+
+ return mGeomIndex;
}
S32 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &normals,
- LLStrider<LLVector2> &tex_coords, U32 *&indicesp)
+ LLStrider<LLVector2> &tex_coords, LLStrider<U32> &indicesp)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
@@ -470,55 +303,31 @@ S32 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no
return -1;
}
- if (isState(BACKLIST))
+ if (mVertexBuffer.notNull())
{
- if (!mBackupMem)
+ mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
+ if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
+ {
+ mVertexBuffer->getNormalStrider(normals, mGeomIndex);
+ }
+ if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD))
{
- printDebugInfo();
- llerrs << "No backup memory for face" << llendl;
+ mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex);
}
- vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]);
- normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]);
- tex_coords= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]);
- tex_coords.setStride(mDrawPoolp->getStride());
- vertices.setStride( mDrawPoolp->getStride());
- normals.setStride( mDrawPoolp->getStride());
- indicesp = (U32*)mBackupMem;
- return 0;
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
}
else
{
- if (!reserveIfNeeded())
- {
- return -1;
- }
-
- llassert(mGeomIndex >= 0);
- llassert(mIndicesIndex >= 0);
-
- mDrawPoolp->getVertexStrider(vertices, mGeomIndex);
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK)
- {
- mDrawPoolp->getNormalStrider(normals, mGeomIndex);
- }
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK)
- {
- mDrawPoolp->getTexCoordStrider(tex_coords, mGeomIndex);
- }
-
- indicesp =mDrawPoolp->getIndices (mIndicesIndex);
-
- mDrawPoolp->setDirty();
-
- llassert(mGeomIndex >= 0);
- return mGeomIndex;
+ mGeomIndex = -1;
}
+
+ return mGeomIndex;
}
S32 LLFace::getGeometryColors(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &normals,
LLStrider<LLVector2> &tex_coords, LLStrider<LLColor4U> &colors,
- U32 *&indicesp)
+ LLStrider<U32> &indicesp)
{
S32 res = getGeometry(vertices, normals, tex_coords, indicesp);
if (res >= 0)
@@ -528,95 +337,25 @@ S32 LLFace::getGeometryColors(LLStrider<LLVector3> &vertices, LLStrider<LLVector
return res;
}
-S32 LLFace::getGeometryMultiTexture(
- LLStrider<LLVector3> &vertices,
- LLStrider<LLVector3> &normals,
- LLStrider<LLVector3> &binormals,
- LLStrider<LLVector2> &tex_coords0,
- LLStrider<LLVector2> &tex_coords1,
- U32 *&indicesp)
+void LLFace::updateCenterAgent()
{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (mGeomCount <= 0)
- {
- return -1;
- }
-
- if (isState(BACKLIST))
+ if (mDrawablep->isActive())
{
- if (!mBackupMem)
- {
- printDebugInfo();
- llerrs << "No backup memory for face" << llendl;
- }
- vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]);
- normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]);
- tex_coords0 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]);
- tex_coords0.setStride( mDrawPoolp->getStride() );
- vertices.setStride( mDrawPoolp->getStride() );
- normals.setStride( mDrawPoolp->getStride() );
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK)
- {
- binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]);
- binormals.setStride( mDrawPoolp->getStride() );
- }
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK)
- {
- tex_coords1 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]);
- tex_coords1.setStride( mDrawPoolp->getStride() );
- }
- indicesp = (U32*)mBackupMem;
-
- return 0;
+ mCenterAgent = mCenterLocal * getRenderMatrix();
}
else
{
- if (!reserveIfNeeded())
- {
- return -1;
- }
-
- llassert(mGeomIndex >= 0);
- llassert(mIndicesIndex >= 0);
-
- mDrawPoolp->getVertexStrider(vertices, mGeomIndex);
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK)
- {
- mDrawPoolp->getNormalStrider(normals, mGeomIndex);
- }
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK)
- {
- mDrawPoolp->getTexCoordStrider(tex_coords0, mGeomIndex);
- }
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK)
- {
- mDrawPoolp->getBinormalStrider(binormals, mGeomIndex);
- }
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK)
- {
- mDrawPoolp->getTexCoordStrider(tex_coords1, mGeomIndex, 1);
- }
- indicesp = mDrawPoolp->getIndices(mIndicesIndex);
-
- mDrawPoolp->setDirty();
-
- llassert(mGeomIndex >= 0);
- return mGeomIndex;
+ mCenterAgent = mCenterLocal;
}
}
-void LLFace::updateCenterAgent()
+void LLFace::renderForSelect(U32 data_mask)
{
- mCenterAgent = mCenterLocal * getRenderMatrix();
-}
-
-void LLFace::renderForSelect() const
-{
- if(mGeomIndex < 0 || mDrawablep.isNull())
+ if(mGeomIndex < 0 || mDrawablep.isNull() || mVertexBuffer.isNull())
{
return;
}
+
if (mVObjp->mGLName)
{
S32 name = mVObjp->mGLName;
@@ -630,47 +369,25 @@ void LLFace::renderForSelect() const
#endif
glColor4ubv(color.mV);
- if (mVObjp->getPCode() == LL_PCODE_VOLUME)
+ if (!getPool())
{
- LLVOVolume *volp;
- volp = (LLVOVolume *)(LLViewerObject*)mVObjp;
- if (volp->getNumFaces() == 1 && !volp->getVolumeChanged())
+ switch (getPoolType())
{
- // We need to special case the coalesced face model.
- S32 num_vfs = volp->getVolume()->getNumFaces();
- S32 offset = 0;
- S32 i;
-
- for (i = 0; i < num_vfs; i++)
- {
- if (gPickFaces)
- {
- // mask off high 4 bits (16 total possible faces)
- color.mV[0] &= 0x0f;
- color.mV[0] |= (i & 0x0f) << 4;
- glColor4ubv(color.mV);
- }
- S32 count = volp->getVolume()->getVolumeFace(i).mIndices.size();
- if (isState(GLOBAL))
- {
- glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset);
- }
- else
- {
- glPushMatrix();
- glMultMatrixf((float*)getRenderMatrix().mMatrix);
- glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset);
- glPopMatrix();
- }
- offset += count;
- }
- // We're done, return.
- return;
+ case LLDrawPool::POOL_ALPHA:
+ getTexture()->bind();
+ break;
+ default:
+ LLImageGL::unbindTexture(0);
+ break;
}
-
- // We don't have coalesced faces, do this the normal way.
}
+ mVertexBuffer->setBuffer(data_mask);
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(data_mask);
+#endif
+ U32* indicesp = (U32*) mVertexBuffer->getIndicesPointer() + mIndicesIndex;
+
if (gPickFaces && mTEOffset != -1)
{
// mask off high 4 bits (16 total possible faces)
@@ -683,13 +400,13 @@ void LLFace::renderForSelect() const
{
if (isState(GLOBAL))
{
- glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices());
+ glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp);
}
else
{
glPushMatrix();
glMultMatrixf((float*)getRenderMatrix().mMatrix);
- glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices());
+ glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp);
glPopMatrix();
}
}
@@ -697,13 +414,13 @@ void LLFace::renderForSelect() const
{
if (isState(GLOBAL))
{
- glDrawArrays(mPrimType, mGeomIndex, mGeomCount);
+ glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount);
}
else
{
glPushMatrix();
glMultMatrixf((float*)getRenderMatrix().mMatrix);
- glDrawArrays(mPrimType, mGeomIndex, mGeomCount);
+ glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount);
glPopMatrix();
}
}
@@ -712,11 +429,12 @@ void LLFace::renderForSelect() const
void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 offset, const S32 count)
{
- if(mGeomIndex < 0 || mDrawablep.isNull())
+ if(mGeomIndex < 0 || mDrawablep.isNull() || mVertexBuffer.isNull())
{
return;
}
- if (mGeomCount > 0)
+
+ if (mGeomCount > 0 && mIndicesCount > 0)
{
LLGLSPipelineAlpha gls_pipeline_alpha;
glColor4fv(color.mV);
@@ -729,110 +447,27 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32
glMultMatrixf((float*)getRenderMatrix().mMatrix);
}
- if (sSafeRenderSelect)
- {
- glBegin(mPrimType);
- if (count)
- {
- for (S32 i = offset; i < offset + count; i++)
- {
- LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0);
- glTexCoord2fv(tc.mV);
- LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i));
- glNormal3fv(normal.mV);
- LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv(vertex.mV);
- }
- }
- else
- {
- for (U32 i = 0; i < getIndicesCount(); i++)
- {
- LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0);
- glTexCoord2fv(tc.mV);
- LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i));
- glNormal3fv(normal.mV);
- LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv(vertex.mV);
- }
- }
- glEnd();
-
- if( gSavedSettings.getBOOL("ShowTangentBasis") )
- {
- S32 start;
- S32 end;
- if (count)
- {
- start = offset;
- end = offset + count;
- }
- else
- {
- start = 0;
- end = getIndicesCount();
- }
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
- LLGLSNoTexture gls_no_texture;
- glColor4f(1, 1, 1, 1);
- glBegin(GL_LINES);
- for (S32 i = start; i < end; i++)
- {
- LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv(vertex.mV);
- LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv( (vertex + normal * 0.1f).mV );
- }
- glEnd();
+ mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
+#endif
+ U32* indicesp = ((U32*) mVertexBuffer->getIndicesPointer()) + mIndicesIndex;
- if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK)
- {
- glColor4f(0, 1, 0, 1);
- glBegin(GL_LINES);
- for (S32 i = start; i < end; i++)
- {
- LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv(vertex.mV);
- LLVector3 binormal = mDrawPoolp->getBinormal(mDrawPoolp->getIndex(getIndicesStart() + i));
- glVertex3fv( (vertex + binormal * 0.1f).mV );
- }
- glEnd();
- }
- }
+ if (count)
+ {
+ glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indicesp + offset);
}
else
{
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- if (count)
- {
- if (mIndicesCount > 0)
- {
- glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset);
- }
- else
- {
- llerrs << "Rendering non-indexed volume face!" << llendl;
- glDrawArrays(mPrimType, mGeomIndex, mGeomCount);
- }
- }
- else
- {
- if (mIndicesCount > 0)
- {
- glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices());
- }
- else
- {
- glDrawArrays(mPrimType, mGeomIndex, mGeomCount);
- }
- }
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
+ glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp);
}
-
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
if (!isState(GLOBAL))
{
// Restore the tranform for non-global objects
@@ -843,6 +478,7 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32
void LLFace::renderSelectedUV(const S32 offset, const S32 count)
{
+#if 0
LLUUID uv_img_red_blue_id(gViewerArt.getString("uv_test1.tga"));
LLUUID uv_img_green_id(gViewerArt.getString("uv_test2.tga"));
LLViewerImage* red_blue_imagep = gImageList.getImage(uv_img_red_blue_id, TRUE, TRUE);
@@ -892,7 +528,7 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
glPolygonOffset(factor, bias);
if (sSafeRenderSelect)
{
- glBegin(mPrimType);
+ glBegin(GL_TRIANGLES);
if (count)
{
for (S32 i = offset; i < offset + count; i++)
@@ -924,7 +560,7 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
{
if (mIndicesCount > 0)
{
- glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset);
+ glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, getRawIndices() + offset);
}
else
{
@@ -936,15 +572,14 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
{
if (mIndicesCount > 0)
{
- glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices());
+ glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, getRawIndices());
}
else
{
- glDrawArrays(mPrimType, mGeomIndex, mGeomCount);
+ glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount);
}
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
}
glDisable(GL_POLYGON_OFFSET_FILL);
@@ -965,12 +600,13 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
//restore blend func
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+#endif
}
void LLFace::printDebugInfo() const
{
- LLDrawPool *poolp = getPool();
+ LLFacePool *poolp = getPool();
llinfos << "Object: " << getViewerObject()->mID << llendl;
if (getDrawable())
{
@@ -986,10 +622,6 @@ void LLFace::printDebugInfo() const
}
llinfos << "Face: " << this << llendl;
- if (isState(BACKLIST))
- {
- llinfos << "Backlisted!" << llendl;
- }
llinfos << "State: " << getState() << llendl;
llinfos << "Geom Index Data:" << llendl;
llinfos << "--------------------" << llendl;
@@ -1018,7 +650,7 @@ void LLFace::printDebugInfo() const
llinfos << "Incorrect number of pool references!" << llendl;
}
-
+#if 0
llinfos << "Indices:" << llendl;
llinfos << "--------------------" << llendl;
@@ -1039,149 +671,7 @@ void LLFace::printDebugInfo() const
llinfos << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << llendl;
}
llinfos << llendl;
-}
-
-S32 LLFace::backup()
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (isState(BACKLIST))
- {
- llwarns << "Face is already backed up in LLFace::backup!" << llendl;
- return mGeomCount;
- }
- if (mGeomIndex < 0)
- {
- // flexible objects can cause this
- //llwarns << "No geometry to back-up" << llendl;
- return 0;
- }
-
- S32 size = 0;
- if (!mBackupMem)
- {
- size = allocBackupMem();
- }
- else
- {
- llerrs << "Memory already backed up!" << llendl;
- }
-
- // Need to flag this, because we can allocate a non-zero backup mem if we have indices and no geometry.
-
- if (mGeomCount || mIndicesCount)
- {
- setState(BACKLIST);
-#if !RELEASE_FOR_DOWNLOAD
- if (mGeomIndex < 0 || mIndicesIndex < 0)
- {
- llerrs << "LLFace::backup" << llendl;
- }
#endif
-
- U32 *backup = (U32*)mBackupMem;
- S32 stride = mDrawPoolp->getStride();
-
- U32 *index = mDrawPoolp->getIndices(mIndicesIndex);
- for (U32 i=0;i<mIndicesCount;i++)
- {
- *backup++ = index[i] - mGeomIndex;
- index[i] = 0;
- }
-
- if (!mGeomCount)
- {
- return mGeomCount;
- }
- //
- // Don't change the order of these unles you change the corresponding getGeometry calls that read out of
- // backup memory, and also the other of the backup/restore pair!
- //
- memcpy(backup, (mDrawPoolp->mMemory.getMem() + mGeomIndex * stride), mGeomCount * stride); /*Flawfinder: ignore*/
- backup += mGeomCount * stride / 4;
-
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK)
- {
- memcpy(backup, &mDrawPoolp->getClothingWeight(mGeomIndex), mGeomCount * sizeof(LLVector4)); /*Flawfinder: ignore*/
- backup += mGeomCount*4;
- }
-
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK)
- {
- memcpy(backup, &mDrawPoolp->getVertexWeight(mGeomIndex), mGeomCount * sizeof(F32)); /*Flawfinder: ignore*/
- backup += mGeomCount;
- }
-
- llassert((U8*)backup - mBackupMem == size);
-
- unReserve();
- }
- return mGeomCount;
-}
-
-void LLFace::restore()
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
- if (!isState(BACKLIST))
- {
- // flexible objects can cause this
-// printDebugInfo();
-// llwarns << "not backlisted for restore" << llendl;
- return;
- }
- if (!mGeomCount || !mBackupMem)
- {
- if (!mBackupMem)
- {
- printDebugInfo();
- llwarns << "no backmem for restore" << llendl;
- }
-
- clearState(BACKLIST);
- return;
- }
-
- S32 stride = mDrawPoolp->getStride();
- mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount);
- mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount);
- mGeneration = mDrawPoolp->mGeneration;
-
- llassert(mGeomIndex >= 0);
- llassert(mIndicesIndex >= 0);
-
- U32 *backup = (U32*)mBackupMem;
- U32 *index = mDrawPoolp->getIndices(mIndicesIndex);
-
- for (U32 i=0;i<mIndicesCount;i++)
- {
- S32 ind = mGeomIndex + *backup;
- index[i] = ind;
- backup++;
- }
-
- mDrawPoolp->mMemory.copyToMem(mGeomIndex * stride, (U8 *)backup, mGeomCount * stride);
- backup += mGeomCount * stride / 4;
-
- //
- // Don't change the order of these unles you change the corresponding getGeometry calls that read out of
- // backup memory, and also the other of the backup/restore pair!
- //
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK)
- {
- mDrawPoolp->mClothingWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount);
- backup += mGeomCount*4;
- }
-
- if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK)
- {
- mDrawPoolp->mWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount);
- backup += mGeomCount;
- }
-
- delete[] mBackupMem;
- mBackupMem = NULL;
- clearState(BACKLIST);
}
// Transform the texture coordinates for this face.
@@ -1213,48 +703,197 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
}
-BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 f,
- const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume)
+BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
+ const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL global_volume)
+{
+ LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
+
+ const LLVolumeFace &face = volume.getVolumeFace(f);
+
+ //get bounding box
+ if (mDrawablep->isState(LLDrawable::REBUILD_ALL))
+ {
+ //vertex buffer no longer valid
+ mVertexBuffer = NULL;
+ mLastVertexBuffer = NULL;
+
+ LLVector3 min,max;
+
+ min = face.mExtents[0];
+ max = face.mExtents[1];
+
+ //min, max are in volume space, convert to drawable render space
+ LLVector3 center = ((min + max) * 0.5f)*mat_vert;
+ LLVector3 size = ((max-min) * 0.5f);
+ if (!global_volume)
+ {
+ size.scaleVec(mDrawablep->getVObj()->getScale());
+ }
+ LLQuaternion rotation = LLQuaternion(mat_normal);
+
+ LLVector3 v[4];
+ //get 4 corners of bounding box
+ v[0] = (size * rotation);
+ v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation);
+ v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation);
+ v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation);
+
+ LLVector3& newMin = mExtents[0];
+ LLVector3& newMax = mExtents[1];
+
+ newMin = newMax = center;
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 3; j++)
+ {
+ F32 delta = fabsf(v[i].mV[j]);
+ F32 min = center.mV[j] - delta;
+ F32 max = center.mV[j] + delta;
+
+ if (min < newMin.mV[j])
+ {
+ newMin.mV[j] = min;
+ }
+
+ if (max > newMax.mV[j])
+ {
+ newMax.mV[j] = max;
+ }
+ }
+ }
+
+ mCenterLocal = (newMin+newMax)*0.5f;
+ updateCenterAgent();
+ }
+
+ return TRUE;
+}
+
+
+BOOL LLFace::getGeometryVolume(const LLVolume& volume,
+ S32 f,
+ LLStrider<LLVector3>& vertices,
+ LLStrider<LLVector3>& normals,
+ LLStrider<LLVector2>& tex_coords,
+ LLStrider<LLVector2>& tex_coords2,
+ LLStrider<LLColor4U>& colors,
+ LLStrider<U32>& indicesp,
+ const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
+ U32& index_offset)
{
const LLVolumeFace &vf = volume.getVolumeFace(f);
S32 num_vertices = (S32)vf.mVertices.size();
S32 num_indices = (S32)vf.mIndices.size();
- setSize(num_vertices, num_indices);
- return genVolumeTriangles(volume, f, f, mat, inv_trans_mat, global_volume);
-}
+ LLStrider<LLVector3> old_verts;
+ LLStrider<LLVector2> old_texcoords;
+ LLStrider<LLVector2> old_texcoords2;
+ LLStrider<LLVector3> old_normals;
+ LLStrider<LLColor4U> old_colors;
-BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
- const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, const BOOL global_volume)
-{
- LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
+ BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
+ BOOL moved = TRUE;
- if (!mDrawablep)
+ BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
+ LLVector3 scale;
+ if (global_volume)
{
- return TRUE;
+ scale.setVec(1,1,1);
+ }
+ else
+ {
+ scale = mVObjp->getScale();
}
- S32 index_offset;
- F32 r, os, ot, ms, mt, cos_ang, sin_ang;
- LLStrider<LLVector3> vertices;
- LLStrider<LLVector3> normals;
- LLStrider<LLVector3> binormals;
- LLStrider<LLVector2> tex_coords;
- LLStrider<LLVector2> tex_coords2;
- U32 *indicesp = NULL;
+ if (!full_rebuild)
+ {
+ if (mLastVertexBuffer == mVertexBuffer &&
+ !mVertexBuffer->isEmpty())
+ { //this face really doesn't need to be regenerated, try real hard not to do so
+ if (mLastGeomCount == mGeomCount &&
+ mLastGeomIndex == mGeomIndex &&
+ mLastIndicesCount == mIndicesCount &&
+ mLastIndicesIndex == mIndicesIndex)
+ { //data is in same location in vertex buffer
+ moved = FALSE;
+ }
- BOOL bump = mDrawPoolp && (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK);
- BOOL is_static = mDrawablep->isStatic();
- BOOL is_global = is_static;
-
- if (bump)
- {
- index_offset = getGeometryMultiTexture(vertices, normals, binormals, tex_coords, tex_coords2, indicesp);
+ if (!moved && !mDrawablep->isState(LLDrawable::REBUILD_ALL))
+ { //nothing needs to be done
+ vertices += mGeomCount;
+ normals += mGeomCount;
+ tex_coords += mGeomCount;
+ colors += mGeomCount;
+ tex_coords2 += mGeomCount;
+ index_offset += mGeomCount;
+ indicesp += mIndicesCount;
+ return FALSE;
+ }
+
+ if (mLastGeomCount == mGeomCount)
+ {
+ if (mLastGeomIndex >= mGeomIndex &&
+ mLastGeomIndex + mGeomCount+1 < mVertexBuffer->getNumVerts())
+ {
+ //copy from further down the buffer
+ mVertexBuffer->getVertexStrider(old_verts, mLastGeomIndex);
+ mVertexBuffer->getTexCoordStrider(old_texcoords, mLastGeomIndex);
+ mVertexBuffer->getTexCoord2Strider(old_texcoords2, mLastGeomIndex);
+ mVertexBuffer->getNormalStrider(old_normals, mLastGeomIndex);
+ mVertexBuffer->getColorStrider(old_colors, mLastGeomIndex);
+
+ if (!mDrawablep->isState(LLDrawable::REBUILD_ALL))
+ {
+ //quick copy
+ for (S32 i = 0; i < mGeomCount; i++)
+ {
+ *vertices++ = *old_verts++;
+ *tex_coords++ = *old_texcoords++;
+ *tex_coords2++ = *old_texcoords2++;
+ *colors++ = *old_colors++;
+ *normals++ = *old_normals++;
+ }
+
+ for (U32 i = 0; i < mIndicesCount; i++)
+ {
+ *indicesp++ = vf.mIndices[i] + index_offset;
+ }
+
+ index_offset += mGeomCount;
+ mLastGeomIndex = mGeomIndex;
+ mLastIndicesCount = mIndicesCount;
+ mLastIndicesIndex = mIndicesIndex;
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ full_rebuild = TRUE;
+ }
+ }
+ }
+ else
+ {
+ full_rebuild = TRUE;
+ }
}
else
{
- index_offset = getGeometry(vertices, normals, tex_coords, indicesp);
+ mLastUpdateTime = gFrameTimeSeconds;
}
+
+
+ BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
+ BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
+ BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
+
+ F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
+
+ BOOL is_static = mDrawablep->isStatic();
+ BOOL is_global = is_static;
+
if (-1 == index_offset)
{
return TRUE;
@@ -1262,16 +901,6 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
LLVector3 center_sum(0.f, 0.f, 0.f);
- LLVector3 render_pos;
-
- if (mDrawablep->isState(LLDrawable::REBUILD_TCOORD) &&
- global_volume)
- {
- render_pos = mVObjp->getRenderPosition();
- }
-
- setPrimType(LLTriangles);
-
if (is_global)
{
setState(GLOBAL);
@@ -1280,26 +909,16 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
{
clearState(GLOBAL);
}
-
- LLVector3 min, max;
+
LLVector2 tmin, tmax;
- BOOL grab_first_vert = TRUE;
- BOOL grab_first_tcoord = TRUE;
-
- for (S32 vol_face = fstart; vol_face <= fend; vol_face++)
+ const LLTextureEntry *tep = mVObjp->getTE(f);
+ U8 bump_code = tep ? bump_code = tep->getBumpmap() : 0;
+
+ if (rebuild_tcoord)
{
- const LLVolumeFace &vf = volume.getVolumeFace(vol_face);
- S32 num_vertices = (S32)vf.mVertices.size();
- S32 num_indices = (S32)vf.mIndices.size();
- llassert(num_indices > 0);
-
- U8 bump_code;
- const LLTextureEntry *tep = mVObjp->getTE(vol_face);
-
if (tep)
{
- bump_code = tep->getBumpmap();
r = tep->getRotation();
os = tep->mOffsetS;
ot = tep->mOffsetT;
@@ -1310,7 +929,6 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
}
else
{
- bump_code = 0;
cos_ang = 1.0f;
sin_ang = 0.0f;
os = 0.0f;
@@ -1318,209 +936,228 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
ms = 1.0f;
mt = 1.0f;
}
+ }
- if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
+ if (isState(TEXTURE_ANIM))
+ {
+ LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
+ U8 mode = vobj->mTexAnimMode;
+ if (mode & LLViewerTextureAnim::TRANSLATE)
{
- // VERTICES & NORMALS
- for (S32 i = 0; i < num_vertices; i++)
- {
- LLVector3 v;
- v = vf.mVertices[i].mPosition * mat_vert;
+ os = ot = 0.f;
+ }
+ if (mode & LLViewerTextureAnim::ROTATE)
+ {
+ r = 0.f;
+ cos_ang = 1.f;
+ sin_ang = 0.f;
+ }
+ if (mode & LLViewerTextureAnim::SCALE)
+ {
+ ms = mt = 1.f;
+ }
+ }
- LLVector3 normal = vf.mVertices[i].mNormal * mat_normal;
- normal.normVec();
- *normals++ = normal;
-
- *vertices++ = v;
-
- if (grab_first_vert)
- {
- grab_first_vert = FALSE;
- min = max = v;
- }
- else
- {
- for (U32 j = 0; j < 3; j++)
- {
- if (v.mV[j] < min.mV[j])
- {
- min.mV[j] = v.mV[j];
- }
- if (v.mV[j] > max.mV[j])
- {
- max.mV[j] = v.mV[j];
- }
- }
- }
+ LLColor4U color = tep->getColor();
+
+ if (rebuild_color)
+ {
+ GLfloat alpha[4] =
+ {
+ 0.00f,
+ 0.25f,
+ 0.5f,
+ 0.75f
+ };
+
+ if (gPipeline.getPoolTypeFromTE(tep, getTexture()) == LLDrawPool::POOL_BUMP)
+ {
+ color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
+ }
+ }
+
+ // INDICES
+ if (full_rebuild || moved)
+ {
+ for (S32 i = 0; i < num_indices; i++)
+ {
+ *indicesp++ = vf.mIndices[i] + index_offset;
+ }
+ }
+ else
+ {
+ indicesp += num_indices;
+ }
+
+ //bump setup
+ LLVector3 binormal_dir( -sin_ang, cos_ang, 0 );
+ LLVector3 bump_s_primary_light_ray;
+ LLVector3 bump_t_primary_light_ray;
+
+ if (bump_code)
+ {
+ F32 offset_multiple;
+ switch( bump_code )
+ {
+ case BE_NO_BUMP:
+ offset_multiple = 0.f;
+ break;
+ case BE_BRIGHTNESS:
+ case BE_DARKNESS:
+ if( mTexture.notNull() && mTexture->getHasGLTexture())
+ {
+ // Offset by approximately one texel
+ S32 cur_discard = mTexture->getDiscardLevel();
+ S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
+ max_size <<= cur_discard;
+ const F32 ARTIFICIAL_OFFSET = 2.f;
+ offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
}
- for (S32 i = 0; i < num_indices; i++)
+ else
{
- S32 index = vf.mIndices[i] + index_offset;
- llassert(index >= 0 && (i != 1 || *(indicesp-1)!=(U32)index));
- *indicesp++ = index;
+ offset_multiple = 1.f/256;
}
+ break;
+
+ default: // Standard bumpmap textures. Assumed to be 256x256
+ offset_multiple = 1.f / 256;
+ break;
}
- if ((mDrawablep->isState(LLDrawable::REBUILD_TCOORD)) ||
- ((bump || getTextureEntry()->getTexGen() != 0) && mDrawablep->isState(LLDrawable::REBUILD_VOLUME)))
+ F32 s_scale = 1.f;
+ F32 t_scale = 1.f;
+ if( tep )
{
- // TEX COORDS AND BINORMALS
- LLVector3 binormal_dir( -sin_ang, cos_ang, 0 );
- LLVector3 bump_s_primary_light_ray;
- LLVector3 bump_t_primary_light_ray;
- if (bump)
- {
- F32 offset_multiple;
- switch( bump_code )
- {
- case BE_NO_BUMP:
- offset_multiple = 0.f;
- break;
- case BE_BRIGHTNESS:
- case BE_DARKNESS:
- if( mTexture.notNull() && mTexture->getHasGLTexture())
- {
- // Offset by approximately one texel
- S32 cur_discard = mTexture->getDiscardLevel();
- S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
- max_size <<= cur_discard;
- const F32 ARTIFICIAL_OFFSET = 2.f;
- offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
- }
- else
- {
- offset_multiple = 1.f/256;
- }
- break;
-
- default: // Standard bumpmap textures. Assumed to be 256x256
- offset_multiple = 1.f / 256;
- break;
- }
+ tep->getScale( &s_scale, &t_scale );
+ }
+ LLVector3 sun_ray = gSky.getSunDirection();
+ LLVector3 moon_ray = gSky.getMoonDirection();
+ LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
+ bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray;
+ bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray;
+ }
+
+ U8 texgen = getTextureEntry()->getTexGen();
- F32 s_scale = 1.f;
- F32 t_scale = 1.f;
- if( tep )
- {
- tep->getScale( &s_scale, &t_scale );
- }
- LLVector3 sun_ray = gSky.getSunDirection();
- LLVector3 moon_ray = gSky.getMoonDirection();
- LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
- bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray;
- bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray;
- }
-
- for (S32 i = 0; i < num_vertices; i++)
+ for (S32 i = 0; i < num_vertices; i++)
+ {
+ if (rebuild_tcoord)
+ {
+ LLVector2 tc = vf.mVertices[i].mTexCoord;
+
+ if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
{
- LLVector2 tc = vf.mVertices[i].mTexCoord;
+ LLVector3 vec = vf.mVertices[i].mPosition;
+
+ vec.scaleVec(scale);
- U8 texgen = getTextureEntry()->getTexGen();
- if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
+ switch (texgen)
{
+ case LLTextureEntry::TEX_GEN_PLANAR:
+ planarProjection(tc, vf.mVertices[i], vf.mCenter, vec);
+ break;
+ case LLTextureEntry::TEX_GEN_SPHERICAL:
+ sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
+ break;
+ case LLTextureEntry::TEX_GEN_CYLINDRICAL:
+ cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
+ break;
+ default:
+ break;
+ }
+ }
- LLVector3 vec = vf.mVertices[i].mPosition; //-vf.mCenter;
-
- if (global_volume)
- {
- vec -= render_pos;
- }
- else
- {
- vec.scaleVec(mVObjp->getScale());
- }
-
- switch (texgen)
- {
- case LLTextureEntry::TEX_GEN_PLANAR:
- planarProjection(tc, vf.mVertices[i], vf.mCenter, vec);
- break;
- case LLTextureEntry::TEX_GEN_SPHERICAL:
- sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
- break;
- case LLTextureEntry::TEX_GEN_CYLINDRICAL:
- cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
- break;
- default:
- break;
- }
- }
- xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
- *tex_coords++ = tc;
- if (grab_first_tcoord)
- {
- grab_first_tcoord = FALSE;
- tmin = tmax = tc;
- }
- else
- {
- for (U32 j = 0; j < 2; j++)
- {
- if (tmin.mV[j] > tc.mV[j])
- {
- tmin.mV[j] = tc.mV[j];
- }
- else if (tmax.mV[j] < tc.mV[j])
- {
- tmax.mV[j] = tc.mV[j];
- }
- }
- }
- if (bump)
- {
- LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal;
- LLMatrix3 tangent_to_object;
- tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal);
- LLVector3 binormal = binormal_dir * tangent_to_object;
+ xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
+ *tex_coords++ = tc;
+
+ if (bump_code)
+ {
+ LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal;
+ LLMatrix3 tangent_to_object;
+ tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal);
+ LLVector3 binormal = binormal_dir * tangent_to_object;
- if (!global_volume)
- {
- binormal = binormal * mat_normal;
- }
- binormal.normVec();
- tangent.normVec();
-
- tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal );
- *tex_coords2++ = tc;
+ binormal = binormal * mat_normal;
+ binormal.normVec();
- *binormals++ = binormal;
- }
+ tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal );
+ *tex_coords2++ = tc;
+ }
+ }
+ else if (moved)
+ {
+ *tex_coords++ = *old_texcoords++;
+ if (bump_code)
+ {
+ *tex_coords2++ = *old_texcoords2++;
}
}
+
+ if (rebuild_pos)
+ {
+ *vertices++ = vf.mVertices[i].mPosition * mat_vert;
- index_offset += num_vertices;
+ LLVector3 normal = vf.mVertices[i].mNormal * mat_normal;
+ normal.normVec();
+
+ *normals++ = normal;
+ }
+ else if (moved)
+ {
+ *normals++ = *old_normals++;
+ *vertices++ = *old_verts++;
+ }
- center_sum += vf.mCenter * mat_vert;
+ if (rebuild_color)
+ {
+ *colors++ = color;
+ }
+ else if (moved)
+ {
+ *colors++ = *old_colors++;
+ }
}
-
- center_sum /= (F32)(fend-fstart+1);
-
- if (is_static)
+
+ if (!rebuild_pos && !moved)
{
- mCenterAgent = center_sum;
- mCenterLocal = mCenterAgent - mDrawablep->getPositionAgent();
+ vertices += num_vertices;
}
- else
+
+ if (!rebuild_tcoord && !moved)
{
- mCenterLocal = center_sum;
- updateCenterAgent();
+ tex_coords2 += num_vertices;
+ tex_coords += num_vertices;
}
-
- if (!grab_first_vert && mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
+ else if (!bump_code)
{
- mExtents[0] = min;
- mExtents[1] = max;
+ tex_coords2 += num_vertices;
}
-
- if (!grab_first_tcoord && mDrawablep->isState(LLDrawable::REBUILD_TCOORD))
+
+ if (!rebuild_color && !moved)
{
- mTexExtents[0] = tmin;
- mTexExtents[1] = tmax;
+ colors += num_vertices;
}
-
+
+ if (rebuild_tcoord)
+ {
+ mTexExtents[0].setVec(0,0);
+ mTexExtents[1].setVec(1,1);
+ xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
+ xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
+ }
+
+ index_offset += num_vertices;
+
+ mLastVertexBuffer = mVertexBuffer;
+ mLastGeomCount = mGeomCount;
+ mLastGeomIndex = mGeomIndex;
+ mLastIndicesCount = mIndicesCount;
+ mLastIndicesIndex = mIndicesIndex;
+
return TRUE;
}
+#if 0
BOOL LLFace::genLighting(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend,
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL do_lighting)
{
@@ -1643,21 +1280,20 @@ BOOL LLFace::genShadows(const LLVolume* volume, const LLDrawable* drawablep, S32
}
return TRUE;
}
+#endif
BOOL LLFace::verify(const U32* indices_array) const
{
BOOL ok = TRUE;
// First, check whether the face data fits within the pool's range.
- if ((mGeomIndex < 0) || (mGeomIndex + mGeomCount) > (S32)getPool()->getVertexCount())
+ if ((mGeomIndex < 0) || (mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts())
{
ok = FALSE;
llinfos << "Face not within pool range!" << llendl;
}
S32 indices_count = (S32)getIndicesCount();
- S32 geom_start = getGeomStart();
- S32 geom_count = mGeomCount;
-
+
if (!indices_count)
{
return TRUE;
@@ -1669,6 +1305,10 @@ BOOL LLFace::verify(const U32* indices_array) const
llinfos << "Face has bogus indices count" << llendl;
}
+#if 0
+ S32 geom_start = getGeomStart();
+ S32 geom_count = mGeomCount;
+
const U32 *indicesp = indices_array ? indices_array + mIndicesIndex : getRawIndices();
for (S32 i = 0; i < indices_count; i++)
@@ -1687,6 +1327,7 @@ BOOL LLFace::verify(const U32* indices_array) const
ok = FALSE;
}
}
+#endif
if (!ok)
{
@@ -1737,7 +1378,7 @@ const LLColor4& LLFace::getRenderColor() const
void LLFace::renderSetColor() const
{
- if (!LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor)
+ if (!LLFacePool::LLOverrideFaceColor::sOverrideFaceColor)
{
const LLColor4* color = &(getRenderColor());
@@ -1754,61 +1395,21 @@ void LLFace::renderSetColor() const
S32 LLFace::pushVertices(const U32* index_array) const
{
- U32 indices_count = mIndicesCount;
- S32 ret = 0;
-#if ENABLE_FACE_LINKING
- LLFace* next = mNextFace;
-#endif
-
- if (mGeomCount < gGLManager.mGLMaxVertexRange && (S32) indices_count < gGLManager.mGLMaxIndexRange)
+ if (mIndicesCount)
{
- LLFace* current = (LLFace*) this;
- S32 geom_count = mGeomCount;
-#if ENABLE_FACE_LINKING
- while (current)
+ if (mGeomCount <= gGLManager.mGLMaxVertexRange &&
+ mIndicesCount <= (U32) gGLManager.mGLMaxIndexRange)
{
- //chop up batch into implementation recommended sizes
- while (next &&
- (current == next ||
- ((S32) (indices_count + next->mIndicesCount) < gGLManager.mGLMaxIndexRange &&
- geom_count + next->mGeomCount < gGLManager.mGLMaxVertexRange)))
- {
- indices_count += next->mIndicesCount;
- geom_count += next->mGeomCount;
- next = next->mNextFace;
- }
-#endif
- if (indices_count)
- {
- glDrawRangeElements(mPrimType, current->mGeomIndex, current->mGeomIndex + geom_count, indices_count,
- GL_UNSIGNED_INT, index_array + current->mIndicesIndex);
- }
- ret += (S32) indices_count;
- indices_count = 0;
- geom_count = 0;
-#if ENABLE_FACE_LINKING
- current = next;
+ glDrawRangeElements(GL_TRIANGLES, mGeomIndex, mGeomIndex + mGeomCount-1, mIndicesCount,
+ GL_UNSIGNED_INT, index_array + mIndicesIndex);
}
-#endif
- }
- else
- {
-#if ENABLE_FACE_LINKING
- while (next)
- {
- indices_count += next->mIndicesCount;
- next = next->mNextFace;
- }
-#endif
- if (indices_count)
+ else
{
- glDrawElements(mPrimType, indices_count, GL_UNSIGNED_INT, index_array + mIndicesIndex);
+ glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, index_array+mIndicesIndex);
}
- ret += (S32) indices_count;
}
- return ret;
-
+ return mIndicesCount;
}
const LLMatrix4& LLFace::getRenderMatrix() const
@@ -1835,19 +1436,25 @@ S32 LLFace::renderElements(const U32 *index_array) const
return ret;
}
-S32 LLFace::renderIndexed(const U32 *index_array) const
+S32 LLFace::renderIndexed()
{
- if (mSkipRender)
+ if(mGeomIndex < 0 || mDrawablep.isNull() || mDrawPoolp == NULL)
{
return 0;
}
+
+ return renderIndexed(mDrawPoolp->getVertexDataMask());
+}
- if(mGeomIndex < 0 || mDrawablep.isNull())
+S32 LLFace::renderIndexed(U32 mask)
+{
+ if (mVertexBuffer.isNull())
{
return 0;
}
-
- renderSetColor();
+
+ mVertexBuffer->setBuffer(mask);
+ U32* index_array = (U32*) mVertexBuffer->getIndicesPointer();
return renderElements(index_array);
}
@@ -1860,26 +1467,13 @@ S32 LLFace::getVertices(LLStrider<LLVector3> &vertices)
{
return -1;
}
- if (isState(BACKLIST))
- {
- if (!mBackupMem)
- {
- printDebugInfo();
- llerrs << "No backup memory for face" << llendl;
- }
- vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]);
- vertices.setStride( mDrawPoolp->getStride());
- return 0;
- }
- else
+
+ if (mGeomIndex >= 0) // flexible objects may not have geometry
{
- if (mGeomIndex >= 0) // flexible objects may not have geometry
- {
- mDrawPoolp->getVertexStrider(vertices, mGeomIndex);
- mDrawPoolp->setDirty();
- }
- return mGeomIndex;
+ mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
+
}
+ return mGeomIndex;
}
S32 LLFace::getColors(LLStrider<LLColor4U> &colors)
@@ -1888,42 +1482,17 @@ S32 LLFace::getColors(LLStrider<LLColor4U> &colors)
{
return -1;
}
- if (isState(BACKLIST))
- {
- llassert(mBackupMem);
- colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]);
- colors.setStride( mDrawPoolp->getStride());
- return 0;
- }
- else
- {
- llassert(mGeomIndex >= 0);
- mDrawPoolp->getColorStrider(colors, mGeomIndex);
- return mGeomIndex;
- }
-}
-
-S32 LLFace::getIndices(U32* &indicesp)
-{
- if (isState(BACKLIST))
- {
- indicesp = (U32*)mBackupMem;
- return 0;
- }
- else
- {
- indicesp = mDrawPoolp->getIndices(mIndicesIndex);
- llassert(mGeomIndex >= 0 && indicesp[0] != indicesp[1]);
- return mGeomIndex;
- }
+
+ llassert(mGeomIndex >= 0);
+ mVertexBuffer->getColorStrider(colors, mGeomIndex);
+ return mGeomIndex;
}
-void LLFace::link(LLFace* facep)
+S32 LLFace::getIndices(LLStrider<U32> &indicesp)
{
-#if ENABLE_FACE_LINKING
- mNextFace = facep;
- facep->mSkipRender = TRUE;
-#endif
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+ llassert(mGeomIndex >= 0 && indicesp[0] != indicesp[1]);
+ return mIndicesIndex;
}
LLVector3 LLFace::getPositionAgent() const
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 0d017d6efe..18db645305 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -19,18 +19,19 @@
#include "llquaternion.h"
#include "xform.h"
#include "lldarrayptr.h"
+#include "llvertexbuffer.h"
+#include "llviewerimage.h"
#include "llpagemem.h"
#include "llstat.h"
#include "lldrawable.h"
-#define ENABLE_FACE_LINKING 1 // Causes problems with snapshot rendering
-
-class LLDrawPool;
+class LLFacePool;
class LLVolume;
class LLViewerImage;
class LLTextureEntry;
class LLVertexProgram;
class LLViewerImage;
+class LLGeometryManager;
class LLFace
{
@@ -38,26 +39,12 @@ public:
enum EMasks
{
- SHARED_GEOM = 0x0001,
- LIGHT = 0x0002,
- REBUILD = 0x0004,
- GLOBAL = 0x0008,
- VISIBLE = 0x0010,
- BACKLIST = 0x0020,
- INTERP = 0x0040,
- FULLBRIGHT = 0x0080,
- HUD_RENDER = 0x0100,
- USE_FACE_COLOR = 0x0200,
-
- POINT_SPRITE = 0x10000,
- BOARD_SPRITE = 0x20000,
- FIXED_SPRITE = 0x40000,
- DEPTH_SPRITE = 0x80000
- };
-
- enum EDirty
- {
- DIRTY = -2
+ LIGHT = 0x0001,
+ GLOBAL = 0x0002,
+ FULLBRIGHT = 0x0004,
+ HUD_RENDER = 0x0008,
+ USE_FACE_COLOR = 0x0010,
+ TEXTURE_ANIM = 0x0020,
};
static void initClass();
@@ -74,54 +61,64 @@ public:
const S32 getGeomIndex() const { return mGeomIndex; } // index into draw pool
const U32 getGeomStart() const { return mGeomIndex; } // index into draw pool
LLViewerImage* getTexture() const { return mTexture; }
+ void setTexture(LLViewerImage* tex) { mTexture = tex; }
LLXformMatrix* getXform() const { return mXform; }
BOOL hasGeometry() const { return mGeomCount > 0; }
LLVector3 getPositionAgent() const;
- void setPrimType(U32 primType) { mPrimType = primType; }
- const U32 getPrimType() const { return mPrimType; }
-
+
U32 getState() const { return mState; }
void setState(U32 state) { mState |= state; }
void clearState(U32 state) { mState &= ~state; }
- BOOL isState(U32 state) const { return ((mState & state) != 0); }
-
+ BOOL isState(U32 state) const { return ((mState & state) != 0) ? TRUE : FALSE; }
+ void setVirtualSize(F32 size) { mVSize = size; }
+ void setPixelArea(F32 area) { mPixelArea = area; }
+ F32 getVirtualSize() const { return mVSize; }
+ F32 getPixelArea() const { return mPixelArea; }
void bindTexture(S32 stage = 0) const { LLViewerImage::bindTexture(mTexture, stage); }
void enableLights() const;
void renderSetColor() const;
S32 renderElements(const U32 *index_array) const;
- S32 renderIndexed (const U32 *index_array) const;
+ S32 renderIndexed ();
+ S32 renderIndexed (U32 mask);
S32 pushVertices(const U32* index_array) const;
void setWorldMatrix(const LLMatrix4& mat);
const LLTextureEntry* getTextureEntry() const { return mVObjp->getTE(mTEOffset); }
- LLDrawPool* getPool() const { return mDrawPoolp; }
- S32 getStride() const { return mDrawPoolp->getStride(); }
- const U32* getRawIndices() const { return &mDrawPoolp->mIndices[mIndicesIndex]; }
+ LLFacePool* getPool() const { return mDrawPoolp; }
+ U32 getPoolType() const { return mPoolType; }
LLDrawable* getDrawable() const { return mDrawablep; }
LLViewerObject* getViewerObject() const { return mVObjp; }
-
- void clearDirty() { mGeneration = mDrawPoolp->mGeneration; };
-
- S32 backup();
- void restore();
+ S32 getLOD() const { return mVObjp.notNull() ? mVObjp->getLOD() : 0; }
+ LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
+ void setPoolType(U32 type) { mPoolType = type; }
+ S32 getTEOffset() { return mTEOffset; }
void setViewerObject(LLViewerObject* object);
- void setPool(LLDrawPool *pool, LLViewerImage *texturep);
+ void setPool(LLFacePool *pool, LLViewerImage *texturep);
+
void setDrawable(LLDrawable *drawable);
void setTEOffset(const S32 te_offset);
- S32 getTEOffset() { return mTEOffset; }
+
void setFaceColor(const LLColor4& color); // override material color
void unsetFaceColor(); // switch back to material color
const LLColor4& getFaceColor() const { return mFaceColor; }
const LLColor4& getRenderColor() const;
- void unReserve(); // Set Removed from pool
-
- BOOL reserveIfNeeded(); // Reserves data if dirty.
-
+ //for volumes
+ S32 getGeometryVolume(const LLVolume& volume,
+ S32 f,
+ LLStrider<LLVector3>& vertices,
+ LLStrider<LLVector3>& normals,
+ LLStrider<LLVector2>& texcoords,
+ LLStrider<LLVector2>& texcoords2,
+ LLStrider<LLColor4U>& colors,
+ LLStrider<U32>& indices,
+ const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
+ U32& index_offset);
+
// For avatar
S32 getGeometryAvatar(
LLStrider<LLVector3> &vertices,
@@ -137,69 +134,51 @@ public:
LLStrider<LLColor4U> &colors,
LLStrider<LLVector2> &texCoords0,
LLStrider<LLVector2> &texCoords1,
- U32* &indices);
+ LLStrider<U32> &indices);
// For volumes, etc.
S32 getGeometry(LLStrider<LLVector3> &vertices,
LLStrider<LLVector3> &normals,
LLStrider<LLVector2> &texCoords,
- U32* &indices);
+ LLStrider<U32> &indices);
S32 getGeometryColors(LLStrider<LLVector3> &vertices,
LLStrider<LLVector3> &normals,
LLStrider<LLVector2> &texCoords,
LLStrider<LLColor4U> &colors,
- U32* &indices);
+ LLStrider<U32> &indices);
- S32 getGeometryMultiTexture(LLStrider<LLVector3> &vertices,
- LLStrider<LLVector3> &normals,
- LLStrider<LLVector3> &binormals,
- LLStrider<LLVector2> &texCoords0,
- LLStrider<LLVector2> &texCoords1,
- U32* &indices);
-
-
- S32 getVertices (LLStrider<LLVector3> &vertices);
- S32 getColors (LLStrider<LLColor4U> &colors);
- S32 getIndices (U32* &indices);
+ S32 getVertices(LLStrider<LLVector3> &vertices);
+ S32 getColors(LLStrider<LLColor4U> &colors);
+ S32 getIndices(LLStrider<U32> &indices);
void setSize(const S32 numVertices, const S32 num_indices = 0);
- BOOL getDirty() const { return (mGeneration != mDrawPoolp->mGeneration); }
-
- BOOL genVolumeTriangles(const LLVolume &volume, S32 f,
- const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE);
- BOOL genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend,
+
+ BOOL genVolumeBBoxes(const LLVolume &volume, S32 f,
const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE);
- BOOL genLighting(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend,
- const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL do_lighting);
-
- BOOL genShadows(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend,
- const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL use_shadow_factor);
-
+
void init(LLDrawable* drawablep, LLViewerObject* objp);
void destroy();
void update();
void updateCenterAgent(); // Update center when xform has changed.
- void renderSelectedUV(const S32 offset = 0, const S32 count = 0);
+ void renderSelectedUV(const S32 offset = 0, const S32 count = 0);
- void renderForSelect() const;
+ void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD);
void renderSelected(LLImageGL *image, const LLColor4 &color, const S32 offset = 0, const S32 count = 0);
F32 getKey() const { return mDistance; }
- S32 getGeneration() const { return mGeneration; }
S32 getReferenceIndex() const { return mReferenceIndex; }
void setReferenceIndex(const S32 index) { mReferenceIndex = index; }
BOOL verify(const U32* indices_array = NULL) const;
void printDebugInfo() const;
- void link(LLFace* facep);
+ void setGeomIndex(S32 idx) { mGeomIndex = idx; }
+ void setIndicesIndex(S32 idx) { mIndicesIndex = idx; }
protected:
- S32 allocBackupMem(); // Allocate backup memory based on the draw pool information.
- void setDirty();
public:
LLVector3 mCenterLocal;
@@ -208,30 +187,39 @@ public:
LLVector2 mTexExtents[2];
F32 mDistance;
F32 mAlphaFade;
- LLFace* mNextFace;
- BOOL mSkipRender;
-
+ LLPointer<LLVertexBuffer> mVertexBuffer;
+ LLPointer<LLVertexBuffer> mLastVertexBuffer;
+ F32 mLastUpdateTime;
+
protected:
- S32 mGeneration;
+ friend class LLGeometryManager;
+ friend class LLVolumeGeometryManager;
+
U32 mState;
- LLDrawPool* mDrawPoolp;
- S32 mGeomIndex; // index into draw pool
+ LLFacePool* mDrawPoolp;
+ U32 mPoolType;
LLColor4 mFaceColor; // overrides material color if state |= USE_FACE_COLOR
- U32 mPrimType;
S32 mGeomCount; // vertex count for this face
+ S32 mGeomIndex; // index into draw pool
U32 mIndicesCount;
S32 mIndicesIndex; // index into draw pool for indices (yeah, I know!)
- LLXformMatrix* mXform;
- LLPointer<LLViewerImage> mTexture;
- U8 *mBackupMem;
+ //previous rebuild's geometry info
+ S32 mLastGeomCount;
+ S32 mLastGeomIndex;
+ U32 mLastIndicesCount;
+ S32 mLastIndicesIndex;
+ LLXformMatrix* mXform;
+ LLPointer<LLViewerImage> mTexture;
LLPointer<LLDrawable> mDrawablep;
LLPointer<LLViewerObject> mVObjp;
S32 mTEOffset;
S32 mReferenceIndex;
+ F32 mVSize;
+ F32 mPixelArea;
protected:
static BOOL sSafeRenderSelect;
@@ -245,6 +233,43 @@ public:
}
};
+ struct CompareTexture
+ {
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
+ {
+ return lhs->getTexture() < rhs->getTexture();
+ }
+ };
+
+ struct CompareTextureAndGeomCount
+ {
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
+ {
+ return lhs->getTexture() == rhs->getTexture() ?
+ lhs->getGeomCount() < rhs->getGeomCount() :
+ lhs->getTexture() > rhs->getTexture();
+ }
+ };
+
+ struct CompareTextureAndLOD
+ {
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
+ {
+ return lhs->getTexture() == rhs->getTexture() ?
+ lhs->getLOD() < rhs->getLOD() :
+ lhs->getTexture() < rhs->getTexture();
+ }
+ };
+
+ struct CompareTextureAndTime
+ {
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
+ {
+ return lhs->getTexture() == rhs->getTexture() ?
+ lhs->mLastUpdateTime < rhs->mLastUpdateTime :
+ lhs->getTexture() < rhs->getTexture();
+ }
+ };
};
#endif // LL_LLFACE_H
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 57f786053a..09610b01a3 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -67,31 +67,41 @@ static struct ft_display_info ft_display_table[] =
{ LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 },
{ LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 },
{ LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 },
- { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 0 },
- { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 },
+ { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 },
+ { LLFastTimer::FTM_TEMP1, " Blur", &LLColor4::red1, 0 },
+ { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 1 },
+ { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 },
+ { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull", &LLColor4::blue4, 0 },
+ { LLFastTimer::FTM_OCCLUSION, " Object Occlude", &LLColor4::pink1, 0 },
+ { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read", &LLColor4::red2, 0 },
{ LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 },
{ LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 },
- { LLFastTimer::FTM_OCCLUSION, " Object Occlude",&LLColor4::pink1, 0 },
- { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read",&LLColor4::red2, 0 },
{ LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 0 },
{ LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
{ LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
{ LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
{ LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
+ { LLFastTimer::FTM_UPDATE_AVATAR, " Avatar", &LLColor4::yellow1, 0 },
+ { LLFastTimer::FTM_UPDATE_TREE, " Tree", &LLColor4::yellow2, 0 },
+ { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain", &LLColor4::yellow6, 0 },
+ { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds", &LLColor4::yellow7, 0 },
+ { LLFastTimer::FTM_UPDATE_GRASS, " Grass", &LLColor4::yellow8, 0 },
+ { LLFastTimer::FTM_UPDATE_WATER, " Water", &LLColor4::yellow9, 0 },
{ LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 },
{ LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 },
{ LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 },
+ { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim", &LLColor4::blue4, 0 },
{ LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 },
{ LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 },
{ LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 },
- { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 1 },
+ { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 0 },
{ LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 },
{ LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 },
{ LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 },
{ LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 },
{ LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 },
{ LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 },
+ { LLFastTimer::FTM_TEMP5, " Check", &LLColor4::red1, 1},
{ LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 },
{ LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 },
{ LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 },
@@ -106,17 +116,35 @@ static struct ft_display_info ft_display_table[] =
{ LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 },
{ LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 },
{ LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 },
+ { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Textures",&LLColor4::red1, 0 },
{ LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 },
// { LLFastTimer::FTM_IDLE_CB, " Callbacks", &LLColor4::pink1, 0 },
- { LLFastTimer::FTM_RENDER, " Render", &green0, 0 },
+ { LLFastTimer::FTM_RENDER, " Render", &green0, 1 },
{ LLFastTimer::FTM_REBUILD, " Rebuild", &LLColor4::green1, 1 },
{ LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
+ { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
+ { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
+ { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
+ { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
+ { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },
+ { LLFastTimer::FTM_REBUILD_NONE_VB, " Unknown", &LLColor4::cyan5, 0 },
+ { LLFastTimer::FTM_REBUILD_BRIDGE_VB, " Bridge", &LLColor4::blue2, 0 },
+ { LLFastTimer::FTM_REBUILD_HUD_VB, " HUD", &LLColor4::blue3, 0 },
+ { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain", &LLColor4::blue4, 0 },
+ { LLFastTimer::FTM_REBUILD_WATER_VB, " Water", &LLColor4::blue5, 0 },
+ { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 },
+ { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 },
+ { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 },
+ { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 },
{ LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 },
- { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 0 },
- { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 0 },
+ { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 },
+ { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 },
{ LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 },
{ LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 },
{ LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 },
+ { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright", &LLColor4::yellow5, 0 },
+ { LLFastTimer::FTM_RENDER_GRASS, " Grass", &LLColor4::yellow6, 0 },
+ { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible", &LLColor4::red2, 0 },
{ LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 },
{ LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 },
{ LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 },
@@ -130,15 +158,16 @@ static struct ft_display_info ft_display_table[] =
// { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 },
// { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
{ LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink1, 0 },
+ { LLFastTimer::FTM_TEMP6, " Client Copy", &LLColor4::red1, 1},
-// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 },
-// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 },
-// { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 },
-// { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 },
-// { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 },
-// { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 },
-// { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 },
-// { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 },
+// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 },
+// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 },
+// { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 },
+// { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 },
+// { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 },
+// { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 },
+// { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 },
+// { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 },
{ LLFastTimer::FTM_OTHER, " Other", &red0 }
};
@@ -148,7 +177,7 @@ static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_
S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse)
LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect)
-: LLView(name, rect, TRUE)
+ : LLFloater(name, rect, "Fast Timers")
{
setVisible(FALSE);
mDisplayMode = 0;
@@ -891,7 +920,10 @@ void LLFastTimerView::draw()
F32 ms = (F32)((F64)max_ticks * iclock_freq);
//display y-axis range
- LLString tdesc = llformat("%4.2f ms", ms);
+ LLString tdesc = mDisplayCalls ?
+ llformat("%d calls", max_ticks) :
+ llformat("%4.2f ms", ms);
+
x = graph_rect.mRight - LLFontGL::sMonospace->getWidth(tdesc)-5;
y = graph_rect.mTop - ((S32)LLFontGL::sMonospace->getLineHeight());
@@ -957,6 +989,13 @@ void LLFastTimerView::draw()
for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++)
{
U64 ticks = ticks_sum[j+1][idx];
+ if (mDisplayCalls)
+ {
+ S32 tidx = ft_display_table[idx].timer;
+ S32 hidx = (LLFastTimer::sLastFrameIndex + j) % LLFastTimer::FTM_HISTORY_NUM;
+ ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx];
+ }
+
if (alpha == 1.f)
{ //normalize to highlighted timer
cur_max = llmax(cur_max, ticks);
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index eb30f60f3d..be66a8481a 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -9,10 +9,10 @@
#ifndef LL_LLFASTTIMERVIEW_H
#define LL_LLFASTTIMERVIEW_H
-#include "llview.h"
+#include "llfloater.h"
#include "llframetimer.h"
-class LLFastTimerView : public LLView
+class LLFastTimerView : public LLFloater
{
public:
LLFastTimerView(const std::string& name, const LLRect& rect);
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index bee2f879ac..e3b5a2bb68 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -137,7 +137,7 @@ BOOL LLFeatureList::maskList(LLFeatureList &mask)
}
#if 0 && !LL_RELEASE_FOR_DOWNLOAD
- llinfos << "After appling mask " << mask.mName << llendl;
+ llinfos << "After applying mask " << mask.mName << llendl;
dump();
#endif
return TRUE;
@@ -276,7 +276,6 @@ BOOL LLFeatureManager::loadFeatureTables()
}
}
file.close();
- //flp->dump();
return TRUE;
}
@@ -361,10 +360,11 @@ void LLFeatureManager::loadGPUClass()
llinfos << "GPU is " << label << llendl;
mGPUString = label;
mGPUClass = (S32) strtol(cls, NULL, 10);
+ file.close();
+ return;
}
}
file.close();
- //flp->dump();
llwarns << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << llendl;
}
@@ -382,11 +382,7 @@ void LLFeatureManager::initCPUFeatureMasks()
{
maskFeatures("RAM256MB");
}
- else if (gSysMemory.getPhysicalMemory() <= 512*1024*1024)
- {
- //maskFeatures("RAM512MB");
- }
-
+
if (gSysCPU.getMhz() < 1100)
{
maskFeatures("CPUSlow");
@@ -449,7 +445,11 @@ void LLFeatureManager::initGraphicsFeatureMasks()
}
if (gGLManager.mIsIntel)
{
- maskFeatures("Brookdale");
+ maskFeatures("Intel");
+ }
+ if (gGLManager.mGLVersion < 1.5f)
+ {
+ maskFeatures("OpenGLPre15");
}
if (gGLManager.mIsMobilityRadeon9000)
@@ -464,303 +464,6 @@ void LLFeatureManager::initGraphicsFeatureMasks()
extern LLOSInfo gSysOS;
-
-BOOL bad_hardware_dialog(const LLString &info_str, const LLString &url)
-{
- if (!gSavedSettings.getWarning("AboutBadPCI"))
- {
- return FALSE;
- }
-
- // XUI:translate
- std::string msg = llformat(
- "[SECOND_LIFE] has detected that there may be a problem with.\n"
- "hardware or drivers on your computer. Often resolving these\n"
- "issues can result in enhanced stability and performance.\n"
- " \n"
- "%s\n"
- " \n"
- "Would you like to view a web page with more detailed\n"
- "information on this problem?\n", info_str.c_str());
-
- // Warn them that runnin without DirectX 9 will
- // not allow us to tell them about driver issues
- S32 button = OSMessageBox(msg.c_str(),
- "Warning",
- OSMB_YESNO);
- if (OSBTN_YES== button)
- {
- llinfos << "User quitting after detecting bad drivers" << llendl;
- spawn_web_browser(url.c_str());
- return TRUE;
- }
- else
- {
- // Don't warn about bad PCI stuff again, they've clicked past it.
- gSavedSettings.setWarning("AboutBadPCI", FALSE);
- }
- return FALSE;
-}
-
-BOOL LLFeatureManager::initPCIFeatureMasks()
-{
-#if LL_WINDOWS
- BOOL exit_after_bad = FALSE;
-
- BOOL is_2000 = FALSE;
- BOOL is_xp = FALSE;
-
- if (gSysOS.mMajorVer != 5)
- {
- // Unknown windows version number, exit!"
- llwarns << "Unknown Windows major version " << gSysOS.mMajorVer << ", aborting detection!" << llendl;
- return FALSE;
- }
- if (gSysOS.mMinorVer == 0)
- {
- is_2000 = TRUE;
- }
- else if (gSysOS.mMinorVer == 1)
- {
- is_xp = TRUE;
- }
- else
- {
- llwarns << "Unknown Windows minor version " << gSysOS.mMinorVer << ", aborting detection!" << llendl;
- return FALSE;
- }
-
- // This only works on Win32, as it relies on DX9 hardware detection
- // The PCI masks are actually the inverse of the normal masks
- // We actually look through the masks,and see if any hardware matches it.
- // This is because the masks encode logic about
-
- // Check for the broken AMD AGP controllers (751, 761, 762)
-
- // Horrible cruddy fixed lookup table.
- // Figure out what OS we're on, the version numbers are different. Sigh...
-
- LLDXDriverFile *dfilep = NULL;
- LLDXDevice *devp = NULL;
-
- // AMD(1022) AGP controllers
- // 7007 AMD-751 AGP Controller
- // 700F AMD-761 AGP Controller
- // 700D AMD-762 AGP Controller
- devp = gDXHardware.findDevice("VEN_1022", "DEV_7007|DEV_700F|DEV_700D");
- if (devp)
- {
- // We're just pretty much screwed here, there are big problems with this hardware
- // We've got trouble with the most recent nVidia drivers. Check for this and warn.
-
- // Note: Need to detect that we're running with older nVidia hardware, probably
- exit_after_bad |= bad_hardware_dialog("AMD AGP Controller",
- AMD_AGP_URL);
- }
-
- // VIA(1106) AGP Controllers
- // These need upgrading on both Win2K and WinXP
- //
- // 8305 VT8363/8365 CPU to AGP - Apollo KT133/KM133
- // 8598 VT82C598MVP/694X CPU to AGP - Apollo MVP3/Pro133A
- // 8605 VT8605 CPU to AGP - Apollo PM133
- // B091 VT8633 CPU to AGP - Apollo Pro 266
- // B099 VT8366/A/T CPU to AGP - Apollo KT266/A/333
- // B168 VT8235 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X333 chipset
- // B188 VT8237 CPU to AGP (AGP 2.0/3.0) - K8T800
- // B198 VT8237 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X600 chipset
-
- devp = gDXHardware.findDevice("VEN_1106",
- "DEV_8305|DEV_8598|DEV_8605|DEV_B091|"
- "DEV_B099|DEV_B168|DEV_B188|DEV_B198");
- if (devp)
- {
- BOOL out_of_date = FALSE;
- // Wanted driver: VIAAGP1.SYS
- // Version Format: M.mm.0000.vvvv
- // M.mm - Major/minor OS version (5.0 for Win2000, 5.1 for WinXP)
- // vvvv - driver version number
- //
- // Notes:
- // 3442 is most recent as of 2/25/04, probably want at least 3430 (seems to be a common version)
-
- // These are DELIBERATE assignments inside if statements, blech.
- if (dfilep = devp->findDriver("pci.sys"))
- {
- // Old driver: pci.sys
- // Version: 5.01.2600.xxxx
- //
- // Notes:
- // Default WinXP driver for B168, B198?
-
- // Old driver: pci.sys
- // Version: 5.01.2195.xxxx
- //
- // Notes:
- // Default Win2K driver for 8305?
-
- llwarns << "Detected pci.sys" << llendl;
- write_debug("Old driver (pci.sys) for VIA detected!");
- out_of_date = TRUE;
- }
- else if (dfilep = devp->findDriver("VIAAGP.SYS"))
- {
- // Old driver: VIAAGP.SYS
- // Version: 5.01.2600.xxxx
- //
- // Notes:
- // Default WinXP driver for B09x?
-
- llwarns << "Detected VIAAGP.SYS" << llendl;
- write_debug("Old driver (VIAAGP.SYS) for VIA detected!");
- out_of_date = TRUE;
- }
- else if (dfilep = devp->findDriver("VIAAGP1.SYS"))
- {
- if (dfilep->mVersion.getField(3) < 3430)
- {
- // They're using a pretty old version of the VIA AGP drivers
- // Maybe they want to upgrade?
- llwarns << "Detected VIAAGP1.SYS" << llendl;
- write_debug("Old driver (VIAAGP1.SYS) for VIA detected!");
- out_of_date = TRUE;
- }
- }
- if (out_of_date)
- {
- exit_after_bad |= bad_hardware_dialog("Out of date VIA AGP chipset driver",
- VIA_URL);
- }
- }
-
- // Intel(8086) AGP controllers (Win2K)
- // These particular controllers only may need drivers on Win2K
- //
- // 1A31 82845[MP|MZ] Processor to AGP Controller
- // 2532 82850/860 Processor to AGP Controller
- if (is_2000)
- {
- devp = gDXHardware.findDevice("VEN_8086",
- "DEV_1A31");
- if (devp)
- {
- if (dfilep = devp->findDriver("pci.sys"))
- {
- // Old driver: pci.sys
- // Version 5.01.21[9|6]5.xxxx
- //
- // Notes:
- // Default driver for Win2K? Not sure what the "correct" driver is -
- // maybe some variant of AGP440.SYS?
- llwarns << "Detected pci.sys" << llendl;
- write_debug("Old driver (pci.sys) for Intel 82845/850 on Win2K detected!");
- exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver",
- INTEL_CHIPSET_URL);
- }
- }
- }
-
- /* Removed 4/3/2006 by JC
- After talking with Doug, we don't know what the proper driver
- and/or version number should be for Intel 865. Regardless, this
- code would _always_ complain if you had that chipset.
-
- // Intel(8086) AGP controllers (All)
- // These particular controllers may need drivers on both Win2K and WinXP
- //
- // 2561 82845G/GL/GE/PE/GV Processor to AGP Controller
- // 2571 82865G/PE/P/GV/28248P Processor to AGP Controller
- devp = gDXHardware.findDevice("VEN_8086",
- "DEV_2571");
- if (devp)
- {
- // Wanted driver: AGP440.SYS(?)
- //
- // Notes:
- // Not sure, need to verify with an actual 82865/75 (Dell 8300?)
-
- // Old driver: pci.sys
- // Version 5.01.21[9|6]5.xxxx
- //
- // Notes:
- // Default driver for Win2K? Not sure what the "correct" driver is -
- // maybe some variant of AGP440.SYS?
- exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver",
- INTEL_CHIPSET_URL);
- }
- */
-
-
- // SiS(1039) AGP controllers (All)
- // These particular controllers may need drivers on both Win2K and WinXP
- //
- // 0001 SiS 530
- // 0002 SiS SG86C202(???)
- // 0003 SiS 648FX
- devp = gDXHardware.findDevice("VEN_1039",
- "DEV_0001|DEV_0002|DEV_0003");
- if (devp)
- {
- BOOL out_of_date = FALSE;
- // Wanted driver: SISAGPX.SYS
- //
- // Notes:
- // Not sure, need to verify with an actual 82865/75 (Dell 8300?)
-
- // Old driver: pci.sys
- // Version 5.01.21[9|6]5.xxxx
- //
- // Notes:
- // Default driver for Win2K? Not sure what the "correct" driver is -
- // maybe some variant of AGP440.SYS?
- if (dfilep = devp->findDriver("pci.sys"))
- {
- // Old driver: pci.sys
- // Version 5.01.21[9|6]5.xxxx
- //
- llwarns << "Detected pci.sys" << llendl;
- write_debug("Old driver (pci.sys) for SiS detected!");
- out_of_date = TRUE;
- }
-
- if (dfilep = devp->findDriver("sisagp.sys"))
- {
- // Old driver: pci.sys
- // Version 5.01.21[9|6]5.xxxx
- //
- llwarns << "Detected sisagp.sys" << llendl;
- write_debug("Old driver (sisagp.sys) for SiS detected!");
- out_of_date = TRUE;
- }
-
- if (dfilep = devp->findDriver("sisagpx.sys"))
- {
- // Old driver: pci.sys
- // Version 7.02.0000.xxxx
- //
- // Notes:
- // Default driver for Win2K? Not sure what the "correct" driver is -
- // maybe some variant of AGP440.SYS?
- if (dfilep->mVersion.getField(3) < 1160)
- {
- out_of_date = TRUE;
- llwarns << "Detected sisagpx.sys" << llendl;
- write_debug("Old driver (sisagpx.sys) for SiS detected!");
- }
- }
- if (out_of_date)
- {
- exit_after_bad |= bad_hardware_dialog("Out of date SiS chipset driver",
- SIS_CHIPSET_URL);
- }
- }
-
- return exit_after_bad;
-#else
- return TRUE;
-#endif
-}
-
void LLFeatureManager::applyRecommendedFeatures()
{
// see featuretable.txt
@@ -770,14 +473,14 @@ void LLFeatureManager::applyRecommendedFeatures()
dump();
#endif
- // Enabling AGP
- if (getRecommendedLevel("RenderAGP"))
+ // Enabling VBO
+ if (getRecommendedLevel("RenderVBO"))
{
- gSavedSettings.setBOOL("RenderUseAGP", TRUE);
+ gSavedSettings.setBOOL("RenderVBOEnable", TRUE);
}
else
{
- gSavedSettings.setBOOL("RenderUseAGP", FALSE);
+ gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
}
// Anisotropic rendering
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index fe37cd7638..8988d790e8 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -81,8 +81,7 @@ public:
void initCPUFeatureMasks();
void initGraphicsFeatureMasks();
- BOOL initPCIFeatureMasks();
-
+
void applyRecommendedFeatures();
protected:
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 98bbf23502..2b2a9fa859 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -345,6 +345,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
mOFN.lpstrFilter = RAW_FILTER \
L"\0";
break;
+ case FFSAVE_J2C:
+ if (!filename)
+ {
+ wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
+ }
+ mOFN.lpstrDefExt = L"j2c";
+ mOFN.lpstrFilter =
+ L"Compressed Images (*.j2c)\0*.j2c\0" \
+ L"\0";
+ break;
default:
return FALSE;
}
@@ -660,6 +670,12 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
extension = CFSTR(".raw");
break;
+ case FFSAVE_J2C:
+ type = '\?\?\?\?';
+ creator = 'prvw';
+ extension = CFSTR(".j2c");
+ break;
+
case FFSAVE_ALL:
default:
type = '\?\?\?\?';
@@ -1063,6 +1079,10 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
caption += "RAW File (*.raw)";
suggest_ext += ".raw";
break;
+ case FFSAVE_J2C:
+ caption += "Compressed Images (*.j2c)";
+ suggest_ext += ".j2c";
+ break;
default:;
break;
}
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 9b0eddbe2d..c04279ee91 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -87,6 +87,7 @@ public:
FFSAVE_XML = 9,
FFSAVE_COLLADA = 10,
FFSAVE_RAW = 11,
+ FFSAVE_J2C = 12,
};
// open the dialog. This is a modal operation
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 5e105ac7e2..4e03e34663 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -25,11 +25,6 @@
#include "llviewerregion.h"
#include "llworld.h"
-/*static*/ LLVolumeImplFlexible::lodset_t LLVolumeImplFlexible::sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ];
-/*static*/ U64 LLVolumeImplFlexible::sCurrentUpdateFrame = 0;
-/*static*/ U32 LLVolumeImplFlexible::sDebugInserted = 0;
-/*static*/ U32 LLVolumeImplFlexible::sDebugVisible = 0;
-
/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
@@ -40,14 +35,13 @@
LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) :
mVO(vo), mAttributes(attributes)
{
+ static U32 seed = 0;
+ mID = seed++;
mInitialized = FALSE;
mUpdated = FALSE;
- mJustShifted = FALSE;
mInitializedRes = -1;
mSimulateRes = 0;
mFrameNum = 0;
- mLastUpdate = 0;
-
}//-----------------------------------------------
LLVector3 LLVolumeImplFlexible::getFramePosition() const
@@ -75,7 +69,6 @@ void LLVolumeImplFlexible::onShift(const LLVector3 &shift_vector)
{
mSection[section].mPosition += shift_vector;
}
- mVO->getVolume()->mBounds[0] += shift_vector;
}
//-----------------------------------------------------------------------------------------------
@@ -88,7 +81,7 @@ void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LL
void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 source_sections,
LLFlexibleObjectSection *dest, S32 dest_sections)
-{
+{
S32 num_output_sections = 1<<dest_sections;
LLVector3 scale = mVO->mDrawable->getScale();
F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
@@ -209,6 +202,7 @@ void LLVolumeImplFlexible::setAttributesOfAllSections()
F32 t_inc = 1.f/F32(num_sections);
F32 t = t_inc;
+
for ( int i=1; i<= num_sections; i++)
{
mSection[i].mAxisRotation.setQuat(lerp(begin_rot,end_rot,t),0,0,1);
@@ -217,18 +211,23 @@ void LLVolumeImplFlexible::setAttributesOfAllSections()
scale.mV[VY] * lerp(bottom_scale.mV[1], top_scale.mV[1], t));
t += t_inc;
}
- mLastUpdate = 0;
}//-----------------------------------------------------------------------------------
void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail)
{
- doIdleUpdate(gAgent, *gWorldp, 0.0);
+ if (mVO && mVO->mDrawable.notNull())
+ {
+ LLVOVolume* volume = (LLVOVolume*) mVO;
+ volume->regenFaces();
+ }
+
+ /*doIdleUpdate(gAgent, *gWorldp, 0.0);
if (mVO && mVO->mDrawable.notNull())
{
gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
gPipeline.markMoved(mVO->mDrawable);
- }
+ }*/
}
//---------------------------------------------------------------------------------
@@ -238,6 +237,13 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons
//---------------------------------------------------------------------------------
BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
+ if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
+ {
+ return TRUE;
+ }
+
+ LLFastTimer ftm(LLFastTimer::FTM_FLEXIBLE_UPDATE);
+
if (mVO->mDrawable.isNull())
{
// Don't do anything until we have a drawable
@@ -248,46 +254,17 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6
mVO->mDrawable->mQuietCount = 0;
if (!mVO->mDrawable->isRoot())
{
- mVO->mDrawable->getParent()->mQuietCount = 0;
- }
-
- if (((LLVOVolume*)mVO)->mLODChanged ||
- mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1))
- {
- mLastUpdate = 0; // Force an immediate update
+ LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
+ parent->mDrawable->mQuietCount = 0;
}
- // Relegate invisible objects to the lowest priority bin
- S32 lod = 0;
- F32 app_angle = mVO->getAppAngle()*DEG_TO_RAD/gCamera->getView();
- if (mVO->mDrawable->isVisible())
- {
- sDebugVisible++;
- if (mVO->isSelected())
- {
- // Force selected objects to update *every* frame
- lod = FLEXIBLE_OBJECT_MAX_LOD-1;
- }
- else
- {
- if (app_angle > 0)
- {
- lod = 5 - (S32)(1.0f/sqrtf(app_angle));
- if (lod < 1)
- {
- lod = 1;
- }
- }
+
+ S32 new_res = mAttributes->getSimulateLOD();
- if (mVO->isAttachment())
- {
- lod += 3;
- }
- }
- }
+ //number of segments only cares about z axis
+ F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
- S32 new_res = mAttributes->getSimulateLOD();
// Rendering sections increases with visible angle on the screen
- mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle);
+ mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/gCamera->getView());
if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS)
{
mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS;
@@ -310,22 +287,32 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6
mInitialized = TRUE;
}
- sLODBins[lod].insert(this);
- sDebugInserted++;
- return TRUE;
-}
-
-// static
-void LLVolumeImplFlexible::resetUpdateBins()
-{
- U32 lod;
- for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
+ if (mVO->mDrawable->isVisible() &&
+ !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) &&
+ mVO->getPixelArea() > 256.f)
{
- sLODBins[lod].clear();
+ U32 id;
+ F32 pixel_area = mVO->getPixelArea();
+
+ if (mVO->isRootEdit())
+ {
+ id = mID;
+ }
+ else
+ {
+ LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
+ id = parent->getVolumeInterfaceID();
+ }
+
+ U32 update_period = (U32) (gCamera->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1;
+
+ if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
+ {
+ gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
+ }
}
- ++sCurrentUpdateFrame;
- sDebugInserted = 0;
- sDebugVisible = 0;
+
+ return TRUE;
}
inline S32 log2(S32 x)
@@ -339,80 +326,15 @@ inline S32 log2(S32 x)
return ret;
}
-// static
-void LLVolumeImplFlexible::doFlexibleUpdateBins()
-{
- U32 lod;
- U32 updated = 0;
- U32 regen = 0;
- U32 newflexies = 0;
- F32 time_alloc[FLEXIBLE_OBJECT_MAX_LOD];
- F32 total_time_alloc = 0;
-
- bool new_objects_only = false;
-
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
- {
- new_objects_only = true;
- }
-
- for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
- {
- int count = sLODBins[lod].size();
- if (count > 0)
- {
- time_alloc[lod] = (F32)((lod+1)*(log2(count)));
- }
- else
- {
- time_alloc[lod] = 0;
- }
- total_time_alloc += time_alloc[lod];
- }
- total_time_alloc = FLEXIBLE_OBJECT_TIMESLICE * (sUpdateFactor+0.01f) / total_time_alloc;
-
- {
- LLFastTimer t(LLFastTimer::FTM_FLEXIBLE_UPDATE);
- LLTimer timer;
- for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
- {
- LLVolumeImplFlexible::lodset_t::iterator itor = sLODBins[lod].begin();
- int bin_count = 0;
- if (!new_objects_only)
- {
- timer.reset();
- double end_time = time_alloc[lod] * total_time_alloc;
- for (; itor!=sLODBins[lod].end(); ++itor)
- {
-
- (*itor)->doFlexibleUpdate();
- ++updated;
- (*itor)->doFlexibleRebuild();
- ++bin_count;
- ++regen;
- if (timer.getElapsedTimeF64() > end_time)
- {
- break;
- }
- }
- }
- for (; itor != sLODBins[lod].end(); ++itor)
- {
- if ((*itor)->getLastUpdate() == 0)
- {
- // *Always* update newly-created objects, or objects which have changed LOD
- (*itor)->doFlexibleUpdate();
- (*itor)->doFlexibleRebuild();
- ++newflexies;
- }
- }
- }
- }
-}
-
void LLVolumeImplFlexible::doFlexibleUpdate()
{
LLPath *path = &mVO->getVolume()->getPath();
+ if (mSimulateRes == 0)
+ {
+ mVO->markForUpdate(TRUE);
+ doIdleUpdate(gAgent, *gWorldp, 0.0);
+ }
+
S32 num_sections = 1 << mSimulateRes;
F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32();
@@ -584,6 +506,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
// calculate velocity
//------------------------------------------------------------------------------------------
mSection[i].mVelocity = mSection[i].mPosition - lastPosition;
+ if (mSection[i].mVelocity.magVecSquared() > 1.f)
+ {
+ mSection[i].mVelocity.normVec();
+ }
}
// Calculate derivatives (not necessary until normals are automagically generated)
@@ -624,11 +550,38 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ];
remapSections(mSection, mSimulateRes, newSection, mRenderRes);
+ //generate transform from global to prim space
+ LLVector3 delta_scale = LLVector3(1,1,1);
+ LLVector3 delta_pos;
+ LLQuaternion delta_rot;
+
+ delta_rot = ~getFrameRotation();
+ delta_pos = -getFramePosition()*delta_rot;
+
+ // Vertex transform (4x4)
+ LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
+ LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
+ LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
+
+ LLMatrix4 rel_xform;
+ rel_xform.initRows(LLVector4(x_axis, 0.f),
+ LLVector4(y_axis, 0.f),
+ LLVector4(z_axis, 0.f),
+ LLVector4(delta_pos, 1.f));
+
for (i=0; i<=num_render_sections; ++i)
{
new_point = &path->mPath[i];
- new_point->mPos = newSection[i].mPosition;
- new_point->mRot = mSection[i].mAxisRotation * newSection[i].mRotation;
+ LLVector3 pos = newSection[i].mPosition * rel_xform;
+ LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot;
+
+ if (!mUpdated || (new_point->mPos-pos).magVecSquared() > 0.000001f)
+ {
+ new_point->mPos = newSection[i].mPosition * rel_xform;
+ mUpdated = FALSE;
+ }
+
+ new_point->mRot = rot;
new_point->mScale = newSection[i].mScale;
new_point->mTexT = ((F32)i)/(num_render_sections);
}
@@ -639,13 +592,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
void LLVolumeImplFlexible::doFlexibleRebuild()
{
mVO->getVolume()->regen();
-
- mVO->markForUpdate(TRUE);
-
mUpdated = TRUE;
+}
- mLastUpdate = sCurrentUpdateFrame;
-}//------------------------------------------------------------------
+//------------------------------------------------------------------
void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
{
@@ -654,8 +604,6 @@ void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
{
- BOOL compiled = FALSE;
-
LLVOVolume *volume = (LLVOVolume*)mVO;
if (volume->mDrawable.isNull()) // Not sure why this is happening, but it is...
@@ -663,60 +611,26 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
return TRUE; // No update to complete
}
- volume->calcAllTEsSame();
-
- if (volume->mVolumeChanged || volume->mFaceMappingChanged)
+ if (volume->mLODChanged)
{
- compiled = TRUE;
- volume->regenFaces();
- }
- else if (volume->mLODChanged)
- {
- LLPointer<LLVolume> old_volumep, new_volumep;
- F32 old_lod, new_lod;
-
- old_volumep = volume->getVolume();
- old_lod = old_volumep->getDetail();
-
- LLVolumeParams volume_params = volume->getVolume()->getParams();
+ LLVolumeParams volume_params = volume->getVolume()->getParams();
volume->setVolume(volume_params, 0);
- doFlexibleUpdate();
- volume->getVolume()->regen();
-
- new_volumep = volume->getVolume();
- new_lod = new_volumep->getDetail();
-
- if (new_lod != old_lod)
- {
- compiled = TRUE;
- if (new_volumep->getNumFaces() != old_volumep->getNumFaces())
- {
- volume->regenFaces();
- }
- }
- }
-
- if (mUpdated)
- {
- compiled = TRUE;
- mUpdated = FALSE;
}
- if(compiled)
+ volume->updateRelativeXform();
+ doFlexibleUpdate();
+ if (!mUpdated || volume->mFaceMappingChanged)
{
- volume->updateRelativeXform(isVolumeGlobal());
- volume->genTriangles(isVolumeGlobal());
- LLPipeline::sCompiles++;
+ doFlexibleRebuild();
+ volume->genBBoxes(isVolumeGlobal());
}
-
+
volume->mVolumeChanged = FALSE;
volume->mLODChanged = FALSE;
volume->mFaceMappingChanged = FALSE;
// clear UV flag
drawable->clearState(LLDrawable::UV);
-
- drawable->movePartition();
return TRUE;
}
@@ -792,42 +706,32 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation()
}//------------------------------------------------------------------
-void LLVolumeImplFlexible::updateRelativeXform(BOOL global_volume)
+void LLVolumeImplFlexible::updateRelativeXform()
{
- LLVOVolume* vo = (LLVOVolume*) mVO;
-
- LLVector3 delta_scale = LLVector3(1,1,1);
- LLVector3 delta_pos;
LLQuaternion delta_rot;
+ LLVector3 delta_pos, delta_scale;
+ LLVOVolume* vo = (LLVOVolume*) mVO;
+
+ //matrix from local space to parent relative/global space
+ delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation();
+ delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
+ delta_scale = LLVector3(1,1,1);
- if (!mVO->mDrawable->isRoot())
- { //global to parent relative
- LLViewerObject* parent = (LLViewerObject*) vo->getParent();
- delta_rot = ~parent->getRenderRotation();
- delta_pos = -parent->getRenderPosition()*delta_rot;
- }
- else
- { //global to local
- delta_rot = ~getFrameRotation();
- delta_pos = -getFramePosition()*delta_rot;
- }
-
// Vertex transform (4x4)
LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f),
- LLVector4(y_axis, 0.f),
- LLVector4(z_axis, 0.f),
- LLVector4(delta_pos, 1.f));
+ LLVector4(y_axis, 0.f),
+ LLVector4(z_axis, 0.f),
+ LLVector4(delta_pos, 1.f));
x_axis.normVec();
y_axis.normVec();
z_axis.normVec();
vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
-
}
const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const
diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h
index 0d782d96ac..5a782bc617 100644
--- a/indra/newview/llflexibleobject.h
+++ b/indra/newview/llflexibleobject.h
@@ -57,6 +57,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface
LLVolumeImplFlexible(LLViewerObject* volume, LLFlexibleObjectData* attributes);
// Implements LLVolumeInterface
+ U32 getID() const { return mID; }
LLVector3 getFramePosition() const;
LLQuaternion getFrameRotation() const;
LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; }
@@ -71,12 +72,10 @@ class LLVolumeImplFlexible : public LLVolumeInterface
bool isVolumeGlobal() const { return true; }
bool isActive() const { return true; }
const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
- void updateRelativeXform(BOOL global_volume = FALSE);
+ void updateRelativeXform();
void doFlexibleUpdate(); // Called to update the simulation
void doFlexibleRebuild(); // Called to rebuild the geometry
- static void resetUpdateBins();
- static void doFlexibleUpdateBins();
-
+
//void setAttributes( LLFlexibleObjectData );
void setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion r );
void setUsingCollisionSphere( bool u );
@@ -109,10 +108,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface
U32 mFrameNum;
LLVector3 mCollisionSpherePosition;
F32 mCollisionSphereRadius;
-
- U64 mLastUpdate;
-
- BOOL mJustShifted;
+ U32 mID;
//--------------------------------------
// private methods
@@ -121,29 +117,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface
void remapSections(LLFlexibleObjectSection *source, S32 source_sections,
LLFlexibleObjectSection *dest, S32 dest_sections);
-
- U64 getLastUpdate() const { return mLastUpdate; }
-
- // LOD Bins
- struct FlexCompare
- {
- bool operator()(LLVolumeImplFlexible* a, LLVolumeImplFlexible* b) const
- {
- U64 a_update = a->getLastUpdate();
- U64 b_update = b->getLastUpdate();
- if (a_update == b_update)
- {
- return a < b; // compare pointers
- }
- return a_update < b_update;
- }
- };
- typedef std::set<LLVolumeImplFlexible*, FlexCompare> lodset_t;
- static lodset_t sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ];
- static U64 sCurrentUpdateFrame;
- static U32 sDebugInserted;
- static U32 sDebugVisible;
-
+
public:
// Global setting for update rate
static F32 sUpdateFactor;
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index 21248c7406..e37850c997 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -997,7 +997,7 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture
mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
mDummyAvatar->startMotion(ANIM_AGENT_STAND, 5.f);
mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE);
- gPipeline.markVisible(mDummyAvatar->mDrawable);
+ gPipeline.markVisible(mDummyAvatar->mDrawable, *gCamera);
// stop extraneous animations
mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE );
@@ -1073,6 +1073,10 @@ BOOL LLPreviewAnimation::render()
avatarp->updateMotion();
}
+ LLVertexBuffer::stopRender();
+ avatarp->updateLOD();
+ LLVertexBuffer::startRender();
+
avatarp->mRoot.updateWorldMatrixChildren();
stop_glerror();
@@ -1082,13 +1086,7 @@ BOOL LLPreviewAnimation::render()
if (avatarp->mDrawable.notNull())
{
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
- gPipeline.unbindAGP();
- avatarPoolp->syncAGP();
- if (avatarPoolp->canUseAGP() && gPipeline.usingAGP())
- {
- gPipeline.bindAGP();
- }
- avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders)
+ avatarPoolp->renderAvatars(avatarp); // renders only one avatar
}
return TRUE;
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 1ae6decfdd..2e77bbcfbd 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -535,7 +535,7 @@ LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLDynamicTex
mDummyAvatar->slamPosition();
mDummyAvatar->updateJointLODs();
mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
- gPipeline.markVisible(mDummyAvatar->mDrawable);
+ gPipeline.markVisible(mDummyAvatar->mDrawable, *gCamera);
mTextureName = 0;
}
@@ -623,6 +623,10 @@ BOOL LLImagePreviewAvatar::render()
gCamera->setView(gCamera->getDefaultFOV() / mCameraZoom);
gCamera->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
+ LLVertexBuffer::stopRender();
+ avatarp->updateLOD();
+ LLVertexBuffer::startRender();
+
if (avatarp->mDrawable.notNull())
{
LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
@@ -631,13 +635,7 @@ BOOL LLImagePreviewAvatar::render()
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
- gPipeline.unbindAGP();
- avatarPoolp->syncAGP();
- if (avatarPoolp->canUseAGP() && gPipeline.usingAGP())
- {
- gPipeline.bindAGP();
- }
- avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders)
+ avatarPoolp->renderAvatars(avatarp); // renders only one avatar
}
return TRUE;
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 05047e1a4a..ac77b3c3f0 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -805,8 +805,10 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
//RN: freeze all avatars
LLCharacter* avatarp;
- for (avatarp = LLCharacter::sInstances.getFirstData(); avatarp; avatarp = LLCharacter::sInstances.getNextData())
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ avatarp = *iter;
sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
}
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 2cb6db5a16..7a6b7b1bf3 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -162,15 +162,17 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance");
select_dist_squared = select_dist_squared * select_dist_squared;
- x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]);
- y = llround((F32)y * LLUI::sGLScaleFactor.mV[VY]);
-
BOOL deselect = (mask == MASK_CONTROL);
S32 left = llmin(x, mDragStartX);
S32 right = llmax(x, mDragStartX);
S32 top = llmax(y, mDragStartY);
S32 bottom =llmin(y, mDragStartY);
+ left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]);
+ right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]);
+ top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]);
+ bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]);
+
F32 old_far_plane = gCamera->getFar();
F32 old_near_plane = gCamera->getNear();
@@ -238,7 +240,7 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
continue;
}
- S32 result = gCamera->sphereInFrustum(drawable->getWorldPosition(), drawable->getRadius());
+ S32 result = gCamera->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius());
switch (result)
{
case 0:
@@ -261,11 +263,16 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
{
std::vector<LLDrawable*> potentials;
- if (gPipeline.mObjectPartition)
+
+ for (U32 i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++)
{
- gPipeline.mObjectPartition->cull(*gCamera, &potentials, TRUE);
+ LLSpatialPartition* part = gPipeline.getSpatialPartition(i);
+ if (part)
+ {
+ part->cull(*gCamera, &potentials, TRUE);
+ }
}
-
+
for (std::vector<LLDrawable*>::iterator iter = potentials.begin();
iter != potentials.end(); iter++)
{
@@ -285,7 +292,7 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
continue;
}
- S32 result = gCamera->sphereInFrustum(drawable->getWorldPosition(), drawable->getRadius());
+ S32 result = gCamera->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius());
if (result)
{
switch (result)
@@ -939,119 +946,6 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV
glEnd();
}
-
-const S32 CLIENT_RECT_VPAD = 4;
-void LLPreviewTexture::draw()
-{
- if( getVisible() )
- {
- updateAspectRatio();
-
- LLPreview::draw();
-
- if (!mMinimized)
- {
- LLGLSUIDefault gls_ui;
- LLGLSNoTexture gls_notex;
-
- const LLRect& border = mClientRect;
- LLRect interior = mClientRect;
- interior.stretch( -PREVIEW_BORDER_WIDTH );
-
- // ...border
- gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
- gl_rect_2d_checkerboard( interior );
-
- if ( mImage.notNull() )
- {
- LLGLSTexture gls_no_texture;
- // Draw the texture
- glColor3f( 1.f, 1.f, 1.f );
- gl_draw_scaled_image(interior.mLeft,
- interior.mBottom,
- interior.getWidth(),
- interior.getHeight(),
- mImage);
-
- // Pump the texture priority
- F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
- mImage->addTextureStats( pixel_area );
-
- // Don't bother decoding more than we can display, unless
- // we're loading the full image.
- if (!mLoadingFullImage)
- {
- S32 int_width = interior.getWidth();
- S32 int_height = interior.getHeight();
- mImage->setKnownDrawSize(int_width, int_height);
- }
- else
- {
- // Don't use this feature
- mImage->setKnownDrawSize(0, 0);
- }
-
- if( mLoadingFullImage )
- {
- LLFontGL::sSansSerif->renderUTF8("Receiving:", 0,
- interior.mLeft + 4,
- interior.mBottom + 4,
- LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::DROP_SHADOW);
-
- F32 data_progress = 0.0f;
- F32 decode_progress = mImage->getDecodeProgress(&data_progress);
-
- // Draw the progress bar.
- const S32 BAR_HEIGHT = 12;
- const S32 BAR_LEFT_PAD = 80;
- S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
- S32 bar_width = mRect.getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
- S32 top = interior.mBottom + 4 + BAR_HEIGHT;
- S32 right = left + bar_width;
- S32 bottom = top - BAR_HEIGHT;
-
- LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
- LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
- LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
-
- gl_rect_2d(left, top, right, bottom, background_color);
-
- if (data_progress > 0.0f)
- {
- // Decoded bytes
- right = left + llfloor(decode_progress * (F32)bar_width);
-
- if (left < right)
- {
- gl_rect_2d(left, top, right, bottom, decoded_color);
- }
-
- // Downloaded bytes
- left = right;
- right = left + llfloor((data_progress - decode_progress) * (F32)bar_width);
-
- if (left < right)
- {
- gl_rect_2d(left, top, right, bottom, downloaded_color);
- }
- }
- }
- else
- if( !mSavedFileTimer.hasExpired() )
- {
- LLFontGL::sSansSerif->renderUTF8("File Saved", 0,
- interior.mLeft + 4,
- interior.mBottom + 4,
- LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::DROP_SHADOW);
- }
- }
- }
- }
-}
-
-
void draw_line_cube(F32 width, const LLVector3& center)
{
width = 0.5f * width;
diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp
index d76250d10a..05da40f214 100644
--- a/indra/newview/llhudeffecttrail.cpp
+++ b/indra/newview/llhudeffecttrail.cpp
@@ -156,7 +156,7 @@ void LLHUDEffectSpiral::triggerLocal()
mKillTime = mTimer.getElapsedTimeF32() + mDuration;
BOOL show_beam = gSavedSettings.getBOOL("ShowSelectionBeam");
-
+
LLColor4 color;
color.setVec(mColor);
@@ -250,20 +250,12 @@ void LLHUDEffectSpiral::setTargetObject(LLViewerObject *objp)
void LLHUDEffectSpiral::render()
{
- if (!mSourceObject.isNull() && mSourceObject->isDead())
- {
- markDead();
- return;
- }
-
- if(!mTargetObject.isNull() && mTargetObject->isDead())
- {
- markDead();
- return;
- }
-
F32 time = mTimer.getElapsedTimeF32();
- if (mKillTime < time)
+
+ if (!mSourceObject.isNull() && mSourceObject->isDead() ||
+ !mTargetObject.isNull() && mTargetObject->isDead() ||
+ mKillTime < time ||
+ !gSavedSettings.getBOOL("ShowSelectionBeam"))
{
markDead();
return;
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index f2ab2dab11..02a3576dff 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -15,6 +15,7 @@
#include "llviewerobject.h"
#include "lldrawable.h"
#include "llviewercamera.h"
+#include "llviewerimage.h"
#include "llviewerwindow.h"
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index f4280aae9c..f090cea5f2 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3187,7 +3187,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
rez_action->mItemID = item->getUUID();
rez_action->mAttachPt = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment);
- if (attachment && attachment->getObject(0))
+ if (attachment && attachment->getObject())
{
gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
}
diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h
index 8b0a5665d4..8e0668ad8f 100644
--- a/indra/newview/lljoystickbutton.h
+++ b/indra/newview/lljoystickbutton.h
@@ -11,6 +11,7 @@
#include "llbutton.h"
#include "llcoord.h"
+#include "llviewerimage.h"
typedef enum e_joystick_quadrant
{
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index e9a6b1d1ba..5a52fc5b0a 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -445,11 +445,7 @@ BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask)
mManipPart = LL_NO_PART;
// Might have missed last update due to timing.
- if (mSendUpdateOnMouseUp)
- {
- gSelectMgr->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION );
- mSendUpdateOnMouseUp = FALSE;
- }
+ gSelectMgr->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION );
gSelectMgr->enableSilhouette(TRUE);
//gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
@@ -505,12 +501,6 @@ extern U32 gFrameCount;
// Freeform rotation
void LLManipRotate::drag( S32 x, S32 y )
{
- static LLTimer update_timer;
- F32 elapsed_time = update_timer.getElapsedTimeF32();
- const F32 UPDATE_DELAY = 0.1f; // min time between transmitted updates
- BOOL send_rotation_update = FALSE;
- BOOL send_position_update = FALSE;
-
if( !updateVisiblity() )
{
return;
@@ -530,7 +520,6 @@ void LLManipRotate::drag( S32 x, S32 y )
LLViewerObject* object;
LLSelectNode* selectNode;
- BOOL using_linked_selection = gSavedSettings.getBOOL("SelectLinkedSet");
for( selectNode = mObjectSelection->getFirstNode(); selectNode != NULL; selectNode = mObjectSelection->getNextNode() )
{
@@ -577,12 +566,6 @@ void LLManipRotate::drag( S32 x, S32 y )
rebuild(object);
}
- // don't send updates all the time for sub-objects
- if (using_linked_selection && object->getRenderRotation() != new_rot)
- {
- send_rotation_update = TRUE;
- }
-
// for individually selected roots, we need to counterrotate all the children
if (object->isRootEdit() && selectNode->mIndividualSelection)
{
@@ -674,11 +657,6 @@ void LLManipRotate::drag( S32 x, S32 y )
}
}
- if (using_linked_selection && object->getPositionAgent() != new_position)
- {
- send_position_update = TRUE;
- }
-
// for individually selected roots, we need to counter-translate all unselected children
if (object->isRootEdit() && selectNode->mIndividualSelection)
{
@@ -709,27 +687,19 @@ void LLManipRotate::drag( S32 x, S32 y )
}
}
- if ((send_position_update || send_rotation_update) && (elapsed_time > UPDATE_DELAY))
+ // store changes to override updates
+ for (LLSelectNode* selectNode = gSelectMgr->getSelection()->getFirstNode();
+ selectNode != NULL;
+ selectNode = gSelectMgr->getSelection()->getNextNode())
{
- U32 flag = UPD_NONE;
- if (send_rotation_update)
- {
- flag |= UPD_ROTATION;
- }
- if (send_position_update)
+ LLViewerObject*cur = selectNode->getObject();
+ if( cur->permModify() && cur->permMove() && !cur->isAvatar())
{
- flag |= UPD_POSITION;
+ selectNode->mLastRotation = cur->getRotation();
+ selectNode->mLastPositionLocal = cur->getPosition();
}
+ }
- gSelectMgr->sendMultipleUpdate( flag );
- update_timer.reset();
- mSendUpdateOnMouseUp = FALSE;
- }
- else
- {
- mSendUpdateOnMouseUp = TRUE;
- }
-
gSelectMgr->updateSelectionCenter();
// RN: just clear focus so camera doesn't follow spurious object updates
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index cec8ff0b13..56a4352e22 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -360,15 +360,27 @@ BOOL LLManipScale::handleMouseUp(S32 x, S32 y, MASK mask)
// first, perform normal processing in case this was a quick-click
handleHover(x, y, mask);
+ if( (LL_FACE_MIN <= (S32)mManipPart)
+ && ((S32)mManipPart <= LL_FACE_MAX) )
+ {
+ sendUpdates(TRUE,TRUE,FALSE);
+ }
+ else
+ if( (LL_CORNER_MIN <= (S32)mManipPart)
+ && ((S32)mManipPart <= LL_CORNER_MAX) )
+ {
+ sendUpdates(TRUE,TRUE,TRUE);
+ }
+
+ //send texture update
+ gSelectMgr->adjustTexturesByScale(TRUE, getStretchTextures());
+
gSelectMgr->enableSilhouette(TRUE);
mManipPart = LL_NO_PART;
// Might have missed last update due to UPDATE_DELAY timing
- if (mSendUpdateOnMouseUp)
- {
- gSelectMgr->sendMultipleUpdate( mLastUpdateFlags );
- }
-
+ gSelectMgr->sendMultipleUpdate( mLastUpdateFlags );
+
//gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
return LLManip::handleMouseUp(x, y, mask);
@@ -398,7 +410,7 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask)
}
// Patch up textures, if possible.
- gSelectMgr->adjustTexturesByScale(TRUE, getStretchTextures());
+ gSelectMgr->adjustTexturesByScale(FALSE, getStretchTextures());
gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLSCALE);
return TRUE;
@@ -789,8 +801,21 @@ void LLManipScale::drag( S32 x, S32 y )
dragCorner( x, y );
}
- //gAgent.setObjectTracking(FALSE);
- gAgent.clearFocusObject();
+ // store changes to override updates
+ for (LLSelectNode* selectNode = gSelectMgr->getSelection()->getFirstNode();
+ selectNode != NULL;
+ selectNode = gSelectMgr->getSelection()->getNextNode())
+ {
+ LLViewerObject*cur = selectNode->getObject();
+ if( cur->permModify() && cur->permMove() && !cur->isAvatar())
+ {
+ selectNode->mLastScale = cur->getScale();
+ selectNode->mLastPositionLocal = cur->getPosition();
+ }
+ }
+
+ gSelectMgr->updateSelectionCenter();
+ gAgent.clearFocusObject();
}
// Scale around the
@@ -801,10 +826,7 @@ void LLManipScale::dragCorner( S32 x, S32 y )
// Suppress scale if mouse hasn't moved.
if (x == mLastMouseX && y == mLastMouseY)
{
- if (mSendUpdateOnMouseUp)
- {
- sendUpdates(TRUE,TRUE,TRUE);
- }
+ // sendUpdates(TRUE,TRUE,TRUE);
return;
}
@@ -1003,11 +1025,8 @@ void LLManipScale::dragCorner( S32 x, S32 y )
if (!selectNode->mIndividualSelection)
{
cur->setPosition(selectNode->mSavedPositionLocal * scale_factor);
- continue;
}
- LLVector3d new_pos_global = drag_global + (selectNode->mSavedPositionGlobal - drag_global) * scale_factor;
- cur->setPositionAbsoluteGlobal( new_pos_global );
rebuild(cur);
}
}
@@ -1015,8 +1034,6 @@ void LLManipScale::dragCorner( S32 x, S32 y )
mDragPointGlobal = drag_point_global;
-
- sendUpdates( TRUE, TRUE, TRUE );
}
@@ -1025,10 +1042,7 @@ void LLManipScale::dragFace( S32 x, S32 y )
// Suppress scale if mouse hasn't moved.
if (x == mLastMouseX && y == mLastMouseY)
{
- if (mSendUpdateOnMouseUp)
- {
- sendUpdates(TRUE,TRUE,FALSE);
- }
+ // sendUpdates(TRUE,TRUE,FALSE);
return;
}
@@ -1162,8 +1176,6 @@ void LLManipScale::dragFace( S32 x, S32 y )
send_scale_update = TRUE;
mDragPointGlobal = drag_point_global;
-
- sendUpdates( send_position_update, send_scale_update );
}
void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_update, BOOL corner )
@@ -1198,8 +1210,6 @@ void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_updat
{
mSendUpdateOnMouseUp = TRUE;
}
-
- gSelectMgr->updateSelectionCenter();
dialog_refresh_all();
}
}
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index f308eb9f5c..93ae74db22 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -40,6 +40,7 @@
#include "llworld.h"
#include "viewer.h"
#include "llui.h"
+#include "pipeline.h"
const S32 NUM_AXES = 3;
const S32 MOUSE_DRAG_SLOP = 2; // pixels
@@ -404,6 +405,8 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
}
}
+ LLViewerObject *object;
+
// Suppress processing if mouse hasn't actually moved.
// This may cause problems if the camera moves outside of the
// rotation above.
@@ -450,7 +453,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
LLVector3 axis_f;
LLVector3d axis_d;
- LLViewerObject *object;
// pick the first object to constrain to grid w/ common origin
// this is so we don't screw up groups
@@ -631,7 +633,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
selectNode = mObjectSelection->getNextNode() )
{
object = selectNode->getObject();
-
+
// Only apply motion to root objects and objects selected
// as "individual".
if (!object->isRootEdit() && !selectNode->mIndividualSelection)
@@ -762,27 +764,12 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
send_update = TRUE;
}
}
+ selectNode->mLastPositionLocal = object->getPosition();
}
}
- // Handle throttling to 10 updates per second.
- F32 elapsed_time = mUpdateTimer.getElapsedTimeF32();
- const F32 UPDATE_DELAY = 0.1f; // min time between transmitted updates
- if (send_update && (elapsed_time > UPDATE_DELAY))
- {
- gSelectMgr->sendMultipleUpdate(UPD_POSITION);
- mUpdateTimer.reset();
- mSendUpdateOnMouseUp = FALSE;
- }
- else
- {
- // ...suppressed update
- mSendUpdateOnMouseUp = TRUE;
- }
-
gSelectMgr->updateSelectionCenter();
gAgent.clearFocusObject();
- //gAgent.setObjectTracking(FALSE);
dialog_refresh_all(); // ??? is this necessary?
lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (active)" << llendl;
@@ -1039,17 +1026,8 @@ BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
gSelectMgr->enableSilhouette(TRUE);
// Might have missed last update due to UPDATE_DELAY timing.
- if (mSendUpdateOnMouseUp)
- {
- gSelectMgr->sendMultipleUpdate( UPD_POSITION );
- mSendUpdateOnMouseUp = FALSE;
- }
-
-// if (mCopyMadeThisDrag)
-// {
-// gSelectMgr->clearGridObjects();
-// }
-
+ gSelectMgr->sendMultipleUpdate( UPD_POSITION );
+
mInSnapRegime = FALSE;
gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
//gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
@@ -1122,6 +1100,30 @@ void LLManipTranslate::renderSnapGuides()
//pick appropriate projection plane for snap rulers according to relative camera position
if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW)
{
+ LLVector3 normal;
+ LLColor4 inner_color;
+ LLManip::EManipPart temp_manip = mManipPart;
+ switch (mManipPart)
+ {
+ case LL_X_ARROW:
+ normal.setVec(1,0,0);
+ inner_color.setVec(0,1,1,line_alpha);
+ mManipPart = LL_YZ_PLANE;
+ break;
+ case LL_Y_ARROW:
+ normal.setVec(0,1,0);
+ inner_color.setVec(1,0,1,line_alpha);
+ mManipPart = LL_XZ_PLANE;
+ break;
+ case LL_Z_ARROW:
+ normal.setVec(0,0,1);
+ inner_color.setVec(1,1,0,line_alpha);
+ mManipPart = LL_XY_PLANE;
+ break;
+ }
+
+ highlightIntersection(normal, selection_center, grid_rotation, inner_color);
+ mManipPart = temp_manip;
getManipAxis(first_object, mManipPart, translate_axis);
LLVector3 at_axis_abs;
@@ -1438,18 +1440,13 @@ void LLManipTranslate::renderSnapGuides()
// render gridlines for planar snapping
F32 u = 0, v = 0;
- glPushMatrix();
-
- F32 x,y,z,angle_radians;
- grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
- glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
- glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
-
+ LLColor4 inner_color;
+ LLVector3 normal;
LLVector3 grid_center = selection_center - grid_origin;
- grid_center *= ~grid_rotation;
-
F32 usc = 1;
F32 vsc = 1;
+
+ grid_center *= ~grid_rotation;
switch (mManipPart)
{
@@ -1458,23 +1455,38 @@ void LLManipTranslate::renderSnapGuides()
v = grid_center.mV[VZ];
usc = grid_scale.mV[VY];
vsc = grid_scale.mV[VZ];
+ inner_color.setVec(0,1,1,line_alpha);
+ normal.setVec(1,0,0);
break;
case LL_XZ_PLANE:
u = grid_center.mV[VX];
v = grid_center.mV[VZ];
usc = grid_scale.mV[VX];
vsc = grid_scale.mV[VZ];
+ inner_color.setVec(1,0,1,line_alpha);
+ normal.setVec(0,1,0);
break;
case LL_XY_PLANE:
u = grid_center.mV[VX];
v = grid_center.mV[VY];
usc = grid_scale.mV[VX];
vsc = grid_scale.mV[VY];
+ inner_color.setVec(1,1,0,line_alpha);
+ normal.setVec(0,0,1);
break;
default:
break;
}
+ highlightIntersection(normal, selection_center, grid_rotation, inner_color);
+
+ glPushMatrix();
+
+ F32 x,y,z,angle_radians;
+ grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
+ glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
+ glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
+
F32 sz = mGridSizeMeters;
F32 tiles = sz;
glMatrixMode(GL_TEXTURE);
@@ -1591,6 +1603,104 @@ void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F
}
+void LLManipTranslate::highlightIntersection(LLVector3 normal,
+ LLVector3 selection_center,
+ LLQuaternion grid_rotation,
+ LLColor4 inner_color)
+{
+ if (!gSavedSettings.getBOOL("GridCrossSections"))
+ {
+ return;
+ }
+
+ U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT };
+
+ GLuint stencil_mask = 0xFFFFFFFF;
+ //stencil in volumes
+ {
+ glStencilMask(stencil_mask);
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ LLGLEnable cull_face(GL_CULL_FACE);
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS);
+ glStencilFunc(GL_ALWAYS, 0, stencil_mask);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ LLGLDisable tex(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+
+ //setup clip plane
+ normal = normal * grid_rotation;
+ if (normal * (gCamera->getOrigin()-selection_center) < 0)
+ {
+ normal = -normal;
+ }
+ F32 d = -(selection_center * normal);
+ F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d };
+ LLGLEnable clip(GL_CLIP_PLANE0);
+ glClipPlane(GL_CLIP_PLANE0, plane);
+
+ BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
+
+ if (particles)
+ {
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+ if (clouds)
+ {
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
+ }
+
+ //stencil in volumes
+ glStencilOp(GL_INCR, GL_INCR, GL_INCR);
+ glCullFace(GL_FRONT);
+ for (U32 i = 0; i < 3; i++)
+ {
+ gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+
+ glStencilOp(GL_DECR, GL_DECR, GL_DECR);
+ glCullFace(GL_BACK);
+ for (U32 i = 0; i < 3; i++)
+ {
+ gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+
+ if (particles)
+ {
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+ if (clouds)
+ {
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
+ }
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ glPushMatrix();
+
+ F32 x,y,z,angle_radians;
+ grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
+ glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
+ glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
+
+ F32 sz = mGridSizeMeters;
+ F32 tiles = sz;
+
+ //draw volume/plane intersections
+ {
+ LLGLDisable tex(GL_TEXTURE_2D);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_EQUAL, 0, stencil_mask);
+ renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f);
+ }
+
+ glPopMatrix();
+}
void LLManipTranslate::renderText()
{
diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h
index 5a93c0a24f..6a317cabcd 100644
--- a/indra/newview/llmaniptranslate.h
+++ b/indra/newview/llmaniptranslate.h
@@ -58,6 +58,10 @@ protected:
void renderSnapGuides();
void renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a);
void renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha);
+ void highlightIntersection(LLVector3 normal,
+ LLVector3 selection_center,
+ LLQuaternion grid_rotation,
+ LLColor4 inner_color);
F32 getMinGridScale();
private:
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 5edb373cbb..7fd2572e08 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -16,6 +16,7 @@
#include "llgl.h"
#include "llmath.h"
#include "llfontgl.h"
+#include "llmemtype.h"
#include "viewer.h"
#include "llui.h"
@@ -95,6 +96,7 @@ static struct mtv_display_info mtv_display_table[] =
{ LLMemType::MTYPE_PIPELINE, "Pipeline", &LLColor4::green3 },
{ LLMemType::MTYPE_PARTICLES, "Particles", &LLColor4::green4 },
{ LLMemType::MTYPE_SPACE_PARTITION, "Space Partition", &LLColor4::blue2 },
+ { LLMemType::MTYPE_VERTEX_DATA, "Vertex Buffer", &LLColor4::blue3 },
{ LLMemType::MTYPE_AVATAR, "Avatar", &LLColor4::purple1 },
{ LLMemType::MTYPE_REGIONS, "Regions", &LLColor4::blue1 },
{ LLMemType::MTYPE_TEMP1, "Temp1", &LLColor4::red1 },
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index ab2a298a06..c13d76886f 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -487,8 +487,11 @@ void LLPanelPick::onCommitAny(LLUICtrl* ctrl, void* data)
}
else
{*/
- LLTabContainerVertical* tab = (LLTabContainerVertical*)self->getParent();
+ LLTabContainerVertical* tab = (LLTabContainerVertical*)self->getParent();
+ if (tab)
+ {
if(tab) tab->setCurrentTabName(self->mNameEditor->getText());
+ }
//}
}
}
diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index 76769c6c7c..e818170ed2 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -1056,10 +1056,10 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
mJointScales[joint] = bone_info->mScaleDeformation;
// apply to children that need to inherit it
- for ( LLViewerJoint *child_joint = (LLViewerJoint *)joint->mChildren.getFirstData();
- child_joint != NULL;
- child_joint = (LLViewerJoint *)joint->mChildren.getNextData() )
+ for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+ iter != joint->mChildren.end(); ++iter)
{
+ LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
if (child_joint->inheritScale())
{
LLVector3 childDeformation = LLVector3(child_joint->getScale());
diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h
index cefda92288..2874f11798 100644
--- a/indra/newview/llpolymesh.h
+++ b/indra/newview/llpolymesh.h
@@ -305,6 +305,7 @@ public:
U32 mFaceVertexOffset;
U32 mFaceVertexCount;
+ U32 mFaceIndexOffset;
U32 mFaceIndexCount;
U32 mCurVertexCount;
private:
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index f6b9f0e018..479f1b1812 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1453,9 +1453,9 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
if( LLLiveLSLEditor::sInstances.checkData(*xored_id) )
{
+ instance = LLLiveLSLEditor::sInstances[*xored_id];
if( LL_ERR_NOERR == status )
{
- instance = LLLiveLSLEditor::sInstances[*xored_id];
instance->loadScriptText(vfs, asset_id, type);
instance->mAssetStatus = PREVIEW_ASSET_LOADED;
}
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 95973a102e..4b7be3701b 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -10,19 +10,20 @@
#include "llpreviewtexture.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
-#include "llresmgr.h"
#include "llagent.h"
#include "llbutton.h"
-#include "llui.h"
+#include "llfilepicker.h"
+#include "llimagetga.h"
#include "llinventoryview.h"
#include "llinventory.h"
-#include "llviewerwindow.h"
+#include "llresmgr.h"
#include "lltextbox.h"
-#include "llimagetga.h"
-#include "llfilepicker.h"
+#include "lltextureview.h"
+#include "llui.h"
+#include "llviewerimage.h"
+#include "llviewerimagelist.h"
#include "llvieweruictrlfactory.h"
+#include "llviewerwindow.h"
#include "lllineeditor.h"
const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
@@ -167,6 +168,105 @@ void LLPreviewTexture::init()
}
}
+void LLPreviewTexture::draw()
+{
+ if( getVisible() )
+ {
+ updateAspectRatio();
+
+ LLPreview::draw();
+
+ if (!mMinimized)
+ {
+ LLGLSUIDefault gls_ui;
+ LLGLSNoTexture gls_notex;
+
+ const LLRect& border = mClientRect;
+ LLRect interior = mClientRect;
+ interior.stretch( -PREVIEW_BORDER_WIDTH );
+
+ // ...border
+ gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
+ gl_rect_2d_checkerboard( interior );
+
+ if ( mImage.notNull() )
+ {
+ LLGLSTexture gls_no_texture;
+ // Draw the texture
+ glColor3f( 1.f, 1.f, 1.f );
+ gl_draw_scaled_image(interior.mLeft,
+ interior.mBottom,
+ interior.getWidth(),
+ interior.getHeight(),
+ mImage);
+
+ // Pump the texture priority
+ F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
+ mImage->addTextureStats( pixel_area );
+
+ // Don't bother decoding more than we can display, unless
+ // we're loading the full image.
+ if (!mLoadingFullImage)
+ {
+ S32 int_width = interior.getWidth();
+ S32 int_height = interior.getHeight();
+ mImage->setKnownDrawSize(int_width, int_height);
+ }
+ else
+ {
+ // Don't use this feature
+ mImage->setKnownDrawSize(0, 0);
+ }
+
+ if( mLoadingFullImage )
+ {
+ LLFontGL::sSansSerif->renderUTF8("Receiving:", 0,
+ interior.mLeft + 4,
+ interior.mBottom + 4,
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::DROP_SHADOW);
+
+ F32 data_progress = mImage->mDownloadProgress;
+
+ // Draw the progress bar.
+ const S32 BAR_HEIGHT = 12;
+ const S32 BAR_LEFT_PAD = 80;
+ S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
+ S32 bar_width = mRect.getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
+ S32 top = interior.mBottom + 4 + BAR_HEIGHT;
+ S32 right = left + bar_width;
+ S32 bottom = top - BAR_HEIGHT;
+
+ LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
+ LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
+ LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
+
+ gl_rect_2d(left, top, right, bottom, background_color);
+
+ if (data_progress > 0.0f)
+ {
+ // Downloaded bytes
+ right = left + llfloor(data_progress * (F32)bar_width);
+ if (right > left)
+ {
+ gl_rect_2d(left, top, right, bottom, downloaded_color);
+ }
+ }
+ }
+ else
+ if( !mSavedFileTimer.hasExpired() )
+ {
+ LLFontGL::sSansSerif->renderUTF8("File Saved", 0,
+ interior.mLeft + 4,
+ interior.mBottom + 4,
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::DROP_SHADOW);
+ }
+ }
+ }
+ }
+}
+
// virtual
BOOL LLPreviewTexture::canSaveAs()
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 2faa9ba351..1172bd8cf0 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -20,8 +20,9 @@
#include "llglheaders.h"
#include "llagent.h"
-#include "llfocusmgr.h"
#include "llbutton.h"
+#include "llfocusmgr.h"
+#include "llstartup.h"
#include "llviewercontrol.h"
#include "llviewerimagelist.h"
#include "llviewerwindow.h"
@@ -29,9 +30,8 @@
LLProgressView* LLProgressView::sInstance = NULL;
-LLPointer<LLImageGL> gStartImageGL = NULL;
-S32 gStartImageWidth = 1;
-S32 gStartImageHeight = 1;
+S32 gStartImageWidth = 1;
+S32 gStartImageHeight = 1;
const F32 FADE_IN_TIME = 1.f;
const LLString ANIMATION_FILENAME = "Login Sequence ";
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index c4e166d68d..27cf29cee0 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -196,6 +196,34 @@ void LLSelectMgr::updateEffects()
}
}
+void LLSelectMgr::overrideObjectUpdates()
+{
+ //override any position updates from simulator on objects being edited
+ LLSelectNode* selectNode;
+ for (selectNode = gSelectMgr->getSelection()->getFirstNode();
+ selectNode != NULL;
+ selectNode = gSelectMgr->getSelection()->getNextNode())
+ {
+ LLViewerObject* object = selectNode->getObject();
+
+ if (object->permMove())
+ {
+ if (!selectNode->mLastPositionLocal.isExactlyZero())
+ {
+ object->setPosition(selectNode->mLastPositionLocal);
+ }
+ if (selectNode->mLastRotation != LLQuaternion())
+ {
+ object->setRotation(selectNode->mLastRotation);
+ }
+ if (!selectNode->mLastScale.isExactlyZero())
+ {
+ object->setScale(selectNode->mLastScale);
+ }
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
// Select just the object, not any other group members.
//-----------------------------------------------------------------------------
@@ -3520,7 +3548,8 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
BOOL build_mode = gToolMgr->inEdit();
// Special case: Attach to default location for this object.
- if (0 == attachment_point)
+ if (0 == attachment_point ||
+ gAgent.getAvatarObject()->mAttachmentPoints.getIfThere(attachment_point))
{
sendListToRegions(
"ObjectAttach",
@@ -3533,48 +3562,6 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
deselectAll();
}
}
- else
- {
- LLViewerJointAttachment* attachment = gAgent.getAvatarObject()->mAttachmentPoints.getIfThere(attachment_point);
- if (attachment)
- {
- LLQuaternion object_world_rot = attach_object->getRenderRotation();
- LLQuaternion attachment_pt__world_rot = attachment->getWorldRotation();
- LLQuaternion local_rot = object_world_rot * ~attachment_pt__world_rot;
-
- F32 x,y,z;
- local_rot.getEulerAngles(&x, &y, &z);
- // snap to nearest 90 degree rotation
- // make sure all euler angles are positive
- if (x < F_PI_BY_TWO) x += F_TWO_PI;
- if (y < F_PI_BY_TWO) y += F_TWO_PI;
- if (z < F_PI_BY_TWO) z += F_TWO_PI;
-
- // add 45 degrees so that rounding down becomes rounding off
- x += F_PI_BY_TWO / 2.f;
- y += F_PI_BY_TWO / 2.f;
- z += F_PI_BY_TWO / 2.f;
- // round down to nearest multiple of 90 degrees
- x -= fmodf(x, F_PI_BY_TWO);
- y -= fmodf(y, F_PI_BY_TWO);
- z -= fmodf(z, F_PI_BY_TWO);
-
- // pass the requested rotation on to the simulator
- local_rot.setQuat(x, y, z);
- attach_object->setRotation(local_rot);
-
- sendListToRegions(
- "ObjectAttach",
- packAgentIDAndSessionAndAttachment,
- packObjectIDAndRotation,
- &attachment_point,
- SEND_ONLY_ROOTS );
- if (!build_mode)
- {
- deselectAll();
- }
- }
- }
}
void LLSelectMgr::sendDetach()
@@ -3764,7 +3751,10 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type)
if (object->isRootEdit())
{
LLXform* parent_xform = object->mDrawable->getXform()->getParent();
- selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition());
+ if (parent_xform)
+ {
+ selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition());
+ }
}
else
{
@@ -4065,6 +4055,17 @@ void LLSelectMgr::sendListToRegions(const LLString& message_name,
S32 packets_sent = 0;
S32 objects_in_this_packet = 0;
+
+ //clear update override data (allow next update through)
+ for (node = mSelectedObjects->getFirstNode();
+ node;
+ node = mSelectedObjects->getNextNode())
+ {
+ node->mLastPositionLocal.setVec(0,0,0);
+ node->mLastRotation = LLQuaternion();
+ node->mLastScale.setVec(0,0,0);
+ }
+
std::queue<LLSelectNode*> nodes_to_send;
switch(send_type)
@@ -4583,7 +4584,7 @@ void LLSelectMgr::updateSilhouettes()
|| objectp->isChanged(LLXform::SILHOUETTE)
|| (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
{
- if (num_sils_genned++ < MAX_SILS_PER_FRAME && objectp->mDrawable->isVisible())
+ if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
{
generateSilhouette(node, gCamera->getOrigin());
changed_objects.put(objectp);
@@ -4816,7 +4817,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
}
if (mSelectedObjects->getNumNodes())
{
- glPushAttrib(GL_FOG_BIT);
LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
for (S32 pass = 0; pass < 2; pass++)
{
@@ -4848,7 +4848,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
}
}
}
- glPopAttrib();
}
if (mHighlightedObjects->getNumNodes())
@@ -5266,12 +5265,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
}
BOOL is_hud_object = objectp->isHUDAttachment();
-
- if (!drawable->isVisible() && !is_hud_object)
- {
- return;
- }
-
+
if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size())
{
return;
@@ -5302,7 +5296,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
else
{
LLVector3 view_vector = gCamera->getOrigin() - objectp->getRenderPosition();
- silhouette_thickness = drawable->mDistanceWRTCamera * LLSelectMgr::sHighlightThickness * (gCamera->getView() / gCamera->getDefaultFOV());
+ silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (gCamera->getView() / gCamera->getDefaultFOV());
}
F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds();
@@ -5328,7 +5322,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
S32 i = 0;
for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++)
{
-// S32 first_i = i;
for(; i < mSilhouetteSegments[seg_num]; i++)
{
u_coord += u_divisor * LLSelectMgr::sHighlightUScale;
@@ -5337,11 +5330,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
glTexCoord2f( u_coord, v_coord );
glVertex3fv( mSilhouetteVertices[i].mV );
}
-
- /*u_coord += u_divisor * LLSelectMgr::sHighlightUScale;
- glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
- glTexCoord2f( u_coord, v_coord );
- glVertex3fv( mSilhouetteVertices[first_i].mV );*/
}
}
glEnd();
@@ -5349,7 +5337,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- //glAlphaFunc(GL_GREATER, LLSelectMgr::sHighlightAlphaTest);
glBegin(GL_TRIANGLES);
{
S32 i = 0;
@@ -5468,6 +5455,10 @@ void LLSelectMgr::updateSelectionCenter()
const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection
// center (tractor beam)
+ //override any object updates received
+ //for selected objects
+ gSelectMgr->overrideObjectUpdates();
+
LLViewerObject* object = mSelectedObjects->getFirstObject();
if (!object)
{
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 2b1568fb45..c0ddad41eb 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -210,6 +210,7 @@ public:
virtual BOOL canDuplicate();
void updateEffects(); // Update HUD effects
+ void overrideObjectUpdates();
void setForceSelection(BOOL force) { mForceSelection = force; }
@@ -580,9 +581,12 @@ public:
LLCategory mCategory;
S16 mInventorySerial;
LLVector3 mSavedPositionLocal; // for interactively modifying object position
+ LLVector3 mLastPositionLocal;
LLVector3d mSavedPositionGlobal; // for interactively modifying object position
LLVector3 mSavedScale; // for interactively modifying object scale
+ LLVector3 mLastScale;
LLQuaternion mSavedRotation; // for interactively modifying object rotation
+ LLQuaternion mLastRotation;
BOOL mDuplicated;
LLVector3d mDuplicatePos;
LLQuaternion mDuplicateRot;
diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp
index 022f02c57e..02f3855ace 100644
--- a/indra/newview/llsky.cpp
+++ b/indra/newview/llsky.cpp
@@ -347,7 +347,7 @@ void LLSky::updateCull()
if (mVOStarsp.notNull() && mVOStarsp->mDrawable.notNull())
{
- gPipeline.markVisible(mVOStarsp->mDrawable);
+ gPipeline.markVisible(mVOStarsp->mDrawable, *gCamera);
}
else
{
@@ -372,10 +372,10 @@ void LLSky::updateSky()
}
if (mVOStarsp)
{
- if (mVOStarsp->mDrawable)
- {
- gPipeline.markRebuild(mVOStarsp->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- }
+ //if (mVOStarsp->mDrawable)
+ //{
+ // gPipeline.markRebuild(mVOStarsp->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+ //}
}
}
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 8b5db02c85..739d30bfe6 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -10,25 +10,21 @@
#include "llspatialpartition.h"
-#include "llglheaders.h"
-
+#include "llviewerwindow.h"
#include "llviewerobjectlist.h"
#include "llvovolume.h"
#include "llviewercamera.h"
#include "llface.h"
#include "viewer.h"
-
+#include "llagent.h"
+#include "llviewerregion.h"
#include "llcamera.h"
#include "pipeline.h"
-static BOOL sIgnoreOcclusion = TRUE;
static GLuint sBoxList = 0;
-const S32 SG_LOD_SWITCH_STAGGER = 4;
-const F32 SG_MAX_OBJ_RAD = 1.f;
-const F32 SG_OCCLUSION_FUDGE = 1.1f;
-const S32 SG_MOVE_PERIOD = 32;
-const S32 SG_LOD_PERIOD = 16;
+const F32 SG_OCCLUSION_FUDGE = 1.01f;
+//const S32 SG_LOD_PERIOD = 16;
#define SG_DISCARD_TOLERANCE 0.25f
@@ -38,11 +34,12 @@ const S32 SG_LOD_PERIOD = 16;
#define assert_octree_valid(x)
#endif
+static U32 sZombieGroups = 0;
+
static F32 sLastMaxTexPriority = 1.f;
static F32 sCurMaxTexPriority = 1.f;
//static counter for frame to switch LOD on
-S32 LLSpatialGroup::sLODSeed = 0;
void sg_assert(BOOL expr)
{
@@ -125,25 +122,22 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3
LLSpatialGroup::~LLSpatialGroup()
{
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (!safeToDelete())
+ if (isState(DEAD))
{
-#ifdef LL_RELEASE_FOR_DOWNLOAD
- llwarns << "Spatial Group deleted while being tracked " << ((void*) mState) << llendl;
-#else
- llerrs << "Spatial Group deleted while being tracked " << ((void*) mState) << llendl;
-#endif
+ sZombieGroups--;
}
-#if LL_OCTREE_PARANOIA_CHECK
- for (U32 i = 0; i < mSpatialPartition->mOccludedList.size(); i++)
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+ clearDrawMap();
+}
+
+void LLSpatialGroup::clearDrawMap()
+{
+ for (LLSpatialGroup::draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
{
- if (mSpatialPartition->mOccludedList[i] == this)
- {
- llerrs << "Spatial Group deleted while being tracked STATE ERROR " << ((void*) mState) << llendl;
- }
+ std::for_each(i->second.begin(), i->second.end(), DeletePointer());
}
-#endif
+ mDrawMap.clear();
}
BOOL LLSpatialGroup::safeToDelete()
@@ -193,13 +187,13 @@ public:
BOOL LLSpatialGroup::isVisible()
{
- if (sIgnoreOcclusion)
+ if (LLPipeline::sUseOcclusion)
{
- return !isState(CULLED);
+ return !isState(CULLED | OCCLUDED);
}
else
{
- return !isState(CULLED | OCCLUDED);
+ return !isState(CULLED);
}
}
@@ -235,6 +229,88 @@ void LLSpatialGroup::validate()
#endif
}
+void validate_draw_info(LLDrawInfo& params)
+{
+#if LL_DEBUG
+/* if (params.mVertexBuffer.isNull())
+ {
+ llerrs << "Draw batch has no vertex buffer." << llendl;
+ }
+
+ //bad range
+ if (params.mStart >= params.mEnd)
+ {
+ llerrs << "Draw batch has invalid range." << llendl;
+ }
+
+ if (params.mEnd >= params.mVertexBuffer->getNumVerts())
+ {
+ llerrs << "Draw batch has buffer overrun error." << llendl;
+ }
+
+ if (params.mOffset + params.mCount > params.mVertexBuffer->getNumIndices())
+ {
+ llerrs << "Draw batch has index buffer ovverrun error." << llendl;
+ }
+
+ //bad indices
+ U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer();
+ if (indicesp)
+ {
+ for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
+ {
+ if (indicesp[i] < params.mStart)
+ {
+ llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
+ }
+
+ if (indicesp[i] > params.mEnd)
+ {
+ llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
+ }
+ }
+ }*/
+#endif
+}
+
+void LLSpatialGroup::validateDrawMap()
+{
+/* for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
+ {
+ std::vector<LLDrawInfo*>& draw_vec = i->second;
+ for (std::vector<LLDrawInfo*>::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
+ {
+ LLDrawInfo& params = **j;
+
+ validate_draw_info(params);
+ }
+ }*/
+}
+
+void LLSpatialGroup::makeStatic()
+{
+ if (isState(GEOM_DIRTY | ALPHA_DIRTY))
+ {
+ return;
+ }
+
+ if (mSpatialPartition->mRenderByGroup && mBufferUsage != GL_STATIC_DRAW_ARB)
+ {
+ mBufferUsage = GL_STATIC_DRAW_ARB;
+ if (mVertexBuffer.notNull())
+ {
+ mVertexBuffer->makeStatic();
+ }
+
+ for (buffer_map_t::iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i)
+ {
+ i->second->makeStatic();
+ }
+
+ mBuilt = 1.f;
+ }
+}
+
BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -246,6 +322,8 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
{
unbound();
setState(OBJECT_DIRTY);
+ setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this);
validate_drawable(drawablep);
return TRUE;
}
@@ -265,11 +343,83 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc
{
drawablep->setSpatialGroup(this, 0);
validate_drawable(drawablep);
+ setState(OBJECT_DIRTY | GEOM_DIRTY);
+ gPipeline.markRebuild(this);
+ mLastAddTime = gFrameTimeSeconds;
+ if (drawablep->isSpatialBridge())
+ {
+ mBridgeList.push_back((LLSpatialBridge*) drawablep);
+ }
+ setState(IMAGE_DIRTY);
}
return TRUE;
}
+void LLSpatialGroup::rebuildGeom()
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+ if (!isDead())
+ {
+ mSpatialPartition->rebuildGeom(this);
+ }
+}
+
+void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
+{
+ if (group->changeLOD())
+ {
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+ }
+
+ if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
+ {
+ return;
+ }
+
+ LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
+
+ group->clearDrawMap();
+
+ //get geometry count
+ group->mIndexCount = 0;
+ group->mVertexCount = 0;
+
+ addGeometryCount(group, group->mVertexCount, group->mIndexCount);
+
+ if (group->mVertexCount > 0 && group->mIndexCount > 0)
+ { //create vertex buffer containing volume geometry for this node
+ group->mBuilt = 1.f;
+ if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
+ {
+ //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB);
+ group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
+ group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true);
+ stop_glerror();
+ }
+ else
+ {
+ //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB);
+ group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount);
+ stop_glerror();
+ }
+
+ {
+ LLFastTimer ftm((LLFastTimer::EFastTimerType) ((U32) LLFastTimer::FTM_REBUILD_VOLUME_VB + mPartitionType));
+ getGeometry(group);
+ }
+ }
+ else
+ {
+ group->mVertexBuffer = NULL;
+ group->mBufferMap.clear();
+ }
+
+ group->mLastUpdateTime = gFrameTimeSeconds;
+ group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY);
+}
+
BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut)
{
const OctreeState* node = mOctreeNode->getOctState();
@@ -285,7 +435,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
LLVector3& newMin = mObjectExtents[0];
LLVector3& newMax = mObjectExtents[1];
-
+
if (isState(OBJECT_DIRTY))
{ //calculate new bounding box
clearState(OBJECT_DIRTY);
@@ -371,11 +521,28 @@ void LLSpatialGroup::unbound()
}
}
+LLSpatialGroup* LLSpatialGroup::getParent()
+{
+ if (isDead())
+ {
+ return NULL;
+ }
+
+ OctreeNode* parent = mOctreeNode->getOctParent();
+
+ if (parent)
+ {
+ return (LLSpatialGroup*) parent->getListener(0);
+ }
+
+ return NULL;
+}
+
BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
unbound();
- if (!from_octree)
+ if (mOctreeNode && !from_octree)
{
if (!mOctreeNode->remove(drawablep))
{
@@ -385,6 +552,19 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
else
{
drawablep->setSpatialGroup(NULL, -1);
+ setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this);
+ if (drawablep->isSpatialBridge())
+ {
+ for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
+ {
+ if (*i == drawablep)
+ {
+ mBridgeList.erase(i);
+ break;
+ }
+ }
+ }
}
return TRUE;
}
@@ -401,6 +581,9 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
mObjectBounds[0] += offset;
mObjectExtents[0] += offset;
mObjectExtents[1] += offset;
+
+ gPipeline.markRebuild(this);
+ setState(GEOM_DIRTY | MATRIX_DIRTY | OCCLUSION_DIRTY);
}
class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
@@ -515,29 +698,152 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
//======================================
LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part)
-: mState(0), mOctreeNode(node), mSpatialPartition(part)
+: mOctreeNode(node), mState(0), mSpatialPartition(part), mVertexBuffer(NULL),
+ mDistance(0.f), mLastUpdateDistance(-1.f),
+ mViewAngle(0.f), mLastUpdateViewAngle(-1.f),
+ mDepth(0.f), mBuilt(0.f),
+ mLastUpdateTime(gFrameTimeSeconds), mLastRenderTime(gFrameTimeSeconds),
+ mLastAddTime(gFrameTimeSeconds),
+ mBufferUsage(GL_STATIC_DRAW_ARB)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
sg_assert(mOctreeNode->getListenerCount() == 0);
mOctreeNode->addListener(this);
- setState(DIRTY);
+ setState(SG_INITIAL_STATE_MASK);
mBounds[0] = LLVector3(node->getCenter());
mBounds[1] = LLVector3(node->getSize());
- sLODSeed = (sLODSeed+1)%SG_LOD_PERIOD;
- mLODHash = sLODSeed;
+ part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
+ mLODHash = part->mLODSeed;
+
+ mRadius = 1;
+ mPixelArea = 1024.f;
+}
+
+void LLSpatialGroup::updateDistance(LLCamera &camera)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if (isState(LLSpatialGroup::OBJECT_DIRTY))
+ {
+ llerrs << "Spatial group dirty on distance update." << llendl;
+ }
+#endif
+ if (!getData().empty())
+ {
+ mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
+ (F32) mOctreeNode->getSize().magVec();
+ mDistance = mSpatialPartition->calcDistance(this, camera);
+ mPixelArea = mSpatialPartition->calcPixelArea(this, camera);
+ }
+}
+
+F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
+{
+ LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin();
+
+ F32 dist = 0.f;
+
+ if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end())
+ {
+ LLVector3 v = eye;
+ dist = eye.normVec();
+
+ if (!group->isState(LLSpatialGroup::ALPHA_DIRTY))
+ {
+ LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0),
+ eye * LLVector3(0,1,0),
+ eye * LLVector3(0,0,1));
+
+ if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
+ {
+ group->mViewAngle = view_angle;
+ group->mLastUpdateViewAngle = view_angle;
+ //for occasional alpha sorting within the group
+ //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
+ //not setting this node to dirty would be a very good thing
+ group->setState(LLSpatialGroup::ALPHA_DIRTY);
+ }
+ }
+
+ //calculate depth of node for alpha sorting
+
+ LLVector3 at = camera.getAtAxis();
+
+ //front of bounding box
+ for (U32 i = 0; i < 3; i++)
+ {
+ v.mV[i] -= group->mObjectBounds[1].mV[i]*0.25f * at.mV[i];
+ }
+
+ group->mDepth = v * at;
+
+ F32 water_height = gAgent.getRegion()->getWaterHeight();
+ //figure out if this node is above or below water
+ if (group->mObjectBounds[0].mV[2] < water_height)
+ {
+ group->setState(LLSpatialGroup::BELOW_WATER);
+ }
+ else
+ {
+ group->clearState(LLSpatialGroup::BELOW_WATER);
+ }
+ }
+ else
+ {
+ dist = eye.magVec();
+ }
+
+ if (dist < 16.f)
+ {
+ dist /= 16.f;
+ dist *= dist;
+ dist *= 16.f;
+ }
+
+ return dist;
+}
+
+F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
+{
+ return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
}
BOOL LLSpatialGroup::changeLOD()
{
- return LLDrawable::getCurrentFrame()%SG_LOD_PERIOD == mLODHash;
+ if (isState(ALPHA_DIRTY))
+ { ///an alpha sort is going to happen, update distance and LOD
+ return TRUE;
+ }
+
+ if (mSpatialPartition->mSlopRatio > 0.f)
+ {
+ F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
+
+ if (fabsf(ratio) >= mSpatialPartition->mSlopRatio)
+ {
+ return TRUE;
+ }
+
+ if (mDistance > mRadius)
+ {
+ return FALSE;
+ }
+ }
+
+ if (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
}
-void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawable)
+void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- addObject(drawable, FALSE, TRUE);
+ addObject(drawablep, FALSE, TRUE);
unbound();
setState(OBJECT_DIRTY);
}
@@ -552,29 +858,13 @@ void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable)
void LLSpatialGroup::handleDestruction(const TreeNode* node)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
-
- if (mOctreeNode)
- {
- OctreeState* state = mOctreeNode->getOctState();
- for (OctreeState::element_iter i = state->getData().begin(); i != state->getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- if (!drawable->isDead())
- {
- drawable->setSpatialGroup(NULL, -1);
- }
- }
- }
-
- if (safeToDelete())
- {
- delete this;
- }
- else
- {
- setState(DEAD);
- mOctreeNode = NULL;
- }
+ setState(DEAD);
+ clearDrawMap();
+ mOcclusionVerts = NULL;
+ mVertexBuffer = NULL;
+ mBufferMap.clear();
+ sZombieGroups++;
+ mOctreeNode = NULL;
}
void LLSpatialGroup::handleStateChange(const TreeNode* node)
@@ -592,7 +882,8 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
if (child->getListenerCount() == 0)
{
- (new LLSpatialGroup(child, mSpatialPartition))->setState(mState & SG_STATE_INHERIT_MASK);
+ LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition);
+ group->setState(mState & SG_STATE_INHERIT_MASK);
}
else
{
@@ -616,7 +907,7 @@ BOOL LLSpatialGroup::rebound()
LLVector3 oldBounds[2];
- if (isState(QUERY_OUT))
+ if (mSpatialPartition->isVolatile() && isState(QUERY_OUT))
{ //a query has been issued, if our bounding box changes significantly
//we need to discard the issued query
oldBounds[0] = mBounds[0];
@@ -681,7 +972,7 @@ BOOL LLSpatialGroup::rebound()
mBounds[1] = (newMax - newMin)*0.5f;
}
- if (isState(QUERY_OUT))
+ if (mSpatialPartition->isVolatile() && isState(QUERY_OUT))
{
for (U32 i = 0; i < 3 && !isState(DISCARD_QUERY); i++)
{
@@ -694,6 +985,8 @@ BOOL LLSpatialGroup::rebound()
}
}
+ setState(OCCLUSION_DIRTY);
+
clearState(DIRTY);
return TRUE;
@@ -701,9 +994,21 @@ BOOL LLSpatialGroup::rebound()
//==============================================
-LLSpatialPartition::LLSpatialPartition()
+LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buffer_usage)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+ mDrawableType = 0;
+ mPartitionType = LLPipeline::PARTITION_NONE;
+ mVolatile = is_volatile;
+ mLODSeed = 0;
+ mLODPeriod = 1;
+ mVertexDataMask = data_mask;
+ mBufferUsage = buffer_usage;
+ mDepthMask = FALSE;
+ mSlopRatio = 0.25f;
+ mRenderByGroup = TRUE;
+ mImageEnabled = FALSE;
+
mOctree = new LLSpatialGroup::OctreeNode(LLVector3d(0,0,0),
LLVector3d(1,1,1),
new LLSpatialGroup::OctreeRoot(), NULL);
@@ -714,12 +1019,18 @@ LLSpatialPartition::LLSpatialPartition()
LLSpatialPartition::~LLSpatialPartition()
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ for (U32 i = 0; i < mOcclusionQueries.size(); i++)
+ {
+ glDeleteQueriesARB(1, (GLuint*)(&(mOcclusionQueries[i])));
+ }
+
delete mOctree;
mOctree = NULL;
}
-LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep)
+LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
@@ -751,7 +1062,13 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep)
LLSpatialGroup::OctreeNode* node = mOctree->getNodeAt(drawablep);
- return (LLSpatialGroup*) node->getListener(0);
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+ if (was_visible && group->isState(LLSpatialGroup::QUERY_OUT))
+ {
+ group->setState(LLSpatialGroup::DISCARD_QUERY);
+ }
+
+ return group;
}
BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp)
@@ -774,14 +1091,16 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
-
+
+ BOOL was_visible = curp ? curp->isVisible() : FALSE;
+
if (curp && curp->mSpatialPartition != this)
{
//keep drawable from being garbage collected
LLPointer<LLDrawable> ptr = drawablep;
if (curp->mSpatialPartition->remove(drawablep, curp))
{
- put(drawablep);
+ put(drawablep, was_visible);
return;
}
else
@@ -804,7 +1123,7 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL
OCT_ERRS << "Move couldn't find existing spatial group!" << llendl;
}
- put(drawablep);
+ put(drawablep, was_visible);
}
class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
@@ -829,13 +1148,9 @@ void LLSpatialPartition::shift(const LLVector3 &offset)
BOOL LLSpatialPartition::checkOcclusion(LLSpatialGroup* group, LLCamera* camera)
{
- if (sIgnoreOcclusion)
- {
- return FALSE;
- }
-
- if (!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) &&
- !earlyFail(camera, group))
+ if (LLPipeline::sUseOcclusion &&
+ !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) &&
+ (!camera || !earlyFail(camera, group)))
{
group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
mQueryQueue.push(group);
@@ -853,8 +1168,8 @@ public:
virtual bool earlyFail(const LLSpatialGroup* group)
{
- if (mRes && //never occlusion cull the root node
- !sIgnoreOcclusion && //never occlusion cull selection
+ if (group->mOctreeNode->getParent() && //never occlusion cull the root node
+ LLPipeline::sUseOcclusion && //never occlusion cull selection
group->isState(LLSpatialGroup::OCCLUDED))
{
return true;
@@ -931,22 +1246,19 @@ public:
group->mSpatialPartition->checkOcclusion(group, mCamera);
}
}
+
+ if (LLPipeline::sDynamicReflections &&
+ group->mOctreeNode->getSize().mdV[0] == 16.0 &&
+ group->mDistance < 64.f &&
+ group->mLastAddTime < gFrameTimeSeconds - 2.f)
+ {
+ group->mSpatialPartition->markReimage(group);
+ }
}
- virtual void processDrawable(LLDrawable* drawable)
+ virtual void processGroup(LLSpatialGroup* group)
{
- if (!drawable->isDead())
- {
- const LLVector3* extents = drawable->getSpatialExtents();
-
- F32 objRad = drawable->getRadius();
- objRad *= objRad;
- F32 distSqr = ((extents[0]+extents[1])*0.5f - mCamera->getOrigin()).magVecSquared();
- if (objRad/distSqr > SG_MIN_DIST_RATIO)
- {
- gPipeline.markNotCulled(drawable, *mCamera);
- }
- }
+ gPipeline.markNotCulled(group, *mCamera);
}
virtual void visit(const LLSpatialGroup::OctreeState* branch)
@@ -957,10 +1269,7 @@ public:
if (checkObjects(branch, group))
{
- for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
- {
- processDrawable(*i);
- }
+ processGroup(group);
}
}
@@ -979,34 +1288,32 @@ public:
virtual void lateFail(LLSpatialGroup* group) { }
virtual void preprocess(LLSpatialGroup* group) { }
- virtual void processDrawable(LLDrawable* drawable)
+ virtual void processGroup(LLSpatialGroup* group)
{
- if (!drawable->isDead())
+ LLSpatialGroup::OctreeState* branch = group->mOctreeNode->getOctState();
+
+ for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
{
- if (drawable->isSpatialBridge())
- {
- drawable->setVisible(*mCamera, mResults, TRUE);
- }
- else
+ LLDrawable* drawable = *i;
+
+ if (!drawable->isDead())
{
- mResults->push_back(drawable);
- }
- }
+ if (drawable->isSpatialBridge())
+ {
+ drawable->setVisible(*mCamera, mResults, TRUE);
+ }
+ else
+ {
+ mResults->push_back(drawable);
+ }
+ }
+ }
}
std::vector<LLDrawable*>* mResults;
};
-void drawBox(const LLVector3& c, const LLVector3& r)
-{
- glPushMatrix();
- glTranslatef(c.mV[0], c.mV[1], c.mV[2]);
- glScalef(r.mV[0], r.mV[1], r.mV[2]);
- glCallList(sBoxList);
- glPopMatrix();
-}
-
void genBoxList()
{
if (sBoxList != 0)
@@ -1058,6 +1365,99 @@ void genBoxList()
glEndList();
}
+void drawBox(const LLVector3& c, const LLVector3& r)
+{
+ genBoxList();
+
+ glPushMatrix();
+ glTranslatef(c.mV[0], c.mV[1], c.mV[2]);
+ glScalef(r.mV[0], r.mV[1], r.mV[2]);
+ glCallList(sBoxList);
+ glPopMatrix();
+}
+
+void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
+{
+ LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
+ LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
+ LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
+ LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
+
+ glBegin(GL_LINE_LOOP); //top
+ glVertex3fv((pos+v1).mV);
+ glVertex3fv((pos+v2).mV);
+ glVertex3fv((pos+v3).mV);
+ glVertex3fv((pos+v4).mV);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP); //bottom
+ glVertex3fv((pos-v1).mV);
+ glVertex3fv((pos-v2).mV);
+ glVertex3fv((pos-v3).mV);
+ glVertex3fv((pos-v4).mV);
+ glEnd();
+
+
+ glBegin(GL_LINES);
+
+ //right
+ glVertex3fv((pos+v1).mV);
+ glVertex3fv((pos-v3).mV);
+
+ glVertex3fv((pos+v4).mV);
+ glVertex3fv((pos-v2).mV);
+
+ //left
+ glVertex3fv((pos+v2).mV);
+ glVertex3fv((pos-v4).mV);
+
+ glVertex3fv((pos+v3).mV);
+ glVertex3fv((pos-v1).mV);
+
+ glEnd();
+}
+
+class LLOctreeDirty : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ virtual void visit(const LLOctreeState<LLDrawable>* state)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
+
+ group->setState(LLSpatialGroup::GEOM_DIRTY |
+ LLSpatialGroup::OCCLUSION_DIRTY |
+ LLSpatialGroup::IMAGE_DIRTY);
+ group->mLastUpdateTime = gFrameTimeSeconds;
+ group->mVertexBuffer = NULL;
+ group->mBufferMap.clear();
+
+ group->mOcclusionVerts = NULL;
+ group->mReflectionMap = NULL;
+ group->clearDrawMap();
+
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ LLDrawable* drawable = *i;
+ for (S32 j = 0; j < drawable->getNumFaces(); j++)
+ {
+ LLFace* facep = drawable->getFace(j);
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ }
+
+ if (drawable->getVObj() && !group->mSpatialPartition->mRenderByGroup)
+ {
+ gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ }
+
+ for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ traverse(bridge->mOctree);
+ }
+ }
+};
void LLSpatialPartition::restoreGL()
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1080,6 +1480,14 @@ void LLSpatialPartition::restoreGL()
genBoxList();
}
+void LLSpatialPartition::resetVertexBuffers()
+{
+ LLOctreeDirty dirty;
+ dirty.traverse(mOctree);
+
+ mOcclusionIndices = NULL;
+}
+
S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1096,11 +1504,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
}
else
{
+ LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
LLOctreeCull culler(&camera);
culler.traverse(mOctree);
}
- sIgnoreOcclusion = !(gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery);
return 0;
}
@@ -1155,9 +1563,10 @@ public:
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
{
LLVector3 c = group->mBounds[0];
- LLVector3 r = group->mBounds[1] * (SG_OCCLUSION_FUDGE*2.f) + LLVector3(0.01f,0.01f,0.01f);
+ LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.2f,0.2f,0.2f);
- if (group->isState(LLSpatialGroup::CULLED) || !camera->AABBInFrustum(c, r))
+ //if (group->isState(LLSpatialGroup::CULLED)) // ||
+ if (!camera->AABBInFrustum(c, r))
{
return TRUE;
}
@@ -1178,6 +1587,160 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
return TRUE;
}
+void LLSpatialPartition::processGeometry(LLCamera* camera)
+{
+ if (!mRenderByGroup || mBufferUsage == GL_STREAM_DRAW_ARB)
+ {
+ return;
+ }
+
+ U32 process_count = 8;
+
+ LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
+ if (!root->isState(LLSpatialGroup::IN_GEOMETRY_QUEUE))
+ {
+ root->setState(LLSpatialGroup::IN_GEOMETRY_QUEUE);
+ mUpdateQueue.push(root);
+ }
+
+ while (process_count > 0 && !mUpdateQueue.empty())
+ {
+ process_count--;
+ LLPointer<LLSpatialGroup> group = mUpdateQueue.front();
+ mUpdateQueue.pop();
+
+ group->clearState(LLSpatialGroup::IN_GEOMETRY_QUEUE);
+
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ //push children onto queue
+ for (U32 i = 0; i < group->mOctreeNode->getChildCount(); i++)
+ {
+ LLSpatialGroup* child = (LLSpatialGroup*) group->mOctreeNode->getChild(i)->getListener(0);
+
+ if (!child->isState(LLSpatialGroup::IN_GEOMETRY_QUEUE))
+ {
+ child->setState(LLSpatialGroup::IN_GEOMETRY_QUEUE);
+ mUpdateQueue.push(child);
+ }
+ }
+
+ if (!group->isDead() &&
+ !group->isVisible() &&
+ !group->isState(LLSpatialGroup::OBJECT_DIRTY) &&
+ group->mBufferUsage != GL_STREAM_DRAW_ARB)
+ {
+ group->updateDistance(*camera);
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ LLDrawable* drawablep = *i;
+ if (!drawablep->isDead())
+ {
+ drawablep->updateDistance(*camera);
+ }
+ }
+ }
+ }
+}
+
+void LLSpatialPartition::markReimage(LLSpatialGroup* group)
+{
+ if (mImageEnabled && group->isState(LLSpatialGroup::IMAGE_DIRTY))
+ {
+ if (!group->isState(LLSpatialGroup::IN_IMAGE_QUEUE))
+ {
+ group->setState(LLSpatialGroup::IN_IMAGE_QUEUE);
+ mImageQueue.push(group);
+ }
+ }
+}
+
+void LLSpatialPartition::processImagery(LLCamera* camera)
+{
+ if (!mImageEnabled)
+ {
+ return;
+ }
+
+ U32 process_count = 1;
+
+ while (process_count > 0 && !mImageQueue.empty())
+ {
+ LLPointer<LLSpatialGroup> group = mImageQueue.front();
+ mImageQueue.pop();
+
+ group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE);
+
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ if (LLPipeline::sDynamicReflections)
+ {
+ process_count--;
+ LLVector3 origin = group->mBounds[0];
+
+ LLCamera cube_cam;
+ cube_cam.setOrigin(origin);
+ cube_cam.setFar(64.f);
+
+ LLPointer<LLCubeMap> cube_map = group->mReflectionMap;
+ group->mReflectionMap = NULL;
+ if (cube_map.isNull())
+ {
+ cube_map = new LLCubeMap();
+ cube_map->initGL();
+ }
+
+ if (gPipeline.mCubeBuffer == NULL)
+ {
+ gPipeline.mCubeBuffer = new LLCubeMap();
+ gPipeline.mCubeBuffer->initGL();
+ }
+
+ gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128);
+ gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, 32);
+ group->mReflectionMap = cube_map;
+ group->setState(LLSpatialGroup::GEOM_DIRTY);
+ gPipeline.markRebuild(group);
+ }
+
+ group->clearState(LLSpatialGroup::IMAGE_DIRTY);
+ }
+}
+
+void validate_occlusion_list(std::vector<LLPointer<LLSpatialGroup> >& occluded_list)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ for (U32 i = 0; i < occluded_list.size(); i++)
+ {
+ LLSpatialGroup* group = occluded_list[i];
+ for (U32 j = i+1; j < occluded_list.size(); j++)
+ {
+ if (occluded_list[i] == occluded_list[j])
+ {
+ llerrs << "Duplicate node in occlusion list." << llendl;
+ }
+ }
+
+ LLSpatialGroup::OctreeNode* parent = group->mOctreeNode->getOctParent();
+ while (parent)
+ {
+ LLSpatialGroup* parent_group = (LLSpatialGroup*) parent->getListener(0);
+ if (parent_group->isState(LLSpatialGroup::OCCLUDED))
+ {
+ llerrs << "Child node of occluded node in occlusion list (redundant query)." << llendl;
+ }
+ parent = parent->getOctParent();
+ }
+ }
+#endif
+}
+
void LLSpatialPartition::processOcclusion(LLCamera* camera)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1198,12 +1761,12 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
const U32 MAX_PUSHED = mOcclusionQueue.size();
U32 count = 0;
U32 pcount = 0;
-
+
while (pcount < MAX_PUSHED && count < MAX_PULLED && !mOcclusionQueue.empty())
{
- LLFastTimer t(LLFastTimer::FTM_OCCLUSION);
+ LLFastTimer t(LLFastTimer::FTM_OCCLUSION);
- LLSpatialGroup* group = mOcclusionQueue.front();
+ LLPointer<LLSpatialGroup> group = mOcclusionQueue.front();
if (!group->isState(LLSpatialGroup::IN_QUEUE))
{
OCT_ERRS << "Spatial Group State Error. Group in queue not tagged as such." << llendl;
@@ -1214,10 +1777,6 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
if (group->isDead())
{
- if (group->safeToDelete())
- {
- delete group;
- }
continue;
}
@@ -1231,22 +1790,14 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
{
LLSpatialGroup* child = (LLSpatialGroup*) group->mOctreeNode->getChild(i)->getListener(0);
- if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED)
- && !child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION))
+ //if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED)
+ if (!child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION))
{
child->setState(LLSpatialGroup::IN_QUEUE);
mOcclusionQueue.push(child);
}
}
-
- /*if (group->isState(LLSpatialGroup::QUERY_PENDING))
- { //already on the pending group, put it back
- group->setState(LLSpatialGroup::IN_QUEUE);
- mOcclusionQueue.push(group);
- pcount++;
- continue;
- }*/
-
+
if (earlyFail(camera, group))
{
sg_assert(!group->isState(LLSpatialGroup::OCCLUDED));
@@ -1265,7 +1816,6 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
sg_assert(mOccludedList[i] != group);
}
#endif
- //group->setState(LLSpatialGroup::QUERY_PENDING);
group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
mQueryQueue.push(group);
count++;
@@ -1277,7 +1827,7 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
{
LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK);
- if (mOccludedList[i]->isDead() || !mOccludedList[i]->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
+ if (mOccludedList[i]->isDead() || mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION))
{
continue;
}
@@ -1328,8 +1878,7 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
LLSpatialGroup* parent = (LLSpatialGroup*) oct_parent->getListener(0);
if (checkOcclusion(parent, camera))
- { //force a guess on the parent and siblings
-
+ { //force a guess on the parent and siblings
for (U32 i = 0; i < parent->mOctreeNode->getChildCount(); i++)
{
LLSpatialGroup* child = (LLSpatialGroup*) parent->mOctreeNode->getChild(i)->getListener(0);
@@ -1337,13 +1886,17 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
}
}
}
+
+ //take children off the active list
+ mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH);
+ mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
}
mOccludedList[i]->setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
}
else
{
//take children off the active list
- mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_DIFF);
+ mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH);
//keep this node on the active list
mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
@@ -1364,15 +1917,13 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) //parent is occluded
{
LLSpatialGroup* groupp = mOccludedList[i];
- mOccludedList.erase(mOccludedList.begin()+i);
- groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
- groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
- groupp->clearState(LLSpatialGroup::OCCLUDING);
-
- if (groupp->isDead() && groupp->safeToDelete())
+ if (!groupp->isDead())
{
- delete groupp;
+ groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
+ groupp->clearState(LLSpatialGroup::OCCLUDING);
}
+ mOccludedList.erase(mOccludedList.begin()+i);
}
else
{
@@ -1380,11 +1931,13 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
}
}
+ validate_occlusion_list(mOccludedList);
+
//pump some non-culled items onto the occlusion list
//count = MAX_PULLED;
while (!mQueryQueue.empty())
{
- LLSpatialGroup* group = mQueryQueue.front();
+ LLPointer<LLSpatialGroup> group = mQueryQueue.front();
mQueryQueue.pop();
//group->clearState(LLSpatialGroup::QUERY_PENDING);
mOccludedList.push_back(group);
@@ -1399,12 +1952,161 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera)
}
}
+class LLOcclusionIndexBuffer : public LLVertexBuffer
+{
+public:
+ LLOcclusionIndexBuffer(U32 size)
+ : LLVertexBuffer(0, GL_STREAM_DRAW_ARB)
+ {
+ allocateBuffer(0, size, TRUE);
+
+ LLStrider<U32> idx;
+
+ getIndexStrider(idx);
+
+ //12 triangles' indices
+ idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
+ idx[3] = 3; idx[4] = 2; idx[5] = 0;
+
+ idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
+ idx[9] = 0; idx[10] = 1; idx[11] = 5;
+
+ idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
+ idx[15] = 7; idx[16] = 6; idx[17] = 4;
+
+ idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
+ idx[21] = 2; idx[22] = 3; idx[23] = 7;
+
+ idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
+ idx[27] = 6; idx[28] = 3; idx[29] = 5;
+
+ idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
+ idx[33] = 2; idx[34] = 7; idx[35] = 1;
+ }
+
+ //virtual BOOL useVBOs() const { return FALSE; }
+
+ void setBuffer(U32 data_mask)
+ {
+ if (useVBOs())
+ {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
+ sIBOActive = TRUE;
+ unmapBuffer();
+ }
+ else if (sIBOActive)
+ {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ sIBOActive = FALSE;
+ }
+
+ sGLRenderIndices = mGLIndices;
+ }
+};
+
+class LLOcclusionVertexBuffer : public LLVertexBuffer
+{
+public:
+ LLOcclusionVertexBuffer(S32 usage)
+ : LLVertexBuffer(MAP_VERTEX, usage)
+ {
+ allocateBuffer(8, 0, TRUE);
+ }
+
+ //virtual BOOL useVBOs() const { return FALSE; }
+
+ void setBuffer(U32 data_mask)
+ {
+ if (useVBOs())
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
+ sVBOActive = TRUE;
+ unmapBuffer();
+ }
+ else if (sVBOActive)
+ {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ sVBOActive = FALSE;
+ }
+
+ if (data_mask)
+ {
+ glVertexPointer(3,GL_FLOAT, 0, useVBOs() ? 0 : mMappedData);
+ }
+
+ sGLRenderBuffer = mGLBuffer;
+ }
+};
+
+void LLSpatialPartition::buildOcclusion()
+{
+ if (mOccludedList.empty())
+ {
+ return;
+ }
+
+ BOOL reset_all = FALSE;
+ if (mOcclusionIndices.isNull())
+ {
+ mOcclusionIndices = new LLOcclusionIndexBuffer(36);
+ reset_all = TRUE;
+ }
+
+ //fill occlusion vertex buffers
+ for (U32 i = 0; i < mOccludedList.size(); i++)
+ {
+ LLSpatialGroup* group = mOccludedList[i];
+
+ if (group->isState(LLSpatialGroup::OCCLUSION_DIRTY) || reset_all)
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB);
+
+ if (group->mOcclusionVerts.isNull())
+ {
+ group->mOcclusionVerts = new LLOcclusionVertexBuffer(GL_STREAM_DRAW_ARB);
+ }
+
+ group->clearState(LLSpatialGroup::OCCLUSION_DIRTY);
+
+ LLStrider<LLVector3> vert;
+
+ group->mOcclusionVerts->getVertexStrider(vert);
+
+ LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f);
+
+ for (U32 k = 0; k < 3; k++)
+ {
+ r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]);
+ }
+
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,1)); // 1 - right top front
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front
+
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back
+ *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
+ }
+ }
+
+/* for (U32 i = 0; i < mOccludedList.size(); i++)
+ {
+ LLSpatialGroup* group = mOccludedList[i];
+ if (!group->mOcclusionVerts.isNull() && group->mOcclusionVerts->isLocked())
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB);
+ group->mOcclusionVerts->setBuffer(0);
+ }
+ }*/
+}
+
void LLSpatialPartition::doOcclusion(LLCamera* camera)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- sIgnoreOcclusion = gUseWireframe;
- LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
+ LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
#if LL_OCTREE_PARANOIA_CHECK
LLSpatialGroup* check = (LLSpatialGroup*) mOctree->getListener(0);
@@ -1413,9 +2115,16 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera)
stop_glerror();
+ U32 num_verts = mOccludedList.size() * 8;
+
+ if (num_verts == 0)
+ {
+ return;
+ }
+
//actually perform the occlusion queries
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- glDisable(GL_TEXTURE_2D);
+ LLGLDisable(GL_TEXTURE_2D);
gPipeline.disableLights();
LLGLEnable cull_face(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
@@ -1424,25 +2133,16 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera)
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glColor4f(1,1,1,1);
- //sort occlusion queries front to back
- /*for (U32 i = 0; i < mOccludedList.size(); i++)
- {
- LLSpatialGroup* group = mOccludedList[i];
-
- LLVector3 v = group->mOctreeNode->getCenter()-camera->getOrigin();
- group->mDistance = v*v;
- }
-
- std::sort(mOccludedList.begin(), mOccludedList.end(), dist_greater());
+ mOcclusionIndices->setBuffer(0);
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT);
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_GREATER, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_SET, GL_KEEP);*/
-
- genBoxList();
+ U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer();
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX);
+#endif
for (U32 i = 0; i < mOccludedList.size(); i++)
{
#if LL_OCTREE_PARANOIA_CHECK
@@ -1463,32 +2163,10 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera)
}
else
{ //early rejection criteria passed, send some geometry to the query
- LLVector3 c;
- LLVector3 r;
-
- sg_assert(!group->isState(LLSpatialGroup::DIRTY));
-
- c = group->mBounds[0];
- r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.01f,0.01f,0.01f);
- for (U32 k = 0; k < 3; k++)
- {
- r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]);
- }
-
-#if LL_OCTREE_PARANOIA_CHECK
- LLVector3 e = camera->getOrigin();
- LLVector3 min = c - r;
- LLVector3 max = c + r;
- BOOL outside = FALSE;
- for (U32 j = 0; j < 3; j++)
- {
- outside = outside || (e.mV[j] < min.mV[j] || e.mV[j] > max.mV[j]);
- }
- sg_assert(outside);
-#endif
-
+ group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQueries[i]);
- drawBox(c,r);
+ glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
+ GL_UNSIGNED_INT, indicesp);
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
group->setState(LLSpatialGroup::QUERY_OUT);
@@ -1497,10 +2175,11 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera)
}
stop_glerror();
+ gPipeline.mTrianglesDrawn += mOccludedList.size()*12;
+
glFlush();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_TEXTURE_2D);
}
class LLOctreeGet : public LLSpatialGroup::OctreeTraveler
@@ -1599,6 +2278,8 @@ S32 LLSpatialPartition::getDrawables(const LLVector3& pos, F32 rad,
S32 LLSpatialPartition::getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results)
{
+ LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
+ group->rebound();
return getDrawables(pos, rad, results, FALSE);
}
@@ -1607,182 +2288,346 @@ S32 LLSpatialPartition::getLights(const LLVector3& pos, F32 rad, LLDrawable::dra
return getDrawables(pos, rad, results, TRUE);
}
-class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
+void pushVerts(LLSpatialGroup* group, U32 mask)
{
-public:
- LLOctreeRenderNonOccluded() {}
-
- virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ LLDrawInfo* params = NULL;
+
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
{
- const LLSpatialGroup::OctreeState* state = node->getOctState();
- LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+ for (std::vector<LLDrawInfo*>::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ params = *j;
+ params->mVertexBuffer->setBuffer(mask);
+ U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
+ GL_UNSIGNED_INT, indicesp+params->mOffset);
+ }
+ }
+}
+
+void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
+{
+ LLDrawInfo* params = NULL;
+
+ LLColor4 colors[] = {
+ LLColor4::green,
+ LLColor4::green1,
+ LLColor4::green2,
+ LLColor4::green3,
+ LLColor4::green4,
+ LLColor4::green5,
+ LLColor4::green6
+ };
- if (!group->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED))
+ static const U32 col_count = sizeof(colors)/sizeof(LLColor4);
+
+ U32 col = 0;
+
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+ {
+ for (std::vector<LLDrawInfo*>::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
- state->accept(this);
+ params = *j;
+ glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
+ params->mVertexBuffer->setBuffer(mask);
+ U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer();
+ glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
+ GL_UNSIGNED_INT, indicesp+params->mOffset);
+ col = (col+1)%col_count;
+ }
+ }
+}
- for (U32 i = 0; i < state->getChildCount(); i++)
+void renderOctree(LLSpatialGroup* group)
+{
+ //render solid object bounding box, color
+ //coded by buffer usage and activity
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ LLVector4 col;
+ if (group->mBuilt > 0.f)
+ {
+ group->mBuilt -= 2.f * gFrameIntervalSeconds;
+ if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
+ {
+ col.setVec(1.0f, 0, 0, group->mBuilt*0.5f);
+ }
+ else
+ {
+ col.setVec(0.1f,0.1f,1,0.1f);
+ //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f);
+ }
+
+ if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
+ {
+ if (group->mBufferUsage == GL_DYNAMIC_DRAW_ARB)
{
- traverse(state->getChild(i));
+ glColor4f(1,0,0,group->mBuilt);
}
-
- /*if (state->getElementCount() == 0)
+ else
{
- return;
- }*/
+ glColor4f(1,1,0,group->mBuilt);
+ }
- //draw tight fit bounding box for spatial group
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
+ LLGLDepthTest gl_depth(FALSE, FALSE);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- if (node->getElementCount() == 0)
- {
- return;
- }
-
- if (node->hasLeafState())
- {
- glColor4f(1,1,1,1);
- }
- else
+ LLDrawable* drawable = *i;
+ for (S32 j = 0; j < drawable->getNumFaces(); j++)
{
- glColor4f(0,1,1,1);
+ LLFace* face = drawable->getFace(j);
+ if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f && face->mVertexBuffer.notNull())
+ {
+ face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
+ // (face->mExtents[1]-face->mExtents[0])*0.5f);
+ glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_INT,
+ ((U32*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart());
+ }
}
+ }
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ }
+ else
+ {
+ if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
+ && group->mSpatialPartition->mRenderByGroup)
+ {
+ col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
+ }
+ else
+ {
+ col.setVec(0.1f, 0.1f, 1.f, 0.1f);
+ }
+ }
+ glColor4fv(col.mV);
+ drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+ glDepthMask(GL_TRUE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- LLVector3 pos;
- LLVector3 size;
-
- pos = group->mObjectBounds[0];
- size = group->mObjectBounds[1];
-
- LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
- LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
- LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
- LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
-
- glBegin(GL_LINE_LOOP); //top
- glVertex3fv((pos+v1).mV);
- glVertex3fv((pos+v2).mV);
- glVertex3fv((pos+v3).mV);
- glVertex3fv((pos+v4).mV);
- glEnd();
-
- glBegin(GL_LINE_LOOP); //bottom
- glVertex3fv((pos-v1).mV);
- glVertex3fv((pos-v2).mV);
- glVertex3fv((pos-v3).mV);
- glVertex3fv((pos-v4).mV);
- glEnd();
-
-
- glBegin(GL_LINES);
-
- //right
- glVertex3fv((pos+v1).mV);
- glVertex3fv((pos-v3).mV);
-
- glVertex3fv((pos+v4).mV);
- glVertex3fv((pos-v2).mV);
-
- //left
- glVertex3fv((pos+v2).mV);
- glVertex3fv((pos-v4).mV);
-
- glVertex3fv((pos+v3).mV);
- glVertex3fv((pos-v1).mV);
+ //draw opaque outline
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
+ drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
- glEnd();
+ if (group->mOctreeNode->hasLeafState())
+ {
+ glColor4f(1,1,1,1);
+ }
+ else
+ {
+ glColor4f(0,1,1,1);
+ }
+
+ drawBoxOutline(group->mBounds[0],group->mBounds[1]);
+
+// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
+// glColor4f(0,1,0,1);
+// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
+}
- LLVector3 nc = LLVector3(node->getCenter());
- LLVector3 ns = LLVector3(node->getSize());
+void renderVisibility(LLSpatialGroup* group)
+{
+ LLGLEnable blend(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ LLGLEnable cull(GL_CULL_FACE);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ {
+ LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
+ glColor4f(0, 0.5f, 0, 0.5f);
+ pushVerts(group, LLVertexBuffer::MAP_VERTEX);
+ }
- LLVector3 nv1 = ns.scaledVec(LLVector3( 1, 1,1));
- LLVector3 nv2 = ns.scaledVec(LLVector3(-1, 1,1));
- LLVector3 nv3 = ns.scaledVec(LLVector3(-1,-1,1));
- LLVector3 nv4 = ns.scaledVec(LLVector3( 1,-1,1));
+ {
+ LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
+ pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX);
-
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- /*if (node->getElementCount() > 0)
- {
- //spokes
- glColor4f(1,1,0,1);
- glVertex3fv(pos.mV);
- glColor4f(1,1,0,0);
- glVertex3fv(nc.mV);
-
- glColor4f(1,1,0,1); glVertex3fv((pos+v1).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos-v1).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos+v2).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos-v2).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos+v3).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos-v3).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos+v4).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- glColor4f(1,1,0,1); glVertex3fv((pos-v4).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV);
- }*/
+ pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX);
+ }
+}
-
+void renderBoundingBox(LLDrawable* drawable)
+{
+ if (drawable->isSpatialBridge())
+ {
+ glColor4f(1,0.5f,0,1);
+ }
+ else if (drawable->getVOVolume())
+ {
+ if (drawable->isRoot())
+ {
+ glColor4f(1,1,0,1);
+ }
+ else
+ {
+ glColor4f(0,1,0,1);
+ }
+ }
+ else if (drawable->getVObj())
+ {
+ switch (drawable->getVObj()->getPCode())
+ {
+ case LLViewerObject::LL_VO_SURFACE_PATCH:
+ glColor4f(0,1,1,1);
+ break;
+ case LLViewerObject::LL_VO_CLOUDS:
+ glColor4f(0.5f,0.5f,0.5f,1.0f);
+ break;
+ case LLViewerObject::LL_VO_PART_GROUP:
+ glColor4f(0,0,1,1);
+ break;
+ case LLViewerObject::LL_VO_WATER:
+ glColor4f(0,0.5f,1,1);
+ break;
+ case LL_PCODE_LEGACY_TREE:
+ glColor4f(0,0.5f,0,1);
+ default:
+ glColor4f(1,0,1,1);
+ break;
+ }
+ }
+ else
+ {
+ glColor4f(1,0,0,1);
+ }
- /*glColor4f(0,1,0,1);
- glBegin(GL_LINE_LOOP); //top
- glVertex3fv((nc+nv1).mV);
- glVertex3fv((nc+nv2).mV);
- glVertex3fv((nc+nv3).mV);
- glVertex3fv((nc+nv4).mV);
- glEnd();
+ const LLVector3* ext;
+ LLVector3 pos, size;
- glBegin(GL_LINE_LOOP); //bottom
- glVertex3fv((nc-nv1).mV);
- glVertex3fv((nc-nv2).mV);
- glVertex3fv((nc-nv3).mV);
- glVertex3fv((nc-nv4).mV);
- glEnd();
+ //render face bounding boxes
+ for (S32 i = 0; i < drawable->getNumFaces(); i++)
+ {
+ LLFace* facep = drawable->getFace(i);
+ ext = facep->mExtents;
- glBegin(GL_LINES);
+ if (ext[0].isExactlyZero() && ext[1].isExactlyZero())
+ {
+ continue;
+ }
+ pos = (ext[0] + ext[1]) * 0.5f;
+ size = (ext[1] - ext[0]) * 0.5f;
+ drawBoxOutline(pos,size);
+ }
- //right
- glVertex3fv((nc+nv1).mV);
- glVertex3fv((nc-nv3).mV);
-
- glVertex3fv((nc+nv4).mV);
- glVertex3fv((nc-nv2).mV);
+ //render drawable bounding box
+ ext = drawable->getSpatialExtents();
- //left
- glVertex3fv((nc+nv2).mV);
- glVertex3fv((nc-nv4).mV);
+ pos = (ext[0] + ext[1]) * 0.5f;
+ size = (ext[1] - ext[0]) * 0.5f;
+
+ drawBoxOutline(pos,size);
+}
- glVertex3fv((nc+nv3).mV);
- glVertex3fv((nc-nv1).mV);
- glEnd();*/
+void renderTexturePriority(LLDrawable* drawable)
+{
+ for (int face=0; face<drawable->getNumFaces(); ++face)
+ {
+ LLFace *facep = drawable->getFace(face);
+
+ LLVector4 cold(0,0,0.25f);
+ LLVector4 hot(1,0.25f,0.25f);
+
+ LLVector4 boost_cold(0,0,0,0);
+ LLVector4 boost_hot(0,1,0,1);
+
+ LLGLDisable blend(GL_BLEND);
+
+ //LLViewerImage* imagep = facep->getTexture();
+ //if (imagep)
+ {
+
+ //F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
+ //F32 vsize = imagep->mMaxVirtualSize;
+ F32 vsize = facep->getPixelArea();
- glLineWidth(1);
-
- glDepthMask(GL_FALSE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glColor4f(0.1f,0.1f,1,0.1f);
- drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
- glDepthMask(GL_TRUE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (vsize > sCurMaxTexPriority)
+ {
+ sCurMaxTexPriority = vsize;
}
+
+ F32 t = vsize/sLastMaxTexPriority;
+
+ LLVector4 col = lerp(cold, hot, t);
+ glColor4fv(col.mV);
}
- /*else
+ //else
+ //{
+ // glColor4f(1,0,1,1);
+ //}
+
+
+
+ LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f;
+ LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f);
+ drawBox(center, size);
+
+ /*S32 boost = imagep->getBoostLevel();
+ if (boost)
+ {
+ F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
+ LLVector4 col = lerp(boost_cold, boost_hot, t);
+ LLGLEnable blend_on(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glColor4fv(col.mV);
+ drawBox(center, size);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }*/
+ }
+}
+
+void renderPoints(LLDrawable* drawablep)
+{
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ glBegin(GL_POINTS);
+ glColor3f(1,1,1);
+ LLVector3 center(drawablep->getPositionGroup());
+ for (S32 i = 0; i < drawablep->getNumFaces(); i++)
+ {
+ glVertex3fv(drawablep->getFace(i)->mCenterLocal.mV);
+ }
+ glEnd();
+}
+
+class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ LLOctreeRenderNonOccluded() {}
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ {
+ const LLSpatialGroup::OctreeState* state = node->getOctState();
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+
+ if ((!gPipeline.sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) &&
+ !group->isState(LLSpatialGroup::CULLED))
{
- //occlusion paranoia check
- const LLSpatialGroup::OctreeNode* parent = node;
- while (parent != NULL)
+ state->accept(this);
+
+ for (U32 i = 0; i < state->getChildCount(); i++)
{
- LLSpatialGroup* grp = (LLSpatialGroup*) parent->getListener(0);
- if (grp->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
- {
- return;
- }
- parent = (const LLSpatialGroup::OctreeNode*) parent->getParent();
+ traverse(state->getChild(i));
+ }
+
+ //draw tight fit bounding boxes for spatial group
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
+ {
+ renderOctree(group);
}
- glColor4f(1,0,1,1);
- drawBox(group->mBounds[0], group->mBounds[1]);
- }*/
+ //render visibility wireframe
+ if (group->mSpatialPartition->mRenderByGroup &&
+ gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) &&
+ !group->isState(LLSpatialGroup::GEOM_DIRTY))
+ {
+ renderVisibility(group);
+ }
+ }
}
virtual void visit(const LLSpatialGroup::OctreeState* branch)
@@ -1797,276 +2642,24 @@ public:
LLVector3 nodeCenter = group->mBounds[0];
LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
- {
- glBegin(GL_LINES);
- glColor4f(1,0.5f,0,1);
- glVertex3fv(nodeCenter.mV);
- glColor4f(0,1,1,0);
- glVertex3fv(octCenter.mV);
- glEnd();
- }
-
for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
{
LLDrawable* drawable = *i;
-
- if (drawable->isSpatialBridge())
- {
- LLSpatialBridge* bridge = (LLSpatialBridge*) drawable;
- glPushMatrix();
- glMultMatrixf((F32*)bridge->mDrawable->getWorldMatrix().mMatrix);
- traverse(bridge->mOctree);
- glPopMatrix();
- }
-
- if (!drawable->isVisible())
- {
- continue;
- }
-
+
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
{
- if (drawable->isSpatialBridge())
- {
- glColor4f(1,0.5f,0,1);
- }
- else if (drawable->getVOVolume())
- {
- if (drawable->isRoot())
- {
- glColor4f(1,1,0,1);
- }
- else
- {
- glColor4f(0,1,0,1);
- }
- }
- else if (drawable->getVObj())
- {
- switch (drawable->getVObj()->getPCode())
- {
- case LLViewerObject::LL_VO_SURFACE_PATCH:
- glColor4f(0,1,1,1);
- break;
- case LLViewerObject::LL_VO_CLOUDS:
- glColor4f(0.5f,0.5f,0.5f,1.0f);
- break;
- case LLViewerObject::LL_VO_PART_GROUP:
- glColor4f(0,0,1,1);
- break;
- case LLViewerObject::LL_VO_WATER:
- glColor4f(0,0.5f,1,1);
- break;
- case LL_PCODE_LEGACY_TREE:
- glColor4f(0,0.5f,0,1);
- default:
- glColor4f(1,0,1,1);
- break;
- }
- }
- else
- {
- glColor4f(1,0,0,1);
- }
-
-
- const LLVector3* ext = drawable->getSpatialExtents();
-
- LLVector3 pos = (ext[0] + ext[1]) * 0.5f;
- LLVector3 size = (ext[1] - ext[0]) * 0.5f;
-
- LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
- LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
- LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
- LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
-
- glBegin(GL_LINE_LOOP); //top
- glVertex3fv((pos+v1).mV);
- glVertex3fv((pos+v2).mV);
- glVertex3fv((pos+v3).mV);
- glVertex3fv((pos+v4).mV);
- glEnd();
-
- glBegin(GL_LINE_LOOP); //bottom
- glVertex3fv((pos-v1).mV);
- glVertex3fv((pos-v2).mV);
- glVertex3fv((pos-v3).mV);
- glVertex3fv((pos-v4).mV);
- glEnd();
-
-
- glBegin(GL_LINES);
-
- //right
- glVertex3fv((pos+v1).mV);
- glVertex3fv((pos-v3).mV);
-
- glVertex3fv((pos+v4).mV);
- glVertex3fv((pos-v2).mV);
-
- //left
- glVertex3fv((pos+v2).mV);
- glVertex3fv((pos-v4).mV);
-
- glVertex3fv((pos+v3).mV);
- glVertex3fv((pos-v1).mV);
-
- glEnd();
-
- //render space partition trace
- glBegin(GL_LINE_STRIP);
- glColor4f(1,0,0,1);
- glVertex3fv(pos.mV);
- glColor4f(0,1,0,1);
- glVertex3dv(drawable->getPositionGroup().mdV);
- glColor4f(0,0,1,1);
- glVertex3fv(nodeCenter.mV);
- glColor4f(1,1,0,1);
- glVertex3fv(octCenter.mV);
- glEnd();
+ renderBoundingBox(drawable);
}
- if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_CHAINS | LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
+ if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
- glLineWidth(3);
-
- for (int face=0; face<drawable->getNumFaces(); ++face)
- {
- LLFace *facep = drawable->getFace(face);
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_CHAINS))
- {
- LLGLDepthTest depth(GL_FALSE);
- if (facep->mNextFace)
- {
- glBegin(GL_LINE_STRIP);
-
- if (facep->isState(LLFace::GLOBAL))
- {
- glColor4f(0,1,0,1);
- }
- else
- {
- glColor4f(1,0.5f,0.25f,1);
- }
-
- if (drawable->isActive())
- {
- glVertex3fv(facep->mCenterLocal.mV);
- glVertex3fv(facep->mNextFace->mCenterLocal.mV);
- }
- else
- {
- glVertex3fv(facep->mCenterAgent.mV);
- glVertex3fv(facep->mNextFace->mCenterAgent.mV);
- }
-
- glEnd();
- }
- else
- {
- glPointSize(5);
- glBegin(GL_POINTS);
-
- if (!facep->isState(LLFace::GLOBAL))
- {
- glColor4f(1,0.75f,0,1);
- glVertex3fv(facep->mCenterLocal.mV);
- }
- else
- {
- glColor4f(0,0.75f,1,1);
- glVertex3fv(facep->mCenterAgent.mV);
- }
-
- glEnd();
- glPointSize(1);
- }
- }
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
- {
- LLVector4 cold(0,0,0.25f);
- LLVector4 hot(1,0.25f,0.25f);
-
- LLVector4 boost_cold(0,0,0,0);
- LLVector4 boost_hot(0,1,0,1);
-
- LLGLDisable blend(GL_BLEND);
-
- LLViewerImage* imagep = facep->getTexture();
- if (imagep)
- {
-
- //F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
- F32 vsize = imagep->mMaxVirtualSize;
-
- if (vsize > sCurMaxTexPriority)
- {
- sCurMaxTexPriority = vsize;
- }
-
- F32 t = vsize/sLastMaxTexPriority;
-
- LLVector4 col = lerp(cold, hot, t);
- glColor4fv(col.mV);
- }
- else
- {
- glColor4f(1,0,1,1);
- }
-
- LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f;
- LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f);
- drawBox(center, size);
-
- S32 boost = imagep->getBoostLevel();
- if (boost)
- {
- F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
- LLVector4 col = lerp(boost_cold, boost_hot, t);
- LLGLEnable blend_on(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glColor4fv(col.mV);
- drawBox(center, size);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- }
- }
+ renderTexturePriority(drawable);
}
-
+
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS))
{
- glPointSize(4);
- glColor4f(1,1,1,1);
- glBegin(GL_POINTS);
- S32 num_faces = drawable->getNumFaces();
- for (S32 i = 0; i < num_faces; i++)
- {
- LLStrider<LLVector3> vertices;
- drawable->getFace(i)->getVertices(vertices);
-
- LLFace* face = drawable->getFace(i);
-
- for (S32 v = 0; v < (S32)drawable->getFace(i)->getGeomCount(); v++)
- {
- if (!face->getDrawable()->isActive())
- {
- //glVertex3fv(vertices[v].mV);
- }
- else
- {
- glVertex3fv((vertices[v]*face->getRenderMatrix()).mV);
- }
- }
- }
- glEnd();
- glPointSize(1);
+ renderPoints(drawable);
}
-
- glLineWidth(1);
}
}
};
@@ -2077,7 +2670,6 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_OCCLUSION |
LLPipeline::RENDER_DEBUG_BBOXES |
LLPipeline::RENDER_DEBUG_POINTS |
- LLPipeline::RENDER_DEBUG_FACE_CHAINS |
LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
return;
@@ -2086,7 +2678,7 @@ void LLSpatialPartition::renderDebug()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
//sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds);
- sLastMaxTexPriority = sCurMaxTexPriority;
+ sLastMaxTexPriority = (F32) gCamera->getScreenPixelArea();
sCurMaxTexPriority = 0.f;
}
@@ -2100,78 +2692,50 @@ void LLSpatialPartition::renderDebug()
LLOctreeRenderNonOccluded render_debug;
render_debug.traverse(mOctree);
-
- LLGLDisable cull_face(GL_CULL_FACE);
- {
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- //draw frustum
- glColor4f(0,0,1,0.5f);
- glBegin(GL_QUADS);
- //glVertex3fv(gCamera->mAgentFrustum[0].mV);
- //glVertex3fv(gCamera->mAgentFrustum[1].mV);
- //glVertex3fv(gCamera->mAgentFrustum[2].mV);
- //glVertex3fv(gCamera->mAgentFrustum[3].mV);
+ LLGLDisable cull_face(GL_CULL_FACE);
- //glVertex3fv(gCamera->mAgentFrustum[4].mV);
- //glVertex3fv(gCamera->mAgentFrustum[5].mV);
- //glVertex3fv(gCamera->mAgentFrustum[6].mV);
- //glVertex3fv(gCamera->mAgentFrustum[7].mV);
-
- glVertex3fv(gCamera->mAgentFrustum[0].mV);
- glVertex3fv(gCamera->mAgentFrustum[1].mV);
- glVertex3fv(gCamera->mAgentFrustum[5].mV);
- glVertex3fv(gCamera->mAgentFrustum[4].mV);
-
- glVertex3fv(gCamera->mAgentFrustum[1].mV);
- glVertex3fv(gCamera->mAgentFrustum[2].mV);
- glVertex3fv(gCamera->mAgentFrustum[6].mV);
- glVertex3fv(gCamera->mAgentFrustum[5].mV);
-
- glVertex3fv(gCamera->mAgentFrustum[2].mV);
- glVertex3fv(gCamera->mAgentFrustum[3].mV);
- glVertex3fv(gCamera->mAgentFrustum[7].mV);
- glVertex3fv(gCamera->mAgentFrustum[6].mV);
-
- glVertex3fv(gCamera->mAgentFrustum[3].mV);
- glVertex3fv(gCamera->mAgentFrustum[0].mV);
- glVertex3fv(gCamera->mAgentFrustum[4].mV);
- glVertex3fv(gCamera->mAgentFrustum[7].mV);
-
- glEnd();
- }
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && !mOccludedList.empty() &&
+ mOcclusionIndices.notNull())
{
LLGLDisable fog(GL_FOG);
LLGLDepthTest gls_depth(GL_FALSE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ mOcclusionIndices->setBuffer(0);
+ U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer();
+
+ LLGLEnable blend(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ LLGLEnable cull(GL_CULL_FACE);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- for (std::vector<LLSpatialGroup*>::iterator i = mOccludedList.begin(); i != mOccludedList.end(); ++i)
+ for (U32 i = 0; i < mOccludedList.size(); i++)
{ //draw occluded nodes
- LLSpatialGroup* node = *i;
- if (node->isDead())
+ LLSpatialGroup* node = mOccludedList[i];
+ if (node->isDead() ||
+ !node->isState(LLSpatialGroup::OCCLUDED) ||
+ node->mOcclusionVerts.isNull())
{
continue;
}
- if (!node->isState(LLSpatialGroup::OCCLUDED))
+
+ node->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
{
- continue;
+ LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
+ glColor4f(0.5, 0.5f, 0, 0.25f);
+ glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
+ GL_UNSIGNED_INT, indicesp);
}
- else
+
{
- glColor4f(0.25f,0.125f,0.1f,0.125f);
+ LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
+ glColor4f(0.0,1.0f,1.0f,1.0f);
+ glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
+ GL_UNSIGNED_INT, indicesp);
}
- LLVector3 c;
- LLVector3 r;
-
- c = node->mBounds[0];
- r = node->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.01f,0.01f,0.01f);;
-
- drawBox(c,r);
}
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
@@ -2253,3 +2817,19 @@ LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVec
collision.setVec(pick.mEnd);
return ret;
}
+
+LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset,
+ LLViewerImage* texture, LLVertexBuffer* buffer,
+ BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
+: mStart(start), mEnd(end), mCount(count), mOffset(offset),
+ mTexture(texture), mVertexBuffer(buffer),
+ mFullbright(fullbright), mBump(bump),
+ mParticle(particle), mPartSize(part_size),
+ mVSize(0.f), mTextureMatrix(NULL)
+{
+}
+
+LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
+{
+ return new LLVertexBuffer(type_mask, usage);
+}
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 012e3a9e82..10312ba0e6 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -14,26 +14,76 @@
#include "llmemory.h"
#include "lldrawable.h"
#include "lloctree.h"
+#include "llvertexbuffer.h"
#include "llgltypes.h"
+#include "llcubemap.h"
#include <queue>
-class LLCullInfo
+#define SG_STATE_INHERIT_MASK (CULLED | OCCLUDED)
+#define SG_INITIAL_STATE_MASK (OCCLUSION_DIRTY | DIRTY | GEOM_DIRTY)
+
+class LLSpatialPartition;
+class LLSpatialBridge;
+
+class LLDrawInfo
{
public:
- LLVector3 mPos;
- F32 mRadius;
- LLPointer<LLDrawable> mDrawablep;
-};
+ LLDrawInfo(U32 start, U32 end, U32 count, U32 offset,
+ LLViewerImage* image, LLVertexBuffer* buffer,
+ BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0);
+
+ LLPointer<LLVertexBuffer> mVertexBuffer;
+ LLPointer<LLViewerImage> mTexture;
+ LLPointer<LLCubeMap> mReflectionMap;
+ const LLMatrix4* mTextureMatrix;
+ U32 mStart;
+ U32 mEnd;
+ U32 mCount;
+ U32 mOffset;
+ BOOL mFullbright;
+ U8 mBump;
+ BOOL mParticle;
+ F32 mPartSize;
+ F32 mVSize;
+
+ struct CompareTexture
+ {
+ bool operator()(const LLDrawInfo& lhs, const LLDrawInfo& rhs)
+ {
+ return lhs.mTexture > rhs.mTexture;
+ }
+ };
-#define SG_STATE_INHERIT_MASK (CULLED | OCCLUDED)
-class LLSpatialPartition;
+ struct CompareTexturePtr
+ {
+ bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs)
+ {
+
+ return lhs == NULL || rhs == NULL || lhs->mTexture > rhs->mTexture;
+ }
+ };
+
+ struct CompareBump
+ {
+ bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs)
+ {
+ return lhs == NULL || rhs == NULL || lhs->mBump > rhs->mBump;
+ }
+ };
+};
class LLSpatialGroup : public LLOctreeListener<LLDrawable>
{
friend class LLSpatialPartition;
public:
+ typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t;
+ typedef std::set<LLPointer<LLSpatialGroup> > sg_set_t;
+ typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t;
+ typedef std::map<U32, std::vector<LLDrawInfo*> > draw_map_t;
+ typedef std::map<LLPointer<LLViewerImage>, LLPointer<LLVertexBuffer> > buffer_map_t;
+
typedef LLOctreeListener<LLDrawable> BaseType;
typedef LLOctreeListener<LLDrawable> OctreeListener;
typedef LLTreeNode<LLDrawable> TreeNode;
@@ -41,6 +91,24 @@ public:
typedef LLOctreeRoot<LLDrawable> OctreeRoot;
typedef LLOctreeState<LLDrawable> OctreeState;
typedef LLOctreeTraveler<LLDrawable> OctreeTraveler;
+ typedef LLOctreeState<LLDrawable>::element_iter element_iter;
+ typedef LLOctreeState<LLDrawable>::element_list element_list;
+
+ struct CompareDistanceGreater
+ {
+ bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs)
+ {
+ return lhs->mDistance > rhs->mDistance;
+ }
+ };
+
+ struct CompareDepthGreater
+ {
+ bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs)
+ {
+ return lhs->mDepth > rhs->mDepth;
+ }
+ };
typedef enum
{
@@ -56,10 +124,18 @@ public:
RESHADOW_QUEUE = 0x00000200,
DIRTY = 0x00000400,
OBJECT_DIRTY = 0x00000800,
- DISCARD_QUERY = 0x00001000,
- QUERY_OUT = 0x00002000,
- OCCLUDING = 0x00004000,
- SKIP_FRUSTUM_CHECK = 0x00008000,
+ GEOM_DIRTY = 0x00001000,
+ MATRIX_DIRTY = 0x00002000,
+ ALPHA_DIRTY = 0x00004000,
+ DISCARD_QUERY = 0x00008000,
+ QUERY_OUT = 0x00010000,
+ OCCLUDING = 0x00020000,
+ SKIP_FRUSTUM_CHECK = 0x00040000,
+ OCCLUSION_DIRTY = 0x00080000,
+ BELOW_WATER = 0x00100000,
+ IN_GEOMETRY_QUEUE = 0x00200000,
+ IN_IMAGE_QUEUE = 0x00400000,
+ IMAGE_DIRTY = 0x00800000,
} eSpatialState;
typedef enum
@@ -73,17 +149,19 @@ public:
BOOL safeToDelete();
virtual ~LLSpatialGroup();
- S32 getCount() const { return mObjects.size(); }
BOOL isDead() { return isState(DEAD); }
BOOL isState(U32 state) const { return mState & state ? TRUE : FALSE; }
U32 getState() { return mState; }
void setState(U32 state) { mState |= state; }
void clearState(U32 state) { mState &= ~state; }
+ void clearDrawMap();
void validate();
-
+ void validateDrawMap();
+
void setState(U32 state, S32 mode);
+ LLSpatialGroup* getParent();
void clearState(U32 state, S32 mode);
BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE);
@@ -94,8 +172,15 @@ public:
BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax);
void unbound();
BOOL rebound();
+
+ void updateDistance(LLCamera& camera);
BOOL changeLOD();
-
+ void rebuildGeom();
+ void makeStatic();
+
+ void dirtyGeom() { setState(GEOM_DIRTY); }
+ element_list& getData() { return mOctreeNode->getOctState()->getData(); }
+
//LISTENER FUNCTIONS
virtual void handleInsertion(const TreeNode* node, LLDrawable* face);
virtual void handleRemoval(const TreeNode* node, LLDrawable* face);
@@ -105,12 +190,15 @@ public:
virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child);
protected:
- std::vector<LLCullInfo> mObjects;
U32 mState;
S32 mLODHash;
static S32 sLODSeed;
public:
+ bridge_list_t mBridgeList;
+ buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture
+
+ F32 mBuilt;
OctreeNode* mOctreeNode;
LLSpatialPartition* mSpatialPartition;
LLVector3 mBounds[2];
@@ -118,69 +206,132 @@ public:
LLVector3 mObjectExtents[2];
LLVector3 mObjectBounds[2];
+ LLPointer<LLVertexBuffer> mVertexBuffer;
+ LLPointer<LLVertexBuffer> mOcclusionVerts;
+ LLPointer<LLCubeMap> mReflectionMap;
+
+ U32 mBufferUsage;
+ draw_map_t mDrawMap;
+
+ U32 mVertexCount;
+ U32 mIndexCount;
+ F32 mDistance;
+ F32 mDepth;
+ F32 mLastUpdateDistance;
+ F32 mLastUpdateTime;
+ F32 mLastAddTime;
+ F32 mLastRenderTime;
+
+ LLVector3 mViewAngle;
+ LLVector3 mLastUpdateViewAngle;
+
+ F32 mPixelArea;
+ F32 mRadius;
};
-class LLSpatialPartition
+class LLGeometryManager
{
public:
- LLSpatialPartition();
+ std::vector<LLFace*> mFaceList;
+ virtual ~LLGeometryManager() { }
+ virtual void rebuildGeom(LLSpatialGroup* group) = 0;
+ virtual void getGeometry(LLSpatialGroup* group) = 0;
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count);
+ virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
+};
+
+class LLSpatialPartition: public LLGeometryManager
+{
+public:
+ LLSpatialPartition(U32 data_mask, BOOL is_volatile = FALSE, U32 mBufferUsage = GL_STATIC_DRAW_ARB);
virtual ~LLSpatialPartition();
- LLSpatialGroup *put(LLDrawable *drawablep);
+ LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
BOOL remove(LLDrawable *drawablep, LLSpatialGroup *curp);
LLDrawable* pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision);
// If the drawable moves, move it here.
virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE);
- void shift(const LLVector3 &offset);
+ virtual void shift(const LLVector3 &offset);
+
+ virtual F32 calcDistance(LLSpatialGroup* group, LLCamera& camera);
+ virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera);
+
+ virtual void rebuildGeom(LLSpatialGroup* group);
S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum
BOOL checkOcclusion(LLSpatialGroup* group, LLCamera* camera);
+ void markReimage(LLSpatialGroup* group);
+ void processGeometry(LLCamera* camera);
+ void processImagery(LLCamera* camera);
void processOcclusion(LLCamera* camera);
+ void buildOcclusion();
void doOcclusion(LLCamera* camera);
BOOL isVisible(const LLVector3& v);
-
+ BOOL isVolatile() const { return mVolatile; }
+
+ virtual LLSpatialBridge* asBridge() { return NULL; }
S32 getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results );
S32 getLights(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results );
void renderDebug();
void restoreGL();
+ void resetVertexBuffers();
protected:
S32 getDrawables(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results, BOOL get_lights );
- LLSpatialGroup *mLastAddedGroupp;
-
- typedef std::set<LLSpatialGroup*> spatial_group_set_t;
+ typedef std::set<LLPointer<LLSpatialGroup> > spatial_group_set_t;
spatial_group_set_t mSpatialGroups;
//things that might be occluded
- std::queue<LLSpatialGroup*> mOcclusionQueue;
+ typedef std::queue<LLPointer<LLSpatialGroup> > spatial_group_queue_t;
+ spatial_group_queue_t mOcclusionQueue;
+
+ //things that need a terse update
+ spatial_group_queue_t mUpdateQueue;
+
+ //things that need an image update
+ spatial_group_queue_t mImageQueue;
//things awaiting query
- std::queue<LLSpatialGroup*> mQueryQueue;
+ spatial_group_queue_t mQueryQueue;
std::vector<LLGLuint> mOcclusionQueries;
public:
LLSpatialGroup::OctreeNode* mOctree;
- //things that are occluded
- std::vector<LLSpatialGroup*> mOccludedList;
-
- std::queue<LLSpatialGroup*> mReshadowQueue;
+ U32 mBufferUsage;
+ BOOL mRenderByGroup;
+ BOOL mImageEnabled;
+ U32 mLODSeed;
+ U32 mLODPeriod;
+ U32 mVertexDataMask;
+ F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25);
+ BOOL mVolatile; //if TRUE, occlusion queries will be discarded when nodes change size
+ BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
+ U32 mDrawableType;
+ U32 mPartitionType;
+
+ //index buffer for occlusion verts
+ LLPointer<LLVertexBuffer> mOcclusionIndices;
+ //things that are occluded
+ std::vector<LLPointer<LLSpatialGroup> > mOccludedList;
};
// class for creating bridges between spatial partitions
class LLSpatialBridge : public LLDrawable, public LLSpatialPartition
{
public:
- LLSpatialBridge(LLDrawable* root);
+ typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t;
+
+ LLSpatialBridge(LLDrawable* root, U32 data_mask);
virtual ~LLSpatialBridge();
- virtual BOOL isSpatialBridge() const { return TRUE; }
+ virtual BOOL isSpatialBridge() const { return TRUE; }
virtual void updateSpatialExtents();
virtual void updateBinRadius();
@@ -193,11 +344,123 @@ public:
virtual void shiftPos(const LLVector3& vec);
virtual void cleanupReferences();
virtual LLSpatialPartition* asPartition() { return this; }
- LLCamera transformCamera(LLCamera& camera);
+ virtual LLSpatialBridge* asBridge() { return this; }
+
+ virtual LLCamera transformCamera(LLCamera& camera);
LLDrawable* mDrawable;
};
+//spatial partition for water (implemented in LLVOWater.cpp)
+class LLWaterPartition : public LLSpatialPartition
+{
+public:
+ LLWaterPartition();
+ virtual void getGeometry(LLSpatialGroup* group) { }
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
+};
+
+//spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp)
+class LLTerrainPartition : public LLSpatialPartition
+{
+public:
+ LLTerrainPartition();
+ virtual void getGeometry(LLSpatialGroup* group);
+ virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
+};
+
+//spatial partition for trees
+class LLTreePartition : public LLSpatialPartition
+{
+public:
+ LLTreePartition();
+ virtual void getGeometry(LLSpatialGroup* group) { }
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
+
+};
+
+//spatial partition for particles (implemented in LLVOPartGroup.cpp)
+class LLParticlePartition : public LLSpatialPartition
+{
+public:
+ LLParticlePartition();
+ virtual void getGeometry(LLSpatialGroup* group);
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count);
+ virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera);
+protected:
+ U32 mRenderPass;
+};
+
+//spatial partition for grass (implemented in LLVOGrass.cpp)
+class LLGrassPartition : public LLParticlePartition
+{
+public:
+ LLGrassPartition();
+};
+
+//spatial partition for clouds (implemented in LLVOClouds.cpp)
+class LLCloudPartition : public LLParticlePartition
+{
+public:
+ LLCloudPartition();
+};
+
+//class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp)
+class LLVolumeGeometryManager: public LLGeometryManager
+{
+public:
+ virtual ~LLVolumeGeometryManager() { }
+ virtual void rebuildGeom(LLSpatialGroup* group);
+ virtual void getGeometry(LLSpatialGroup* group);
+ void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
+};
+
+//spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
+class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager
+{
+public:
+ LLVolumePartition();
+ virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); }
+ virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); }
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); }
+};
+
+//spatial bridge that uses volume geometry manager (implemented in LLVOVolume.cpp)
+class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager
+{
+public:
+ LLVolumeBridge(LLDrawable* drawable);
+ virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); }
+ virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); }
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); }
+};
+
+class LLHUDBridge : public LLVolumeBridge
+{
+public:
+ LLHUDBridge(LLDrawable* drawablep);
+ virtual void shiftPos(const LLVector3& vec);
+ virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera);
+};
+
+//spatial partition that holds nothing but spatial bridges
+class LLBridgePartition : public LLSpatialPartition
+{
+public:
+ LLBridgePartition();
+ virtual void getGeometry(LLSpatialGroup* group) { }
+ virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
+};
+
+class LLHUDPartition : public LLBridgePartition
+{
+public:
+ LLHUDPartition();
+ virtual void shift(const LLVector3 &offset);
+};
+
+void validate_draw_info(LLDrawInfo& params);
+
extern const F32 SG_BOX_SIDE;
extern const F32 SG_BOX_OFFSET;
extern const F32 SG_BOX_RAD;
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index e614134080..d253271b52 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -75,14 +75,7 @@ void LLSprite::updateFace(LLFace &face)
// First, figure out how many vertices/indices we need.
U32 num_vertices, num_indices;
U32 vertex_count = 0;
-
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> tex_coordsp;
- U32 *indicesp;
- S32 index_offset;
-
+
// Get the total number of vertices and indices
if (mFollow)
{
@@ -95,14 +88,7 @@ void LLSprite::updateFace(LLFace &face)
num_indices = 12;
}
- // Setup face
- face.setPrimType(LLTriangles);
face.setSize(num_vertices, num_indices);
- index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp);
- if (-1 == index_offset)
- {
- return;
- }
if (mFollow)
{
@@ -187,7 +173,30 @@ void LLSprite::updateFace(LLFace &face)
}
face.setFaceColor(mColor);
-
+
+ LLStrider<LLVector3> verticesp;
+ LLStrider<LLVector3> normalsp;
+ LLStrider<LLVector2> tex_coordsp;
+ LLStrider<U32> indicesp;
+ S32 index_offset;
+
+ // Setup face
+ if (face.mVertexBuffer.isNull())
+ {
+ face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD,
+ GL_STREAM_DRAW_ARB);
+ face.mVertexBuffer->allocateBuffer(4, 12, TRUE);
+ face.setGeomIndex(0);
+ face.setIndicesIndex(0);
+ }
+
+ index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp);
+ if (-1 == index_offset)
+ {
+ return;
+ }
+
*tex_coordsp = LLVector2(0.f, 0.f);
*verticesp = mC;
tex_coordsp++;
@@ -232,6 +241,7 @@ void LLSprite::updateFace(LLFace &face)
*indicesp++ = 3 + index_offset;
}
+ //face.mVertexBuffer->setBuffer(0);
face.mCenterAgent = mPosition;
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 04b5fe7340..421e836f93 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -99,6 +99,8 @@
#include "llsky.h"
#include "llstatview.h"
#include "llsurface.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
#include "lltoolmgr.h"
#include "llui.h"
#include "llurlwhitelist.h"
@@ -167,7 +169,6 @@ const char* SCREEN_LAST_FILENAME = "screen_last.bmp";
//
// Imported globals
//
-extern LLPointer<LLImageGL> gStartImageGL;
extern S32 gStartImageWidth;
extern S32 gStartImageHeight;
extern std::string gSerialNumber;
@@ -176,6 +177,8 @@ extern std::string gSerialNumber;
// local globals
//
+LLPointer<LLImageGL> gStartImageGL;
+
static LLHost gAgentSimHost;
static BOOL gSkipOptionalUpdate = FALSE;
@@ -234,7 +237,13 @@ public:
}
};
-
+void update_texture_fetch()
+{
+ gTextureCache->update(1); // unpauses the texture cache thread
+ gImageDecodeThread->update(1); // unpauses the image thread
+ gTextureFetch->update(1); // unpauses the texture fetch thread
+ gImageList.updateImages(0.10f);
+}
// Returns FALSE to skip other idle processing. Should only return
// TRUE when all initialization done.
@@ -285,8 +294,6 @@ BOOL idle_startup()
static BOOL samename = FALSE;
- static BOOL did_precache = FALSE;
-
BOOL do_normal_idle = FALSE;
// HACK: These are things from the main loop that usually aren't done
@@ -1590,6 +1597,8 @@ BOOL idle_startup()
args["[ERROR_MESSAGE]"] = emsg.str();
gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
gStartupState = STATE_LOGIN_SHOW;
+ gAutoLogin = FALSE;
+ show_connect_box = TRUE;
}
}
else
@@ -1605,6 +1614,8 @@ BOOL idle_startup()
args["[ERROR_MESSAGE]"] = emsg.str();
gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
gStartupState = STATE_LOGIN_SHOW;
+ gAutoLogin = FALSE;
+ show_connect_box = TRUE;
}
return do_normal_idle;
}
@@ -1637,6 +1648,9 @@ BOOL idle_startup()
//
// Initialize classes w/graphics stuff.
//
+ gImageList.doPrefetchImages();
+ update_texture_fetch();
+
LLSurface::initClasses();
LLFace::initClass();
@@ -1799,7 +1813,7 @@ BOOL idle_startup()
llinfos << "Decoding images..." << llendl;
// For all images pre-loaded into viewer cache, decode them.
// Need to do this AFTER we init the sky
- gImageList.decodeAllImages();
+ gImageList.decodeAllImages(2.f);
gStartupState++;
// JC - Do this as late as possible to increase likelihood Purify
@@ -2368,18 +2382,6 @@ BOOL idle_startup()
if (STATE_PRECACHE == gStartupState)
{
do_normal_idle = TRUE;
- if (!did_precache)
- {
- did_precache = TRUE;
- // Don't preload map information! The amount of data for all the
- // map items (icons for classifieds, avatar locations, etc.) is
- // huge, and not throttled. This overflows the downstream
- // pipe during startup, when lots of information is being sent.
- // The problem manifests itself as invisible avatars on login. JC
- //gWorldMap->setCurrentLayer(0); // pre-load layer 0 of the world map
-
- gImageList.doPreloadImages(); // pre-load some images from static VFS
- }
F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
// wait precache-delay and for agent's avatar or a lot longer.
@@ -2390,6 +2392,7 @@ BOOL idle_startup()
}
else
{
+ update_texture_fetch();
set_startup_status(0.50f + 0.50f * timeout_frac, "Precaching...",
gAgent.mMOTD.c_str());
}
@@ -2418,6 +2421,7 @@ BOOL idle_startup()
}
else
{
+ update_texture_fetch();
set_startup_status(0.f + 0.25f * wearables_time / MAX_WEARABLES_TIME,
"Downloading clothing...",
gAgent.mMOTD.c_str());
@@ -2520,34 +2524,6 @@ BOOL idle_startup()
// local function definition
//
-void unsupported_graphics_callback(S32 option, void* userdata)
-{
- if (0 == option)
- {
- llinfos << "User cancelled after driver check" << llendl;
- std::string help_path;
- help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
- "unsupported_card.html");
- app_force_quit( help_path.c_str() );
- }
-
- LLPanelLogin::giveFocus();
-}
-
-void check_driver_callback(S32 option, void* userdata)
-{
- if (0 == option)
- {
- llinfos << "User cancelled after driver check" << llendl;
- std::string help_path;
- help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
- "graphics_driver_update.html");
- app_force_quit( help_path.c_str() );
- }
-
- LLPanelLogin::giveFocus();
-}
-
void login_show()
{
LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(),
@@ -2555,7 +2531,7 @@ void login_show()
login_callback, NULL );
// Make sure all the UI textures are present and decoded.
- gImageList.decodeAllImages();
+ gImageList.decodeAllImages(2.f);
if( USERSERVER_OTHER == gUserServerChoice )
{
@@ -3027,8 +3003,8 @@ void use_circuit_callback(void**, S32 result)
void register_viewer_callbacks(LLMessageSystem* msg)
{
msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
- msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImage::receiveImage );
- msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImage::receiveImagePacket );
+ msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImageList::receiveImageHeader );
+ msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImageList::receiveImagePacket );
msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
@@ -3869,7 +3845,7 @@ void dialog_choose_gender_first_start()
// location_id = 1 => home position
void init_start_screen(S32 location_id)
{
- if (gStartImageGL)
+ if (gStartImageGL.notNull())
{
gStartImageGL = NULL;
llinfos << "re-initializing start screen" << llendl;
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index c7b3bc13d5..e5952f4f5b 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -9,10 +9,13 @@
#ifndef LL_LLSTARTUP_H
#define LL_LLSTARTUP_H
+#include "llimagegl.h"
+
// functions
BOOL idle_startup();
void cleanup_app();
LLString load_password_from_disk();
+void release_start_screen();
// constants, variables, & enumerations
extern const char* SCREEN_HOME_FILENAME;
@@ -59,6 +62,7 @@ enum EStartupState{
// exorted symbol
extern S32 gStartupState;
extern bool gQuickTimeInitialized;
+extern LLPointer<LLImageGL> gStartImageGL;
class LLStartUp
{
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index fc0c46bbe1..4087f7f96c 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -31,7 +31,7 @@
#include "noise.h"
#include "llviewercamera.h"
#include "llglheaders.h"
-#include "lldrawpool.h"
+#include "lldrawpoolterrain.h"
#include "lldrawable.h"
extern LLPipeline gPipeline;
@@ -101,7 +101,7 @@ LLSurface::~LLSurface()
mNumberOfPatches = 0;
destroyPatchData();
- LLDrawPool *poolp = gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep);
+ LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep);
if (!poolp)
{
llwarns << "No pool for terrain on destruction!" << llendl;
@@ -312,7 +312,6 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global)
LLVector3d water_origin_global(x, y, z);
mWaterObjp->setPositionGlobal(water_origin_global);
- gPipeline.markMoved(mWaterObjp->mDrawable);
}
}
@@ -602,45 +601,45 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent)
}
}
-
-
-BOOL LLSurface::idleUpdate()
+BOOL LLSurface::idleUpdate(F32 max_update_time)
{
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
{
- return TRUE;
+ return FALSE;
}
// Perform idle time update of non-critical stuff.
// In this case, texture and normal updates.
LLTimer update_timer;
- LLSurfacePatch *patchp = NULL;
+ BOOL did_update = FALSE;
// If the Z height data has changed, we need to rebuild our
// property line vertex arrays.
- if (mDirtyPatchList.count() > 0)
+ if (mDirtyPatchList.size() > 0)
{
getRegion()->dirtyHeights();
}
- S32 i = 0;
- while (i < mDirtyPatchList.count())
+ // Always call updateNormals() / updateVerticalStats()
+ // every frame to avoid artifacts
+ for(std::set<LLSurfacePatch *>::iterator iter = mDirtyPatchList.begin();
+ iter != mDirtyPatchList.end(); )
{
- patchp = mDirtyPatchList[i];
+ std::set<LLSurfacePatch *>::iterator curiter = iter++;
+ LLSurfacePatch *patchp = *curiter;
patchp->updateNormals();
patchp->updateVerticalStats();
-
- if ((update_timer.getElapsedTimeF32() < 0.05f) && patchp->updateTexture())
- {
- patchp->clearDirty();
- mDirtyPatchList.remove(i);
- }
- else
+ if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time)
{
- i++;
+ if (patchp->updateTexture())
+ {
+ did_update = TRUE;
+ patchp->clearDirty();
+ mDirtyPatchList.erase(curiter);
+ }
}
}
- return TRUE;
+ return did_update;
}
// TODO -- move this to LLViewerRegion class
@@ -1210,10 +1209,7 @@ void LLSurface::dirtyAllPatches()
void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp)
{
// Put surface patch on dirty surface patch list
- if (-1 == mDirtyPatchList.find(patchp))
- {
- mDirtyPatchList.put(patchp);
- }
+ mDirtyPatchList.insert(patchp);
}
diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h
index 7698c272ab..ca22535542 100644
--- a/indra/newview/llsurface.h
+++ b/indra/newview/llsurface.h
@@ -22,7 +22,6 @@
#include "llvowater.h"
#include "llpatchvertexarray.h"
-#include "lldarray.h"
#include "llviewerimage.h"
class LLTimer;
@@ -96,7 +95,7 @@ public:
LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const;
// Update methods (called during idle, normally)
- BOOL idleUpdate();
+ BOOL idleUpdate(F32 max_update_time);
void renderSurfaceBounds();
@@ -181,7 +180,7 @@ protected:
// Array of grid normals, mGridsPerEdge * mGridsPerEdge
LLVector3 *mNorm;
- LLDynamicArray<LLSurfacePatch *> mDirtyPatchList;
+ std::set<LLSurfacePatch *> mDirtyPatchList;
// The textures should never be directly initialized - use the setter methods!
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index ac0add8ae3..4be7cf41e7 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -794,7 +794,7 @@ void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32
void LLSurfacePatch::updateVisibility()
{
- if (mVObjp == (LLVOSurfacePatch*)NULL)
+ if (mVObjp.isNull())
{
return;
}
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
new file mode 100644
index 0000000000..13efadf213
--- /dev/null
+++ b/indra/newview/lltexturecache.cpp
@@ -0,0 +1,1365 @@
+/**
+ * @file texturecache.cpp
+ * @brief Object which handles local texture caching
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltexturecache.h"
+
+#include "llapr.h"
+#include "lldir.h"
+#include "llimage.h"
+#include "lllfsthread.h"
+#include "llviewercontrol.h"
+
+#define USE_LFS_READ 0
+#define USE_LFS_WRITE 0
+
+// Note: first 4 bytes store file size, rest is j2c data
+const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024;
+
+class LLTextureCacheWorker : public LLWorkerClass
+{
+ friend class LLTextureCache;
+
+private:
+ enum e_state
+ {
+ INIT = 0,
+ LOCAL = 1,
+ CACHE = 2,
+ HEADER = 3,
+ BODY = 4
+ };
+
+ class ReadResponder : public LLLFSThread::Responder
+ {
+ public:
+ ReadResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
+ ~ReadResponder() {}
+ void completed(S32 bytes)
+ {
+ mCache->lockWorkers();
+ LLTextureCacheWorker* reader = mCache->getReader(mHandle);
+ if (reader) reader->ioComplete(bytes);
+ mCache->unlockWorkers();
+ }
+ LLTextureCache* mCache;
+ LLTextureCacheWorker::handle_t mHandle;
+ };
+
+ class WriteResponder : public LLLFSThread::Responder
+ {
+ public:
+ WriteResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
+ ~WriteResponder() {}
+ void completed(S32 bytes)
+ {
+ mCache->lockWorkers();
+ LLTextureCacheWorker* writer = mCache->getWriter(mHandle);
+ if (writer) writer->ioComplete(bytes);
+ mCache->unlockWorkers();
+ }
+ LLTextureCache* mCache;
+ LLTextureCacheWorker::handle_t mHandle;
+ };
+
+public:
+ LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
+ U8* data, S32 datasize, S32 offset,
+ S32 imagesize, // for writes
+ LLTextureCache::Responder* responder)
+ : LLWorkerClass(cache, "LLTextureCacheWorker"),
+ mCache(cache),
+ mPriority(priority),
+ mID(id),
+ mState(INIT),
+ mReadData(NULL),
+ mWriteData(data),
+ mDataSize(datasize),
+ mOffset(offset),
+ mImageSize(imagesize),
+ mImageFormat(IMG_CODEC_J2C),
+ mImageLocal(FALSE),
+ mResponder(responder),
+ mFileHandle(LLLFSThread::nullHandle()),
+ mBytesToRead(0),
+ mBytesRead(0)
+ {
+ mPriority &= LLWorkerThread::PRIORITY_LOWBITS;
+ }
+ ~LLTextureCacheWorker()
+ {
+ llassert_always(!haveWork());
+ delete[] mReadData;
+ }
+
+ bool doRead();
+ bool doWrite();
+ virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
+
+ handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
+ handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
+ bool complete() { return checkWork(); }
+ void ioComplete(S32 bytes)
+ {
+ mBytesRead = bytes;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority);
+ }
+
+private:
+ virtual void startWork(S32 param); // called from addWork() (MAIN THREAD)
+ virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
+ virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
+
+private:
+ LLTextureCache* mCache;
+ U32 mPriority;
+ LLUUID mID;
+ e_state mState;
+
+ U8* mReadData;
+ U8* mWriteData;
+ S32 mDataSize;
+ S32 mOffset;
+ S32 mImageSize;
+ S32 mImageFormat;
+ BOOL mImageLocal;
+ LLPointer<LLTextureCache::Responder> mResponder;
+ LLLFSThread::handle_t mFileHandle;
+ S32 mBytesToRead;
+ LLAtomicS32 mBytesRead;
+};
+
+//virtual
+void LLTextureCacheWorker::startWork(S32 param)
+{
+}
+
+bool LLTextureCacheWorker::doRead()
+{
+ S32 local_size = 0;
+ std::string local_filename;
+
+ if (mState == INIT)
+ {
+ std::string filename = mCache->getLocalFileName(mID);
+ local_filename = filename + ".j2c";
+ local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+ if (local_size == 0)
+ {
+ local_filename = filename + ".tga";
+ local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+ if (local_size > 0)
+ {
+ mImageFormat = IMG_CODEC_TGA;
+ mDataSize = local_size; // Only a complete .tga file is valid
+ }
+ }
+ if (local_size > 0)
+ {
+ mState = LOCAL;
+ }
+ else
+ {
+ mState = CACHE;
+ }
+ }
+
+ if (mState == LOCAL)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ mImageLocal = TRUE;
+ mImageSize = local_size;
+ if (!mDataSize || mDataSize + mOffset > local_size)
+ {
+ mDataSize = local_size - mOffset;
+ }
+ if (mDataSize <= 0)
+ {
+ // no more data to read
+ mDataSize = 0;
+ return true;
+ }
+ mReadData = new U8[mDataSize];
+ mBytesRead = -1;
+ mBytesToRead = mDataSize;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "Error reading file from local cache: " << local_filename
+ << " Bytes: " << mDataSize << " Offset: " << mOffset
+ << " / " << mDataSize << llendl;
+ mDataSize = 0; // failed
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ if (!mDataSize || mDataSize > local_size)
+ {
+ mDataSize = local_size;
+ }
+ mReadData = new U8[mDataSize];
+ S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(),
+ mReadData, mOffset, mDataSize);
+ if (bytes_read != mDataSize)
+ {
+ llwarns << "Error reading file from local cache: " << local_filename
+ << " Bytes: " << mDataSize << " Offset: " << mOffset
+ << " / " << mDataSize << llendl;
+ mDataSize = 0;
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ else
+ {
+ mImageSize = local_size;
+ mImageLocal = TRUE;
+ }
+ return true;
+#endif
+ }
+
+ S32 idx = -1;
+
+ if (mState == CACHE)
+ {
+ llassert_always(mImageSize == 0);
+ idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize);
+ if (idx >= 0 && mImageSize > mOffset)
+ {
+ llassert_always(mImageSize > 0);
+ if (!mDataSize || mDataSize > mImageSize)
+ {
+ mDataSize = mImageSize;
+ }
+ mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ }
+ else
+ {
+ mDataSize = 0; // no data
+ return true;
+ }
+ }
+
+ if (mState == HEADER)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ llassert_always(mReadData == NULL);
+ mReadData = new U8[size];
+ mBytesRead = -1;
+ mBytesToRead = size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName,
+ mReadData, offset, mBytesToRead,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from header: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ return true; // done
+ }
+ else
+ {
+ mFileHandle = LLLFSThread::nullHandle();
+ mState = BODY;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ mReadData = new U8[size];
+ S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
+ mReadData, offset, size);
+ if (bytes_read != size)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from header: " << bytes_read
+ << " / " << size << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ return true; // done
+ }
+ else
+ {
+ mState = BODY;
+ }
+#endif
+ }
+
+ if (mState == BODY)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
+ if (filesize > mOffset)
+ {
+ S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
+ mDataSize = llmin(datasize, mDataSize);
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+
+ llassert_always(mDataSize > 0);
+ U8* data = new U8[mDataSize];
+ if (data_offset > 0)
+ {
+ llassert_always(mReadData);
+ llassert_always(data_offset <= mDataSize);
+ memcpy(data, mReadData, data_offset);
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ llassert_always(mReadData == NULL);
+ mReadData = data;
+
+ mBytesRead = -1;
+ mBytesToRead = file_size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ llassert_always(data_offset + mBytesToRead <= mDataSize);
+ mFileHandle = LLLFSThread::sLocal->read(filename,
+ mReadData + data_offset, file_offset, mBytesToRead,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
+ return true; // done
+ }
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from body: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ std::string filename = mCache->getTextureFileName(mID);
+ S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
+ S32 bytes_read = 0;
+ if (filesize > mOffset)
+ {
+ S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
+ mDataSize = llmin(datasize, mDataSize);
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+
+ U8* data = new U8[mDataSize];
+ if (data_offset > 0)
+ {
+ llassert_always(mReadData);
+ memcpy(data, mReadData, data_offset);
+ delete[] mReadData;
+ }
+ mReadData = data;
+ bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(),
+ mReadData + data_offset,
+ file_offset, file_size);
+ if (bytes_read != file_size)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from body: " << bytes_read
+ << " / " << file_size << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ }
+ else
+ {
+ mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
+ }
+
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+bool LLTextureCacheWorker::doWrite()
+{
+ S32 idx = -1;
+
+ if (mState == INIT)
+ {
+ llassert_always(mOffset == 0); // Currently don't support offsets
+ mState = CACHE;
+ }
+
+ // No LOCAL state for write()
+
+ if (mState == CACHE)
+ {
+ S32 cur_imagesize = 0;
+ S32 offset = mOffset;
+ idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize);
+ if (idx >= 0 && cur_imagesize > 0)
+ {
+ offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header
+ }
+ idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry
+ if (idx >= 0)
+ {
+ llassert_always(cur_imagesize <= 0 || mImageSize == cur_imagesize);
+ mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ }
+ else
+ {
+ mDataSize = -1; // failed
+ return true;
+ }
+ }
+
+ if (mState == HEADER)
+ {
+#if USE_LFS_WRITE
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ mBytesRead = -1;
+ mBytesToRead = size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName,
+ mWriteData, offset, mBytesToRead,
+ new WriteResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes written to header: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= mBytesToRead)
+ {
+ return true; // done
+ }
+ else
+ {
+ mFileHandle = LLLFSThread::nullHandle();
+ mState = BODY;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
+ mWriteData, offset, size);
+
+ if (bytes_written <= 0)
+ {
+ llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+
+ if (mDataSize <= size)
+ {
+ return true; // done
+ }
+ else
+ {
+ mState = BODY;
+ }
+#endif
+ }
+
+ if (mState == BODY)
+ {
+#if USE_LFS_WRITE
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+ if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ mBytesRead = -1;
+ mBytesToRead = file_size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->write(filename,
+ mWriteData + data_offset, file_offset, mBytesToRead,
+ new WriteResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ mDataSize = 0; // no data written
+ return true; // done
+ }
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes written to body: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+ S32 bytes_written = 0;
+ if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(),
+ mWriteData + data_offset,
+ file_offset, file_size);
+ if (bytes_written <= 0)
+ {
+ mDataSize = -1; // failed
+ }
+ }
+ else
+ {
+ mDataSize = 0; // no data written
+ }
+
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+//virtual
+bool LLTextureCacheWorker::doWork(S32 param)
+{
+ bool res = false;
+ if (param == 0) // read
+ {
+ res = doRead();
+ }
+ else if (param == 1) // write
+ {
+ res = doWrite();
+ }
+ else
+ {
+ llassert_always(0);
+ }
+ return res;
+}
+
+//virtual (WORKER THREAD)
+void LLTextureCacheWorker::finishWork(S32 param, bool completed)
+{
+ if (mResponder.notNull())
+ {
+ bool success = (completed && mDataSize > 0);
+ if (param == 0)
+ {
+ // read
+ if (success)
+ {
+ mResponder->setData(mReadData, mDataSize, mImageSize, mImageFormat, mImageLocal);
+ mReadData = NULL; // responder owns data
+ mDataSize = 0;
+ }
+ else
+ {
+ delete[] mReadData;
+ mReadData = NULL;
+
+ }
+ }
+ else
+ {
+ // write
+ mWriteData = NULL; // we never owned data
+ mDataSize = 0;
+ }
+ mResponder->completed(success);
+ }
+}
+
+//virtual (MAIN THREAD)
+void LLTextureCacheWorker::endWork(S32 param, bool aborted)
+{
+ if (aborted)
+ {
+ // Let the destructor handle any cleanup
+ return;
+ }
+ switch(param)
+ {
+ default:
+ case 0: // read
+ case 1: // write
+ {
+ if (mDataSize < 0)
+ {
+ // failed
+ mCache->removeFromCache(mID);
+ }
+ break;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLTextureCache::LLTextureCache(bool threaded)
+ : LLWorkerThread("TextureCache", threaded),
+ mWorkersMutex(getAPRPool()),
+ mHeaderMutex(getAPRPool()),
+ mFileAPRPool(NULL),
+ mReadOnly(FALSE),
+ mTexturesSizeTotal(0),
+ mDoPurge(FALSE)
+{
+ apr_pool_create(&mFileAPRPool, NULL);
+}
+
+LLTextureCache::~LLTextureCache()
+{
+ apr_pool_destroy(mFileAPRPool);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//virtual
+S32 LLTextureCache::update(U32 max_time_ms)
+{
+ S32 res;
+ res = LLWorkerThread::update(max_time_ms);
+
+ lockWorkers();
+ for (std::vector<handle_t>::iterator iter1 = mPrioritizeWriteList.begin();
+ iter1 != mPrioritizeWriteList.end(); ++iter1)
+ {
+ handle_t handle = *iter1;
+ handle_map_t::iterator iter2 = mWriters.find(handle);
+ if(iter2 != mWriters.end())
+ {
+ LLTextureCacheWorker* worker = iter2->second;
+ worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
+ }
+ }
+ mPrioritizeWriteList.clear();
+ unlockWorkers();
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+std::string LLTextureCache::getLocalFileName(const LLUUID& id)
+{
+ // Does not include extension
+ std::string idstr = id.asString();
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "textures", idstr);
+ return filename;
+}
+
+std::string LLTextureCache::getTextureFileName(const LLUUID& id)
+{
+ std::string idstr = id.asString();
+ std::string delem = gDirUtilp->getDirDelimiter();
+ std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr;
+ return filename;
+}
+
+bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize)
+{
+ bool res = false;
+ bool purge = false;
+ // Append UUID to end of texture entries
+ {
+ LLMutexLock lock(&mHeaderMutex);
+ size_map_t::iterator iter = mTexturesSizeMap.find(id);
+ if (iter == mTexturesSizeMap.end() || iter->second < bodysize)
+ {
+ llassert_always(bodysize > 0);
+ Entry* entry = new Entry(id, bodysize, time(NULL));
+ ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(),
+ (U8*)entry, -1, 1*sizeof(Entry));
+ delete entry;
+ if (iter != mTexturesSizeMap.end())
+ {
+ mTexturesSizeTotal -= iter->second;
+ }
+ mTexturesSizeTotal += bodysize;
+ mTexturesSizeMap[id] = bodysize;
+ if (mTexturesSizeTotal > sCacheMaxTexturesSize)
+ {
+ purge = true;
+ }
+ res = true;
+ }
+ }
+ if (purge)
+ {
+ mDoPurge = TRUE;
+ }
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//static
+const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
+F32 LLTextureCache::sHeaderCacheVersion = 1.0f;
+U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
+S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
+const char* entries_filename = "texture.entries";
+const char* cache_filename = "texture.cache";
+const char* textures_dirname = "textures";
+
+void LLTextureCache::setDirNames(ELLPath location)
+{
+ std::string delem = gDirUtilp->getDirDelimiter();
+ mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename);
+ mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename);
+ mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
+ mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename;
+}
+
+void LLTextureCache::purgeCache(ELLPath location)
+{
+ if (!mReadOnly)
+ {
+ setDirNames(location);
+
+ ll_apr_file_remove(mHeaderEntriesFileName, NULL);
+ ll_apr_file_remove(mHeaderDataFileName, NULL);
+ }
+ purgeAllTextures(true);
+}
+
+S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only)
+{
+ mReadOnly = read_only;
+
+ S64 header_size = (max_size * 2) / 10;
+ S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
+ sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
+ header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE;
+ max_size -= header_size;
+ if (sCacheMaxTexturesSize > 0)
+ sCacheMaxTexturesSize = llmin(sCacheMaxTexturesSize, max_size);
+ else
+ sCacheMaxTexturesSize = max_size;
+ max_size -= sCacheMaxTexturesSize;
+
+ llinfos << "TEXTURE CACHE: Headers: " << sCacheMaxEntries
+ << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << llendl;
+
+ setDirNames(location);
+
+ if (!mReadOnly)
+ {
+ LLFile::mkdir(mTexturesDirName.c_str());
+ const char* subdirs = "0123456789abcdef";
+ for (S32 i=0; i<16; i++)
+ {
+ std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i];
+ LLFile::mkdir(dirname.c_str());
+ }
+ }
+ readHeaderCache();
+ purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
+
+ return max_size; // unused cache space
+}
+
+struct lru_data
+{
+ lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; }
+ U32 time;
+ S32 index;
+ LLUUID uuid;
+ struct Compare
+ {
+ // lhs < rhs
+ typedef const lru_data* lru_data_ptr;
+ bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const
+ {
+ if (!(a->time < b->time))
+ return true;
+ else if (!(b->time < a->time))
+ return false;
+ else
+ return a->index < b->index;
+ }
+ };
+};
+
+// Called from either the main thread or the worker thread
+void LLTextureCache::readHeaderCache(apr_pool_t* poolp)
+{
+ LLMutexLock lock(&mHeaderMutex);
+ mHeaderEntriesInfo.mVersion = 0.f;
+ mHeaderEntriesInfo.mEntries = 0;
+ if (ll_apr_file_exists(mHeaderEntriesFileName, poolp))
+ {
+ ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion)
+ {
+ if (!mReadOnly)
+ {
+ // Info with 0 entries
+ mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
+ ll_apr_file_write_ex(mHeaderEntriesFileName, poolp,
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ }
+ else
+ {
+ S32 num_entries = mHeaderEntriesInfo.mEntries;
+ if (num_entries)
+ {
+ Entry* entries = new Entry[num_entries];
+ ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
+ (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry));
+ typedef std::set<lru_data*, lru_data::Compare> lru_set_t;
+ lru_set_t lru;
+ for (S32 i=0; i<num_entries; i++)
+ {
+ if (entries[i].mSize >= 0) // -1 indicates erased entry, skip
+ {
+ const LLUUID& id = entries[i].mID;
+ lru.insert(new lru_data(entries[i].mTime, i, id));
+ mHeaderIDMap[id] = i;
+ }
+ }
+ mLRU.clear();
+ S32 lru_entries = sCacheMaxEntries / 10;
+ for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter)
+ {
+ lru_data* data = *iter;
+ mLRU[data->index] = data->uuid;
+ if (--lru_entries <= 0)
+ break;
+ }
+ for_each(lru.begin(), lru.end(), DeletePointer());
+ delete[] entries;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureCache::purgeAllTextures(bool purge_directories)
+{
+ if (!mReadOnly)
+ {
+ const char* subdirs = "0123456789abcdef";
+ std::string delem = gDirUtilp->getDirDelimiter();
+ std::string mask = delem + "*";
+ for (S32 i=0; i<16; i++)
+ {
+ std::string dirname = mTexturesDirName + delem + subdirs[i];
+ gDirUtilp->deleteFilesInDir(dirname.c_str(),mask);
+ if (purge_directories)
+ {
+ LLFile::rmdir(dirname.c_str());
+ }
+ }
+ ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
+ if (purge_directories)
+ {
+ LLFile::rmdir(mTexturesDirName.c_str());
+ }
+ }
+ mTexturesSizeMap.clear();
+}
+
+void LLTextureCache::purgeTextures(bool validate)
+{
+ if (mReadOnly)
+ {
+ return;
+ }
+
+ LLMutexLock lock(&mHeaderMutex);
+
+ S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL);
+ S32 num_entries = filesize / sizeof(Entry);
+ if (num_entries * sizeof(Entry) != filesize)
+ {
+ llwarns << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << llendl;
+ purgeAllTextures(false);
+ return;
+ }
+ if (num_entries == 0)
+ {
+ return; // nothing to do
+ }
+
+ Entry* entries = new Entry[num_entries];
+ S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL,
+ (U8*)entries, 0, num_entries*sizeof(Entry));
+ if (bytes_read != filesize)
+ {
+ llwarns << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << llendl;
+ purgeAllTextures(false);
+ return;
+ }
+
+ llinfos << "TEXTURE CACHE: Reading Entries..." << llendl;
+
+ std::map<LLUUID, S32> entry_idx_map;
+ S64 total_size = 0;
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ const LLUUID& id = entries[idx].mID;
+// llinfos << "Entry: " << id << " Size: " << entries[i].mSize << " Time: " << entries[i].mTime << llendl;
+ std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id);
+ if (iter != entry_idx_map.end())
+ {
+ // Newer entry replacing older entry
+ S32 pidx = iter->second;
+ total_size -= entries[pidx].mSize;
+ entries[pidx].mSize = 0; // flag: skip older entry
+ }
+ entry_idx_map[id] = idx;
+ total_size += entries[idx].mSize;
+ }
+
+ U32 validate_idx = 0;
+ if (validate)
+ {
+ validate_idx = gSavedSettings.getU32("CacheValidateCounter");
+ U32 next_idx = (++validate_idx) % 256;
+ gSavedSettings.setU32("CacheValidateCounter", next_idx);
+ llinfos << "TEXTURE CACHE: Validating: " << validate_idx << llendl;
+ }
+
+ S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10;
+ S32 purge_count = 0;
+ S32 next_idx = 0;
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ if (entries[idx].mSize == 0)
+ {
+ continue;
+ }
+ bool purge_entry = false;
+ std::string filename = getTextureFileName(entries[idx].mID);
+ if (total_size >= min_cache_size)
+ {
+ purge_entry = true;
+ }
+ else if (validate)
+ {
+ // make sure file exists and is the correct size
+ S32 uuididx = entries[idx].mID.mData[0];
+ if (uuididx == validate_idx)
+ {
+// llinfos << "Validating: " << filename << "Size: " << entries[idx].mSize << llendl;
+ S32 bodysize = ll_apr_file_size(filename, NULL);
+ if (bodysize != entries[idx].mSize)
+ {
+ llwarns << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize
+ << filename << llendl;
+ purge_entry = true;
+ }
+ }
+ }
+ if (purge_entry)
+ {
+ purge_count++;
+// llinfos << "PURGING: " << filename << llendl;
+ ll_apr_file_remove(filename, NULL);
+ total_size -= entries[idx].mSize;
+ entries[idx].mSize = 0;
+ }
+ else
+ {
+ if (next_idx != idx)
+ {
+ entries[next_idx] = entries[idx];
+ }
+ ++next_idx;
+ }
+ }
+ num_entries = next_idx;
+
+ llinfos << "TEXTURE CACHE: Writing Entries: " << num_entries << llendl;
+
+ ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
+ ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL,
+ (U8*)&entries[0], 0, num_entries*sizeof(Entry));
+
+ mTexturesSizeTotal = 0;
+ mTexturesSizeMap.clear();
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize;
+ mTexturesSizeTotal += entries[idx].mSize;
+ }
+ llassert(mTexturesSizeTotal == total_size);
+
+ delete[] entries;
+
+ llinfos << "TEXTURE CACHE:"
+ << " PURGED: " << purge_count
+ << " ENTRIES: " << num_entries
+ << " CACHE SIZE: " << total_size / 1024*1024 << " MB"
+ << llendl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// call lockWorkers() first!
+LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)
+{
+ LLTextureCacheWorker* res = NULL;
+ handle_map_t::iterator iter = mReaders.find(handle);
+ if (iter != mReaders.end())
+ {
+ res = iter->second;
+ }
+ return res;
+}
+
+LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
+{
+ LLTextureCacheWorker* res = NULL;
+ handle_map_t::iterator iter = mWriters.find(handle);
+ if (iter != mWriters.end())
+ {
+ res = iter->second;
+ }
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Called from work thread
+S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize)
+{
+ bool retry = false;
+ S32 idx = -1;
+
+ {
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::iterator iter = mHeaderIDMap.find(id);
+ if (iter != mHeaderIDMap.end())
+ {
+ idx = iter->second;
+ }
+ else if (touch && !mReadOnly)
+ {
+ if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries)
+ {
+ // Add an entry
+ idx = mHeaderEntriesInfo.mEntries++;
+ mHeaderIDMap[id] = idx;
+ // Update Info
+ ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ else if (!mLRU.empty())
+ {
+ idx = mLRU.begin()->first; // will be erased below
+ const LLUUID& oldid = mLRU.begin()->second;
+ mHeaderIDMap.erase(oldid);
+ mTexturesSizeMap.erase(oldid);
+ mHeaderIDMap[id] = idx;
+ }
+ else
+ {
+ idx = -1;
+ retry = true;
+ }
+ }
+ if (idx >= 0)
+ {
+ if (touch && !mReadOnly)
+ {
+ // Update the lru entry
+ mLRU.erase(idx);
+ llassert_always(imagesize && *imagesize > 0);
+ Entry* entry = new Entry(id, *imagesize, time(NULL));
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)entry, offset, sizeof(Entry));
+ delete entry;
+ }
+ else if (imagesize)
+ {
+ // Get the image size
+ Entry entry;
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)&entry, offset, sizeof(Entry));
+ *imagesize = entry.mSize;
+ }
+ }
+ }
+ if (retry)
+ {
+ readHeaderCache(getFileAPRPool()); // updates the lru
+ llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries);
+ idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion
+ }
+ return idx;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Calls from texture pipeline thread (i.e. LLTextureFetch)
+
+LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority,
+ S32 offset, S32 size, ReadResponder* responder)
+{
+ // Note: checking to see if an entry exists can cause a stall,
+ // so let the thread handle it
+ LLMutexLock lock(&mWorkersMutex);
+ LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
+ NULL, size, offset, 0,
+ responder);
+ handle_t handle = worker->read();
+ mReaders[handle] = worker;
+ return handle;
+}
+
+bool LLTextureCache::readComplete(handle_t handle, bool abort)
+{
+ lockWorkers();
+ handle_map_t::iterator iter = mReaders.find(handle);
+ llassert_always(iter != mReaders.end());
+ LLTextureCacheWorker* worker = iter->second;
+ bool res = worker->complete();
+ if (res || abort)
+ {
+ mReaders.erase(handle);
+ unlockWorkers();
+ worker->scheduleDelete();
+ return true;
+ }
+ else
+ {
+ unlockWorkers();
+ return false;
+ }
+}
+
+LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
+ U8* data, S32 datasize, S32 imagesize,
+ WriteResponder* responder)
+{
+ if (mReadOnly)
+ {
+ return LLWorkerThread::nullHandle();
+ }
+ if (mDoPurge)
+ {
+ // NOTE: This may cause an occasional hiccup,
+ // but it really needs to be done on the control thread
+ // (i.e. here)
+ purgeTextures(false);
+ mDoPurge = FALSE;
+ }
+ if (datasize >= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ LLMutexLock lock(&mWorkersMutex);
+ llassert_always(imagesize > 0);
+ LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
+ data, datasize, 0,
+ imagesize, responder);
+ handle_t handle = worker->write();
+ mWriters[handle] = worker;
+ return handle;
+ }
+ return LLWorkerThread::nullHandle();
+}
+
+bool LLTextureCache::writeComplete(handle_t handle, bool abort)
+{
+ lockWorkers();
+ handle_map_t::iterator iter = mWriters.find(handle);
+ llassert_always(iter != mWriters.end());
+ LLTextureCacheWorker* worker = iter->second;
+ if (worker->complete() || abort)
+ {
+ mWriters.erase(handle);
+ unlockWorkers();
+ worker->scheduleDelete();
+ return true;
+ }
+ else
+ {
+ unlockWorkers();
+ return false;
+ }
+}
+
+void LLTextureCache::prioritizeWrite(handle_t handle)
+{
+ // Don't prioritize yet, we might be working on this now
+ // which could create a deadlock
+ mPrioritizeWriteList.push_back(handle);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Called from MAIN thread (endWork())
+
+bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id)
+{
+ if (mReadOnly)
+ {
+ return false;
+ }
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::iterator iter = mHeaderIDMap.find(id);
+ if (iter != mHeaderIDMap.end())
+ {
+ S32 idx = iter->second;
+ if (idx >= 0)
+ {
+ Entry* entry = new Entry(id, -1, time(NULL));
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_write_ex(mHeaderEntriesFileName, NULL,
+ (U8*)entry, offset, sizeof(Entry));
+ delete entry;
+ mLRU[idx] = id;
+ mHeaderIDMap.erase(id);
+ mTexturesSizeMap.erase(id);
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLTextureCache::removeFromCache(const LLUUID& id)
+{
+ llwarns << "Removing texture from cache: " << id << llendl;
+ if (!mReadOnly)
+ {
+ removeHeaderCacheEntry(id);
+ ll_apr_file_remove(getTextureFileName(id), NULL);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLTextureCache::ReadResponder::ReadResponder()
+ : mImageSize(0),
+ mImageLocal(FALSE)
+{
+}
+
+void LLTextureCache::ReadResponder::setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
+{
+ if (mFormattedImage.notNull())
+ {
+ llassert_always(mFormattedImage->getCodec() == imageformat);
+ mFormattedImage->appendData(data, datasize);
+ }
+ else
+ {
+ mFormattedImage = LLImageFormatted::createFromType(imageformat);
+ mFormattedImage->setData(data,datasize);
+ }
+ mImageSize = imagesize;
+ mImageLocal = imagelocal;
+}
+
+//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
new file mode 100644
index 0000000000..3b16b26b4a
--- /dev/null
+++ b/indra/newview/lltexturecache.h
@@ -0,0 +1,149 @@
+/**
+ * @file lltexturecache.h
+ * @brief Object for managing texture cachees.
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLTEXTURECACHE_
+#define LL_LLTEXTURECACHE_H
+
+#include "lldir.h"
+#include "llstl.h"
+#include "llstring.h"
+#include "lluuid.h"
+
+#include "llworkerthread.h"
+
+class LLTextureCacheWorker;
+
+class LLTextureCache : public LLWorkerThread
+{
+ friend class LLTextureCacheWorker;
+
+public:
+
+ class Responder : public LLResponder
+ {
+ public:
+ virtual void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) = 0;
+ };
+
+ class ReadResponder : public Responder
+ {
+ public:
+ ReadResponder();
+ void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal);
+ void setImage(LLImageFormatted* image) { mFormattedImage = image; }
+ protected:
+ LLPointer<LLImageFormatted> mFormattedImage;
+ S32 mImageSize;
+ BOOL mImageLocal;
+ };
+
+ class WriteResponder : public Responder
+ {
+ void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
+ {
+ // not used
+ }
+ };
+
+ LLTextureCache(bool threaded);
+ ~LLTextureCache();
+
+ /*virtual*/ S32 update(U32 max_time_ms);
+
+ void purgeCache(ELLPath location);
+ S64 initCache(ELLPath location, S64 maxsize, BOOL read_only);
+
+ handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
+ ReadResponder* responder);
+ bool readComplete(handle_t handle, bool abort);
+ handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize,
+ WriteResponder* responder);
+ bool writeComplete(handle_t handle, bool abort = false);
+ void prioritizeWrite(handle_t handle);
+
+ void removeFromCache(const LLUUID& id);
+
+ // For LLTextureCacheWorker::Responder
+ LLTextureCacheWorker* getReader(handle_t handle);
+ LLTextureCacheWorker* getWriter(handle_t handle);
+ void lockWorkers() { mWorkersMutex.lock(); }
+ void unlockWorkers() { mWorkersMutex.unlock(); }
+
+ // debug
+ S32 getNumReads() { return mReaders.size(); }
+ S32 getNumWrites() { return mWriters.size(); }
+
+protected:
+ // Accessed by LLTextureCacheWorker
+ apr_pool_t* getFileAPRPool() { return mFileAPRPool; }
+ bool appendToTextureEntryList(const LLUUID& id, S32 size);
+ std::string getLocalFileName(const LLUUID& id);
+ std::string getTextureFileName(const LLUUID& id);
+
+private:
+ void setDirNames(ELLPath location);
+ void readHeaderCache(apr_pool_t* poolp = NULL);
+ void purgeAllTextures(bool purge_directories);
+ void purgeTextures(bool validate);
+ S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
+ bool removeHeaderCacheEntry(const LLUUID& id);
+ void lockHeaders() { mHeaderMutex.lock(); }
+ void unlockHeaders() { mHeaderMutex.unlock(); }
+
+private:
+ // Internal
+ LLMutex mWorkersMutex;
+ LLMutex mHeaderMutex;
+ apr_pool_t* mFileAPRPool;
+
+ typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
+ handle_map_t mReaders;
+ handle_map_t mWriters;
+ std::vector<handle_t> mPrioritizeWriteList;
+
+ BOOL mReadOnly;
+
+ // Entries
+ struct EntriesInfo
+ {
+ F32 mVersion;
+ U32 mEntries;
+ };
+ struct Entry
+ {
+ Entry() {}
+ Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {}
+ LLUUID mID; // 128 bits
+ S32 mSize; // total size of image if known (NOT size cached)
+ U32 mTime; // seconds since 1/1/1970
+ };
+
+ // HEADERS (Include first mip)
+ std::string mHeaderEntriesFileName;
+ std::string mHeaderDataFileName;
+ EntriesInfo mHeaderEntriesInfo;
+ typedef std::map<S32,LLUUID> index_map_t;
+ index_map_t mLRU; // index, id; stored as a map for fast removal
+ typedef std::map<LLUUID,S32> id_map_t;
+ id_map_t mHeaderIDMap;
+
+ // BODIES (TEXTURES minus headers)
+ std::string mTexturesDirName;
+ std::string mTexturesDirEntriesFileName;
+ typedef std::map<LLUUID,S32> size_map_t;
+ size_map_t mTexturesSizeMap;
+ S64 mTexturesSizeTotal;
+ LLAtomic32<BOOL> mDoPurge;
+
+ // Statics
+ static F32 sHeaderCacheVersion;
+ static U32 sCacheMaxEntries;
+ static S64 sCacheMaxTexturesSize;
+};
+
+#endif // LL_LLTEXTURECACHE_H
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 75777024da..db747c60fc 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1,6 +1,6 @@
/**
- * @file llviewerimage.cpp
- * @brief Object which handles a received image (and associated texture(s))
+ * @file lltexturecache.cpp
+ * @brief Object which fetches textures from the cache and/or network
*
* Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
* $License$
@@ -12,96 +12,283 @@
#include "lltexturefetch.h"
-#include "llworkerthread.h"
+#include "llcurl.h"
+#include "llhttpclient.h"
#include "llimage.h"
-#include "llvfs.h"
+#include "llimageworker.h"
+#include "llworkerthread.h"
+#include "llagent.h"
+#include "lltexturecache.h"
+#include "llviewerimagelist.h"
#include "llviewerimage.h"
+#include "llviewerregion.h"
#include "viewer.h"
//////////////////////////////////////////////////////////////////////////////
+//static
class LLTextureFetchWorker : public LLWorkerClass
{
- friend class LLTextureFetchImpl;
-
-public:
- // From LLWorkerClass
- static void initClass(bool threaded, bool runalways);
- static void updateClass();
- static void cleanupClass();
-
- // New methods
- static LLTextureFetchWorker* getWorker(const LLUUID& id, const LLHost& host,
- F32 mPriority, S32 discard,
- BOOL needs_aux = FALSE);
- static LLTextureFetchWorker* getActiveWorker(const LLUUID& id);
+ friend class LLTextureFetch;
private:
- static void sendRequestListToSimulators();
+ class URLResponder : public LLHTTPClient::Responder
+ {
+ public:
+ URLResponder(LLTextureFetch* fetcher, const LLUUID& id)
+ : mFetcher(fetcher), mID(id)
+ {
+ }
+ ~URLResponder()
+ {
+ }
+ virtual void error(U32 status, const std::string& reason)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ llinfos << "LLTextureFetchWorker::URLResponder::error " << status << ": " << reason << llendl;
+ worker->callbackURLReceived(LLSD(), false);
+ }
+ mFetcher->unlockQueue();
+ }
+ virtual void result(const LLSD& content)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ worker->callbackURLReceived(content, true);
+ }
+ mFetcher->unlockQueue();
+ }
+ private:
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ };
+
+ class HTTPGetResponder : public LLCurl::Responder
+ {
+ public:
+ HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id)
+ : mFetcher(fetcher), mID(id)
+ {
+ }
+ ~HTTPGetResponder()
+ {
+ }
+ virtual void completed(U32 status, const std::stringstream& content)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ const std::string& cstr = content.str();
+ if (200 <= status && status < 300)
+ {
+ if (203 == status) // partial information (i.e. last block)
+ {
+ worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), true);
+ }
+ else
+ {
+ worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), false);
+ }
+ }
+ else
+ {
+ llinfos << "LLTextureFetchWorker::HTTPGetResponder::error " << status << ": " << cstr << llendl;
+ worker->callbackHttpGet(NULL, -1, true);
+ }
+ }
+ mFetcher->unlockQueue();
+ }
+ private:
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ };
+
+ class CacheReadResponder : public LLTextureCache::ReadResponder
+ {
+ public:
+ CacheReadResponder(LLTextureFetch* fetcher, const LLUUID& id, LLImageFormatted* image)
+ : mFetcher(fetcher), mID(id)
+ {
+ setImage(image);
+ }
+ virtual void completed(bool success)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ worker->callbackCacheRead(success, mFormattedImage, mImageSize, mImageLocal);
+ }
+ mFetcher->unlockQueue();
+ }
+ private:
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ };
+
+ class CacheWriteResponder : public LLTextureCache::WriteResponder
+ {
+ public:
+ CacheWriteResponder(LLTextureFetch* fetcher, const LLUUID& id)
+ : mFetcher(fetcher), mID(id)
+ {
+ }
+ virtual void completed(bool success)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ worker->callbackCacheWrite(success);
+ }
+ mFetcher->unlockQueue();
+ }
+ private:
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ };
+
+ class DecodeResponder : public LLResponder
+ {
+ public:
+ DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker)
+ : mFetcher(fetcher), mID(id), mWorker(worker)
+ {
+ }
+ virtual void completed(bool success)
+ {
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ worker->callbackDecoded(success);
+ }
+ mFetcher->unlockQueue();
+ }
+ private:
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ LLTextureFetchWorker* mWorker; // debug only (may get deleted from under us, use mFetcher/mID)
+ };
+
+ struct Compare
+ {
+ // lhs < rhs
+ bool operator()(const LLTextureFetchWorker* lhs, const LLTextureFetchWorker* rhs) const
+ {
+ // greater priority is "less"
+ const F32 lpriority = lhs->mImagePriority;
+ const F32 rpriority = rhs->mImagePriority;
+ if (lpriority > rpriority) // higher priority
+ return true;
+ else if (lpriority < rpriority)
+ return false;
+ else
+ return lhs < rhs;
+ }
+ };
public:
- virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
+ /*virtual*/ bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
+ /*virtual*/ void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
+ /*virtual*/ bool deleteOK(); // called from update() (WORK THREAD)
~LLTextureFetchWorker();
void relese() { --mActiveCount; }
-
protected:
- LLTextureFetchWorker(const LLUUID& id, const LLHost& host, F32 mPriority, S32 discard);
+ LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host,
+ F32 priority, S32 discard, S32 size);
private:
- virtual void startWork(S32 param); // called from addWork() (MAIN THREAD)
- virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
+ /*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD)
+ /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
+ void resetFormattedData();
+
void setImagePriority(F32 priority);
- void setDesiredDiscard(S32 discard);
- void insertPacket(S32 index, U8* data, S32 size);
+ void setDesiredDiscard(S32 discard, S32 size);
+ bool insertPacket(S32 index, U8* data, S32 size);
void clearPackets();
U32 calcWorkPriority();
- bool startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type);
- bool loadFromVFS();
+ void removeFromCache();
bool processSimulatorPackets();
void startDecode();
bool decodeImage();
-
+ bool writeToCacheComplete();
+
void lockWorkData() { mWorkMutex.lock(); }
void unlockWorkData() { mWorkMutex.unlock(); }
-
- static void lockQueue() { sDataMutex->lock(); }
- static void unlockQueue() { sDataMutex->unlock(); }
+
+ void callbackURLReceived(const LLSD& data, bool success);
+ void callbackHttpGet(U8* data, S32 data_size, bool last_block);
+ void callbackCacheRead(bool success, LLImageFormatted* image,
+ S32 imagesize, BOOL islocal);
+ void callbackCacheWrite(bool success);
+ void callbackDecoded(bool success);
private:
enum e_state
{
- INIT = 1,
- LOAD_FROM_CACHE,
+ // NOTE: Affects LLTextureBar::draw in lltextureview.cpp (debug hack)
+ INVALID = 0,
+ INIT,
+ LOAD_FROM_TEXTURE_CACHE,
+ CACHE_POST,
+ LOAD_FROM_NETWORK,
LOAD_FROM_SIMULATOR,
- WRITE_TO_VFS,
+ LOAD_FROM_HTTP_GET_URL,
+ LOAD_FROM_HTTP_GET_DATA,
DECODE_IMAGE,
DECODE_IMAGE_UPDATE,
+ WRITE_TO_CACHE,
+ WAIT_ON_WRITE,
DONE
};
+ static const char* sStateDescs[];
e_state mState;
+ LLTextureFetch* mFetcher;
+ LLImageWorker* mImageWorker;
LLPointer<LLImageFormatted> mFormattedImage;
LLPointer<LLImageRaw> mRawImage;
LLPointer<LLImageRaw> mAuxImage;
LLUUID mID;
LLHost mHost;
- F32 mPriority;
+ F32 mImagePriority;
+ U32 mWorkPriority;
+ F32 mRequestedPriority;
S32 mDesiredDiscard;
+ S32 mSimRequestedDiscard;
S32 mRequestedDiscard;
+ S32 mLoadedDiscard;
S32 mDecodedDiscard;
LLFrameTimer mRequestedTimer;
LLFrameTimer mIdleTimer;
- LLVFSThread::handle_t mFileHandle;
+ LLTextureCache::handle_t mCacheReadHandle;
+ LLTextureCache::handle_t mCacheWriteHandle;
U8* mBuffer;
S32 mBufferSize;
S32 mRequestedSize;
+ S32 mDesiredSize;
+ S32 mFileSize;
+ S32 mCachedSize;
BOOL mLoaded;
BOOL mRequested;
BOOL mDecoded;
+ BOOL mWritten;
BOOL mNeedsAux;
+ BOOL mHaveAllData;
+ BOOL mUseHTTPGet;
+ BOOL mInLocalCache;
+ S32 mRetryAttempt;
+ std::string mURL;
S32 mActiveCount;
// Work Data
@@ -110,638 +297,1450 @@ private:
{
PacketData(U8* data, S32 size) { mData = data; mSize = size; }
~PacketData() { clearData(); }
- void clearData() { delete mData; mData = NULL; }
+ void clearData() { delete[] mData; mData = NULL; }
U8* mData;
U32 mSize;
};
std::vector<PacketData*> mPackets;
+ S32 mFirstPacket;
S32 mLastPacket;
- S32 mTotalPackets;
- S32 mTotalBytes;
-
- // Class variables (statics)
-
- static LLWorkerThread* sWorkerThread;
- static LLMutex* sDataMutex;
+ U16 mTotalPackets;
+ U8 mImageCodec;
+ LLFrameTimer mFetchTimer; // debug
+};
- // Map of all requests by UUID
- typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
- static map_t sRequests;
+//static
+const char* LLTextureFetchWorker::sStateDescs[] = {
+ "INVALID",
+ "INIT",
+ "LOAD_FROM_TEXTURE_CACHE",
+ "CACHE_POST",
+ "LOAD_FROM_NETWORK",
+ "LOAD_FROM_SIMULATOR",
+ "LOAD_FROM_HTTP_URL",
+ "LOAD_FROM_HTTP_DATA",
+ "DECODE_IMAGE",
+ "DECODE_IMAGE_UPDATE",
+ "WRITE_TO_CACHE",
+ "WAIT_ON_WRITE",
+ "DONE",
+};
- // Set of requests that require network data
- typedef std::set<LLTextureFetchWorker*> queue_t ;
- static queue_t sNetworkQueue;
+// called from MAIN THREAD
- static LLFrameTimer sNetworkTimer;
-};
+LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
+ const LLUUID& id, // Image UUID
+ const LLHost& host, // Simulator host
+ F32 priority, // Priority
+ S32 discard, // Desired discard
+ S32 size) // Desired size
+ : LLWorkerClass(fetcher, "TextureFetch"),
+ mState(INIT),
+ mFetcher(fetcher),
+ mImageWorker(NULL),
+ mID(id),
+ mHost(host),
+ mImagePriority(priority),
+ mWorkPriority(0),
+ mRequestedPriority(0.f),
+ mDesiredDiscard(-1),
+ mSimRequestedDiscard(-1),
+ mRequestedDiscard(-1),
+ mLoadedDiscard(-1),
+ mDecodedDiscard(-1),
+ mCacheReadHandle(LLTextureCache::nullHandle()),
+ mCacheWriteHandle(LLTextureCache::nullHandle()),
+ mBuffer(NULL),
+ mBufferSize(0),
+ mRequestedSize(0),
+ mDesiredSize(FIRST_PACKET_SIZE),
+ mFileSize(0),
+ mCachedSize(0),
+ mLoaded(FALSE),
+ mRequested(FALSE),
+ mDecoded(FALSE),
+ mWritten(FALSE),
+ mNeedsAux(FALSE),
+ mHaveAllData(FALSE),
+ mUseHTTPGet(FALSE),
+ mInLocalCache(FALSE),
+ mRetryAttempt(0),
+ mActiveCount(0),
+ mWorkMutex(fetcher->getWorkerAPRPool()),
+ mFirstPacket(0),
+ mLastPacket(-1),
+ mTotalPackets(0),
+ mImageCodec(IMG_CODEC_INVALID)
+{
+ calcWorkPriority();
+ if ((gSavedSettings.getBOOL("ImagePipelineUseHTTP")) &&
+ (host == LLHost::invalid))
+ {
+ mUseHTTPGet = TRUE;
+ }
+ if (!mFetcher->mDebugPause)
+ {
+ U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
+ addWork(0, work_priority );
+ }
+ setDesiredDiscard(discard, size);
+}
-//statics
-LLTextureFetchWorker::map_t LLTextureFetchWorker::sRequests;
-LLTextureFetchWorker::queue_t LLTextureFetchWorker::sNetworkQueue;
-LLFrameTimer LLTextureFetchWorker::sNetworkTimer;
-LLWorkerThread* LLTextureFetchWorker::sWorkerThread = NULL;
-LLMutex* LLTextureFetchWorker::sDataMutex = NULL;
+LLTextureFetchWorker::~LLTextureFetchWorker()
+{
+ llassert_always(!haveWork());
+ lockWorkData();
+ if (mCacheReadHandle != LLTextureCache::nullHandle())
+ {
+ mFetcher->mTextureCache->readComplete(mCacheReadHandle, true);
+ }
+ if (mCacheWriteHandle != LLTextureCache::nullHandle())
+ {
+ mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true);
+ }
+ if (mImageWorker)
+ {
+ mImageWorker->scheduleDelete();
+ }
+ mFormattedImage = NULL;
+ clearPackets();
+ unlockWorkData();
+}
-// called from MAIN THREAD
-//static
-void LLTextureFetchWorker::initClass(bool threaded, bool runalways)
+void LLTextureFetchWorker::clearPackets()
{
- sWorkerThread = new LLWorkerThread(threaded, runalways);
- sDataMutex = new LLMutex(sWorkerThread->getAPRPool());
+ for_each(mPackets.begin(), mPackets.end(), DeletePointer());
+ mPackets.clear();
+ mTotalPackets = 0;
+ mLastPacket = -1;
+ mFirstPacket = 0;
}
-// called from MAIN THREAD
-//static
-void LLTextureFetchWorker::updateClass()
+U32 LLTextureFetchWorker::calcWorkPriority()
{
- const F32 REQUEST_TIME = 1.f;
- const F32 MIN_IDLE_TIME = 1.f * 60.f; // 1 minute
- const F32 MAX_IDLE_TIME = 5.f * 60.f; // 5 minutes
- const S32 MIN_IDLE_COUNT = 16; // always keep last 16 idle requests
- const F32 MAX_IDLE_COUNT = 1024; // max number of idle requests
+ F32 priority_scale = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerImage::maxDecodePriority();
+ mWorkPriority = (U32)(mImagePriority * priority_scale);
+ return mWorkPriority;
+}
- // Periodically, gather the list of textures that need data from the network
- // And send the requests out to the simulators
- if (sNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME)
+void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
+{
+ if (mDesiredDiscard != discard)
{
- sNetworkTimer.reset();
- sendRequestListToSimulators();
+ if (!haveWork())
+ {
+ calcWorkPriority();
+ if (!mFetcher->mDebugPause)
+ {
+ U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
+ addWork(0, work_priority);
+ }
+ }
+ else if (mDesiredDiscard < discard)
+ {
+ U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
+ setPriority(work_priority);
+ }
+ mDesiredDiscard = discard;
+ mDesiredSize = size;
}
- // Remove any old requests (releasing their raw data)
- typedef std::pair<F32, LLTextureFetchWorker*> idle_pair;
- typedef std::set<idle_pair, compare_pair_greater<F32,LLTextureFetchWorker*> > idle_set;
- idle_set remove_set;
- for (map_t::iterator iter = sRequests.begin(); iter != sRequests.end(); ++iter)
+ else if (size > mDesiredSize)
{
- LLTextureFetchWorker* worker = iter->second;
- if (worker->mActiveCount > 0)
- continue;
- if (worker->haveWork())
- continue;
- F32 idletime = worker->mIdleTimer.getElapsedTimeF32();
- if (idletime < MIN_IDLE_TIME)
- continue;
- remove_set.insert(std::make_pair(idletime, worker));
+ mDesiredSize = size;
+ U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
+ setPriority(work_priority);
}
- S32 num_left = remove_set.size();
- for (idle_set::iterator iter = remove_set.begin(); iter != remove_set.end(); ++iter)
+}
+
+void LLTextureFetchWorker::setImagePriority(F32 priority)
+{
+ F32 delta = fabs(priority - mImagePriority);
+ if (delta > (mImagePriority * .05f)) // 5%
{
- if (num_left <= MIN_IDLE_COUNT)
- break;
- if (iter->first < MAX_IDLE_TIME &&
- num_left < MAX_IDLE_COUNT)
- break;
- num_left--;
+ mImagePriority = priority;
+ calcWorkPriority();
+ U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS);
+ setPriority(work_priority);
}
}
-// called from MAIN THREAD
-//static
-void LLTextureFetchWorker::sendRequestListToSimulators()
+void LLTextureFetchWorker::resetFormattedData()
{
- const F32 LAZY_FLUSH_TIMEOUT = 60.f;
- const S32 IMAGES_PER_REQUEST = 50;
- // Send requests
- typedef std::map< LLHost, std::vector<LLTextureFetchWorker*> > work_request_map_t;
- work_request_map_t requests;
- for (queue_t::iterator iter = sNetworkQueue.begin(); iter != sNetworkQueue.end(); ++iter)
+ delete[] mBuffer;
+ mBuffer = NULL;
+ mBufferSize = 0;
+ if (mFormattedImage.notNull())
+ {
+ mFormattedImage->deleteData();
+ }
+ mHaveAllData = FALSE;
+}
+
+// Called from MAIN thread
+void LLTextureFetchWorker::startWork(S32 param)
+{
+ llassert(mImageWorker == NULL);
+ llassert(mFormattedImage.isNull());
+}
+
+#include "llviewerimagelist.h" // debug
+
+// Called from LLWorkerThread::processRequest()
+bool LLTextureFetchWorker::doWork(S32 param)
+{
+ LLMutexLock lock(&mWorkMutex);
+
+ e_state old_state = mState;
+ mFetchTimer.reset();
+
+ if (mFetcher->mDebugPause)
+ {
+ return false; // debug: don't do any work
+ }
+ if (mID == mFetcher->mDebugID)
+ {
+ mFetcher->mDebugCount++; // for setting breakpoints
+ }
+
+ if (mState == INIT)
{
- LLTextureFetchWorker* req = *iter;
- if (req->haveWork())
+ mRequestedDiscard = -1;
+ mLoadedDiscard = -1;
+ mDecodedDiscard = -1;
+ mRequestedSize = 0;
+ mFileSize = 0;
+ mCachedSize = 0;
+ mLoaded = FALSE;
+ mRequested = FALSE;
+ mDecoded = FALSE;
+ mWritten = FALSE;
+ delete[] mBuffer;
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mHaveAllData = FALSE;
+ clearPackets();
+ mCacheReadHandle = LLTextureCache::nullHandle();
+ mCacheWriteHandle = LLTextureCache::nullHandle();
+ mURL.clear();
+ mState = LOAD_FROM_TEXTURE_CACHE;
+ // fall through
+ }
+
+ if (mState == LOAD_FROM_TEXTURE_CACHE)
+ {
+ if (mCacheReadHandle == LLTextureCache::nullHandle())
{
- continue; // busy
+ U32 cache_priority = mWorkPriority;
+ S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
+ S32 size = mDesiredSize - offset;
+ if (size <= 0)
+ {
+ mState = CACHE_POST;
+ return false;
+ }
+ mFileSize = 0;
+ mLoaded = FALSE;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
+ CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
+ mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
+ offset, size, responder);
}
- if ((req->mRequestedDiscard == req->mDesiredDiscard) &&
- (req->mRequestedTimer.getElapsedTimeF32() < LAZY_FLUSH_TIMEOUT))
+
+ if (mLoaded)
{
- continue;
+ // Make sure request is complete. *TODO: make this auto-complete
+ if (mFetcher->mTextureCache->readComplete(mCacheReadHandle, false))
+ {
+ mCacheReadHandle = LLTextureCache::nullHandle();
+ mState = CACHE_POST;
+ // fall through
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
}
- req->mRequestedDiscard = req->mDesiredDiscard;
- req->mRequestedTimer.reset();
- requests[req->mHost].push_back(req);
}
- for (work_request_map_t::iterator iter1 = requests.begin();
- iter1 != requests.end(); ++iter1)
+
+ if (mState == CACHE_POST)
{
- LLHost host = iter1->first;
- // invalid host = load from static VFS
- if (host != LLHost::invalid)
+ mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
+ // Successfully loaded
+ if ((mCachedSize >= mDesiredSize) || mHaveAllData)
{
- S32 request_count = 0;
- for (std::vector<LLTextureFetchWorker*>::iterator iter2 = iter1->second.begin();
- iter2 != iter1->second.end(); ++iter2)
+ // we have enough data, decode it
+ llassert_always(mFormattedImage->getDataSize() > 0);
+ mState = DECODE_IMAGE;
+ // fall through
+ }
+ else
+ {
+ // need more data
+ mState = LOAD_FROM_NETWORK;
+ // fall through
+ }
+ }
+
+ if (mState == LOAD_FROM_NETWORK)
+ {
+ if (mFormattedImage.isNull())
+ {
+ mFormattedImage = new LLImageJ2C;
+ }
+ mState = mUseHTTPGet ? LOAD_FROM_HTTP_GET_URL : LOAD_FROM_SIMULATOR;
+ return false;
+ }
+
+ if (mState == LOAD_FROM_SIMULATOR)
+ {
+ if (!mRequested)
+ {
+ S32 data_size = mFormattedImage->getDataSize();
+ if (data_size > 0)
{
- LLTextureFetchWorker* req = *iter2;
- if (0 == request_count)
+ mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1;
+ if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size)
{
- gMessageSystem->newMessageFast(_PREHASH_RequestImage);
+ llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl;
+ removeFromCache();
+ resetFormattedData();
+ clearPackets();
}
- S32 packet = req->mLastPacket + 1;
- gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
- gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
- gMessageSystem->addS32Fast(_PREHASH_DiscardLevel, req->mDesiredDiscard);
- gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mPriority);
- gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
+ else
+ {
+ mLastPacket = mFirstPacket-1;
+ mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1;
+ }
+ }
+ mRequested = TRUE;
+ mRequestedSize = mDesiredSize;
+ mRequestedDiscard = mDesiredDiscard;
+ mFetcher->lockQueue();
+ mFetcher->addToNetworkQueue(this);
+ mFetcher->unlockQueue();
+ }
+ if (processSimulatorPackets())
+ {
+ mFetcher->lockQueue();
+ mFetcher->removeFromNetworkQueue(this);
+ mFetcher->unlockQueue();
+ if (!mFormattedImage->getDataSize())
+ {
+ // processSimulatorPackets() failed
+ llwarns << "processSimulatorPackets() failed to load buffer" << llendl;
+ return true; // failed
+ }
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ mState = DECODE_IMAGE;
+ }
+ else
+ {
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ }
+ return false;
+ }
+
+ if (mState == LOAD_FROM_HTTP_GET_URL)
+ {
+ if (!mRequested)
+ {
+ mRequested = TRUE;
+ mLoaded = FALSE;
+ std::string url;
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ url = region->getCapability("RequestTextureDownload");
+ }
+ if (!url.empty())
+ {
+ LLSD sd;
+ sd = mID.asString();
+ LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID));
+//*TODO:uncomment setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return false;
+ }
+ else
+ {
+ llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl;
+ mRequested = FALSE;
+ mState = LOAD_FROM_SIMULATOR;
+ return false;
+ }
+ }
+ else
+ {
+ if (mLoaded)
+ {
+ if (!mURL.empty())
+ {
+ mState = LOAD_FROM_HTTP_GET_DATA;
+ mRequested = FALSE; // reset
+ mLoaded = FALSE; // reset
+ }
+ else
+ {
+ llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl;
+ mRequested = FALSE;
+ mState = LOAD_FROM_SIMULATOR;
+ return false;
+ }
+ }
+ }
+ // fall through
+ }
+
+ if (mState == LOAD_FROM_HTTP_GET_DATA)
+ {
+ if (!mRequested)
+ {
+ mRequested = TRUE;
+ S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have
+ mRequestedSize = mDesiredSize;
+ mRequestedDiscard = mDesiredDiscard;
+#if 1 // *TODO: LLCurl::getByteRange is broken (ignores range)
+ cur_size = 0;
+ mFormattedImage->deleteData();
+#endif
+ mRequestedSize -= cur_size;
+ // F32 priority = mImagePriority / (F32)LLViewerImage::maxDecodePriority(); // 0-1
+ S32 offset = cur_size;
+ mBufferSize = cur_size; // This will get modified by callbackHttpGet()
+ std::string url;
+ if (mURL.empty())
+ {
+ //url = "http://asset.agni/0000002f-38ae-0e17-8e72-712e58964e9c.texture";
+ std::stringstream urlstr;
+ urlstr << "http://asset.agni/" << mID.asString() << ".texture";
+ url = urlstr.str();
+ }
+ else
+ {
+ url = mURL;
+ }
+ mLoaded = FALSE;
+// llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl;
+ LLCurl::getByteRange(url, offset, mRequestedSize,
+ new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority
+//*TODO:uncomment setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return false; // not done
+ }
- request_count++;
- if (request_count >= IMAGES_PER_REQUEST)
+ if (mLoaded)
+ {
+ S32 cur_size = mFormattedImage->getDataSize();
+ if (mRequestedSize < 0)
+ {
+ llwarns << "http get failed for: " << mID << llendl;
+ if (cur_size == 0)
{
- gMessageSystem->sendSemiReliable(host, NULL, NULL);
- request_count = 0;
+ resetFormattedData();
+ return true; // failed
+ }
+ else
+ {
+ mState = DECODE_IMAGE;
+ return false; // use what we have
}
}
- if (request_count >= IMAGES_PER_REQUEST)
+ llassert(mBufferSize == cur_size + mRequestedSize);
+ if (mHaveAllData)
{
- gMessageSystem->sendSemiReliable(host, NULL, NULL);
+ mFileSize = mBufferSize;
+ }
+ if (mRequestedSize > 0)
+ {
+ U8* buffer = new U8[mBufferSize];
+ if (cur_size > 0)
+ {
+ memcpy(buffer, mFormattedImage->getData(), cur_size);
+ }
+ memcpy(buffer + cur_size, mBuffer, mRequestedSize); // append
+ // NOTE: setData releases current data and owns new data (buffer)
+ mFormattedImage->setData(buffer, mBufferSize);
+ // delete temp data
+ delete[] mBuffer; // Note: not 'buffer' (assigned in setData())
+ mBuffer = NULL;
+ mBufferSize = 0;
+ }
+ else
+ {
+ llassert_always(cur_size);
}
+ mLoadedDiscard = mRequestedDiscard;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ mState = DECODE_IMAGE;
+ return false;
}
+
+ // NOTE: Priority gets updated when the http get completes (in callbackHTTPGet())
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return false;
}
-}
-//static
-LLTextureFetchWorker* LLTextureFetchWorker::getWorker(const LLUUID& id,
- const LLHost& host,
- F32 priority,
- S32 discard,
- BOOL needs_aux)
-{
- LLTextureFetchWorker* res;
- lockQueue();
- map_t::iterator iter = sRequests.find(id);
- if (iter != sRequests.end())
+ if (mState == DECODE_IMAGE)
{
- res = iter->second;
- if (res->mHost != host)
+ llassert_always(mFormattedImage->getDataSize() > 0);
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
+ startDecode();
+ mState = DECODE_IMAGE_UPDATE;
+ // fall though (need to call requestDecodedData() to start work)
+ }
+
+ if (mState == DECODE_IMAGE_UPDATE)
+ {
+ if (decodeImage())
{
- llerrs << "LLTextureFetchWorker::getWorker called with multiple hosts" << llendl;
+ if (mDecodedDiscard < 0)
+ {
+ if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0)
+ {
+ // Cache file should be deleted, try again
+ llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl;
+ mFormattedImage = NULL;
+ ++mRetryAttempt;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ mState = INIT;
+ return false;
+ }
+ else
+ {
+ llwarns << "UNABLE TO LOAD TEXTURE: " << mID << " RETRIES: " << mRetryAttempt << llendl;
+ mState = DONE; // failed
+ }
+ }
+ else
+ {
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ mState = WRITE_TO_CACHE;
+ }
+ // fall through
+ }
+ else
+ {
+ return false;
}
- res->setImagePriority(priority);
- res->setDesiredDiscard(discard);
-
}
- else
+
+ if (mState == WRITE_TO_CACHE)
{
- res = new LLTextureFetchWorker(id, host, priority, discard);
+ if (mInLocalCache || !mFileSize || !mRequested)
+ {
+ // If we're in a local cache or we didn't actually receive any new data, skip
+ mState = DONE;
+ return false;
+ }
+ S32 datasize = mFormattedImage->getDataSize();
+ llassert_always(datasize);
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
+ U32 cache_priority = mWorkPriority;
+ mWritten = FALSE;
+ CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
+ mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
+ mFormattedImage->getData(), datasize,
+ mFileSize, responder);
+ mState = WAIT_ON_WRITE;
+ // fall through
+ }
+
+ if (mState == WAIT_ON_WRITE)
+ {
+ if (writeToCacheComplete())
+ {
+ mState = DONE;
+ // fall through
+ }
+ else
+ {
+ if (mDesiredDiscard < mDecodedDiscard)
+ {
+ // We're waiting for this write to complete before we can receive more data
+ // (we can't touch mFormattedImage until the write completes)
+ // Prioritize the write
+ mFetcher->mTextureCache->prioritizeWrite(mCacheWriteHandle);
+ }
+ return false;
+ }
}
- unlockQueue();
- res->mActiveCount++;
- res->mNeedsAux = needs_aux;
- return res;
-}
-LLTextureFetchWorker* LLTextureFetchWorker::getActiveWorker(const LLUUID& id)
-{
- LLTextureFetchWorker* res = NULL;
- lockQueue();
- map_t::iterator iter = sRequests.find(id);
- if (iter != sRequests.end())
+ if (mState == DONE)
{
- res = iter->second;
+ if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard)
+ {
+ // More data was requested, return to INIT
+ mState = INIT;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ return false;
+ }
+ if (old_state != DONE)
+ {
+ mIdleTimer.reset();
+ }
+ return true;
}
- unlockQueue();
- return res;
+
+ return false;
}
-LLTextureFetchWorker::LLTextureFetchWorker(const LLUUID& id, // Image UUID
- const LLHost& host, // Simulator host
- F32 priority, // Priority
- S32 discard) // Desired discard level
- : LLWorkerClass(sWorkerThread, "TextureFetch"),
- mState(INIT),
- mID(id),
- mHost(host),
- mPriority(priority),
- mDesiredDiscard(discard),
- mRequestedDiscard(-1),
- mDecodedDiscard(-1),
- mFileHandle(LLVFSThread::nullHandle()),
- mBuffer(NULL),
- mBufferSize(0),
- mRequestedSize(0),
- mLoaded(FALSE),
- mRequested(FALSE),
- mDecoded(FALSE),
- mActiveCount(0),
- mWorkMutex(sWorkerThread->getAPRPool()),
- mLastPacket(-1),
- mTotalPackets(0),
- mTotalBytes(0)
+// Called from MAIN thread
+void LLTextureFetchWorker::endWork(S32 param, bool aborted)
{
- lockQueue();
- sRequests[mID] = this;
- unlockQueue();
- addWork(0, calcWorkPriority());
+ if (mImageWorker)
+ {
+ mImageWorker->scheduleDelete();
+ mImageWorker = NULL;
+ }
+ mFormattedImage = NULL;
}
-LLTextureFetchWorker::~LLTextureFetchWorker()
+//////////////////////////////////////////////////////////////////////////////
+
+// virtual
+void LLTextureFetchWorker::finishWork(S32 param, bool completed)
{
- lockQueue();
- mFormattedImage = NULL;
- map_t::iterator iter = sRequests.find(mID);
- if (iter != sRequests.end() && iter->second == this)
+ // The following are required in case the work was aborted
+ if (mCacheReadHandle != LLTextureCache::nullHandle())
{
- sRequests.erase(iter);
+ mFetcher->mTextureCache->readComplete(mCacheReadHandle, true);
+ mCacheReadHandle = LLTextureCache::nullHandle();
+ }
+ if (mCacheWriteHandle != LLTextureCache::nullHandle())
+ {
+ mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true);
+ mCacheWriteHandle = LLTextureCache::nullHandle();
}
- sNetworkQueue.erase(this);
- unlockQueue();
- clearPackets();
}
-void LLTextureFetchWorker::clearPackets()
+// virtual
+bool LLTextureFetchWorker::deleteOK()
{
- lockWorkData();
- for_each(mPackets.begin(), mPackets.end(), DeletePointer());
- mPackets.clear();
- unlockWorkData();
+ bool delete_ok = true;
+ // Allow any pending reads or writes to complete
+ if (mCacheReadHandle != LLTextureCache::nullHandle())
+ {
+ if (mFetcher->mTextureCache->readComplete(mCacheReadHandle, true))
+ {
+ mCacheReadHandle = LLTextureCache::nullHandle();
+ }
+ else
+ {
+ delete_ok = false;
+ }
+ }
+ if (mCacheWriteHandle != LLTextureCache::nullHandle())
+ {
+ if (mFetcher->mTextureCache->writeComplete(mCacheWriteHandle))
+ {
+ mCacheWriteHandle = LLTextureCache::nullHandle();
+ }
+ else
+ {
+ delete_ok = false;
+ }
+ }
+ // Don't delete while waiting for network requests *TODO: Need LLCurl::abort()
+ // Don't delete while waiting on writes
+ if ((mState >= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_URL &&
+ mState <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA) ||
+ (mState >= LLTextureFetchWorker::WRITE_TO_CACHE &&
+ mState <= LLTextureFetchWorker::WAIT_ON_WRITE))
+ {
+ delete_ok = false;
+ }
+ return delete_ok;
}
-U32 LLTextureFetchWorker::calcWorkPriority()
+
+void LLTextureFetchWorker::removeFromCache()
{
- F32 priority_scale = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerImage::maxDecodePriority();
- U32 priority = (U32)(mPriority * priority_scale);
- return LLWorkerThread::PRIORITY_NORMAL | priority;
+ if (!mInLocalCache)
+ {
+ mFetcher->mTextureCache->removeFromCache(mID);
+ }
}
-void LLTextureFetchWorker::setDesiredDiscard(S32 discard)
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool LLTextureFetchWorker::processSimulatorPackets()
{
- if (mDesiredDiscard != discard)
+ if (mLastPacket >= mFirstPacket)
{
- mDesiredDiscard = discard;
- if (!haveWork())
+ S32 buffer_size = mFormattedImage->getDataSize();
+ for (S32 i = mFirstPacket; i<=mLastPacket; i++)
{
- addWork(0, calcWorkPriority());
+ buffer_size += mPackets[i]->mSize;
+ }
+ bool have_all_data = mLastPacket >= mTotalPackets-1;
+ llassert_always(mRequestedSize > 0);
+ if (buffer_size >= mRequestedSize || have_all_data)
+ {
+ /// We have enough (or all) data
+ if (have_all_data)
+ {
+ mHaveAllData = TRUE;
+ }
+ S32 cur_size = mFormattedImage->getDataSize();
+ if (buffer_size > cur_size)
+ {
+ /// We have new data
+ U8* buffer = new U8[buffer_size];
+ S32 offset = 0;
+ if (cur_size > 0 && mFirstPacket > 0)
+ {
+ memcpy(buffer, mFormattedImage->getData(), cur_size);
+ offset = cur_size;
+ }
+ for (S32 i=mFirstPacket; i<=mLastPacket; i++)
+ {
+ memcpy(buffer + offset, mPackets[i]->mData, mPackets[i]->mSize);
+ offset += mPackets[i]->mSize;
+ }
+ // NOTE: setData releases current data
+ mFormattedImage->setData(buffer, buffer_size);
+ }
+ mLoadedDiscard = mRequestedDiscard;
+ return true;
}
}
+ return false;
}
-void LLTextureFetchWorker::setImagePriority(F32 priority)
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success)
{
- if (priority != mPriority)
+ LLMutexLock lock(&mWorkMutex);
+ if (success)
{
- mPriority = priority;
- setPriority(calcWorkPriority());
+ mURL = data.asString();
}
+ mLoaded = TRUE;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
-void LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block)
{
- PacketData* packet = new PacketData(data, size);
-
- lockWorkData();
- if (index >= (S32)mPackets.size())
+ LLMutexLock lock(&mWorkMutex);
+ llassert_always(mRequested);
+// llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl;
+ if (mLoaded)
{
- mPackets.resize(index+1, (PacketData*)NULL); // initializes v to NULL pointers
+ llwarns << "Duplicate callback for " << mID.asString() << llendl;
+ return; // ignore duplicate callback
}
- if (mPackets[index] != NULL)
+ if (data_size >= 0)
{
- llwarns << "LLTextureFetchWorker::insertPacket called for duplicate packet: " << index << llendl;
+ if (data_size > 0)
+ {
+ mBuffer = new U8[data_size];
+ // *TODO: set the formatted image data here
+ memcpy(mBuffer, data, data_size);
+ mBufferSize += data_size;
+ if (data_size < mRequestedSize || last_block == true)
+ {
+ mHaveAllData = TRUE;
+ }
+ else if (data_size > mRequestedSize)
+ {
+ // *TODO: This will happen until we fix LLCurl::getByteRange()
+ llinfos << "HUH?" << llendl;
+ mHaveAllData = TRUE;
+ mFormattedImage->deleteData();
+ mBufferSize = data_size;
+ }
+ }
+ else
+ {
+ // We requested data but received none (and no error),
+ // so presumably we have all of it
+ mHaveAllData = TRUE;
+ }
+ mRequestedSize = data_size;
}
- mPackets[index] = packet;
- while (mLastPacket+1 < (S32)mPackets.size() && mPackets[mLastPacket+1] != NULL)
+ else
{
- ++mLastPacket;
+ mRequestedSize = -1; // error
}
- unlockWorkData();
+ mLoaded = TRUE;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
-// Called from LLWorkerThread::processRequest()
-bool LLTextureFetchWorker::doWork(S32 param)
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* image,
+ S32 imagesize, BOOL islocal)
{
- switch(mState)
- {
- case INIT:
- {
- // fall through
- }
- case LOAD_FROM_CACHE:
- {
- // Load any existing data from the cache
- if (mFileHandle == LLVFSThread::nullHandle())
- {
- bool res = startVFSLoad(gVFS, LLAssetType::AT_TEXTURE);
- if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE_TGA);
- if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE);
- if (!res)
- {
- // Didn't load from VFS
- mFormattedImage = new LLImageJ2C;
- mState = LOAD_FROM_SIMULATOR;
- }
- }
- if (mFileHandle != LLVFSThread::nullHandle())
- {
- if (!loadFromVFS())
- {
- return false; // not done
- }
- if (!mLoaded)
- {
- llwarns << "Load from VFS failed on: " << mID << llendl;
- return true;
- }
- bool res = mFormattedImage->setData(mBuffer, mBufferSize);
- if (!res)
- {
- llwarns << "loadLocalImage() - setData() failed" << llendl;
- mFormattedImage->deleteData();
- return true;
- }
- // Successfully loaded
- if (mFormattedImage->getDiscardLevel() <= mRequestedDiscard)
- {
- // we have enough data, decode it
- mState = DECODE_IMAGE;
- mRequestedSize = mBufferSize;
- }
- else
- {
- // need more data
- mState = LOAD_FROM_SIMULATOR;
- mRequestedSize = mFormattedImage->calcDataSize(mRequestedDiscard);
- }
- }
- return false;
- }
- case LOAD_FROM_SIMULATOR:
- {
- if (!mRequested)
- {
- lockQueue();
- sNetworkQueue.insert(this);
- unlockQueue();
- mRequested = TRUE;
- }
- if (processSimulatorPackets())
- {
- mState = WRITE_TO_VFS;
- }
- return false;
- }
- case WRITE_TO_VFS:
- {
- mState = DECODE_IMAGE;
- // fall through
- }
- case DECODE_IMAGE:
- {
- startDecode();
- mState = DECODE_IMAGE_UPDATE;
- // fall through
- }
- case DECODE_IMAGE_UPDATE:
- {
- if (decodeImage())
- {
- mState = DONE;
- }
- return false;
- }
- case DONE:
- {
- // Do any cleanup here
- // Destroy the formatted image, we don't need it any more (raw image is still valid)
- mFormattedImage = NULL;
- mIdleTimer.reset();
- return true;
- }
- default:
- {
- llerrs << "LLTextureFetchWorker::doWork() has illegal state" << llendl;
- return true;
- }
+ LLMutexLock lock(&mWorkMutex);
+ if (success)
+ {
+ llassert_always(imagesize > 0);
+ mFileSize = imagesize;
+ mFormattedImage = image;
+ mImageCodec = image->getCodec();
+ mInLocalCache = islocal;
+ if (mFileSize != 0 && mFormattedImage->getDataSize() >= mFileSize)
+ {
+ mHaveAllData = TRUE;
+ }
}
+ mLoaded = TRUE;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
-// Called from MAIN thread
-void LLTextureFetchWorker::startWork(S32 param)
+void LLTextureFetchWorker::callbackCacheWrite(bool success)
{
+ LLMutexLock lock(&mWorkMutex);
+ mWritten = TRUE;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
-void LLTextureFetchWorker::endWork(S32 param, bool aborted)
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureFetchWorker::callbackDecoded(bool success)
{
+// llinfos << mID << " : DECODE COMPLETE " << llendl;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
//////////////////////////////////////////////////////////////////////////////
-bool LLTextureFetchWorker::startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type)
+void LLTextureFetchWorker::startDecode()
{
- // Start load from VFS if it's there
- if (vfs->getExists(mID, asset_type))
+ mRawImage = NULL;
+ mAuxImage = NULL;
+ llassert_always(mImageWorker == NULL);
+ llassert_always(mFormattedImage.notNull());
+ S32 discard = mHaveAllData ? 0 : mLoadedDiscard;
+ U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
+// llinfos << mID << " : DECODE STARTED : " << discard
+// << " Pri: " << priority
+// << " Components:" << (S32)mFormattedImage->getComponents() << llendl;
+ mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this));
+}
+
+bool LLTextureFetchWorker::decodeImage()
+{
+ llassert_always(mImageWorker);
+ bool res = true;
+ if (mRawImage.isNull())
{
- mBufferSize = vfs->getSize(mID, asset_type);
- mBuffer = new U8[mBufferSize];
- mFileHandle = LLVFSThread::sLocal->read(vfs, mID, asset_type, mBuffer, 0, mBufferSize); /* Flawfinder: ignore */
- if (mFileHandle == LLVFSThread::nullHandle())
+ res = false;
+ if (mImageWorker->requestDecodedData(mRawImage, -1))
{
- llwarns << "loadLocalImage() - vfs read failed in static VFS: " << mID << llendl;
- delete mBuffer;
- mBuffer = NULL;
- return false;
+ res = true;
+// llinfos << mID << " : BASE DECODE FINISHED" << llendl;
}
- if (asset_type == LLAssetType::AT_TEXTURE_TGA)
+ }
+ if (res &&
+ (mRawImage.notNull() && mRawImage->getDataSize() > 0) &&
+ (mNeedsAux && mAuxImage.isNull()))
+ {
+ res = false;
+ if (mImageWorker->requestDecodedAuxData(mAuxImage, 4, -1))
{
- mFormattedImage = new LLImageTGA;
+ res = true;
+// llinfos << mID << " : AUX DECODE FINISHED" << llendl;
}
- else if (asset_type == LLAssetType::AT_TEXTURE)
+ }
+ if (res)
+ {
+ if ((mRawImage.notNull() && mRawImage->getDataSize() > 0) &&
+ (!mNeedsAux || (mAuxImage.notNull() && mAuxImage->getDataSize() > 0)))
{
- mFormattedImage = new LLImageJ2C;
+ mDecodedDiscard = mFormattedImage->getDiscardLevel();
+// llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl;
}
else
{
- llerrs << "LLTextureFetchWorker::startVFSLoad called with bad asset type: " << asset_type << llendl;
+ llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl;
+ removeFromCache();
}
- return true;
+ mImageWorker->scheduleDelete();
+ mImageWorker = NULL;
}
- return false;
+ else
+ {
+ U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
+ mImageWorker->setPriority(image_priority);
+ //llinfos << worker->mID << " : DECODE PRIORITY : " << priority << llendl;
+ }
+ return res;
}
-bool LLTextureFetchWorker::loadFromVFS()
+//////////////////////////////////////////////////////////////////////////////
+
+bool LLTextureFetchWorker::writeToCacheComplete()
{
- LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE);
+ // Complete write to cache
+ if (mCacheWriteHandle != LLTextureCache::nullHandle())
+ {
+ if (!mWritten)
+ {
+ return false;
+ }
+ if (mFetcher->mTextureCache->writeComplete(mCacheWriteHandle))
+ {
+ mCacheWriteHandle = LLTextureCache::nullHandle();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
+}
- llassert(mLoaded == FALSE);
-
- // Check loading status
- LLVFSThread::status_t status = LLVFSThread::sLocal->getRequestStatus(mFileHandle);
- if (status == LLVFSThread::STATUS_QUEUED || status == LLVFSThread::STATUS_INPROGRESS)
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+// public
+
+LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded)
+ : LLWorkerThread("TextureFetch", threaded),
+ mDebugCount(0),
+ mDebugPause(0),
+ mTextureCache(cache),
+ mQueueMutex(getAPRPool())
+{
+}
+
+LLTextureFetch::~LLTextureFetch()
+{
+ // ~LLQueuedThread() called here
+}
+
+bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 priority,
+ S32 w, S32 h, S32 c, S32 discard, bool needs_aux)
+{
+ LLTextureFetchWorker* worker = NULL;
+ LLMutexLock lock(&mQueueMutex);
+ map_t::iterator iter = mRequestMap.find(id);
+ if (iter != mRequestMap.end())
{
- return false;
+ worker = iter->second;
+ if (worker->mHost != host)
+ {
+ llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts" << llendl;
+ removeRequest(worker, false);
+ worker = NULL;
+ }
}
- else if (status == LLVFSThread::STATUS_COMPLETE)
+ // If the requester knows the dimentions of the image,
+ // this will calculate how much data we need without having to parse the header
+ S32 desired_size;
+ if (w*h*c > 0)
{
- mLoaded = TRUE;
- return true;
+ desired_size = LLImageJ2C::calcDataSizeJ2C(w, h, c, discard);
}
else
{
- llwarns << "loadLocalImage() - vfs read failed" << llendl;
- LLVFSThread::Request* req = (LLVFSThread::Request*)LLVFSThread::sLocal->getRequest(mFileHandle);
- if (req && mFormattedImage.notNull())
+ desired_size = FIRST_PACKET_SIZE;
+ discard = MAX_DISCARD_LEVEL;
+ }
+ if (worker)
+ {
+ if (worker->wasAborted())
{
- LLVFS* vfs = req->getVFS();
- LLAssetType::EType asset_type = mFormattedImage->getCodec() == IMG_CODEC_TGA ? LLAssetType::AT_TEXTURE_TGA : LLAssetType::AT_TEXTURE;
- vfs->removeFile(mID, asset_type);
+ return false; // need to wait for previous aborted request to complete
}
- return true;
+ worker->lockWorkData();
+ worker->setImagePriority(priority);
+ worker->setDesiredDiscard(discard, desired_size);
+ worker->unlockWorkData();
+ }
+ else
+ {
+ worker = new LLTextureFetchWorker(this, id, host, priority, discard, desired_size);
+ mRequestMap[id] = worker;
+ }
+ worker->mActiveCount++;
+ worker->mNeedsAux = needs_aux;
+// llinfos << "REQUESTED: " << id << " Discard: " << discard << llendl;
+ return true;
+}
+
+void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
+{
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker)
+ {
+ removeRequest(worker, cancel);
}
}
+// protected
-//////////////////////////////////////////////////////////////////////////////
+// call lockQueue() first!
+void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
+{
+ if (mRequestMap.find(worker->mID) != mRequestMap.end())
+ {
+ // only add to the queue if in the request map
+ // i.e. a delete has not been requested
+ mNetworkQueue.insert(worker->mID);
+ }
+}
-bool LLTextureFetchWorker::processSimulatorPackets()
+// call lockQueue() first!
+void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker)
+{
+ mNetworkQueue.erase(worker->mID);
+}
+
+// call lockQueue() first!
+void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
+{
+ mRequestMap.erase(worker->mID);
+ size_t erased = mNetworkQueue.erase(worker->mID);
+ if (cancel && erased > 0)
+ {
+ mCancelQueue[worker->mHost].insert(worker->mID);
+ }
+ worker->scheduleDelete();
+}
+
+// call lockQueue() first!
+LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
+{
+ LLTextureFetchWorker* res = NULL;
+ map_t::iterator iter = mRequestMap.find(id);
+ if (iter != mRequestMap.end())
+ {
+ res = iter->second;
+ }
+ return res;
+}
+
+
+bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
+ LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
{
bool res = false;
- lockWorkData();
- if (mLastPacket >= 0)
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker)
{
- S32 data_size = 0;
- for (S32 i = 0; i<=mLastPacket; i++)
+ if (worker->wasAborted())
{
- data_size += mPackets[i]->mSize;
+ res = true;
}
- if (data_size >= mRequestedSize || mLastPacket == mTotalPackets)
+ else if (!worker->haveWork())
{
- /// We have enough (or all) data, copy it into mBuffer
- if (mBufferSize < data_size)
+ // Should only happen if we set mDebugPause...
+ if (!mDebugPause)
{
- delete mBuffer;
- mBuffer = new U8[data_size];
- mBufferSize = data_size;
+ worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
}
- S32 offset = 0;
- for (S32 i = 0; i<=mLastPacket; i++)
+ }
+ else if (worker->checkWork())
+ {
+ discard_level = worker->mDecodedDiscard;
+ raw = worker->mRawImage; worker->mRawImage = NULL;
+ aux = worker->mAuxImage; worker->mAuxImage = NULL;
+ res = true;
+ }
+ else
+ {
+ worker->lockWorkData();
+ if ((worker->mDecodedDiscard >= 0) &&
+ (worker->mDecodedDiscard < discard_level || discard_level < 0) &&
+ (worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE))
{
- if (mPackets[i]->mData != NULL)
- {
- memcpy(mBuffer + offset, mPackets[i]->mData, mPackets[i]->mSize); /* Flawfinder: ignore */
- offset += mPackets[i]->mSize;
- }
+ // Not finished, but data is ready
+ discard_level = worker->mDecodedDiscard;
+ if (worker->mRawImage) raw = worker->mRawImage;
+ if (worker->mAuxImage) aux = worker->mAuxImage;
}
- res = true;
+ worker->unlockWorkData();
}
}
- unlockWorkData();
+ else
+ {
+ res = true;
+ }
+ return res;
+}
+
+bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
+{
+ bool res = false;
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker)
+ {
+ worker->lockWorkData();
+ worker->setImagePriority(priority);
+ worker->unlockWorkData();
+ res = true;
+ }
return res;
}
//////////////////////////////////////////////////////////////////////////////
-void LLTextureFetchWorker::startDecode()
+//virtual
+S32 LLTextureFetch::update(U32 max_time_ms)
{
- mRawImage = NULL;
- mAuxImage = NULL;
+ S32 res;
+ res = LLWorkerThread::update(max_time_ms);
+
+ const F32 REQUEST_TIME = 1.f;
+
+ // Periodically, gather the list of textures that need data from the network
+ // And send the requests out to the simulators
+ if (mNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME)
+ {
+ mNetworkTimer.reset();
+ sendRequestListToSimulators();
+ }
+
+#if 0 // Currently this logic is handled in LLViewer
+ {
+ LLMutexLock lock(&mQueueMutex);
+ const F32 MIN_IDLE_TIME = 1.f * 60.f; // 1 minute
+ const F32 MAX_IDLE_TIME = 5.f * 60.f; // 5 minutes
+ const S32 MIN_IDLE_COUNT = 16; // always keep last 16 idle requests
+ const F32 MAX_IDLE_COUNT = 1024; // max number of idle requests
+ // Remove any old requests (releasing their raw data)
+ typedef std::pair<F32, LLTextureFetchWorker*> idle_pair;
+ typedef std::set<idle_pair, compare_pair_greater<F32,LLTextureFetchWorker*> > idle_set;
+ idle_set remove_set;
+ for (map_t::iterator iter = mRequestMap.begin(); iter != mRequestMap.end(); ++iter)
+ {
+ LLTextureFetchWorker* worker = iter->second;
+ if (worker->mActiveCount > 0)
+ continue;
+ if (worker->haveWork())
+ continue;
+ F32 idletime = worker->mIdleTimer.getElapsedTimeF32();
+ if (idletime < MIN_IDLE_TIME)
+ continue;
+ remove_set.insert(std::make_pair(idletime, worker));
+ }
+ S32 num_left = remove_set.size();
+ for (idle_set::iterator iter = remove_set.begin(); iter != remove_set.end(); ++iter)
+ {
+ if (num_left <= MIN_IDLE_COUNT)
+ break;
+ if (iter->first < MAX_IDLE_TIME &&
+ num_left < MAX_IDLE_COUNT)
+ break;
+ num_left--;
+ }
+ }
+#endif
+
+ return res;
}
-bool LLTextureFetchWorker::decodeImage()
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureFetch::sendRequestListToSimulators()
{
- const F32 MAX_DECODE_TIME = .001f; // 1 ms
- if (mRawImage->getDataSize() == 0)
+ const S32 IMAGES_PER_REQUEST = 50;
+ const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp
+ const F32 MIN_REQUEST_TIME = 1.0f;
+ const F32 MIN_DELTA_PRIORITY = 1000.f;
+
+ LLMutexLock lock(&mQueueMutex);
+
+ // Send requests
+ typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
+ typedef std::map< LLHost, request_list_t > work_request_map_t;
+ work_request_map_t requests;
+ for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ++iter)
{
- if (!mFormattedImage->requestDecodedData(mRawImage, -1, MAX_DECODE_TIME))
+ LLTextureFetchWorker* req = getWorker(*iter);
+ if (req->mID == mDebugID)
{
- return false;
+ mDebugCount++; // for setting breakpoints
+ }
+ if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1)
+ {
+ // We have all the packets... make sure this is high priority
+ req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
+ continue;
+ }
+ F32 elapsed = req->mRequestedTimer.getElapsedTimeF32();
+ F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
+ if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
+ (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
+ (elapsed >= LAZY_FLUSH_TIMEOUT))
+ {
+ requests[req->mHost].insert(req);
}
- mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image
}
- if (mNeedsAux && mAuxImage->getDataSize() == 0)
+ for (work_request_map_t::iterator iter1 = requests.begin();
+ iter1 != requests.end(); ++iter1)
{
- if (!mFormattedImage->requestDecodedAuxData(mAuxImage, 4, -1, MAX_DECODE_TIME ))
+ LLHost host = iter1->first;
+ // invalid host = use agent host
+ if (host == LLHost::invalid)
{
- return false;
+ host = gAgent.getRegionHost();
+ }
+
+ S32 request_count = 0;
+ for (request_list_t::iterator iter2 = iter1->second.begin();
+ iter2 != iter1->second.end(); ++iter2)
+ {
+ LLTextureFetchWorker* req = *iter2;
+ if (0 == request_count)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_RequestImage);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ S32 packet = req->mLastPacket + 1;
+ gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
+ gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
+ gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard);
+ gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
+ gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
+ U8 type = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
+ gMessageSystem->addU8Fast(_PREHASH_Type, type);
+// llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
+// << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl;
+
+ req->lockWorkData();
+ req->mSimRequestedDiscard = req->mDesiredDiscard;
+ req->mRequestedPriority = req->mImagePriority;
+ req->mRequestedTimer.reset();
+ req->unlockWorkData();
+ request_count++;
+ if (request_count >= IMAGES_PER_REQUEST)
+ {
+// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+ gMessageSystem->sendSemiReliable(host, NULL, NULL);
+ request_count = 0;
+ break; // only send the top requests
+ }
+ }
+ if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
+ {
+// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+ gMessageSystem->sendSemiReliable(host, NULL, NULL);
}
- mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image
}
- mDecodedDiscard = mFormattedImage->getDiscardLevel();
- return true;
+
+ // Send cancelations
+ if (!mCancelQueue.empty())
+ {
+ for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
+ iter1 != mCancelQueue.end(); ++iter1)
+ {
+ LLHost host = iter1->first;
+ // invalid host = use agent host
+ if (host == LLHost::invalid)
+ {
+ host = gAgent.getRegionHost();
+ }
+ S32 request_count = 0;
+ for (queue_t::iterator iter2 = iter1->second.begin();
+ iter2 != iter1->second.end(); ++iter2)
+ {
+ if (0 == request_count)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_RequestImage);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
+ gMessageSystem->addUUIDFast(_PREHASH_Image, *iter2);
+ gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, -1);
+ gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, 0);
+ gMessageSystem->addU32Fast(_PREHASH_Packet, 0);
+ gMessageSystem->addU8Fast(_PREHASH_Type, 0);
+// llinfos << "CANCELING IMAGE REQUEST: " << (*iter2) << llendl;
+
+ request_count++;
+ if (request_count >= IMAGES_PER_REQUEST)
+ {
+ gMessageSystem->sendSemiReliable(host, NULL, NULL);
+ request_count = 0;
+ }
+ }
+ if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
+ {
+ gMessageSystem->sendSemiReliable(host, NULL, NULL);
+ }
+ }
+ mCancelQueue.clear();
+ }
}
//////////////////////////////////////////////////////////////////////////////
-#if 0
-// static
-void LLTextureFetchWorker::receiveImageHeader(LLMessageSystem *msg, void **user_data)
+bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
{
- LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
+ mRequestedTimer.reset();
+ if (index >= mTotalPackets)
+ {
+ llwarns << "Received Image Packet " << index << " > max: " << mTotalPackets << " Skipping. " << llendl;
+ return false;
+ }
+ if (index > 0 && index < mTotalPackets-1 && size != MAX_IMG_PACKET_SIZE)
+ {
+ llwarns << "Received bad sized packet: " << index << ", " << size << " != " << MAX_IMG_PACKET_SIZE << " Skipping. " << llendl;
+ return false;
+ }
- // Receive image header, copy into image object and decompresses
- // if this is a one-packet image.
+ if (index >= (S32)mPackets.size())
+ {
+ mPackets.resize(index+1, (PacketData*)NULL); // initializes v to NULL pointers
+ }
+ else if (mPackets[index] != NULL)
+ {
+// llwarns << "LLTextureFetchWorker::insertPacket called for duplicate packet: " << index << llendl;
+ return false;
+ }
- gImageList.sTextureBits += msg->getReceiveBytes();
- gImageList.sTexturePackets++;
+ mPackets[index] = new PacketData(data, size);
+ while (mLastPacket+1 < (S32)mPackets.size() && mPackets[mLastPacket+1] != NULL)
+ {
+ ++mLastPacket;
+ }
+ return true;
+}
- LLUUID id;
- msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
-// LLString ip_string(u32_to_ip_string(msg->getSenderIP()));
-
- LLTextureFetchWorker* worker = getActiveWorker(id);
+bool LLTextureFetch::receiveImageHeader(const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
+ U16 data_size, U8* data)
+{
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
if (!worker)
{
- llwarns << "receiveImageHeader for non active worker: " << id << llendl;
- return;
+// llwarns << "receiveImageHeader for non active worker: " << id << llendl;
+ return false;
}
- worker->mRequestedTimer.reset();
-
// check to see if we've gotten this packet before
if (worker->mLastPacket != -1)
{
- llwarns << "Img: " << id << ":" << " Duplicate Image Header" << llendl;
- return;
+// llwarns << "Img: " << id << ":" << " Duplicate Image Header" << llendl;
+ return false;
}
- // Copy header data into image object
worker->lockWorkData();
- msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, image->mDataCodec);
- msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, image->mTotalPackets);
- msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, image->mTotalBytes);
- if (0 == image->mTotalPackets)
+
+ // Copy header data into image object
+ worker->mImageCodec = codec;
+ worker->mTotalPackets = packets;
+ worker->mFileSize = (S32)totalbytes;
+ llassert_always(totalbytes > 0);
+ bool res = false;
+ if (data_size)
{
- llwarns << "Img: " << id << ":" << " Number of packets is 0" << llendl;
+ llassert(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);
+ res = worker->insertPacket(0, data, data_size);
+ worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
}
worker->unlockWorkData();
+ return res;
+}
- U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
+bool LLTextureFetch::receiveImagePacket(const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
+{
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (!worker)
+ {
+// llwarns << "receiveImagePacket " << packet_num << " for non active worker: " << id << llendl;
+ return false;
+ }
+ if (worker->mLastPacket == -1)
+ {
+// llwarns << "Img: " << id << ":" << " Image Packet " << packet_num << " received before header" << llendl;
+ return false;
+ }
+
+ bool res = false;
if (data_size)
{
- U8 *data = new U8[data_size];
- msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
- worker->insertPacket(0, data, data_size)
+ worker->lockWorkData();
+ res = worker->insertPacket(packet_num, data, data_size);
+ worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
+ worker->unlockWorkData();
}
+ return res;
}
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLTextureFetchWorker::receiveImagePacket(LLMessageSystem *msg, void **user_data)
+//////////////////////////////////////////////////////////////////////////////
+
+S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p,
+ U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p)
{
- LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE);
- LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
+ S32 state = LLTextureFetchWorker::INVALID;
+ F32 data_progress = 0.0f;
+ F32 requested_priority = 0.0f;
+ F32 fetch_dtime = 999999.f;
+ F32 request_dtime = 999999.f;
+ U32 fetch_priority = 0;
- gImageList.sTextureBits += msg->getReceiveBytes();
- gImageList.sTexturePackets++;
-
- LLUUID id;
- msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
-// LLString ip_string(u32_to_ip_string(msg->getSenderIP()));
-
- U16 packet_num;
- msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num);
-
- LLTextureFetchWorker* worker = getActiveWorker(id);
- if (!worker)
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker && worker->haveWork())
{
- llwarns << "receiveImageHeader for non active worker: " << id << llendl;
- return;
+ worker->lockWorkData();
+ state = worker->mState;
+ fetch_dtime = worker->mFetchTimer.getElapsedTimeF32();
+ request_dtime = worker->mRequestedTimer.getElapsedTimeF32();
+ if (worker->mFileSize > 0)
+ {
+ if (state == LLTextureFetchWorker::LOAD_FROM_SIMULATOR)
+ {
+ S32 data_size = FIRST_PACKET_SIZE + (worker->mLastPacket-1) * MAX_IMG_PACKET_SIZE;
+ data_size = llmax(data_size, 0);
+ data_progress = (F32)data_size / (F32)worker->mFileSize;
+ }
+ else if (worker->mFormattedImage.notNull())
+ {
+ data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize;
+ }
+ }
+ if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA)
+ {
+ requested_priority = worker->mRequestedPriority;
+ }
+ else
+ {
+ requested_priority = worker->mImagePriority;
+ }
+ fetch_priority = worker->getPriority();
+ worker->unlockWorkData();
}
- worker->mRequestedTimer.reset();
+ data_progress_p = data_progress;
+ requested_priority_p = requested_priority;
+ fetch_priority_p = fetch_priority;
+ fetch_dtime_p = fetch_dtime;
+ request_dtime_p = request_dtime;
+ return state;
+}
- U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
- if (data_size)
+void LLTextureFetch::dump()
+{
+ llinfos << "LLTextureFetch REQUESTS:" << llendl;
+ for (request_queue_t::iterator iter = mRequestQueue.begin();
+ iter != mRequestQueue.end(); ++iter)
{
- U8 *data = new U8[data_size];
- msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
- worker->insertPacket(0, data, data_size)
+ LLQueuedThread::QueuedRequest* qreq = *iter;
+ LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq;
+ LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass();
+ llinfos << " ID: " << worker->mID
+ << " PRI: " << llformat("0x%08x",wreq->getPriority())
+ << " STATE: " << worker->sStateDescs[worker->mState]
+ << llendl;
}
}
-#endif
- //////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 9d841ae23a..b3510d9e82 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -9,20 +9,77 @@
#ifndef LL_LLTEXTUREFETCH_H
#define LL_LLTEXTUREFETCH_H
+#include "lldir.h"
+#include "llimage.h"
+#include "lluuid.h"
#include "llworkerthread.h"
class LLViewerImage;
+class LLTextureFetchWorker;
+class LLTextureCache;
+class LLHost;
// Interface class
-class LLTextureFetch
+class LLTextureFetch : public LLWorkerThread
{
+ friend class LLTextureFetchWorker;
+
public:
- static void initClass();
- static void updateClass();
- static void cleanupClass();
+ LLTextureFetch(LLTextureCache* cache, bool threaded);
+ ~LLTextureFetch();
- static LLWorkerClass::handle_t addRequest(LLImageFormatted* image, S32 discard);
- static bool getRequestFinished(LLWorkerClass::handle_t handle);
+ /*virtual*/ S32 update(U32 max_time_ms);
+
+ bool createRequest(const LLUUID& id, const LLHost& host, F32 priority,
+ S32 w, S32 h, S32 c, S32 discard, bool needs_aux);
+ void deleteRequest(const LLUUID& id, bool cancel);
+ bool getRequestFinished(const LLUUID& id, S32& discard_level,
+ LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
+ bool updateRequestPriority(const LLUUID& id, F32 priority);
+
+ bool receiveImageHeader(const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
+ bool receiveImagePacket(const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
+
+ // Debug
+ S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
+ U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p);
+ void dump();
+ S32 getNumRequests() { return mRequestMap.size(); }
+
+ // Public for access by callbacks
+ void lockQueue() { mQueueMutex.lock(); }
+ void unlockQueue() { mQueueMutex.unlock(); }
+ LLTextureFetchWorker* getWorker(const LLUUID& id);
+
+protected:
+ void addToNetworkQueue(LLTextureFetchWorker* worker);
+ void removeFromNetworkQueue(LLTextureFetchWorker* worker);
+ void removeRequest(LLTextureFetchWorker* worker, bool cancel);
+
+private:
+ void sendRequestListToSimulators();
+
+public:
+ LLUUID mDebugID;
+ S32 mDebugCount;
+ BOOL mDebugPause;
+
+private:
+ LLMutex mQueueMutex;
+
+ LLTextureCache* mTextureCache;
+
+ // Map of all requests by UUID
+ typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
+ map_t mRequestMap;
+
+ // Set of requests that require network data
+ typedef std::set<LLUUID> queue_t;
+ queue_t mNetworkQueue;
+ typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t;
+ cancel_queue_t mCancelQueue;
+
+ LLFrameTimer mNetworkTimer;
};
#endif LL_LLTEXTUREFETCH_H
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index d115cf1158..f051236fba 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -14,46 +14,510 @@
#include "llrect.h"
#include "llerror.h"
-
-#include "viewer.h"
+#include "lllfsthread.h"
#include "llui.h"
+#include "llimageworker.h"
-#include "llviewerimagelist.h"
+#include "llhoverview.h"
#include "llselectmgr.h"
+#include "lltexlayer.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "lltexturetable.h"
#include "llviewerobject.h"
#include "llviewerimage.h"
-#include "llhoverview.h"
+#include "llviewerimagelist.h"
+#include "viewer.h"
+
+extern F32 texmem_lower_bound_scale;
LLTextureView *gTextureView = NULL;
//static
std::set<LLViewerImage*> LLTextureView::sDebugImages;
+////////////////////////////////////////////////////////////////////////////
+
+static LLString title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max");
+static LLString title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max");
+static LLString title_string2("State");
+static LLString title_string3("Pkt Bnd");
+static LLString title_string4(" W x H (Dis) Mem");
+
+static S32 title_x1 = 0;
+static S32 title_x2 = 440;
+static S32 title_x3 = title_x2 + 40;
+static S32 title_x4 = title_x3 + 50;
+static S32 texture_bar_height = 8;
+
+////////////////////////////////////////////////////////////////////////////
+
+class LLTextureBar : public LLView
+{
+public:
+ LLPointer<LLViewerImage> mImagep;
+ S32 mHilite;
+
+public:
+ LLTextureBar(const std::string& name, const LLRect& r, LLTextureView* texview)
+ : LLView(name, r, FALSE),
+ mHilite(0),
+ mTextureView(texview)
+ {
+ }
+
+ virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEXTURE_BAR; }
+ virtual LLString getWidgetTag() const { return LL_TEXTURE_BAR_TAG; }
+
+ virtual void draw();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual LLRect getRequiredRect(); // Return the height of this object, given the set options.
+
// Used for sorting
-struct SortTextureBars
+ struct sort
+ {
+ bool operator()(const LLView* i1, const LLView* i2)
+ {
+ LLTextureBar* bar1p = (LLTextureBar*)i1;
+ LLTextureBar* bar2p = (LLTextureBar*)i2;
+ LLViewerImage *i1p = bar1p->mImagep;
+ LLViewerImage *i2p = bar2p->mImagep;
+ F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
+ F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
+ if (pri1 > pri2)
+ return true;
+ else if (pri2 > pri1)
+ return false;
+ else
+ return i1p->getID() < i2p->getID();
+ }
+ };
+
+ struct sort_fetch
+ {
+ bool operator()(const LLView* i1, const LLView* i2)
+ {
+ LLTextureBar* bar1p = (LLTextureBar*)i1;
+ LLTextureBar* bar2p = (LLTextureBar*)i2;
+ LLViewerImage *i1p = bar1p->mImagep;
+ LLViewerImage *i2p = bar2p->mImagep;
+ U32 pri1 = i1p->mFetchPriority;
+ U32 pri2 = i2p->mFetchPriority;
+ if (pri1 > pri2)
+ return true;
+ else if (pri2 > pri1)
+ return false;
+ else
+ return i1p->getID() < i2p->getID();
+ }
+ };
+private:
+ LLTextureView* mTextureView;
+};
+
+void LLTextureBar::draw()
{
- bool operator()(const LLView* i1, const LLView* i2)
- {
- LLTextureBar* bar1p = (LLTextureBar*)i1;
- LLTextureBar* bar2p = (LLTextureBar*)i2;
- LLViewerImage *i1p = bar1p->mImagep;
- LLViewerImage *i2p = bar2p->mImagep;
- F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
- F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
- if (pri1 > pri2)
- return true;
- else if (pri2 > pri1)
- return false;
+ if (!mImagep)
+ {
+ return;
+ }
+
+ LLColor4 color;
+ if (mImagep->getID() == gTextureFetch->mDebugID)
+ {
+ color = LLColor4::cyan2;
+ }
+ else if (mHilite)
+ {
+ S32 idx = llclamp(mHilite,1,4);
+ if (idx==1) color = LLColor4::yellow;
+ if (idx==2) color = LLColor4::cyan;
+ if (idx==3) color = LLColor4::magenta;
+ if (idx==4) color = LLColor4::blue;
+ }
+ else if (mImagep->getBoostLevel())
+ {
+ color = LLColor4::magenta;
+ }
+ else if (mImagep->mDontDiscard)
+ {
+ color = LLColor4::pink2;
+ }
+ else if (!mImagep->getUseMipMaps())
+ {
+ color = LLColor4::green4;
+ }
+ else if (mImagep->getDecodePriority() == 0.0f)
+ {
+ color = LLColor4::grey; color[VALPHA] = .7f;
+ }
+ else
+ {
+ color = LLColor4::white; color[VALPHA] = .7f;
+ }
+
+ // We need to draw:
+ // The texture UUID or name
+ // The progress bar for the texture, highlighted if it's being download
+ // Various numerical stats.
+ char tex_str[256];
+ S32 left, right;
+ S32 top = 0;
+ S32 bottom = top + 6;
+ LLColor4 clr;
+
+ LLGLSUIDefault gls_ui;
+
+ // Get the name or UUID of the image.
+ gTextureTable.getName(mImagep->mID);
+
+ // Name, pixel_area, requested pixel area, decode priority
+ char uuid_str[255];
+ mImagep->mID.toString(uuid_str);
+ uuid_str[8] = 0;
+ if (mTextureView->mOrderFetch)
+ {
+ sprintf(tex_str, "%s %7.0f %d(%d) 0x%08x(%8.0f)",
+ uuid_str,
+ mImagep->mMaxVirtualSize,
+ mImagep->mDesiredDiscardLevel,
+ mImagep->mRequestedDiscardLevel,
+ mImagep->mFetchPriority,
+ mImagep->getDecodePriority());
+ }
+ else
+ {
+ sprintf(tex_str, "%s %7.0f %d(%d) %8.0f(0x%08x)",
+ uuid_str,
+ mImagep->mMaxVirtualSize,
+ mImagep->mDesiredDiscardLevel,
+ mImagep->mRequestedDiscardLevel,
+ mImagep->getDecodePriority(),
+ mImagep->mFetchPriority);
+ }
+
+ LLFontGL::sMonospace->renderUTF8(tex_str, 0, title_x1, mRect.getHeight(),
+ color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ // State
+ // Hack: mirrored from lltexturefetch.cpp
+ struct { const char* desc; LLColor4 color; } fetch_state_desc[] = {
+ { "---", LLColor4::red }, // INVALID
+ { "INI", LLColor4::white }, // INIT
+ { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE
+ { "DSK", LLColor4::blue }, // CACHE_POST
+ { "NET", LLColor4::green }, // LOAD_FROM_NETWORK
+ { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR
+ { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL
+ { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA
+ { "DEC", LLColor4::yellow },// DECODE_IMAGE
+ { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE
+ { "WRT", LLColor4::purple },// WRITE_TO_CACHE
+ { "WRT", LLColor4::orange },// WAIT_ON_WRITE
+ { "END", LLColor4::red }, // DONE
+#define LAST_STATE 12
+ { "CRE", LLColor4::magenta }, // LAST_STATE+1
+ { "FUL", LLColor4::green }, // LAST_STATE+2
+ { "BAD", LLColor4::red }, // LAST_STATE+3
+ { "MIS", LLColor4::red }, // LAST_STATE+4
+ { "---", LLColor4::white }, // LAST_STATE+5
+ };
+ const S32 fetch_state_desc_size = (S32)(sizeof(fetch_state_desc)/sizeof(fetch_state_desc[0]));
+ S32 state =
+ mImagep->mNeedsCreateTexture ? LAST_STATE+1 :
+ mImagep->mFullyLoaded ? LAST_STATE+2 :
+ mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 :
+ mImagep->mIsMissingAsset ? LAST_STATE+4 :
+ !mImagep->mIsFetching ? LAST_STATE+5 :
+ mImagep->mFetchState;
+ state = llclamp(state,0,fetch_state_desc_size-1);
+
+ LLFontGL::sMonospace->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, mRect.getHeight(),
+ fetch_state_desc[state].color,
+ LLFontGL::LEFT, LLFontGL::TOP);
+ LLGLSNoTexture gls_no_texture;
+
+ // Draw the progress bar.
+ S32 bar_width = 100;
+ S32 bar_left = 280;
+ left = bar_left;
+ right = left + bar_width;
+
+ glColor4f(0.f, 0.f, 0.f, 0.75f);
+ gl_rect_2d(left, top, right, bottom);
+
+ F32 data_progress = mImagep->mDownloadProgress;
+
+ if (data_progress > 0.0f)
+ {
+ // Downloaded bytes
+ right = left + llfloor(data_progress * (F32)bar_width);
+ if (right > left)
+ {
+ glColor4f(0.f, 0.f, 1.f, 0.75f);
+ gl_rect_2d(left, top, right, bottom);
+ }
+ }
+
+ S32 pip_width = 6;
+ S32 pip_space = 14;
+ S32 pip_x = title_x3 + pip_space/2;
+
+ // Draw the packet pip
+ F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32();
+ if (last_event < 1.f)
+ {
+ clr = LLColor4::white;
+ }
+ else
+ {
+ last_event = mImagep->mRequestDeltaTime;
+ if (last_event < 1.f)
+ {
+ clr = LLColor4::green;
+ }
else
- return i1p->getID() < i2p->getID();
+ {
+ last_event = mImagep->mFetchDeltaTime;
+ if (last_event < 1.f)
+ {
+ clr = LLColor4::yellow;
+ }
+ }
+ }
+ if (last_event < 1.f)
+ {
+ clr.setAlpha(1.f - last_event);
+ glColor4fv(clr.mV);
+ gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
+ }
+ pip_x += pip_width + pip_space;
+
+ // we don't want to show bind/resident pips for textures using the default texture
+ if (mImagep->getHasGLTexture())
+ {
+ // Draw the bound pip
+ last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime;
+ if (last_event < 1.f)
+ {
+ clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1;
+ clr.setAlpha(1.f - last_event);
+ glColor4fv(clr.mV);
+ gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
+ }
+ }
+ pip_x += pip_width + pip_space;
+
+
+ {
+ LLGLSUIDefault gls_ui;
+ // draw the packet data
+// {
+// LLString num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets);
+// LLFontGL::sMonospace->renderUTF8(num_str, 0, bar_left + 100, mRect.getHeight(), color,
+// LLFontGL::LEFT, LLFontGL::TOP);
+// }
+
+ // draw the image size at the end
+ {
+ LLString num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(),
+ mImagep->getDiscardLevel(), mImagep->mTextureMemory);
+ LLFontGL::sMonospace->renderUTF8(num_str, 0, title_x4, mRect.getHeight(), color,
+ LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ }
+
+}
+
+BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (mask & MASK_ALT)
+ {
+ gTextureFetch->mDebugID = mImagep->getID();
+ return TRUE;
+ }
+ return LLView::handleMouseDown(x,y,mask);
+}
+
+LLRect LLTextureBar::getRequiredRect()
+{
+ LLRect rect;
+
+ rect.mTop = texture_bar_height;
+
+ return rect;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+class LLGLTexMemBar : public LLView
+{
+public:
+ LLGLTexMemBar(const std::string& name, LLTextureView* texview)
+ : LLView(name, FALSE),
+ mTextureView(texview)
+ {
+ S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f);
+ setRect(LLRect(0,0,100,line_height * 4));
+ updateRect();
}
+
+ virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEX_MEM_BAR; };
+ virtual LLString getWidgetTag() const { return LL_GL_TEX_MEM_BAR_TAG; };
+
+ virtual void draw();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual LLRect getRequiredRect(); // Return the height of this object, given the set options.
+
+private:
+ LLTextureView* mTextureView;
};
+void LLGLTexMemBar::draw()
+{
+ S32 bound_mem = LLViewerImage::sBoundTextureMemory;
+ S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMem;
+ S32 total_mem = LLViewerImage::sTotalTextureMemory;
+ S32 max_total_mem = LLViewerImage::sMaxTotalTextureMem;
+ F32 discard_bias = LLViewerImage::sDesiredDiscardBias;
+ S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f);
+
+ //----------------------------------------------------------------------------
+ LLGLSUIDefault gls_ui;
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+
+ std::string text;
+ text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f",
+ total_mem/(1024*1024),
+ max_total_mem/(1024*1024),
+ bound_mem/(1024*1024),
+ max_bound_mem/(1024*1024),
+ discard_bias);
+
+ LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ //----------------------------------------------------------------------------
+ S32 bar_left = 380;
+ S32 bar_width = 200;
+ S32 top = line_height*3 - 2;
+ S32 bottom = top - 6;
+ S32 left = bar_left;
+ S32 right = left + bar_width;
+
+ F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f);
+
+ LLGLSNoTexture gls_no_texture;
+
+ glColor4f(0.5f, 0.5f, 0.5f, 0.75f);
+ gl_rect_2d(left, top, right, bottom);
+
+
+ left = bar_left;
+ right = left + llfloor(bound_mem * bar_scale);
+ if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale))
+ {
+ glColor4f(0.f, 1.f, 0.f, 0.75f);
+ }
+ else if (bound_mem < max_bound_mem)
+ {
+ glColor4f(1.f, 1.f, 0.f, 0.75f);
+ }
+ else
+ {
+ glColor4f(1.f, 0.f, 0.f, 0.75f);
+ }
+ gl_rect_2d(left, top, right, bottom);
+
+ bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
+
+ top = bottom - 2;
+ bottom = top - 6;
+ left = bar_left;
+ right = left + llfloor(total_mem * bar_scale);
+ if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale))
+ {
+ glColor4f(0.f, 1.f, 0.f, 0.75f);
+ }
+ else if (total_mem < max_total_mem)
+ {
+ glColor4f(1.f, 1.f, 0.f, 0.75f);
+ }
+ else
+ {
+ glColor4f(1.f, 0.f, 0.f, 0.75f);
+ }
+ gl_rect_2d(left, top, right, bottom);
+
+ //----------------------------------------------------------------------------
+
+ LLGLEnable tex(GL_TEXTURE_2D);
+
+ text = llformat("Textures: Count: %d Fetch: %d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d",
+ gImageList.getNumImages(),
+ gTextureFetch->getNumRequests(), gTextureFetch->getNumDeletes(),
+ gTextureCache->getNumReads(), gTextureCache->getNumWrites(),
+ LLLFSThread::sLocal->getPending(),
+ LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(),
+ LLImageRaw::sRawImageCount);
+
+ LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ S32 dx1 = 0;
+ if (gTextureFetch->mDebugPause)
+ {
+ LLFontGL::sMonospace->renderUTF8("!", 0, title_x1, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ dx1 += 8;
+ }
+ if (mTextureView->mFreezeView)
+ {
+ LLFontGL::sMonospace->renderUTF8("*", 0, title_x1, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ dx1 += 8;
+ }
+ if (mTextureView->mOrderFetch)
+ {
+ LLFontGL::sMonospace->renderUTF8(title_string1b, 0, title_x1+dx1, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ else
+ {
+ LLFontGL::sMonospace->renderUTF8(title_string1a, 0, title_x1+dx1, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ LLFontGL::sMonospace->renderUTF8(title_string2, 0, title_x2, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ LLFontGL::sMonospace->renderUTF8(title_string3, 0, title_x3, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ LLFontGL::sMonospace->renderUTF8(title_string4, 0, title_x4, line_height,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+}
+
+BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ return FALSE;
+}
+
+LLRect LLGLTexMemBar::getRequiredRect()
+{
+ LLRect rect;
+ rect.mTop = 8;
+ return rect;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
LLTextureView::LLTextureView(const std::string& name, const LLRect& rect)
: LLContainerView(name, rect)
{
setVisible(FALSE);
mFreezeView = FALSE;
+ mOrderFetch = FALSE;
mNumTextureBars = 0;
setDisplayChildren(TRUE);
@@ -103,29 +567,40 @@ void LLTextureView::draw()
typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t;
display_list_t display_image_list;
- for (LLViewerImageList::image_list_t::iterator iter = gImageList.mImageList.begin();
+ for (LLViewerImageList::image_priority_list_t::iterator iter = gImageList.mImageList.begin();
iter != gImageList.mImageList.end(); )
{
LLPointer<LLViewerImage> imagep = *iter++;
-#if 1
+#if 0
if (imagep->getDontDiscard())
{
continue;
}
-#endif
+
if (imagep->isMissingAsset())
{
continue;
}
-
-#define HIGH_PRIORITY 100000000.f
- F32 pri = imagep->getDecodePriority();
+#endif
+#define HIGH_PRIORITY 100000000.f
+ F32 pri;
+ if (mOrderFetch)
+ {
+ pri = ((F32)imagep->mFetchPriority)/256.f;
+ }
+ else
+ {
+ pri = imagep->getDecodePriority();
+ }
+
if (sDebugImages.find(imagep) != sDebugImages.end())
{
pri += 3*HIGH_PRIORITY;
}
-
+
+ if (!mOrderFetch)
+ {
#if 1
if (pri < HIGH_PRIORITY && gSelectMgr)
{
@@ -173,13 +648,15 @@ void LLTextureView::draw()
if (pri > 0.f && pri < HIGH_PRIORITY)
{
if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f ||
- imagep->mLastDecodeTime.getElapsedTimeF32() < 1.f)
+ imagep->mFetchDeltaTime < 0.25f)
{
pri += 1*HIGH_PRIORITY;
}
}
#endif
-// if (pri > 0.0f)
+ }
+
+ if (pri > 0.0f)
{
display_image_list.insert(std::make_pair(pri, imagep));
}
@@ -206,9 +683,12 @@ void LLTextureView::draw()
}
}
- sortChildren(SortTextureBars());
+ if (mOrderFetch)
+ sortChildren(LLTextureBar::sort_fetch());
+ else
+ sortChildren(LLTextureBar::sort());
- mGLTexMemBar = new LLGLTexMemBar("gl texmem bar");
+ mGLTexMemBar = new LLGLTexMemBar("gl texmem bar", this);
addChild(mGLTexMemBar);
reshape(mRect.getWidth(), mRect.getHeight(), TRUE);
@@ -238,54 +718,41 @@ void LLTextureView::draw()
BOOL LLTextureView::addBar(LLViewerImage *imagep, S32 hilite)
{
- if (!imagep)
- {
- return FALSE;
- }
-
+ llassert(imagep);
+
LLTextureBar *barp;
LLRect r;
mNumTextureBars++;
- for (std::vector<LLTextureBar*>::iterator iter = mTextureBars.begin();
- iter != mTextureBars.end(); iter++)
- {
- LLTextureBar* barp = *iter;
- if (barp->mImagep == imagep)
- {
- barp->mHilite = hilite;
- return FALSE;
- }
- }
-
- barp = new LLTextureBar("texture bar", r);
+ barp = new LLTextureBar("texture bar", r, this);
barp->mImagep = imagep;
barp->mHilite = hilite;
addChild(barp);
mTextureBars.push_back(barp);
- // Rearrange all child bars.
- reshape(mRect.getWidth(), mRect.getHeight());
return TRUE;
}
BOOL LLTextureView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- if (mask & MASK_SHIFT)
+ if ((mask & MASK_CONTROL) && (mask & MASK_SHIFT))
{
- mFreezeView = !mFreezeView;
+ gTextureFetch->mDebugPause = !gTextureFetch->mDebugPause;
return TRUE;
}
- else if (mask & MASK_CONTROL)
+ if (mask & MASK_SHIFT)
{
- return FALSE;
+ mFreezeView = !mFreezeView;
+ return TRUE;
}
- else
+ if (mask & MASK_CONTROL)
{
- return FALSE;
+ mOrderFetch = !mOrderFetch;
+ return TRUE;
}
+ return LLView::handleMouseDown(x,y,mask);
}
BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask)
@@ -295,11 +762,6 @@ BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
- if (key == ' ')
- {
- mFreezeView = !mFreezeView;
- return TRUE;
- }
return FALSE;
}
diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h
index e832a55211..691438c64e 100644
--- a/indra/newview/lltextureview.h
+++ b/indra/newview/lltextureview.h
@@ -9,11 +9,12 @@
#ifndef LL_LLTEXTUREVIEW_H
#define LL_LLTEXTUREVIEW_H
-#include "lltexturebar.h"
#include "llcontainerview.h"
#include "linked_lists.h"
class LLViewerImage;
+class LLTextureBar;
+class LLGLTexMemBar;
class LLTextureView : public LLContainerView
{
@@ -36,6 +37,10 @@ public:
private:
BOOL addBar(LLViewerImage *image, BOOL hilight = FALSE);
void removeAllBars();
+
+public:
+ BOOL mFreezeView;
+ BOOL mOrderFetch;
private:
LLTextBox *mInfoTextp;
@@ -44,8 +49,6 @@ private:
U32 mNumTextureBars;
LLGLTexMemBar* mGLTexMemBar;
-
- BOOL mFreezeView;
public:
static std::set<LLViewerImage*> sDebugImages;
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 3f111583b5..1947459c6a 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -204,7 +204,7 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
{
mMouseDown = TRUE;
- gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
+ gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE);
return TRUE;
}
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index c439797c47..cdfc6c2ebf 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -69,13 +69,19 @@ LLToolCamera::~LLToolCamera()
// virtual
void LLToolCamera::handleSelect()
{
- if (gFloaterTools) gFloaterTools->setStatusText("Click and drag to change view");
+ if (gFloaterTools)
+ {
+ gFloaterTools->setStatusText("Click and drag to change view");
+ }
}
// virtual
void LLToolCamera::handleDeselect()
{
- if (gFloaterTools) gFloaterTools->setStatusText("");
+ if (gFloaterTools)
+ {
+ gFloaterTools->setStatusText("");
+ }
// gAgent.setLookingAtAvatar(FALSE);
}
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 87e6496588..49f21909a5 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -215,10 +215,7 @@ BOOL LLVisualParamHint::render()
{
LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
- gPipeline.unbindAGP();
- avatarPoolp->syncAGP();
- gPipeline.bindAGP();
- avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders)
+ avatarPoolp->renderAvatars(avatarp); // renders only one avatar
}
avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index e0b4483224..68d9ddbd54 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -61,10 +61,9 @@ LLToolPie::LLToolPie()
BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
{
- // if buttons swapped, don't pick transparent so users can't "pay"
- // transparent objects
+ //left mouse down always picks transparent
gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback,
- FALSE, TRUE);
+ TRUE, TRUE);
mGrabMouseButtonDown = TRUE;
return TRUE;
}
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index 20677fea98..66ed7cd1fe 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -152,7 +152,6 @@ LLPCode LLToolPlacerPanel::sSphere = LL_PCODE_SPHERE;
LLPCode LLToolPlacerPanel::sSphereHemi = LL_PCODE_SPHERE_HEMI;
LLPCode LLToolPlacerPanel::sTree = LL_PCODE_LEGACY_TREE;
LLPCode LLToolPlacerPanel::sGrass = LL_PCODE_LEGACY_GRASS;
-LLPCode LLToolPlacerPanel::sTreeNew = LL_PCODE_TREE_NEW;
S32 LLToolPlacerPanel::sButtonsAdded = 0;
LLButton* LLToolPlacerPanel::sButtons[ TOOL_PLACER_NUM_BUTTONS ];
diff --git a/indra/newview/lltoolplacer.h b/indra/newview/lltoolplacer.h
index 650fc03b01..b38272cfa9 100644
--- a/indra/newview/lltoolplacer.h
+++ b/indra/newview/lltoolplacer.h
@@ -66,7 +66,6 @@ public:
static LLPCode sSphereHemi;
static LLPCode sTree;
static LLPCode sGrass;
- static LLPCode sTreeNew;
private:
void addButton( const LLString& up_state, const LLString& down_state, LLPCode* pcode );
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index c4c25b33f4..2c7c892807 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -119,7 +119,8 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const
LLMatrix4 gProjectionMat;
-void LLViewerCamera::updateFrustumPlanes()
+//static
+void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho)
{
GLint viewport[4];
GLdouble model[16];
@@ -140,23 +141,26 @@ void LLViewerCamera::updateFrustumPlanes()
frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
- /*gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
- frust[4].setVec((F32)objX,(F32)objY,(F32)objZ);
- gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
- frust[5].setVec((F32)objX,(F32)objY,(F32)objZ);
- gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
- frust[6].setVec((F32)objX,(F32)objY,(F32)objZ);
- gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
- frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);*/
- for (U32 i = 0; i < 4; i++)
+ if (ortho)
{
- LLVector3 vec = frust[i] - getOrigin();
- vec.normVec();
- frust[i+4] = getOrigin() + vec*getFar()*2.0;
+ LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0);
+ for (U32 i = 0; i < 4; i++)
+ {
+ frust[i+4] = frust[i] + far_shift;
+ }
+ }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ LLVector3 vec = frust[i] - camera.getOrigin();
+ vec.normVec();
+ frust[i+4] = camera.getOrigin() + vec*camera.getFar()*2.0f;
+ }
}
- calcAgentFrustumPlanes(frust);
+ camera.calcAgentFrustumPlanes(frust);
}
void LLViewerCamera::setPerspective(BOOL for_selection,
@@ -255,7 +259,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
glGetIntegerv(GL_VIEWPORT, (GLint*)gGLViewport);
}
- updateFrustumPlanes();
+ updateFrustumPlanes(*this);
if (gSavedSettings.getBOOL("CameraOffset"))
{
@@ -583,22 +587,34 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
return FALSE;
}
- num_faces = drawablep->getNumFaces();
+ LLVolume* volume = volumep->getVolume();
+ if (!volume)
+ {
+ return FALSE;
+ }
+
+ LLVOVolume* vo_volume = (LLVOVolume*) volumep;
+
+ vo_volume->updateRelativeXform();
+ LLMatrix4 mat = vo_volume->getRelativeXform();
+
+ LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition()));
+
+ num_faces = volume->getNumFaces();
for (i = 0; i < num_faces; i++)
{
- LLStrider<LLVector3> vertices;
- LLFace* face = drawablep->getFace(i);
- face->getVertices(vertices);
-
- for (S32 v = 0; v < (S32)drawablep->getFace(i)->getGeomCount(); v++)
+ const LLVolumeFace& face = volume->getVolumeFace(i);
+
+ for (U32 v = 0; v < face.mVertices.size(); v++)
{
- LLVector3 vec = vertices[v];
- if (!face->isState(LLFace::GLOBAL))
+ LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat;
+
+ if (drawablep->isActive())
{
- vec = vec*face->getRenderMatrix();
+ vec = vec * render_mat;
}
-
- BOOL in_frustum = pointInFrustum(vec) > 0;
+
+ BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0;
if ( !in_frustum && all_verts ||
in_frustum && !all_verts)
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 6797103997..6ce1dcc046 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -36,7 +36,7 @@ public:
const LLVector3 &up_direction,
const LLVector3 &point_of_interest);
- void updateFrustumPlanes();
+ static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE);
void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0);
const LLMatrix4 &getProjection() const;
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index 55d92c2d7a..389f0e8bc6 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -36,6 +36,7 @@ protected:
//setting variables are declared in this function
void declare_settings();
+void settings_version_fixup();
// saved at end of session
extern LLControlGroup gSavedSettings;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 9c3643128b..837eaa90e9 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -44,6 +44,9 @@
#include "llfloatertools.h"
#include "llviewerimagelist.h"
#include "llfocusmgr.h"
+#include "llcubemap.h"
+#include "llviewerregion.h"
+#include "lldrawpoolwater.h"
extern U32 gFrameCount;
extern LLPointer<LLImageGL> gStartImageGL;
@@ -84,8 +87,12 @@ void display_startup()
return;
}
- LLDynamicTexture::updateAllInstances();
-
+ // Required for HTML update in login screen
+ static S32 frame_count = 0;
+ if (frame_count++ > 1) // make sure we have rendered a frame first
+ {
+ LLDynamicTexture::updateAllInstances();
+ }
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
LLGLSDefault gls_default;
LLGLSUIDefault gls_ui;
@@ -364,6 +371,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
//
gCamera->setZoomParameters(zoom_factor, subfield);
+ gCamera->setNear(MIN_NEAR_PLANE);
//////////////////////////
//
@@ -379,6 +387,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
else if (!gViewerWindow->isPickPending())
{
glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+ //DEBUG TEMPORARY
+ glClear(GL_COLOR_BUFFER_BIT);
}
gViewerWindow->setupViewport();
@@ -399,7 +409,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
glClearColor(0.5f, 0.5f, 0.5f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ LLPipeline::sUseOcclusion = FALSE;
}
+ else
+ {
+ LLPipeline::sUseOcclusion = gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery;
+ }
+
stop_glerror();
///////////////////////////////////////
@@ -412,7 +428,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one);
stop_glerror();
- //LLGLState::verify();
+ //Increment drawable frame counter
+ LLDrawable::incrementVisible();
/////////////////////////////////////
//
@@ -422,6 +439,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
//
if (!gDisconnected)
{
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE);
stop_glerror();
display_update_camera();
@@ -437,34 +459,41 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
gPipeline.updateGeom(max_geom_update_time);
stop_glerror();
+ LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME);
+ part->processImagery(gCamera);
+
+ display_update_camera();
+
gFrameStats.start(LLFrameStats::UPDATE_CULL);
- gPipeline.updateCull();
+ gPipeline.updateCull(*gCamera);
stop_glerror();
- if (rebuild)
+ ///////////////////////////////////
+ //
+ // StateSort
+ //
+ // Responsible for taking visible objects, and adding them to the appropriate draw orders.
+ // In the case of alpha objects, z-sorts them first.
+ // Also creates special lists for outlines and selected face rendering.
+ //
{
LLFastTimer t(LLFastTimer::FTM_REBUILD);
-
- ///////////////////////////////////
- //
- // StateSort
- //
- // Responsible for taking visible objects, and adding them to the appropriate draw orders.
- // In the case of alpha objects, z-sorts them first.
- // Also creates special lists for outlines and selected face rendering.
- //
- gFrameStats.start(LLFrameStats::STATE_SORT);
- gPipeline.stateSort();
- stop_glerror();
- //////////////////////////////////////
- //
- // rebuildPools
- //
- //
- gFrameStats.start(LLFrameStats::REBUILD);
- gPipeline.rebuildPools();
+ gFrameStats.start(LLFrameStats::STATE_SORT);
+ gPipeline.stateSort(*gCamera);
stop_glerror();
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gFrameStats.start(LLFrameStats::REBUILD);
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
}
}
@@ -509,10 +538,65 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
&& !gRestoreGL
&& !gDisconnected)
{
- gPipeline.renderGeom();
+ gPipeline.renderGeom(*gCamera);
stop_glerror();
}
+ //render hud attachments
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE))
+ {
+ LLCamera hud_cam = *gCamera;
+ glClear(GL_DEPTH_BUFFER_BIT);
+ LLVector3 origin = hud_cam.getOrigin();
+ hud_cam.setOrigin(-1.f,0,0);
+ hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
+ LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
+ //only render hud objects
+ U32 mask = gPipeline.getRenderTypeMask();
+ gPipeline.setRenderTypeMask(0);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+
+ BOOL has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ BOOL use_occlusion = gSavedSettings.getBOOL("UseOcclusion");
+ gSavedSettings.setBOOL("UseOcclusion", FALSE);
+
+ //cull, sort, and render hud objects
+ gPipeline.updateCull(hud_cam);
+
+ gPipeline.toggleRenderType(LLDrawPool::POOL_ALPHA_POST_WATER);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
+
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_REBUILD);
+ gPipeline.stateSort(hud_cam);
+ }
+
+ gPipeline.renderGeom(hud_cam);
+
+ //restore type mask
+ gPipeline.setRenderTypeMask(mask);
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ gSavedSettings.setBOOL("UseOcclusion", use_occlusion);
+ }
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
gFrameStats.start(LLFrameStats::RENDER_UI);
if (gHandleKeysAsync)
@@ -535,6 +619,64 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
}
+BOOL setup_hud_matrices(BOOL for_select)
+{
+ LLVOAvatar* my_avatarp = gAgent.getAvatarObject();
+ if (my_avatarp && my_avatarp->hasHUDAttachment())
+ {
+ if (!for_select)
+ {
+ // clamp target zoom level to reasonable values
+ my_avatarp->mHUDTargetZoom = llclamp(my_avatarp->mHUDTargetZoom, 0.1f, 1.f);
+ // smoothly interpolate current zoom level
+ my_avatarp->mHUDCurZoom = lerp(my_avatarp->mHUDCurZoom, my_avatarp->mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
+ }
+
+ F32 zoom_level = my_avatarp->mHUDCurZoom;
+ // clear z buffer and set up transform for hud
+ if (!for_select)
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ LLBBox hud_bbox = my_avatarp->getHUDBBox();
+
+ // set up transform to encompass bounding box of HUD
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+ if (for_select)
+ {
+ //RN: reset viewport to window extents so ortho screen is calculated with proper reference frame
+ gViewerWindow->setupViewport();
+ }
+ glOrtho(-0.5f * gCamera->getAspect(), 0.5f * gCamera->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+
+ // apply camera zoom transform (for high res screenshots)
+ F32 zoom_factor = gCamera->getZoomFactor();
+ S16 sub_region = gCamera->getZoomSubRegion();
+ if (zoom_factor > 1.f)
+ {
+ float offset = zoom_factor - 1.f;
+ int pos_y = sub_region / llceil(zoom_factor);
+ int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+ glTranslatef(gCamera->getAspect() * 0.5f * (offset - (F32)pos_x * 2.f), 0.5f * (offset - (F32)pos_y * 2.f), 0.f);
+ glScalef(zoom_factor, zoom_factor, 1.f);
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame
+ glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f);
+ glScalef(zoom_level, zoom_level, zoom_level);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
void render_ui_and_swap()
{
@@ -546,7 +688,7 @@ void render_ui_and_swap()
{
LLGLSUIDefault gls_ui;
gPipeline.disableLights();
-
+ LLVertexBuffer::startRender();
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
@@ -563,6 +705,8 @@ void render_ui_and_swap()
LLGLState::checkStates();
#endif
}
+ LLVertexBuffer::stopRender();
+ glFlush();
// now do the swap buffer
if (gDisplaySwapBuffers)
@@ -570,6 +714,11 @@ void render_ui_and_swap()
LLFastTimer t(LLFastTimer::FTM_SWAP);
gViewerWindow->mWindow->swapBuffers();
}
+
+ {
+// LLFastTimer ftm(LLFastTimer::FTM_TEMP6);
+ LLVertexBuffer::clientCopy();
+ }
}
}
@@ -585,8 +734,6 @@ void render_ui_3d()
//
// Render selections
-
- glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
@@ -643,7 +790,6 @@ void render_ui_2d()
LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor);
}
-
stop_glerror();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index cfd23e7120..0ab1fd1cbf 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -82,10 +82,10 @@ void LLViewerJoint::setValid( BOOL valid, BOOL recursive )
//----------------------------------------------------------------
if (recursive)
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
joint->setValid(valid, TRUE);
}
}
@@ -198,10 +198,10 @@ void LLViewerJoint::renderSkeleton(BOOL recursive)
//----------------------------------------------------------------
if (recursive)
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
joint->renderSkeleton();
}
}
@@ -216,7 +216,7 @@ void LLViewerJoint::renderSkeleton(BOOL recursive)
//--------------------------------------------------------------------
// render()
//--------------------------------------------------------------------
-U32 LLViewerJoint::render( F32 pixelArea )
+U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass )
{
U32 triangle_count = 0;
@@ -226,73 +226,68 @@ U32 LLViewerJoint::render( F32 pixelArea )
if ( mValid )
{
+
//----------------------------------------------------------------
// if object is transparent, defer it, otherwise
// give the joint subclass a chance to draw itself
//----------------------------------------------------------------
if ( gRenderForSelect )
{
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, first_pass );
}
else if ( isTransparent() )
{
- LLGLEnable blend(GL_BLEND);
// Hair and Skirt
if ((pixelArea > MIN_PIXEL_AREA_3PASS_HAIR))
{
// render all three passes
- LLGLEnable alpha_test(GL_ALPHA_TEST);
LLGLDisable cull(GL_CULL_FACE);
// first pass renders without writing to the z buffer
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, first_pass);
}
// second pass writes to z buffer only
glColorMask(FALSE, FALSE, FALSE, FALSE);
{
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, FALSE );
}
// third past respects z buffer and writes color
glColorMask(TRUE, TRUE, TRUE, TRUE);
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, FALSE );
}
}
else
{
- LLGLEnable alpha_test(GL_ALPHA_TEST);
// Render Inside (no Z buffer write)
glCullFace(GL_FRONT);
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, first_pass );
}
// Render Outside (write to the Z buffer)
glCullFace(GL_BACK);
{
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, FALSE );
}
}
}
else
{
// set up render state
- LLGLDisable blend(GL_BLEND);
- LLGLSPipelineAvatar gls_pipeline_avatar;
- triangle_count += drawShape( pixelArea );
+ triangle_count += drawShape( pixelArea, first_pass );
}
}
//----------------------------------------------------------------
// render children
//----------------------------------------------------------------
- LLViewerJoint *joint;
- for ( joint = (LLViewerJoint *)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint *)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
F32 jointLOD = joint->getLOD();
if (pixelArea >= jointLOD || sDisableLOD)
{
@@ -305,7 +300,6 @@ U32 LLViewerJoint::render( F32 pixelArea )
}
}
- glColorMask(TRUE, TRUE, TRUE, TRUE);
return triangle_count;
}
@@ -377,7 +371,7 @@ BOOL LLViewerJoint::isTransparent()
//--------------------------------------------------------------------
// drawShape()
//--------------------------------------------------------------------
-U32 LLViewerJoint::drawShape( F32 pixelArea )
+U32 LLViewerJoint::drawShape( F32 pixelArea, BOOL first_pass )
{
return 0;
}
@@ -390,65 +384,75 @@ void LLViewerJoint::setSkeletonComponents( U32 comp, BOOL recursive )
mComponents = comp;
if (recursive)
{
- for ( LLViewerJoint *joint = (LLViewerJoint *)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint *)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
joint->setSkeletonComponents(comp, recursive);
}
}
}
-void LLViewerJoint::updateFaceSizes(U32 &num_vertices, F32 pixel_area)
+void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
- F32 jointLOD = joint->getLOD();
- if (pixel_area >= jointLOD || sDisableLOD)
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
+ //F32 jointLOD = joint->getLOD();
+ //if (pixel_area >= jointLOD || sDisableLOD)
{
- joint->updateFaceSizes(num_vertices, pixel_area);
+ joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
- if (jointLOD != DEFAULT_LOD)
- {
- break;
- }
+ // if (jointLOD != DEFAULT_LOD)
+ // {
+ // break;
+ // }
}
}
}
void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
- F32 jointLOD = joint->getLOD();
- if (pixel_area >= jointLOD || sDisableLOD)
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
+ //F32 jointLOD = joint->getLOD();
+ //if (pixel_area >= jointLOD || sDisableLOD)
{
joint->updateFaceData(face, pixel_area, damp_wind);
- if (jointLOD != DEFAULT_LOD)
- {
- break;
- }
+ // if (jointLOD != DEFAULT_LOD)
+ // {
+ // break;
+ // }
}
}
}
+void LLViewerJoint::updateGeometry()
+{
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
+ joint->updateGeometry();
+ }
+}
+
BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate)
{
BOOL lod_changed = FALSE;
BOOL found_lod = FALSE;
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
F32 jointLOD = joint->getLOD();
-
+
if (found_lod || jointLOD == DEFAULT_LOD)
{
// we've already found a joint to enable, so enable the rest as alternatives
@@ -472,12 +476,12 @@ BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate)
void LLViewerJoint::dump()
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
- {
- joint->dump();
- }
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
+ joint->dump();
+ }
}
void LLViewerJoint::setVisible(BOOL visible, BOOL recursive)
@@ -486,12 +490,12 @@ void LLViewerJoint::setVisible(BOOL visible, BOOL recursive)
if (recursive)
{
- for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
- {
- joint->setVisible(visible, recursive);
- }
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
+ joint->setVisible(visible, recursive);
+ }
}
}
@@ -511,10 +515,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp)
LLQuaternion bone_rot;
S32 num_children = 0;
- for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
if (joint->mJointNum != -1)
{
num_children++;
@@ -541,10 +545,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp)
apr_file_printf(fp, " <LOCALROTATION>0 0 0 1</LOCALROTATION>\n");
apr_file_printf(fp, " <PARENTID>%d</PARENTID>\n", mParent ? mParent->mJointNum + 1 : -1);
- for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
if (joint->mJointNum != -1)
{
apr_file_printf(fp, " <CHILDID>%d</CHILDID>\n", joint->mJointNum + 1);
@@ -553,10 +557,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp)
apr_file_printf(fp, " </BONE>\n");
// recurse
- for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData();
- joint != NULL;
- joint = (LLViewerJoint*)mChildren.getNextData() )
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
{
+ LLViewerJoint* joint = (LLViewerJoint*)(*iter);
if (joint->mJointNum != -1)
{
joint->writeCAL3D(fp);
diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h
index e38c1c8e7d..9b5185267f 100644
--- a/indra/newview/llviewerjoint.h
+++ b/indra/newview/llviewerjoint.h
@@ -43,7 +43,7 @@ public:
// Traverses the entire joint hierarchy, setting up
// transforms and calling the drawShape().
// Derived classes may add text/graphic output.
- virtual U32 render( F32 pixelArea ); // Returns triangle count
+ virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE ); // Returns triangle count
// Draws a bone graphic to the parent joint.
// Derived classes may add text/graphic output.
@@ -59,7 +59,7 @@ public:
// Draws the shape attached to a joint.
// Called by render().
- virtual U32 drawShape( F32 pixelArea );
+ virtual U32 drawShape( F32 pixelArea, BOOL first_pass = TRUE );
virtual void drawNormals() {}
enum Components
@@ -78,9 +78,9 @@ public:
// Sets the level of detail for this node as a minimum
// pixel area threshold. If the current pixel area for this
// object is less than the specified threshold, the node is
- // not traversed. In additin, if a value is specified (not
+ // not traversed. In addition, if a value is specified (not
// default of 0.0), and the pixel area is larger than the
- // specified miniumn, the node is rendered, but no other siblings
+ // specified minimum, the node is rendered, but no other siblings
// of this node under the same parent will be.
F32 getLOD() { return mMinPixelArea; }
void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; }
@@ -101,9 +101,10 @@ public:
void setPickName(PickName name) { mPickName = name; }
PickName getPickName() { return mPickName; }
- virtual void updateFaceSizes(U32 &num_vertices, F32 pixel_area);
+ virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area);
virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE);
virtual BOOL updateLOD(F32 pixel_area, BOOL activate);
+ virtual void updateGeometry();
virtual void dump();
void setVisible( BOOL visible, BOOL recursive );
@@ -135,3 +136,4 @@ public:
#endif // LL_LLVIEWERJOINT_H
+
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index 4ae527eee5..090276ef51 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -60,7 +60,7 @@ BOOL LLViewerJointAttachment::isTransparent()
//-----------------------------------------------------------------------------
// drawShape()
//-----------------------------------------------------------------------------
-U32 LLViewerJointAttachment::drawShape( F32 pixelArea )
+U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass )
{
if (LLVOAvatar::sShowAttachmentPoints)
{
@@ -277,47 +277,20 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
{
- if (!mAttachedObject || mAttachedObject->mDrawable.isNull())
+ if (!mAttachedObject || mAttachedObject->mDrawable.isNull() ||
+ !(mAttachedObject->mDrawable->getSpatialBridge()))
return;
if (visible)
{
// Hack to make attachments not visible by disabling their type mask!
// This will break if you can ever attach non-volumes! - djs 02/14/03
- mAttachedObject->mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- for (LLViewerObject::child_list_t::iterator iter = mAttachedObject->mChildList.begin();
- iter != mAttachedObject->mChildList.end(); ++iter)
- {
- LLViewerObject* childp = *iter;
- if (childp && childp->mDrawable.notNull())
- {
- childp->mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- }
- }
+ mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType =
+ mAttachedObject->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
}
else
{
- //RN: sometimes we call this on objects that are already invisible, so check for that case
- if (!mAttachedObject->mDrawable->isRenderType(LLPipeline::RENDER_TYPE_VOLUME) &&
- !mAttachedObject->mDrawable->isRenderType(0))
- {
- llerrs << "Tried to attach non-volume to a joint, visibility hack dangerous!" << llendl;
- }
- mAttachedObject->mDrawable->setRenderType(0);
- for (LLViewerObject::child_list_t::iterator iter = mAttachedObject->mChildList.begin();
- iter != mAttachedObject->mChildList.end(); ++iter)
- {
- LLViewerObject* childp = *iter;
- if (childp && childp->mDrawable.notNull())
- {
- if (!childp->mDrawable->isRenderType(LLPipeline::RENDER_TYPE_VOLUME) &&
- !mAttachedObject->mDrawable->isRenderType(0))
- {
- llerrs << "Tried to attach non-volume to a joint, visibility hack dangerous!" << llendl;
- }
- childp->mDrawable->setRenderType(0);
- }
- }
+ mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = 0;
}
}
diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h
index b3a6ccb89c..e0354a8c10 100644
--- a/indra/newview/llviewerjointattachment.h
+++ b/indra/newview/llviewerjointattachment.h
@@ -37,7 +37,7 @@ public:
// Draws the shape attached to a joint.
// Called by render().
- /*virtual*/ U32 drawShape( F32 pixelArea );
+ /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass );
/*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate);
@@ -60,7 +60,7 @@ public:
S32 getGroup() { return mGroup; }
S32 getPieSlice() { return mPieSlice; }
BOOL getAttachmentDirty() { return mAttachmentDirty && mAttachedObject; }
- LLViewerObject *getObject(S32 i) { return mAttachedObject; }
+ LLViewerObject *getObject() { return mAttachedObject; }
S32 getNumObjects() { return (mAttachedObject ? 1 : 0); }
const LLUUID& getItemID() { return mItemID; }
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index aec15a8d6c..512ddc8565 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -19,7 +19,6 @@
#include "llfasttimer.h"
#include "llagent.h"
-#include "llagparray.h"
#include "llbox.h"
#include "lldrawable.h"
#include "lldrawpoolavatar.h"
@@ -43,6 +42,10 @@ extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
#endif
extern BOOL gRenderForSelect;
+static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
+static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD;
LLMatrix4 gBlendMat;
//-----------------------------------------------------------------------------
@@ -375,11 +378,11 @@ void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
}
// depth-first traversal
- for (LLJoint *child_joint = current_joint->mChildren.getFirstData();
- child_joint;
- child_joint = current_joint->mChildren.getNextData())
+ for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
+ iter != current_joint->mChildren.end(); ++iter)
{
- setupJoint((LLViewerJoint*)child_joint);
+ LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
+ setupJoint(child_joint);
}
}
@@ -412,7 +415,7 @@ void LLViewerJointMesh::uploadJointMatrices()
if (hardware_skinning)
{
- joint_mat *= gCamera->getModelview();
+ joint_mat *= LLDrawPoolAvatar::getModelView();
}
gJointMat[joint_num] = joint_mat;
gJointRot[joint_num] = joint_mat.getMat3();
@@ -513,620 +516,39 @@ int compare_int(const void *a, const void *b)
else return 0;
}
-#if LL_WINDOWS || (LL_DARWIN && __i386__) // SSE optimizations in avatar code
-
-#if LL_DARWIN
-#include <xmmintrin.h>
-
- // On Windows, this class is defined in fvec.h. I've only reproduced the parts of it we use here for now.
- #pragma pack(push,16) /* Must ensure class & union 16-B aligned */
- class F32vec4
- {
- protected:
- __m128 vec;
- public:
-
- /* Constructors: __m128, 4 floats, 1 float */
- F32vec4() {}
-
- /* initialize 4 SP FP with __m128 data type */
- F32vec4(__m128 m) { vec = m;}
-
- /* Explicitly initialize each of 4 SP FPs with same float */
- explicit F32vec4(float f) { vec = _mm_set_ps1(f); }
- };
- #pragma pack(pop) /* 16-B aligned */
-
-
-#endif
-
-void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
- LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
+void llDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
{
- F32 last_weight = F32_MAX;
- LLMatrix4 *blend_mat = &gBlendMat;
-
- for (S32 index = vert_offset; index < vert_offset + vert_count; index++)
+ if (end-start+1 > (U32) gGLManager.mGLMaxVertexRange ||
+ count > gGLManager.mGLMaxIndexRange)
{
- F32 w = weights [index]; // register copy of weight
- F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever
- F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned
-
- if (w == last_weight)
- {
- // load input and output vertices, and last blended matrix
- __asm {
- mov esi, vin
- mov edi, vout
-
- mov edx, blend_mat
- movaps xmm4, [edx]
- movaps xmm5, [edx+0x10]
- movaps xmm6, [edx+0x20]
- movaps xmm7, [edx+0x30]
- }
- }
- else
- {
- last_weight = w;
- S32 joint = llfloor(w);
- w -= joint;
-
- LLMatrix4 *m0 = &(gJointMat[joint+1]);
- LLMatrix4 *m1 = &(gJointMat[joint+0]);
-
- // some initial code to load Matrix 0 into SSE registers
- __asm {
- mov esi, vin
- mov edi, vout
-
- //matrix2
- mov edx, m0
- movaps xmm4, [edx]
- movaps xmm5, [edx+0x10]
- movaps xmm6, [edx+0x20]
- movaps xmm7, [edx+0x30]
- };
-
- // if w == 1.0f, we don't need to blend.
- // but since we do the trick of blending the matrices, here, if w != 1.0,
- // we load Matrix 1 into the other 4 SSE registers and blend both matrices
- // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w)
-
- if (w != 1.0f)
- {
- F32vec4 weight(w);
-
- __asm { // do blending of matrices instead of verts and normals -- faster
- mov edx, m1
- movaps xmm0, [edx]
- movaps xmm1, [edx+0x10]
- movaps xmm2, [edx+0x20]
- movaps xmm3, [edx+0x30]
-
- subps xmm4, xmm0 // do blend for each matrix column
- subps xmm5, xmm1 // diff, then multiply weight and re-add
- subps xmm6, xmm2
- subps xmm7, xmm3
-
- mulps xmm4, weight
- mulps xmm5, weight
- mulps xmm6, weight
- mulps xmm7, weight
-
- addps xmm4, xmm0
- addps xmm5, xmm1
- addps xmm6, xmm2
- addps xmm7, xmm3
- };
- }
-
- __asm {
- // save off blended matrix
- mov edx, blend_mat;
- movaps [edx], xmm4;
- movaps [edx+0x10], xmm5;
- movaps [edx+0x20], xmm6;
- movaps [edx+0x30], xmm7;
- }
- }
-
- // now, we have either a blended matrix in xmm4-7 or the original Matrix 0
- // we then multiply each vertex and normal by this one matrix.
-
- // For SSE2, we would try to keep the original two matrices in other registers
- // and avoid reloading them. However, they should ramain in L1 cache in the
- // current case.
-
- // One possible optimization would be to sort the vertices by weight instead
- // of just index (we still want to uniqify). If we note when two or more vertices
- // share the same weight, we can avoid doing the middle SSE code above and just
- // re-use the blended matrix for those vertices
-
-
- // now, we do the actual vertex blending
- __asm {
- // load Vertex into xmm0.
- movaps xmm0, [esi] // change aps to ups when input is no longer 16-baligned
- movaps xmm1, xmm0 // copy vector into xmm0 through xmm2 (x,y,z)
- movaps xmm2, xmm0
- shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // clone vertex (x) across vector
- shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1); // clone vertex (y) across vector
- shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2); // same for Z
- mulps xmm0, xmm4 // do the actual matrix multipication for r0
- mulps xmm1, xmm5 // for r1
- mulps xmm2, xmm6 // for r2
- addps xmm0, xmm1 // accumulate
- addps xmm0, xmm2 // accumulate
- addps xmm0, xmm7 // add in the row 4 which holds the x,y,z translation. assumes w=1 (vertex-w, not weight)
-
- movaps [edi], xmm0 // store aligned in output array
-
- // load Normal into xmm0.
- movaps xmm0, [esi + 0x10] // change aps to ups when input no longer 16-byte aligned
- movaps xmm1, xmm0 //
- movaps xmm2, xmm0
- shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // since UV sits between vertex and normal, normal starts at element 1, not 0
- shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1);
- shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2);
- mulps xmm0, xmm4 // multiply by matrix
- mulps xmm1, xmm5 // multiply
- mulps xmm2, xmm6 // multiply
- addps xmm0, xmm1 // accumulate
- addps xmm0, xmm2 // accumulate. note: do not add translation component to normals, save time too
- movaps [edi + 0x10], xmm0 // store aligned
- }
-
- *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot.
- }
-}
-
-#elif LL_LINUX
-
-void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
- LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
-{
- assert(0);
-}
-
-#elif LL_DARWIN
-// AltiVec versions of the same...
-
-static inline vector float loadAlign(int offset, vector float *addr)
-{
- vector float in0 = vec_ld(offset, addr);
- vector float in1 = vec_ld(offset + 16, addr);
- vector unsigned char perm = vec_lvsl(0, (unsigned char*)addr);
-
- return(vec_perm(in0, in1, perm));
-}
-
-static inline void storeAlign(vector float v, int offset, vector float *addr)
-{
- vector float in0 = vec_ld(offset, addr);
- vector float in1 = vec_ld(offset + 16, addr);
- vector unsigned char perm = vec_lvsr(0, (unsigned char *)addr);
- vector float temp = vec_perm(v, v, perm);
- vector unsigned char mask = (vector unsigned char)vec_cmpgt(perm, vec_splat_u8(15));
-
- in0 = vec_sel(in0, temp, (vector unsigned int)mask);
- in1 = vec_sel(temp, in1, (vector unsigned int)mask);
-
- vec_st(in0, offset, addr);
- vec_st(in1, offset + 16, addr);
-}
-
-void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
- LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
-{
- F32 last_weight = F32_MAX;
-// LLMatrix4 &blend_mat = gBlendMat;
-
- vector float matrix0_0, matrix0_1, matrix0_2, matrix0_3;
- vector unsigned char out0perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F );
-// vector unsigned char out1perm = (vector unsigned char) ( 0x00,0x01,0x02,0x03, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B );
- vector unsigned char out1perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F );
-
- vector float zero = (vector float)vec_splat_u32(0);
-
- for (U32 index = vert_offset; index < vert_offset + vert_count; index++)
- {
- F32 w = weights [index]; // register copy of weight
- F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever
- F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned
-
- // MBW -- XXX -- If this isn't the case, this code gets more complicated.
- if(0x0000000F & (U32)vin)
- {
- llerrs << "blend_SSE_batch: input not 16-byte aligned!" << llendl;
- }
- if(0x0000000F & (U32)vout)
- {
- llerrs << "blend_SSE_batch: output not 16-byte aligned!" << llendl;
- }
-// if(0x0000000F & (U32)&(blend_mat.mMatrix))
-// {
-// llerrs << "blend_SSE_batch: blend_mat not 16-byte aligned!" << llendl;
-// }
-
- if (w == last_weight)
- {
- // load last blended matrix
- // Still loaded from last time through the loop.
-// matrix0_0 = vec_ld(0x00, (vector float*)&(blend_mat.mMatrix));
-// matrix0_1 = vec_ld(0x10, (vector float*)&(blend_mat.mMatrix));
-// matrix0_2 = vec_ld(0x20, (vector float*)&(blend_mat.mMatrix));
-// matrix0_3 = vec_ld(0x30, (vector float*)&(blend_mat.mMatrix));
- }
- else
- {
- last_weight = w;
- S32 joint = llfloor(w);
- w -= joint;
-
- LLMatrix4 &m0 = gJointMat[joint+1];
- LLMatrix4 &m1 = gJointMat[joint+0];
-
- // load Matrix 0 into vector registers
- matrix0_0 = vec_ld(0x00, (vector float*)&(m0.mMatrix));
- matrix0_1 = vec_ld(0x10, (vector float*)&(m0.mMatrix));
- matrix0_2 = vec_ld(0x20, (vector float*)&(m0.mMatrix));
- matrix0_3 = vec_ld(0x30, (vector float*)&(m0.mMatrix));
-
- // if w == 1.0f, we don't need to blend.
- // but since we do the trick of blending the matrices, here, if w != 1.0,
- // we load Matrix 1 into the other 4 SSE registers and blend both matrices
- // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w)
-
- if (w != 1.0f)
- {
- vector float matrix1_0, matrix1_1, matrix1_2, matrix1_3;
-
- // This loads the weight somewhere in the vector register
- vector float weight = vec_lde(0, &(w));
- // and this splats it to all elements.
- weight = vec_splat(vec_perm(weight, weight, vec_lvsl(0, &(w))), 0);
-
- // do blending of matrices instead of verts and normals -- faster
- matrix1_0 = vec_ld(0x00, (vector float*)&(m1.mMatrix));
- matrix1_1 = vec_ld(0x10, (vector float*)&(m1.mMatrix));
- matrix1_2 = vec_ld(0x20, (vector float*)&(m1.mMatrix));
- matrix1_3 = vec_ld(0x30, (vector float*)&(m1.mMatrix));
-
- // m0[col] = ((m0[col] - m1[col]) * weight) + m1[col];
- matrix0_0 = vec_madd(vec_sub(matrix0_0, matrix1_0), weight, matrix1_0);
- matrix0_1 = vec_madd(vec_sub(matrix0_1, matrix1_1), weight, matrix1_1);
- matrix0_2 = vec_madd(vec_sub(matrix0_2, matrix1_2), weight, matrix1_2);
- matrix0_3 = vec_madd(vec_sub(matrix0_3, matrix1_3), weight, matrix1_3);
- }
-
- // save off blended matrix
-// vec_st(matrix0_0, 0x00, (vector float*)&(blend_mat.mMatrix));
-// vec_st(matrix0_1, 0x10, (vector float*)&(blend_mat.mMatrix));
-// vec_st(matrix0_2, 0x20, (vector float*)&(blend_mat.mMatrix));
-// vec_st(matrix0_3, 0x30, (vector float*)&(blend_mat.mMatrix));
- }
-
- // now, we have either a blended matrix in matrix0_0-3 or the original Matrix 0
- // we then multiply each vertex and normal by this one matrix.
-
- // For SSE2, we would try to keep the original two matrices in other registers
- // and avoid reloading them. However, they should ramain in L1 cache in the
- // current case.
-
- // One possible optimization would be to sort the vertices by weight instead
- // of just index (we still want to uniqify). If we note when two or more vertices
- // share the same weight, we can avoid doing the middle SSE code above and just
- // re-use the blended matrix for those vertices
-
-
- // now, we do the actual vertex blending
-
- vector float in0 = vec_ld(AVATAR_OFFSET_POS, (vector float*)vin);
- vector float in1 = vec_ld(AVATAR_OFFSET_NORMAL, (vector float*)vin);
-
- // Matrix multiply vertex
- vector float out0 = vec_madd
- (
- vec_splat(in0, 0),
- matrix0_0,
- vec_madd
- (
- vec_splat(in0, 1),
- matrix0_1,
- vec_madd
- (
- vec_splat(in0, 2),
- matrix0_2,
- matrix0_3
- )
- )
- );
-
- // Matrix multiply normal
- vector float out1 = vec_madd
- (
- vec_splat(in1, 0),
- matrix0_0,
- vec_madd
- (
- vec_splat(in1, 1),
- matrix0_1,
- vec_madd
- (
- vec_splat(in1, 2),
- matrix0_2,
- // no translation for normals
- (vector float)vec_splat_u32(0)
- )
- )
- );
-
- // indexed store
- vec_stl(vec_perm(in0, out0, out0perm), AVATAR_OFFSET_POS, (vector float*)vout); // Pos
- vec_stl(vec_perm(in1, out1, out1perm), AVATAR_OFFSET_NORMAL, (vector float*)vout); // Norm
- *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot.
- }
-}
-
-#endif
-
-
-void llDrawElementsBatchBlend(const U32 vert_offset, const U32 vert_count, LLFace *face, const S32 index_count, const U32 *indices)
-{
- U8* gAGPVertices = gPipeline.bufferGetScratchMemory();
-
- if (gAGPVertices)
- {
- LLStrider<LLVector3> vertices;
- LLStrider<LLVector3> normals;
- LLStrider<LLVector2> tcoords0;
- LLStrider<F32> weights;
-
- LLStrider<LLVector3> o_vertices;
- LLStrider<LLVector3> o_normals;
- LLStrider<LLVector2> o_texcoords0;
-
-
- LLStrider<LLVector3> binormals;
- LLStrider<LLVector2> o_texcoords1;
- // get the source vertices from the draw pool. We index these ourselves, as there was
- // no guarantee the indices for a single jointmesh were contigious
-
- LLDrawPool *pool = face->getPool();
- pool->getVertexStrider (vertices, 0);
- pool->getTexCoordStrider (tcoords0, 0, 0);
- pool->getNormalStrider (normals, 0);
- pool->getBinormalStrider (binormals, 0);
- pool->getVertexWeightStrider(weights, 0);
-
- // load the addresses of the output striders
- o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES);
- o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES);
- o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES);
- o_texcoords1= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX1); o_texcoords1.setStride(AVATAR_VERTEX_BYTES);
-
-#if !LL_LINUX // !!! *TODO: do the linux implementation
- if (gGLManager.mSoftwareBlendSSE)
- {
- // do SSE blend without binormals or extra texcoords
- blend_SSE_32_32_batch(vert_offset, vert_count, (float*)gAGPVertices,
- vertices, tcoords0, normals, weights);
- }
- else // fully backwards compatible software blending, no SSE
-#endif
- {
- LLVector4 tpos0, tnorm0, tpos1, tnorm1, tbinorm0, tbinorm1;
- F32 last_weight = F32_MAX;
- LLMatrix3 gBlendRotMat;
-
- {
- for (U32 index=vert_offset; index < vert_offset + vert_count; index++)
- {
- // blend by first matrix
- F32 w = weights [index];
-
- if (w != last_weight)
- {
- last_weight = w;
-
- S32 joint = llfloor(w);
- w -= joint;
-
- LLMatrix4 &m0 = gJointMat[joint+1];
- LLMatrix4 &m1 = gJointMat[joint+0];
- LLMatrix3 &n0 = gJointRot[joint+1];
- LLMatrix3 &n1 = gJointRot[joint+0];
-
- if (w == 1.0f)
- {
- gBlendMat = m0;
- gBlendRotMat = n0;
- }
- else
- {
- gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
- gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
- gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
-
- gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
- gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
- gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
-
- gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
- gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
- gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
-
- gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
- gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
- gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
-
- gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
- gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
- gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
-
- gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
- gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
- gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
-
- gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
- gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
- gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
- }
- }
-
- // write result
- o_vertices [index] = vertices[index] * gBlendMat;
- o_normals [index] = normals [index] * gBlendRotMat;
- o_texcoords0[index] = tcoords0[index];
-
- /*
- // Verification code. Leave this here. It's useful for keeping the SSE and non-SSE versions in sync.
- LLVector3 temp;
- temp = tpos0;
- if( (o_vertices[index] - temp).magVecSquared() > 0.001f )
- {
- llerrs << "V SSE: " << o_vertices[index] << " v. " << temp << llendl;
- }
-
- temp = tnorm0;
- if( (o_normals[index] - temp).magVecSquared() > 0.001f )
- {
- llerrs << "N SSE: " << o_normals[index] << " v. " << temp << llendl;
- }
-
- if( (o_texcoords0[index] - tcoords0[index]).magVecSquared() > 0.001f )
- {
- llerrs << "T0 SSE: " << o_texcoords0[index] << " v. " << tcoords0[index] << llendl;
- }
- */
- }
- }
- }
-
-#if LL_DARWIN
- // *HACK* *CHOKE* *PUKE*
- // No way does this belong here.
- glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * vert_count, gAGPVertices + (AVATAR_VERTEX_BYTES * vert_offset));
-#endif
- glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices); // draw it!
+ glDrawElements(mode,count,type,indices);
}
else
{
- glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices);
+ glDrawRangeElements(mode,start,end,count,type,indices);
}
}
-
-
-//--------------------------------------------------------------------
-// DrawElements
-
-// works just like glDrawElements, except it assumes GL_TRIANGLES and GL_UNSIGNED_INT indices
-
-// why? because the destination buffer may not be the AGP buffer and the eyes do not use blending
-// separate the eyes into their own drawpools and this code goes away.
-
-//--------------------------------------------------------------------
-
-void llDrawElements(const S32 count, const U32 *indices, LLFace *face)
-{
- U8* gAGPVertices = gPipeline.bufferGetScratchMemory();
-
- if (gAGPVertices)
- {
-#if LL_DARWIN
- U32 minIndex = indices[0];
- U32 maxIndex = indices[0];
-#endif
- {
- LLStrider<LLVector3> vertices;
- LLStrider<LLVector3> normals;
- LLStrider<LLVector2> tcoords;
- LLStrider<F32> weights;
-
- LLStrider<LLVector3> o_vertices;
- LLStrider<LLVector3> o_normals;
- LLStrider<LLVector2> o_texcoords0;
-
- LLDrawPool *pool = face->getPool();
- pool->getVertexStrider (vertices,0);
- pool->getNormalStrider (normals, 0);
- pool->getTexCoordStrider (tcoords, 0);
-
- o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES);
- o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES);
- o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES);
-
- for (S32 i=0; i < count; i++)
- {
- U32 index = indices[i];
-
- o_vertices [index] = vertices[index];
- o_normals [index] = normals [index];
- o_texcoords0[index] = tcoords [index];
-
-#if LL_DARWIN
- maxIndex = llmax(index, maxIndex);
- minIndex = llmin(index, minIndex);
-#endif
- }
- }
-
-#if LL_DARWIN
- // *HACK* *CHOKE* *PUKE*
- // No way does this belong here.
- glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * (maxIndex + 1 - minIndex), gAGPVertices + (AVATAR_VERTEX_BYTES * minIndex));
-#endif
-
- glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices);
- }
- else
- {
- glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices);
- }
-}
-
-
//--------------------------------------------------------------------
// LLViewerJointMesh::drawShape()
//--------------------------------------------------------------------
-U32 LLViewerJointMesh::drawShape( F32 pixelArea )
+U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
{
- if (!mValid || !mVisible) return 0;
-
- U32 triangle_count = 0;
-
- //----------------------------------------------------------------
- // if no mesh bail out now
- //----------------------------------------------------------------
- if ( !mMesh || !mFace)
+ if (!mValid || !mMesh || !mFace || !mVisible ||
+ mFace->mVertexBuffer.isNull() ||
+ mMesh->getNumFaces() == 0)
{
return 0;
}
- //----------------------------------------------------------------
- // if we have no faces, bail out now
- //----------------------------------------------------------------
- if ( mMesh->getNumFaces() == 0 )
- {
- return 0;
- }
+ U32 triangle_count = 0;
stop_glerror();
//----------------------------------------------------------------
// setup current color
//----------------------------------------------------------------
- if (gRenderForSelect)
- {
- S32 name = mFace->getDrawable() ? mFace->getDrawable()->getVObj()->mGLName : 0;
- LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name, 0xff);
- LLColor4 color_float(color);
-
- glColor4f(color_float.mV[0], color_float.mV[1], color_float.mV[2], 1.f);
- }
- else
+ if (!gRenderForSelect)
{
if ((mFace->getPool()->getVertexShaderLevel() > 0))
{
@@ -1150,7 +572,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
stop_glerror();
-// LLGLSSpecular specular(mSpecular, gRenderForSelect ? 0.0f : mShiny);
LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
LLGLEnable texture_2d((gRenderForSelect && isTransparent()) ? GL_TEXTURE_2D : 0);
@@ -1160,11 +581,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
//----------------------------------------------------------------
llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive
- //GLuint test_image_name = 0;
-
- //
- LLGLState force_alpha_test(GL_ALPHA_TEST, isTransparent());
-
if (mTestImageName)
{
LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D );
@@ -1217,11 +633,12 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
gImageList.getImage(IMG_DEFAULT_AVATAR)->bind();
}
+ LLGLDisable tex(gRenderForSelect && !isTransparent() ? GL_TEXTURE_2D : 0);
+
if (gRenderForSelect)
{
if (isTransparent())
{
- //gGLSObjectSelectDepthAlpha.set();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
@@ -1232,19 +649,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); // GL_TEXTURE_ENV_COLOR is set in renderPass1
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
- else
- {
- //gGLSObjectSelectDepth.set();
- }
}
else
{
//----------------------------------------------------------------
// by default, backface culling is enabled
//----------------------------------------------------------------
- if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER)
+ /*if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER)
{
- //LLGLSPipelineAvatar gls_pipeline_avatar;
LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
glClientActiveTextureARB(GL_TEXTURE0_ARB);
@@ -1284,7 +696,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
}
else if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_OUTER)
{
- //gGLSPipelineAvatarAlphaPass1.set();
glAlphaFunc(GL_GREATER, 0.1f);
LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
@@ -1315,81 +726,48 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
- }
- else if ( isTransparent())
- {
- //gGLSNoCullFaces.set();
- }
- else
- {
- //gGLSCullFaces.set();
- }
+ }*/
}
- if (mMesh->hasWeights())
- {
- uploadJointMatrices();
+ mFace->mVertexBuffer->setBuffer(sRenderMask);
+ U32 start = mMesh->mFaceVertexOffset;
+ U32 end = start + mMesh->mFaceVertexCount - 1;
+ U32 count = mMesh->mFaceIndexCount;
+ U32* indicesp = ((U32*) mFace->mVertexBuffer->getIndicesPointer()) + mMesh->mFaceIndexOffset;
+ if (mMesh->hasWeights())
+ {
if ((mFace->getPool()->getVertexShaderLevel() > 0))
{
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices());
-
- glPopMatrix();
+ if (first_pass)
+ {
+ uploadJointMatrices();
+ }
+ llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
}
else
{
- if (mFace->getGeomIndex() < 0)
- {
- llerrs << "Invalid geometry index in LLViewerJointMesh::drawShape() " << mFace->getGeomIndex() << llendl;
- }
-
- if ((S32)(mMesh->mFaceVertexOffset + mMesh->mFaceVertexCount) > mFace->getGeomCount())
- {
- ((LLVOAvatar*)mFace->getDrawable()->getVObj())->mRoot.dump();
- llerrs << "Rendering outside of vertex bounds with mesh " << mName << " at pixel area " << pixelArea << llendl;
- }
- llDrawElementsBatchBlend(mMesh->mFaceVertexOffset, mMesh->mFaceVertexCount,
- mFace, mMesh->mFaceIndexCount, mMesh->getIndices());
+ llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
}
-
}
else
{
glPushMatrix();
LLMatrix4 jointToWorld = getWorldMatrix();
- jointToWorld *= gCamera->getModelview();
- glLoadMatrixf((GLfloat*)jointToWorld.mMatrix);
-
- if ((mFace->getPool()->getVertexShaderLevel() > 0))
- {
- glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices());
- }
- else // this else clause handles non-weighted vertices. llDrawElements just copies and draws
- {
- llDrawElements(mMesh->mFaceIndexCount, mMesh->getIndices(), mFace);
- }
-
+ glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
+ llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
glPopMatrix();
}
triangle_count += mMesh->mFaceIndexCount;
-
- if (gRenderForSelect)
- {
- glColor4fv(mColor.mV);
- }
-
+
if (mTestImageName)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
- if (sRenderPass != AVATAR_RENDER_PASS_SINGLE)
+ /*if (sRenderPass != AVATAR_RENDER_PASS_SINGLE)
{
LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
@@ -1402,7 +780,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glAlphaFunc(GL_GREATER, 0.01f);
- }
+ }*/
if (mTexture.notNull()) {
if (!mTexture->getClampS()) {
@@ -1419,19 +797,20 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea )
//-----------------------------------------------------------------------------
// updateFaceSizes()
//-----------------------------------------------------------------------------
-void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, F32 pixel_area)
+void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
{
// Do a pre-alloc pass to determine sizes of data.
if (mMesh && mValid)
{
mMesh->mFaceVertexOffset = num_vertices;
mMesh->mFaceVertexCount = mMesh->getNumVertices();
+ mMesh->mFaceIndexOffset = num_indices;
+ mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
+
mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount;
- num_vertices += mMesh->getNumVertices();
- mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
-
- mMesh->getSharedData()->genIndices(mMesh->mFaceVertexOffset);
+ num_vertices += mMesh->getNumVertices();
+ num_indices += mMesh->mFaceIndexCount;
}
}
@@ -1441,9 +820,7 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, F32 pixel_area)
void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
{
U32 i;
-
- if (!mValid) return;
-
+
mFace = face;
LLStrider<LLVector3> verticesp;
@@ -1452,13 +829,15 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
LLStrider<LLVector2> tex_coordsp;
LLStrider<F32> vertex_weightsp;
LLStrider<LLVector4> clothing_weightsp;
+ LLStrider<U32> indicesp;
// Copy data into the faces from the polymesh data.
- if (mMesh)
+ if (mMesh && mValid)
{
if (mMesh->getNumVertices())
{
S32 index = face->getGeometryAvatar(verticesp, normalsp, binormalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
+ face->mVertexBuffer->getIndexStrider(indicesp);
if (-1 == index)
{
@@ -1474,11 +853,20 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i);
if (damp_wind)
{
- clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(0,0,0,0);
+ clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0);
}
else
{
- clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(*(mMesh->getClothingWeights() + i));
+ clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i));
+ }
+ }
+
+ for (S32 i = 0; i < mMesh->getNumFaces(); i++)
+ {
+ for (U32 j = 0; j < 3; j++)
+ {
+ U32 k = i*3+j+mMesh->mFaceIndexOffset;
+ indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset;
}
}
}
@@ -1495,6 +883,92 @@ BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate)
return (valid != activate);
}
+void LLViewerJointMesh::updateGeometry()
+{
+ if (mValid && mMesh && mFace &&
+ mMesh->hasWeights() &&
+ mFace->mVertexBuffer.notNull() &&
+ gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR) == 0)
+ {
+ uploadJointMatrices();
+ LLStrider<LLVector3> o_vertices;
+ LLStrider<LLVector3> o_normals;
+
+ //get vertex and normal striders
+ LLVertexBuffer *buffer = mFace->mVertexBuffer;
+ buffer->getVertexStrider(o_vertices, 0);
+ buffer->getNormalStrider(o_normals, 0);
+
+ {
+ LLVector4 tpos0, tnorm0, tpos1, tnorm1, tbinorm0, tbinorm1;
+ F32 last_weight = F32_MAX;
+ LLMatrix3 gBlendRotMat;
+
+
+ for (U32 index= 0; index < mMesh->getNumVertices(); index++)
+ {
+ // blend by first matrix
+ F32 w = mMesh->getWeights()[index];
+
+ if (w != last_weight)
+ {
+ last_weight = w;
+
+ S32 joint = llfloor(w);
+ w -= joint;
+
+ LLMatrix4 &m0 = gJointMat[joint+1];
+ LLMatrix4 &m1 = gJointMat[joint+0];
+ LLMatrix3 &n0 = gJointRot[joint+1];
+ LLMatrix3 &n1 = gJointRot[joint+0];
+
+ if (w == 1.0f)
+ {
+ gBlendMat = m0;
+ gBlendRotMat = n0;
+ }
+ else
+ {
+ gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
+ gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
+ gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
+
+ gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
+ gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
+ gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
+
+ gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
+ gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
+ gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
+
+ gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
+ gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
+ gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
+
+ gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
+ gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
+ gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
+
+ gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
+ gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
+ gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
+
+ gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
+ gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
+ gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
+ }
+ }
+
+ // write result
+ U32 bidx = index + mMesh->mFaceVertexOffset;
+
+ o_vertices[bidx] = mMesh->getCoords()[index] * gBlendMat;
+ o_normals[bidx] = mMesh->getNormals()[index] * gBlendRotMat;
+ }
+ }
+ }
+}
+
void LLViewerJointMesh::dump()
{
if (mValid)
diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h
index 963ad05595..b6fd8afcdb 100644
--- a/indra/newview/llviewerjointmesh.h
+++ b/indra/newview/llviewerjointmesh.h
@@ -114,11 +114,12 @@ public:
// overloaded from base class
/*virtual*/ void drawBone();
/*virtual*/ BOOL isTransparent();
- /*virtual*/ U32 drawShape( F32 pixelArea );
+ /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass );
- /*virtual*/ void updateFaceSizes(U32 &num_vertices, F32 pixel_area);
+ /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area);
/*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE);
/*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate);
+ /*virtual*/ void updateGeometry();
/*virtual*/ void dump();
void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; }
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f6873c61b8..e9e98a4916 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -57,7 +57,6 @@
#include "lldir.h"
#include "lldrawable.h"
#include "lldrawpoolalpha.h"
-#include "lldrawpoolhud.h"
#include "lldrawpooltree.h"
#include "llface.h"
#include "llfirstuse.h"
@@ -263,7 +262,6 @@ typedef LLMemberListener<LLView> view_listener_t;
//
// Local prototypes
//
-BOOL enable_attach(void*);
void handle_leave_group(void *);
// File Menu
@@ -335,9 +333,6 @@ BOOL check_toggle_hacked_godmode(void*);
void toggle_glow(void *);
BOOL check_glow(void *);
-void toggle_vbo(void *);
-BOOL check_vbo(void *);
-
void toggle_vertex_shaders(void *);
BOOL check_vertex_shaders(void *);
@@ -758,6 +753,12 @@ void init_client_menu(LLMenuGL* menu)
menu->append(new LLMenuItemToggleGL("Quiet Snapshots to Disk",
&gQuietSnapshot));
+ menu->append(new LLMenuItemCheckGL( "Compress Snapshots to Disk",
+ &menu_toggle_control,
+ NULL,
+ &menu_check_control,
+ (void*)"CompressSnapshotsToDisk"));
+
menu->append(new LLMenuItemCheckGL("Show Mouselook Crosshairs",
&menu_toggle_control,
NULL,
@@ -880,6 +881,11 @@ void init_client_menu(LLMenuGL* menu)
menu->append(new LLMenuItemToggleGL("Disable Camera Constraints",
&LLViewerCamera::sDisableCameraConstraints));
+ menu->append(new LLMenuItemCheckGL("Mouse Smoothing",
+ &menu_toggle_control,
+ NULL,
+ &menu_check_control,
+ (void*) "MouseSmooth"));
menu->appendSeparator();
menu->append(new LLMenuItemCheckGL( "Console Window",
@@ -1008,56 +1014,56 @@ void init_debug_rendering_menu(LLMenuGL* menu)
menu->appendMenu(sub_menu);
sub_menu->append(new LLMenuItemCheckGL("Simple",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_SIMPLE, '1', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Alpha",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_ALPHA, '2', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Tree",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_TREE, '3', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Character",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_AVATAR, '4', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("SurfacePatch",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_TERRAIN, '5', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Sky",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_SKY, '6', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Water",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_WATER, '7', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Ground",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_GROUND, '8', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Volume",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_VOLUME, '9', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Grass",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_GRASS, '0', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Clouds",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_CLOUDS, '-', MASK_CONTROL|MASK_ALT| MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Particles",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_PARTICLES, '=', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->append(new LLMenuItemCheckGL("Bump",
- &LLPipeline::toggleRenderType, NULL,
- &LLPipeline::toggleRenderTypeControl,
+ &LLPipeline::toggleRenderTypeControl, NULL,
+ &LLPipeline::hasRenderTypeControl,
(void*)LLPipeline::RENDER_TYPE_BUMP, '\\', MASK_CONTROL|MASK_ALT|MASK_SHIFT));
sub_menu->createJumpKeys();
sub_menu = new LLMenuGL("Features");
@@ -1078,6 +1084,10 @@ void init_debug_rendering_menu(LLMenuGL* menu)
&LLPipeline::toggleRenderDebugFeature, NULL,
&LLPipeline::toggleRenderDebugFeatureControl,
(void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, '4', MASK_ALT|MASK_CONTROL));
+ sub_menu->append(new LLMenuItemCheckGL( "Foot Shadows",
+ &LLPipeline::toggleRenderDebugFeature, NULL,
+ &LLPipeline::toggleRenderDebugFeatureControl,
+ (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, '5', MASK_ALT|MASK_CONTROL));
sub_menu->append(new LLMenuItemCheckGL("Fog",
&LLPipeline::toggleRenderDebugFeature, NULL,
&LLPipeline::toggleRenderDebugFeatureControl,
@@ -1091,13 +1101,9 @@ void init_debug_rendering_menu(LLMenuGL* menu)
&LLPipeline::toggleRenderDebugFeatureControl,
(void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, '8', MASK_ALT|MASK_CONTROL));
sub_menu->append(new LLMenuItemCheckGL( "Flexible Objects",
- &LLPipeline::toggleRenderDebugFeature, NULL,
+ &LLPipeline::toggleRenderDebugFeature, NULL,
&LLPipeline::toggleRenderDebugFeatureControl,
(void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, '9', MASK_ALT|MASK_CONTROL));
- sub_menu->append(new LLMenuItemCheckGL( "Chain Faces",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES, '0', MASK_ALT|MASK_CONTROL));
sub_menu->createJumpKeys();
/////////////////////////////
@@ -1110,9 +1116,6 @@ void init_debug_rendering_menu(LLMenuGL* menu)
sub_menu->append(new LLMenuItemCheckGL("Verify", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_VERIFY));
- sub_menu->append(new LLMenuItemCheckGL("AGP Map", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_AGP_MEM));
sub_menu->append(new LLMenuItemCheckGL("BBoxes", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_BBOXES));
@@ -1125,12 +1128,18 @@ void init_debug_rendering_menu(LLMenuGL* menu)
sub_menu->append(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_OCCLUSION));
- sub_menu->append(new LLMenuItemCheckGL("Face Chains", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_FACE_CHAINS));
sub_menu->append(new LLMenuItemCheckGL("Texture Priority", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY));
+ (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY));
+ sub_menu->append(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
+ &LLPipeline::toggleRenderDebugControl,
+ (void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA));
+ sub_menu->append(new LLMenuItemCheckGL("Pick Render", &LLPipeline::toggleRenderDebug, NULL,
+ &LLPipeline::toggleRenderDebugControl,
+ (void*)LLPipeline::RENDER_DEBUG_PICKING));
+ sub_menu->append(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderDebug, NULL,
+ &LLPipeline::toggleRenderDebugControl,
+ (void*)LLPipeline::RENDER_DEBUG_PARTICLES));
sub_menu->append(new LLMenuItemCheckGL("Composition", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_COMPOSITION));
@@ -1140,16 +1149,7 @@ void init_debug_rendering_menu(LLMenuGL* menu)
sub_menu->append(new LLMenuItemCheckGL("LightTrace",&LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_LIGHT_TRACE));
- sub_menu->append(new LLMenuItemCheckGL("Pools", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_POOLS));
- sub_menu->append(new LLMenuItemCheckGL("Queues", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_QUEUES));
- sub_menu->append(new LLMenuItemCheckGL("Map", &LLPipeline::toggleRenderDebug, NULL,
- LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_MAP));
-
+
sub_menu->append(new LLMenuItemCheckGL("Show Depth Buffer",
&menu_toggle_control,
NULL,
@@ -1174,8 +1174,6 @@ void init_debug_rendering_menu(LLMenuGL* menu)
menu->appendSeparator();
menu->append(new LLMenuItemCheckGL("Axes", menu_toggle_control, NULL, menu_check_control, (void*)"ShowAxes"));
- menu->append(new LLMenuItemCheckGL("Use VBO", toggle_vbo, NULL, check_vbo, NULL));
- menu->append(new LLMenuItemCheckGL("Light Glows", toggle_glow, NULL, check_glow, NULL));
// menu->append(new LLMenuItemCheckGL("Cull Small Objects", toggle_cull_small, NULL, menu_check_control, (void*)"RenderCullBySize"));
menu->appendSeparator();
@@ -1200,6 +1198,19 @@ void init_debug_rendering_menu(LLMenuGL* menu)
item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_variable, NULL, menu_check_variable, (void*)&LLViewerImage::sDontLoadVolumeTextures);
menu->append(item);
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, NULL, menu_check_control, (void*)"ImagePipelineUseHTTP");
+ menu->append(item);
+#endif
+
+ item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, NULL, menu_check_control, (void*)"RunMultipleThreads");
+ menu->append(item);
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ item = new LLMenuItemCheckGL("Dynamic Reflections", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDynamicReflections");
+ menu->append(item);
+#endif
+
item = new LLMenuItemCheckGL("Cheesy Beacon", menu_toggle_control, NULL, menu_check_control, (void*)"CheesyBeacon");
menu->append(item);
@@ -1256,10 +1267,6 @@ void init_debug_avatar_menu(LLMenuGL* menu)
//menu->append(new LLMenuItemToggleGL("Show Attachment Points", &LLVOAvatar::sShowAttachmentPoints));
menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane));
menu->append(new LLMenuItemToggleGL("Show Collision Skeleton", &LLVOAvatar::sShowCollisionVolumes));
- menu->append(new LLMenuItemToggleGL("Software Blending SSE", &gGLManager.mSoftwareBlendSSE));
-#if 0 // Removed since this feature doesn't actually work as of 1.9.1 --TomY
- menu->append(new LLMenuItemToggleGL("Character Load Test", &LLVOAvatar::sAvatarLoadTest));
-#endif
menu->append(new LLMenuItemToggleGL( "Display Agent Target", &LLAgent::sDebugDisplayTarget));
menu->append(new LLMenuItemToggleGL( "Debug Rotation", &gDebugAvatarRotation));
menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments));
@@ -1319,7 +1326,8 @@ void init_server_menu(LLMenuGL* menu)
menu->appendMenu(sub);
sub->append(new LLMenuItemCallGL( "Take Copy",
- &force_take_copy, &enable_god_customer_service, NULL));
+ &force_take_copy, &enable_god_customer_service, NULL,
+ 'O', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
#ifdef _CORY_TESTING
sub->append(new LLMenuItemCallGL( "Export Copy",
&force_export_copy, NULL, NULL));
@@ -1509,37 +1517,6 @@ class LLObjectEnableReportAbuse : public view_listener_t
}
};
-
-BOOL enable_attach(void*)
-{
- // All root objects must be owned by agent.
- LLObjectSelectionHandle selection = gSelectMgr->getSelection();
- BOOL rv = FALSE;
- LLViewerObject* obj = selection->getFirstRootObject();
- if(obj)
- {
- rv = TRUE;
- for(obj = selection->getFirstRootObject() ; obj != NULL; obj = selection->getNextRootObject())
- {
- for (U32 child_num = 0; child_num < obj->mChildList.size(); child_num++ )
- {
- LLViewerObject *child = obj->mChildList[child_num];
- if (child->isAvatar())
- {
- return FALSE;
- }
- }
- if(!obj->permMove())
- {
- rv = FALSE;
- break;
- }
- }
- }
- return rv;
-}
-
-
class LLObjectTouch : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -1886,7 +1863,7 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
attachmentp;
attachmentp = avatarp->mAttachmentPoints.getNextData())
{
- if (attachmentp->getObject(0))
+ if (attachmentp->getObject())
{
new_value = true;
break;
@@ -6096,15 +6073,6 @@ class LLToolsLookAtSelection : public view_listener_t
}
};
-/*
-void handle_reset_rotation(void*)
-{
- gSelectMgr->selectionResetRotation();
-
- dialog_refresh_all();
-}
-*/
-
class LLAvatarAddFriend : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -6789,7 +6757,10 @@ private:
LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
if (selectedObject)
{
- LLViewerJointAttachment* attachment_point = gAgent.getAvatarObject()->mAttachmentPoints[userdata.asInteger()];
+ S32 index = userdata.asInteger();
+ LLViewerJointAttachment* attachment_point = index > 0 ?
+ gAgent.getAvatarObject()->mAttachmentPoints[index] :
+ NULL;
confirm_replace_attachment(0, attachment_point);
}
return true;
@@ -6830,7 +6801,7 @@ void handle_attach_to_avatar(void* user_data)
{
LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
- if (attachment && attachment->getObject(0))
+ if (attachment && attachment->getObject())
{
gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment, user_data);
}
@@ -6921,7 +6892,7 @@ void handle_detach_from_avatar(void* user_data)
{
LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
- LLViewerObject* attached_object = attachment->getObject(0);
+ LLViewerObject* attached_object = attachment->getObject();
if (attached_object)
{
@@ -6942,7 +6913,7 @@ void attach_label(LLString& label, void* user_data)
if (attachmentp)
{
label = attachmentp->getName();
- if (attachmentp->getObject(0))
+ if (attachmentp->getObject())
{
LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
if (itemp)
@@ -6959,7 +6930,7 @@ void detach_label(LLString& label, void* user_data)
if (attachmentp)
{
label = attachmentp->getName();
- if (attachmentp->getObject(0))
+ if (attachmentp->getObject())
{
LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
if (itemp)
@@ -7159,23 +7130,7 @@ class LLObjectEnableWear : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
- bool new_value = false;
- if (gSelectMgr)
- {
- LLObjectSelectionHandle selection = gSelectMgr->getSelection();
- LLViewerObject* first_root = selection->getFirstRootObject();
- if (first_root)
- {
- new_value = selection->getRootObjectCount() == 1
- && first_root->getPCode() == LL_PCODE_VOLUME
- && first_root->permYouOwner()
- && !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar()
- && (first_root->getNVPair("AssetContainer") == NULL);
- }
- }
-
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return object_selected_and_point_valid(NULL);
}
};
@@ -7184,7 +7139,7 @@ BOOL object_attached(void *user_data)
{
LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
- return attachment->getObject(0) != NULL;
+ return attachment->getObject() != NULL;
}
class LLAvatarSendIM : public view_listener_t
@@ -7481,16 +7436,16 @@ void handle_dump_attachments(void*)
attachment = avatar->mAttachmentPoints.getNextData() )
{
S32 key = avatar->mAttachmentPoints.getCurrentKeyWithoutIncrement();
- BOOL visible = (attachment->getObject(0) != NULL &&
- attachment->getObject(0)->mDrawable.notNull() &&
- !attachment->getObject(0)->mDrawable->isRenderType(0));
+ BOOL visible = (attachment->getObject() != NULL &&
+ attachment->getObject()->mDrawable.notNull() &&
+ !attachment->getObject()->mDrawable->isRenderType(0));
LLVector3 pos;
- if (visible) pos = attachment->getObject(0)->mDrawable->getPosition();
+ if (visible) pos = attachment->getObject()->mDrawable->getPosition();
llinfos << "ATTACHMENT " << key << ": item_id=" << attachment->getItemID()
- << (attachment->getObject(0) ? " present " : " absent ")
+ << (attachment->getObject() ? " present " : " absent ")
<< (visible ? "visible " : "invisible ")
<< " at " << pos
- << " and " << (visible ? attachment->getObject(0)->getPosition() : LLVector3::zero)
+ << " and " << (visible ? attachment->getObject()->getPosition() : LLVector3::zero)
<< llendl;
}
}
@@ -7873,26 +7828,6 @@ BOOL enable_god_basic(void*)
return gAgent.getGodLevel() > GOD_NOT;
}
-void toggle_vbo(void *)
-{
- gPipeline.mUseVBO = !gPipeline.mUseVBO;
-
- if (!gPipeline.usingAGP())
- {
- return;
- }
-
- gPipeline.setUseAGP(FALSE);
- gPipeline.setUseAGP(TRUE);
-
- gSavedSettings.setBOOL("RenderUseVBO", gPipeline.mUseVBO);
-}
-
-BOOL check_vbo(void *)
-{
- return gPipeline.mUseVBO;
-}
-
#if 0 // 1.9.2
void toggle_vertex_shaders(void *)
{
@@ -7906,19 +7841,6 @@ BOOL check_vertex_shaders(void *)
}
#endif
-void toggle_glow(void *)
-{
- gRenderLightGlows = !gRenderLightGlows;
-
- gSavedSettings.setBOOL("RenderLightGlows", gRenderLightGlows);
-}
-
-BOOL check_glow(void *)
-{
- return gRenderLightGlows;
-}
-
-
void toggle_show_xui_names(void *)
{
BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames");
@@ -8428,7 +8350,7 @@ class LLViewToggleRenderType : public view_listener_t
LLString type = userdata.asString();
if (type == "particles")
{
- LLPipeline::toggleRenderType((void *)(S32)LLPipeline::RENDER_TYPE_PARTICLES);
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
}
return true;
}
@@ -8449,12 +8371,11 @@ class LLViewCheckRenderType : public view_listener_t
}
};
-// TomY TODO: Get rid of these?
class LLViewShowHUDAttachments : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
- LLDrawPoolHUD::sShowHUDAttachments = !LLDrawPoolHUD::sShowHUDAttachments;
+ LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
return true;
}
};
@@ -8463,7 +8384,7 @@ class LLViewCheckHUDAttachments : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
- bool new_value = LLDrawPoolHUD::sShowHUDAttachments;
+ bool new_value = LLPipeline::sShowHUDAttachments;
gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
return true;
}
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e1f51586f4..8ed5406e85 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2893,7 +2893,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
extern U32 gObjectBits;
void process_object_update(LLMessageSystem *mesgsys, void **user_data)
-{
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -2911,6 +2912,7 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data)
void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -2928,6 +2930,7 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -2946,6 +2949,7 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data)
{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
if (mesgsys->getReceiveCompressedSize())
{
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1ff2d81b0c..615bc1bf4f 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -68,7 +68,6 @@
#include "llvosurfacepatch.h"
#include "llvotextbubble.h"
#include "llvotree.h"
-#include "llvotreenew.h"
#include "llvovolume.h"
#include "llvowater.h"
#include "llworld.h"
@@ -112,7 +111,6 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
case LL_PCODE_TREE_NEW:
llwarns << "Creating new tree!" << llendl;
// res = new LLVOTree(id, pcode, regionp); break;
-// res = new LLVOTreeNew(id, pcode, regionp); break;
res = NULL; break;
case LL_PCODE_LEGACY_TEXT_BUBBLE:
res = new LLVOTextBubble(id, pcode, regionp); break;
@@ -154,10 +152,11 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mText(),
mLastInterpUpdateSecs(0.f),
mLastMessageUpdateSecs(0.f),
+ mLatestRecvPacketID(0),
mData(NULL),
mAudioSourcep(NULL),
mAppAngle(0.f),
- mPixelArea(0.f),
+ mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
mRegionp( regionp ),
@@ -169,7 +168,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mOnActiveList(FALSE),
mOnMap(FALSE),
mStatic(FALSE),
- mFaceIndexOffset(0),
mNumFaces(0),
mLastUpdateFrame(0),
mTimeDilation(1.f),
@@ -349,10 +347,12 @@ void LLViewerObject::dump() const
llinfos << "Velocity: " << getVelocity() << llendl;
if (mDrawable.notNull() && mDrawable->getNumFaces())
{
- LLDrawPool *poolp = mDrawable->getFace(0)->getPool();
- llinfos << "Pool: " << poolp << llendl;
- llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
- llinfos << "Pool vertex count: " << poolp->getVertexCount() << llendl;
+ LLFacePool *poolp = mDrawable->getFace(0)->getPool();
+ if (poolp)
+ {
+ llinfos << "Pool: " << poolp << llendl;
+ llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
+ }
}
//llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl;
//llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl;
@@ -596,11 +596,24 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
return FALSE;
}
+ LLDrawable* old_parent = mDrawable->mParent;
+
mDrawable->mParent = parentp;
BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- gPipeline.markMoved(mDrawable, FALSE);
+ if (old_parent || (parentp && parentp->isActive()))
+ {
+ gPipeline.markMoved(mDrawable, FALSE);
+ }
+ else
+ {
+ mDrawable->updateXform(TRUE);
+ if (!mDrawable->getSpatialGroup())
+ {
+ mDrawable->movePartition();
+ }
+ }
return ret;
}
@@ -655,7 +668,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
LLVector3 new_acc;
LLVector3 new_angv;
LLQuaternion new_rot;
- LLVector3 new_scale;
+ LLVector3 new_scale = getScale();
U32 parent_id = 0;
U8 material = 0;
@@ -881,13 +894,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// ...new objects that should come in selected need to be added to the selected list
mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
- // Set the change flags for scale
- if (new_scale != getScale())
- {
- setChanged(SCALED | SILHOUETTE);
- setScale(new_scale); // Must follow setting permYouOwner()
- }
-
// Set all name value pairs
S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue);
if (nv_size > 0)
@@ -1465,14 +1471,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// ...new objects that should come in selected need to be added to the selected list
mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
-
- // Set the change flags for scale
- if (new_scale != getScale())
- {
- setChanged(SCALED | SILHOUETTE);
- setScale(new_scale); // Must follow setting permYouOwner()
- }
-
}
break;
@@ -1744,6 +1742,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
//
//
+ U32 packet_id = mesgsys->getCurrentRecvPacketID();
+ if (packet_id < mLatestRecvPacketID &&
+ mLatestRecvPacketID - packet_id < 65536)
+ {
+ //skip application of this message, it's old
+ return retval;
+ }
+
+ mLatestRecvPacketID = packet_id;
+
+ // Set the change flags for scale
+ if (new_scale != getScale())
+ {
+ setChanged(SCALED | SILHOUETTE);
+ setScale(new_scale); // Must follow setting permYouOwner()
+ }
+
// first, let's see if the new position is actually a change
//static S32 counter = 0;
@@ -1771,14 +1786,10 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (new_rot != mLastRot)
{
- // if (getAngularVelocity().isExactlyZero() ||
- // new_angv != getAngularVelocity())
- {
- mLastRot = new_rot;
- setChanged(ROTATED | SILHOUETTE);
- setRotation(new_rot);
- resetRot();
- }
+ mLastRot = new_rot;
+ setChanged(ROTATED | SILHOUETTE);
+ setRotation(new_rot);
+ resetRot();
}
@@ -2625,6 +2636,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable)
return TRUE;
}
+void LLViewerObject::updateFaceSize(S32 idx)
+{
+
+}
+
LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline)
{
return NULL;
@@ -2665,13 +2681,23 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
void LLViewerObject::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
{
LLVector3 center = getRenderPosition();
- F32 sz = llmin(mDrawable->getRadius(), 256.f);
- LLVector3 size = LLVector3(sz,sz,sz);
+ LLVector3 size = getScale();
newMin.setVec(center-size);
newMax.setVec(center+size);
mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
}
+F32 LLViewerObject::getBinRadius()
+{
+ if (mDrawable.notNull())
+ {
+ const LLVector3* ext = mDrawable->getSpatialExtents();
+ return (ext[1]-ext[0]).magVec();
+ }
+
+ return getScale().magVec();
+}
+
F32 LLViewerObject::getMaxScale() const
{
return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]);
@@ -3574,11 +3600,6 @@ S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen)
{
retval = LLPrimitive::setTETexGen(te, texgen);
setChanged(TEXTURE);
- if (mDrawable.notNull() && retval)
- {
- gPipeline.markTextured(mDrawable);
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
- }
}
return retval;
}
@@ -3595,11 +3616,6 @@ S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny)
{
retval = LLPrimitive::setTEShiny(te, shiny);
setChanged(TEXTURE);
- if (mDrawable.notNull() && retval)
- {
- gPipeline.markTextured(mDrawable);
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- }
}
return retval;
}
@@ -3744,7 +3760,7 @@ LLViewerImage *LLViewerObject::getTEImage(const U8 face) const
}
}
- llerrs << "Requested invalid face!" << llendl;
+ llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl;
return NULL;
}
@@ -3838,6 +3854,11 @@ void LLViewerObject::setCanSelect(BOOL canSelect)
void LLViewerObject::setDebugText(const std::string &utf8text)
{
+ if (utf8text.empty() && !mText)
+ {
+ return;
+ }
+
if (!mText)
{
mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
@@ -4558,6 +4579,7 @@ void LLViewerObject::markForUpdate(BOOL priority)
void LLViewerObject::setRegion(LLViewerRegion *regionp)
{
llassert(regionp);
+ mLatestRecvPacketID = 0;
mRegionp = regionp;
setChanged(MOVED | SILHOUETTE);
updateDrawable(FALSE);
@@ -4646,3 +4668,30 @@ void LLViewerObject::resetRot()
{
mRotTime = 0.0f;
}
+
+U32 LLViewerObject::getPartitionType() const
+{
+ return LLPipeline::PARTITION_NONE;
+}
+
+BOOL LLAlphaObject::isParticle()
+{
+ return FALSE;
+}
+
+F32 LLAlphaObject::getPartSize(S32 idx)
+{
+ return 0.f;
+}
+
+// virtual
+void LLStaticViewerObject::updateDrawable(BOOL force_damped)
+{
+ // Force an immediate rebuild on any update
+ if (mDrawable.notNull())
+ {
+ mDrawable->updateXform(TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ clearChanged(SHIFTED);
+}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 285d684dc6..d8b5a14897 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -18,6 +18,7 @@
#include "llhudicon.h"
#include "llinventory.h"
#include "llmemory.h"
+#include "llmemtype.h"
#include "llprimitive.h"
#include "lluuid.h"
#include "llvoinventorylistener.h"
@@ -25,6 +26,7 @@
#include "llquaternion.h"
#include "v3dmath.h"
#include "v3math.h"
+#include "llvertexbuffer.h"
class LLAgent; // TODO: Get rid of this.
class LLAudioSource;
@@ -168,6 +170,7 @@ public:
virtual LLDrawable* createDrawable(LLPipeline *pipeline);
virtual BOOL updateGeometry(LLDrawable *drawable);
+ virtual void updateFaceSize(S32 idx);
virtual BOOL updateLOD();
virtual BOOL setDrawableParent(LLDrawable* parentp);
virtual BOOL updateLighting(BOOL do_lighting) { return TRUE; };
@@ -184,7 +187,7 @@ public:
LLViewerRegion* getRegion() const { return mRegionp; }
BOOL isSelected() const { return mUserSelected; }
- void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;}
+ virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;}
const LLUUID &getID() const { return mID; }
U32 getLocalID() const { return mLocalID; }
@@ -274,8 +277,6 @@ public:
/*virtual*/ BOOL setMaterial(const U8 material);
virtual void setTEImage(const U8 te, LLViewerImage *imagep); // Not derived from LLPrimitive
LLViewerImage *getTEImage(const U8 te) const;
-
- S32 getFaceIndexOffset() { return mFaceIndexOffset; }
void fitFaceTexture(const U8 face);
void sendTEUpdate() const; // Sends packed representation of all texture entry information
@@ -288,6 +289,8 @@ public:
U8 getState() { return mState; }
F32 getAppAngle() const { return mAppAngle; }
+ F32 getPixelArea() const { return mPixelArea; }
+ void setPixelArea(F32 area) { mPixelArea = area; }
F32 getMaxScale() const;
F32 getMidScale() const;
F32 getMinScale() const;
@@ -320,6 +323,7 @@ public:
void markForUpdate(BOOL priority);
void updateVolume(const LLVolumeParams& volume_params);
virtual void updateSpatialExtents(LLVector3& min, LLVector3& max);
+ virtual F32 getBinRadius();
LLBBox getBoundingBoxAgent() const;
@@ -417,6 +421,7 @@ public:
void printNameValuePairs() const;
virtual S32 getLOD() const { return 3; }
+ virtual U32 getPartitionType() const;
virtual LLNetworkData* getParameterEntry(U16 param_type) const;
virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin);
@@ -528,7 +533,7 @@ protected:
F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation
F64 mLastMessageUpdateSecs; // Last update from a message from the simulator
-
+ TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator
// extra data sent from the sim...currently only used for tree species info
U8* mData;
@@ -559,7 +564,6 @@ protected:
BOOL mOnActiveList;
BOOL mOnMap; // On the map.
BOOL mStatic; // Object doesn't move.
- S32 mFaceIndexOffset; // offset into drawable's faces, zero except in special cases
S32 mNumFaces;
S32 mLastUpdateFrame; // frames in which an object had last moved for smart coalescing of drawables
@@ -592,7 +596,6 @@ private:
static S32 sNumObjects;
};
-
///////////////////
//
// Inlines
@@ -623,4 +626,34 @@ public:
U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc.
};
+// subclass of viewer object that can be added to particle partitions
+class LLAlphaObject : public LLViewerObject
+{
+public:
+ LLAlphaObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp)
+ : LLViewerObject(id,type,regionp)
+ { mDepth = 0.f; }
+
+ virtual BOOL isParticle();
+ virtual F32 getPartSize(S32 idx);
+ virtual void getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp) = 0;
+
+ F32 mDepth;
+};
+
+class LLStaticViewerObject : public LLViewerObject
+{
+public:
+ LLStaticViewerObject(const LLUUID& id, const LLPCode type, LLViewerRegion* regionp)
+ : LLViewerObject(id,type,regionp)
+ { }
+
+ virtual void updateDrawable(BOOL force_damped);
+};
+
#endif
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index f4c733299f..68193604bb 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -731,6 +731,15 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
mNumVisCulledStat.addValue(mNumVisCulled);
}
+void LLViewerObjectList::clearDebugText()
+{
+ for (S32 i = 0; i < mObjects.count(); i++)
+ {
+ mObjects[i]->setDebugText("");
+ }
+}
+
+
void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
{
LLMemType mt(LLMemType::MTYPE_OBJECT);
@@ -1052,7 +1061,15 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce
mSelectPickList.clear();
std::vector<LLDrawable*> pick_drawables;
- gPipeline.mObjectPartition->cull(camera, &pick_drawables, TRUE);
+
+ for (i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++)
+ {
+ LLSpatialPartition* part = gPipeline.getSpatialPartition(i);
+ if (part)
+ {
+ part->cull(camera, &pick_drawables, TRUE);
+ }
+ }
for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
iter != pick_drawables.end(); iter++)
@@ -1074,10 +1091,10 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce
LLHUDText::addPickable(mSelectPickList);
- for (objectp = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- objectp;
- objectp = (LLVOAvatar*)LLCharacter::sInstances.getNextData())
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ objectp = (LLVOAvatar*) *iter;
if (!objectp->isDead())
{
if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
@@ -1098,7 +1115,7 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce
{
if (attachmentp->getIsHUDAttachment())
{
- LLViewerObject* objectp = attachmentp->getObject(0);
+ LLViewerObject* objectp = attachmentp->getObject();
if (objectp)
{
mSelectPickList.insert(objectp);
@@ -1114,32 +1131,36 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce
}
}
}
-
+
S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
- S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
-
- std::set<LLViewerObject*>::iterator pick_it;
- i = 0;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
+ if (num_pickables != 0)
{
- LLViewerObject* objp = (*pick_it);
- if (!objp || objp->isDead() || !objp->mbCanSelect)
+ S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
+
+ std::set<LLViewerObject*>::iterator pick_it;
+ i = 0;
+ for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
{
- mSelectPickList.erase(pick_it++);
- continue;
+ LLViewerObject* objp = (*pick_it);
+ if (!objp || objp->isDead() || !objp->mbCanSelect)
+ {
+ mSelectPickList.erase(pick_it++);
+ continue;
+ }
+
+ objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
+ i++;
+ ++pick_it;
}
- objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
- i++;
- ++pick_it;
+ LLHUDIcon::generatePickIDs(i * step, step);
+
+ // At this point, we should only have live drawables/viewer objects
+ gPipeline.renderForSelect(mSelectPickList);
}
-
- LLHUDIcon::generatePickIDs(i * step, step);
}
- // At this point, we should only have live drawables/viewer objects
- gPipeline.renderForSelect();
//
// Render pass for selected objects
//
@@ -1432,6 +1453,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
}
}
+////////////////////////////////////////////////////////////////////////////
LLViewerObjectList::OrphanInfo::OrphanInfo()
{
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index a2893c4b7d..3e148c822f 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -96,6 +96,7 @@ public:
void addToMap(LLViewerObject *objectp);
void removeFromMap(LLViewerObject *objectp);
+ void clearDebugText();
////////////////////////////////////////////
//
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index c1d2f2742e..cd915317ba 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1552,7 +1552,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mHighlightSegments );
- delete bitmap;
+ delete[] bitmap;
bitmap = NULL;
gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
@@ -1604,7 +1604,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
gParcelMgr->resetSegments(gParcelMgr->mCollisionSegments);
gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mCollisionSegments );
- delete bitmap;
+ delete[] bitmap;
bitmap = NULL;
}
@@ -1753,10 +1753,10 @@ void optionally_start_music(const LLString& music_url)
{
if (gSavedSettings.getWarning("FirstStreamingMusic"))
{
- void* data = (void*)strdup(music_url.c_str());
+ std::string* newstring = new std::string(music_url);
gViewerWindow->alertXml("ParcelCanPlayMusic",
callback_start_music,
- (void*)data);
+ (void*)newstring);
}
else if (gSavedSettings.getBOOL("AudioStreamingMusic"))
@@ -1779,7 +1779,7 @@ void optionally_start_music(const LLString& music_url)
void callback_start_music(S32 option, void* data)
{
- const char* music_url = (const char*)data;
+ std::string* music_url = (std::string*)data;
if (0 == option)
{
@@ -1787,7 +1787,7 @@ void callback_start_music(S32 option, void* data)
llinfos << "Starting first parcel music " << music_url << llendl;
if (gAudiop)
{
- gAudiop->startInternetStream(music_url);
+ gAudiop->startInternetStream(music_url->c_str());
LLMediaRemoteCtrl* ctrl = gOverlayBar->getMusicRemoteControl();
ctrl->setTransportState( LLMediaRemoteCtrl::Play, FALSE );
}
@@ -1799,7 +1799,7 @@ void callback_start_music(S32 option, void* data)
gSavedSettings.setWarning("FirstStreamingMusic", FALSE);
- delete [] music_url;
+ delete music_url;
music_url = NULL;
}
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index a159bacd16..f5d7aa1094 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -761,27 +761,6 @@ S32 LLViewerParcelOverlay::renderPropertyLines ()
const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS );
const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3;
- /* JC - Don't do this. Unbinding AGP stalls the draw process,
- dropping frame rate. Not unbinding AGP causes random crashes
- on nVidia cards due to binding non-AGP arrays.
-
- gPipeline.unbindAGP();
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, mVertexArray );
- glColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColorArray );
-
- S32 i;
- for (i = 0; i < mVertexCount; i += vertex_per_edge)
- {
- // Each edge is several vertices
- glDrawArrays(GL_LINE_STRIP, i, vertex_per_edge);
- }
-
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- */
-
// Stomp the camera into two dimensions
LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgent.getCameraPositionGlobal() );
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index db18b74d1f..a6895aff2f 100644
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -13,6 +13,7 @@
#include "llviewercontrol.h"
#include "llagent.h"
+#include "llviewercamera.h"
#include "llviewerobjectlist.h"
#include "llviewerpartsource.h"
#include "llviewerregion.h"
@@ -22,7 +23,7 @@
const S32 MAX_PART_COUNT = 4096;
-const F32 PART_SIM_BOX_SIDE = 32.f;
+const F32 PART_SIM_BOX_SIDE = 16.f;
const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE;
const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
@@ -33,18 +34,28 @@ S32 LLViewerPartSim::sParticleCount = 0;
U32 LLViewerPart::sNextPartID = 1;
+F32 calc_desired_size(LLVector3 pos, LLVector2 scale)
+{
+ F32 desired_size = (pos-gCamera->getOrigin()).magVec();
+ desired_size /= 4;
+ return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2);
+}
+
LLViewerPart::LLViewerPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartSourcep = NULL;
}
LLViewerPart::~LLViewerPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartSourcep = NULL;
}
LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartID = part.mPartID;
mFlags = part.mFlags;
mMaxAge = part.mMaxAge;
@@ -74,6 +85,7 @@ LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVPCallback cb)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartID = LLViewerPart::sNextPartID;
LLViewerPart::sNextPartID++;
mFlags = 0x00f;
@@ -96,8 +108,13 @@ void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVP
LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 box_side)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mVOPartGroupp = NULL;
+ mUniformParticles = TRUE;
+
mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent);
+ llassert_always(center_agent.isFinite());
+
if (!mRegionp)
{
//llwarns << "No region at position, using agent region!" << llendl;
@@ -106,28 +123,39 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 bo
mCenterAgent = center_agent;
mBoxRadius = F_SQRT3*box_side*0.5f;
- LLVector3 rad_vec(box_side*0.5f, box_side*0.5f, box_side*0.5f);
- rad_vec += LLVector3(0.001f, 0.001f, 0.001f);
- mMinObjPos = mCenterAgent - rad_vec;
- mMaxObjPos = mCenterAgent + rad_vec;
+ mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
+ mVOPartGroupp->setViewerPartGroup(this);
+ mVOPartGroupp->setPositionAgent(getCenterAgent());
+ F32 scale = box_side * 0.5f;
+ mVOPartGroupp->setScale(LLVector3(scale,scale,scale));
+ gPipeline.addObject(mVOPartGroupp);
+
+ LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup();
+
+ LLVector3 center(group->mOctreeNode->getCenter());
+ LLVector3 size(group->mOctreeNode->getSize());
+ size += LLVector3(0.01f, 0.01f, 0.01f);
+ mMinObjPos = center - size;
+ mMaxObjPos = center + size;
+
+ static U32 id_seed = 0;
+ mID = ++id_seed;
}
LLViewerPartGroup::~LLViewerPartGroup()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
cleanup();
- S32 count = mParticles.count();
- S32 i;
-
- for (i = 0; i < count; i++)
- {
- mParticles[i].mPartSourcep = NULL;
- }
- mParticles.reset();
+
+ S32 count = (S32) mParticles.size();
+ mParticles.clear();
+
LLViewerPartSim::decPartCount(count);
}
void LLViewerPartGroup::cleanup()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (mVOPartGroupp)
{
if (!mVOPartGroupp->isDead())
@@ -138,8 +166,9 @@ void LLViewerPartGroup::cleanup()
}
}
-BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos)
+BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if ((pos.mV[VX] < mMinObjPos.mV[VX])
|| (pos.mV[VY] < mMinObjPos.mV[VY])
|| (pos.mV[VZ] < mMinObjPos.mV[VZ]))
@@ -154,29 +183,33 @@ BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos)
return FALSE;
}
+ if (desired_size > 0 &&
+ (desired_size < mBoxRadius*0.5f ||
+ desired_size > mBoxRadius*2.f))
+ {
+ return FALSE;
+ }
+
return TRUE;
}
-BOOL LLViewerPartGroup::addPart(LLViewerPart &part)
+BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size)
{
- if (!posInGroup(part.mPosAgent) ||
- (mVOPartGroupp.notNull() && (part.mImagep != mVOPartGroupp->getTEImage(0))))
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] &&
+ !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK);
+
+ if (!posInGroup(part->mPosAgent, desired_size) ||
+ (mUniformParticles && !uniform_part) ||
+ (!mUniformParticles && uniform_part))
{
return FALSE;
}
- if (!mVOPartGroupp)
- {
- mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
- mVOPartGroupp->setViewerPartGroup(this);
- mVOPartGroupp->setPositionAgent(getCenterAgent());
- mVOPartGroupp->setScale(LLVector3(PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE));
- mVOPartGroupp->setTEImage(0, part.mImagep);
- gPipeline.addObject(mVOPartGroupp);
- }
+ gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
- mParticles.put(part);
+ mParticles.push_back(part);
LLViewerPartSim::incPartCount(1);
return TRUE;
}
@@ -184,33 +217,29 @@ BOOL LLViewerPartGroup::addPart(LLViewerPart &part)
void LLViewerPartGroup::removePart(const S32 part_num)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
// Remove the entry for the particle we just deleted.
- LLPointer<LLViewerPartSource> ps = mParticles[mParticles.count() - 1].mPartSourcep;
-
- mParticles[mParticles.count() - 1].mPartSourcep = NULL;
- mParticles.remove(part_num);
- if (part_num < mParticles.count())
+ mParticles.erase(mParticles.begin() + part_num);
+ if (mVOPartGroupp.notNull())
{
- mParticles[part_num].mPartSourcep = ps;
+ gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
}
-
LLViewerPartSim::decPartCount(1);
}
-
void LLViewerPartGroup::updateParticles(const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
S32 i, count;
-
-
+
LLVector3 gravity(0.f, 0.f, -9.8f);
LLViewerRegion *regionp = getRegion();
- count = mParticles.count();
+ count = (S32) mParticles.size();
for (i = 0; i < count; i++)
{
LLVector3 a(0.f, 0.f, 0.f);
- LLViewerPart &part = mParticles[i];
+ LLViewerPart& part = *((LLViewerPart*) mParticles[i]);
// Update current time
const F32 cur_time = part.mLastUpdateTime + dt;
@@ -252,8 +281,6 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
part.mVelocity *= (1.f - step);
part.mVelocity += step*delta_pos;
- //part.mPosAgent *= 1.f - to_target_frac;
- //part.mPosAgent += to_target_frac*part.mPartSourcep->mTargetPosAgent;
}
@@ -322,18 +349,22 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
i--;
count--;
}
- else if (!posInGroup(part.mPosAgent))
+ else
{
- // Transfer particles between groups
- gWorldPointer->mPartSim.put(part);
- removePart(i);
- i--;
- count--;
+ F32 desired_size = calc_desired_size(part.mPosAgent, part.mScale);
+ if (!posInGroup(part.mPosAgent, desired_size))
+ {
+ // Transfer particles between groups
+ gWorldPointer->mPartSim.put(&part);
+ removePart(i);
+ i--;
+ count--;
+ }
}
}
// Kill the viewer object if this particle group is empty
- if (!mParticles.count())
+ if (mParticles.empty())
{
gObjectList.killObject(mVOPartGroupp);
mVOPartGroupp = NULL;
@@ -343,15 +374,16 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
void LLViewerPartGroup::shift(const LLVector3 &offset)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mCenterAgent += offset;
mMinObjPos += offset;
mMaxObjPos += offset;
- S32 count = mParticles.count();
+ S32 count = (S32) mParticles.size();
S32 i;
for (i = 0; i < count; i++)
{
- mParticles[i].mPosAgent += offset;
+ mParticles[i]->mPosAgent += offset;
}
}
@@ -365,34 +397,34 @@ void LLViewerPartGroup::shift(const LLVector3 &offset)
LLViewerPartSim::LLViewerPartSim()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount");
+ static U32 id_seed = 0;
+ mID = ++id_seed;
}
LLViewerPartSim::~LLViewerPartSim()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
S32 i;
S32 count;
// Kill all of the groups (and particles)
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
delete mViewerPartGroups[i];
}
- mViewerPartGroups.reset();
+ mViewerPartGroups.clear();
// Kill all of the sources
- count = mViewerPartSources.count();
- for (i = 0; i < count; i++)
- {
- mViewerPartSources[i] = NULL;
- }
- mViewerPartSources.reset();
+ mViewerPartSources.clear();
}
BOOL LLViewerPartSim::shouldAddPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (sParticleCount > 0.75f*sMaxParticleCount)
{
@@ -413,33 +445,35 @@ BOOL LLViewerPartSim::shouldAddPart()
return TRUE;
}
-void LLViewerPartSim::addPart(LLViewerPart &part)
+void LLViewerPartSim::addPart(LLViewerPart* part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (sParticleCount < MAX_PART_COUNT)
{
put(part);
}
}
-LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part)
+
+LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
- if (part.mPosAgent.magVecSquared() > MAX_MAG)
+ if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite())
{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
+#if !LL_RELEASE_FOR_DOWNLOAD
llwarns << "LLViewerPartSim::put Part out of range!" << llendl;
- llwarns << part.mPosAgent << llendl;
+ llwarns << part->mPosAgent << llendl;
#endif
return NULL;
}
+
+ F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
- S32 i;
- S32 count;
-
- count = mViewerPartGroups.count();
- for (i = 0; i < count; i++)
+ S32 count = (S32) mViewerPartGroups.size();
+ for (S32 i = 0; i < count; i++)
{
- if (mViewerPartGroups[i]->addPart(part))
+ if (mViewerPartGroups[i]->addPart(part, desired_size))
{
// We found a spatial group that we fit into, add us and exit
return mViewerPartGroups[i];
@@ -448,43 +482,27 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part)
// Hmm, we didn't fit in any of the existing spatial groups
// Create a new one...
- LLViewerPartGroup *groupp = createViewerPartGroup(part.mPosAgent);
+ llassert_always(part->mPosAgent.isFinite());
+ LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size);
+ groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] &&
+ !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK));
if (!groupp->addPart(part))
{
llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl;
llinfos << groupp->getCenterAgent() << llendl;
- llinfos << part.mPosAgent << llendl;
+ llinfos << part->mPosAgent << llendl;
return NULL;
}
return groupp;
}
-LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent)
+LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size)
{
- F32 x_origin = ((S32)(pos_agent.mV[VX]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (x_origin > pos_agent.mV[VX])
- {
- x_origin -= PART_SIM_BOX_SIDE;
- }
-
- F32 y_origin = ((S32)(pos_agent.mV[VY]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (y_origin > pos_agent.mV[VY])
- {
- y_origin -= PART_SIM_BOX_SIDE;
- }
-
- F32 z_origin = ((S32)(pos_agent.mV[VZ]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (z_origin > pos_agent.mV[VZ])
- {
- z_origin -= PART_SIM_BOX_SIDE;
- }
-
- LLVector3 group_center(x_origin + PART_SIM_BOX_OFFSET,
- y_origin + PART_SIM_BOX_OFFSET,
- z_origin + PART_SIM_BOX_OFFSET);
-
- LLViewerPartGroup *groupp = new LLViewerPartGroup(group_center, PART_SIM_BOX_SIDE);
- mViewerPartGroups.put(groupp);
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses
+ //pos_agent
+ LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size);
+ mViewerPartGroups.push_back(groupp);
return groupp;
}
@@ -494,7 +512,7 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
S32 i;
S32 count;
- count = mViewerPartSources.count();
+ count = (S32) mViewerPartSources.size();
for (i = 0; i < count; i++)
{
mViewerPartSources[i]->mPosAgent += offset;
@@ -502,13 +520,20 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
mViewerPartSources[i]->mLastUpdatePosAgent += offset;
}
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
mViewerPartGroups[i]->shift(offset);
}
}
+S32 dist_rate_func(F32 distance)
+{
+ //S32 dist = (S32) sqrtf(distance);
+ //dist /= 2;
+ //return llmax(dist,1);
+ return 1;
+}
void LLViewerPartSim::updateSimulation()
{
@@ -523,13 +548,15 @@ void LLViewerPartSim::updateSimulation()
return;
}
+ LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES);
+
// Start at a random particle system so the same
// particle system doesn't always get first pick at the
// particles. Theoretically we'd want to do this in distance
// order or something, but sorting particle sources will be a big
// pain.
S32 i;
- S32 count = mViewerPartSources.count();
+ S32 count = (S32) mViewerPartSources.size();
S32 start = (S32)ll_frand((F32)count);
S32 dir = 1;
if (ll_frand() > 0.5f)
@@ -551,12 +578,24 @@ void LLViewerPartSim::updateSimulation()
if (!mViewerPartSources[i]->isDead())
{
- mViewerPartSources[i]->update(dt);
+ LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp;
+ if (source_object && source_object->mDrawable.notNull())
+ {
+ S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera);
+ if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0)
+ {
+ mViewerPartSources[i]->update(dt*dist);
+ }
+ }
+ else
+ {
+ mViewerPartSources[i]->update(dt);
+ }
}
if (mViewerPartSources[i]->isDead())
{
- mViewerPartSources.remove(i);
+ mViewerPartSources.erase(mViewerPartSources.begin() + i);
count--;
}
else
@@ -567,16 +606,36 @@ void LLViewerPartSim::updateSimulation()
}
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
- mViewerPartGroups[i]->updateParticles(dt);
- if (!mViewerPartGroups[i]->getCount())
+ LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp;
+
+ S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ?
+ dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1;
+ if (vobj)
{
- delete mViewerPartGroups[i];
- mViewerPartGroups.remove(i);
- i--;
- count--;
+ LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
+ if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
+ {
+ dist *= 8;
+ }
+ }
+
+ if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0)
+ {
+ if (vobj)
+ {
+ gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ mViewerPartGroups[i]->updateParticles(dt*dist);
+ if (!mViewerPartGroups[i]->getCount())
+ {
+ delete mViewerPartGroups[i];
+ mViewerPartGroups.erase(mViewerPartGroups.begin() + i);
+ i--;
+ count--;
+ }
}
}
//llinfos << "Particles: " << sParticleCount << llendl;
@@ -585,42 +644,40 @@ void LLViewerPartSim::updateSimulation()
void LLViewerPartSim::addPartSource(LLViewerPartSource *sourcep)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!sourcep)
{
llwarns << "Null part source!" << llendl;
return;
}
- mViewerPartSources.put(sourcep);
+ mViewerPartSources.push_back(sourcep);
}
void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp)
{
- S32 i, count;
- count = mViewerPartGroups.count();
- for (i = 0; i < count; i++)
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); )
{
- if (mViewerPartGroups[i]->getRegion() == regionp)
+ group_list_t::iterator iter = i++;
+
+ if ((*iter)->getRegion() == regionp)
{
- delete mViewerPartGroups[i];
- mViewerPartGroups.remove(i);
- i--;
- count--;
+ i = mViewerPartGroups.erase(iter);
}
}
}
void LLViewerPartSim::cleanMutedParticles(const LLUUID& task_id)
{
- S32 i;
- S32 count = mViewerPartSources.count();
- for (i = 0; i < count; ++i)
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); )
{
- if (mViewerPartSources[i]->getOwnerUUID() == task_id)
+ source_list_t::iterator iter = i++;
+
+ if ((*iter)->getOwnerUUID() == task_id)
{
- mViewerPartSources.remove(i);
- i--;
- count--;
+ i = mViewerPartSources.erase(iter);
}
}
}
diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h
index 83c374a42e..b0b9500ac6 100644
--- a/indra/newview/llviewerpartsim.h
+++ b/indra/newview/llviewerpartsim.h
@@ -31,7 +31,7 @@ typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt);
//
-class LLViewerPart : public LLPartData
+class LLViewerPart : public LLPartData, public LLRefCount
{
public:
LLViewerPart();
@@ -71,19 +71,26 @@ public:
void cleanup();
- BOOL addPart(LLViewerPart &part);
+ BOOL addPart(LLViewerPart* part, const F32 desired_size = -1.f);
void updateParticles(const F32 dt);
- BOOL posInGroup(const LLVector3 &pos);
+ BOOL posInGroup(const LLVector3 &pos, const F32 desired_size = -1.f);
void shift(const LLVector3 &offset);
- LLDynamicArray<LLViewerPart> mParticles;
+ typedef std::vector<LLPointer<LLViewerPart> > part_list_t;
+ part_list_t mParticles;
const LLVector3 &getCenterAgent() const { return mCenterAgent; }
- S32 getCount() const { return mParticles.count(); }
+ S32 getCount() const { return (S32) mParticles.size(); }
LLViewerRegion *getRegion() const { return mRegionp; }
+
+ LLPointer<LLVOPartGroup> mVOPartGroupp;
+
+ BOOL mUniformParticles;
+ U32 mID;
+
protected:
void removePart(const S32 part_num);
@@ -93,11 +100,9 @@ protected:
LLVector3 mMinObjPos;
LLVector3 mMaxObjPos;
- LLPointer<LLVOPartGroup> mVOPartGroupp;
LLViewerRegion *mRegionp;
};
-
class LLViewerPartSim
{
public:
@@ -113,7 +118,7 @@ public:
void cleanupRegion(LLViewerRegion *regionp);
BOOL shouldAddPart(); // Just decides whether this particle should be added or not (for particle count capping)
- void addPart(LLViewerPart &part);
+ void addPart(LLViewerPart* part);
void cleanMutedParticles(const LLUUID& task_id);
friend class LLViewerPartGroup;
@@ -125,15 +130,18 @@ public:
static void incPartCount(const S32 count) { sParticleCount += count; }
static void decPartCount(const S32 count) { sParticleCount -= count; }
+ U32 mID;
+
protected:
- LLViewerPartGroup *createViewerPartGroup(const LLVector3 &pos_agent);
- LLViewerPartGroup *put(LLViewerPart &part);
+ LLViewerPartGroup *createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size);
+ LLViewerPartGroup *put(LLViewerPart* part);
protected:
- LLDynamicArray<LLViewerPartGroup *> mViewerPartGroups;
- LLDynamicArrayPtr<LLPointer<LLViewerPartSource> > mViewerPartSources;
+ typedef std::vector<LLViewerPartGroup *> group_list_t;
+ typedef std::vector<LLPointer<LLViewerPartSource> > source_list_t;
+ group_list_t mViewerPartGroups;
+ source_list_t mViewerPartSources;
LLFrameTimer mSimulationTimer;
-
static S32 sMaxParticleCount;
static S32 sParticleCount;
};
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index 981c5531c9..b14a82e3f1 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -18,6 +18,7 @@
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
#include "llworld.h"
+#include "pipeline.h"
LLViewerPartSource::LLViewerPartSource(const U32 type) :
mType(type),
@@ -26,6 +27,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) :
mLastUpdateTime = 0.f;
mLastPartTime = 0.f;
mIsDead = FALSE;
+ static U32 id_seed = 0;
+ mID = ++id_seed;
}
void LLViewerPartSource::setDead()
@@ -48,6 +51,7 @@ void LLViewerPartSource::update(const F32 dt)
LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
llassert(source_objp);
mSourceObjectp = source_objp;
mPosAgent = mSourceObjectp->getPositionAgent();
@@ -61,18 +65,18 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp)
void LLViewerPartSourceScript::setDead()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mIsDead = TRUE;
mSourceObjectp = NULL;
mTargetObjectp = NULL;
}
-
-
void LLViewerPartSourceScript::update(const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
F32 old_update_time = mLastUpdateTime;
mLastUpdateTime += dt;
-
+
F32 dt_update = mLastUpdateTime - mLastPartTime;
// Update this for objects which have the follow flag set...
@@ -123,6 +127,17 @@ void LLViewerPartSourceScript::update(const F32 dt)
return;
}
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
+ {
+ if (mSourceObjectp.notNull())
+ {
+ std::ostringstream ostr;
+ ostr << mPartSysData;
+ mSourceObjectp->setDebugText(ostr.str());
+ }
+ }
+
BOOL first_run = FALSE;
if (old_update_time <= 0.f)
{
@@ -134,21 +149,7 @@ void LLViewerPartSourceScript::update(const F32 dt)
while ((dt_update > mPartSysData.mBurstRate) || first_run)
{
first_run = FALSE;
- LLViewerPart part;
-
- part.init(this, mImagep, NULL);
- part.mFlags = mPartSysData.mPartData.mFlags;
- part.mMaxAge = mPartSysData.mPartData.mMaxAge;
- part.mStartColor = mPartSysData.mPartData.mStartColor;
- part.mEndColor = mPartSysData.mPartData.mEndColor;
- part.mColor = part.mStartColor;
-
- part.mStartScale = mPartSysData.mPartData.mStartScale;
- part.mEndScale = mPartSysData.mPartData.mEndScale;
- part.mScale = part.mStartScale;
-
- part.mAccel = mPartSysData.mPartAccel;
-
+
// Update the rotation of the particle source by the angular velocity
// First check to see if there is still an angular velocity.
F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
@@ -181,14 +182,29 @@ void LLViewerPartSourceScript::update(const F32 dt)
continue;
}
+ LLPointer<LLViewerPart> part = new LLViewerPart();
+
+ part->init(this, mImagep, NULL);
+ part->mFlags = mPartSysData.mPartData.mFlags;
+ part->mMaxAge = mPartSysData.mPartData.mMaxAge;
+ part->mStartColor = mPartSysData.mPartData.mStartColor;
+ part->mEndColor = mPartSysData.mPartData.mEndColor;
+ part->mColor = part->mStartColor;
+
+ part->mStartScale = mPartSysData.mPartData.mStartScale;
+ part->mEndScale = mPartSysData.mPartData.mEndScale;
+ part->mScale = part->mStartScale;
+
+ part->mAccel = mPartSysData.mPartAccel;
+
if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
{
- part.mPosAgent = mPosAgent;
- part.mVelocity.setVec(0.f, 0.f, 0.f);
+ part->mPosAgent = mPosAgent;
+ part->mVelocity.setVec(0.f, 0.f, 0.f);
}
else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
{
- part.mPosAgent = mPosAgent;
+ part->mPosAgent = mPosAgent;
LLVector3 part_dir_vector;
F32 mvs;
@@ -202,19 +218,18 @@ void LLViewerPartSourceScript::update(const F32 dt)
while ((mvs > 1.f) || (mvs < 0.01f));
part_dir_vector.normVec();
- part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
- part.mVelocity = part_dir_vector;
+ part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
+ part->mVelocity = part_dir_vector;
F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
- part.mVelocity *= speed;
+ part->mVelocity *= speed;
}
else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
|| mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
- {
- part.mPosAgent = mPosAgent;
+ {
+ part->mPosAgent = mPosAgent;
// original implemenetation for part_dir_vector was just:
LLVector3 part_dir_vector(0.0, 0.0, 1.0);
-
// params from the script...
// outer = outer cone angle
// inner = inner cone angle
@@ -224,13 +239,11 @@ void LLViewerPartSourceScript::update(const F32 dt)
// generate a random angle within the given space...
F32 angle = innerAngle + ll_frand(outerAngle - innerAngle);
-
// split which side it will go on randomly...
if (ll_frand() < 0.5)
{
angle = -angle;
}
-
// Both patterns rotate around the x-axis first:
part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
@@ -239,31 +252,32 @@ void LLViewerPartSourceScript::update(const F32 dt)
{
part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0);
}
-
+
// Only apply this rotation if using the deprecated angles.
if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
{
// Deprecated...
part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
}
-
+
if (mSourceObjectp)
{
part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
}
+
part_dir_vector = part_dir_vector * mRotation;
+
+ part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
- part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
-
- part.mVelocity = part_dir_vector;
+ part->mVelocity = part_dir_vector;
F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
- part.mVelocity *= speed;
+ part->mVelocity *= speed;
}
else
{
- part.mPosAgent = mPosAgent;
- part.mVelocity.setVec(0.f, 0.f, 0.f);
+ part->mPosAgent = mPosAgent;
+ part->mVelocity.setVec(0.f, 0.f, 0.f);
//llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl;
}
@@ -278,6 +292,7 @@ void LLViewerPartSourceScript::update(const F32 dt)
// static
LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, const S32 block_num)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!pssp)
{
if (LLPartSysData::isNullPS(block_num))
@@ -319,6 +334,7 @@ LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *so
LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, LLDataPacker &dp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!pssp)
{
LLViewerPartSourceScript *new_pssp = new LLViewerPartSourceScript(source_objp);
@@ -350,11 +366,13 @@ LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *so
void LLViewerPartSourceScript::setImage(LLViewerImage *imagep)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mImagep = imagep;
}
void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mTargetObjectp = objp;
}
@@ -370,6 +388,7 @@ LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
void LLViewerPartSourceSpiral::setDead()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mIsDead = TRUE;
mSourceObjectp = NULL;
}
@@ -377,6 +396,7 @@ void LLViewerPartSourceSpiral::setDead()
void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
F32 frac = part.mLastUpdateTime/part.mMaxAge;
LLVector3 center_pos;
@@ -401,6 +421,7 @@ void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
void LLViewerPartSourceSpiral::update(const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!mImagep)
{
LLUUID id;
@@ -429,18 +450,18 @@ void LLViewerPartSourceSpiral::update(const F32 dt)
{
mPosAgent = mSourceObjectp->getRenderPosition();
}
- LLViewerPart part;
- part.init(this, mImagep, updatePart);
- part.mStartColor = mColor;
- part.mEndColor = mColor;
- part.mEndColor.mV[3] = 0.f;
- part.mPosAgent = mPosAgent;
- part.mMaxAge = 1.f;
- part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
- part.mLastUpdateTime = 0.f;
- part.mScale.mV[0] = 0.25f;
- part.mScale.mV[1] = 0.25f;
- part.mParameter = ll_frand(F_TWO_PI);
+ LLPointer<LLViewerPart> part = new LLViewerPart();
+ part->init(this, mImagep, updatePart);
+ part->mStartColor = mColor;
+ part->mEndColor = mColor;
+ part->mEndColor.mV[3] = 0.f;
+ part->mPosAgent = mPosAgent;
+ part->mMaxAge = 1.f;
+ part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
+ part->mLastUpdateTime = 0.f;
+ part->mScale.mV[0] = 0.25f;
+ part->mScale.mV[1] = 0.25f;
+ part->mParameter = ll_frand(F_TWO_PI);
gWorldPointer->mPartSim.addPart(part);
}
@@ -448,6 +469,7 @@ void LLViewerPartSourceSpiral::update(const F32 dt)
void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mSourceObjectp = objp;
}
@@ -471,6 +493,7 @@ LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
void LLViewerPartSourceBeam::setDead()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mIsDead = TRUE;
mSourceObjectp = NULL;
mTargetObjectp = NULL;
@@ -484,6 +507,7 @@ void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
F32 frac = part.mLastUpdateTime/part.mMaxAge;
LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
@@ -528,7 +552,7 @@ void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
void LLViewerPartSourceBeam::update(const F32 dt)
{
-
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
const F32 RATE = 0.025f;
mLastUpdateTime += dt;
@@ -576,25 +600,25 @@ void LLViewerPartSourceBeam::update(const F32 dt)
mImagep = gImageList.getImage(id);
}
- LLViewerPart part;
- part.init(this, mImagep, NULL);
+ LLPointer<LLViewerPart> part = new LLViewerPart();
+ part->init(this, mImagep, NULL);
- part.mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
+ part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
LLPartData::LL_PART_INTERP_SCALE_MASK |
LLPartData::LL_PART_TARGET_POS_MASK |
LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
- part.mMaxAge = 0.5f;
- part.mStartColor = mColor;
- part.mEndColor = part.mStartColor;
- part.mEndColor.mV[3] = 0.4f;
- part.mColor = part.mStartColor;
+ part->mMaxAge = 0.5f;
+ part->mStartColor = mColor;
+ part->mEndColor = part->mStartColor;
+ part->mEndColor.mV[3] = 0.4f;
+ part->mColor = part->mStartColor;
- part.mStartScale = LLVector2(0.1f, 0.1f);
- part.mEndScale = LLVector2(0.1f, 0.1f);
- part.mScale = part.mStartScale;
+ part->mStartScale = LLVector2(0.1f, 0.1f);
+ part->mEndScale = LLVector2(0.1f, 0.1f);
+ part->mScale = part->mStartScale;
- part.mPosAgent = mPosAgent;
- part.mVelocity = mTargetPosAgent - mPosAgent;
+ part->mPosAgent = mPosAgent;
+ part->mVelocity = mTargetPosAgent - mPosAgent;
gWorldPointer->mPartSim.addPart(part);
}
@@ -602,11 +626,13 @@ void LLViewerPartSourceBeam::update(const F32 dt)
void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mSourceObjectp = objp;
}
void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mTargetObjectp = objp;
}
@@ -621,6 +647,7 @@ LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
void LLViewerPartSourceChat::setDead()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mIsDead = TRUE;
mSourceObjectp = NULL;
}
@@ -628,6 +655,7 @@ void LLViewerPartSourceChat::setDead()
void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
F32 frac = part.mLastUpdateTime/part.mMaxAge;
LLVector3 center_pos;
@@ -652,6 +680,7 @@ void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
void LLViewerPartSourceChat::update(const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!mImagep)
{
LLUUID id;
@@ -690,18 +719,18 @@ void LLViewerPartSourceChat::update(const F32 dt)
{
mPosAgent = mSourceObjectp->getRenderPosition();
}
- LLViewerPart part;
- part.init(this, mImagep, updatePart);
- part.mStartColor = mColor;
- part.mEndColor = mColor;
- part.mEndColor.mV[3] = 0.f;
- part.mPosAgent = mPosAgent;
- part.mMaxAge = 1.f;
- part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
- part.mLastUpdateTime = 0.f;
- part.mScale.mV[0] = 0.25f;
- part.mScale.mV[1] = 0.25f;
- part.mParameter = ll_frand(F_TWO_PI);
+ LLPointer<LLViewerPart> part = new LLViewerPart();
+ part->init(this, mImagep, updatePart);
+ part->mStartColor = mColor;
+ part->mEndColor = mColor;
+ part->mEndColor.mV[3] = 0.f;
+ part->mPosAgent = mPosAgent;
+ part->mMaxAge = 1.f;
+ part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
+ part->mLastUpdateTime = 0.f;
+ part->mScale.mV[0] = 0.25f;
+ part->mScale.mV[1] = 0.25f;
+ part->mParameter = ll_frand(F_TWO_PI);
gWorldPointer->mPartSim.addPart(part);
}
@@ -709,6 +738,7 @@ void LLViewerPartSourceChat::update(const F32 dt)
void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mSourceObjectp = objp;
}
diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h
index 05fa007ead..4bd577b7a5 100644
--- a/indra/newview/llviewerpartsource.h
+++ b/indra/newview/llviewerpartsource.h
@@ -51,13 +51,16 @@ public:
LLVector3 mPosAgent; // Location of the particle source
LLVector3 mTargetPosAgent; // Location of the target position
LLVector3 mLastUpdatePosAgent;
+ LLPointer<LLViewerObject> mSourceObjectp;
+ U32 mID;
+
protected:
U32 mType;
BOOL mIsDead;
F32 mLastUpdateTime;
F32 mLastPartTime;
LLUUID mOwnerUUID;
-
+
// Particle information
U32 mPartFlags; // Flags for the particle
};
@@ -96,7 +99,6 @@ public:
protected:
LLQuaternion mRotation; // Current rotation for particle source
LLPointer<LLViewerImage> mImagep; // Cached image pointer of the mPartSysData UUID
- LLPointer<LLViewerObject> mSourceObjectp; // Source object that this particle system is attached to
LLPointer<LLViewerObject> mTargetObjectp; // Target object for the particle source
};
@@ -122,7 +124,6 @@ public:
LLColor4 mColor;
protected:
LLPointer<LLViewerImage> mImagep;
- LLPointer<LLViewerObject> mSourceObjectp;
LLVector3d mLKGSourcePosGlobal;
};
@@ -150,7 +151,6 @@ public:
static void updatePart(LLViewerPart &part, const F32 dt);
LLPointer<LLViewerImage> mImagep;
- LLPointer<LLViewerObject> mSourceObjectp;
LLPointer<LLViewerObject> mTargetObjectp;
LLVector3d mLKGTargetPosGlobal;
LLColor4 mColor;
@@ -180,7 +180,6 @@ public:
LLColor4 mColor;
protected:
LLPointer<LLViewerImage> mImagep;
- LLPointer<LLViewerObject> mSourceObjectp;
LLVector3d mLKGSourcePosGlobal;
};
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index fa68e25b0e..5235410156 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -575,23 +575,25 @@ void LLViewerRegion::dirtyHeights()
}
}
-BOOL LLViewerRegion::idleUpdate(LLTimer &timer, const F32 max_time)
+BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
{
- BOOL done = mLandp->idleUpdate();
-
+ // did_update returns TRUE if we did at least one significant update
+ BOOL did_update = mLandp->idleUpdate(max_update_time);
+
if (mParcelOverlay)
{
+ // Hopefully not a significant time sink...
mParcelOverlay->idleUpdate();
}
- return done;
+ return did_update;
}
// As above, but forcibly do the update.
void LLViewerRegion::forceUpdate()
{
- mLandp->idleUpdate();
+ mLandp->idleUpdate(0.f);
if (mParcelOverlay)
{
@@ -826,7 +828,7 @@ LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) con
LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const
{
- return getPosRegionFromGlobal(gAgent.getPosGlobalFromAgent(pos_agent));
+ return pos_agent - getOriginAgent();
}
F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
@@ -1260,6 +1262,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewAgentInventory");
capabilityNames.append("EventQueueGet");
+ capabilityNames.append("RequestTextureDownload");
LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this));
}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 3ce6c89430..b3392baf81 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -153,7 +153,7 @@ public:
F32 getWidth() const { return mWidth; }
- BOOL idleUpdate(LLTimer &timer, const F32 max_time);
+ BOOL idleUpdate(F32 max_update_time);
// Like idleUpdate, but forces everything to complete regardless of
// how long it takes.
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index baf241697b..4a5cbd20e6 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -103,13 +103,13 @@ const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] =
// ST_SIM_FPS_20_SECONDS
StatAttributes("Seconds with sim FPS below 20", TRUE, TRUE),
// ST_PHYS_FPS_20_SECONDS
- StatAttributes("Seconds with physics FPS below 20", TRUE, TRUE),
+ StatAttributes("Seconds with physics FPS below 20", FALSE, TRUE),
// ST_LOSS_05_SECONDS
StatAttributes("Seconds with packet loss > 5%", TRUE, TRUE),
// ST_FPS_DROP_50_RATIO
- StatAttributes("Ratio of frames 2x longer than previous", TRUE, FALSE),
- // ST_MEDIA_OBJECT_LIST_LENGTH
- StatAttributes("Number of objects that want to display web pages", TRUE, FALSE),
+ StatAttributes("Ratio of frames 2x longer than previous", FALSE, FALSE),
+ // ST_ENABLE_VBO
+ StatAttributes("Vertex Buffers Enabled", TRUE, FALSE),
// ST_DELTA_BANDWIDTH
StatAttributes("Increase/Decrease in bandwidth based on packet loss", TRUE, FALSE),
// ST_MAX_BANDWIDTH
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 055b21d116..33ed6bcbcf 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -114,7 +114,7 @@ public:
ST_PHYS_FPS_20_SECONDS = 32,
ST_LOSS_05_SECONDS = 33,
ST_FPS_DROP_50_RATIO = 34,
- ST_MEDIA_OBJECT_LIST_LENGTH = 35,
+ ST_ENABLE_VBO = 35,
ST_DELTA_BANDWIDTH = 36,
ST_MAX_BANDWIDTH = 37,
ST_LIGHTING_DETAIL = 38,
diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp
index 4ffdabbbc9..ceef3bbac5 100644
--- a/indra/newview/llviewerthrottle.cpp
+++ b/indra/newview/llviewerthrottle.cpp
@@ -18,11 +18,7 @@
// consts
-// The viewer is allowed to set the under-the-hood bandwidth to 50%
-// greater than the prefs UI shows, under the assumption that the
-// viewer won't receive all the different message types at once.
-// I didn't design this, don't know who did. JC
-const F32 MAX_FRACTIONAL = 1.5f;
+const F32 MAX_FRACTIONAL = 1.0f; // was 1.5, which was causing packet loss, reduced to 1.0 - SJB
const F32 MIN_FRACTIONAL = 0.2f;
const F32 MIN_BANDWIDTH = 50.f;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 1b39c5bf7e..9d4367cc79 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -114,6 +114,8 @@
#include "llimview.h"
#include "lltexlayer.h"
#include "lltextbox.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
#include "lltextureview.h"
#include "lltool.h"
#include "lltoolbar.h"
@@ -1203,6 +1205,13 @@ LLViewerWindow::LLViewerWindow(
LLFontManager::initClass();
+ if (!gFeatureManagerp->isFeatureAvailable("RenderVBO") ||
+ !gGLManager.mHasVertexBufferObject)
+ {
+ gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
+ }
+ LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"));
+
//
// We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
// stuff like AGP if we think that it'll crash the viewer.
@@ -1231,7 +1240,6 @@ LLViewerWindow::LLViewerWindow(
gPipeline.init();
stop_glerror();
initGLDefaults();
- LLViewerImage::initClass();
}
//
@@ -1244,6 +1252,7 @@ LLViewerWindow::LLViewerWindow(
// Init the image list. Must happen after GL is initialized and before the images that
// LLViewerWindow needs are requested.
gImageList.init();
+ LLViewerImage::initClass();
gBumpImageList.init();
// Create container for all sub-views
@@ -1677,11 +1686,23 @@ LLViewerWindow::~LLViewerWindow()
LLWorldMapView::cleanupTextures();
+ llinfos << "Cleaning up pipeline" << llendl;
+ gPipeline.cleanup();
+ stop_glerror();
+
LLViewerImage::cleanupClass();
delete[] mPickBuffer;
mPickBuffer = NULL;
+ if (gSelectMgr)
+ {
+ llinfos << "Cleaning up select manager" << llendl;
+ gSelectMgr->cleanup();
+ }
+
+ LLVertexBuffer::cleanupClass();
+
llinfos << "Stopping GL during shutdown" << llendl;
if (!gNoRender)
{
@@ -1689,15 +1710,7 @@ LLViewerWindow::~LLViewerWindow()
stop_glerror();
}
- if (gSelectMgr)
- {
- llinfos << "Cleaning up select manager" << llendl;
- gSelectMgr->cleanup();
- }
- llinfos << "Cleaning up pipeline" << llendl;
- gPipeline.cleanup();
- stop_glerror();
llinfos << "Destroying Window" << llendl;
destroyWindow();
}
@@ -1829,6 +1842,13 @@ void LLViewerWindow::reshape(S32 width, S32 height)
gViewerStats->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
gViewerStats->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
+
+ //reposition HUD attachments
+ LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ if (avatarp)
+ {
+ avatarp->resetHUDAttachments();
+ }
}
}
@@ -2263,44 +2283,15 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
void LLViewerWindow::moveCursorToCenter()
{
-#if 1 // old version
-
-#if 0 // Dave's changes - this reportedly is making the drift worse on some systems?
- S32 x = llround((F32) mVirtualWindowRect.getWidth() / 2);
- S32 y = llround((F32) mVirtualWindowRect.getHeight() / 2);
-#else
S32 x = mVirtualWindowRect.getWidth() / 2;
S32 y = mVirtualWindowRect.getHeight() / 2;
-#endif
//on a forced move, all deltas get zeroed out to prevent jumping
mCurrentMousePoint.set(x,y);
mLastMousePoint.set(x,y);
mCurrentMouseDelta.set(0,0);
- LLUI::setCursorPositionScreen(x, y);
-
-#else // Richard's version - fails on intel macs
-
- S32 x = llround((F32) mWindowRect.getWidth() / 2);
- S32 y = llround((F32) mWindowRect.getHeight() / 2);
-
- LLCoordWindow window_point;
- mWindow->convertCoords(LLCoordGL(x, y), &window_point);
- mWindow->setCursorPosition(window_point);
-
- // read back cursor position
- mWindow->getCursorPosition(&window_point);
- LLCoordGL new_mouse_pos;
- mWindow->convertCoords(window_point, &new_mouse_pos);
- new_mouse_pos.mX = llround((F32)new_mouse_pos.mX / mDisplayScale.mV[VX]);
- new_mouse_pos.mY = llround((F32)new_mouse_pos.mY / mDisplayScale.mV[VY]);
-
- //on a forced move, all deltas get zeroed out to prevent jumping
- mCurrentMousePoint = new_mouse_pos;
- mLastMousePoint = new_mouse_pos;
- mCurrentMouseDelta.set(0,0);
-#endif
+ LLUI::setCursorPositionScreen(x, y);
}
//////////////////////////////////////////////////////////////////////
@@ -2329,10 +2320,29 @@ BOOL LLViewerWindow::handlePerFrameHover()
mMouseInWindow = TRUE;
}
- S32 dx = mCurrentMousePoint.mX - mLastMousePoint.mX;
- S32 dy = mCurrentMousePoint.mY - mLastMousePoint.mY;
- mCurrentMouseDelta.set(dx,dy);
- LLVector2 mouse_vel((F32)dx, (F32)dy);
+ S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
+ S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+
+ LLVector2 mouse_vel;
+
+ if (gSavedSettings.getBOOL("MouseSmooth"))
+ {
+ static F32 fdx = 0.f;
+ static F32 fdy = 0.f;
+
+ F32 amount = 16.f;
+ fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
+ fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
+
+ mCurrentMouseDelta.set(llround(fdx), llround(fdy));
+ mouse_vel.setVec(fdx,fdy);
+ }
+ else
+ {
+ mCurrentMouseDelta.set(dx, dy);
+ mouse_vel.setVec((F32) dx, (F32) dy);
+ }
+
mMouseVelocityStat.addValue(mouse_vel.magVec());
if (gNoRender)
@@ -3377,8 +3387,8 @@ void LLViewerWindow::analyzeHit(
const S32 UV_PICK_WIDTH = 41;
const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
- S32 pick_face = ((LLVOVolume*)objectp)->getAllTEsSame() ? 0 : face;
- LLFace* facep = objectp->mDrawable->getFace(objectp->getFaceIndexOffset() + pick_face);
+ S32 pick_face = face;
+ LLFace* facep = objectp->mDrawable->getFace(pick_face);
gCamera->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
gPipeline.renderFaceForUVSelect(facep);
@@ -3604,22 +3614,38 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d
}
// Saves an image to the harddrive as "SnapshotX" where X >= 1.
-BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw)
+BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extension_in)
{
if (! raw)
{
return FALSE;
}
+
+ LLString extension(extension_in);
+ if (extension.empty())
+ {
+ extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp";
+ }
+
+ LLFilePicker::ESaveFilter pick_type;
+ if (extension == ".j2c")
+ pick_type = LLFilePicker::FFSAVE_J2C;
+ else if (extension == ".bmp")
+ pick_type = LLFilePicker::FFSAVE_BMP;
+ else if (extension == ".tga")
+ pick_type = LLFilePicker::FFSAVE_TGA;
+ else
+ pick_type = LLFilePicker::FFSAVE_ALL; // ???
// Get a directory if this is the first time.
if (strlen(sSnapshotDir) == 0) /* Flawfinder: ignore */
{
LLString proposed_name( sSnapshotBaseName );
- proposed_name.append( ".bmp" );
+ proposed_name.append( extension );
// pick a directory in which to save
LLFilePicker& picker = LLFilePicker::instance();
- if (!picker.getSaveFile(LLFilePicker::FFSAVE_BMP, proposed_name.c_str()))
+ if (!picker.getSaveFile(pick_type, proposed_name.c_str()))
{
// Clicked cancel
return FALSE;
@@ -3634,8 +3660,8 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw)
S32 length = strlen(directory); /* Flawfinder: ignore */
S32 index = length;
- // Back up over ".bmp"
- index -= 4;
+ // Back up over extension
+ index -= extension.length();
if (index >= 0 && directory[index] == '.')
{
directory[index] = '\0';
@@ -3674,10 +3700,9 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw)
do
{
- char extension[100]; /* Flawfinder: ignore */
- snprintf( extension, sizeof(extension), "_%.3d.bmp", i ); /* Flawfinder: ignore */
filepath = sSnapshotDir;
filepath += sSnapshotBaseName;
+ filepath += llformat("_%.3d",i);
filepath += extension;
struct stat stat_info;
@@ -3686,12 +3711,12 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw)
}
while( -1 != err ); // search until the file is not found (i.e., stat() gives an error).
- LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+ LLPointer<LLImageFormatted> formatted_image = LLImageFormatted::createFromExtension(extension);
LLImageBase::setSizeOverride(TRUE);
- BOOL success = bmp_image->encode(raw);
+ BOOL success = formatted_image->encode(raw);
if( success )
{
- success = bmp_image->save(filepath);
+ success = formatted_image->save(filepath);
}
else
{
@@ -3894,10 +3919,11 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
}
- BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD);
+
+ BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
if (hide_hud)
{
- LLPipeline::toggleRenderType((void*)LLPipeline::RENDER_TYPE_HUD);
+ LLPipeline::sShowHUDAttachments = FALSE;
}
// Copy screen to a buffer
@@ -4034,7 +4060,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
if (hide_hud)
{
- LLPipeline::toggleRenderType((void*)LLPipeline::RENDER_TYPE_HUD);
+ LLPipeline::sShowHUDAttachments = TRUE;
}
if (high_res)
@@ -4296,6 +4322,12 @@ void LLViewerWindow::stopGL(BOOL save_state)
if (!gGLManager.mIsDisabled)
{
llinfos << "Shutting down GL..." << llendl;
+
+ // Pause texture decode threads (will get unpaused during main loop)
+ gTextureCache->pause();
+ gImageDecodeThread->pause();
+ gTextureFetch->pause();
+
gSky.destroyGL();
stop_glerror();
@@ -4346,7 +4378,6 @@ void LLViewerWindow::restoreGL(const LLString& progress_message)
LLManipTranslate::restoreGL();
gImageList.restoreGL();
gBumpImageList.restoreGL();
- gPipeline.setUseAGP(gSavedSettings.getBOOL("RenderUseAGP"));
LLDynamicTexture::restoreGL();
LLVOAvatar::restoreGL();
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 0097a00b7a..5b56bbae06 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -189,7 +189,7 @@ public:
BOOL saveSnapshot(const LLString& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE,
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR );
- BOOL saveImageNumbered(LLImageRaw *raw);
+ BOOL saveImageNumbered(LLImageRaw *raw, const LLString& extension = "");
void playSnapshotAnimAndSound();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 193fd4e325..2c920ecde8 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -28,7 +28,6 @@
#include "timing.h"
#include "llagent.h" // Get state values from here
-#include "llagparray.h"
#include "llviewercontrol.h"
#include "llcriticaldamp.h"
#include "lldir.h"
@@ -191,7 +190,7 @@ const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f;
const F32 APPEARANCE_MORPH_TIME = 0.65f;
const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f;
const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds
-const S32 AVATAR_AGP_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing AGP memory
+const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory
const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f;
const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f;
const S32 MAX_LOD_CHANGES_PER_FRAME = 2;
@@ -770,7 +769,6 @@ LLVOAvatar::LLVOAvatar(
mEyesLayerSet( NULL ),
mSkirtLayerSet( NULL ),
mRenderPriority(1.0f),
- mNumAGPVertices(0),
mNameString(),
mTitle(),
mNameAway(FALSE),
@@ -988,7 +986,7 @@ LLVOAvatar::LLVOAvatar(
//-------------------------------------------------------------------------
// register motions
//-------------------------------------------------------------------------
- if (LLCharacter::sInstances.getLength() == 1)
+ if (LLCharacter::sInstances.size() == 1)
{
LLKeyframeMotion::setVFS(gStaticVFS);
addMotion( ANIM_AGENT_BUSY, LLNullMotion::create );
@@ -1132,7 +1130,8 @@ void LLVOAvatar::markDead()
BOOL LLVOAvatar::isFullyBaked()
{
if (mIsDummy) return TRUE;
-
+ if (getNumTEs() == 0) return FALSE;
+
BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
@@ -1161,10 +1160,10 @@ void LLVOAvatar::deleteLayerSetCaches()
// static
BOOL LLVOAvatar::areAllNearbyInstancesBaked()
{
- for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
if( inst->isDead() )
{
continue;
@@ -1194,10 +1193,10 @@ void LLVOAvatar::dumpBakedStatus()
{
LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal();
- for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
llinfos << "Avatar ";
LLNameValue* firstname = inst->getNVPair("FirstName");
@@ -1386,11 +1385,10 @@ void LLVOAvatar::initVertexPrograms()
//static
void LLVOAvatar::restoreGL()
{
- LLVOAvatar* inst;
- for( inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
inst->setCompositeUpdatesEnabled( TRUE );
inst->invalidateComposite( inst->mHeadLayerSet, FALSE );
inst->invalidateComposite( inst->mLowerBodyLayerSet, FALSE );
@@ -1414,10 +1412,10 @@ void LLVOAvatar::deleteCachedImages()
if (LLTexLayerSet::sHasCaches)
{
lldebugs << "Deleting layer set caches" << llendl;
- for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
inst->deleteLayerSetCaches();
}
LLTexLayerSet::sHasCaches = FALSE;
@@ -1518,30 +1516,30 @@ void LLVOAvatar::initClass()
sSkeletonInfo = new LLVOAvatarSkeletonInfo;
if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
{
- llerrs << "Error parsing skeleton XML file" << llendl;
+ llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
}
// parse avatar_lad.xml
llassert(!sAvatarInfo);
sAvatarInfo = new LLVOAvatarInfo;
if (!sAvatarInfo->parseXmlSkeletonNode(root))
{
- llerrs << "Error parsing skeleton node in avatar XML file" << llendl;
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
if (!sAvatarInfo->parseXmlMeshNodes(root))
{
- llerrs << "Error parsing skeleton node in avatar XML file" << llendl;
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
if (!sAvatarInfo->parseXmlColorNodes(root))
{
- llerrs << "Error parsing skeleton node in avatar XML file" << llendl;
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
if (!sAvatarInfo->parseXmlLayerNodes(root))
{
- llerrs << "Error parsing skeleton node in avatar XML file" << llendl;
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
if (!sAvatarInfo->parseXmlDriverNodes(root))
{
- llerrs << "Error parsing skeleton node in avatar XML file" << llendl;
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
}
@@ -1557,6 +1555,19 @@ void LLVOAvatar::cleanupClass()
}
+void LLVOAvatar::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
+{
+ LLVector3 center = getRenderPosition();
+ LLVector3 size = getScale();
+ //maximum amount an animation can move avatar from drawable position
+ LLVector3 animation_buffer(5, 5, 5);
+
+ newMin.setVec((center-size)-animation_buffer);
+ newMax.setVec(center+size+animation_buffer);
+ mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
+}
+
+
//-----------------------------------------------------------------------------
// parseSkeletonFile()
//-----------------------------------------------------------------------------
@@ -1709,10 +1720,13 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info)
}
// add special-purpose "screen" joint
- mScreenp = new LLViewerJoint("mScreen", NULL);
- // for now, put screen at origin, as it is only used during special
- // HUD rendering mode
- mScreenp->setWorldPosition(LLVector3::zero);
+ if (mIsSelf)
+ {
+ mScreenp = new LLViewerJoint("mScreen", NULL);
+ // for now, put screen at origin, as it is only used during special
+ // HUD rendering mode
+ mScreenp->setWorldPosition(LLVector3::zero);
+ }
return TRUE;
}
@@ -1793,7 +1807,7 @@ void LLVOAvatar::buildCharacter()
return;
}
- gPrintMessagesThisFrame = TRUE;
+// gPrintMessagesThisFrame = TRUE;
lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl;
if ( ! status )
@@ -2076,7 +2090,7 @@ void LLVOAvatar::releaseMeshData()
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
- if (sInstances.getLength() < AVATAR_AGP_RELEASE_THRESHOLD || mIsDummy)
+ if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy)
{
return;
}
@@ -2093,18 +2107,11 @@ void LLVOAvatar::releaseMeshData()
mEyeBallRightLOD.setValid(FALSE, TRUE);
mSkirtLOD.setValid(FALSE, TRUE);
- //cleanup AGP data
+ //cleanup data
if (mDrawable.notNull())
{
LLFace* facep = mDrawable->getFace(0);
facep->setSize(0, 0);
- mNumAGPVertices = 0;
-
- // You need to reset the vertex data in order to guarantee
- // that the data is deallocated, AND you start at the 0 index
- // when you restore the face. We're assuming ONLY ONE FACE per
- // avatar pool, this logic is broken if that isn't the case!
- facep->getPool()->resetVertexData(0);
}
for (LLViewerJointAttachment *attachmentPoint = mAttachmentPoints.getFirstData();
@@ -2148,7 +2155,7 @@ void LLVOAvatar::restoreMeshData()
}
// force mesh update as LOD might not have changed to trigger this
- updateMeshData();
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
}
//-----------------------------------------------------------------------------
@@ -2161,29 +2168,28 @@ void LLVOAvatar::updateMeshData()
LLFace* facep = mDrawable->getFace(0);
U32 num_vertices = 0;
+ U32 num_indices = 0;
// this order is determined by number of LODS
// if a mesh earlier in this list changed LODs while a later mesh doesn't,
// the later mesh's index offset will be inaccurate
- mEyeBallLeftLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mEyeBallRightLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mEyeLashLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mHeadLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mLowerBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mSkirtLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mUpperBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
- mHairLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea);
-
- if (num_vertices != mNumAGPVertices)
- {
- // resize immediately
-// llinfos << "Resizing avatar AGP buffer!" << llendl;
- facep->getPool()->resetVertexData(num_vertices);
- facep->setSize(0,0);
- facep->setSize(num_vertices, 0);
- mNumAGPVertices = num_vertices;
- }
-
+ mEyeBallLeftLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mEyeBallRightLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mEyeLashLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mHeadLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mLowerBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mSkirtLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mUpperBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ mHairLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+
+ // resize immediately
+ facep->setSize(num_vertices, num_indices);
+
+ facep->mVertexBuffer = new LLVertexBufferAvatar();
+ facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
+ facep->setGeomIndex(0);
+ facep->setIndicesIndex(0);
+
// This is a hack! Avatars have their own pool, so we are detecting
// the case of more than one avatar in the pool (thus > 0 instead of >= 0)
if (facep->getGeomIndex() > 0)
@@ -2366,13 +2372,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
setPixelAreaAndAngle(gAgent);
// Update the LOD of the joints
- static const F32 UPDATE_TIME = .5f;
- if (mUpdateLODTimer.hasExpired())
- {
- mUpdateLODTimer.setTimerExpirySec(UPDATE_TIME * (.75f + ll_frand(0.5f)));
- updateJointLODs();
- }
-
+ //static const F32 UPDATE_TIME = .5f;
+
// force asynchronous drawable update
if(mDrawable.notNull() && !gNoRender)
{
@@ -2432,6 +2433,17 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
updateCharacter(agent);
+
+
+ if (LLVOAvatar::sJointDebug)
+ {
+ llinfos << getNVPair("FirstName")->getString() << getNVPair("LastName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl;
+ }
+
+ LLJoint::sNumUpdates = 0;
+ LLJoint::sNumTouches = 0;
+
+
if (gNoRender)
{
return TRUE;
@@ -2440,7 +2452,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// *NOTE: this is necessary for the floating name text above your head.
if (mDrawable.notNull())
{
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE);
}
// update attachments positions
@@ -2450,8 +2462,12 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
attachment;
attachment = mAttachmentPoints.getNextData())
{
- LLViewerObject *attached_object = attachment->getObject(0);
- if (attached_object && !attached_object->isDead() && attachment->getValid())
+ LLViewerObject *attached_object = attachment->getObject();
+
+ BOOL visibleAttachment = isVisible() || !(attached_object && attached_object->mDrawable->getSpatialBridge()
+ && (attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+
+ if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
{
// if selecting any attachments, update all of them as non-damped
if (gSelectMgr->getSelection()->getObjectCount() && gSelectMgr->getSelection()->isAttachment())
@@ -2605,9 +2621,9 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds
BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
BOOL render_name = visible_chat ||
- (mVisible &&
- (sRenderName == RENDER_NAME_ALWAYS) ||
- (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME));
+ (isVisible() &&
+ ((sRenderName == RENDER_NAME_ALWAYS) ||
+ (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
// If it's your own avatar, don't draw in mouselook, and don't
// draw if we're specifically hiding our own name.
if (mIsSelf)
@@ -2984,6 +3000,15 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
+ // update screen joint size
+ if (mScreenp)
+ {
+ F32 aspect = gCamera->getAspect();
+ LLVector3 scale(1.f, aspect, 1.f);
+ mScreenp->setScale(scale);
+ mScreenp->updateWorldMatrixChildren();
+ }
+
// clear debug text
mDebugText.clear();
@@ -3020,14 +3045,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
- if (LLVOAvatar::sJointDebug)
- {
- llinfos << getNVPair("FirstName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl;
-
- LLJoint::sNumUpdates = 0;
- LLJoint::sNumTouches = 0;
- }
-// llinfos << mPixelArea << llendl;
if (gNoRender)
{
// Hack if we're running drones...
@@ -3046,10 +3063,15 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
return;
}
+ if (!mIsSelf && !isVisible())
+ {
+ return;
+ }
+
// change animation time quanta based on avatar render load
if (!mIsSelf)
{
- F32 time_quantum = clamp_rescale((F32)sInstances.getLength(), 10.f, 35.f, 0.f, 0.25f);
+ F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f);
F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f);
F32 time_step = time_quantum * pixel_area_scale;
if (time_step != 0.f)
@@ -3078,10 +3100,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
mTimeVisible.reset();
}
- // update screen joint size
- mScreenp->setScale(LLVector3(1.f, gCamera->getAspect(), 1.f));
- mScreenp->updateWorldMatrixChildren();
-
//--------------------------------------------------------------------
// create local variables in world coords for region position values
//--------------------------------------------------------------------
@@ -3092,6 +3110,8 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
xyVel.mV[VZ] = 0.0f;
speed = xyVel.magVec();
+ BOOL throttle = TRUE;
+
if (!(mIsSitting && getParent()))
{
//--------------------------------------------------------------------
@@ -3102,6 +3122,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
if (mTimeLast == 0.0f)
{
mTimeLast = animation_time;
+ throttle = FALSE;
// put the pelvis at slaved position/mRotation
mRoot.setWorldPosition( getPositionAgent() ); // first frame
@@ -3145,7 +3166,16 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
// correct for the fact that the pelvis is not necessarily the center
// of the agent's physical representation
root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot;
- mRoot.setWorldPosition(gAgent.getPosAgentFromGlobal(root_pos) ); // regular update
+
+
+ LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
+
+ if (newPosition != mRoot.getXform()->getWorldPosition())
+ {
+ mRoot.touch();
+ mRoot.setWorldPosition(newPosition ); // regular update
+ }
+
//--------------------------------------------------------------------
// Propagate viewer object rotation to root of avatar
@@ -3315,9 +3345,10 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
//}
//end Ventrella
- F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f);
-
+ F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f);
+
mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) );
+
}
}
else if (mDrawable.notNull())
@@ -3329,8 +3360,17 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
//--------------------------------------------------------------------
// the rest should only be done when close enough to see it
//--------------------------------------------------------------------
+
+
+ if (mPixelArea > 12.0f)
+ throttle = FALSE;
+ if (mPixelArea < 400.0f)
+ {
+ throttle = (LLDrawable::getCurrentFrame()+mID.mData[0])%2 != 0;
+ }
+
if ( !(mIsSitting && getParent()) &&
- ((mPixelArea < 12.0f) ||
+ (throttle ||
(!isVisible() && (mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE))) )
{
mRoot.setWorldRotation( getRotation() );
@@ -3434,7 +3474,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
}
-
+
mRoot.updateWorldMatrixChildren();
if (!mDebugText.size() && mText.notNull())
@@ -3491,10 +3531,8 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
else if (!force_invisible)
{
// calculate avatar distance wrt head
- LLVector3 pos = mDrawable->getPositionAgent();
- pos -= gCamera->getOrigin();
- mDrawable->mDistanceWRTCamera = pos.magVec();
-
+ mDrawable->updateDistance(*gCamera);
+
if (!mDrawable->getSpatialGroup() || mDrawable->getSpatialGroup()->isVisible())
{
visible = TRUE;
@@ -3566,9 +3604,9 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
attachment;
attachment = mAttachmentPoints.getNextData())
{
- if (attachment->getObject(0))
+ if (attachment->getObject())
{
- if(attachment->getObject(0)->mDrawable->isVisible())
+ if(attachment->getObject()->mDrawable->isVisible())
{
llinfos << attachment->getName() << " visible" << llendl;
}
@@ -3592,7 +3630,6 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
{
restoreMeshData();
}
- gPipeline.markVisible(mDrawable);
}
else
{
@@ -3619,11 +3656,12 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
void LLVOAvatar::updateAllAvatarVisiblity()
{
LLVOAvatar::sNumVisibleAvatars = 0;
- LLVOAvatar *avatarp;
-
+
F32 render_priority = (F32)LLVOAvatar::sMaxVisible;
- for (avatarp = (LLVOAvatar*)sInstances.getFirstData(); avatarp; avatarp = (LLVOAvatar*)sInstances.getNextData())
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* avatarp = (LLVOAvatar*) *iter;
if (avatarp->isDead())
{
continue;
@@ -3761,26 +3799,22 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (pass == AVATAR_RENDER_PASS_SINGLE)
{
+ BOOL first_pass = TRUE;
if (!mIsSelf || gAgent.needsRenderHead())
{
num_indices += mHeadLOD.render(mAdjustedPixelArea);
+ first_pass = FALSE;
}
- num_indices += mUpperBodyLOD.render(mAdjustedPixelArea);
- num_indices += mLowerBodyLOD.render(mAdjustedPixelArea);
- if( isWearingWearableType( WT_SKIRT ) )
- {
- glAlphaFunc(GL_GREATER,0.25f);
- num_indices += mSkirtLOD.render(mAdjustedPixelArea);
- glAlphaFunc(GL_GREATER,0.01f);
- }
+ num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass);
+ num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE);
- if (!mIsSelf || gAgent.needsRenderHead())
{
- num_indices += mEyeLashLOD.render(mAdjustedPixelArea);
- num_indices += mHairLOD.render(mAdjustedPixelArea);
+ LLGLEnable blend(GL_BLEND);
+ LLGLEnable test(GL_ALPHA_TEST);
+ num_indices += renderTransparent();
}
}
- else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER)
+ /*else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER)
{
if (!mIsSelf || gAgent.needsRenderHead())
{
@@ -3813,7 +3847,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
LLViewerJointMesh::sClothingMaskImageName = mLowerMaskTexName;
num_indices += mLowerBodyLOD.render(mAdjustedPixelArea);
LLViewerJointMesh::sClothingMaskImageName = 0;
- }
+ }*/
LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
@@ -3824,6 +3858,27 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
return num_indices;
}
+U32 LLVOAvatar::renderTransparent()
+{
+ U32 num_indices = 0;
+ BOOL first_pass = FALSE;
+ if( isWearingWearableType( WT_SKIRT ) )
+ {
+ glAlphaFunc(GL_GREATER,0.25f);
+ num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE);
+ first_pass = FALSE;
+ glAlphaFunc(GL_GREATER,0.01f);
+ }
+
+ if (!mIsSelf || gAgent.needsRenderHead())
+ {
+ num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass);
+ num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE);
+ }
+
+ return num_indices;
+}
+
//-----------------------------------------------------------------------------
// renderRigid()
//-----------------------------------------------------------------------------
@@ -3852,6 +3907,39 @@ U32 LLVOAvatar::renderRigid()
return num_indices;
}
+U32 LLVOAvatar::renderFootShadows()
+{
+ U32 num_indices = 0;
+
+ if (!mIsBuilt)
+ {
+ return 0;
+ }
+
+ if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
+ {
+ return 0;
+ }
+
+ if (!mIsBuilt)
+ {
+ return 0;
+ }
+
+ U32 foot_mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD;
+
+ //render foot shadows
+ LLGLEnable blend(GL_BLEND);
+ mShadowImagep->bind();
+ glColor4fv(mShadow0Facep->getRenderColor().mV);
+ mShadow0Facep->renderIndexed(foot_mask);
+ glColor4fv(mShadow1Facep->getRenderColor().mV);
+ mShadow1Facep->renderIndexed(foot_mask);
+
+ return num_indices;
+}
+
//-----------------------------------------------------------------------------
// renderCollisionVolumes()
//-----------------------------------------------------------------------------
@@ -3868,6 +3956,7 @@ void LLVOAvatar::renderCollisionVolumes()
//------------------------------------------------------------------------
void LLVOAvatar::updateTextures(LLAgent &agent)
{
+ LLFastTimer ftm(LLFastTimer::FTM_TEMP5);
BOOL render_avatar = TRUE;
if (mIsDummy || gNoRender)
@@ -3942,6 +4031,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
}
*/
+ mMaxPixelArea = 0.f;
+ mMinPixelArea = 99999999.f;
for (U32 i = 0; i < getNumTEs(); i++)
{
LLViewerImage *imagep = getTEImage(i);
@@ -4039,40 +4130,35 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
case TEX_HEAD_BAKED:
if (head_baked)
{
- imagep->setBoostLevel(boost_level);
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
break;
case TEX_UPPER_BAKED:
if (upper_baked)
{
- imagep->setBoostLevel(boost_level);
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
break;
case TEX_LOWER_BAKED:
if (lower_baked)
{
- imagep->setBoostLevel(boost_level);
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
break;
case TEX_EYES_BAKED:
if (eyes_baked)
{
- imagep->setBoostLevel(boost_level);
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
break;
case TEX_SKIRT_BAKED:
if (skirt_baked)
{
- imagep->setBoostLevel(boost_level);
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
break;
@@ -4080,15 +4166,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
// Hair is neither a local texture used for baking, nor the output
// of the baking process. It's just a texture that happens to be
// used to draw avatars. Hence BOOST_AVATAR. JC
- if (mIsSelf)
- {
- imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF);
- }
- else
- {
- imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR);
- }
- imagep->addTextureStats(mPixelArea, texel_area_ratio);
+ boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR;
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
break;
default:
@@ -4098,6 +4177,11 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
}
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ {
+ setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea)));
+ }
+
if( render_avatar )
{
mShadowImagep->addTextureStats(mPixelArea, 1.f);
@@ -4127,6 +4211,15 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma
}
}
+
+void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
+{
+ mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
+ mMinPixelArea = llmin(pixel_area, mMinPixelArea);
+ imagep->addTextureStats(pixel_area, texel_area_ratio);
+ imagep->setBoostLevel(boost_level);
+}
+
//-----------------------------------------------------------------------------
// resolveHeight()
//-----------------------------------------------------------------------------
@@ -4611,7 +4704,7 @@ F32 LLVOAvatar::getTimeDilation()
//-----------------------------------------------------------------------------
// LLVOAvatar::getPixelArea()
//-----------------------------------------------------------------------------
-F32 LLVOAvatar::getPixelArea()
+F32 LLVOAvatar::getPixelArea() const
{
if (mIsDummy)
{
@@ -4973,6 +5066,11 @@ BOOL LLVOAvatar::loadSkeletonNode ()
iter != sAvatarInfo->mAttachmentInfoList.end(); iter++)
{
LLVOAvatarInfo::LLVOAvatarAttachmentInfo *info = *iter;
+ if (!isSelf() && info->mJointName == "mScreen")
+ { //don't process screen joint for other avatars
+ continue;
+ }
+
LLViewerJointAttachment* attachment = new LLViewerJointAttachment();
attachment->setName(info->mName);
@@ -5323,15 +5421,6 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
- LLVector3 viewer_pos_agent = agent.getCameraPositionAgent();
- LLVector3 pos_agent;
-
- pos_agent = getRenderPosition();
-
- F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX];
- F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY];
- F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ];
-
F32 max_scale = getMaxScale();
F32 mid_scale = getMidScale();
F32 min_scale = llmin( getScale().mV[VX], llmin( getScale().mV[VY], getScale().mV[VZ] ) );
@@ -5340,7 +5429,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
// to try to get a min distance from face, subtract min_scale/2 from the range.
// This means we'll load too much detail sometimes, but that's better than not enough
// I don't think there's a better way to do this without calculating distance per-poly
- F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2;
+ F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec() - min_scale/2;
if (range < 0.001f) // range == zero
{
@@ -5375,17 +5464,11 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
//-----------------------------------------------------------------------------
// updateJointLODs()
//-----------------------------------------------------------------------------
-void LLVOAvatar::updateJointLODs()
+BOOL LLVOAvatar::updateJointLODs()
{
- if (!mMeshValid)
- {
- return;
- }
-
F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE));
F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f);
F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);
-
{
if (mIsSelf)
{
@@ -5408,16 +5491,17 @@ void LLVOAvatar::updateJointLODs()
mAdjustedPixelArea = (F32)mPixelArea * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor;
}
- // now select meshes to render based on adjusted pixel area, and perform AGP data push as necessary
+ // now select meshes to render based on adjusted pixel area
BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE);
if (res)
{
sNumLODChangesThisFrame++;
- updateMeshData();
+ dirtyMesh();
+ return TRUE;
}
}
- return;
+ return FALSE;
}
//-----------------------------------------------------------------------------
@@ -5428,24 +5512,22 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
- LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_AVATAR);
+ LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR);
// Only a single face (one per avatar)
mDrawable->setState(LLDrawable::ACTIVE);
mDrawable->addFace(poolp, NULL);
+ mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
- poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
-
LLFace *facep;
// Add faces for the foot shadows
- facep = mDrawable->addFace(poolp, mShadowImagep);
+ facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
mShadow0Facep = facep;
- facep = mDrawable->addFace(poolp, mShadowImagep);
+ facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
mShadow1Facep = facep;
- gPipeline.markMaterialed(mDrawable);
dirtyMesh();
return mDrawable;
}
@@ -5456,6 +5538,7 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
{
return TRUE;
@@ -5471,30 +5554,9 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
llerrs << "LLVOAvatar::updateGeometry() called with NULL drawable" << llendl;
}
- // Update the shadow, tractor, and text label geometry.
-
- updateShadowFaces();
-
- if (!drawable->isVisible())
- {
- return TRUE;
- }
-
- LLFace* facep = drawable->getFace(0);
- if (!mDirtyMesh && !facep->getDirty())
- {
- return TRUE;
- }
-
- // U32 num_vertices = 0;
-
- updateMeshData();
-
- mDirtyMesh = FALSE;
return TRUE;
}
-
//-----------------------------------------------------------------------------
// updateShadowFaces()
//-----------------------------------------------------------------------------
@@ -5710,28 +5772,26 @@ void LLVOAvatar::removeChild(LLViewerObject *childp)
detachObject(childp);
}
-//-----------------------------------------------------------------------------
-// attachObject()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
{
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState());
- //clamp((S32)(viewer_object->getState() & AGENT_ATTACH_MASK) >> AGENT_ATTACH_OFFSET, 1, 0xff);
-
- //if (mIsSelf)
- //{
- // gSelectMgr->deselectObjectAndFamily(viewer_object);
- //}
LLViewerJointAttachment* attachment = mAttachmentPoints.getIfThere(attachmentID);
if (!attachment)
{
- llwarns << "Tried to attach object to invalid attachment point: " << attachmentID << llendl;
- return FALSE;
+ llwarns << "Object attachment point invalid: " << attachmentID << llendl;
}
-// LLQuaternion object_world_rot = viewer_object->getWorldRotation();
+ return attachment;
+}
+
+//-----------------------------------------------------------------------------
+// attachObject()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+{
+ LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
if (!attachment->addObject(viewer_object))
{
@@ -5744,10 +5804,6 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
gSelectMgr->updatePointAt();
}
-// LLQuaternion desired_rot = (object_world_rot * ~attachment->getWorldRotation());
-
- lldebugs << "Attaching object (" << attachmentID << ") item_id=" << attachment->getItemID() << " task_id=" << viewer_object->getID() << "to " << attachment->getName() << llendl;
-
if (mIsSelf)
{
updateAttachmentVisibility(gAgent.getCameraMode());
@@ -5780,6 +5836,23 @@ void LLVOAvatar::lazyAttach()
}
}
+void LLVOAvatar::resetHUDAttachments()
+{
+ for(LLViewerJointAttachment* attachment = mAttachmentPoints.getFirstData();
+ attachment;
+ attachment = mAttachmentPoints.getNextData())
+ {
+ if (attachment->getIsHUDAttachment())
+ {
+ LLViewerObject* obj = attachment->getObject();
+ if (obj && obj->mDrawable.notNull())
+ {
+ gPipeline.markMoved(obj->mDrawable);
+ }
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
// detachObject()
//-----------------------------------------------------------------------------
@@ -5790,7 +5863,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
attachment = mAttachmentPoints.getNextData())
{
// only one object per attachment point for now
- if (attachment->getObject(0) == viewer_object)
+ if (attachment->getObject() == viewer_object)
{
LLUUID item_id = attachment->getItemID();
attachment->removeObject(viewer_object);
@@ -5983,7 +6056,7 @@ LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id )
{
if( attachment_point->getItemID() == inv_item_id )
{
- return attachment_point->getObject(0);
+ return attachment_point->getObject();
}
}
return NULL;
@@ -6321,10 +6394,10 @@ const LLUUID& LLVOAvatar::getLocalTextureID( S32 index )
void LLVOAvatar::dumpTotalLocalTextureByteCount()
{
S32 total_gl_bytes = 0;
- for( LLVOAvatar* cur = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- cur;
- cur = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* cur = (LLVOAvatar*) *iter;
S32 gl_bytes = 0;
cur->getLocalTextureByteCount(&gl_bytes );
total_gl_bytes += gl_bytes;
@@ -7724,7 +7797,7 @@ BOOL LLVOAvatar::hasHUDAttachment()
attachment;
attachment = mAttachmentPoints.getNextData())
{
- if (attachment->getIsHUDAttachment() && attachment->getObject(0))
+ if (attachment->getIsHUDAttachment() && attachment->getObject())
{
return TRUE;
}
@@ -7739,9 +7812,9 @@ LLBBox LLVOAvatar::getHUDBBox()
attachment;
attachment = mAttachmentPoints.getNextData())
{
- if (attachment->getIsHUDAttachment() && attachment->getObject(0))
+ if (attachment->getIsHUDAttachment() && attachment->getObject())
{
- LLViewerObject* hud_object = attachment->getObject(0);
+ LLViewerObject* hud_object = attachment->getObject();
// initialize bounding box to contain identity orientation and center point for attached object
bbox.addPointLocal(hud_object->getPosition());
@@ -7759,52 +7832,6 @@ LLBBox LLVOAvatar::getHUDBBox()
void LLVOAvatar::rebuildHUD()
{
- if (!mIsSelf)
- {
- return;
- }
-
- for(LLViewerJointAttachment *attachment = mAttachmentPoints.getFirstData();
- attachment;
- attachment = mAttachmentPoints.getNextData())
- {
- if (attachment->getIsHUDAttachment() && attachment->getObject(0))
- {
- LLViewerObject* hud_object = attachment->getObject(0);
- LLDrawable* hud_drawable = hud_object->mDrawable;
-
- if (hud_drawable)
- {
- // this assumes that an AGP sync will happen because face has been backlisted,
- // so that pool has been rebuilt this frame and is scheduled for a sync
- for(S32 face_index = 0; face_index < hud_drawable->getNumFaces(); ++face_index)
- {
- LLFace* facep = hud_drawable->getFace(face_index);
- if (facep->isState(LLFace::BACKLIST))
- {
- facep->restore();
- }
- }
- }
- for (U32 child_num = 0; child_num < hud_object->mChildList.size(); ++child_num)
- {
- LLViewerObject* childp = hud_object->mChildList[child_num];
- LLDrawable* child_drawable = childp->mDrawable;
-
- if (child_drawable)
- {
- for(S32 face_index = 0; face_index < child_drawable->getNumFaces(); ++face_index)
- {
- LLFace* facep = child_drawable->getFace(face_index);
- if (facep->isState(LLFace::BACKLIST))
- {
- facep->restore();
- }
- }
- }
- }
- }
- }
}
//-----------------------------------------------------------------------------
@@ -8061,8 +8088,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
{
if (!aux_src->getData())
{
- llwarns << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl;
- src_vi->startImageDecode();
+ llerrs << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl;
return;
}
@@ -8370,10 +8396,10 @@ void LLVOAvatar::dumpArchetypeXML( void* )
S32 LLVOAvatar::getUnbakedPixelAreaRank()
{
S32 rank = 1;
- for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
if( inst == this )
{
return rank;
@@ -8392,16 +8418,15 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank()
// static
void LLVOAvatar::cullAvatarsByPixelArea()
{
- LLVOAvatar::sInstances.bubbleSortList();
-
-
+ std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater());
+
// Update the avatars that have changed status
S32 rank = 1;
- for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData();
- inst;
- inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() )
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
{
+ LLVOAvatar* inst = (LLVOAvatar*) *iter;
BOOL culled;
if( inst->isDead() )
{
@@ -8591,8 +8616,6 @@ void LLVOAvatar::dumpLocalTextures()
else
{
LLViewerImage* image = mLocalTexture[i];
- F32 data_progress = 0.0f;
- F32 decode_progress = image->getDecodeProgress(&data_progress);
llinfos << "LocTex " << names[i] << ": "
<< "Discard " << image->getDiscardLevel() << ", "
@@ -8602,10 +8625,7 @@ void LLVOAvatar::dumpLocalTextures()
// makes textures easier to steal
<< image->getID() << " "
#endif
- << "Data: " << (data_progress * 100) << "% "
- << "Decode: " << (decode_progress * 100) << "% "
- << "Priority: " << image->getDecodePriority() << " "
- << (image->needsDecode() ? "pending decode" : "not pending decode")
+ << "Priority: " << image->getDecodePriority()
<< llendl;
}
}
@@ -8707,7 +8727,7 @@ BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
}
else
{
- llerrs << "Invalid node " << node->getName() << llendl;
+ llwarns << "Invalid node " << node->getName() << llendl;
return FALSE;
}
@@ -8765,7 +8785,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones");
if (!node->getFastAttributeS32(num_bones_string, mNumBones))
{
- llerrs << "Couldn't find number of bones." << llendl;
+ llwarns << "Couldn't find number of bones." << llendl;
return FALSE;
}
@@ -8779,7 +8799,8 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
if (!info->parseXml(child))
{
delete info;
- llerrs << "Error parsing bone in skeleton file" << llendl;
+ llwarns << "Error parsing bone in skeleton file" << llendl;
+ return FALSE;
}
mBoneInfoList.push_back(info);
}
@@ -9210,7 +9231,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base)
attachment;
attachment = mAttachmentPoints.getNextData())
{
- LLViewerObject *attached_object = attachment->getObject(0);
+ LLViewerObject *attached_object = attachment->getObject();
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull() &&
attached_object->getPCode() == LL_PCODE_VOLUME)
{
@@ -9231,7 +9252,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base)
attachment;
attachment = mAttachmentPoints.getNextData())
{
- LLViewerObject *attached_object = attachment->getObject(0);
+ LLViewerObject *attached_object = attachment->getObject();
if (attached_object && !attached_object->isDead() && attached_object->getPCode() == LL_PCODE_VOLUME)
{
LLVOVolume* attached_volume = (LLVOVolume*)attached_object;
@@ -9443,3 +9464,58 @@ LLHost LLVOAvatar::getObjectHost() const
return LLHost::invalid;
}
}
+
+BOOL LLVOAvatar::updateLOD()
+{
+ BOOL res = updateJointLODs();
+
+ LLFace* facep = mDrawable->getFace(0);
+ if (facep->mVertexBuffer.isNull() ||
+ LLVertexBuffer::sEnableVBOs &&
+ ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) !=
+ (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))
+ {
+ mDirtyMesh = TRUE;
+ }
+
+ if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
+ { //LOD changed or new mesh created, allocate new vertex buffer if needed
+ updateMeshData();
+ mDirtyMesh = FALSE;
+ mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
+ }
+
+ if (facep->getPool()->getVertexShaderLevel() <= 0)
+ {
+ //generate animated mesh
+ mLowerBodyLOD.updateGeometry();
+ mUpperBodyLOD.updateGeometry();
+
+ if( isWearingWearableType( WT_SKIRT ) )
+ {
+ mSkirtLOD.updateGeometry();
+ }
+
+ if (!mIsSelf || gAgent.needsRenderHead())
+ {
+ mEyeLashLOD.updateGeometry();
+ mHeadLOD.updateGeometry();
+ mHairLOD.updateGeometry();
+ }
+ }
+
+ // Update the shadow, tractor, and text label geometry.
+ if (mDrawable->isState(LLDrawable::REBUILD_SHADOW))
+ {
+ updateShadowFaces();
+ mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
+ }
+
+ return res;
+}
+
+U32 LLVOAvatar::getPartitionType() const
+{ //avatars merely exist as drawables in the bridge partition
+ return LLPipeline::PARTITION_BRIDGE;
+}
+
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 871502a373..2660e7c90d 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -57,6 +57,13 @@ class LLDriverParamInfo;
class LLHUDText;
class LLHUDEffectSpiral;
+class LLVertexBufferAvatar : public LLVertexBuffer
+{
+public:
+ LLVertexBufferAvatar();
+ virtual void setupVertexBuffer(U32 data_mask) const;
+};
+
typedef enum e_mesh_id
{
MESH_ID_HAIR,
@@ -213,6 +220,25 @@ protected:
virtual ~LLVOAvatar();
public:
+
+ struct CompareScreenAreaGreater
+ {
+ bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
+ {
+ return lhs->getPixelArea() > rhs->getPixelArea();
+ }
+ };
+
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD) |
+ (1 << LLVertexBuffer::TYPE_WEIGHT) |
+ (1 << LLVertexBuffer::TYPE_CLOTHWEIGHT)
+ }
+ eVertexDataMask;
+
LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
/*virtual*/ void markDead();
@@ -228,20 +254,24 @@ public:
const EObjectUpdateType update_type,
LLDataPacker *dp);
virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+ virtual BOOL updateLOD();
void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; }
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
// Graphical stuff for objects - maybe broken out into render class later?
- U32 renderSkinned(EAvatarRenderPass pass);
+ U32 renderFootShadows();
U32 renderRigid();
-
+ U32 renderSkinned(EAvatarRenderPass pass);
+ U32 renderTransparent();
void renderCollisionVolumes();
/*virtual*/ void updateTextures(LLAgent &agent);
// If setting a baked texture, need to request it from a non-local sim.
/*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid);
-
+
+ virtual U32 getPartitionType() const;
+
void updateVisibility(BOOL force_invisible);
void updateAttachmentVisibility(U32 camera_mode);
void clampAttachmentPositions();
@@ -259,11 +289,14 @@ public:
void updateShadowFaces();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
- void updateJointLODs();
+ BOOL updateJointLODs();
void writeCAL3D(std::string& path, std::string& file_base);
virtual void updateRegion(LLViewerRegion *regionp);
+
+
+ void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax);
//--------------------------------------------------------------------
// texture entry assignment
@@ -323,7 +356,7 @@ public:
virtual BOOL allocateCharacterJoints( U32 num );
virtual LLJoint *getCharacterJoint( U32 num );
virtual void requestStopMotion( LLMotion* motion );
- virtual F32 getPixelArea();
+ virtual F32 getPixelArea() const;
virtual LLPolyMesh* getHeadMesh();
virtual LLPolyMesh* getUpperBodyMesh();
virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position);
@@ -343,7 +376,7 @@ public:
// Other public functions
//--------------------------------------------------------------------
BOOL allocateCollisionVolumes( U32 num );
-
+ void resetHUDAttachments();
static void getAnimLabels( LLDynamicArray<const char*>* labels );
static void getAnimNames( LLDynamicArray<const char*>* names );
@@ -420,6 +453,7 @@ public:
virtual void addChild(LLViewerObject *childp);
virtual void removeChild(LLViewerObject *childp);
+ LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
BOOL attachObject(LLViewerObject *viewer_object);
BOOL detachObject(LLViewerObject *viewer_object);
void lazyAttach();
@@ -817,7 +851,6 @@ protected:
F32 mRenderPriority;
F32 mAdjustedPixelArea;
- S32 mNumAGPVertices;
LLWString mNameString;
LLString mTitle;
@@ -858,6 +891,8 @@ protected:
U32 mLowerMaskTexName;
BOOL mCulled;
+ F32 mMinPixelArea; // debug
+ F32 mMaxPixelArea; // debug
//--------------------------------------------------------------------
// Global Colors
@@ -884,6 +919,7 @@ protected:
void requestLayerSetUpdate(LLVOAvatar::ELocTexIndex i);
void addLocalTextureStats(LLVOAvatar::ELocTexIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked);
+ void addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level);
static void onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
static void onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
void useBakedTexture(const LLUUID& id);
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
index b4924a45f1..1e5caa17d4 100644
--- a/indra/newview/llvoclouds.cpp
+++ b/indra/newview/llvoclouds.cpp
@@ -10,6 +10,8 @@
#include "llvoclouds.h"
+#include "lldrawpoolalpha.h"
+
#include "llviewercontrol.h"
#include "llagent.h" // to get camera position
@@ -27,7 +29,7 @@
#include "viewer.h"
LLVOClouds::LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, LL_VO_CLOUDS, regionp)
+: LLAlphaObject(id, LL_VO_CLOUDS, regionp)
{
mCloudGroupp = NULL;
mbCanSelect = FALSE;
@@ -80,77 +82,132 @@ LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline)
mDrawable->setLit(FALSE);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
- LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_CLOUDS);
-
- mDrawable->setNumFaces(1, pool, getTEImage(0));
-
return mDrawable;
}
BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
return TRUE;
- LLVector3 at;
- LLVector3 up;
- LLVector3 right;
- LLVector3 normal(0.f,0.f,-1.f);
- LLVector3 position_agent;
- //LLVector3 v[4];
LLFace *facep;
- const LLVector3 region_pos_agent = mRegionp->getOriginAgent();
- const LLVector3 camera_agent = gAgent.getCameraPositionAgent();
- LLVector3 center_offset = getPositionRegion();
- LLVector2 uvs[4];
-
- uvs[0].setVec(0.f, 1.f);
- uvs[1].setVec(0.f, 0.f);
- uvs[2].setVec(1.f, 1.f);
- uvs[3].setVec(1.f, 0.f);
-
- LLVector3 vtx[4];
-
+
S32 num_faces = mCloudGroupp->getNumPuffs();
- drawable->setNumFacesFast(num_faces, gPipeline.getPool(LLDrawPool::POOL_CLOUDS), getTEImage(0));
+ if (num_faces > drawable->getNumFaces())
+ {
+ drawable->setNumFacesFast(num_faces, NULL, getTEImage(0));
+ }
+
+ mDepth = (getPositionAgent()-gCamera->getOrigin())*gCamera->getAtAxis();
S32 face_indx = 0;
for ( ; face_indx < num_faces; face_indx++)
{
facep = drawable->getFace(face_indx);
-
- LLStrider<LLVector3> verticesp, normalsp;
- LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
- S32 index_offset;
-
- facep->setPrimType(LLTriangles);
- facep->setSize(4, 6);
- index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == index_offset)
+ if (isParticle())
{
- return TRUE;
+ facep->setSize(1,1);
}
-
+ else
+ {
+ facep->setSize(4, 6);
+ }
+ facep->setTEOffset(face_indx);
+ facep->setTexture(getTEImage(0));
const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx);
const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal());
- facep->mCenterAgent = puff_pos_agent;
+ facep->mCenterLocal = puff_pos_agent;
+ }
+ for ( ; face_indx < drawable->getNumFaces(); face_indx++)
+ {
+ facep = drawable->getFace(face_indx);
+ facep->setTEOffset(face_indx);
+ facep->setSize(0,0);
+ }
+
+ drawable->movePartition();
+
+ return TRUE;
+}
+
+BOOL LLVOClouds::isParticle()
+{
+ return FALSE; // gGLManager.mHasPointParameters;
+}
+
+F32 LLVOClouds::getPartSize(S32 idx)
+{
+ return (CLOUD_PUFF_HEIGHT+CLOUD_PUFF_WIDTH)*0.5f;
+}
+
+void LLVOClouds::getGeometry(S32 te,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp)
+{
- LLVector3 from_camera_vec = gCamera->getAtAxis();//puff_pos_agent - camera_agent;
- at = from_camera_vec;
+ if (te >= mCloudGroupp->getNumPuffs())
+ {
+ return;
+ }
+
+ LLDrawable* drawable = mDrawable;
+ LLFace *facep = drawable->getFace(te);
+
+ if (!facep->hasGeometry())
+ {
+ return;
+ }
+
+ LLVector3 normal(0.f,0.f,-1.f);
+
+ const LLCloudPuff &puff = mCloudGroupp->getPuff(te);
+ S32 index_offset = facep->getGeomIndex();
+ LLColor4U color(255, 255, 255, (U8) (puff.getAlpha()*255));
+ facep->setFaceColor(LLColor4(color));
+
+
+ if (isParticle())
+ {
+ *verticesp++ = facep->mCenterLocal;
+ *texcoordsp++ = LLVector2(0.5f, 0.5f);
+ *colorsp++ = color;
+ *normalsp++ = normal;
+ *indicesp++ = facep->getGeomIndex();
+ }
+ else
+ {
+ LLVector3 up;
+ LLVector3 right;
+ LLVector3 at;
+
+ const LLVector3& puff_pos_agent = facep->mCenterLocal;
+ LLVector2 uvs[4];
+
+ uvs[0].setVec(0.f, 1.f);
+ uvs[1].setVec(0.f, 0.f);
+ uvs[2].setVec(1.f, 1.f);
+ uvs[3].setVec(1.f, 0.f);
+
+ LLVector3 vtx[4];
+
+ at = gCamera->getAtAxis();
right = at % LLVector3(0.f, 0.f, 1.f);
right.normVec();
up = right % at;
up.normVec();
right *= 0.5f*CLOUD_PUFF_WIDTH;
up *= 0.5f*CLOUD_PUFF_HEIGHT;;
-
- facep->mCenterAgent = puff_pos_agent;
-
- LLColor4 color(1.f, 1.f, 1.f, puff.getAlpha());
- facep->setFaceColor(color);
+ *colorsp++ = color;
+ *colorsp++ = color;
+ *colorsp++ = color;
+ *colorsp++ = color;
+
vtx[0] = puff_pos_agent - right + up;
vtx[1] = puff_pos_agent - right - up;
vtx[2] = puff_pos_agent + right + up;
@@ -161,10 +218,10 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
*verticesp++ = vtx[2];
*verticesp++ = vtx[3];
- *texCoordsp++ = uvs[0];
- *texCoordsp++ = uvs[1];
- *texCoordsp++ = uvs[2];
- *texCoordsp++ = uvs[3];
+ *texcoordsp++ = uvs[0];
+ *texcoordsp++ = uvs[1];
+ *texcoordsp++ = uvs[2];
+ *texcoordsp++ = uvs[3];
*normalsp++ = normal;
*normalsp++ = normal;
@@ -179,10 +236,28 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
*indicesp++ = index_offset + 3;
*indicesp++ = index_offset + 2;
}
- for ( ; face_indx < drawable->getNumFaces(); face_indx++)
+}
+
+U32 LLVOClouds::getPartitionType() const
+{
+ return LLPipeline::PARTITION_CLOUD;
+}
+
+// virtual
+void LLVOClouds::updateDrawable(BOOL force_damped)
+{
+ // Force an immediate rebuild on any update
+ if (mDrawable.notNull())
{
- drawable->getFace(face_indx)->setSize(0,0);
+ mDrawable->updateXform(TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
}
+ clearChanged(SHIFTED);
+}
- return TRUE;
+LLCloudPartition::LLCloudPartition()
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_CLOUDS;
+ mPartitionType = LLPipeline::PARTITION_CLOUD;
}
+
diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h
index 0debe20730..180e4703b9 100644
--- a/indra/newview/llvoclouds.h
+++ b/indra/newview/llvoclouds.h
@@ -19,7 +19,7 @@ class LLViewerCloudGroup;
class LLCloudGroup;
-class LLVOClouds : public LLViewerObject
+class LLVOClouds : public LLAlphaObject
{
public:
LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp );
@@ -28,16 +28,29 @@ public:
// Initialize data that's only inited once per class.
static void initClass();
+ void updateDrawable(BOOL force_damped);
+
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ /*virtual*/ void getGeometry(S32 te,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp);
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
+ BOOL isParticle();
+ F32 getPartSize(S32 idx);
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
-
+
+ void updateFaceSize(S32 idx) { }
BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+ virtual U32 getPartitionType() const;
+
void setCloudGroup(LLCloudGroup *cgp) { mCloudGroupp = cgp; }
protected:
LLCloudGroup *mCloudGroupp;
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index b9d39272ac..418a810f6a 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -49,7 +49,7 @@ S32 LLVOGrass::sMaxGrassSpecies = 0;
LLVOGrass::LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, pcode, regionp)
+: LLAlphaObject(id, pcode, regionp)
{
mPatch = NULL;
mLastPatchUpdateTime = 0;
@@ -299,38 +299,45 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent)
{
// This should be the camera's center, as soon as we move to all region-local.
LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
- F32 range = relative_position.magVec(); // ugh, square root
+ F32 range = relative_position.magVec();
F32 max_scale = getMaxScale();
mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
// Compute pixels per meter at the given range
- F32 pixels_per_meter = gCamera->getViewHeightInPixels() /
- (tan(gCamera->getView()) * range);
+ F32 pixels_per_meter = gCamera->getViewHeightInPixels() / (tan(gCamera->getView()) * range);
- // Assume grass texture is a 1 meter by 1 meter sprite at the grass object's center
- mPixelArea = (pixels_per_meter) * (pixels_per_meter);
+ // Assume grass texture is a 5 meter by 5 meter sprite at the grass object's center
+ mPixelArea = (pixels_per_meter) * (pixels_per_meter) * 25.f;
}
// BUG could speed this up by caching the relative_position and range calculations
void LLVOGrass::updateTextures(LLAgent &agent)
{
- // dot_product = A B cos T
- // BUT at_axis is unit, so dot_product = B cos T
- LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
- F32 dot_product = relative_position * agent.getFrameAgent().getAtAxis();
- F32 cos_angle = dot_product / relative_position.magVec();
+ F32 texel_area_ratio = 1.f;
+ F32 cos_angle = 1.f;
if (getTEImage(0))
{
- getTEImage(0)->addTextureStats(mPixelArea*20.f, 1.f, cos_angle);
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ {
+ setDebugText(llformat("%4.0f", fsqrtf(mPixelArea)));
+ }
+ getTEImage(0)->addTextureStats(mPixelArea, texel_area_ratio, cos_angle);
}
}
BOOL LLVOGrass::updateLOD()
{
+ if (mDrawable->getNumFaces() <= 0)
+ {
+ return FALSE;
+ }
+
+ LLFace* face = mDrawable->getFace(0);
+
F32 tan_angle = 0.f;
S32 num_blades = 0;
@@ -344,6 +351,7 @@ BOOL LLVOGrass::updateLOD()
mNumBlades <<= 1;
}
+ face->setSize(mNumBlades*8, mNumBlades*12);
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
}
else if (num_blades <= (mNumBlades >> 1))
@@ -353,6 +361,7 @@ BOOL LLVOGrass::updateLOD()
mNumBlades >>=1;
}
+ face->setSize(mNumBlades*8, mNumBlades*12);
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
return TRUE;
}
@@ -363,53 +372,20 @@ BOOL LLVOGrass::updateLOD()
LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline)
{
pipeline->allocDrawable(this);
-// mDrawable->setLit(FALSE);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GRASS);
-
- LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
-
- mDrawable->setNumFaces(1, pool, getTEImage(0));
-
+
return mDrawable;
}
BOOL LLVOGrass::updateGeometry(LLDrawable *drawable)
{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_GRASS);
plantBlades();
return TRUE;
}
void LLVOGrass::plantBlades()
{
- mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
- mLastPatchUpdateTime = mPatch->getLastUpdateTime();
-
- LLVector3 position;
- // Create random blades of grass with gaussian distribution
- F32 x,y,xf,yf,dzx,dzy;
-
- LLVector3 normal(0,0,1);
- LLColor4U color(0,0,0,1);
-
- LLFace *face = mDrawable->getFace(0);
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoordsp;
- LLStrider<LLColor4U> colorsp;
-
- U32 *indicesp;
-
- face->setPool(face->getPool(), getTEImage(0));
- face->setState(LLFace::GLOBAL);
- face->setSize(mNumBlades * 4, mNumBlades * 12);
- face->setPrimType(LLTriangles);
- S32 index_offset = face->getGeometryColors(verticesp,normalsp,texCoordsp,colorsp,indicesp);
- if (-1 == index_offset)
- {
- return;
- }
-
// It is possible that the species of a grass is not defined
// This is bad, but not the end of the world.
if (!sSpeciesTable.count(mSpecies))
@@ -418,9 +394,49 @@ void LLVOGrass::plantBlades()
return;
}
+ if (mDrawable->getNumFaces() < 1)
+ {
+ mDrawable->setNumFaces(1, NULL, getTEImage(0));
+ }
+
+ LLFace *face = mDrawable->getFace(0);
+
+ face->setTexture(getTEImage(0));
+ face->setState(LLFace::GLOBAL);
+ face->setSize(mNumBlades * 8, mNumBlades * 12);
+ face->mVertexBuffer = NULL;
+ face->setTEOffset(0);
+ face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
+
+ mDepth = (face->mCenterLocal - gCamera->getOrigin())*gCamera->getAtAxis();
+ mDrawable->setPosition(face->mCenterLocal);
+ mDrawable->movePartition();
+ LLPipeline::sCompiles++;
+}
+
+void LLVOGrass::getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp)
+{
+ mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
+ mLastPatchUpdateTime = mPatch->getLastUpdateTime();
+
+ LLVector3 position;
+ // Create random blades of grass with gaussian distribution
+ F32 x,y,xf,yf,dzx,dzy;
+
+ LLColor4U color(255,255,255,255);
+
+ LLFace *face = mDrawable->getFace(idx);
+
F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
+ U32 index_offset = face->getGeomIndex();
+
for (S32 i = 0; i < mNumBlades; i++)
{
x = exp_x[i] * mScale.mV[VX];
@@ -430,70 +446,113 @@ void LLVOGrass::plantBlades()
dzx = dz_x [i];
dzy = dz_y [i];
+ LLVector3 v1,v2,v3;
F32 blade_height= GRASS_BLADE_HEIGHT * height * w_mod[i];
- *texCoordsp++ = LLVector2(0, 0);
- *texCoordsp++ = LLVector2(0, 0.98f);
- *texCoordsp++ = LLVector2(1, 0);
- *texCoordsp++ = LLVector2(1, 0.98f);
+ *texcoordsp++ = LLVector2(0, 0);
+ *texcoordsp++ = LLVector2(0, 0);
+ *texcoordsp++ = LLVector2(0, 0.98f);
+ *texcoordsp++ = LLVector2(0, 0.98f);
+ *texcoordsp++ = LLVector2(1, 0);
+ *texcoordsp++ = LLVector2(1, 0);
+ *texcoordsp++ = LLVector2(1, 0.98f);
+ *texcoordsp++ = LLVector2(1, 0.98f);
position.mV[0] = mPosition.mV[VX] + x + xf;
position.mV[1] = mPosition.mV[VY] + y + yf;
- position.mV[2] = 0.f;
position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- *verticesp++ = position + mRegionp->getOriginAgent();
+ *verticesp++ = v1 = position + mRegionp->getOriginAgent();
+ *verticesp++ = v1;
+
position.mV[0] += dzx;
position.mV[1] += dzy;
position.mV[2] += blade_height;
- *verticesp++ = position + mRegionp->getOriginAgent();
+ *verticesp++ = v2 = position + mRegionp->getOriginAgent();
+ *verticesp++ = v2;
position.mV[0] = mPosition.mV[VX] + x - xf;
position.mV[1] = mPosition.mV[VY] + y - xf;
- position.mV[2] = 0.f;
position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- *verticesp++ = position + mRegionp->getOriginAgent();
+ *verticesp++ = v3 = position + mRegionp->getOriginAgent();
+ *verticesp++ = v3;
+
+ LLVector3 normal1 = (v1-v2) % (v2-v3);
+ normal1.mV[VZ] = 0.75f;
+ normal1.normVec();
+ LLVector3 normal2 = -normal1;
+ normal2.mV[VZ] = -normal2.mV[VZ];
position.mV[0] += dzx;
position.mV[1] += dzy;
position.mV[2] += blade_height;
- *verticesp++ = position + mRegionp->getOriginAgent();
+ *verticesp++ = v1 = position + mRegionp->getOriginAgent();
+ *verticesp++ = v1;
+
+ *(normalsp++) = normal1;
+ *(normalsp++) = normal2;
+ *(normalsp++) = normal1;
+ *(normalsp++) = normal2;
- *(normalsp++) = normal;
- *(normalsp++) = normal;
- *(normalsp++) = normal;
- *(normalsp++) = normal;
+ *(normalsp++) = normal1;
+ *(normalsp++) = normal2;
+ *(normalsp++) = normal1;
+ *(normalsp++) = normal2;
*(colorsp++) = color;
*(colorsp++) = color;
*(colorsp++) = color;
*(colorsp++) = color;
+ *(colorsp++) = color;
+ *(colorsp++) = color;
+ *(colorsp++) = color;
+ *(colorsp++) = color;
*indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 1;
*indicesp++ = index_offset + 2;
+ *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 3;
*indicesp++ = index_offset + 2;
+ *indicesp++ = index_offset + 6;
+ *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 2;
*indicesp++ = index_offset + 1;
+ *indicesp++ = index_offset + 5;
+ *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 2;
*indicesp++ = index_offset + 3;
- index_offset += 4;
+ *indicesp++ = index_offset + 5;
+ *indicesp++ = index_offset + 7;
+ index_offset += 8;
}
LLPipeline::sCompiles++;
-
- face->mCenterLocal = mPosition;
-
}
+U32 LLVOGrass::getPartitionType() const
+{
+ return LLPipeline::PARTITION_GRASS;
+}
+LLGrassPartition::LLGrassPartition()
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_GRASS;
+ mPartitionType = LLPipeline::PARTITION_GRASS;
+ mLODPeriod = 16;
+ mDepthMask = TRUE;
+ mSlopRatio = 0.1f;
+ mRenderPass = LLRenderPass::PASS_GRASS;
+ mBufferUsage = GL_DYNAMIC_DRAW_ARB;
+}
-
-
+// virtual
+void LLVOGrass::updateDrawable(BOOL force_damped)
+{
+ // Force an immediate rebuild on any update
+ if (mDrawable.notNull())
+ {
+ mDrawable->updateXform(TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ clearChanged(SHIFTED);
+}
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index ef3d30c5ea..38aef64cd8 100644
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -17,7 +17,7 @@ class LLSurfacePatch;
class LLViewerImage;
-class LLVOGrass : public LLViewerObject
+class LLVOGrass : public LLAlphaObject
{
public:
LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
@@ -27,6 +27,8 @@ public:
static void initClass();
static void cleanupClass();
+ virtual U32 getPartitionType() const;
+
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num,
@@ -34,11 +36,19 @@ public:
LLDataPacker *dp);
static void import(FILE *file, LLMessageSystem *mesgsys, const LLVector3 &pos);
/*virtual*/ void exportFile(FILE *file, const LLVector3 &position);
-
+
+ void updateDrawable(BOOL force_damped);
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
-
+ /*virtual*/ void getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp);
+
+ void updateFaceSize(S32 idx) { }
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ BOOL updateLOD();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index dd3ef61173..ef81943718 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -9,6 +9,7 @@
#include "llviewerprecompiledheaders.h"
#include "llvoground.h"
+#include "lldrawpoolground.h"
#include "llviewercontrol.h"
@@ -21,7 +22,7 @@
#include "pipeline.h"
LLVOGround::LLVOGround(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, pcode, regionp)
+: LLStaticViewerObject(id, pcode, regionp)
{
mbCanSelect = FALSE;
}
@@ -38,10 +39,10 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
return TRUE;
}
- if (mDrawable)
+ /*if (mDrawable)
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- }
+ }*/
return TRUE;
}
@@ -56,7 +57,8 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
- LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_GROUND);
+ mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GROUND);
+ LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND);
mDrawable->addFace(poolp, NULL);
@@ -68,15 +70,25 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
LLStrider<LLVector3> verticesp;
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
LLFace *face;
+ LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND);
+
if (drawable->getNumFaces() < 1)
- drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_GROUND), NULL);
+ drawable->addFace(poolp, NULL);
face = drawable->getFace(0);
- face->setPrimType(LLTriangles);
- face->setSize(6, 12);
+
+ if (face->mVertexBuffer.isNull())
+ {
+ face->setSize(5, 12);
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+ }
+
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
{
@@ -98,68 +110,40 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
left_dir.normVec();
// Our center top point
- LLVector3 center_top, center_bottom;
-
LLColor4 ground_color = gSky.getFogColor();
ground_color.mV[3] = 1.f;
face->setFaceColor(ground_color);
- if (gCamera->getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight())
- {
- // Underwater
- //center_top = gCamera->getOrigin() + at_dir*gCamera->getFar();
- center_top = gCamera->getOrigin() - LLVector3(0, 0, 5);
- center_bottom = gCamera->getOrigin() + at_dir*gCamera->getFar();;
- //center_top.mV[VZ] = gAgent.getRegion()->getWaterHeight() + 0.5f;
- center_bottom.mV[VZ] = -100.f;
- }
- else
- {
- // Above water
- center_top = gCamera->getOrigin() - LLVector3(0, 0, 30);
- if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) > 0))
- {
- center_top.mV[VZ] = gAgent.getRegion()->getWaterHeight();
- }
- //center_top = gCamera->getOrigin() + at_dir*9000.f;
- center_bottom = gCamera->getOrigin() - at_dir*gCamera->getFar();
- //center_top.mV[VZ] = 0.f;
- //center_bottom.mV[VZ] = gAgent.getRegion()->getWaterHeight();
- }
-
- *(verticesp++) = center_top + LLVector3(6000, 6000, 0);
- *(verticesp++) = center_top + LLVector3(-6000, 6000, 0);
- *(verticesp++) = center_top + LLVector3(-6000, -6000, 0);
-
- *(verticesp++) = center_top + LLVector3(-6000, -6000, 0);
- *(verticesp++) = center_top + LLVector3(6000, -6000, 0);
- *(verticesp++) = center_top + LLVector3(6000, 6000, 0);
+ *(verticesp++) = LLVector3(64, 64, 0);
+ *(verticesp++) = LLVector3(-64, 64, 0);
+ *(verticesp++) = LLVector3(-64, -64, 0);
+ *(verticesp++) = LLVector3(64, -64, 0);
+ *(verticesp++) = LLVector3(0, 0, -1024);
// Triangles for each side
*indicesp++ = index_offset + 0;
*indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 3;
+ *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 3;
+ *indicesp++ = index_offset + 1;
*indicesp++ = index_offset + 2;
+ *indicesp++ = index_offset + 4;
*indicesp++ = index_offset + 2;
*indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 5;
+ *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 5;
+ *indicesp++ = index_offset + 3;
+ *indicesp++ = index_offset + 0;
*indicesp++ = index_offset + 4;
*(texCoordsp++) = LLVector2(0.f, 0.f);
*(texCoordsp++) = LLVector2(1.f, 0.f);
- *(texCoordsp++) = LLVector2(0.f, 1.f);
*(texCoordsp++) = LLVector2(1.f, 1.f);
- *(texCoordsp++) = LLVector2(0.f, 2.f);
- *(texCoordsp++) = LLVector2(1.f, 2.f);
-
+ *(texCoordsp++) = LLVector2(0.f, 1.f);
+ *(texCoordsp++) = LLVector2(0.5f, 0.5f);
+
LLPipeline::sCompiles++;
return TRUE;
}
diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h
index 228d872eaf..587b0064de 100644
--- a/indra/newview/llvoground.h
+++ b/indra/newview/llvoground.h
@@ -15,7 +15,7 @@
#include "llviewerimage.h"
#include "llviewerobject.h"
-class LLVOGround : public LLViewerObject
+class LLVOGround : public LLStaticViewerObject
{
protected:
public:
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 38db15c0c7..b641bf6f27 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -10,6 +10,8 @@
#include "llvopartgroup.h"
+#include "lldrawpoolalpha.h"
+
#include "llfasttimer.h"
#include "message.h"
#include "v2math.h"
@@ -28,7 +30,7 @@ const F32 MAX_PART_LIFETIME = 120.f;
extern U64 gFrameTime;
LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
- : LLViewerObject(id, pcode, regionp),
+ : LLAlphaObject(id, pcode, regionp),
mViewerPartGroupp(NULL)
{
setNumTEs(1);
@@ -42,37 +44,37 @@ LLVOPartGroup::~LLVOPartGroup()
{
}
+
BOOL LLVOPartGroup::isActive() const
{
return TRUE;
}
+F32 LLVOPartGroup::getBinRadius()
+{
+ return mScale.mV[0]*2.f;
+}
+
+void LLVOPartGroup::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
+{
+ LLVector3 pos_agent = getPositionAgent();
+ mExtents[0] = pos_agent - mScale;
+ mExtents[1] = pos_agent + mScale;
+ newMin = mExtents[0];
+ newMax = mExtents[1];
+ mDrawable->setPositionGroup(pos_agent);
+}
+
BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- }
-
- // Particle groups don't need any of default idleUpdate velocity interpolation stuff.
- //LLViewerObject::idleUpdate(agent, world, time);
return TRUE;
}
-
void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
{
// mPixelArea is calculated during render
-
- LLVector3 viewer_pos_agent = agent.getCameraPositionAgent();
- LLVector3 pos_agent = getRenderPosition();
-
- F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX];
- F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY];
- F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ];
-
F32 mid_scale = getMidScale();
- F32 range = sqrt(dx*dx + dy*dy + dz*dz);
+ F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec();
if (range < 0.001f || isHUDAttachment()) // range == zero
{
@@ -86,7 +88,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
void LLVOPartGroup::updateTextures(LLAgent &agent)
{
- // Texture stats for particles will need to be updated in a different way...
+ // Texture stats for particles need to be updated in a different way...
}
@@ -95,37 +97,45 @@ LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
-
- LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
- mDrawable->setNumFaces(mViewerPartGroupp->getCount(), pool, getTEImage(0));
return mDrawable;
}
const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw
-BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
+F32 LLVOPartGroup::getPartSize(S32 idx)
{
- LLFastTimer t(LLFastTimer::FTM_UPDATE_PARTICLES);
-
- LLVector3 at;
- LLVector3 up;
- LLVector3 right;
- LLVector3 position_agent;
- LLVector3 camera_agent = gAgent.getCameraPositionAgent();
- LLVector2 uvs[4];
+ if (idx < (S32) mViewerPartGroupp->mParticles.size())
+ {
+ return mViewerPartGroupp->mParticles[idx]->mScale.mV[0];
+ }
+
+ return 0.f;
+}
- uvs[0].setVec(0.f, 1.f);
- uvs[1].setVec(0.f, 0.f);
- uvs[2].setVec(1.f, 1.f);
- uvs[3].setVec(1.f, 0.f);
+BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
+{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_PARTICLES);
- LLDrawPool *drawpool = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
+ LLVector3 at;
+ LLVector3 position_agent;
+ LLVector3 camera_agent = gCamera->getOrigin();
+
S32 num_parts = mViewerPartGroupp->getCount();
LLFace *facep;
-
+ LLSpatialGroup* group = drawable->getSpatialGroup();
+ if (!group && num_parts)
+ {
+ drawable->movePartition();
+ group = drawable->getSpatialGroup();
+ }
+
if (!num_parts)
{
- drawable->setNumFaces(0, drawpool, getTEImage(0));
+ if (drawable->getNumFaces())
+ {
+ group->dirtyGeom();
+ }
+ drawable->setNumFaces(0, NULL, getTEImage(0));
LLPipeline::sCompiles++;
return TRUE;
}
@@ -135,30 +145,30 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
return TRUE;
}
-// drawable->setNumFaces(num_parts, drawpool, getTEImage(0));
- drawable->setNumFacesFast(num_parts, drawpool, getTEImage(0));
-
- LLVector3 normal(-gCamera->getXAxis()); // make point agent face camera
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoordsp;
- U32 *indicesp = 0;
+ if (num_parts > drawable->getNumFaces())
+ {
+ drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0));
+ }
- S32 vert_offset;
F32 tot_area = 0;
+ BOOL is_particle = isParticle();
+
F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE;
-
+ F32 pixel_meter_ratio = gCamera->getPixelMeterRatio();
+ pixel_meter_ratio *= pixel_meter_ratio;
+
S32 count=0;
- for (S32 i = 0; i < num_parts; i++)
+ S32 i;
+ F32 max_width = 0.f;
+ mDepth = 0.f;
+
+ for (i = 0; i < num_parts; i++)
{
- const LLViewerPart &part = mViewerPartGroupp->mParticles[i];
+ const LLViewerPart &part = *((LLViewerPart*) mViewerPartGroupp->mParticles[i]);
LLVector3 part_pos_agent(part.mPosAgent);
at = part_pos_agent - camera_agent;
- //F32 invcamdist = 1.0f / at.magVec();
- //area += (part.mScale.mV[0]*invcamdist)*(part.mScale.mV[1]*invcamdist);
F32 camera_dist_squared = at.magVecSquared();
F32 inv_camera_dist_squared;
if (camera_dist_squared > 1.f)
@@ -167,29 +177,124 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
inv_camera_dist_squared = 1.f;
F32 area = part.mScale.mV[0] * part.mScale.mV[1] * inv_camera_dist_squared;
tot_area += area;
- if (tot_area > max_area)
+
+ if (!is_particle && tot_area > max_area)
{
break;
}
-
+
count++;
facep = drawable->getFace(i);
+ facep->setTEOffset(i);
const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera
const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera
- if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
+
+ if (!is_particle)
{
- facep->setSize(0, 0);
- continue;
+ if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
+ {
+ facep->setSize(0, 0);
+ continue;
+ }
+
+ facep->setSize(4, 6);
+ }
+ else
+ {
+ facep->setSize(1,1);
+ }
+
+ facep->setViewerObject(this);
+
+ if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
+ {
+ facep->setState(LLFace::FULLBRIGHT);
}
- facep->setSize(4, 6);
- facep->mCenterAgent = part_pos_agent;
- vert_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == vert_offset)
+ else
{
- return TRUE;
+ facep->clearState(LLFace::FULLBRIGHT);
}
+
+ facep->mCenterLocal = part.mPosAgent;
+ facep->setFaceColor(part.mColor);
+ facep->setTexture(part.mImagep);
+ if (i == 0)
+ {
+ mExtents[0] = mExtents[1] = part.mPosAgent;
+ }
+ else
+ {
+ update_min_max(mExtents[0], mExtents[1], part.mPosAgent);
+ }
+
+ max_width = llmax(max_width, part.mScale.mV[0]);
+ max_width = llmax(max_width, part.mScale.mV[1]);
+
+ mPixelArea = tot_area * pixel_meter_ratio;
+ const F32 area_scale = 10.f; // scale area to increase priority a bit
+ facep->setVirtualSize(mPixelArea*area_scale);
+ }
+ for (i = count; i < drawable->getNumFaces(); i++)
+ {
+ LLFace* facep = drawable->getFace(i);
+ facep->setTEOffset(i);
+ facep->setSize(0,0);
+ }
+
+ LLVector3 y = gCamera->mYAxis;
+ LLVector3 z = gCamera->mZAxis;
+
+ LLVector3 pad;
+ for (i = 0; i < 3; i++)
+ {
+ pad.mV[i] = llmax(max_width, max_width * (fabsf(y.mV[i]) + fabsf(z.mV[i])));
+ }
+
+ mExtents[0] -= pad;
+ mExtents[1] += pad;
+
+ mDrawable->movePartition();
+ LLPipeline::sCompiles++;
+ return TRUE;
+}
+
+void LLVOPartGroup::getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp)
+{
+ if (idx >= (S32) mViewerPartGroupp->mParticles.size())
+ {
+ return;
+ }
+
+ const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
+
+ U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex();
+
+ if (isParticle())
+ {
+ LLVector3 part_pos_agent(part.mPosAgent);
+
+ const LLVector3& normal = -gCamera->getXAxis();
+
+ *verticesp++ = part_pos_agent;
+ *normalsp++ = normal;
+ *colorsp++ = part.mColor;
+ *texcoordsp++ = LLVector2(0.5f, 0.5f);
+ *indicesp++ = vert_offset;
+ }
+ else
+ {
+ LLVector3 part_pos_agent(part.mPosAgent);
+ LLVector3 camera_agent = gAgent.getCameraPositionAgent();
+ LLVector3 at = part_pos_agent - camera_agent;
+ LLVector3 up, right;
+
right = at % LLVector3(0.f, 0.f, 1.f);
right.normVec();
up = right % at;
@@ -217,31 +322,28 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
right *= 0.5f*part.mScale.mV[0];
up *= 0.5f*part.mScale.mV[1];
+ const LLVector3& normal = -gCamera->getXAxis();
+
*verticesp++ = part_pos_agent + up - right;
*verticesp++ = part_pos_agent - up - right;
*verticesp++ = part_pos_agent + up + right;
*verticesp++ = part_pos_agent - up + right;
- *texCoordsp++ = uvs[0];
- *texCoordsp++ = uvs[1];
- *texCoordsp++ = uvs[2];
- *texCoordsp++ = uvs[3];
+ *colorsp++ = part.mColor;
+ *colorsp++ = part.mColor;
+ *colorsp++ = part.mColor;
+ *colorsp++ = part.mColor;
+
+ *texcoordsp++ = LLVector2(0.f, 1.f);
+ *texcoordsp++ = LLVector2(0.f, 0.f);
+ *texcoordsp++ = LLVector2(1.f, 1.f);
+ *texcoordsp++ = LLVector2(1.f, 0.f);
*normalsp++ = normal;
*normalsp++ = normal;
*normalsp++ = normal;
*normalsp++ = normal;
- if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
- {
- facep->setState(LLFace::FULLBRIGHT);
- }
- else
- {
- facep->clearState(LLFace::FULLBRIGHT);
- }
- facep->setFaceColor(part.mColor);
-
*indicesp++ = vert_offset + 0;
*indicesp++ = vert_offset + 1;
*indicesp++ = vert_offset + 2;
@@ -250,17 +352,149 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
*indicesp++ = vert_offset + 3;
*indicesp++ = vert_offset + 2;
}
- for (S32 j = count; j < drawable->getNumFaces(); j++)
+}
+
+BOOL LLVOPartGroup::isParticle()
+{
+ return FALSE; //gGLManager.mHasPointParameters && mViewerPartGroupp->mUniformParticles;
+}
+
+U32 LLVOPartGroup::getPartitionType() const
+{
+ return LLPipeline::PARTITION_PARTICLE;
+}
+
+LLParticlePartition::LLParticlePartition()
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK)
+{
+ mRenderPass = LLRenderPass::PASS_ALPHA;
+ mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
+ mPartitionType = LLPipeline::PARTITION_PARTICLE;
+ mBufferUsage = GL_DYNAMIC_DRAW_ARB;
+ mSlopRatio = 0.f;
+ mLODPeriod = 1;
+}
+
+void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
+{
+ group->mBufferUsage = mBufferUsage;
+
+ mFaceList.clear();
+
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- drawable->getFace(j)->setSize(0,0);
+ LLDrawable* drawablep = *i;
+
+ if (drawablep->isDead())
+ {
+ continue;
+ }
+
+ LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj();
+ obj->mDepth = 0.f;
+
+ if (drawablep->isAnimating())
+ {
+ group->mBufferUsage = GL_STREAM_DRAW_ARB;
+ }
+
+ U32 count = 0;
+ for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
+ {
+ drawablep->updateFaceSize(j);
+
+ LLFace* facep = drawablep->getFace(j);
+ if (!facep->hasGeometry())
+ {
+ continue;
+ }
+
+ count++;
+ facep->mDistance = (facep->mCenterLocal - gCamera->getOrigin()) * gCamera->getAtAxis();
+ obj->mDepth += facep->mDistance;
+
+ mFaceList.push_back(facep);
+ vertex_count += facep->getGeomCount();
+ index_count += facep->getIndicesCount();
+ }
+
+ obj->mDepth /= count;
}
-
- mPixelArea = tot_area * gCamera->getPixelMeterRatio() * gCamera->getPixelMeterRatio();
- const F32 area_scale = 10.f; // scale area to increase priority a bit
- getTEImage(0)->addTextureStats(mPixelArea * area_scale);
+}
- LLPipeline::sCompiles++;
+void LLParticlePartition::getGeometry(LLSpatialGroup* group)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- return TRUE;
+ std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater());
+
+ U32 index_count = 0;
+ U32 vertex_count = 0;
+
+ group->clearDrawMap();
+
+ LLVertexBuffer* buffer = group->mVertexBuffer;
+
+ LLStrider<U32> indicesp;
+ LLStrider<LLVector3> verticesp;
+ LLStrider<LLVector3> normalsp;
+ LLStrider<LLVector2> texcoordsp;
+ LLStrider<LLColor4U> colorsp;
+
+ buffer->getVertexStrider(verticesp);
+ buffer->getNormalStrider(normalsp);
+ buffer->getColorStrider(colorsp);
+ buffer->getTexCoordStrider(texcoordsp);
+ buffer->getIndexStrider(indicesp);
+
+ std::vector<LLDrawInfo*>& draw_vec = group->mDrawMap[mRenderPass];
+
+ for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
+ {
+ LLFace* facep = *i;
+ LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
+ facep->setGeomIndex(vertex_count);
+ facep->setIndicesIndex(index_count);
+ facep->mVertexBuffer = buffer;
+ facep->setPoolType(LLDrawPool::POOL_ALPHA);
+ object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
+
+ vertex_count += facep->getGeomCount();
+ index_count += facep->getIndicesCount();
+
+ S32 idx = draw_vec.size()-1;
+
+ BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
+ F32 vsize = facep->getVirtualSize();
+
+ if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
+ draw_vec[idx]->mTexture == facep->getTexture() &&
+ draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
+ draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
+ draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 &&
+ draw_vec[idx]->mFullbright == fullbright)
+ {
+ draw_vec[idx]->mCount += facep->getIndicesCount();
+ draw_vec[idx]->mEnd += facep->getGeomCount();
+ draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
+ }
+ else
+ {
+ U32 start = facep->getGeomIndex();
+ U32 end = start + facep->getGeomCount()-1;
+ U32 offset = facep->getIndicesStart();
+ U32 count = facep->getIndicesCount();
+ LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright);
+ info->mVSize = vsize;
+ draw_vec.push_back(info);
+ }
+ }
+
+ mFaceList.clear();
+}
+
+F32 LLParticlePartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
+{
+ return 1024.f;
}
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 657d1824d0..4082700971 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -16,26 +16,50 @@
class LLViewerPartGroup;
-class LLVOPartGroup : public LLViewerObject
+class LLVOPartGroup : public LLAlphaObject
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD) |
+ (1 << LLVertexBuffer::TYPE_COLOR)
+ }
+ eVertexDataMask;
+
LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
~LLVOPartGroup();
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+ BOOL isParticle();
+ virtual F32 getBinRadius();
+ virtual void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax);
+ virtual U32 getPartitionType() const;
+
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ void getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp);
+ void updateFaceSize(S32 idx) { }
+ F32 getPartSize(S32 idx);
void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; }
+ LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; }
+
protected:
LLViewerPartGroup *mViewerPartGroupp;
-
+ LLVector3 mExtents[2];
LLColor4 mDebugColor;
};
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 2f580ba5f7..eb62f8ceb0 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -421,7 +421,7 @@ void LLSkyTex::initEmpty(const S32 tex)
}
}
- createTexture(tex);
+ createGLImage(tex);
}
@@ -448,10 +448,10 @@ void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt)
*pix = temp1.mAll;
}
}
- createTexture(sCurrent);
+ createGLImage(sCurrent);
}
-void LLSkyTex::createTexture(S32 which)
+void LLSkyTex::createGLImage(S32 which)
{
mImageGL[which]->createGLTexture(0, mImageRaw[which]);
mImageGL[which]->setClamp(TRUE, TRUE);
@@ -475,7 +475,7 @@ S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, pcode, regionp),
+: LLStaticViewerObject(id, pcode, regionp),
mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
mBrightnessScale(1.f),
mBrightnessScaleNew(0.f),
@@ -1035,11 +1035,9 @@ void LLVOSky::calcBrightnessScaleAndColors()
}
calculateColors(); // MSMSM Moved this down here per Milo Lindens suggestion, to fix orange flashing bug at sunset.
- generateScatterMap();
}
-
void LLVOSky::calculateColors()
{
const F32 h = -0.1f;
@@ -1049,14 +1047,13 @@ void LLVOSky::calculateColors()
F32 sun_factor = 1;
// Sun Diffuse
- if (calcHitsEarth(mCameraPosAgent, tosun) < 0)
- {
- mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(tosun.mV[2], h);
- }
- else
- {
- mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(0, h);
- }
+ F32 sun_height = tosun.mV[2];
+
+ if (sun_height <= 0.0)
+ sun_height = 0.0;
+
+ mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(sun_height, h);
+
mSunDiffuse = 1.0f * color_norm(mSunDiffuse);
// Sun Ambient
@@ -1169,8 +1166,6 @@ BOOL LLVOSky::updateSky()
return TRUE;
}
- setPositionAgent(gAgent.getCameraPositionAgent());
-
static S32 next_frame = 0;
const S32 total_no_tiles = 6 * NUM_TILES;
const S32 cycle_frame_no = total_no_tiles + 1;
@@ -1234,21 +1229,27 @@ BOOL LLVOSky::updateSky()
LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
raw2->copy(raw1);
- mSkyTex[side].createTexture(mSkyTex[side].getWhich(FALSE));
+ mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE));
}
next_frame = 0;
//llSkyTex::stepCurrent();
}
- std::vector<LLPointer<LLImageRaw> > images;
- for (S32 side = 0; side < 6; side++)
+ if (!gSavedSettings.getBOOL("RenderDynamicReflections"))
{
- images.push_back(mSkyTex[side].getImageRaw(FALSE));
+ std::vector<LLPointer<LLImageRaw> > images;
+ for (S32 side = 0; side < 6; side++)
+ {
+ images.push_back(mSkyTex[side].getImageRaw(FALSE));
+ }
+ mCubeMap->init(images);
}
- mCubeMap->init(images);
}
}
+ gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ gPipeline.markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+
mForceUpdate = FALSE;
}
else
@@ -1287,7 +1288,8 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
poolp->setSkyTex(mSkyTex);
poolp->setSun(&mSun);
poolp->setMoon(&mMoon);
-
+ mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
+
for (S32 i = 0; i < 6; ++i)
{
mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
@@ -1297,9 +1299,6 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
- //mDrawable->addFace(poolp, LLViewerImage::sDefaultImagep);
- gPipeline.markMaterialed(mDrawable);
-
return mDrawable;
}
@@ -1307,70 +1306,74 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
{
if (mFace[FACE_REFLECTION] == NULL)
{
- mFace[FACE_REFLECTION] = drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL);
+ LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
+ mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
}
mCameraPosAgent = drawable->getPositionAgent();
mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
-
LLVector3 v_agent[8];
for (S32 i = 0; i < 8; ++i)
{
F32 x_sgn = (i&1) ? 1.f : -1.f;
F32 y_sgn = (i&2) ? 1.f : -1.f;
F32 z_sgn = (i&4) ? 1.f : -1.f;
- v_agent[i] = mCameraPosAgent + HORIZON_DIST * LLVector3(x_sgn, y_sgn, z_sgn);
+ v_agent[i] = HORIZON_DIST*0.25f * LLVector3(x_sgn, y_sgn, z_sgn);
}
LLStrider<LLVector3> verticesp;
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
LLFace *face;
for (S32 side = 0; side < 6; ++side)
{
face = mFace[FACE_SIDE0 + side];
- face->setPrimType(LLTriangles);
- face->setSize(4, 6);
- index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == index_offset)
+
+ if (face->mVertexBuffer.isNull())
{
- return TRUE;
+ face->setSize(4, 6);
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
+
+ index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
+
+ S32 vtx = 0;
+ S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
+ S32 side_dir = side & 1; // even - 0, odd - 1
+ S32 i_bit = (curr_bit + 2) % 3;
+ S32 j_bit = (i_bit + 2) % 3;
+
+ LLVector3 axis;
+ axis.mV[curr_bit] = 1;
+ face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
+
+ vtx = side_dir << curr_bit;
+ *(verticesp++) = v_agent[vtx];
+ *(verticesp++) = v_agent[vtx | 1 << j_bit];
+ *(verticesp++) = v_agent[vtx | 1 << i_bit];
+ *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit];
+
+ *(texCoordsp++) = TEX00;
+ *(texCoordsp++) = TEX01;
+ *(texCoordsp++) = TEX10;
+ *(texCoordsp++) = TEX11;
+
+ // Triangles for each side
+ *indicesp++ = index_offset + 0;
+ *indicesp++ = index_offset + 1;
+ *indicesp++ = index_offset + 3;
+
+ *indicesp++ = index_offset + 0;
+ *indicesp++ = index_offset + 3;
+ *indicesp++ = index_offset + 2;
}
-
- S32 vtx = 0;
- S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
- S32 side_dir = side & 1; // even - 0, odd - 1
- S32 i_bit = (curr_bit + 2) % 3;
- S32 j_bit = (i_bit + 2) % 3;
-
- LLVector3 axis;
- axis.mV[curr_bit] = 1;
- face->mCenterAgent = mCameraPosAgent + (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
-
- vtx = side_dir << curr_bit;
- *(verticesp++) = v_agent[vtx];
- *(verticesp++) = v_agent[vtx | 1 << j_bit];
- *(verticesp++) = v_agent[vtx | 1 << i_bit];
- *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit];
-
- *(texCoordsp++) = TEX00;
- *(texCoordsp++) = TEX01;
- *(texCoordsp++) = TEX10;
- *(texCoordsp++) = TEX11;
-
- // Triangles for each side
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 3;
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 2;
}
const LLVector3 &look_at = gCamera->getAtAxis();
@@ -1445,7 +1448,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
LLStrider<LLVector3> verticesp;
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
LLFace *facep;
@@ -1493,8 +1496,16 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
hb.setVisible(TRUE);
facep = mFace[f];
- facep->setPrimType(LLTriangles);
- facep->setSize(4, 6);
+
+ if (facep->mVertexBuffer.isNull())
+ {
+ facep->setSize(4, 6);
+ facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+ facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
+ facep->setGeomIndex(0);
+ facep->setIndicesIndex(0);
+ }
+
index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
{
@@ -1623,7 +1634,7 @@ void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
LLStrider<LLVector3> verticesp;
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
LLFace *face;
@@ -1642,8 +1653,16 @@ void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
v_glow_corner[3] = draw_pos + right - up;
face = mFace[FACE_BLOOM];
- face->setPrimType(LLTriangles);
- face->setSize(4, 6);
+
+ if (face->mVertexBuffer.isNull())
+ {
+ face->setSize(4, 6);
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
+ }
+
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
{
@@ -1877,15 +1896,23 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
dt_clip = -0.1f;
}
+ LLFace *face = mFace[FACE_REFLECTION];
+
+ if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount())
+ {
+ face->setSize(quads * 4, quads * 6);
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
+ face->setIndicesIndex(0);
+ face->setGeomIndex(0);
+ }
+
LLStrider<LLVector3> verticesp;
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
- LLFace *face = mFace[FACE_REFLECTION];
-
- face->setPrimType(LLTriangles);
- face->setSize(quads * 4, quads * 6);
+
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
{
@@ -2113,16 +2140,14 @@ void LLVOSky::updateFog(const F32 distance)
color_gamma_correct(sky_fog_color);
- if (!(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) > LLDrawPool::SHADER_LEVEL_SCATTERING))
- {
- render_fog_color = sky_fog_color;
- }
-
+ render_fog_color = sky_fog_color;
+
if (camera_height > water_height)
{
fog_distance = mFogRatio * distance;
LLColor4 fog(render_fog_color);
glFogfv(GL_FOG_COLOR, fog.mV);
+ mGLFogCol = fog;
}
else
{
@@ -2142,6 +2167,7 @@ void LLVOSky::updateFog(const F32 distance)
LLColor4 fogCol = brightness * (color_frac * render_fog_color + (1.f - color_frac) * LLColor4(0.f, 0.2f, 0.3f, 1.f));
fogCol.setAlpha(1);
glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
+ mGLFogCol = fogCol;
}
mFogColor = sky_fog_color;
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index c140e97e5e..c705c3951e 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -178,7 +178,7 @@ protected:
}
LLImageRaw* getImageRaw(BOOL curr=TRUE) { return mImageRaw[getWhich(curr)]; }
- void createTexture(BOOL curr=TRUE);
+ void createGLImage(BOOL curr=TRUE);
};
@@ -492,7 +492,7 @@ public:
class LLCubeMap;
-class LLVOSky : public LLViewerObject
+class LLVOSky : public LLStaticViewerObject
{
public:
enum
@@ -574,6 +574,7 @@ public:
LLColor4 getMoonAmbientColor() const { return mMoonAmbient; }
const LLColor4& getTotalAmbientColor() const { return mTotalAmbient; }
LLColor4 getFogColor() const { return mFogColor; }
+ LLColor4 getGLFogColor() const { return mGLFogCol; }
LLVector3 calcUpVec(const LLVector3 &pos) const
{
@@ -710,6 +711,8 @@ protected:
F32 sInterpVal;
LLColor4 mFogColor;
+ LLColor4 mGLFogCol;
+
F32 mFogRatio;
F32 mWorldScale;
@@ -720,7 +723,7 @@ protected:
LLColor3 mMoonDiffuse;
LLColor4U mFadeColor; // Color to fade in from
- LLCubeMap *mCubeMap; // Cube map for the sky
+ LLCubeMap *mCubeMap; // Cube map for the environment
S32 mDrawRefl;
LLFrameTimer mUpdateTimer;
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index ae7d46dfee..759493504e 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -10,6 +10,8 @@
#include "llvosurfacepatch.h"
+#include "lldrawpoolterrain.h"
+
#include "lldrawable.h"
#include "llface.h"
#include "llprimitive.h"
@@ -22,8 +24,52 @@
#include "llvovolume.h"
#include "pipeline.h"
+//============================================================================
+
+class LLVertexBufferTerrain : public LLVertexBuffer
+{
+public:
+ LLVertexBufferTerrain() :
+ LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD | MAP_TEXCOORD2 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB)
+ {
+ };
+
+ // virtual
+ void setupVertexBuffer(U32 data_mask) const
+ {
+ if (LLDrawPoolTerrain::getDetailMode() == 0)
+ {
+ LLVertexBuffer::setupVertexBuffer(data_mask);
+ }
+ else if (data_mask & LLVertexBuffer::MAP_TEXCOORD2)
+ {
+ U8* base = useVBOs() ? NULL : mMappedData;
+
+ glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0));
+ glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL]));
+ glColorPointer(4, GL_UNSIGNED_BYTE, mStride, (void*)(base + mOffsets[TYPE_COLOR]));
+
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+ }
+ else
+ {
+ LLVertexBuffer::setupVertexBuffer(data_mask);
+ }
+ llglassertok();
+ }
+};
+
+//============================================================================
+
LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, LL_VO_SURFACE_PATCH, regionp)
+: LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp)
{
// Terrain must draw during selection passes so it can block objects behind it.
mbCanSelect = TRUE;
@@ -76,9 +122,9 @@ void LLVOSurfacePatch::updateTextures(LLAgent &agent)
}
-LLDrawPool *LLVOSurfacePatch::getPool()
+LLFacePool *LLVOSurfacePatch::getPool()
{
- mPool = gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture());
+ mPool = (LLDrawPoolTerrain*) gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture());
return mPool;
}
@@ -106,15 +152,18 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline)
range = 3;
}
- LLDrawPool *poolp = getPool();
+ LLFacePool *poolp = getPool();
mDrawable->addFace(poolp, NULL);
+
return mDrawable;
}
BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN);
+
S32 min_comp, max_comp, range;
min_comp = lltrunc(mPatchp->getMinComposition());
max_comp = lltrunc(ceil(mPatchp->getMaxComposition()));
@@ -166,57 +215,63 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
east_stride = render_stride;
}
+ mLastLength = length;
+ mLastStride = render_stride;
+ mLastNorthStride = north_stride;
+ mLastEastStride = east_stride;
+
+ return TRUE;
+}
+
+void LLVOSurfacePatch::updateFaceSize(S32 idx)
+{
+ if (idx != 0)
+ {
+ llwarns << "Terrain partition requested invalid face!!!" << llendl;
+ return;
+ }
+
+ LLFace* facep = mDrawable->getFace(idx);
+
S32 num_vertices = 0;
S32 num_indices = 0;
- S32 new_north_offset = 0;
- S32 new_east_offset = 0;
-
- getGeomSizesMain(render_stride, num_vertices, num_indices);
- new_north_offset = num_vertices;
- getGeomSizesNorth(render_stride, north_stride, num_vertices, num_indices);
- new_east_offset = num_vertices;
- getGeomSizesEast(render_stride, east_stride, num_vertices, num_indices);
- S32 new_num_vertices = num_vertices;
- S32 new_num_indices = num_indices;
-
- LLFace *facep = NULL;
-
- // Update the allocated face
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoords0p;
- LLStrider<LLVector2> texCoords1p;
- LLStrider<LLColor4U> colorsp;
- U32* indicesp = NULL;
- S32 index_offset;
-
- facep = mDrawable->getFace(0);
-
- facep->setSize(new_num_vertices, new_num_indices);
- facep->setPrimType(LLTriangles);
-
- index_offset = facep->getGeometryTerrain(
- verticesp,
- normalsp,
- colorsp,
- texCoords0p,
- texCoords1p,
- indicesp);
- if (-1 == index_offset)
+
+ if (mLastStride)
{
- return TRUE;
+ getGeomSizesMain(mLastStride, num_vertices, num_indices);
+ getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices);
+ getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices);
}
- mDrawable->updateLightSet();
+ facep->setSize(num_vertices, num_indices);
+}
+
+BOOL LLVOSurfacePatch::updateLOD()
+{
+ //mDrawable->updateLightSet();
+ mDrawable->setState(LLDrawable::LIGHTING_BUILT);
+ return TRUE;
+}
+
+void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp,
+ LLStrider<LLVector3> &normalsp,
+ LLStrider<LLColor4U> &colorsp,
+ LLStrider<LLVector2> &texCoords0p,
+ LLStrider<LLVector2> &texCoords1p,
+ LLStrider<U32> &indicesp)
+{
+ LLFace* facep = mDrawable->getFace(0);
+
+ U32 index_offset = facep->getGeomIndex();
updateMainGeometry(facep,
- verticesp,
- normalsp,
- colorsp,
- texCoords0p,
- texCoords1p,
- indicesp,
- index_offset);
+ verticesp,
+ normalsp,
+ colorsp,
+ texCoords0p,
+ texCoords1p,
+ indicesp,
+ index_offset);
updateNorthGeometry(facep,
verticesp,
normalsp,
@@ -233,24 +288,6 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
texCoords1p,
indicesp,
index_offset);
-
- if (mLastLength != 0)
- {
- // lazy, should cache the geom sizes so we know the offsets.
- num_vertices = 0;
- num_indices = 0;
-
- }
-
- mLastLength = length;
- mLastStride = render_stride;
- mLastNorthStride = north_stride;
- mLastEastStride = east_stride;
-
- mDrawable->setState(LLDrawable::LIGHTING_BUILT);
-
- LLPipeline::sCompiles++;
- return TRUE;
}
void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
@@ -259,8 +296,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset)
+ LLStrider<U32> &indicesp,
+ U32 &index_offset)
{
S32 i, j, x, y;
@@ -268,7 +305,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
S32 num_vertices, num_indices;
U32 index;
- render_stride = mPatchp->getRenderStride();
+ render_stride = mLastStride;
patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
S32 vert_size = patch_size / render_stride;
@@ -364,29 +401,20 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset)
+ LLStrider<U32> &indicesp,
+ U32 &index_offset)
{
S32 vertex_count = 0;
S32 i, x, y;
S32 num_vertices, num_indices;
- U32 render_stride = mPatchp->getRenderStride();
+ U32 render_stride = mLastStride;
S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
S32 length = patch_size / render_stride;
S32 half_length = length / 2;
-
- U32 north_stride;
- if (mPatchp->getNeighborPatch(NORTH))
- {
- north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride();
- }
- else
- {
- north_stride = render_stride;
- }
-
+ U32 north_stride = mLastNorthStride;
+
///////////////////////////
//
// Render the north strip
@@ -586,27 +614,19 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset)
+ LLStrider<U32> &indicesp,
+ U32 &index_offset)
{
S32 i, x, y;
S32 num_vertices, num_indices;
- U32 render_stride = mPatchp->getRenderStride();
+ U32 render_stride = mLastStride;
S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
S32 length = patch_size / render_stride;
S32 half_length = length / 2;
- U32 east_stride;
- if (mPatchp->getNeighborPatch(EAST))
- {
- east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride();
- }
- else
- {
- east_stride = render_stride;
- }
+ U32 east_stride = mLastEastStride;
// Stride lengths are the same
if (east_stride == render_stride)
@@ -825,10 +845,6 @@ void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp)
void LLVOSurfacePatch::dirtyPatch()
{
- if (mDrawable)
- {
- gPipeline.markMoved(mDrawable);
- }
mDirtiedPatch = TRUE;
dirtyGeom();
mDirtyTerrain = TRUE;
@@ -846,6 +862,8 @@ void LLVOSurfacePatch::dirtyGeom()
if (mDrawable)
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ mDrawable->getFace(0)->mVertexBuffer = NULL;
+ mDrawable->movePartition();
}
}
@@ -918,7 +936,67 @@ void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax
{
LLVector3 posAgent = getPositionAgent();
LLVector3 scale = getScale();
- newMin = posAgent-scale;
- newMax = posAgent+scale;
+ newMin = posAgent-scale*0.5f;
+ newMax = posAgent+scale*0.5f;
mDrawable->setPositionGroup((newMin+newMax)*0.5f);
}
+
+U32 LLVOSurfacePatch::getPartitionType() const
+{
+ return LLPipeline::PARTITION_TERRAIN;
+}
+
+LLTerrainPartition::LLTerrainPartition()
+: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK)
+{
+ mRenderByGroup = FALSE;
+ mBufferUsage = GL_DYNAMIC_DRAW_ARB;
+ mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN;
+ mPartitionType = LLPipeline::PARTITION_TERRAIN;
+}
+
+LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage)
+{
+ return new LLVertexBufferTerrain();
+}
+
+void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
+{
+ LLVertexBuffer* buffer = group->mVertexBuffer;
+
+ //get vertex buffer striders
+ LLStrider<LLVector3> vertices;
+ LLStrider<LLVector3> normals;
+ LLStrider<LLVector2> texcoords2;
+ LLStrider<LLVector2> texcoords;
+ LLStrider<LLColor4U> colors;
+ LLStrider<U32> indices;
+
+ buffer->getVertexStrider(vertices);
+ buffer->getNormalStrider(normals);
+ buffer->getTexCoordStrider(texcoords);
+ buffer->getTexCoord2Strider(texcoords2);
+ buffer->getColorStrider(colors);
+ buffer->getIndexStrider(indices);
+
+ U32 indices_index = 0;
+ U32 index_offset = 0;
+
+ for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
+ {
+ LLFace* facep = *i;
+
+ facep->setIndicesIndex(indices_index);
+ facep->setGeomIndex(index_offset);
+ facep->mVertexBuffer = buffer;
+
+ LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
+ patchp->getGeometry(vertices, normals, colors, texcoords, texcoords2, indices);
+
+ indices_index += facep->getIndicesCount();
+ index_offset += facep->getGeomCount();
+ }
+
+ mFaceList.clear();
+}
+
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index f1c44aa598..fd2eff710b 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -16,9 +16,19 @@ class LLSurfacePatch;
class LLDrawPool;
class LLVector2;
-class LLVOSurfacePatch : public LLViewerObject
+class LLVOSurfacePatch : public LLStaticViewerObject
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD2) |
+ (1 << LLVertexBuffer::TYPE_COLOR)
+ }
+ eVertexDataMask;
+
LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
virtual ~LLVOSurfacePatch();
@@ -27,8 +37,18 @@ public:
// Initialize data that's only inited once per class.
static void initClass();
+ virtual U32 getPartitionType() const;
+
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ /*virtual*/ BOOL updateLOD();
+ /*virtual*/ void updateFaceSize(S32 idx);
+ void getGeometry(LLStrider<LLVector3> &verticesp,
+ LLStrider<LLVector3> &normalsp,
+ LLStrider<LLColor4U> &colorsp,
+ LLStrider<LLVector2> &texCoords0p,
+ LLStrider<LLVector2> &texCoords1p,
+ LLStrider<U32> &indicesp);
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
@@ -44,8 +64,8 @@ public:
BOOL mDirtiedPatch;
protected:
- LLDrawPool *mPool;
- LLDrawPool *getPool();
+ LLFacePool *mPool;
+ LLFacePool *getPool();
S32 mBaseComp;
LLSurfacePatch *mPatchp;
BOOL mDirtyTexture;
@@ -70,24 +90,24 @@ protected:
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset);
+ LLStrider<U32> &indicesp,
+ U32 &index_offset);
void updateNorthGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset);
+ LLStrider<U32> &indicesp,
+ U32 &index_offset);
void updateEastGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLColor4U> &colorsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
- U32* &indicesp,
- S32 &index_offset);
+ LLStrider<U32> &indicesp,
+ U32 &index_offset);
};
#endif // LL_VOSURFACEPATCH_H
diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp
index d9f3d83f11..1a68fa88bf 100644
--- a/indra/newview/llvotextbubble.cpp
+++ b/indra/newview/llvotextbubble.cpp
@@ -24,7 +24,7 @@
#include "pipeline.h"
LLVOTextBubble::LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, pcode, regionp)
+: LLAlphaObject(id, pcode, regionp)
{
setScale(LLVector3(1.5f, 1.5f, 0.25f));
mbCanSelect = FALSE;
@@ -83,8 +83,10 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
for (i = 0; i < getNumTEs(); i++)
{
setTEColor(i, color);
+ setTEFullbright(i, TRUE);
}
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
return TRUE;
}
@@ -126,15 +128,14 @@ LLDrawable *LLVOTextBubble::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- LLDrawPool *poolp;
+
for (U32 i = 0; i < getNumTEs(); i++)
{
LLViewerImage *imagep;
const LLTextureEntry *texture_entry = getTE(i);
imagep = gImageList.getImage(texture_entry->getID());
- poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA);
- mDrawable->addFace(poolp, imagep);
+ mDrawable->addFace((LLFacePool*) NULL, imagep);
}
return mDrawable;
@@ -181,24 +182,65 @@ BOOL LLVOTextBubble::updateGeometry(LLDrawable *drawable)
for (S32 i = 0; i < drawable->getNumFaces(); i++)
{
LLFace *face = drawable->getFace(i);
-
- if (i == 0)
- {
- face->setSize(0);
- continue;
- }
- if (i == 2)
- {
- face->setSize(0);
- continue;
- }
-
- // Need to figure out how to readd logic to determine face dirty vs. entire object dirty.
face->setTEOffset(i);
- face->clearState(LLFace::GLOBAL);
- face->genVolumeTriangles(*getVolume(), i, identity4, identity3);
+ face->setTexture(LLViewerImage::sSmokeImagep);
+ face->setState(LLFace::FULLBRIGHT);
}
+
mVolumeChanged = FALSE;
+ mDrawable->movePartition();
return TRUE;
}
+
+void LLVOTextBubble::updateFaceSize(S32 idx)
+{
+ LLFace* face = mDrawable->getFace(idx);
+
+ if (idx == 0 || idx == 2)
+ {
+ face->setSize(0,0);
+ }
+ else
+ {
+ const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
+ face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
+ }
+}
+
+void LLVOTextBubble::getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp)
+{
+ if (idx == 0 || idx == 2)
+ {
+ return;
+ }
+
+ const LLVolumeFace& face = getVolume()->getVolumeFace(idx);
+
+ LLVector3 pos = getPositionAgent();
+ LLColor4U color = LLColor4U(getTE(idx)->getColor());
+ U32 offset = mDrawable->getFace(idx)->getGeomIndex();
+
+ for (U32 i = 0; i < face.mVertices.size(); i++)
+ {
+ *verticesp++ = face.mVertices[i].mPosition.scaledVec(getScale()) + pos;
+ *normalsp++ = face.mVertices[i].mNormal;
+ *texcoordsp++ = face.mVertices[i].mTexCoord;
+ *colorsp++ = color;
+ }
+
+ for (U32 i = 0; i < face.mIndices.size(); i++)
+ {
+ *indicesp++ = face.mIndices[i] + offset;
+ }
+}
+
+U32 LLVOTextBubble::getPartitionType() const
+{
+ return LLPipeline::PARTITION_PARTICLE;
+}
diff --git a/indra/newview/llvotextbubble.h b/indra/newview/llvotextbubble.h
index 9fe6386a3b..a348a53c7c 100644
--- a/indra/newview/llvotextbubble.h
+++ b/indra/newview/llvotextbubble.h
@@ -12,7 +12,7 @@
#include "llviewerobject.h"
#include "llframetimer.h"
-class LLVOTextBubble : public LLViewerObject
+class LLVOTextBubble : public LLAlphaObject
{
public:
LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
@@ -25,6 +25,16 @@ public:
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ BOOL updateLOD();
+ /*virtual*/ void updateFaceSize(S32 idx);
+
+ /*virtual*/ void getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U32>& indicesp);
+
+ virtual U32 getPartitionType() const;
LLColor4 mColor;
S32 mLOD;
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index a4b61f13bd..f67188ff05 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -10,6 +10,8 @@
#include "llvotree.h"
+#include "lldrawpooltree.h"
+
#include "llviewercontrol.h"
#include "lldir.h"
#include "llprimitive.h"
@@ -19,7 +21,6 @@
#include "object_flags.h"
#include "llagent.h"
-#include "llagparray.h"
#include "llcylinder.h"
#include "lldrawable.h"
#include "llface.h"
@@ -389,6 +390,10 @@ void LLVOTree::updateTextures(LLAgent &agent)
F32 cos_angle = 1.f;
if (mTreeImagep)
{
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ {
+ setDebugText(llformat("%4.0f", fsqrtf(mPixelArea)));
+ }
mTreeImagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle);
}
@@ -402,14 +407,12 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE);
- LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep);
+ LLDrawPoolTree *poolp = (LLDrawPoolTree*) gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep);
// Just a placeholder for an actual object...
- LLFace *facep = mDrawable->addFace(poolp, mTreeImagep, TRUE);
+ LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
facep->setSize(1, 3);
- gPipeline.markMaterialed(mDrawable);
-
updateRadius();
return mDrawable;
@@ -422,6 +425,7 @@ const S32 LEAF_VERTICES = 16;
BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE);
U32 i, j;
const S32 MAX_SLICES = 32;
@@ -444,20 +448,6 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
face->mCenterAgent = getPositionAgent();
face->mCenterLocal = face->mCenterAgent;
- LLDrawPool *poolp = face->getPool();
-
- if (poolp->getVertexCount())
- {
- return TRUE;
- }
-
- if (!face->getDirty())
- {
- return FALSE;
- }
-
- poolp->setDirty();
-
for (lod = 0; lod < 4; lod++)
{
slices = sLODSlices[lod];
@@ -472,10 +462,17 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
LLStrider<LLVector3> vertices;
LLStrider<LLVector3> normals;
LLStrider<LLVector2> tex_coords;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
face->setSize(max_vertices, max_indices);
+
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE);
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+
face->getGeometry(vertices, normals, tex_coords, indicesp);
+
S32 vertex_count = 0;
S32 index_count = 0;
@@ -774,17 +771,13 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
return TRUE;
}
-void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha)
+U32 LLVOTree::drawBranchPipeline(U32* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha)
{
+ U32 ret = 0;
//
// Draws a tree by recursing, drawing branches and then a 'leaf' texture.
// If stop_level = -1, simply draws the whole tree as a billboarded texture
//
-
- if (!draw_pool->getIndexCount())
- {
- return; // safety net
- }
static F32 constant_twist;
static F32 width = 0;
@@ -808,15 +801,15 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop
width = scale * length * aspect;
glPushMatrix();
glScalef(width,width,scale * length);
- //glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, draw_pool.getRawIndices() + sLODIndexOffset[trunk_LOD]);
- glDrawRangeElements(GL_TRIANGLES,
+ glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, indicesp + sLODIndexOffset[trunk_LOD]);
+ /*glDrawRangeElements(GL_TRIANGLES,
sLODVertexOffset[trunk_LOD],
sLODVertexOffset[trunk_LOD] + sLODVertexCount[trunk_LOD]-1,
sLODIndexCount[trunk_LOD],
GL_UNSIGNED_INT,
- draw_pool->getRawIndices() + sLODIndexOffset[trunk_LOD]);
+ indicesp + sLODIndexOffset[trunk_LOD]);*/
stop_glerror();
- draw_pool->addIndicesDrawn(sLODIndexCount[trunk_LOD]);
+ ret += sLODIndexCount[trunk_LOD];
glPopMatrix();
}
@@ -828,7 +821,7 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop
glRotatef((constant_twist + ((i%2==0)?twist:-twist))*i, 0.f, 0.f, 1.f);
glRotatef(droop, 0.f, 1.f, 0.f);
glRotatef(20.f, 0.f, 0.f, 1.f); // rotate 20deg about axis of new branch to add some random variation
- drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
+ ret += drawBranchPipeline(indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
glPopMatrix();
}
// Recurse to continue trunk
@@ -837,7 +830,7 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop
glPushMatrix();
glTranslatef(0.f, 0.f, scale * length);
glRotatef(70.5f, 0.f, 0.f, 1.f); // rotate a bit around Z when ascending
- drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
+ ret += drawBranchPipeline(indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
glPopMatrix();
}
}
@@ -852,15 +845,15 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop
//width = scale * (TREE_BRANCH_ASPECT + TREE_LEAF_ASPECT);
glScalef(scale*mLeafScale, scale*mLeafScale, scale*mLeafScale);
//glScalef(1.5f*width*mLeafScale,1,1.5f*scale*mLeafScale);
-// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices());
- glDrawRangeElements(GL_TRIANGLES,
+ glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, indicesp);
+ /*glDrawRangeElements(GL_TRIANGLES,
0,
LEAF_VERTICES-1,
LEAF_INDICES,
GL_UNSIGNED_INT,
- draw_pool->getRawIndices());
+ indicesp);*/
stop_glerror();
- draw_pool->addIndicesDrawn(LEAF_INDICES);
+ ret += LEAF_INDICES;
glPopMatrix();
}
}
@@ -878,21 +871,23 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop
{
glPushMatrix();
glScalef(mBillboardScale*mBillboardRatio, mBillboardScale*mBillboardRatio, mBillboardScale);
-// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices());
- glDrawRangeElements(GL_TRIANGLES,
+ glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, indicesp);
+/* glDrawRangeElements(GL_TRIANGLES,
0,
LEAF_VERTICES-1,
LEAF_INDICES,
GL_UNSIGNED_INT,
- draw_pool->getRawIndices());
+ indicesp);*/
stop_glerror();
- draw_pool->addIndicesDrawn(LEAF_INDICES);
+ ret += LEAF_INDICES;
glPopMatrix();
}
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
+
+ return ret;
}
void LLVOTree::updateRadius()
@@ -904,3 +899,30 @@ void LLVOTree::updateRadius()
mDrawable->setRadius(32.0f);
}
+
+void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
+{
+ LLVector3 center = getRenderPosition();
+ LLVector3 size = getScale();
+ center.mV[2] += size.mV[2];
+
+ newMin.setVec(center-size);
+ newMax.setVec(center+size);
+ mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
+}
+
+U32 LLVOTree::getPartitionType() const
+{
+ return LLPipeline::PARTITION_TREE;
+}
+
+LLTreePartition::LLTreePartition()
+: LLSpatialPartition(0)
+{
+ mRenderByGroup = FALSE;
+ mDrawableType = LLPipeline::RENDER_TYPE_TREE;
+ mPartitionType = LLPipeline::PARTITION_TREE;
+ mSlopRatio = 0.f;
+ mLODPeriod = 1;
+}
+
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index f962516803..487dd706df 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -20,6 +20,14 @@ class LLDrawPool;
class LLVOTree : public LLViewerObject
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD)
+ }
+ eVertexDataMask;
+
LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
virtual ~LLVOTree();
@@ -40,10 +48,13 @@ public:
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ /*virtual*/ void updateSpatialExtents(LLVector3 &min, LLVector3 &max);
+
+ virtual U32 getPartitionType() const;
void updateRadius();
- void drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha);
+ U32 drawBranchPipeline(U32* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha);
void drawBranch(S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha, BOOL draw_leaves);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index c1cc5b9ecb..55445f21fe 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -23,7 +23,6 @@
#include "material_codes.h"
#include "message.h"
#include "object_flags.h"
-
#include "llagent.h"
#include "lldrawable.h"
#include "lldrawpoolsimple.h"
@@ -45,14 +44,14 @@
#include "pipeline.h"
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
-
-//#define LLDEBUG_DISPLAY_LODS 1
+const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
+const F32 FORCE_CULL_AREA = 8.f;
BOOL gAnimateTextures = TRUE;
+extern BOOL gHideSelectedObjects;
F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
-F32 LLVOVolume::sLODComplexityDistanceBias = 0.0f;//Changing this to zero makes all prims LOD equally regardless of complexity
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
@@ -65,12 +64,8 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mLOD = MIN_LOD;
mInited = FALSE;
- mAllTEsSame = FALSE;
mTextureAnimp = NULL;
mGlobalVolume = FALSE;
-
- mTextureAnimp = NULL;
- mAllTEsSame = FALSE;
mVObjRadius = LLVector3(1,1,0.5f).magVec();
mNumFaces = 0;
}
@@ -124,11 +119,17 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
}
}
mTextureAnimp->unpackTAMessage(mesgsys, block_num);
+ gPipeline.markTextured(mDrawable);
}
else
{
- delete mTextureAnimp;
- mTextureAnimp = NULL;
+ if (mTextureAnimp)
+ {
+ delete mTextureAnimp;
+ mTextureAnimp = NULL;
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
+ }
}
// Unpack volume data
@@ -239,52 +240,39 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
if (mTextureAnimp && gAnimateTextures)
{
- F32 off_s, off_t, scale_s, scale_t, rot;
+ F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
S32 result;
- if ((result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot)))
+ if (result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))
{
- U8 has_bump = 0;
- if (mTextureAnimp->mFace <= -1)
+ mTexAnimMode = result | mTextureAnimp->mMode;
+ LLQuaternion quat;
+ LLVector3 scale(1,1,1);
+
+ if (result & LLViewerTextureAnim::ROTATE)
{
- S32 face;
- for (face = 0; face < getNumTEs(); face++)
- {
- if (result & LLViewerTextureAnim::TRANSLATE)
- {
- setTEOffset(face, off_s, off_t);
- }
- if (result & LLViewerTextureAnim::SCALE)
- {
- setTEScale(face, scale_s, scale_t);
- }
- if (result & LLViewerTextureAnim::ROTATE)
- {
- setTERotation(face, rot);
- }
- has_bump |= getTE(face)->getBumpmap();
- }
+ quat.setQuat(rot, 0, 0, -1);
}
- else if (mTextureAnimp->mFace < getNumTEs())
+
+ if (!(result & LLViewerTextureAnim::TRANSLATE))
{
- if (result & LLViewerTextureAnim::TRANSLATE)
- {
- setTEOffset(mTextureAnimp->mFace, off_s, off_t);
- }
- if (result & LLViewerTextureAnim::SCALE)
- {
- setTEScale(mTextureAnimp->mFace, scale_s, scale_t);
- }
- if (result & LLViewerTextureAnim::ROTATE)
- {
- setTERotation(mTextureAnimp->mFace, rot);
- }
- has_bump |= getTE(mTextureAnimp->mFace)->getBumpmap();
+ off_s = off_t = 0.f;
}
-// mFaceMappingChanged = TRUE;
- if (mDrawable->isVisible())
+
+ LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f);
+
+ mTextureMatrix.identity();
+ mTextureMatrix.translate(LLVector3(-0.5f, -0.5f, 0.f));
+ mTextureMatrix.rotate(quat);
+
+ if (result & LLViewerTextureAnim::SCALE)
{
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE);
+ scale.setVec(scale_s, scale_t, 1.f);
+ LLMatrix4 mat;
+ mat.initAll(scale, LLQuaternion(), LLVector3());
+ mTextureMatrix *= mat;
}
+
+ mTextureMatrix.translate(trans);
}
}
@@ -299,71 +287,40 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
void LLVOVolume::updateTextures(LLAgent &agent)
{
-
+// LLFastTimer t(LLFastTimer::FTM_TEMP6);
+ const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
+ if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
+ {
+ if (mDrawable->isVisible())
+ {
+ updateTextures();
+ }
+ }
}
-//static
-F32 LLVOVolume::getTextureVirtualSize(const LLFace* face)
+void LLVOVolume::updateTextures()
{
- //LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0];
- //F32 pixel_area = 1.f/llmin(llmax(tdim.mV[0] * tdim.mV[1], 1.f), 10.f);
- LLVector3 cross_vec = (face->mExtents[1] - face->mExtents[0]);
-
-
- LLVector3 lookAt = (face->getPositionAgent()-gCamera->getOrigin());
- F32 dist = lookAt.normVec();
+ // Update the pixel area of all faces
- F32 face_area;
-
- if (face->isState(LLFace::GLOBAL))
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
{
- face_area = cross_vec.mV[0]*cross_vec.mV[1]*fabsf(lookAt.mV[2]) +
- cross_vec.mV[1]*cross_vec.mV[2]*fabsf(lookAt.mV[0]) +
- cross_vec.mV[0]*cross_vec.mV[2]*fabsf(lookAt.mV[1]);
- }
- else
- {
- face_area = cross_vec.mV[0]*cross_vec.mV[1] +
- cross_vec.mV[1]*cross_vec.mV[2] +
- cross_vec.mV[0]*cross_vec.mV[2];
- }
-
- if (face_area <= 0)
- {
- return 0.f;
+ return;
}
-
- F32 view = llmax(lookAt*gCamera->getAtAxis(), 0.5f);
- F32 dist_ramp = dist * view/face_area;
- //ramp down distance for things closer than 16 m * lookAt
- dist /= dist_ramp;
- dist *= dist;
- dist *= dist_ramp;
-
- F32 dist_ratio = face_area / llmax(dist, 0.1f);
- F32 pixel_area = dist_ratio*gCamera->getScreenPixelArea();
- return view*pixel_area;
-}
-
-void LLVOVolume::updateTextures(S32 lod)
-{
- // Update the image levels of all textures...
- // First we do some quick checks.
-
- // This doesn't take into account whether the object is in front
- // or behind...
-
- if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull() || !mDrawable->isVisible())
+ if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible())
{
return;
}
-
- const S32 num_faces = mDrawable->getNumFaces();
+
+ mTextureUpdateTimer.reset();
+ mPixelArea = 0.f;
+ const S32 num_faces = mDrawable->getNumFaces();
+
+ F32 min_vsize=999999999.f, max_vsize=0.f;
for (S32 i = 0; i < num_faces; i++)
{
- const LLFace* face = mDrawable->getFace(i);
+ LLFace* face = mDrawable->getFace(i);
const LLTextureEntry *te = face->getTextureEntry();
LLViewerImage *imagep = face->getTexture();
@@ -376,23 +333,77 @@ void LLVOVolume::updateTextures(S32 lod)
if (isHUDAttachment())
{
- vsize = (F32) (imagep->getWidth(0) * imagep->getHeight(0));
+ F32 area = (F32) gCamera->getScreenPixelArea();
+ vsize = area;
imagep->setBoostLevel(LLViewerImage::BOOST_HUD);
+ face->setPixelArea(area); // treat as full screen
}
else
{
vsize = getTextureVirtualSize(face);
}
+ mPixelArea = llmax(mPixelArea, face->getPixelArea());
+ face->setVirtualSize(vsize);
imagep->addTextureStats(vsize);
-
-
- U8 bump = te->getBumpmap();
- if( te && bump)
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ {
+ if (vsize < min_vsize) min_vsize = vsize;
+ if (vsize > max_vsize) max_vsize = vsize;
+ }
+ else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
- gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1);
+ F32 pri = imagep->getDecodePriority();
+ if (pri < min_vsize) min_vsize = pri;
+ if (pri > max_vsize) max_vsize = pri;
}
+ // U8 bump = te->getBumpmap();
+ // if( te && bump)
+ // {
+ // gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1);
+ // }
+ }
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ {
+ setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
+ }
+ else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
+ {
+ setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
+ }
+}
+
+F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
+{
+ //get area of circle around face
+ LLVector3 center = face->getPositionAgent();
+ LLVector3 size = //isFlexible() ?
+ // getScale()*3.f :
+ (face->mExtents[1] - face->mExtents[0]) * 0.5f;
+
+ F32 face_area = LLPipeline::calcPixelArea(center, size, *gCamera);
+
+ face->setPixelArea(face_area);
+
+ if (face_area <= 0)
+ {
+ return 0.f;
+ }
+
+ //get area of circle in texture space
+ LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0];
+ F32 texel_area = (tdim * 0.5f).magVecSquared()*3.14159f;
+ if (texel_area <= 0)
+ {
+ // Probably animated, use default
+ texel_area = 1.f;
}
+
+ //apply texel area to face area to get accurate ratio
+ face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
+
+ return face_area;
}
BOOL LLVOVolume::isActive() const
@@ -436,7 +447,7 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
//since drawable transforms do not include scale, changing volume scale
//requires an immediate rebuild of volume verts.
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
}
}
@@ -444,16 +455,7 @@ LLFace* LLVOVolume::addFace(S32 f)
{
const LLTextureEntry* te = getTE(f);
LLViewerImage* imagep = getTEImage(f);
- LLDrawPool* poolp;
- if (isHUDAttachment())
- {
- poolp = gPipeline.getPool(LLDrawPool::POOL_HUD);
- }
- else
- {
- poolp = LLPipeline::getPoolFromTE(te, imagep);
- }
- return mDrawable->addFace(poolp, imagep);
+ return mDrawable->addFace(te, imagep);
}
LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
@@ -461,7 +463,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- S32 max_tes_to_set = calcAllTEsSame() ? 1 : getNumTEs();
+ S32 max_tes_to_set = getNumTEs();
for (S32 i = 0; i < max_tes_to_set; i++)
{
LLFace* face = addFace(i);
@@ -518,10 +520,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
}
mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal());
- //MSMSM Recompute LOD here in case the object was just created,
- // its LOD might be incorrectly set to minumum detail...
- calcLOD();
-
if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique())))
{
mFaceMappingChanged = TRUE;
@@ -536,45 +534,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
return FALSE;
}
-
-F32 LLVOVolume::computeLODProfilePathComplexityBias(){
- //compute a complexity cost from 0 to 1.0 where the 'simplest' prim has a cost of 0.0
- // and the 'heaviest' prim has a cost of 1.0
-// LLVolume* volume = getVolume();
- F32 complexity = 0.0f;
-// const LLVolumeParams& params = volume->getParams();
-// U8 type = volume->getPathType();
-// U8 pcode = this->getPCode();
-// U8 proftype = volume->getProfileType();
-
- //if(params.getHollow()>0.0f){// || (proftype == 1) || (proftype == 0)){
- //If it is hollow, or a cube/pyramid(subdivided), the complexity is roughly doubled
- // complexity+=0.5f;
- //}
-
- if(this->getVolume()->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE &&
- this->getVolume()->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE)
- {
- //Object is a cube so bias it heavily since cubes are subdivided alot.
-// this->setDebugText("CUBE");
- complexity += 1.0f;
- }
-
-// if(params.getTwist() != params.getTwistBegin()){
- //if there is twist.. the complexity is bumped
-// complexity+=0.25f;
-// }
-// if(type != LL_PCODE_PATH_LINE)//If the path is not a line it is more complex
-// complexity+=0.2f;
- return complexity * sLODComplexityDistanceBias;
-}
-
S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius)
{
S32 cur_detail;
// We've got LOD in the profile, and in the twist. Use radius.
F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
- cur_detail = LLVolumeLODGroup::getDetailFromTan(tan_angle);
+ cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f));
return cur_detail;
}
@@ -584,62 +549,35 @@ BOOL LLVOVolume::calcLOD()
{
return FALSE;
}
+
+ //update textures here as well
+ updateTextures();
+
S32 cur_detail = 0;
- /*if (isHUDAttachment())
+
+ F32 radius = mVolumep->mLODScaleBias.scaledVec(getScale()).magVec();
+ F32 distance = mDrawable->mDistanceWRTCamera;
+ distance *= sDistanceFactor;
+
+ F32 rampDist = LLVOVolume::sLODFactor * 2;
+
+ if (distance < rampDist)
{
- cur_detail = LLVolumeLODGroup::NUM_LODS-1; // max detail
+ // Boost LOD when you're REALLY close
+ distance *= 1.0f/rampDist;
+ distance *= distance;
+ distance *= rampDist;
}
- else*/
- {
- F32 radius = (mVolumep->mLODScaleBias.scaledVec(getScale())).magVec();
- F32 distance = mDrawable->mDistanceWRTCamera;
- distance *= sDistanceFactor;
-
- F32 rampDist = LLVOVolume::sLODFactor * 2;
-
- if (distance < rampDist)
- {
- // Boost LOD when you're REALLY close
- distance *= 1.0f/rampDist;
- distance *= distance;
- distance *= rampDist;
- }
- else
- {
- //Now adjust the computed distance by some factor based on the geometric complexity of the primitive
- distance += computeLODProfilePathComplexityBias();
- }
- // Compensate for field of view changing on FOV zoom.
- distance *= gCamera->getView();
-
- cur_detail = computeLODDetail(distance, radius);
-
- //update textures with what the real LOD is
- updateTextures(cur_detail);
+
+ // DON'T Compensate for field of view changing on FOV zoom.
+ distance *= 3.14159f/3.f;
- if(cur_detail != mLOD)
- {
- // Here we test whether the LOD is increasing or decreasing to introduce a slop factor
- if(cur_detail < mLOD)
- {
- // Viewer is moving away from the object
- // so bias our LOD by adding a fixed amount to the distance.
- // This will reduce the problem of LOD twitching when the
- // user makes slight movements near the LOD transition threshhold.
- F32 test_distance = distance - (distance*sLODSlopDistanceFactor/(1.0f+sLODFactor));
- if(test_distance < 0.0f) test_distance = 0.0f;
- S32 potential_detail = computeLODDetail( test_distance, radius );
- if(potential_detail >= mLOD )
- { //The LOD has truly not changed
- cur_detail = mLOD;
- }
- }
- }
- }
+ cur_detail = computeLODDetail(llround(distance, 0.01f),
+ llround(radius, 0.01f));
if (cur_detail != mLOD)
{
- mAppAngle = (F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG;
+ mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
mLOD = cur_detail;
return TRUE;
}
@@ -657,17 +595,10 @@ BOOL LLVOVolume::updateLOD()
}
BOOL lod_changed = calcLOD();
-
-#if LLDEBUG_DISPLAY_LODS
- //MS Enable this to display LOD numbers on objects
- std::ostringstream msg;
- msg << cur_detail;//((cur_detail<mLOD)?"-":cur_detail==mLOD?"=":"+") << (int)cur_detail << " , " << mDrawable->mDistanceWRTCamera << " , " << ((LLVOVolume::sLODFactor*mVObjRadius)/mDrawable->mDistanceWRTCamera);
- this->setDebugText(msg.str());
-#endif
-
+
if (lod_changed)
{
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
mLODChanged = TRUE;
}
@@ -684,8 +615,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
if (!mDrawable->isRoot())
{
- // parent is dynamic, so I'll need to share its drawable, must rebuild to share drawables
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
+ // rebuild vertices in parent relative space
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
if (mDrawable->isActive() && !parentp->isActive())
{
@@ -704,7 +635,7 @@ void LLVOVolume::updateFaceFlags()
{
for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
{
- LLFace *face = mDrawable->getFace(i + mFaceIndexOffset);
+ LLFace *face = mDrawable->getFace(i);
BOOL fullbright = getTE(i)->getFullbright();
face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
@@ -720,10 +651,6 @@ void LLVOVolume::updateFaceFlags()
{
face->setState(LLFace::HUD_RENDER);
}
- if (getAllTEsSame())
- {
- break; // only 1 face
- }
}
}
@@ -731,104 +658,74 @@ void LLVOVolume::updateFaceFlags()
void LLVOVolume::regenFaces()
{
// remove existing faces
- // use mDrawable->getVOVolume() in case of shared drawables
- mDrawable->getVOVolume()->deleteFaces(this);
- mFaceIndexOffset = mDrawable->getNumFaces();
+ deleteFaces();
+
// add new faces
- mNumFaces = getAllTEsSame() ? 1 : getNumTEs();
+ mNumFaces = getNumTEs();
for (S32 i = 0; i < mNumFaces; i++)
{
LLFace* facep = addFace(i);
facep->setViewerObject(this);
facep->setTEOffset(i);
}
- // Need to do this as texture entries may not correspond to faces any more!
- mDrawable->updateTexture();
- gPipeline.markMaterialed(mDrawable);
}
-BOOL LLVOVolume::genTriangles(BOOL force_global)
+BOOL LLVOVolume::genBBoxes(BOOL force_global)
{
BOOL res = TRUE;
LLVector3 min,max;
- if (getAllTEsSame())
+ BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION);
+
+ for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
{
- setupSingleFace(mFaceIndexOffset);
- LLFace *face = mDrawable->getFace(mFaceIndexOffset);
- S32 num_faces = getVolume()->getNumFaces();
- res = face->genVolumeTriangles(*getVolume(), 0, num_faces-1,
- mRelativeXform, mRelativeXformInvTrans,
- mGlobalVolume | force_global);
+ LLFace *face = mDrawable->getFace(i);
+ res &= face->genVolumeBBoxes(*getVolume(), i,
+ mRelativeXform, mRelativeXformInvTrans,
+ mGlobalVolume | force_global);
- if (mDrawable->isState(LLDrawable::REBUILD_VOLUME))
+ if (rebuild)
{
- min = face->mExtents[0];
- max = face->mExtents[1];
- }
- mWereAllTEsSame = TRUE;
- }
- else
- {
- for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
- {
- LLFace *face = mDrawable->getFace(i + mFaceIndexOffset);
- res &= face->genVolumeTriangles(*getVolume(), i,
- mRelativeXform, mRelativeXformInvTrans,
- mGlobalVolume | force_global);
-
- if (mDrawable->isState(LLDrawable::REBUILD_VOLUME))
+ if (i == 0)
{
- if (i == 0)
- {
- min = face->mExtents[0];
- max = face->mExtents[1];
- }
- else
+ min = face->mExtents[0];
+ max = face->mExtents[1];
+ }
+ else
+ {
+ for (U32 i = 0; i < 3; i++)
{
- for (U32 i = 0; i < 3; i++)
+ if (face->mExtents[0].mV[i] < min.mV[i])
{
- if (face->mExtents[0].mV[i] < min.mV[i])
- {
- min.mV[i] = face->mExtents[0].mV[i];
- }
- if (face->mExtents[1].mV[i] > max.mV[i])
- {
- max.mV[i] = face->mExtents[1].mV[i];
- }
+ min.mV[i] = face->mExtents[0].mV[i];
+ }
+ if (face->mExtents[1].mV[i] > max.mV[i])
+ {
+ max.mV[i] = face->mExtents[1].mV[i];
}
}
}
}
- mWereAllTEsSame = FALSE;
}
-
- if (mDrawable->isState(LLDrawable::REBUILD_VOLUME))
+
+ if (rebuild)
{
mDrawable->setSpatialExtents(min,max);
- if (!isVolumeGlobal())
- {
- mDrawable->setPositionGroup((min+max)*0.5f);
- }
- else
- {
- mDrawable->setPositionGroup(getPosition());
- }
-
- updateRadius();
- mDrawable->updateBinRadius();
- mDrawable->movePartition();
+ mDrawable->setPositionGroup((min+max)*0.5f);
}
-
+
+ updateRadius();
+ mDrawable->movePartition();
+
return res;
}
-void LLVOVolume::updateRelativeXform(BOOL global_volume)
+void LLVOVolume::updateRelativeXform()
{
if (mVolumeImpl)
{
- mVolumeImpl->updateRelativeXform(global_volume);
+ mVolumeImpl->updateRelativeXform();
return;
}
@@ -854,12 +751,25 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume)
LLVector4(y_axis, 0.f),
LLVector4(z_axis, 0.f),
LLVector4(delta_pos, 1.f));
-
- x_axis.normVec();
- y_axis.normVec();
- z_axis.normVec();
+
- mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
+ // compute inverse transpose for normals
+ // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
+ // mRelativeXformInvTrans.invert();
+ // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
+ // grumble - invert is NOT a matrix invert, so we do it by hand:
+
+ LLMatrix3 rot_inverse = LLMatrix3(~delta_rot);
+
+ LLMatrix3 scale_inverse;
+ scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX],
+ LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY],
+ LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]);
+
+
+ mRelativeXformInvTrans = rot_inverse * scale_inverse;
+
+ mRelativeXformInvTrans.transpose();
}
else
{
@@ -886,34 +796,35 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume)
LLVector4(z_axis, 0.f),
LLVector4(pos, 1.f));
- x_axis.normVec();
- y_axis.normVec();
- z_axis.normVec();
-
- mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
+ // compute inverse transpose for normals
+ LLMatrix3 rot_inverse = LLMatrix3(~rot);
+
+ LLMatrix3 scale_inverse;
+ scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX],
+ LLVector3(0.0, 1.0, 0.0) / scale.mV[VY],
+ LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]);
+
+
+ mRelativeXformInvTrans = rot_inverse * scale_inverse;
+
+ mRelativeXformInvTrans.transpose();
}
}
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES);
-
+
if (mVolumeImpl != NULL)
{
LLFastTimer t(LLFastTimer::FTM_GEN_FLEX);
BOOL res = mVolumeImpl->doUpdateGeometry(drawable);
updateFaceFlags();
- if (res)
- {
- drawable->clearState(LLDrawable::REBUILD_GEOMETRY);
- }
-
return res;
}
BOOL compiled = FALSE;
- BOOL change_shared = FALSE;
-
+
updateRelativeXform();
if (mDrawable.isNull()) // Not sure why this is happening, but it is...
@@ -921,28 +832,23 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
return TRUE; // No update to complete
}
- calcAllTEsSame();
-
- if (mVolumeChanged || mFaceMappingChanged || change_shared)
+ if (mVolumeChanged || mFaceMappingChanged )
{
compiled = TRUE;
mInited = TRUE;
+ if (mVolumeChanged)
{
LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
LLVolumeParams volume_params = getVolume()->getParams();
setVolume(volume_params, 0);
- }
- drawable->setState(LLDrawable::REBUILD_GEOMETRY);
- if (mVolumeChanged || change_shared)
- {
- drawable->setState(LLDrawable::REBUILD_LIGHTING);
+ drawable->setState(LLDrawable::REBUILD_VOLUME);
}
{
LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
regenFaces();
- genTriangles(FALSE);
+ genBBoxes(FALSE);
}
}
else if (mLODChanged)
@@ -964,9 +870,9 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
if (new_lod != old_lod)
{
compiled = TRUE;
- sNumLODChanges += (getAllTEsSame() ? 1 : getVolume()->getNumFaces());
+ sNumLODChanges += getVolume()->getNumFaces();
- drawable->setState(LLDrawable::REBUILD_ALL); // for face->genVolumeTriangles()
+ drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
{
LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
@@ -974,7 +880,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
regenFaces();
}
- genTriangles(FALSE);
+ genBBoxes(FALSE);
}
}
}
@@ -984,7 +890,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
compiled = TRUE;
// All it did was move or we changed the texture coordinate offset
LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
- genTriangles(FALSE);
+ genBBoxes(FALSE);
}
// Update face flags
@@ -999,11 +905,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
mLODChanged = FALSE;
mFaceMappingChanged = FALSE;
- drawable->clearState(LLDrawable::REBUILD_GEOMETRY);
-
return TRUE;
}
+void LLVOVolume::updateFaceSize(S32 idx)
+{
+ const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
+ LLFace* facep = mDrawable->getFace(idx);
+ facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
+}
+
BOOL LLVOVolume::isRootEdit() const
{
if (mParent && !((LLViewerObject*)mParent)->isAvatar())
@@ -1015,178 +926,121 @@ BOOL LLVOVolume::isRootEdit() const
void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep)
{
-// llinfos << "SetTEImage:" << llendl;
BOOL changed = (mTEImages[te] != imagep);
LLViewerObject::setTEImage(te, imagep);
- if (mDrawable.notNull())
+ if (changed)
{
- if (changed)
- {
- calcAllTEsSame();
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
}
S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
{
- BOOL changed = (uuid != getTE(te)->getID() || (uuid == LLUUID::null));
-
S32 res = LLViewerObject::setTETexture(te, uuid);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color)
{
- BOOL changed = (color != getTE(te)->getColor());
S32 res = LLViewerObject::setTEColor(te, color);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
-// mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
{
- BOOL changed = (bumpmap != getTE(te)->getBumpmap());
S32 res = LLViewerObject::setTEBumpmap(te, bumpmap);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
{
- BOOL changed = (texgen != getTE(te)->getTexGen());
S32 res = LLViewerObject::setTETexGen(te, texgen);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
{
- BOOL changed = (shiny != getTE(te)->getShiny());
S32 res = LLViewerObject::setTEShiny(te, shiny);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
{
- BOOL changed = (fullbright != getTE(te)->getFullbright());
S32 res = LLViewerObject::setTEFullbright(te, fullbright);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- if (!mDrawable->isState(LLDrawable::REBUILD_VOLUME))
- {
- updateFaceFlags();
- }
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
{
- bool changed = (media_flags != getTE(te)->getMediaFlags());
S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
{
- F32 olds,oldt;
- getTE(te)->getScale(&olds, &oldt);
- bool changed = (s != olds || t != oldt);
S32 res = LLViewerObject::setTEScale(te, s, t);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s)
{
- F32 olds,oldt;
- getTE(te)->getScale(&olds, &oldt);
- bool changed = (s != olds);
S32 res = LLViewerObject::setTEScaleS(te, s);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
{
- F32 olds,oldt;
- getTE(te)->getScale(&olds, &oldt);
- bool changed = (t != oldt);
S32 res = LLViewerObject::setTEScaleT(te, t);
- if (mDrawable.notNull())
+ if (res)
{
- if (changed)
- {
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- }
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
}
return res;
}
@@ -1195,135 +1049,9 @@ void LLVOVolume::updateTEData()
{
if (mDrawable.notNull())
{
- calcAllTEsSame();
- mFaceMappingChanged = TRUE;
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- }
-}
-
-BOOL LLVOVolume::calcAllTEsSame()
-{
- BOOL is_alpha = FALSE;
- BOOL was_same = mAllTEsSame;
- BOOL all_same = TRUE;
- S32 num_tes = getNumTEs();
-
- LLViewerImage *first_texturep = getTEImage(0);
- if (!first_texturep)
- {
- return FALSE;
- }
-
- const LLTextureEntry *tep = getTE(0);
- if (!tep)
- {
- llwarns << "Volume with zero textures!" << llendl;
- return FALSE;
- }
-
- if (tep->getColor().mV[3] != 1.f)
- {
- is_alpha = TRUE;
- }
- const LLColor4 first_color = tep->getColor();
- const U8 first_bump = tep->getBumpShinyFullbright();
- const U8 first_media_flags = tep->getMediaTexGen();
-
- if (first_texturep->getComponents() == 4)
- {
- is_alpha = TRUE;
- }
-
- F32 s_scale, t_scale;
- tep->getScale(&s_scale, &t_scale);
-
- for (S32 f = 1; f < num_tes; f++)
- {
- LLViewerImage *texturep = getTEImage(f);
- if (texturep != first_texturep)
- {
- all_same = FALSE;
- break;
- }
-
- tep = getTE(f);
-
- if( tep->getBumpShinyFullbright() != first_bump )
- {
- all_same = FALSE;
- break;
- }
-
- if (first_bump)
- {
- F32 cur_s, cur_t;
- tep->getScale(&cur_s, &cur_t);
- if ((cur_s != s_scale) || (cur_t != t_scale))
- {
- all_same = FALSE;
- break;
- }
- }
-
- if ((texturep->getComponents() == 4) || (tep->getColor().mV[3] != 1.f))
- {
- if (!is_alpha)
- {
- all_same = FALSE;
- break;
- }
- }
- else if (is_alpha)
- {
- all_same = FALSE;
- break;
- }
-
- if (tep->getColor() != first_color)
- {
- all_same = FALSE;
- break;
- }
-
- if (tep->getMediaTexGen() != first_media_flags)
- {
- all_same = FALSE;
- break;
- }
- }
-
- mAllTEsSame = all_same;
- if (was_same != all_same)
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); // rebuild NOW
mFaceMappingChanged = TRUE;
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE);
}
- return mAllTEsSame;
-}
-
-void LLVOVolume::setupSingleFace(S32 face_offset)
-{
- S32 num_indices = 0;
- S32 num_vertices = 0;
-
- if (mDrawable.isNull())
- {
- llerrs << "setupSingleFace called with NULL mDrawable" << llendl;
- }
- if (face_offset >= mDrawable->getNumFaces())
- {
- llerrs << "setupSingleFace called with invalid face_offset" << llendl;
- }
-
- const S32 num_faces = getVolume()->getNumFaces();
- for (S32 i = 0; i < num_faces; i++)
- {
- const LLVolumeFace &vf = getVolume()->getVolumeFace(i);
- num_vertices += vf.mVertices.size();
- num_indices += vf.mIndices.size();
- }
- LLFace *facep = mDrawable->getFace(face_offset);
- facep->setSize(num_vertices, num_indices);
}
//----------------------------------------------------------------------------
@@ -1532,7 +1260,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL
LLVector3 light_dir = light_pos - pos;
F32 dist = light_dir.normVec();
F32 dp = norm * light_dir;
- if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS))
+ if ((gPipeline.getLightingDetail() > 2))
{
if (dp <= 0)
{
@@ -1571,7 +1299,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL
BOOL LLVOVolume::updateLighting(BOOL do_lighting)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
-
+#if 0
if (mDrawable->isStatic())
{
do_lighting = FALSE;
@@ -1581,31 +1309,31 @@ BOOL LLVOVolume::updateLighting(BOOL do_lighting)
const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation());
LLVolume* volume = getVolume();
- if (getAllTEsSame())
+
+ for (S32 i = 0; i < volume->getNumFaces(); i++)
{
- LLFace *face = mDrawable->getFace(mFaceIndexOffset);
- S32 num_faces = volume->getNumFaces();
+ LLFace *face = mDrawable->getFace(i);
if (face && face->getGeomCount())
{
- face->genLighting(volume, mDrawable, 0, num_faces-1, mat_vert, mat_normal, do_lighting);
- }
- }
- else
- {
- for (S32 i = 0; i < volume->getNumFaces(); i++)
- {
- LLFace *face = mDrawable->getFace(i + mFaceIndexOffset);
- if (face && face->getGeomCount())
- {
- face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting);
- }
+ face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting);
}
}
+#endif
return TRUE;
}
//----------------------------------------------------------------------------
+U32 LLVOVolume::getVolumeInterfaceID() const
+{
+ if (mVolumeImpl)
+ {
+ return mVolumeImpl->getID();
+ }
+
+ return 0;
+}
+
BOOL LLVOVolume::isFlexible() const
{
if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE))
@@ -1696,16 +1424,18 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p
LLVector3 view_vector;
view_vector = view_point;
+ //transform view vector into volume space
+ view_vector -= getRenderPosition();
+ mDrawable->mDistanceWRTCamera = view_vector.magVec();
+ LLQuaternion worldRot = getRenderRotation();
+ view_vector = view_vector * ~worldRot;
if (!isVolumeGlobal())
- { //transform view vector into volume space
- view_vector -= getRenderPosition();
- LLQuaternion worldRot = getRenderRotation();
- view_vector = view_vector * ~worldRot;
+ {
LLVector3 objScale = getScale();
LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
view_vector.scaleVec(invObjScale);
}
-
+
updateRelativeXform();
volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans);
@@ -1713,33 +1443,15 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p
}
}
-void LLVOVolume::deleteFaces(LLVOVolume* childp)
+void LLVOVolume::deleteFaces()
{
- S32 face_count = childp->mNumFaces;
- S32 start_index = childp->mFaceIndexOffset;
+ S32 face_count = mNumFaces;
if (mDrawable.notNull())
{
- mDrawable->deleteFaces(start_index, face_count);
- }
- if (mFaceIndexOffset > start_index)
- {
- mFaceIndexOffset -= face_count;
+ mDrawable->deleteFaces(0, face_count);
}
- for (U32 i = 0; i < mChildList.size(); i++)
- {
- LLViewerObject* siblingp = mChildList[i];
- if (siblingp != childp)
- {
- if (siblingp->getPCode() == LL_PCODE_VOLUME &&
- ((LLVOVolume*)siblingp)->mFaceIndexOffset > start_index)
- {
- ((LLVOVolume*)siblingp)->mFaceIndexOffset -= face_count;
- }
- }
- }
- childp->mFaceIndexOffset = 0;
- childp->mNumFaces = 0;
+ mNumFaces = 0;
}
void LLVOVolume::updateRadius()
@@ -1787,7 +1499,8 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file_base, S32 joint_num, LLVector3& pos, LLQuaternion& rot, S32& material_index, S32& texture_index, std::multimap<LLUUID, LLMaterialExportInfo*>& material_map)
{
- LLPointer<LLImageTGA> tga_image = new LLImageTGA;
+#if 0
+ LLImageTGA tga_image;
if (mDrawable.isNull())
{
@@ -1868,10 +1581,10 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file
llinfos << "No image data available for " << filename << llendl;
continue;
}
- LLPointer<LLImageRaw> raw_image = new LLImageRaw;
+ LLImageRaw raw_image;
imagep->readBackRaw(-1, raw_image);
- BOOL success = tga_image->encode(raw_image);
- success = tga_image->save(filename);
+ BOOL success = tga_image.encode(raw_image);
+ success = tga_image.save(filename);
}
material_info = new LLMaterialExportInfo(my_material, my_texture, face_color);
@@ -1912,6 +1625,7 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file
{
((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map);
}
+#endif
}
//static
@@ -1942,10 +1656,62 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
}
}
+void LLVOVolume::setSelected(BOOL sel)
+{
+ LLViewerObject::setSelected(sel);
+ if (mDrawable.notNull())
+ {
+ mDrawable->movePartition();
+ }
+}
+
void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
{
}
+F32 LLVOVolume::getBinRadius()
+{
+ F32 radius;
+
+ const LLVector3* ext = mDrawable->getSpatialExtents();
+
+ BOOL shrink_wrap = mDrawable->isAnimating();
+ BOOL alpha_wrap = FALSE;
+ //if (!shrink_wrap)
+ {
+ for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
+ {
+ if (mDrawable->getFace(i)->getPoolType() == LLDrawPool::POOL_ALPHA)
+ {
+ alpha_wrap = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (alpha_wrap)
+ {
+ LLVector3 bounds = getScale();
+ radius = llmin(bounds.mV[1], bounds.mV[2]);
+ radius = llmin(radius, bounds.mV[0]);
+ radius *= 0.5f;
+ }
+ else if (shrink_wrap)
+ {
+ radius = (ext[1]-ext[0]).magVec()*0.5f;
+ }
+ else if (mDrawable->isStatic())
+ {
+ radius = 32.f;
+ }
+ else
+ {
+ radius = 8.f;
+ }
+
+ return llclamp(radius, 0.5f, 256.f);
+}
+
const LLVector3 LLVOVolume::getPivotPositionAgent() const
{
if (mVolumeImpl)
@@ -1961,6 +1727,8 @@ void LLVOVolume::onShift(const LLVector3 &shift_vector)
{
mVolumeImpl->onShift(shift_vector);
}
+
+ updateRelativeXform();
}
const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
@@ -1974,14 +1742,9 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
{
- if (isVolumeGlobal())
- {
- return pos;
- }
-
LLVector3 ret = pos - getRenderPosition();
ret = ret * ~getRenderRotation();
- LLVector3 objScale = getScale();
+ LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
ret.scaleVec(invObjScale);
@@ -1990,7 +1753,7 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const
{
- return isVolumeGlobal() ? dir : (dir * ~getRenderRotation());
+ return dir * ~getRenderRotation();
}
LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
@@ -2005,6 +1768,9 @@ LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
{
+ return FALSE;
+
+#if 0 // needs to be rewritten to use face extents instead of volume bounds
LLVolume* volume = getVolume();
BOOL ret = FALSE;
if (volume)
@@ -2024,4 +1790,538 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) co
}
}
return ret;
+#endif
+}
+
+U32 LLVOVolume::getPartitionType() const
+{
+ if (isHUDAttachment())
+ {
+ return LLPipeline::PARTITION_HUD;
+ }
+
+ return LLPipeline::PARTITION_VOLUME;
+}
+
+LLVolumePartition::LLVolumePartition()
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE)
+{
+ mLODPeriod = 16;
+ mDepthMask = FALSE;
+ mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
+ mPartitionType = LLPipeline::PARTITION_VOLUME;
+ mSlopRatio = 0.25f;
+ mBufferUsage = GL_DYNAMIC_DRAW_ARB;
+ mImageEnabled = TRUE;
+}
+
+LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
+: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK)
+{
+ mDepthMask = FALSE;
+ mLODPeriod = 16;
+ mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
+ mPartitionType = LLPipeline::PARTITION_BRIDGE;
+
+ mBufferUsage = GL_DYNAMIC_DRAW_ARB;
+
+ mSlopRatio = 0.25f;
+}
+
+void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
+ {
+ return;
+ }
+
+ //add face to drawmap
+ std::vector<LLDrawInfo*>& draw_vec = group->mDrawMap[type];
+
+ S32 idx = draw_vec.size()-1;
+
+
+ BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT ||
+ type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE;
+ BOOL texanim = (type == LLRenderPass::PASS_SHINY) ? FALSE : facep->isState(LLFace::TEXTURE_ANIM);
+ U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0);
+
+ const LLMatrix4* tex_mat = NULL;
+ if (texanim)
+ {
+ LLVOVolume* volume = (LLVOVolume*) facep->getViewerObject();
+ tex_mat = volume->getTextureMatrix();
+ }
+
+ //LLViewerImage* tex = facep->mAppAngle < FORCE_SIMPLE_RENDER_ANGLE ? NULL : facep->getTexture();
+ LLViewerImage* tex = facep->getTexture();
+
+ if (idx >= 0 &&
+ draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer &&
+ draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
+ draw_vec[idx]->mTexture == tex &&
+ //draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
+ //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
+ draw_vec[idx]->mFullbright == fullbright &&
+ draw_vec[idx]->mBump == bump &&
+ draw_vec[idx]->mTextureMatrix == tex_mat)
+ {
+ draw_vec[idx]->mCount += facep->getIndicesCount();
+ draw_vec[idx]->mEnd += facep->getGeomCount();
+ draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
+ validate_draw_info(*draw_vec[idx]);
+ }
+ else
+ {
+ U32 start = facep->getGeomIndex();
+ U32 end = start + facep->getGeomCount()-1;
+ U32 offset = facep->getIndicesStart();
+ U32 count = facep->getIndicesCount();
+ LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex,
+ facep->mVertexBuffer, fullbright, bump);
+ draw_info->mVSize = facep->getVirtualSize();
+ draw_vec.push_back(draw_info);
+ draw_info->mReflectionMap = group->mReflectionMap;
+ draw_info->mTextureMatrix = tex_mat;
+ validate_draw_info(*draw_info);
+ }
}
+
+void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)
+{
+
+}
+
+void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
+{
+ if (group->changeLOD())
+ {
+ group->mLastUpdateDistance = group->mDistance;
+ }
+
+ group->mLastUpdateViewAngle = group->mViewAngle;
+
+ if (!group->isState(LLSpatialGroup::GEOM_DIRTY |
+ LLSpatialGroup::ALPHA_DIRTY))
+ {
+ return;
+ }
+
+ group->mBuilt = 1.f;
+ LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
+
+ LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
+
+ //find reflection map
+ if (group->mSpatialPartition->mImageEnabled)
+ {
+ if (group->mReflectionMap.isNull())
+ {
+ LLSpatialGroup* parent = group->getParent();
+ while (parent && group->mReflectionMap.isNull())
+ {
+ group->mReflectionMap = parent->mReflectionMap;
+ parent = parent->getParent();
+ }
+ }
+ }
+
+ group->clearDrawMap();
+
+ mFaceList.clear();
+
+ std::vector<LLFace*> alpha_faces;
+ U32 vertex_count = 0;
+ U32 index_count = 0;
+ U32 useage = group->mSpatialPartition->mBufferUsage;
+
+ //get all the faces into a list, putting alpha faces in their own list
+ for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
+ {
+ LLDrawable* drawablep = *drawable_iter;
+
+ if (drawablep->isDead())
+ {
+ continue;
+ }
+
+ if (drawablep->isAnimating())
+ { //fall back to stream draw for animating verts
+ useage = GL_STREAM_DRAW_ARB;
+ }
+
+ LLVOVolume* vobj = drawablep->getVOVolume();
+
+ //for each face
+ for (S32 i = 0; i < drawablep->getNumFaces(); i++)
+ {
+ //sum up face verts and indices
+ drawablep->updateFaceSize(i);
+ LLFace* facep = drawablep->getFace(i);
+ if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
+ {
+ const LLTextureEntry* te = facep->getTextureEntry();
+ LLViewerImage* tex = facep->getTexture();
+
+ BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA);
+ U32 type = gPipeline.getPoolTypeFromTE(te, tex);
+ if (type != LLDrawPool::POOL_ALPHA && force_simple)
+ {
+ type = LLDrawPool::POOL_SIMPLE;
+ }
+ facep->setPoolType(type);
+
+ if (vobj->isHUDAttachment())
+ {
+ facep->setState(LLFace::FULLBRIGHT);
+ }
+
+ if (vobj->mTextureAnimp)
+ {
+ if (vobj->mTextureAnimp->mFace <= -1)
+ {
+ S32 face;
+ for (face = 0; face < vobj->getNumTEs(); face++)
+ {
+ if (vobj->mTextureAnimp->mMode & LLViewerTextureAnim::ON)
+ {
+ drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM);
+ }
+ else
+ {
+ drawablep->getFace(face)->clearState(LLFace::TEXTURE_ANIM);
+ }
+ }
+ }
+ else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs())
+ {
+ drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM);
+ }
+ }
+
+ if (type == LLDrawPool::POOL_ALPHA)
+ {
+ vertex_count += facep->getGeomCount();
+ index_count += facep->getIndicesCount();
+ alpha_faces.push_back(facep);
+ }
+ else
+ {
+ if (drawablep->isState(LLDrawable::REBUILD_VOLUME))
+ {
+ facep->mLastUpdateTime = gFrameTimeSeconds;
+ }
+ mFaceList.push_back(facep);
+ }
+ }
+ else
+ { //face has no renderable geometry
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ //don't alpha wrap drawables that have only tiny tiny alpha faces
+ facep->setPoolType(LLDrawPool::POOL_SIMPLE);
+ }
+
+ vobj->updateTextures();
+ }
+ }
+
+ group->mVertexCount = vertex_count;
+ group->mIndexCount = index_count;
+ group->mBufferUsage = useage;
+
+ LLStrider<LLVector3> vertices;
+ LLStrider<LLVector3> normals;
+ LLStrider<LLVector2> texcoords2;
+ LLStrider<LLVector2> texcoords;
+ LLStrider<LLColor4U> colors;
+ LLStrider<U32> indices;
+
+ //PROCESS NON-ALPHA FACES
+ {
+ //sort faces by texture
+ std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareTextureAndTime());
+
+ std::vector<LLFace*>::iterator face_iter = mFaceList.begin();
+
+ LLSpatialGroup::buffer_map_t buffer_map;
+
+ while (face_iter != mFaceList.end())
+ {
+ //pull off next face
+ LLFace* facep = *face_iter;
+ LLViewerImage* tex = facep->getTexture();
+
+ U32 index_count = facep->getIndicesCount();
+ U32 geom_count = facep->getGeomCount();
+
+ //sum up vertices needed for this texture
+ std::vector<LLFace*>::iterator i = face_iter;
+ ++i;
+ while (i != mFaceList.end() && (*i)->getTexture() == tex)
+ {
+ facep = *i;
+ ++i;
+ index_count += facep->getIndicesCount();
+ geom_count += facep->getGeomCount();
+ }
+
+ //create/delete/resize vertex buffer if needed
+ LLVertexBuffer* buffer = NULL;
+ LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex);
+ if (found_iter != group->mBufferMap.end())
+ {
+ buffer = found_iter->second;
+ }
+
+ if (!buffer)
+ { //create new buffer if needed
+ buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
+ group->mBufferUsage);
+ buffer->allocateBuffer(geom_count, index_count, TRUE);
+ }
+ else
+ {
+ if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage)
+ {
+ buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
+ group->mBufferUsage);
+ buffer->allocateBuffer(geom_count, index_count, TRUE);
+ }
+ else
+ {
+ buffer->resizeBuffer(geom_count, index_count);
+ }
+ }
+
+ BOOL clean = TRUE;
+ buffer_map[tex] = buffer;
+
+ //add face geometry
+
+ //get vertex buffer striders
+ buffer->getVertexStrider(vertices);
+ buffer->getNormalStrider(normals);
+ buffer->getTexCoordStrider(texcoords);
+ buffer->getTexCoord2Strider(texcoords2);
+ buffer->getColorStrider(colors);
+ buffer->getIndexStrider(indices);
+
+ U32 indices_index = 0;
+ U32 index_offset = 0;
+
+ while (face_iter < i)
+ {
+ facep = *face_iter;
+ LLDrawable* drawablep = facep->getDrawable();
+ LLVOVolume* vobj = drawablep->getVOVolume();
+ LLVolume* volume = vobj->getVolume();
+
+ U32 te_idx = facep->getTEOffset();
+ facep->mIndicesIndex = indices_index;
+ facep->mGeomIndex = index_offset;
+ facep->mVertexBuffer = buffer;
+ {
+ if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices,
+ vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
+ {
+ clean = FALSE;
+ buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(),
+ facep->getIndicesStart(), facep->getIndicesCount());
+ }
+ }
+
+ indices_index += facep->mIndicesCount;
+
+ BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
+ BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
+ const LLTextureEntry* te = facep->getTextureEntry();
+
+ if (tex->getPrimaryFormat() == GL_ALPHA)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
+ }
+ else if (fullbright)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
+ }
+
+ facep->setPoolType(LLDrawPool::POOL_SIMPLE);
+
+ if (te->getShiny())
+ {
+ registerFace(group, facep, LLRenderPass::PASS_SHINY);
+ }
+
+ if (!force_simple && te->getBumpmap())
+ {
+ registerFace(group, facep, LLRenderPass::PASS_BUMP);
+ }
+
+ ++face_iter;
+ }
+
+ if (clean)
+ {
+ buffer->markClean();
+ }
+ }
+
+ group->mBufferMap.clear();
+ for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i)
+ {
+ group->mBufferMap[i->first] = i->second;
+ }
+ }
+
+ //PROCESS ALPHA FACES
+ if (!alpha_faces.empty())
+ {
+ //sort alpha faces by distance
+ std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater());
+
+ //store alpha faces in root vertex buffer
+ if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage()))
+ {
+ group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
+ group->mBufferUsage);
+ group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true);
+ stop_glerror();
+ }
+ else
+ {
+ group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount);
+ stop_glerror();
+ }
+
+ //get vertex buffer striders
+ LLVertexBuffer* buffer = group->mVertexBuffer;
+
+ BOOL clean = TRUE;
+
+ buffer->getVertexStrider(vertices);
+ buffer->getNormalStrider(normals);
+ buffer->getTexCoordStrider(texcoords);
+ buffer->getTexCoord2Strider(texcoords2);
+ buffer->getColorStrider(colors);
+ buffer->getIndexStrider(indices);
+
+ U32 index_offset = 0;
+ U32 indices_index = 0;
+
+ for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i)
+ {
+ LLFace* facep = *i;
+ LLDrawable* drawablep = facep->getDrawable();
+ LLVOVolume* vobj = drawablep->getVOVolume();
+ LLVolume* volume = vobj->getVolume();
+
+ U32 te_idx = facep->getTEOffset();
+ facep->mIndicesIndex = indices_index;
+ facep->mGeomIndex = index_offset;
+ facep->mVertexBuffer = group->mVertexBuffer;
+ if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices,
+ vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
+ {
+ clean = FALSE;
+ buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(),
+ facep->getIndicesStart(), facep->getIndicesCount());
+ }
+
+ indices_index += facep->mIndicesCount;
+
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+
+ if (clean)
+ {
+ buffer->markClean();
+ }
+ }
+ else
+ {
+ group->mVertexBuffer = NULL;
+ }
+
+ //get all the faces into a list, putting alpha faces in their own list
+ for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
+ {
+ LLDrawable* drawablep = *drawable_iter;
+ drawablep->clearState(LLDrawable::REBUILD_ALL);
+ }
+
+ group->mLastUpdateTime = gFrameTimeSeconds;
+ group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY |
+ LLSpatialGroup::ALPHA_DIRTY);
+
+ mFaceList.clear();
+}
+
+void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
+{
+ //initialize to default usage for this partition
+ U32 usage = group->mSpatialPartition->mBufferUsage;
+
+ //clear off any old faces
+ mFaceList.clear();
+
+ //for each drawable
+ for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
+ {
+ LLDrawable* drawablep = *drawable_iter;
+
+ if (drawablep->isDead())
+ {
+ continue;
+ }
+
+ if (drawablep->isAnimating())
+ { //fall back to stream draw for animating verts
+ usage = GL_STREAM_DRAW_ARB;
+ }
+
+ //for each face
+ for (S32 i = 0; i < drawablep->getNumFaces(); i++)
+ {
+ //sum up face verts and indices
+ drawablep->updateFaceSize(i);
+ LLFace* facep = drawablep->getFace(i);
+ if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
+ {
+ vertex_count += facep->getGeomCount();
+ index_count += facep->getIndicesCount();
+
+ //remember face (for sorting)
+ mFaceList.push_back(facep);
+ }
+ else
+ {
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ }
+ }
+ }
+
+ group->mBufferUsage = usage;
+}
+
+LLHUDPartition::LLHUDPartition()
+{
+ mPartitionType = LLPipeline::PARTITION_HUD;
+ mDrawableType = LLPipeline::RENDER_TYPE_HUD;
+ mSlopRatio = 0.f;
+ mLODPeriod = 16;
+}
+
+void LLHUDPartition::shift(const LLVector3 &offset)
+{
+ //HUD objects don't shift with region crossing. That would be silly.
+}
+
+
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 26764d62c9..f36c367f52 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -10,6 +10,7 @@
#define LL_LLVOVOLUME_H
#include "llviewerobject.h"
+#include "llspatialpartition.h"
#include "llviewerimage.h"
#include "llframetimer.h"
#include "llapr.h"
@@ -41,7 +42,8 @@ public:
virtual bool isVolumeGlobal() const = 0; // Are we in global space?
virtual bool isActive() const = 0; // Is this object currently active?
virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0;
- virtual void updateRelativeXform(BOOL global_volume = FALSE) = 0;
+ virtual void updateRelativeXform() = 0;
+ virtual U32 getID() const = 0;
};
// Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME)
@@ -50,17 +52,24 @@ class LLVOVolume : public LLViewerObject
public:
static void initClass();
static void preUpdateGeom();
- static F32 getTextureVirtualSize(const LLFace* face);
-
- BOOL mWereAllTEsSame;
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD2) |
+ (1 << LLVertexBuffer::TYPE_COLOR)
+ }
+ eVertexDataMask;
+
public:
LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
virtual ~LLVOVolume();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
- void deleteFaces(LLVOVolume* childp);
+ void deleteFaces();
/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
@@ -71,12 +80,12 @@ public:
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
- BOOL getAllTEsSame() const { return mAllTEsSame; }
F32 getIndividualRadius() { return mRadius; }
S32 getLOD() const { return mLOD; }
const LLVector3 getPivotPositionAgent() const;
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
+ const LLMatrix4* getTextureMatrix() const { return &mTextureMatrix; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, LLVector3& end) const;
@@ -86,6 +95,7 @@ public:
BOOL getVolumeChanged() const { return mVolumeChanged; }
+ F32 getTextureVirtualSize(LLFace* face);
/*virtual*/ F32 getRadius() const { return mVObjRadius; };
const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
@@ -101,6 +111,7 @@ public:
U32 block_num, const EObjectUpdateType update_type,
LLDataPacker *dp);
+ /*virtual*/ void setSelected(BOOL sel);
/*virtual*/ BOOL setDrawableParent(LLDrawable* parentp);
/*virtual*/ void setScale(const LLVector3 &scale, BOOL damped);
@@ -121,17 +132,19 @@ public:
void setTexture(const S32 face);
/*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
- void updateRelativeXform(BOOL global_volume = FALSE);
+ void updateRelativeXform();
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ /*virtual*/ void updateFaceSize(S32 idx);
/*virtual*/ BOOL updateLOD();
void updateRadius();
/*virtual*/ void updateTextures(LLAgent &agent);
- void updateTextures(S32 lod);
+ void updateTextures();
void updateFaceFlags();
void regenFaces();
- BOOL genTriangles(BOOL force_global);
+ BOOL genBBoxes(BOOL force_global);
virtual void updateSpatialExtents(LLVector3& min, LLVector3& max);
+ virtual F32 getBinRadius();
virtual void writeCAL3D(apr_file_t* fp,
std::string& path,
std::string& file_base,
@@ -142,6 +155,9 @@ public:
S32& texture_index,
std::multimap<LLUUID, LLMaterialExportInfo*>& material_map);
+
+ virtual U32 getPartitionType() const;
+
// For Lights
void setIsLight(BOOL is_light);
void setLightColor(const LLColor3& color);
@@ -159,6 +175,7 @@ public:
F32 getLightDistance(const LLVector3& pos) const; // returns < 0 if inside radius
// Flexible Objects
+ U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;
BOOL isVolumeGlobal() const;
BOOL canBeFlexible() const;
@@ -169,27 +186,26 @@ public:
BOOL updateLighting(BOOL do_lighting);
protected:
- F32 computeLODProfilePathComplexityBias();
S32 computeLODDetail(F32 distance, F32 radius);
BOOL calcLOD();
- void setupSingleFace(S32 face_offset); // Set up the face for combined volumes.
LLFace* addFace(S32 face_index);
void updateTEData();
- BOOL calcAllTEsSame();
public:
LLViewerTextureAnim *mTextureAnimp;
+ U8 mTexAnimMode;
protected:
friend class LLDrawable;
- BOOL mAllTEsSame; // All TE's have the same pool/texture
BOOL mFaceMappingChanged;
BOOL mGlobalVolume;
BOOL mInited;
+ LLFrameTimer mTextureUpdateTimer;
S32 mLOD;
BOOL mLODChanged;
F32 mRadius;
+ LLMatrix4 mTextureMatrix;
LLMatrix4 mRelativeXform;
LLMatrix3 mRelativeXformInvTrans;
BOOL mVolumeChanged;
@@ -199,8 +215,6 @@ protected:
// statics
public:
static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop
- static F32 sLODComplexityDistanceBias; // Changing this to zero makes all prims LOD at the same distance,
- // regardless of complexity
static F32 sLODFactor; // LOD scale factor
static F32 sDistanceFactor; // LOD distance factor
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 135873b5b8..abff230c4e 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -45,22 +45,8 @@ const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
const F32 g = 9.81f; // gravitational constant (m/s^2)
-///////////////////////////////////
-
-LLWaterSurface::LLWaterSurface() :
- mInitialized(FALSE),
- mWind(9, 0, 0),
- mA(0.2f),
- mVisc(0.001f),
- mShininess(8.0f)
-{}
-
-
-LLWaterGrid *LLVOWater::sGrid = 0;
-
-
LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLViewerObject(id, LL_VO_WATER, regionp)
+: LLStaticViewerObject(id, LL_VO_WATER, regionp)
{
// Terrain must draw during selection passes so it can block objects behind it.
mbCanSelect = FALSE;
@@ -94,18 +80,6 @@ void LLVOWater::updateTextures(LLAgent &agent)
{
}
-// virtual
-void LLVOWater::updateDrawable(BOOL force_damped)
-{
- // Force an immediate rebuild on any update
- if (mDrawable.notNull())
- {
- gPipeline.updateMoveNormalAsync(mDrawable);
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
- }
- clearChanged(SHIFTED);
-}
-
// Never gets called
BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
@@ -142,17 +116,13 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
{
- return updateGeometryFlat(drawable);
-}
-
-
-BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
-{
+ LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
LLFace *face;
if (drawable->getNumFaces() < 1)
{
- drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL);
+ LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
+ drawable->addFace(poolp, NULL);
}
face = drawable->getFace(0);
@@ -161,15 +131,26 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
LLStrider<LLVector3> verticesp, normalsp;
LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
+ LLStrider<U32> indicesp;
S32 index_offset;
S32 size = 16;
- S32 num_quads = size*size;
-
- face->setPrimType(LLTriangles);
- face->setSize(4*num_quads, 6*num_quads);
+ if (face->mVertexBuffer.isNull())
+ {
+ S32 num_quads = size*size;
+ face->setSize(4*num_quads, 6*num_quads);
+
+ face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
+ face->mVertexBuffer->allocateBuffer(4*num_quads, 6*num_quads, TRUE);
+ face->setIndicesIndex(0);
+ face->setGeomIndex(0);
+ }
+ else
+ {
+ face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
+ }
+
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
{
@@ -179,6 +160,7 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
LLVector3 position_agent;
position_agent = getPositionAgent();
face->mCenterAgent = position_agent;
+ face->mCenterLocal = position_agent;
S32 x, y;
F32 step_x = getScale().mV[0] / size;
@@ -237,378 +219,20 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
*indicesp++ = toffset + 2;
}
}
-
-
- mDrawable->movePartition();
- LLPipeline::sCompiles++;
- return TRUE;
-}
-
-
-BOOL LLVOWater::updateGeometryHeightFieldRoam(LLDrawable *drawable)
-{
- LLVector3 position_agent = getPositionAgent();
- const LLVector3 region_size = getScale();
- const LLVector3 region_origin = position_agent - region_size * 0.5f;
-
- S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth;
- S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth;
- S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth;
- S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth;
-
- static S32 res = (S32)sGrid->mPatchRes;
- if (patch_origx < 0)
- {
- patch_dimx -= - patch_origx;
- if (patch_dimx < 1)
- {
- return TRUE;
- }
- patch_origx = 0;
- }
- if (patch_origy < 0)
- {
- patch_dimy -= - patch_origy;
- if (patch_dimy < 1)
- {
- return TRUE;
- }
- patch_origy = 0;
- }
- if (patch_origx >= res)
- {
- return TRUE;
- }
- if (patch_origy >= res)
- {
- return TRUE;
- }
-
- patch_dimx = llmin<U32>(patch_dimx, res - patch_origx);
- patch_dimy = llmin<U32>(patch_dimy, res - patch_origy);
-
- U32 num_of_tris = 0;
- S32 px, py;
- for (py = patch_origy; py < patch_origy + patch_dimy; py++)
- {
- for (px = patch_origx; px < patch_origx + patch_dimx; px++)
- {
- const U32 ind = py * sGrid->mPatchRes + px;
- if (sGrid->mPatches[ind].visible() && sGrid->mTab[px][py] == 0)
- {
- num_of_tris += sGrid->mPatches[ind].numTris();
- sGrid->mTab[px][py] = this;
- }
- }
- }
-
- if (num_of_tris == 0)
- {
- return TRUE;
- }
-
- if (drawable->getNumFaces() < 1)
- {
- drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER),
- gWorldp->getDefaultWaterTexture());
- }
-
- LLFace *face;
-
- face = drawable->getFace(0);
- face->mCenterAgent = position_agent;
-
- LLStrider<LLVector3> verticesp, normalsp;
- LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
- S32 index_offset;
-
- const F32 water_height = getRegion()->getWaterHeight();
-
- face->setPrimType(LLTriangles);
- face->setSize(3 * num_of_tris, 3 * num_of_tris);
- index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == index_offset)
- {
- return TRUE;
- }
-
- U32 num_of_vtx = 0;
-
- for (py = patch_origy; py < patch_origy + patch_dimy; py++)
- {
- for (px = patch_origx; px < patch_origx + patch_dimx; px++)
- {
- for (U8 h = 0; h < 2; h++)
- {
- const U32 ind = py * sGrid->mPatchRes + px;
- if (!sGrid->mPatches[ind].visible() || sGrid->mTab[px][py] != this)
- continue;
- LLWaterTri* half = (LLWaterTri*) sGrid->mPatches[ind].half(h);
- for (const LLWaterTri* tri = (LLWaterTri*) half->getFirstLeaf();
- tri != NULL;
- tri = (LLWaterTri*) tri->getNextLeaf())
- {
- /////// check for coordinates
- *(verticesp++) = sGrid->vtx(tri->Lvtx(), water_height);
- *(verticesp++) = sGrid->vtx(tri->Rvtx(), water_height);
- *(verticesp++) = sGrid->vtx(tri->Tvtx(), water_height);
-
- *(normalsp++) = sGrid->norm(tri->Lvtx());
- *(normalsp++) = sGrid->norm(tri->Rvtx());
- *(normalsp++) = sGrid->norm(tri->Tvtx());
-
- *(indicesp++) = index_offset + num_of_vtx + 0;
- *(indicesp++) = index_offset + num_of_vtx + 1;
- *(indicesp++) = index_offset + num_of_vtx + 2;
- num_of_vtx += 3;
- }
- }
- }
- }
-
-
- LLPipeline::sCompiles++;
- return TRUE;
-}
-
-
-
-BOOL LLVOWater::updateGeometryHeightFieldSimple(LLDrawable *drawable)
-{
- LLVector3 position_agent = getPositionAgent();
- const LLVector3 region_size = getScale();
- const LLVector3 region_origin = position_agent - region_size * 0.5f;
-
- S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth;
- S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth;
- S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth;
- S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth;
-
- static S32 res = sGrid->mPatchRes;
- if (patch_origx < 0)
- {
- patch_dimx -= - patch_origx;
- if (patch_dimx < 1)
- {
- return TRUE;
- }
- patch_origx = 0;
- }
- if (patch_origy < 0)
- {
- patch_dimy -= - patch_origy;
- if (patch_dimy < 1)
- {
- return TRUE;
- }
- patch_origy = 0;
- }
- if (patch_origx >= res)
- {
- return TRUE;
- }
- if (patch_origy >= res)
- {
- return TRUE;
- }
-
- patch_dimx = llmin<U32>(patch_dimx, res - patch_origx);
- patch_dimy = llmin<U32>(patch_dimy, res - patch_origy);
-
-
- U32 num_of_regions = 0;
- S32 px, py;
-
- for (py = patch_origy; py < patch_origy + patch_dimy; py++)
- {
- for (px = patch_origx; px < patch_origx + patch_dimx; px++)
- {
- // if (sGrid->mTab[px][py] != 0)
- // bool stop = true;
- if (sGrid->mPatches[py * sGrid->mPatchRes + px].visible() && sGrid->mTab[px][py] == 0)
- {
- num_of_regions++;
- sGrid->mTab[px][py] = this;
- }
- }
- }
-
- if (num_of_regions == 0)
- {
- return TRUE;
- }
-
- if (drawable->getNumFaces() < 1)
- {
- drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER),
- gWorldp->getDefaultWaterTexture());
- }
-
- LLFace *face;
-
- face = drawable->getFace(0);
- face->mCenterAgent = position_agent;
-
- LLStrider<LLVector3> verticesp, normalsp;
- LLStrider<LLVector2> texCoordsp;
- U32 *indicesp;
- S32 index_offset;
-
- const F32 water_height = getRegion()->getWaterHeight();
-
- const U32 steps_in_region = sGrid->mStepsInRegion / sGrid->mResDecrease;
- const U32 num_quads = steps_in_region * steps_in_region * num_of_regions;
-
- face->setPrimType(LLTriangles);
- face->setSize(4*num_quads, 6*num_quads);
- index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == index_offset)
- {
- return TRUE;
- }
-
- U32 num_of_vtx = 0;
-
- for (py = patch_origy; py < patch_origy + patch_dimy; py++)
- {
- for (px = patch_origx; px < patch_origx + patch_dimx; px++)
- {
- if (!sGrid->mPatches[py * sGrid->mPatchRes + px].visible() || sGrid->mTab[px][py] != this)
- {
- continue;
- }
-
- U32 orig_indx = px * sGrid->mStepsInRegion;
- U32 orig_indy = py * sGrid->mStepsInRegion;
-
- for (U32 qy = 0; qy < steps_in_region; qy++)
- {
- for (U32 qx = 0; qx < steps_in_region; qx++)
- {
- const S32 x0 = orig_indx + qx * sGrid->mResDecrease;
- const S32 y0 = orig_indy + qy * sGrid->mResDecrease;
- const S32 x1 = x0 + sGrid->mResDecrease;
- const S32 y1 = y0 + sGrid->mResDecrease;
-
- sGrid->setVertex(x0, y1, water_height, *(verticesp));
- verticesp++;
- sGrid->setVertex(x0, y0, water_height, *(verticesp));
- verticesp++;
- sGrid->setVertex(x1, y1, water_height, *(verticesp));
- verticesp++;
- sGrid->setVertex(x1, y0, water_height, *(verticesp));
- verticesp++;
- /*
- *(verticesp++) = sGrid->vtx(x0, y1, water_height);
- *(verticesp++) = sGrid->vtx(x0, y0, water_height);
- *(verticesp++) = sGrid->vtx(x1, y1, water_height);
- *(verticesp++) = sGrid->vtx(x1, y0, water_height);
- */
- *(normalsp++) = sGrid->norm(x0, y1);
- *(normalsp++) = sGrid->norm(x0, y0);
- *(normalsp++) = sGrid->norm(x1, y1);
- *(normalsp++) = sGrid->norm(x1, y0);
-
- const S32 curr_index_offset = index_offset + num_of_vtx;
-
- *indicesp++ = curr_index_offset + 0;
- *indicesp++ = curr_index_offset + 1;
- *indicesp++ = curr_index_offset + 2;
-
- *indicesp++ = curr_index_offset + 1;
- *indicesp++ = curr_index_offset + 3;
- *indicesp++ = curr_index_offset + 2;
- num_of_vtx += 4;
- }
- }
- }
- }
-
-
+ mDrawable->movePartition();
LLPipeline::sCompiles++;
return TRUE;
}
void LLVOWater::initClass()
{
- sGrid = new LLWaterGrid;
}
void LLVOWater::cleanupClass()
{
- if (sGrid)
- {
- sGrid->cleanup();
- delete sGrid;
- sGrid = 0;
- }
-}
-
-
-LLWaterGrid::LLWaterGrid() : mResIncrease(1)//0.5)
-{
- init();
}
-
-void LLWaterGrid::init()
-{
- //mRegionOrigin = LLVector3(-2 * mRegionWidth, -2 * mRegionWidth, 0);
- mRegionWidth = 256;
- mPatchRes = 5;
- mMaxGridSize = mPatchRes * mRegionWidth;
- mMinStep = (U32)(WAVE_STEP * mResIncrease);
-
- LLWaterTri::sMinStep = mMinStep;
- LLWaterTri::sQueues = &mRoam;
-
- setGridDim(mMaxGridSize / mMinStep);
-
- mVtx = new LLVector3[mGridDim1 * mGridDim1];
- mNorms = new LLVector3[mGridDim1 * mGridDim1];
-
- mPatches = new LLWaterPatch[mPatchRes * mPatchRes];
-
- mStepsInRegion = mRegionWidth / mMinStep;
- const U32 max_div_level = 2 * (U32)(log((F32)mStepsInRegion) / log(2.0f));
-
- for (U32 y = 0; y < mPatchRes; y++)
- {
- for (U32 x = 0; x < mPatchRes; x++)
- {
- LLVector3 patch_center(mRegionWidth * (x + 0.5f), mRegionWidth * (y + 0.5f), 0);
-
- mPatches[y * mPatchRes + x].set(x * mStepsInRegion, y * mStepsInRegion,
- mStepsInRegion, mRegionWidth, patch_center, max_div_level);
- if (x > 0)
- {
- mPatches[y * mPatchRes + x].left()->setRight(mPatches[y * mPatchRes + x - 1].right());
- mPatches[y * mPatchRes + x - 1].right()->setRight(mPatches[y * mPatchRes + x].left());
- }
- if (y > 0)
- {
- mPatches[y * mPatchRes + x].left()->setLeft(mPatches[(y - 1) * mPatchRes + x].right());
- mPatches[(y - 1) * mPatchRes + x].right()->setLeft(mPatches[y * mPatchRes + x].left());
- }
- }
- }
-}
-
-void LLWaterGrid::cleanup()
-{
- delete[] mVtx;
- mVtx = NULL;
-
- delete[] mNorms;
- mNorms = NULL;
-
- delete[] mPatches;
- mPatches = NULL;
-}
-
-
void setVecZ(LLVector3& v)
{
v.mV[VX] = 0;
@@ -616,413 +240,31 @@ void setVecZ(LLVector3& v)
v.mV[VZ] = 1;
}
-void LLWaterGrid::update()
-{
- static LLViewerRegion* prev_region = gAgent.getRegion();
- LLViewerRegion* region = gAgent.getRegion();
-
- mRegionOrigin = region->getOriginAgent();
- mRegionOrigin.mV[VX] -= 2 * mRegionWidth;
- mRegionOrigin.mV[VY] -= 2 * mRegionWidth;
- mRegionOrigin.mV[VZ] = 0;
-
- const F32 clip_far = gCamera->getFar() - 31;
- const F32 clip_far2 = clip_far * clip_far;
-
- const LLVector3 camera_pos = gAgent.getCameraPositionAgent();
- const LLVector3 look_at = gCamera->getAtAxis();
-
-
- if (camera_pos.mV[VZ] > 200)
- {
- mResDecrease = 4;
- }
- else if (camera_pos.mV[VZ] > 100)
- {
- mResDecrease = 2;
- }
- else
- {
- mResDecrease = 1;
- }
-
-
- //U32 mResDecrease = res_decrease;
- U32 res_decrease = 1;
-
- const F32 res_change = mResIncrease;// * res_decrease ;
-
- F32 height;
-
- // Set the grid
-
- //U32 fractions = 1;
- U32 fractions_res = res_decrease;
- if (res_change < 1)
- {
- //fractions = llround(1. / res_change);
- fractions_res = llround(1.f / mResIncrease);
- }
-
-
- //const U32 fractions_res = fractions * res_decrease;
-
- LLVector3 cur_pos;
- U32 x, y;
- U32 ind = 0;
- for (y = 0; y < mGridDim1; y += fractions_res)
- {
- const F32 dispy = (F32)(y * mMinStep);//step;
- for (x = 0; x < mGridDim1; x += fractions_res)
- {
- const F32 dispx = (F32)(x * mMinStep);//step;
- cur_pos = mRegionOrigin;
- cur_pos.mV[VX] += dispx;
- cur_pos.mV[VY] += dispy;
-
- const F32 x_dist = cur_pos.mV[VX] - camera_pos.mV[VX];
- const F32 y_dist = cur_pos.mV[VY] - camera_pos.mV[VY];
-
- if (x_dist * look_at.mV[VX] + y_dist * look_at.mV[VY] < 0)
- {
- mVtx[ind] = cur_pos;
- setVecZ(mNorms[ind]);
- ind++;
- continue;
- }
-
- const F32 dist_to_vtx2 = x_dist * x_dist + y_dist * y_dist;
- if (dist_to_vtx2 > .81 * clip_far2)
- {
- mVtx[ind] = cur_pos;
- setVecZ(mNorms[ind]);
- ind++;
- continue;
- }
-
- mWater.getIntegerHeightAndNormal(llround(WAVE_STEP_INV * dispx),
- llround(WAVE_STEP_INV * dispy), height, mNorms[ind]);
-
- cur_pos.mV[VZ] += height;
- mVtx[ind] = cur_pos;
- ind++;
- }
- }
-
- if (res_change < 1)
- {
- U32 fractions = llround(1.f / mResIncrease);
- for (y = 0; y < mGridDim1; y += fractions_res)
- {
- for (x = 0; x < mGridDim; x += fractions_res)
- {
- const U32 ind00 = index(x, y);
- const U32 ind01 = ind00 + fractions_res;
- for (U32 frx = 1; frx < fractions; frx += res_decrease)
- {
- const U32 ind = ind00 + frx;
- mNorms[ind] = LERP(mNorms[ind00], mNorms[ind01], frx * res_change);
- mVtx[ind] = LERP( mVtx[ind00], mVtx[ind01], frx * res_change);
- }
- }
- }
- for (x = 0; x < mGridDim1; x += res_decrease)
- {
- for (y = 0; y < mGridDim; y += fractions_res)
- {
- const U32 ind00 = index(x, y);
- const U32 ind10 = ind00 + fractions_res * mGridDim1;//(y + fractions) * quad_resx1 + x;
- for (U32 fry = 1; fry < fractions; fry += res_decrease)
- {
- const U32 ind = ind00 + fry * mGridDim1;//(y + fry) * quad_resx1 + x;
- mNorms[ind] = LERP(mNorms[ind00], mNorms[ind10], fry * res_change);
- mVtx[ind] = LERP( mVtx[ind00], mVtx[ind10], fry * res_change);
- }
- }
- }
- }
-
- if (gUseRoam)
- {
- updateTree(camera_pos, look_at, clip_far, prev_region != region);
- }
- else
- {
- updateVisibility(camera_pos, look_at, clip_far);
- }
-
- prev_region = region;
-
-
- //mTab[0][0] = 0;
- for (y = 0; y < mPatchRes; y++)
- {
- for (x = 0; x < mPatchRes; x++)
- mTab[x][y] = 0;
- }
-
-}
-
-void LLWaterGrid::updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far,
- BOOL restart = FALSE)
-{
- static S8 recalculate_frame = 0;
-
- if (restart)
- {
- recalculate_frame = 0;
- }
-
- if (recalculate_frame == 0)
- {
- LLWaterTri::nextRound();
- setCamPosition(LLWaterTri::sCam, camera_pos);
- LLWaterTri::sClipFar = clip_far;
-
-
- const U32 step = (U32)(WAVE_STEP * mResIncrease * mResDecrease);
- const U32 steps_in_region = mRegionWidth / step;
- LLWaterTri::sMaxDivLevel = 2 * llround(log((F32)steps_in_region) / log(2.0f));
-
- for (U32 y = 0; y < mPatchRes; y++)
- {
- for (U32 x = 0; x < mPatchRes; x++)
- {
- U32 patch_ind = y * mPatchRes + x;
- mPatches[patch_ind].updateTree(camera_pos, look_at, mRegionOrigin);
- }
- }
-
- mRoam.process();
-
- // debug
- /*
- for (y = 0; y < mPatchRes; y++)
- {
- for (U32 x = 0; x < mPatchRes; x++)
- {
- //mPatches[y * mPatchRes + x].checkUpToDate();
- //mPatches[y * mPatchRes + x].checkConsistensy();
- mPatches[y * mPatchRes + x].checkCount();
- }
- }
- */
- }
- ++recalculate_frame;
- recalculate_frame = recalculate_frame % 2;
-}
-
-void LLWaterGrid::updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far)
-{
- for (U32 y = 0; y < mPatchRes; y++)
- {
- for (U32 x = 0; x < mPatchRes; x++)
- {
- mPatches[y * mPatchRes + x].updateVisibility(camera_pos, look_at, mRegionOrigin);
- }
- }
-}
-
-
void LLVOWater::setUseTexture(const BOOL use_texture)
{
mUseTexture = use_texture;
}
-F32 LLWaterSurface::agentDepth() const
+void LLVOWater::updateSpatialExtents(LLVector3 &newMin, LLVector3& newMax)
{
- const LLViewerRegion* region = gAgent.getRegion();
- LLVector3 position_agent = region->getOriginAgent();// getPositionAgent();
- const LLVector3 region_origin = position_agent;
- const LLVector3 camera_pos = gAgent.getCameraPositionAgent();
+ LLVector3 pos = getPositionAgent();
+ LLVector3 scale = getScale();
- F32 height;
- LLVector3 normal;
+ newMin = pos - scale * 0.5f;
+ newMax = pos + scale * 0.5f;
- getHeightAndNormal(WAVE_STEP_INV * camera_pos.mV[VX],
- WAVE_STEP_INV * camera_pos.mV[VY], height, normal);
- F32 agent_water_height = gAgent.getRegion()->getWaterHeight();
- return camera_pos.mV[VZ] - (agent_water_height + height);
+ mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
}
-////////////////////////////////////////////////
-
-
-void LLWaterSurface::getHeightAndNormal(F32 i, F32 j, F32& wave_height, LLVector3& normal) const
-{
- S32 i_ind = llfloor(i);
- S32 j_ind = llfloor(j);
- F32 i_fr = i - i_ind;
- F32 j_fr = j - j_ind;
-
- i_ind = i_ind % N_RES;
- j_ind = j_ind % N_RES;
-
- S32 i_ind_next = i_ind + 1;
- S32 j_ind_next = j_ind + 1;
- if (i_ind_next == (S32)N_RES) i_ind_next = 0;
- if (j_ind_next == (S32)N_RES) j_ind_next = 0;
-
- const F32 i_fr1 = 1 - i_fr;
- const F32 j_fr1 = 1 - j_fr;
-
- const F32 hi0 = i_fr1 * height(i_ind, j_ind) + i_fr * height(i_ind_next, j_ind);
- const F32 hi1 = i_fr1 * height(i_ind, j_ind_next) + i_fr * height(i_ind_next, j_ind_next);
- wave_height = j_fr1 * hi0 + j_fr * hi1;
-
- normal = i_fr1 * mNorms[i_ind][j_ind];
- normal += i_fr * mNorms[i_ind_next][j_ind];
- LLVector3 vi1 = i_fr1 * mNorms[i_ind][j_ind_next];
- vi1 += i_fr * mNorms[i_ind_next][j_ind_next];
- normal *= j_fr1;
- normal += j_fr * vi1;
-
- //normal.normVec();
-}
-
-void LLWaterSurface::getIntegerHeightAndNormal(S32 i, S32 j, F32& wave_height, LLVector3& normal) const
-{
- S32 i_ind = i % N_RES;
- S32 j_ind = j % N_RES;
-
- wave_height = height(i_ind, j_ind);
- normal = mNorms[i_ind][j_ind];
+U32 LLVOWater::getPartitionType() const
+{
+ return LLPipeline::PARTITION_WATER;
}
-F32 LLWaterSurface::phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small)
+LLWaterPartition::LLWaterPartition()
+: LLSpatialPartition(0)
{
- F32 k2 = k * k;
- F32 k_dot_wind = k * wind_n;
- F32 spectrum = mA * (F32) exp(-1 / (L * L * k2)) / (k2 * k2) * (k_dot_wind * k_dot_wind / k2);
-
- if (k_dot_wind < 0) spectrum *= .25f; // scale down waves that move opposite to the wind
-
- F32 damp = (F32) exp(- k2 * L_small * L_small);
-
- return (spectrum * damp);
+ mRenderByGroup = FALSE;
+ mDrawableType = LLPipeline::RENDER_TYPE_WATER;
+ mPartitionType = LLPipeline::PARTITION_WATER;
}
-
-
-
-void LLWaterSurface::initAmplitudes()
-{
- U16 i, j;
- LLVector2 k;
- F32 sqrtPhillips;
-
- const LLVector2 wind(mWind.mV);
-
- LLVector2 wind_n = wind;
- const F32 wind_vel = wind_n.normVec();
-
- const F32 L = wind_vel * wind_vel / g; // largest wave arising from constant wind of speed wind_vel
-
- const F32 L_small = L / 70; // eliminate waves with very small length (L_small << L)
-
-
- for (i = 0; i <= N_RES; i++)
- {
- k.mV[VX] = (- (S32)N_RES_HALF + i) * (F_TWO_PI / WIDTH);
- for (j = 0; j <= N_RES; j++)
- {
- k.mV[VY] = (- (S32)N_RES_HALF + j) * (F_TWO_PI / WIDTH);
-
- const F32 k_mag = k.magVec();
- mOmega[i][j] = (F32) sqrt(g * k_mag);
-
- if (k_mag < F_APPROXIMATELY_ZERO)
- sqrtPhillips = 0;
- else
- sqrtPhillips = (F32) sqrt(phillips(k, wind_n, L, L_small));
-
- //const F32 r1 = rand() / (F32) RAND_MAX;
- //const F32 r2 = rand() / (F32) RAND_MAX;
- const F32 r1 = randGauss(0, 1);
- const F32 r2 = randGauss(0, 1);
-
- mHtilda0[i][j].re = sqrtPhillips * r1 * OO_SQRT2;
- mHtilda0[i][j].im = sqrtPhillips * r2 * OO_SQRT2;
-
- }
- }
-
- mPlan.init(N_RES, N_RES);
- mInitialized = 1; // initialization complete
-}
-
-void LLWaterSurface::generateWaterHeightField(F64 t)
-{
- S32 i, j;
- S32 mi, mj; // -K indices
- COMPLEX plus, minus;
-
- if (!mInitialized) initAmplitudes();
-
- for (i = 0; i < (S32)N_RES_HALF; i++)
- {
- mi = N_RES - i;
- for (j = 0; j < (S32)N_RES ; j++)
- {
- mj = N_RES - j;
-
- const F32 cos_wt = cosf(mOmega[i][j] * t); // = cos(-mOmega[i][j] * t)
- const F32 sin_wt = sinf(mOmega[i][j] * t); // = -sin(-mOmega[i][j] * t)
- plus.re = mHtilda0[i][j].re * cos_wt - mHtilda0[i][j].im * sin_wt;
- plus.im = mHtilda0[i][j].re * sin_wt + mHtilda0[i][j].im * cos_wt;
- minus.re = mHtilda0[mi][mj].re * cos_wt - mHtilda0[mi][mj].im * sin_wt;
- minus.im = -mHtilda0[mi][mj].re * sin_wt - mHtilda0[mi][mj].im * cos_wt;
-
- // now sum the plus and minus waves to get the total wave amplitude h
- mHtilda[i * N_RES + j].re = plus.re + minus.re;
- mHtilda[i * N_RES + j].im = plus.im + minus.im;
- if (mi < (S32)N_RES && mj < (S32)N_RES)
- {
- mHtilda[mi * N_RES + mj].re = plus.re + minus.re;
- mHtilda[mi * N_RES + mj].im = -plus.im - minus.im;
- }
- }
- }
-
- inverse_fft(mPlan, mHtilda, N_RES, N_RES);
-
- calcNormals();
-}
-
-
-/*
- * Computer normals by taking finite differences.
- */
-
-void LLWaterSurface::calcNormals()
-{
- LLVector3 n;
-
- for (U32 i = 0; i < N_RES; i++)
- {
- for (U32 j = 0; j < N_RES; j++)
- {
- F32 px = heightWrapped(i + 1, j);
- F32 mx = heightWrapped(i - 1, j);
- F32 py = heightWrapped(i, j + 1);
- F32 my = heightWrapped(i, j - 1);
- F32 pxpy = heightWrapped(i + 1, j + 1);
- F32 pxmy = heightWrapped(i + 1, j - 1);
- F32 mxpy = heightWrapped(i - 1, j + 1);
- F32 mxmy = heightWrapped(i - 1, j - 1);
-
- n.mV[VX] = -((2 * px + pxpy + pxmy) - (2 * mx + mxpy + mxmy));
- n.mV[VY] = -((2 * py + pxpy + mxpy) - (2 * my + pxmy + mxmy));
- n.mV[VZ] = 8 * WIDTH / (F32) N_RES;
- n.normVec();
-
- mNorms[i][j] = n;
- }
- }
-}
-
-void LLVOWater::generateNewWaves(F64 time)
-{
- getWaterSurface()->generateWaterHeightField(time);
- sGrid->update();
-}
-
diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h
index 2b846dba20..74a5e81d8c 100644
--- a/indra/newview/llvowater.h
+++ b/indra/newview/llvowater.h
@@ -16,195 +16,25 @@
#include "llwaterpatch.h"
-
const U32 N_RES = 16; //32 // number of subdivisions of wave tile
const U8 WAVE_STEP = 8;
-/*
-#define N_DET 32 // number of subdivisions of wave tile for details
-
-class LLWaterDetail
-{
-protected:
- S32 mResolution;
- LLViewerImage *mTex;
- U8 *mTexData;
-
-public:
- LLWaterDetail() : mResolution(N_DET), mTex(0), mTexData(0) {init();}
- void init();
-
- ~LLWaterDetail()
- {
- delete[] mTexData;
- mTexData = NULL;
- }
-
-
- //void initEmpty();
-
- void setPixel(const LLVector3 &norm, const S32 i, const S32 j)
- {
- S32 offset = (i * mResolution + j) * 3;
- mTexData[offset] = llround(norm.mV[VX] * 255);
- mTexData[offset+1] = llround(norm.mV[VX] * 255);
- mTexData[offset+2] = llround(norm.mV[VX] * 255);
- }
- void setPixel(F32 x, F32 y, F32 z, const S32 i, const S32 j)
- {
- S32 offset = (i * mResolution + j) * 3;
- mTexData[offset] = llround(x * 255);
- mTexData[offset+1] = llround(y * 255);
- mTexData[offset+2] = llround(z * 255);
- }
-
- S32 getResolution() { return mResolution; }
-
- void createDetailBumpmap(F32* u, F32* v);
- void createTexture() const { mTex->createTexture(); }
- void bindTexture() const { mTex->bindTexture(); }
- LLViewerImage* getTexture() const { return mTex; }
-};
-*/
-
-class LLWaterSurface
-{
-protected:
- BOOL mInitialized;
- LLVector3 mWind;
- F32 mA;
- F32 mVisc; // viscosity of the fluid
- F32 mShininess;
-
- //LLWaterDetail* mDetail;
-
- LLFFTPlan mPlan;
- F32 mOmega[N_RES+1][N_RES+1]; // wave frequency
- COMPLEX mHtilda0[N_RES+1][N_RES+1]; // wave amplitudes and phases at time 0.
- LLVector3 mNorms[N_RES][N_RES];
- COMPLEX mHtilda[N_RES * N_RES];
-
-public:
- LLWaterSurface();
- ~LLWaterSurface() {}
-
- //void initSpecularLookup();
-
- F32 phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small);
-
- void initAmplitudes();
-
- F32 height(S32 i, S32 j) const { return mHtilda[i * N_RES + j].re; }
- F32 heightWrapped(S32 i, S32 j) const
- {
- return height((i + N_RES) % N_RES, (j + N_RES) % N_RES);
- }
-
- void generateWaterHeightField(F64 time);
- void calcNormals();
-
- void getHeightAndNormal(F32 i, F32 j, F32& height, LLVector3& normal) const;
- void getIntegerHeightAndNormal(S32 i, S32 j, F32& height, LLVector3& normal) const;
- F32 agentDepth() const;
-
-// const LLWaterHeightField* hField() const { return &mHeightField; }
-
- //void generateDetail(F64 t);
- //void fluidSolver(F32* u, F32* v, F32* u0, F32* v0, F64 dt);
-
- const LLVector3& getWind() const { return mWind; }
- void setWind(const LLVector3& w) { mWind = w; } // initialized = 0?
- F32 A() const { return mA; }
- void setA(F32 a) { mA = a; }
- F32 getShininess() const { return mShininess; }
- //LLViewerImage* getSpecularLookup() const { return mSpecularLookup; }
- //LLViewerImage* getDetail() const { return mDetail->getTexture(); }
-};
-
-class LLVOWater;
-
-class LLWaterGrid
-{
-public:
- LLWaterGrid();
-
- void init();
- void cleanup();
-
- LLWaterSurface* getWaterSurface() { return &mWater; }
-
- void update();
- void updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far,
- BOOL restart);
- void updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far);
-
- LLVector3 mRegionOrigin;
-
- LLVector3* mVtx;
- LLVector3* mNorms;
- U32 mRegionWidth;
- U32 mMaxGridSize;
- U32 mPatchRes;
- U32 mMinStep;
- U32 mStepsInRegion;
- LLWaterPatch* mPatches;
- LLRoam mRoam;
- F32 mResIncrease;
- U32 mResDecrease;
-
- LLVOWater* mTab[5][5];
-
- U32 gridDim() const { return mGridDim; }
- U32 rowSize() const { return mGridDim1; }
- void setGridDim(U32 gd) { mGridDim = gd; mGridDim1 = mGridDim + 1; }
- U32 index(const LL2Coord& c) const { return c.y() * mGridDim1 + c.x(); }
- U32 index(U32 x, U32 y) const { return y * mGridDim1 + x; }
-
- LLVector3 vtx(const LL2Coord& c, F32 raised) const
- {
- LLVector3 v = mVtx[index(c)];
- v.mV[VZ] += raised;
- return v;
- }
-
- LLVector3 vtx(U32 x, U32 y, F32 raised) const
- {
- LLVector3 v = mVtx[index(x, y)];
- v.mV[VZ] += raised;
- return v;
- }
-
- void setVertex(const U32 x, const U32 y, const F32 raised, LLVector3 &vertex) const
- {
- vertex = mVtx[index(x, y)];
- vertex.mV[VZ] += raised;
- }
-
- void setCamPosition(LL2Coord& cam, const LLVector3& cam_pos)
- {
- cam.x() = llround((cam_pos.mV[VX] - mRegionOrigin.mV[VX]) / mMinStep);
- cam.y() = llround((cam_pos.mV[VY] - mRegionOrigin.mV[VY]) / mMinStep);
- }
-
- LLVector3 vtx(const LL2Coord& c) const { return mVtx[index(c)]; }
- LLVector3 norm(const LL2Coord& c) const { return mNorms[index(c)]; }
- LLVector3 vtx(U32 x, U32 y) const { return mVtx[index(x, y)]; }
- LLVector3 norm(U32 x, U32 y) const { return mNorms[index(x, y)]; }
-
-protected:
- LLWaterSurface mWater;
- U32 mGridDim;
- U32 mGridDim1;
-};
-
class LLSurface;
class LLHeavenBody;
class LLVOSky;
class LLFace;
-class LLVOWater : public LLViewerObject
+class LLVOWater : public LLStaticViewerObject
{
public:
+ enum
+ {
+ VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) |
+ (1 << LLVertexBuffer::TYPE_NORMAL) |
+ (1 << LLVertexBuffer::TYPE_TEXCOORD)
+ }
+ eVertexDataMask;
+
LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
virtual ~LLVOWater() {}
@@ -217,24 +47,19 @@ public:
/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
- BOOL updateGeometryFlat(LLDrawable *drawable);
- BOOL updateGeometryHeightFieldSimple(LLDrawable *drawable);
- BOOL updateGeometryHeightFieldRoam(LLDrawable *drawable);
+ /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax);
- /*virtual*/ void updateDrawable(BOOL force_damped);
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
+ virtual U32 getPartitionType() const;
+
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
void setUseTexture(const BOOL use_texture);
- static void generateNewWaves(F64 time);
- static LLWaterSurface* getWaterSurface() { return sGrid->getWaterSurface(); }//return &mWater; }
- static const LLWaterGrid* getGrid() { return sGrid; }
protected:
BOOL mUseTexture;
- static LLWaterGrid *sGrid;
};
#endif // LL_VOSURFACEPATCH_H
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 813eb0c7ea..752d5a38c6 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -43,7 +43,6 @@ U32 gAgentPauseSerialNum = 0;
// Constants
//
const S32 MAX_NUMBER_OF_CLOUDS = 750;
-const F32 MIN_IDLE_UPDATE_TIME = 0.025f;
const S32 WORLD_PATCH_SIZE = 16;
extern LLColor4U MAX_WATER_COLOR;
@@ -63,7 +62,6 @@ LLWorld::LLWorld(const U32 grids_per_region, const F32 meters_per_grid)
mLastPacketsOut = 0;
mLastPacketsLost = 0;
mLandFarClip = DEFAULT_FAR_PLANE;
- mIdleUpdateTime = MIN_IDLE_UPDATE_TIME;
if (gNoRender)
{
@@ -616,31 +614,22 @@ void LLWorld::updateVisibilities()
gCamera->setFar(cur_far_clip);
}
-
-void LLWorld::updateRegions()
+void LLWorld::updateRegions(F32 max_update_time)
{
LLViewerRegion *regionp;
LLTimer update_timer;
-
+ BOOL did_one = FALSE;
+
// Perform idle time updates for the regions (and associated surfaces)
for (regionp = mRegionList.getFirstData();
regionp;
regionp = mRegionList.getNextData())
{
- update_timer.reset();
- if (!regionp->idleUpdate(update_timer, mIdleUpdateTime))
- {
- // Didn't finish all the updates. Slightly increase the idle update time.
- mIdleUpdateTime *= 1.05f;
- }
- else
- {
- mIdleUpdateTime *= 0.9f;
- if (mIdleUpdateTime < MIN_IDLE_UPDATE_TIME)
- {
- mIdleUpdateTime = MIN_IDLE_UPDATE_TIME;
- }
- }
+ F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
+ if (did_one && max_time <= 0.f)
+ break;
+ max_time = llmin(max_time, max_update_time*.1f);
+ did_one |= regionp->idleUpdate(max_update_time);
}
}
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 71d7a02322..0d0d1b3211 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -95,7 +95,7 @@ public:
F32 getRegionMinHeight() const { return -mWidthInMeters; }
F32 getRegionMaxHeight() const { return 3.f*mWidthInMeters; }
- void updateRegions();
+ void updateRegions(F32 max_update_time);
void updateVisibilities();
void updateParticles();
void updateClouds(const F32 dt);
@@ -140,7 +140,6 @@ private:
const F32 mWidthInMeters;
F32 mLandFarClip; // Far clip distance for land.
- F32 mIdleUpdateTime;
LLPatchVertexArray mLandPatch;
S32 mLastPacketsIn;
S32 mLastPacketsOut;
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 10994d38d2..fde1411563 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -298,7 +298,6 @@ void LLWorldMapView::draw()
{
LLGLSNoTexture no_texture;
-
glMatrixMode(GL_MODELVIEW);
// Clear the background alpha to 0
@@ -362,14 +361,12 @@ void LLWorldMapView::draw()
current_image->setBoostLevel(LLViewerImage::BOOST_MAP_LAYER);
current_image->setKnownDrawSize(llround(pix_width), llround(pix_height));
-#if 1 || LL_RELEASE_FOR_DOWNLOAD
if (!current_image->getHasGLTexture())
{
continue; // better to draw nothing than the default image
}
-#endif
- LLTextureView::addDebugImage(current_image);
+// LLTextureView::addDebugImage(current_image);
// Draw using the texture. If we don't clamp we get artifact at
// the edge.
@@ -522,7 +519,7 @@ void LLWorldMapView::draw()
overlayimage->setKnownDrawSize(draw_size, draw_size);
}
- LLTextureView::addDebugImage(simimage);
+// LLTextureView::addDebugImage(simimage);
if (sim_visible && info->mAlpha > 0.001f)
{
@@ -815,6 +812,39 @@ void LLWorldMapView::draw()
updateVisibleBlocks();
}
+//virtual
+void LLWorldMapView::setVisible(BOOL visible)
+{
+ LLPanel::setVisible(visible);
+ if (!visible && gWorldMap)
+ {
+ for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++)
+ {
+ for (U32 layer_idx=0; layer_idx<gWorldMap->mMapLayers[map].size(); ++layer_idx)
+ {
+ if (gWorldMap->mMapLayers[map][layer_idx].LayerDefined)
+ {
+ LLWorldMapLayer *layer = &gWorldMap->mMapLayers[map][layer_idx];
+ layer->LayerImage->setBoostLevel(0);
+ }
+ }
+ }
+ for (LLWorldMap::sim_info_map_t::iterator it = gWorldMap->mSimInfoMap.begin();
+ it != gWorldMap->mSimInfoMap.end(); ++it)
+ {
+ LLSimInfo* info = (*it).second;
+ if (info->mCurrentImage.notNull())
+ {
+ info->mCurrentImage->setBoostLevel(0);
+ }
+ if (info->mOverlayImage.notNull())
+ {
+ info->mOverlayImage->setBoostLevel(0);
+ }
+ }
+ }
+}
+
void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLPointer<LLViewerImage> image)
{
LLWorldMap::item_info_list_t::const_iterator e;
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index d0a6aeacb2..9b353efc72 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -47,12 +47,13 @@ public:
virtual ~LLWorldMapView();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE );
+ virtual void setVisible(BOOL visible);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen );
+ virtual BOOL handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen );
bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track);
void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id);
diff --git a/indra/newview/macview_Prefix.h b/indra/newview/macview_Prefix.h
index 60097bd422..06a2c1604b 100644
--- a/indra/newview/macview_Prefix.h
+++ b/indra/newview/macview_Prefix.h
@@ -111,17 +111,15 @@
#include "lldrawpoolalpha.h"
#include "lldrawpoolavatar.h"
#include "lldrawpooltree.h"
-#include "lldrawpooltreenew.h"
#include "lldrawpoolterrain.h"
#include "lldrawpoolsky.h"
#include "lldrawpoolwater.h"
#include "lldrawpoolground.h"
#include "lldrawpoolbump.h"
-#include "llvotreenew.h"
/////////////////// From llface.cpp
#include "llgl.h"
-#include "llviewerimagelist.h"
+#include "llviewerimage.h"
#include "llsky.h"
#include "llvosky.h"
#include "llcontrol.h"
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 445f8c6fbf..4108298dfd 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -13,12 +13,12 @@
// library includes
#include "audioengine.h" // For MAX_BUFFERS for debugging.
#include "imageids.h"
-#include "llagpmempool.h"
#include "llerror.h"
#include "llviewercontrol.h"
#include "llfasttimer.h"
#include "llfontgl.h"
#include "llmemory.h"
+#include "llmemtype.h"
#include "llnamevalue.h"
#include "llprimitive.h"
#include "llvolume.h"
@@ -26,17 +26,17 @@
#include "timing.h"
#include "v3color.h"
#include "llui.h"
+#include "llglheaders.h"
// newview includes
#include "llagent.h"
-#include "llagparray.h"
#include "lldrawable.h"
#include "lldrawpoolalpha.h"
#include "lldrawpoolavatar.h"
#include "lldrawpoolground.h"
#include "lldrawpoolsimple.h"
+#include "lldrawpoolbump.h"
#include "lldrawpooltree.h"
-#include "lldrawpoolhud.h"
#include "lldrawpoolwater.h"
#include "llface.h"
#include "llfeaturemanager.h"
@@ -63,10 +63,13 @@
#include "llvosky.h"
#include "llvotree.h"
#include "llvovolume.h"
+#include "llvosurfacepatch.h"
+#include "llvowater.h"
+#include "llvotree.h"
+#include "llvopartgroup.h"
#include "llworld.h"
#include "viewer.h"
-#include "llagpmempoolarb.h"
-#include "llagparray.inl"
+#include "llcubemap.h"
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -75,6 +78,8 @@
//#define DEBUG_INDICES
#endif
+#define AGGRESSIVE_OCCLUSION 0
+
const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
@@ -98,10 +103,8 @@ extern S32 gBoxFrame;
extern BOOL gRenderLightGlows;
extern BOOL gHideSelectedObjects;
-
BOOL gAvatarBacklight = FALSE;
-F32 gMinObjectDistance = MIN_NEAR_PLANE;
S32 gTrivialAccepts = 0;
BOOL gRenderForSelect = FALSE;
@@ -157,6 +160,13 @@ const char* LLPipeline::sTerrainUniforms[] =
U32 LLPipeline::sTerrainUniformCount = sizeof(LLPipeline::sTerrainUniforms)/sizeof(char*);
+const char* LLPipeline::sShinyUniforms[] =
+{
+ "origin"
+};
+
+U32 LLPipeline::sShinyUniformCount = sizeof(LLPipeline::sShinyUniforms)/sizeof(char*);
+
const char* LLPipeline::sWaterUniforms[] =
{
"screenTex",
@@ -173,8 +183,6 @@ const char* LLPipeline::sWaterUniforms[] =
U32 LLPipeline::sWaterUniformCount = sizeof(LLPipeline::sWaterUniforms)/sizeof(char*);
-// the SSE variable is dependent on software blending being enabled.
-
//----------------------------------------
void stamp(F32 x, F32 y, F32 xs, F32 ys)
@@ -196,40 +204,35 @@ void stamp(F32 x, F32 y, F32 xs, F32 ys)
//----------------------------------------
S32 LLPipeline::sCompiles = 0;
-S32 LLPipeline::sAGPMaxPoolSize = 1 << 25; // 32MB
+
+BOOL LLPipeline::sShowHUDAttachments = TRUE;
BOOL LLPipeline::sRenderPhysicalBeacons = FALSE;
BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
BOOL LLPipeline::sRenderParticleBeacons = FALSE;
BOOL LLPipeline::sRenderSoundBeacons = FALSE;
+BOOL LLPipeline::sUseOcclusion = FALSE;
+BOOL LLPipeline::sSkipUpdate = FALSE;
+BOOL LLPipeline::sDynamicReflections = FALSE;
LLPipeline::LLPipeline() :
mVertexShadersEnabled(FALSE),
mVertexShadersLoaded(0),
mLastRebuildPool(NULL),
mAlphaPool(NULL),
+ mAlphaPoolPostWater(NULL),
mSkyPool(NULL),
mStarsPool(NULL),
- mCloudsPool(NULL),
mTerrainPool(NULL),
mWaterPool(NULL),
mGroundPool(NULL),
- mHUDPool(NULL),
- mAGPMemPool(NULL),
- mGlobalFence(0),
- mBufferIndex(0),
- mBufferCount(kMaxBufferCount),
- mUseOcclusionCulling(FALSE),
+ mSimplePool(NULL),
+ mBumpPool(NULL),
mLightMask(0),
- mLightMovingMask(0)
+ mLightMovingMask(0),
+ mCubeBuffer(NULL),
+ mCubeList(0)
{
- for(S32 i = 0; i < kMaxBufferCount; i++)
- {
- mBufferMemory[i] = NULL;
- }
- for (S32 i = 0; i < kMaxBufferCount; i++)
- {
- mBufferFence[i] = 0;
- }
+
}
void LLPipeline::init()
@@ -238,8 +241,25 @@ void LLPipeline::init()
stop_glerror();
- mAGPBound = FALSE;
- mObjectPartition = new LLSpatialPartition;
+ //create object partitions
+ //MUST MATCH declaration of eObjectPartitions
+ mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME
+ mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
+ mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
+ mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
+ mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
+ mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
+ mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
+ mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD
+ mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS
+ mObjectPartition.push_back(NULL); //PARTITION_NONE
+
+ //create render pass pools
+ getPool(LLDrawPool::POOL_ALPHA);
+ getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
+ getPool(LLDrawPool::POOL_SIMPLE);
+ getPool(LLDrawPool::POOL_BUMP);
+
mTrianglesDrawnStat.reset();
resetFrameStats();
@@ -248,43 +268,15 @@ void LLPipeline::init()
mRenderFeatureMask = 0; // All features start off
mRenderDebugMask = 0; // All debug starts off
+ mOldRenderDebugMask = mRenderDebugMask;
+
mBackfaceCull = TRUE;
- // Disable AGP initially.
- mRenderFeatureMask &= ~RENDER_FEATURE_AGP;
-
stop_glerror();
// Enable features
-
- mUseVBO = gSavedSettings.getBOOL("RenderUseVBO");
-
- // Allocate the shared buffers for software skinning
- for(S32 i=0; i < mBufferCount; i++)
- {
- mBufferMemory[i] = new LLAGPArray<U8>;
- mBufferMemory[i]->reserve_block(AVATAR_VERTEX_BYTES*AVATAR_BUFFER_ELEMENTS);
- }
-
- if (gFeatureManagerp->isFeatureAvailable("RenderAGP"))
- {
- setUseAGP(gSavedSettings.getBOOL("RenderUseAGP") && gGLManager.mHasAnyAGP);
- }
- else
- {
- setUseAGP(FALSE);
- }
-
stop_glerror();
-
- for(S32 i=0; i < mBufferCount; i++)
- {
- if (!mBufferMemory[i]->isAGP() && usingAGP())
- {
- llwarns << "pipeline buffer memory is non-AGP when AGP available!" << llendl;
- }
- }
-
+
setShaders();
}
@@ -307,7 +299,17 @@ void LLPipeline::cleanup()
{
pool_set_t::iterator curiter = iter++;
LLDrawPool* poolp = *curiter;
- if (poolp->mReferences.empty())
+ if (poolp->isFacePool())
+ {
+ LLFacePool* face_pool = (LLFacePool*) poolp;
+ if (face_pool->mReferences.empty())
+ {
+ mPools.erase(curiter);
+ removeFromQuickLookup( poolp );
+ delete poolp;
+ }
+ }
+ else
{
mPools.erase(curiter);
removeFromQuickLookup( poolp );
@@ -315,10 +317,6 @@ void LLPipeline::cleanup()
}
}
- if (!mSimplePools.empty())
- {
- llwarns << "Simple Pools not cleaned up" << llendl;
- }
if (!mTerrainPools.empty())
{
llwarns << "Terrain Pools not cleaned up" << llendl;
@@ -327,208 +325,107 @@ void LLPipeline::cleanup()
{
llwarns << "Tree Pools not cleaned up" << llendl;
}
- if (!mTreeNewPools.empty())
- {
- llwarns << "TreeNew Pools not cleaned up" << llendl;
- }
- if (!mBumpPools.empty())
- {
- llwarns << "Bump Pools not cleaned up" << llendl;
- }
+
delete mAlphaPool;
mAlphaPool = NULL;
+ delete mAlphaPoolPostWater;
+ mAlphaPoolPostWater = NULL;
delete mSkyPool;
mSkyPool = NULL;
delete mStarsPool;
mStarsPool = NULL;
- delete mCloudsPool;
- mCloudsPool = NULL;
delete mTerrainPool;
mTerrainPool = NULL;
delete mWaterPool;
mWaterPool = NULL;
delete mGroundPool;
mGroundPool = NULL;
- delete mHUDPool;
- mHUDPool = NULL;
-
- mBloomImagep = NULL;
- mBloomImage2p = NULL;
- mFaceSelectImagep = NULL;
- mAlphaSizzleImagep = NULL;
+ delete mSimplePool;
+ mSimplePool = NULL;
+ delete mBumpPool;
+ mBumpPool = NULL;
- for(S32 i=0; i < mBufferCount; i++)
+ if (mCubeBuffer)
{
- delete mBufferMemory[i];
- mBufferMemory[i] = NULL;
+ delete mCubeBuffer;
+ mCubeBuffer = NULL;
}
- delete mObjectPartition;
- mObjectPartition = NULL;
-
- if (mAGPMemPool && mGlobalFence)
+ if (mCubeList)
{
- mAGPMemPool->deleteFence(mGlobalFence);
- mGlobalFence = 0;
+ glDeleteLists(mCubeList, 1);
+ mCubeList = 0;
}
- delete mAGPMemPool;
- mAGPMemPool = NULL;
-}
-//============================================================================
-
-BOOL LLPipeline::initAGP()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- mAGPMemPool = LLAGPMemPool::createPool(sAGPMaxPoolSize, mUseVBO);
+ mBloomImagep = NULL;
+ mBloomImage2p = NULL;
+ mFaceSelectImagep = NULL;
+ mAlphaSizzleImagep = NULL;
- if (!mAGPMemPool)
- {
- llinfos << "Warning! Couldn't allocate AGP memory!" << llendl;
- llinfos << "Disabling AGP!" << llendl;
- mAGPMemPool = NULL;
- mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag
- return FALSE;
- }
- else if (!mAGPMemPool->getSize())
+ for (S32 i = 0; i < NUM_PARTITIONS-1; i++)
{
- llinfos << "Warning! Unable to allocate AGP memory! Disabling AGP" << llendl;
- delete mAGPMemPool;
- mAGPMemPool = NULL;
- mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag
- return FALSE;
- }
- else
- {
- llinfos << "Allocated " << mAGPMemPool->getSize() << " bytes of AGP memory" << llendl;
- mAGPMemPool->bind();
-
- if (mAGPMemPool->getSize() < MIN_AGP_SIZE)
- {
- llwarns << "Not enough AGP memory!" << llendl;
- delete mAGPMemPool;
- mAGPMemPool = NULL;
- mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag
- return FALSE;
- }
-
-
- if (mAGPMemPool)
- {
- // Create the fence that we use for global synchronization.
- mGlobalFence = mAGPMemPool->createFence();
- }
- return TRUE;
+ delete mObjectPartition[i];
}
+ mObjectPartition.clear();
+ mGroupQ.clear();
+ mVisibleList.clear();
+ mVisibleGroups.clear();
+ mDrawableGroups.clear();
+ mActiveGroups.clear();
+ mVisibleBridge.clear();
+ mMovedBridge.clear();
+ mOccludedBridge.clear();
+ mAlphaGroups.clear();
+ clearRenderMap();
}
-void LLPipeline::cleanupAGP()
-{
- int i;
- for(i=0; i < mBufferCount; i++)
- {
- mBufferMemory[i]->deleteFence(mBufferFence[i]);
- mBufferMemory[i]->setUseAGP(FALSE);
- }
-
- flushAGPMemory();
- if (mAGPMemPool && mGlobalFence)
- {
- mAGPMemPool->deleteFence(mGlobalFence);
- mGlobalFence = 0;
- }
- delete mAGPMemPool;
- mAGPMemPool = NULL;
-}
+//============================================================================
-BOOL LLPipeline::usingAGP() const
+void LLPipeline::destroyGL()
{
- return (mRenderFeatureMask & RENDER_FEATURE_AGP) ? TRUE : FALSE;
-}
+ stop_glerror();
+ unloadShaders();
+ mHighlightFaces.clear();
+ mGroupQ.clear();
+ mVisibleList.clear();
+ mVisibleGroups.clear();
+ mDrawableGroups.clear();
+ mActiveGroups.clear();
+ mVisibleBridge.clear();
+ mOccludedBridge.clear();
+ mAlphaGroups.clear();
+ clearRenderMap();
+ resetVertexBuffers();
-void LLPipeline::setUseAGP(const BOOL use_agp)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- if (use_agp == usingAGP())
+ if (mCubeBuffer)
{
- return;
+ delete mCubeBuffer;
+ mCubeBuffer = NULL;
}
- else if (use_agp)
- {
- mRenderFeatureMask |= RENDER_FEATURE_AGP;
- initAGP();
- // Forces us to allocate an AGP memory block immediately.
- int i;
- for(i=0; i < mBufferCount; i++)
- {
- mBufferMemory[i]->setUseAGP(use_agp);
- mBufferMemory[i]->realloc(mBufferMemory[i]->getMax());
- mBufferFence[i] = mBufferMemory[i]->createFence();
- }
-
- // Must be done AFTER you initialize AGP
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- poolp->setUseAGP(use_agp);
- }
- }
- else
+ if (mCubeList)
{
- unbindAGP();
- mRenderFeatureMask &= ~RENDER_FEATURE_AGP;
-
- // Must be done BEFORE you blow away AGP
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- poolp->setUseAGP(use_agp);
- }
-
- int i;
- for(i=0; i < mBufferCount; i++)
- {
- if (mBufferMemory[i])
- {
- mBufferMemory[i]->setUseAGP(use_agp);
- mBufferMemory[i]->deleteFence(mBufferFence[i]);
- mBufferFence[i] = 0;
- }
- else
- {
- llerrs << "setUseAGP without buffer memory" << llendl;
- }
- }
-
- cleanupAGP();
+ glDeleteLists(mCubeList, 1);
+ mCubeList = 0;
}
-
-}
-
-//============================================================================
-
-void LLPipeline::destroyGL()
-{
- setUseAGP(FALSE);
- stop_glerror();
- unloadShaders();
- mHighlightFaces.reset();
}
void LLPipeline::restoreGL()
{
+ resetVertexBuffers();
+
if (mVertexShadersEnabled)
{
setShaders();
}
- if (mObjectPartition)
+ for (U32 i = 0; i < mObjectPartition.size()-1; i++)
{
- mObjectPartition->restoreGL();
+ if (mObjectPartition[i])
+ {
+ mObjectPartition[i]->restoreGL();
+ }
}
}
@@ -596,7 +493,7 @@ GLhandleARB LLPipeline::loadShader(const LLString& filename, S32 cls, GLenum typ
fname << gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class");
fname << gpu_class << "/" << filename;
- llinfos << "Looking in " << fname.str().c_str() << llendl;
+// llinfos << "Looking in " << fname.str().c_str() << llendl;
file = fopen(fname.str().c_str(), "r"); /* Flawfinder: ignore */
if (file)
{
@@ -771,6 +668,11 @@ BOOL LLPipeline::validateProgramObject(GLhandleARB obj)
void LLPipeline::setShaders()
{
+ sDynamicReflections = gSavedSettings.getBOOL("RenderDynamicReflections");
+
+ //hack to reset buffers that change behavior with shaders
+ resetVertexBuffers();
+
if (gViewerWindow)
{
gViewerWindow->setCursor(UI_CURSOR_WAIT);
@@ -789,6 +691,8 @@ void LLPipeline::setShaders()
{
S32 light_class = 2;
S32 env_class = 2;
+ S32 obj_class = 0;
+
if (getLightingDetail() == 0)
{
light_class = 1;
@@ -798,7 +702,11 @@ void LLPipeline::setShaders()
mMaxVertexShaderLevel[SHADER_LIGHTING] = light_class;
mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class;
mMaxVertexShaderLevel[SHADER_ENVIRONMENT] = env_class;
+ mVertexShaderLevel[SHADER_OBJECT] = obj_class;
+ mMaxVertexShaderLevel[SHADER_OBJECT] = obj_class;
+
BOOL loaded = loadShadersLighting();
+
if (loaded)
{
mVertexShadersEnabled = TRUE;
@@ -806,7 +714,7 @@ void LLPipeline::setShaders()
// Load all shaders to set max levels
loadShadersEnvironment();
-
+ loadShadersObject();
// Load max avatar shaders to set the max level
mVertexShaderLevel[SHADER_AVATAR] = 3;
mMaxVertexShaderLevel[SHADER_AVATAR] = 3;
@@ -878,6 +786,7 @@ BOOL LLPipeline::canUseVertexShaders()
void LLPipeline::unloadShaders()
{
mObjectSimpleProgram.unload();
+ mObjectShinyProgram.unload();
mObjectBumpProgram.unload();
mObjectAlphaProgram.unload();
mWaterProgram.unload();
@@ -919,7 +828,8 @@ BOOL LLPipeline::loadShaders()
light_class = 2; // Use medium lighting shader
}
mVertexShaderLevel[SHADER_LIGHTING] = light_class;
- mVertexShaderLevel[SHADER_OBJECT] = llmin(mMaxVertexShaderLevel[SHADER_OBJECT], gSavedSettings.getS32("VertexShaderLevelObject"));
+ //mVertexShaderLevel[SHADER_OBJECT] = llmin(mMaxVertexShaderLevel[SHADER_OBJECT], gSavedSettings.getS32("VertexShaderLevelObject"));
+ mVertexShaderLevel[SHADER_OBJECT] = 0;
mVertexShaderLevel[SHADER_AVATAR] = llmin(mMaxVertexShaderLevel[SHADER_AVATAR], gSavedSettings.getS32("VertexShaderLevelAvatar"));
mVertexShaderLevel[SHADER_ENVIRONMENT] = llmin(mMaxVertexShaderLevel[SHADER_ENVIRONMENT], gSavedSettings.getS32("VertexShaderLevelEnvironment"));
mVertexShaderLevel[SHADER_INTERFACE] = mMaxVertexShaderLevel[SHADER_INTERFACE];
@@ -1100,12 +1010,14 @@ BOOL LLPipeline::loadShadersObject()
if (mVertexShaderLevel[SHADER_OBJECT] == 0)
{
+ mObjectShinyProgram.unload();
mObjectSimpleProgram.unload();
mObjectBumpProgram.unload();
mObjectAlphaProgram.unload();
return FALSE;
}
-
+
+#if 0
if (success)
{
//load object (volume/tree) vertex shader
@@ -1166,6 +1078,28 @@ BOOL LLPipeline::loadShadersObject()
llwarns << "Failed to load " << alphavertex << llendl;
}
}
+#endif
+
+ if (success)
+ {
+ //load shiny vertex shader
+ std::string shinyvertex = "objects/shinyV.glsl";
+ std::string shinyfragment = "objects/shinyF.glsl";
+ mObjectShinyProgram.mProgramObject = glCreateProgramObjectARB();
+ mObjectShinyProgram.attachObjects(baseObjects, baseCount);
+ mObjectShinyProgram.attachObject(loadShader(shinyvertex, SHADER_OBJECT, GL_VERTEX_SHADER_ARB));
+ mObjectShinyProgram.attachObject(loadShader(shinyfragment, SHADER_OBJECT, GL_FRAGMENT_SHADER_ARB));
+
+ success = mObjectShinyProgram.mapAttributes();
+ if (success)
+ {
+ success = mObjectShinyProgram.mapUniforms(LLPipeline::sShinyUniforms, LLPipeline::sShinyUniformCount);
+ }
+ if( !success )
+ {
+ llwarns << "Failed to load " << shinyvertex << llendl;
+ }
+ }
if( !success )
{
@@ -1322,11 +1256,11 @@ void LLPipeline::enableShadows(const BOOL enable_shadows)
S32 LLPipeline::getMaxLightingDetail() const
{
- if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
+ /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
{
return 3;
}
- else
+ else*/
{
return 1;
}
@@ -1356,79 +1290,63 @@ S32 LLPipeline::setLightingDetail(S32 level)
return mLightingDetail;
}
-LLAGPMemBlock *LLPipeline::allocAGPFromPool(const S32 bytes, const U32 target)
+class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- if (!mAGPMemPool)
- {
- llwarns << "Attempting to allocate AGP memory when AGP disabled!" << llendl;
- return NULL;
- }
- else
+public:
+ const std::set<LLViewerImage*>& mTextures;
+
+ LLOctreeDirtyTexture(const std::set<LLViewerImage*>& textures) : mTextures(textures) { }
+
+ virtual void visit(const LLOctreeState<LLDrawable>* state)
{
- if (mUseVBO)
+ LLSpatialGroup* group = (LLSpatialGroup*) state->getNode()->getListener(0);
+
+ if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
{
- return ((LLAGPMemPoolARB*) mAGPMemPool)->allocBlock(bytes, target);
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+ {
+ for (std::vector<LLDrawInfo*>::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ LLDrawInfo* params = *j;
+ if (mTextures.find(params->mTexture) != mTextures.end())
+ {
+ group->setState(LLSpatialGroup::GEOM_DIRTY);
+ gPipeline.markRebuild(group);
+ }
+ }
+ }
}
- else
+
+ for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
{
- return mAGPMemPool->allocBlock(bytes);
+ LLSpatialBridge* bridge = *i;
+ traverse(bridge->mOctree);
}
}
-}
-
-
-void LLPipeline::unbindAGP()
-{
- if (mAGPMemPool && mAGPBound)
- {
- mAGPMemPool->disable();
- mAGPBound = FALSE;
- }
-}
-
-void LLPipeline::bindAGP()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- if (mAGPMemPool && !mAGPBound && usingAGP())
- {
- mAGPMemPool->enable();
- mAGPBound = TRUE;
- }
-}
-
-U8* LLPipeline::bufferGetScratchMemory(void)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- return(mBufferMemory[mBufferIndex]->getScratchMemory());
-}
-
-void LLPipeline::bufferWaitFence(void)
-{
- mBufferMemory[mBufferIndex]->waitFence(mBufferFence[mBufferIndex]);
-}
-
-void LLPipeline::bufferSendFence(void)
-{
- mBufferMemory[mBufferIndex]->sendFence(mBufferFence[mBufferIndex]);
-}
+};
-void LLPipeline::bufferRotate(void)
+// Called when a texture changes # of channels (causes faces to move to alpha pool)
+void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures)
{
- mBufferIndex++;
- if(mBufferIndex >= mBufferCount)
- mBufferIndex = 0;
-}
+ // *TODO: This is inefficient and causes frame spikes; need a better way to do this
+ // Most of the time is spent in dirty.traverse.
-// Called when a texture changes # of channels (rare, may cause faces to move to alpha pool)
-void LLPipeline::dirtyPoolObjectTextures(const LLViewerImage *texturep)
-{
for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
{
LLDrawPool *poolp = *iter;
- poolp->dirtyTexture(texturep);
+ if (poolp->isFacePool())
+ {
+ ((LLFacePool*) poolp)->dirtyTextures(textures);
+ }
+ }
+
+ LLOctreeDirtyTexture dirty(textures);
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i])
+ {
+ dirty.traverse(mObjectPartition[i]->mOctree);
+ }
}
}
@@ -1438,33 +1356,29 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
switch( type )
{
case LLDrawPool::POOL_SIMPLE:
- poolp = get_if_there(mSimplePools, (uintptr_t)tex0, (LLDrawPool*)0 );
+ poolp = mSimplePool;
break;
case LLDrawPool::POOL_TREE:
poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
break;
- case LLDrawPool::POOL_TREE_NEW:
- poolp = get_if_there(mTreeNewPools, (uintptr_t)tex0, (LLDrawPool*)0 );
- break;
-
case LLDrawPool::POOL_TERRAIN:
poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
break;
case LLDrawPool::POOL_BUMP:
- poolp = get_if_there(mBumpPools, (uintptr_t)tex0, (LLDrawPool*)0 );
- break;
-
- case LLDrawPool::POOL_MEDIA:
- poolp = get_if_there(mMediaPools, (uintptr_t)tex0, (LLDrawPool*)0 );
+ poolp = mBumpPool;
break;
case LLDrawPool::POOL_ALPHA:
poolp = mAlphaPool;
break;
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ poolp = mAlphaPoolPostWater;
+ break;
+
case LLDrawPool::POOL_AVATAR:
break; // Do nothing
@@ -1476,10 +1390,6 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
poolp = mStarsPool;
break;
- case LLDrawPool::POOL_CLOUDS:
- poolp = mCloudsPool;
- break;
-
case LLDrawPool::POOL_WATER:
poolp = mWaterPool;
break;
@@ -1488,10 +1398,6 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
poolp = mGroundPool;
break;
- case LLDrawPool::POOL_HUD:
- poolp = mHUDPool;
- break;
-
default:
llassert(0);
llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl;
@@ -1522,29 +1428,37 @@ LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ U32 type = getPoolTypeFromTE(te, imagep);
+ return gPipeline.getPool(type, imagep);
+}
+
+//static
+U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ if (!te || !imagep)
+ {
+ return 0;
+ }
+
bool alpha = te->getColor().mV[3] < 0.999f;
if (imagep)
{
alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2);
}
-#if 0 // Not currently used
- if (te->getMediaFlags() == LLTextureEntry::MF_WEB_PAGE)
- {
- return gPipeline.getPool(LLDrawPool::POOL_MEDIA, imagep);
- }
- else
-#endif
+
if (alpha)
{
- return gPipeline.getPool(LLDrawPool::POOL_ALPHA);
+ return LLDrawPool::POOL_ALPHA;
}
else if ((te->getBumpmap() || te->getShiny()))
{
- return gPipeline.getPool(LLDrawPool::POOL_BUMP, imagep);
+ return LLDrawPool::POOL_BUMP;
}
else
{
- return gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep);
+ return LLDrawPool::POOL_SIMPLE;
}
}
@@ -1575,14 +1489,20 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj)
}
-void LLPipeline::unlinkDrawable(LLDrawable *drawablep)
+void LLPipeline::unlinkDrawable(LLDrawable *drawable)
{
LLFastTimer t(LLFastTimer::FTM_PIPELINE);
+
+ LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
// Based on flags, remove the drawable from the queues that it's on.
if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
{
- mMovedList.erase(drawablep);
+ LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
+ if (iter != mMovedList.end())
+ {
+ mMovedList.erase(iter);
+ }
}
if (drawablep->getSpatialGroup())
@@ -1612,9 +1532,6 @@ U32 LLPipeline::addObject(LLViewerObject *vobj)
llassert(drawablep);
- //mCompleteSet.put(drawable);
- //gResyncObjects = TRUE;
-
if (vobj->getParent())
{
vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
@@ -1624,28 +1541,6 @@ U32 LLPipeline::addObject(LLViewerObject *vobj)
vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
}
-
- if ((!drawablep->getVOVolume()) &&
- (vobj->getPCode() != LLViewerObject::LL_VO_SKY) &&
- (vobj->getPCode() != LLViewerObject::LL_VO_STARS) &&
- (vobj->getPCode() != LLViewerObject::LL_VO_GROUND))
- {
- drawablep->getSpatialPartition()->put(drawablep);
- if (!drawablep->getSpatialGroup())
- {
-#ifdef LL_RELEASE_FOR_DOWNLOAD
- llwarns << "Failure adding drawable to object partition!" << llendl;
-#else
- llerrs << "Failure adding drawable to object partition!" << llendl;
-#endif
- }
- }
- else
- {
- markMoved(drawablep);
- }
-
- markMaterialed(drawablep);
markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
return 1;
@@ -1654,11 +1549,27 @@ U32 LLPipeline::addObject(LLViewerObject *vobj)
void LLPipeline::resetFrameStats()
{
+ mCompilesStat.addValue(sCompiles);
+ mLightingChangesStat.addValue(mLightingChanges);
+ mGeometryChangesStat.addValue(mGeometryChanges);
+ mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
+ mVerticesRelitStat.addValue(mVerticesRelit);
+ mNumVisibleFacesStat.addValue(mNumVisibleFaces);
+ mNumVisibleDrawablesStat.addValue((S32)mVisibleList.size());
+
+ mTrianglesDrawn = 0;
sCompiles = 0;
mVerticesRelit = 0;
mLightingChanges = 0;
mGeometryChanges = 0;
mNumVisibleFaces = 0;
+
+ if (mOldRenderDebugMask != mRenderDebugMask)
+ {
+ gObjectList.clearDebugText();
+ mOldRenderDebugMask = mRenderDebugMask;
+ }
+
}
//external functions for asynchronous updating
@@ -1683,7 +1594,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
// Put on move list so that EARLY_MOVE gets cleared
if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
{
- mMovedList.insert(drawablep);
+ mMovedList.push_back(drawablep);
drawablep->setState(LLDrawable::ON_MOVE_LIST);
}
}
@@ -1709,15 +1620,35 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
// Put on move list so that EARLY_MOVE gets cleared
if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
{
- mMovedList.insert(drawablep);
+ mMovedList.push_back(drawablep);
drawablep->setState(LLDrawable::ON_MOVE_LIST);
}
}
+void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
+{
+ for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
+ iter != moved_list.end(); )
+ {
+ LLDrawable::drawable_vector_t::iterator curiter = iter++;
+ LLDrawable *drawablep = *curiter;
+ BOOL done = TRUE;
+ if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
+ {
+ done = drawablep->updateMove();
+ }
+ drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
+ if (done)
+ {
+ drawablep->clearState(LLDrawable::ON_MOVE_LIST);
+ iter = moved_list.erase(curiter);
+ }
+ }
+}
+
void LLPipeline::updateMove()
{
- mObjectPartition->mOctree->validate();
- LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
+ //LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
LLMemType mt(LLMemType::MTYPE_PIPELINE);
if (gSavedSettings.getBOOL("FreezeTime"))
@@ -1727,23 +1658,18 @@ void LLPipeline::updateMove()
mMoveChangesStat.addValue((F32)mMovedList.size());
- for (LLDrawable::drawable_set_t::iterator iter = mMovedList.begin();
- iter != mMovedList.end(); )
+ for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
+ iter != mRetexturedList.end(); ++iter)
{
- LLDrawable::drawable_set_t::iterator curiter = iter++;
- LLDrawable *drawablep = *curiter;
- BOOL done = TRUE;
- if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
- {
- done = drawablep->updateMove();
- }
- drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
- if (done)
+ LLDrawable* drawablep = *iter;
+ if (drawablep && !drawablep->isDead())
{
- mMovedList.erase(curiter);
- drawablep->clearState(LLDrawable::ON_MOVE_LIST);
+ drawablep->updateTexture();
}
}
+ mRetexturedList.clear();
+
+ updateMovedList(mMovedList);
for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin();
iter != mActiveQ.end(); )
@@ -1752,7 +1678,8 @@ void LLPipeline::updateMove()
LLDrawable* drawablep = *curiter;
if (drawablep && !drawablep->isDead())
{
- if (drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&
+ if (drawablep->isRoot() &&
+ drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&
(!drawablep->getParent() || !drawablep->getParent()->isActive()))
{
drawablep->makeStatic(); // removes drawable and its children from mActiveQ
@@ -1765,172 +1692,168 @@ void LLPipeline::updateMove()
}
}
- for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
- iter != mRetexturedList.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
- if (drawablep && !drawablep->isDead())
- {
- drawablep->updateTexture();
- }
- }
- mRetexturedList.clear();
-
- for (LLDrawable::drawable_set_t::iterator iter = mRematerialedList.begin();
- iter != mRematerialedList.end(); ++iter)
+ //balance octrees
{
- LLDrawable* drawablep = *iter;
- if (drawablep && !drawablep->isDead())
+ LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
+ for (U32 i = 0; i < mObjectPartition.size()-1; i++)
{
- drawablep->updateMaterial();
+ if (mObjectPartition[i])
+ {
+ mObjectPartition[i]->mOctree->balance();
+ }
}
}
- mRematerialedList.clear();
-
- if (mObjectPartition->mOctree)
- {
- //balance octree
- LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
- mObjectPartition->mOctree->validate();
- mObjectPartition->mOctree->balance();
- mObjectPartition->mOctree->validate();
- }
}
/////////////////////////////////////////////////////////////////////////////
// Culling and occlusion testing
/////////////////////////////////////////////////////////////////////////////
-void LLPipeline::updateCull()
+//static
+F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
{
- LLFastTimer t(LLFastTimer::FTM_CULL);
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLVector3 lookAt = center - camera.getOrigin();
+ LLVector3 cross_vec = size * 2.f;
+ F32 dist = lookAt.magVec();
- LLDrawable::incrementVisible();
- mVisibleList.resize(0);
- mVisibleList.reserve(ESTIMATED_VISIBLE_OBJECT_COUNT);
-
- gTrivialAccepts = 0;
-
- if (mObjectPartition)
+ //ramp down distance for nearby objects
+ if (dist < 16.f)
{
- if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery)
- {
- mObjectPartition->processOcclusion(gCamera);
- stop_glerror();
- }
- mObjectPartition->cull(*gCamera);
+ dist /= 16.f;
+ dist *= dist;
+ dist *= 16.f;
}
-
- // Hack for avatars - warning - this is really FRAGILE! - djs 05/06/02
- LLVOAvatar::updateAllAvatarVisiblity();
- // If there are any other hacks here, make sure to add them to the
- // standard pick code.
-
- gMinObjectDistance = llclamp(gMinObjectDistance, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
+ //get area of circle around node
+ F32 app_angle = atanf((cross_vec*0.5f).magVec()/dist);
+ F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+ return radius*radius * 3.14159f;
+}
- F32 water_height = gAgent.getRegion()->getWaterHeight();
- F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
- if (fabs(camera_height - water_height) < 2.f)
- {
- gMinObjectDistance = MIN_NEAR_PLANE;
- }
+void LLPipeline::updateCull(LLCamera& camera)
+{
+ LLFastTimer t(LLFastTimer::FTM_CULL);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
- gCamera->setNear(gMinObjectDistance);
+ mVisibleList.clear();
+ mVisibleGroups.clear();
+ mDrawableGroups.clear();
+ mActiveGroups.clear();
+ gTrivialAccepts = 0;
+ mVisibleBridge.clear();
- // Disable near clip stuff for now...
+ processOcclusion(camera);
- // now push it back out to max value
- gMinObjectDistance = MIN_NEAR_PLANE;
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
+ {
+ mObjectPartition[i]->cull(camera);
+ }
+ }
+ //do a terse update on some off-screen geometry
+ processGeometry(camera);
+
if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
{
// Hack for sky - always visible.
- gSky.mVOSkyp->mDrawable->setVisible(*gCamera);
- mVisibleList.push_back(gSky.mVOSkyp->mDrawable);
- gSky.updateCull();
- stop_glerror();
+ if (hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+ {
+ gSky.mVOSkyp->mDrawable->setVisible(camera);
+ mVisibleList.push_back(gSky.mVOSkyp->mDrawable);
+ gSky.updateCull();
+ stop_glerror();
+ }
}
else
{
llinfos << "No sky drawable!" << llendl;
}
- if (gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull())
+ if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull())
{
- gSky.mVOGroundp->mDrawable->setVisible(*gCamera);
+ gSky.mVOGroundp->mDrawable->setVisible(camera);
mVisibleList.push_back(gSky.mVOGroundp->mDrawable);
}
+}
- // add all HUD attachments
- LLVOAvatar* my_avatarp = gAgent.getAvatarObject();
- if (my_avatarp && my_avatarp->hasHUDAttachment())
+void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera, BOOL active)
+{
+ if (group->getData().empty())
+ {
+ return;
+ }
+
+ if (!sSkipUpdate)
{
- for (LLViewerJointAttachment* attachmentp = my_avatarp->mAttachmentPoints.getFirstData();
- attachmentp;
- attachmentp = my_avatarp->mAttachmentPoints.getNextData())
- {
- if (attachmentp->getIsHUDAttachment() && attachmentp->getObject(0))
- {
- LLViewerObject* objectp = attachmentp->getObject(0);
- markVisible(objectp->mDrawable);
- objectp->mDrawable->updateDistance(*gCamera);
- for (S32 i = 0; i < (S32)objectp->mChildList.size(); i++)
- {
- LLViewerObject* childp = objectp->mChildList[i];
- if (childp->mDrawable.notNull())
- {
- markVisible(childp->mDrawable);
- childp->mDrawable->updateDistance(*gCamera);
- }
- }
- }
- }
+ group->updateDistance(camera);
}
-}
+
+ const F32 MINIMUM_PIXEL_AREA = 16.f;
-void LLPipeline::markNotCulled(LLDrawable* drawablep, LLCamera& camera)
-{
- if (drawablep->isVisible())
+ if (group->mPixelArea < MINIMUM_PIXEL_AREA)
{
return;
}
- // Tricky render mode to hide selected objects, but we definitely
- // don't want to do any unnecessary pointer dereferences. JC
- if (gHideSelectedObjects)
- {
- if (drawablep->getVObj() && drawablep->getVObj()->isSelected())
+ group->mLastRenderTime = gFrameTimeSeconds;
+ if (!group->mSpatialPartition->mRenderByGroup)
+ { //render by drawable
+ mDrawableGroups.push_back(group);
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- return;
+ markVisible(*i, camera);
}
}
-
- if (drawablep && (hasRenderType(drawablep->mRenderType)))
- {
- if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
+ else
+ { //render by group
+ if (active)
{
- mVisibleList.push_back(drawablep);
- drawablep->setVisible(camera, NULL, FALSE);
+ mActiveGroups.push_back(group);
}
- else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
+ else
{
- // clear invisible flag here to avoid single frame glitch
- drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
+ mVisibleGroups.push_back(group);
+ for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ markVisible(bridge, camera);
+ }
}
}
}
-void LLPipeline::doOcclusion()
+void LLPipeline::doOcclusion(LLCamera& camera)
{
- if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery)
+ if (sUseOcclusion)
{
- mObjectPartition->doOcclusion(gCamera);
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
+ {
+ mObjectPartition[i]->doOcclusion(&camera);
+ }
+ }
+
+#if AGGRESSIVE_OCCLUSION
+ for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ glPushMatrix();
+ glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ LLCamera trans = bridge->transformCamera(camera);
+ bridge->doOcclusion(&trans);
+ glPopMatrix();
+ mOccludedBridge.push_back(bridge);
+ }
+ }
+#endif
}
}
-
BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
{
BOOL update_complete = drawablep->updateGeometry(priority);
@@ -1955,19 +1878,31 @@ void LLPipeline::updateGeom(F32 max_dtime)
LLVOVolume::preUpdateGeom();
// Iterate through all drawables on the priority build queue,
- for (LLDrawable::drawable_set_t::iterator iter = mBuildQ1.begin();
+ for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
iter != mBuildQ1.end();)
{
- LLDrawable::drawable_set_t::iterator curiter = iter++;
+ LLDrawable::drawable_list_t::iterator curiter = iter++;
LLDrawable* drawablep = *curiter;
- BOOL update_complete = TRUE;
if (drawablep && !drawablep->isDead())
{
- update_complete = updateDrawableGeom(drawablep, TRUE);
+ if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+ LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
+ if (find != mBuildQ2.end())
+ {
+ mBuildQ2.erase(find);
+ }
+ }
+
+ if (updateDrawableGeom(drawablep, TRUE))
+ {
+ drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
+ mBuildQ1.erase(curiter);
+ }
}
- if (update_complete)
+ else
{
- drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
mBuildQ1.erase(curiter);
}
}
@@ -1978,20 +1913,34 @@ void LLPipeline::updateGeom(F32 max_dtime)
{
min_count = mBuildQ2.size();
}
- else
- {
- mBuildQ2.sort(LLDrawable::CompareDistanceGreaterVisibleFirst());
- }
-
+
S32 count = 0;
max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
-
+ LLSpatialGroup* last_group = NULL;
+ LLSpatialBridge* last_bridge = NULL;
+
for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
iter != mBuildQ2.end(); )
{
LLDrawable::drawable_list_t::iterator curiter = iter++;
LLDrawable* drawablep = *curiter;
+
+ LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
+ drawablep->getParent()->getSpatialBridge();
+
+ if (drawablep->getSpatialGroup() != last_group &&
+ (!last_bridge || bridge != last_bridge) &&
+ (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
+ {
+ break;
+ }
+
+ //make sure updates don't stop in the middle of a spatial group
+ //to avoid thrashing (objects are enqueued by group)
+ last_group = drawablep->getSpatialGroup();
+ last_bridge = bridge;
+
BOOL update_complete = TRUE;
if (drawablep && !drawablep->isDead())
{
@@ -2003,14 +1952,12 @@ void LLPipeline::updateGeom(F32 max_dtime)
drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
mBuildQ2.erase(curiter);
}
- if ((update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
- {
- break;
- }
- }
+ }
+
+ updateMovedList(mMovedBridge);
}
-void LLPipeline::markVisible(LLDrawable *drawablep)
+void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
if(!drawablep || drawablep->isDead())
@@ -2018,11 +1965,36 @@ void LLPipeline::markVisible(LLDrawable *drawablep)
llwarns << "LLPipeline::markVisible called with NULL drawablep" << llendl;
return;
}
- if (!drawablep->isVisible())
+
+
+#if LL_DEBUG
+ if (drawablep->isSpatialBridge())
+ {
+ if (std::find(mVisibleBridge.begin(), mVisibleBridge.end(), (LLSpatialBridge*) drawablep) !=
+ mVisibleBridge.end())
+ {
+ llerrs << "Spatial bridge marked visible redundantly." << llendl;
+ }
+ }
+ else
+ {
+ if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) !=
+ mVisibleList.end())
+ {
+ llerrs << "Drawable marked visible redundantly." << llendl;
+ }
+ }
+#endif
+
+ if (drawablep->isSpatialBridge())
+ {
+ mVisibleBridge.push_back((LLSpatialBridge*) drawablep);
+ }
+ else
{
- drawablep->setVisible(*gCamera);
mVisibleList.push_back(drawablep);
}
+ drawablep->setVisible(camera);
}
void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
@@ -2046,10 +2018,17 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
markMoved(drawablep->getParent(), damped_motion);
}
-
+
if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
{
- mMovedList.insert(drawablep);
+ if (drawablep->isSpatialBridge())
+ {
+ mMovedBridge.push_back(drawablep);
+ }
+ else
+ {
+ mMovedList.push_back(drawablep);
+ }
drawablep->setState(LLDrawable::ON_MOVE_LIST);
}
if (damped_motion == FALSE)
@@ -2098,30 +2077,33 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
mShiftList.resize(0);
- mObjectPartition->shift(offset);
+ for (U32 i = 0; i < mObjectPartition.size()-1; i++)
+ {
+ if (mObjectPartition[i])
+ {
+ mObjectPartition[i]->shift(offset);
+ }
+ }
}
void LLPipeline::markTextured(LLDrawable *drawablep)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
- if (!drawablep->isDead())
+ if (drawablep && !drawablep->isDead())
{
mRetexturedList.insert(drawablep);
}
}
-void LLPipeline::markMaterialed(LLDrawable *drawablep)
+void LLPipeline::markRebuild(LLSpatialGroup* group)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- if (!drawablep->isDead())
- {
- mRematerialedList.insert(drawablep);
- }
+ mGroupQ.insert(group);
}
void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
if (drawablep && !drawablep->isDead())
{
if (!drawablep->isState(LLDrawable::BUILT))
@@ -2130,15 +2112,18 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f
}
if (priority)
{
- mBuildQ1.insert(drawablep);
- drawablep->setState(LLDrawable::IN_REBUILD_Q1); // flag is not needed, just for debugging
+ if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
+ {
+ mBuildQ1.push_back(drawablep);
+ drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
+ }
}
else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
{
mBuildQ2.push_back(drawablep);
drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
}
- if (flag & LLDrawable::REBUILD_VOLUME)
+ if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
{
drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
}
@@ -2165,111 +2150,406 @@ void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority)
}
}
-void LLPipeline::stateSort()
+void LLPipeline::stateSort(LLCamera& camera)
{
LLFastTimer ftm(LLFastTimer::FTM_STATESORT);
LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mVisibleGroups.begin(); iter != mVisibleGroups.end(); ++iter)
+ {
+ stateSort(*iter, camera);
+ }
+
+ for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead())
+ {
+ stateSort(bridge, camera);
+ }
+ }
+
for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin();
iter != mVisibleList.end(); iter++)
{
LLDrawable *drawablep = *iter;
- if (drawablep->isDead())
+ if (!drawablep->isDead())
{
- continue;
+ stateSort(drawablep, camera);
}
+ }
+
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mActiveGroups.begin(); iter != mActiveGroups.end(); ++iter)
+ {
+ stateSort(*iter, camera);
+ }
+
+ postSort(camera);
+}
- if (!drawablep->isActive())
+void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ if (!sSkipUpdate && group->changeLOD())
+ {
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- drawablep->updateDistance(*gCamera);
+ LLDrawable* drawablep = *i;
+ stateSort(drawablep, camera);
}
+ }
+
+ if (gFrameTimeSeconds - group->mLastUpdateTime > 4.f)
+ {
+ group->makeStatic();
+ }
+}
- /*
- if (!drawablep->isState(LLDrawable::BUILT))
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ if (!sSkipUpdate)
+ {
+ bridge->updateDistance(camera);
+ }
+}
+
+void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
+
+ if (drawablep->isDead() || !hasRenderType(drawablep->getRenderType()))
+ {
+ return;
+ }
+
+ if (gHideSelectedObjects)
+ {
+ if (drawablep->getVObj() &&
+ drawablep->getVObj()->isSelected())
{
- // This geometry hasn't been rebuilt but it's visible, make sure it gets put on the rebuild list.
- llerrs << "Visible object " << drawablep << ":" << drawablep->getVObj()->getPCodeString();
- llcont << " visible but not built, put on rebuild" << llendl;
- markRebuild(drawablep);
- continue;
+ return;
}
- */
+ }
- for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
- iter != drawablep->mFaces.end(); iter++)
+ if (drawablep && (hasRenderType(drawablep->mRenderType)))
+ {
+ if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
{
- LLFace* facep = *iter;
- if (facep->hasGeometry())
+ drawablep->setVisible(camera, NULL, FALSE);
+ }
+ else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
+ {
+ // clear invisible flag here to avoid single frame glitch
+ drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
+ }
+ }
+
+ if (!drawablep->isActive() && drawablep->isVisible())
+ {
+ if (!sSkipUpdate)
+ {
+ drawablep->updateDistance(camera);
+ }
+ }
+ else if (drawablep->isAvatar() && drawablep->isVisible())
+ {
+ LLVOAvatar* vobj = (LLVOAvatar*) drawablep->getVObj();
+ vobj->updateVisibility(FALSE);
+ }
+
+ for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+ iter != drawablep->mFaces.end(); iter++)
+ {
+ LLFace* facep = *iter;
+
+ if (facep->hasGeometry())
+ {
+ if (facep->getPool())
{
facep->getPool()->enqueue(facep);
}
+ else
+ {
+ break;
+ }
}
-
- if (sRenderPhysicalBeacons)
- {
- // Only show the beacon on the root object.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- && !vobj->getParent()
- && vobj->usePhysics())
+ }
+
+
+ mNumVisibleFaces += drawablep->getNumFaces();
+}
+
+
+void LLPipeline::forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*))
+{
+ for (LLSpatialGroup::sg_vector_t::iterator i = groups.begin(); i != groups.end(); ++i)
+ {
+ for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
+ {
+ func(*j);
+ }
+ }
+}
+
+void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
+{
+ forAllDrawables(mDrawableGroups, func);
+ forAllDrawables(mVisibleGroups, func);
+ forAllDrawables(mActiveGroups, func);
+}
+
+//function for creating scripted beacons
+void renderScriptedBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && !vobj->isAvatar()
+ && !vobj->getParent()
+ && vobj->flagScripted())
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f));
+ }
+}
+
+void renderPhysicalBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && !vobj->isAvatar()
+ && !vobj->getParent()
+ && vobj->usePhysics())
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f));
+ }
+}
+
+void renderParticleBeacons(LLDrawable* drawablep)
+{
+ // Look for attachments, objects, etc.
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && vobj->isParticleSource())
+ {
+ LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f));
+ }
+}
+
+void LLPipeline::highlightPhysical(LLDrawable* drawablep)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLViewerObject *vobj;
+ vobj = drawablep->getVObj();
+ if (vobj && !vobj->isAvatar())
+ {
+ if (!vobj->isAvatar() &&
+ (vobj->usePhysics() || vobj->flagHandleTouch()))
+ {
+ S32 face_id;
+ for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
{
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f));
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
}
}
+ }
+}
+
+void LLPipeline::postSort(LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT);
+ //reset render data sets
+ clearRenderMap();
+ mAlphaGroups.clear();
+ mAlphaGroupsPostWater.clear();
+
+ if (!gSavedSettings.getBOOL("RenderRippleWater") && hasRenderType(LLDrawPool::POOL_ALPHA))
+ { //turn off clip plane for non-ripple water
+ toggleRenderType(LLDrawPool::POOL_ALPHA);
+ }
+
+ F32 water_height = gAgent.getRegion()->getWaterHeight();
+ BOOL above_water = gCamera->getOrigin().mV[2] > water_height ? TRUE : FALSE;
- if (sRenderScriptedBeacons)
+ //prepare occlusion geometry
+ if (sUseOcclusion)
+ {
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
{
- // Only show the beacon on the root object.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- && !vobj->getParent()
- && vobj->flagScripted())
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
{
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f));
+ mObjectPartition[i]->buildOcclusion();
+ }
+ }
+
+#if AGGRESSIVE_OCCLUSION
+ for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ bridge->buildOcclusion();
}
}
+#endif
+ }
+
+
+ //rebuild offscreen geometry
+ if (!sSkipUpdate)
+ {
+ for (LLSpatialGroup::sg_set_t::iterator iter = mGroupQ.begin(); iter != mGroupQ.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->rebuildGeom();
+ }
+ mGroupQ.clear();
+
+ //rebuild drawable geometry
+ for (LLSpatialGroup::sg_vector_t::iterator i = mDrawableGroups.begin(); i != mDrawableGroups.end(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ group->rebuildGeom();
+ }
+ }
- if (sRenderParticleBeacons)
+ //build render map
+ for (LLSpatialGroup::sg_vector_t::iterator i = mVisibleGroups.begin(); i != mVisibleGroups.end(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!sSkipUpdate)
+ {
+ group->rebuildGeom();
+ }
+ for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
{
- // Look for attachments, objects, etc.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && vobj->isParticleSource())
+ std::vector<LLDrawInfo*>& src_vec = j->second;
+ std::vector<LLDrawInfo*>& dest_vec = mRenderMap[j->first];
+
+ for (std::vector<LLDrawInfo*>::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
{
- LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f));
+ dest_vec.push_back(*k);
}
}
+
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
+
+ if (alpha != group->mDrawMap.end())
+ { //store alpha groups for sorting
+ if (!sSkipUpdate)
+ {
+ group->updateDistance(camera);
+ }
+
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ BOOL above = group->mObjectBounds[0].mV[2] + group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
+ BOOL below = group->mObjectBounds[0].mV[2] - group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
+
+ if (below == above_water || above == below)
+ {
+ mAlphaGroups.push_back(group);
+ }
- // Draw physical objects in red.
- if (gHUDManager->getShowPhysical())
+ if (above == above_water || below == above)
+ {
+ mAlphaGroupsPostWater.push_back(group);
+ }
+ }
+ else
+ {
+ mAlphaGroupsPostWater.push_back(group);
+ }
+ }
+ }
+
+ //store active alpha groups
+ for (LLSpatialGroup::sg_vector_t::iterator i = mActiveGroups.begin(); i != mActiveGroups.end(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!sSkipUpdate)
{
- LLViewerObject *vobj;
- vobj = drawablep->getVObj();
- if (vobj && !vobj->isAvatar())
+ group->rebuildGeom();
+ }
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
+
+ if (alpha != group->mDrawMap.end())
+ {
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+ LLCamera trans_camera = bridge->transformCamera(camera);
+ if (!sSkipUpdate)
{
- if (!vobj->isAvatar() &&
- (vobj->usePhysics() || vobj->flagHandleTouch()))
+ group->updateDistance(trans_camera);
+ }
+
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ LLSpatialGroup* bridge_group = bridge->getSpatialGroup();
+ BOOL above = bridge_group->mObjectBounds[0].mV[2] + bridge_group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
+ BOOL below = bridge_group->mObjectBounds[0].mV[2] - bridge_group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
+
+
+ if (below == above_water || above == below)
{
- if (!drawablep->isVisible())
- {
- // Skip objects that aren't visible.
- continue;
- }
- S32 face_id;
- for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
- {
- mHighlightFaces.put(drawablep->getFace(face_id) );
- }
+ mAlphaGroups.push_back(group);
+ }
+
+ if (above == above_water || below == above)
+ {
+ mAlphaGroupsPostWater.push_back(group);
}
}
+ else
+ {
+ mAlphaGroupsPostWater.push_back(group);
+ }
}
+ }
- mNumVisibleFaces += drawablep->getNumFaces();
+ //sort by texture or bump map
+ for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
+ {
+ if (!mRenderMap[i].empty())
+ {
+ if (i == LLRenderPass::PASS_BUMP)
+ {
+ std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareBump());
+ }
+ else
+ {
+ std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareTexturePtr());
+ }
+ }
}
-
+
+ std::sort(mAlphaGroups.begin(), mAlphaGroups.end(), LLSpatialGroup::CompareDepthGreater());
+ std::sort(mAlphaGroupsPostWater.begin(), mAlphaGroupsPostWater.end(), LLSpatialGroup::CompareDepthGreater());
+
+ if (sRenderScriptedBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderScriptedBeacons);
+ }
+
+ if (sRenderPhysicalBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderPhysicalBeacons);
+ }
+
+ if (sRenderParticleBeacons)
+ {
+ forAllVisibleDrawables(renderParticleBeacons);
+ }
+
+ // Draw physical objects in red.
+ if (gHUDManager->getShowPhysical())
+ {
+ forAllVisibleDrawables(highlightPhysical);
+ }
+
// If god mode, also show audio cues
if (sRenderSoundBeacons && gAudiop)
{
@@ -2292,7 +2572,7 @@ void LLPipeline::stateSort()
LLFloaterTelehub::addBeacons();
}
- mSelectedFaces.reset();
+ mSelectedFaces.clear();
// Draw face highlights for selected faces.
if (gSelectMgr->getTEMode())
@@ -2303,54 +2583,7 @@ void LLPipeline::stateSort()
while (vobjp)
{
- LLDrawable *drawablep = vobjp->mDrawable;
- if (!drawablep || drawablep->isDead() || (!vobjp->isHUDAttachment() && !drawablep->isVisible()))
- {
- llwarns << "Dead drawable on selected face list!" << llendl;
- }
- else
- {
- LLVOVolume *volp = drawablep->getVOVolume();
- if (volp)
- {
- if (volp->getAllTEsSame())
- {
- SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1);
- faceinfo->mFacep = drawablep->getFace(vobjp->getFaceIndexOffset());
- faceinfo->mTE = te;
- }
- else
- {
- // This is somewhat inefficient, but works correctly.
- S32 face_id;
- for (face_id = 0; face_id < vobjp->getVolume()->getNumFaces(); face_id++)
- {
- LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset());
- if (te == facep->getTEOffset())
- {
- SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1);
- faceinfo->mFacep = facep;
- faceinfo->mTE = -1;
- }
- }
- }
- }
- else
- {
- // This is somewhat inefficient, but works correctly.
- S32 face_id;
- for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
- {
- LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset());
- if (te == facep->getTEOffset())
- {
- SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1);
- faceinfo->mFacep = facep;
- faceinfo->mTE = -1;
- }
- }
- }
- }
+ mSelectedFaces.push_back(vobjp->mDrawable->getFace(te));
gSelectMgr->getSelection()->getNextTE(&vobjp,&te);
}
}
@@ -2363,13 +2596,13 @@ static void render_hud_elements()
gPipeline.disableLights();
gPipeline.renderDebug();
-
+
LLGLDisable fog(GL_FOG);
LLGLSUIDefault gls_ui;
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
- gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD bersion in render_ui_3d()
+ gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
// Draw the tracking overlays
LLTracker::render3D();
@@ -2384,7 +2617,7 @@ static void render_hud_elements()
gParcelMgr->render();
gParcelMgr->renderParcelCollision();
}
-
+
// Render debugging beacons.
gObjectList.renderObjectBeacons();
LLHUDObject::renderAll();
@@ -2395,11 +2628,15 @@ static void render_hud_elements()
// This is only set when not rendering the UI, for parcel snapshots
gParcelMgr->render();
}
-
+ else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ LLHUDText::renderAllHUD();
+ }
}
void LLPipeline::renderHighlights()
{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
// Render highlighted faces.
LLColor4 color(1.f, 1.f, 1.f, 0.5f);
@@ -2421,48 +2658,15 @@ void LLPipeline::renderHighlights()
}
mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
- for (S32 i = 0; i < mSelectedFaces.count(); i++)
+ for (U32 i = 0; i < mSelectedFaces.size(); i++)
{
- LLFace *facep = mSelectedFaces[i].mFacep;
+ LLFace *facep = mSelectedFaces[i];
if (!facep || facep->getDrawable()->isDead())
{
llerrs << "Bad face on selection" << llendl;
}
- LLDrawPool* poolp = facep->getPool();
-
- if (!poolp->canUseAGP())
- {
- unbindAGP();
- }
- else if (usingAGP())
- {
- bindAGP();
- }
-
- if (mSelectedFaces[i].mTE == -1)
- {
- // Yes, I KNOW this is stupid...
- poolp->renderFaceSelected(facep, mFaceSelectImagep, color);
- }
- else
- {
- LLVOVolume *volp = (LLVOVolume *)facep->getViewerObject();
- // Do the special coalesced face mode.
- S32 j;
- S32 offset = 0;
- S32 count = volp->getVolume()->getVolumeFace(0).mIndices.size();
- for (j = 0; j <= mSelectedFaces[i].mTE; j++)
- {
- count = volp->getVolume()->getVolumeFace(j).mIndices.size();
- if (j < mSelectedFaces[i].mTE)
- {
- offset += count;
- }
- }
-
- poolp->renderFaceSelected(facep, mFaceSelectImagep, color, offset, count);
- }
+ facep->renderSelected(mFaceSelectImagep, color);
}
}
@@ -2470,26 +2674,16 @@ void LLPipeline::renderHighlights()
{
// Paint 'em red!
color.setVec(1.f, 0.f, 0.f, 0.5f);
- for (S32 i = 0; i < mHighlightFaces.count(); i++)
+ for (U32 i = 0; i < mHighlightFaces.size(); i++)
{
LLFace* facep = mHighlightFaces[i];
- LLDrawPool* poolp = facep->getPool();
- if (!poolp->canUseAGP())
- {
- unbindAGP();
- }
- else if (usingAGP())
- {
- bindAGP();
- }
-
- poolp->renderFaceSelected(facep, LLViewerImage::sNullImagep, color);
+ facep->renderSelected(LLViewerImage::sNullImagep, color);
}
}
// Contains a list of the faces of objects that are physical or
// have touch-handlers.
- mHighlightFaces.reset();
+ mHighlightFaces.clear();
if (mVertexShaderLevel[SHADER_INTERFACE] > 0)
{
@@ -2497,11 +2691,11 @@ void LLPipeline::renderHighlights()
}
}
-void LLPipeline::renderGeom()
+void LLPipeline::renderGeom(LLCamera& camera)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
-
+
if (!mAlphaSizzleImagep)
{
mAlphaSizzleImagep = gImageList.getImage(LLUUID(gViewerArt.getString("alpha_sizzle.tga")), MIPMAP_TRUE, TRUE);
@@ -2513,6 +2707,8 @@ void LLPipeline::renderGeom()
//
//
+ glEnableClientState(GL_VERTEX_ARRAY);
+
stop_glerror();
gFrameStats.start(LLFrameStats::RENDER_SYNC);
@@ -2520,6 +2716,7 @@ void LLPipeline::renderGeom()
#ifndef LL_RELEASE_FOR_DOWNLOAD
LLGLState::checkStates();
LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
#endif
if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
{
@@ -2529,27 +2726,23 @@ void LLPipeline::renderGeom()
}
}
- if (mAGPMemPool)
{
- mAGPMemPool->waitFence(mGlobalFence);
+ //LLFastTimer ftm(LLFastTimer::FTM_TEMP6);
+ LLVertexBuffer::startRender();
}
- unbindAGP();
for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
{
LLDrawPool *poolp = *iter;
if (hasRenderType(poolp->getType()))
{
poolp->prerender();
- poolp->syncAGP();
}
}
gFrameStats.start(LLFrameStats::RENDER_GEOM);
// Initialize lots of GL state to "safe" values
- mTrianglesDrawn = 0;
-
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
@@ -2557,13 +2750,13 @@ void LLPipeline::renderGeom()
LLGLSPipeline gls_pipeline;
LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
- LLGLState normalize(GL_NORMALIZE, TRUE);
+ // LLGLState normalize(GL_NORMALIZE, TRUE);
// Toggle backface culling for debugging
LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
// Set fog
LLGLEnable fog_enable(hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG) ? GL_FOG : 0);
-
+ gSky.updateFog(camera.getFar());
LLViewerImage::sDefaultImagep->bind(0);
LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE);
@@ -2572,19 +2765,20 @@ void LLPipeline::renderGeom()
//
// Actually render all of the geometry
//
- //
-
+ //
stop_glerror();
- BOOL non_agp = FALSE;
BOOL did_hud_elements = FALSE;
-
+ BOOL occlude = sUseOcclusion;
+
U32 cur_type = 0;
- S32 skipped_vertices = 0;
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
+ {
+ gObjectList.renderObjectsForSelect(camera);
+ }
+ else
{
LLFastTimer t(LLFastTimer::FTM_POOLS);
- BOOL occlude = TRUE;
-
calcNearbyLights();
pool_set_t::iterator iter1 = mPools.begin();
@@ -2594,80 +2788,27 @@ void LLPipeline::renderGeom()
cur_type = poolp->getType();
- if (cur_type >= LLDrawPool::POOL_TREE && occlude)
- { //all the occluders have been drawn, do occlusion queries
- if (mVertexShadersEnabled)
- {
- glUseProgramObjectARB(0);
- }
- doOcclusion();
+ if (occlude && cur_type > LLDrawPool::POOL_AVATAR)
+ {
occlude = FALSE;
+ doOcclusion(camera);
}
-
- if (cur_type >= LLDrawPool::POOL_HUD && !did_hud_elements)
+
+ if (cur_type > LLDrawPool::POOL_ALPHA_POST_WATER && !did_hud_elements)
{
renderHighlights();
// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
- if (mVertexShadersEnabled)
- {
- glUseProgramObjectARB(0);
- }
render_hud_elements();
did_hud_elements = TRUE;
}
pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()))
+ if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
{
LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
setupHWLights(poolp);
-
- if (mVertexShadersEnabled && poolp->getVertexShaderLevel() == 0)
- {
- glUseProgramObjectARB(0);
- }
- else if (mVertexShadersEnabled)
- {
- mMaterialIndex = mSpecularIndex = 0;
- switch(cur_type)
- {
- case LLDrawPool::POOL_SKY:
- case LLDrawPool::POOL_STARS:
- case LLDrawPool::POOL_CLOUDS:
- glUseProgramObjectARB(0);
- break;
- case LLDrawPool::POOL_TERRAIN:
- mTerrainProgram.bind();
- break;
- case LLDrawPool::POOL_GROUND:
- mGroundProgram.bind();
- break;
- case LLDrawPool::POOL_TREE:
- case LLDrawPool::POOL_TREE_NEW:
- case LLDrawPool::POOL_SIMPLE:
- case LLDrawPool::POOL_MEDIA:
- mObjectSimpleProgram.bind();
- break;
- case LLDrawPool::POOL_BUMP:
- mObjectBumpProgram.bind();
- break;
- case LLDrawPool::POOL_AVATAR:
- glUseProgramObjectARB(0);
- break;
- case LLDrawPool::POOL_WATER:
- glUseProgramObjectARB(0);
- break;
- case LLDrawPool::POOL_ALPHA:
- mObjectAlphaProgram.bind();
- break;
- case LLDrawPool::POOL_HUD:
- default:
- glUseProgramObjectARB(0);
- break;
- }
- }
-
+
for( S32 i = 0; i < poolp->getNumPasses(); i++ )
{
poolp->beginRenderPass(i);
@@ -2678,33 +2819,19 @@ void LLPipeline::renderGeom()
{
break;
}
- if (p->getType() != LLDrawPool::POOL_AVATAR
- && p->getType() != LLDrawPool::POOL_ALPHA
- && p->getType() != LLDrawPool::POOL_HUD
- && (!p->getIndexCount() || !p->getVertexCount()))
- {
- continue;
- }
-
- if (p->canUseAGP() && usingAGP())
- {
- bindAGP();
- }
- else
- {
- //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl;
- unbindAGP();
- non_agp = TRUE;
- }
-
+
p->resetTrianglesDrawn();
p->render(i);
mTrianglesDrawn += p->getTrianglesDrawn();
- skipped_vertices += p->mSkippedVertices;
- p->mSkippedVertices = 0;
}
poolp->endRenderPass(i);
#ifndef LL_RELEASE_FOR_DOWNLOAD
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
@@ -2726,21 +2853,18 @@ void LLPipeline::renderGeom()
iter1 = iter2;
stop_glerror();
}
-
- if (occlude)
- {
- if (mVertexShadersEnabled)
- {
- glUseProgramObjectARB(0);
- }
- doOcclusion();
- }
}
- stop_glerror();
-
- if (mVertexShadersEnabled)
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+#endif
+
+ if (occlude)
{
- glUseProgramObjectARB(0);
+ doOcclusion(camera);
+ occlude = FALSE;
}
if (!did_hud_elements)
@@ -2748,32 +2872,65 @@ void LLPipeline::renderGeom()
renderHighlights();
render_hud_elements();
}
+
+ stop_glerror();
- static S32 agp_mix_count = 0;
- if (non_agp && usingAGP())
{
- if (0 == agp_mix_count % 16)
- {
- lldebugs << "Mixing AGP and non-AGP pools, slow!" << llendl;
- }
- agp_mix_count++;
+ LLVertexBuffer::stopRender();
}
- else
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+#endif
+
+ // Contains a list of the faces of objects that are physical or
+ // have touch-handlers.
+ mHighlightFaces.clear();
+}
+
+void LLPipeline::processGeometry(LLCamera& camera)
+{
+ if (sSkipUpdate)
{
- agp_mix_count = 0;
+ return;
}
- // Contains a list of the faces of objects that are physical or
- // have touch-handlers.
- mHighlightFaces.reset();
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
+ {
+ mObjectPartition[i]->processGeometry(&camera);
+ }
+ }
+}
- // This wait is in case we try to do multiple renders of a frame,
- // I don't know what happens when we send a fence multiple times without
- // checking it.
- if (mAGPMemPool)
+void LLPipeline::processOcclusion(LLCamera& camera)
+{
+ //process occlusion (readback)
+ if (sUseOcclusion)
{
- mAGPMemPool->waitFence(mGlobalFence);
- mAGPMemPool->sendFence(mGlobalFence);
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
+ {
+ mObjectPartition[i]->processOcclusion(&camera);
+ }
+ }
+
+#if AGGRESSIVE_OCCLUSION
+ for (LLSpatialBridge::bridge_vector_t::iterator i = mOccludedBridge.begin(); i != mOccludedBridge.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ LLCamera trans = bridge->transformCamera(camera);
+ bridge->processOcclusion(&trans);
+ }
+ }
+#endif
+ mOccludedBridge.clear();
}
}
@@ -2782,13 +2939,30 @@ void LLPipeline::renderDebug()
LLMemType mt(LLMemType::MTYPE_PIPELINE);
// Disable all client state
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
// Debug stuff.
- mObjectPartition->renderDebug();
+ for (U32 i = 0; i < mObjectPartition.size(); i++)
+ {
+ if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
+ {
+ mObjectPartition[i]->renderDebug();
+ }
+ }
+
+ for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ glPushMatrix();
+ glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ bridge->renderDebug();
+ glPopMatrix();
+ }
+ }
if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_LIGHT_TRACE)
{
@@ -2835,81 +3009,6 @@ void LLPipeline::renderDebug()
}
}
- mCompilesStat.addValue(sCompiles);
- mLightingChangesStat.addValue(mLightingChanges);
- mGeometryChangesStat.addValue(mGeometryChanges);
- mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
- mVerticesRelitStat.addValue(mVerticesRelit);
- mNumVisibleFacesStat.addValue(mNumVisibleFaces);
- mNumVisibleDrawablesStat.addValue((S32)mVisibleList.size());
-
- if (gRenderLightGlows)
- {
- displaySSBB();
- }
-
- /*if (mRenderDebugMask & RENDER_DEBUG_BBOXES)
- {
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLGLSNoTexture no_texture;
-
- for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); iter != mVisibleList.end(); iter++)
- {
- LLDrawable *drawablep = *iter;
- if (drawablep->isDead())
- {
- continue;
- }
- LLVector3 min, max;
-
- if (drawablep->getVObj() && drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
- {
- // Render drawable bbox
- drawablep->getBounds(min, max);
- glColor4f(0.f, 1.f, 0.f, 0.25f);
- render_bbox(min, max);
-
- // Render object bbox
- LLVector3 scale = drawablep->getVObj()->getScale();
- LLVector3 pos = drawablep->getVObj()->getPositionAgent();
- min = pos - scale * 0.5f;
- max = pos + scale * 0.5f;
- glColor4f(1.f, 0.f, 0.f, 0.25f);
- render_bbox(min, max);
- }
- }
- }*/
-
- /*
- // Debugging code for parcel sound.
- F32 x, y;
-
- LLGLSNoTexture gls_no_texture;
-
- glBegin(GL_POINTS);
- if (gAgent.getRegion())
- {
- // Draw the composition layer for the region that I'm in.
- for (x = 0; x <= 260; x++)
- {
- for (y = 0; y <= 260; y++)
- {
- if (gParcelMgr->isSoundLocal(gAgent.getRegion()->getOriginGlobal() + LLVector3d(x, y, 0.f)))
- {
- glColor4f(1.f, 0.f, 0.f, 1.f);
- }
- else
- {
- glColor4f(0.f, 0.f, 1.f, 1.f);
- }
-
- glVertex3f(x, y, gAgent.getRegion()->getLandHeightRegion(LLVector3(x, y, 0.f)));
- }
- }
- }
- glEnd();
- */
-
if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
{
// Debug composition layers
@@ -2942,358 +3041,163 @@ void LLPipeline::renderDebug()
}
glEnd();
}
-
- if (mRenderDebugMask & RENDER_DEBUG_AGP_MEM)
- {
- displayAGP();
- }
-
- if (mRenderDebugMask & RENDER_DEBUG_POOLS)
- {
- displayPools();
- }
-
-// if (mRenderDebugMask & RENDER_DEBUG_QUEUES)
-// {
-// displayQueues();
-// }
-
- if (mRenderDebugMask & RENDER_DEBUG_MAP)
- {
- displayMap();
- }
}
-
-
-
-BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max)
+void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
{
- min.setVec(1000,1000);
- max.setVec(-1000,-1000);
-
- if (box.mMatrix[3][3] <= 0.0f) return FALSE;
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ LLVertexBuffer::startRender();
+
+ glMatrixMode(GL_MODELVIEW);
- const F32 vec[8][3] = {
- { -0.5f,-0.5f,-0.5f },
- { -0.5f,-0.5f,+0.5f },
- { -0.5f,+0.5f,-0.5f },
- { -0.5f,+0.5f,+0.5f },
- { +0.5f,-0.5f,-0.5f },
- { +0.5f,-0.5f,+0.5f },
- { +0.5f,+0.5f,-0.5f },
- { +0.5f,+0.5f,+0.5f } };
-
- LLVector4 v;
+ LLGLSDefault gls_default;
+ LLGLSObjectSelect gls_object_select;
+ LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
+ disableLights();
+
+ glEnableClientState ( GL_VERTEX_ARRAY );
- for (S32 i=0;i<8;i++)
+ //for each drawpool
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ U32 last_type = 0;
+#endif
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
{
- v.setVec(vec[i][0],vec[i][1],vec[i][2],1);
- v = v * box;
- F32 iw = 1.0f / v.mV[3];
- v.mV[0] *= iw;
- v.mV[1] *= iw;
-
- min.mV[0] = llmin(min.mV[0],v.mV[0]);
- max.mV[0] = llmax(max.mV[0],v.mV[0]);
-
- min.mV[1] = llmin(min.mV[1],v.mV[1]);
- max.mV[1] = llmax(max.mV[1],v.mV[1]);
+ LLDrawPool *poolp = *iter;
+ if (poolp->isFacePool() && hasRenderType(poolp->getType()))
+ {
+ LLFacePool* face_pool = (LLFacePool*) poolp;
+ face_pool->renderForSelect();
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (poolp->getType() != last_type)
+ {
+ last_type = poolp->getType();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+#endif
+ }
}
- /*
- min.mV[0] = max.mV[0] = box.mMatrix[3][0];
- min.mV[1] = max.mV[1] = box.mMatrix[3][1];
- F32 iw = 1.0f / box.mMatrix[3][3];
-
- F32 f0 = (fabs(box.mMatrix[0][0])+fabs(box.mMatrix[1][0])+fabs(box.mMatrix[2][0])) * 0.5f;
- F32 f1 = (fabs(box.mMatrix[0][1])+fabs(box.mMatrix[1][1])+fabs(box.mMatrix[2][1])) * 0.5f;
- F32 f2 = (fabs(box.mMatrix[0][2])+fabs(box.mMatrix[1][2])+fabs(box.mMatrix[2][2])) * 0.5f;
-
- min.mV[0] -= f0;
- min.mV[1] -= f1;
-
- max.mV[0] += f0;
- max.mV[1] += f1;
-
- min.mV[0] *= iw;
- min.mV[1] *= iw;
-
- max.mV[0] *= iw;
- max.mV[1] *= iw;
- */
- return TRUE;
-}
-
-void LLPipeline::displaySSBB()
-{
- LLMatrix4 proj;
- LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
- LLMatrix4 camera;
- LLMatrix4 comb;
-
- gCamera->getMatrixToLocal(camera);
-
- if (!mBloomImagep)
+ LLGLEnable tex(GL_TEXTURE_2D);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ LLGLEnable alpha_test(GL_ALPHA_TEST);
+ if (gPickTransparent)
{
- mBloomImagep = gImageList.getImage(IMG_BLOOM1);
+ glAlphaFunc(GL_GEQUAL, 0.0f);
+ }
+ else
+ {
+ glAlphaFunc(GL_GREATER, 0.2f);
}
- // don't write to depth buffer with light glows so that chat bubbles can pop through
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLViewerImage::bindTexture(mBloomImagep);
-
- glGetFloatv(GL_PROJECTION_MATRIX,(float*)proj.mMatrix);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
- LLGLSPipelineAlpha gls_pipeline_alpha;
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
- //glScalef(0.25,0.25,0.25);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
- S32 sizex = gViewerWindow->getWindowWidth() / 2;
- S32 sizey = gViewerWindow->getWindowHeight() / 2;
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
- F32 aspect = (float)sizey / (float)sizex;
+ U32 prim_mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD;
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
- iter != mLights.end(); iter++)
+ for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
{
- LLDrawable *lightp = *iter;
- if (lightp->isDead())
+ LLViewerObject* vobj = *i;
+ LLDrawable* drawable = vobj->mDrawable;
+ if (vobj->isDead() ||
+ vobj->isHUDAttachment() ||
+ (gHideSelectedObjects && vobj->isSelected()) ||
+ drawable->isDead() ||
+ !hasRenderType(drawable->getRenderType()))
{
continue;
}
-
- LLMatrix4 mat = lightp->mXform.getWorldMatrix();
-
- mat *= camera;
- mat *= cfr;
- mat *= proj;
-
- U8 color[64];
- LLVector2 min,max;
- if (mat.mMatrix[3][3] < 160 && compute_min_max(mat,min,max))
+ for (S32 j = 0; j < drawable->getNumFaces(); ++j)
{
- F32 cx = (max.mV[0] + min.mV[0]) * 0.5f;
- F32 cy = (max.mV[1] + min.mV[1]) * 0.5f;
- F32 sx = (max.mV[0] - min.mV[0]) * 2.0f;
- F32 sy = (max.mV[1] - min.mV[1]) * 2.0f;
- S32 x = (S32)(cx * (F32)sizex) + sizex;
- S32 y = (S32)(cy * (F32)sizey) + sizey;
-
- if (cx > -1 && cx < 1 && cy > -1 && cy < 1)
+ LLFace* facep = drawable->getFace(j);
+ if (!facep->getPool())
{
- glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]);
-
- S32 total = 0;
- for (S32 i=0;i<64;i++)
- {
- total += color[i];
- }
- total /= 64;
-
- sx = (sy = (sx + sy) * 0.5f * ((float)total/255.0f)) * aspect;
-
-
- if (total > 60)
- {
- color[3+32] = total >> 1;
- glBegin(GL_QUADS);
- glColor4ubv(&color[32]);
- glTexCoord2f(0,0);
- glVertex3f(cx-sx,cy-sy,0);
- glTexCoord2f(1,0);
- glVertex3f(cx+sx,cy-sy,0);
- glTexCoord2f(1,1);
- glVertex3f(cx+sx,cy+sy,0);
- glTexCoord2f(0,1);
- glVertex3f(cx-sx,cy+sy,0);
- glEnd();
- }
+ facep->renderForSelect(prim_mask);
}
}
-
}
- // sun
+ // pick HUD objects
+ LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ if (avatarp && sShowHUDAttachments)
{
- LLVector4 sdir(gSky.getSunDirection() * 10000.0f + gAgent.getPositionAgent());
- sdir.mV[3] = 1.0f;
- sdir = sdir * camera;
- sdir = sdir * cfr;
- sdir = sdir * proj; // todo: preconcat
-
- sdir.mV[0] /= sdir.mV[3];
- sdir.mV[1] /= sdir.mV[3];
-
- U8 color[64];
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
- if (sdir.mV[3] > 0)
+ setup_hud_matrices(TRUE);
+ LLViewerJointAttachment* attachmentp;
+ for (attachmentp = avatarp->mAttachmentPoints.getFirstData();
+ attachmentp;
+ attachmentp = avatarp->mAttachmentPoints.getNextData())
{
- F32 cx = sdir.mV[0];
- F32 cy = sdir.mV[1];
- F32 sx, sy;
- S32 x = (S32)(cx * (F32)sizex) + sizex;
- S32 y = (S32)(cy * (F32)sizey) + sizey;
-
- if (cx > -1 && cx < 1 && cy > -1 && cy < 1)
+ if (attachmentp->getIsHUDAttachment())
{
- glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]);
-
- S32 total = 0;
- for (S32 i=0;i<64;i++)
+ LLViewerObject* objectp = attachmentp->getObject();
+ if (objectp)
{
- total += color[i];
- }
- total >>= 7;
-
- sx = (sy = ((float)total/255.0f)) * aspect;
-
- const F32 fix = -0.1f;
+ LLDrawable* drawable = objectp->mDrawable;
+ if (drawable->isDead())
+ {
+ continue;
+ }
- color[32] = (U8)(color[32] * 0.5f + 255 * 0.5f);
- color[33] = (U8)(color[33] * 0.5f + 255 * 0.5f);
- color[34] = (U8)(color[34] * 0.5f + 255 * 0.5f);
+ for (S32 j = 0; j < drawable->getNumFaces(); ++j)
+ {
+ LLFace* facep = drawable->getFace(j);
+ if (!facep->getPool())
+ {
+ facep->renderForSelect(prim_mask);
+ }
+ }
- if (total > 80)
- {
- color[32+3] = (U8)total;
- glBegin(GL_QUADS);
- glColor4ubv(&color[32]);
- glTexCoord2f(0,0);
- glVertex3f(cx-sx,cy-sy+fix,0);
- glTexCoord2f(1,0);
- glVertex3f(cx+sx,cy-sy+fix,0);
- glTexCoord2f(1,1);
- glVertex3f(cx+sx,cy+sy+fix,0);
- glTexCoord2f(0,1);
- glVertex3f(cx-sx,cy+sy+fix,0);
- glEnd();
- }
+ //render child faces
+ for (U32 k = 0; k < drawable->getChildCount(); ++k)
+ {
+ LLDrawable* child = drawable->getChild(k);
+ for (S32 l = 0; l < child->getNumFaces(); ++l)
+ {
+ LLFace* facep = child->getFace(l);
+ if (!facep->getPool())
+ {
+ facep->renderForSelect(prim_mask);
+ }
+ }
+ }
+ }
}
}
- }
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-}
-
-void LLPipeline::displayMap()
-{
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLGLSNoTexture no_texture;
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
-
- glTranslatef(-1,-1,0);
- glScalef(2,2,0);
-
- glColor4f(0,0,0,0.5);
- glBegin(GL_QUADS);
- glVertex3f(0,0,0);
- glVertex3f(1,0,0);
- glVertex3f(1,1,0);
- glVertex3f(0,1,0);
- glEnd();
-
- static F32 totalW = 1.5f;
- static F32 offset = 0.5f;
- static F32 scale = 1.0f;
-
- S32 mousex = gViewerWindow->getCurrentMouseX();
- S32 mousey = gViewerWindow->getCurrentMouseY();
- S32 w = gViewerWindow->getWindowWidth();
- S32 h = gViewerWindow->getWindowHeight();
-
- if (mousex < 20 && offset > 0) offset -= (20 - mousex) * 0.02f;
- if (mousex > (w - 20)) offset += (20 - (w - mousex)) * 0.02f;
- if (offset > (totalW-1)) offset = (totalW-1);
- if (mousey < 20 && scale > 0.1) scale -= (20 - mousey) * 0.001f;
- if (mousey > (h - 20) && scale < 1.0f) scale += (20 - (h - mousey)) * 0.001f;
-
- glScalef(scale*scale,scale,1);
- glTranslatef(-offset,0,0);
- //totalW = mStaticTree->render2D(0,0.8f/scale);
- //mDynamicTree->render2D(0,0.4f/scale);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-}
-
-void LLPipeline::renderForSelect()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- //for each drawpool
-
- glMatrixMode(GL_MODELVIEW);
-
- LLGLSDefault gls_default;
- LLGLSObjectSelect gls_object_select;
- LLGLDepthTest gls_depth(GL_TRUE);
- disableLights();
-
- glEnableClientState ( GL_VERTEX_ARRAY );
- glDisableClientState( GL_NORMAL_ARRAY );
- glDisableClientState( GL_TEXTURE_COORD_ARRAY );
-
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- U32 last_type = 0;
-#endif
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (poolp->canUseAGP() && usingAGP())
- {
- bindAGP();
- }
- else
- {
- //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl;
- unbindAGP();
- }
- poolp->renderForSelect();
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- if (poolp->getType() != last_type)
- {
- last_type = poolp->getType();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- }
-#endif
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
- // Disable all of the client state
- glDisableClientState( GL_VERTEX_ARRAY );
-
- if (mAGPMemPool)
- {
- mAGPMemPool->waitFence(mGlobalFence);
- mAGPMemPool->sendFence(mGlobalFence);
- }
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+
+ LLVertexBuffer::stopRender();
}
void LLPipeline::renderFaceForUVSelect(LLFace* facep)
@@ -3305,7 +3209,6 @@ void LLPipeline::rebuildPools()
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
S32 max_count = mPools.size();
- S32 num_rebuilds = 0;
pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
{
@@ -3314,8 +3217,8 @@ void LLPipeline::rebuildPools()
iter1 = mPools.begin();
}
LLDrawPool* poolp = *iter1;
- num_rebuilds += poolp->rebuild();
- if (poolp->mReferences.empty())
+
+ if (poolp->isDead())
{
mPools.erase(iter1++);
removeFromQuickLookup( poolp );
@@ -3345,27 +3248,35 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
switch( new_poolp->getType() )
{
case LLDrawPool::POOL_SIMPLE:
- mSimplePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+ if (mSimplePool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate simple pool." << llendl;
+ }
+ else
+ {
+ mSimplePool = (LLRenderPass*) new_poolp;
+ }
break;
case LLDrawPool::POOL_TREE:
mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
break;
-
- case LLDrawPool::POOL_TREE_NEW:
- mTreeNewPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
- break;
case LLDrawPool::POOL_TERRAIN:
mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
break;
case LLDrawPool::POOL_BUMP:
- mBumpPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
- break;
-
- case LLDrawPool::POOL_MEDIA:
- mMediaPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+ if (mBumpPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate bump pool." << llendl;
+ }
+ else
+ {
+ mBumpPool = new_poolp;
+ }
break;
case LLDrawPool::POOL_ALPHA:
@@ -3380,6 +3291,18 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ if( mAlphaPoolPostWater )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
+ }
+ else
+ {
+ mAlphaPoolPostWater = new_poolp;
+ }
+ break;
+
case LLDrawPool::POOL_AVATAR:
break; // Do nothing
@@ -3406,19 +3329,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
mStarsPool = new_poolp;
}
break;
-
- case LLDrawPool::POOL_CLOUDS:
- if( mCloudsPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate Clouds pool" << llendl;
- }
- else
- {
- mCloudsPool = new_poolp;
- }
- break;
-
+
case LLDrawPool::POOL_WATER:
if( mWaterPool )
{
@@ -3443,14 +3354,6 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
- case LLDrawPool::POOL_HUD:
- if( mHUDPool )
- {
- llerrs << "LLPipeline::addPool(): Duplicate HUD Pool!" << llendl;
- }
- mHUDPool = new_poolp;
- break;
-
default:
llassert(0);
llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl;
@@ -3471,14 +3374,8 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
switch( poolp->getType() )
{
case LLDrawPool::POOL_SIMPLE:
- #ifdef _DEBUG
- {
- BOOL found = mSimplePools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mSimplePools.erase( (uintptr_t)poolp->getTexture() );
- #endif
+ llassert(mSimplePool == poolp);
+ mSimplePool = NULL;
break;
case LLDrawPool::POOL_TREE:
@@ -3492,17 +3389,6 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
#endif
break;
- case LLDrawPool::POOL_TREE_NEW:
- #ifdef _DEBUG
- {
- BOOL found = mTreeNewPools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mTreeNewPools.erase( (uintptr_t)poolp->getTexture() );
- #endif
- break;
-
case LLDrawPool::POOL_TERRAIN:
#ifdef _DEBUG
{
@@ -3515,32 +3401,20 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
break;
case LLDrawPool::POOL_BUMP:
- #ifdef _DEBUG
- {
- BOOL found = mBumpPools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mBumpPools.erase( (uintptr_t)poolp->getTexture() );
- #endif
- break;
-
- case LLDrawPool::POOL_MEDIA:
- #ifdef _DEBUG
- {
- BOOL found = mMediaPools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mMediaPools.erase( (uintptr_t)poolp->getTexture() );
- #endif
+ llassert( poolp == mBumpPool );
+ mBumpPool = NULL;
break;
-
+
case LLDrawPool::POOL_ALPHA:
llassert( poolp == mAlphaPool );
mAlphaPool = NULL;
break;
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ llassert( poolp == mAlphaPoolPostWater );
+ mAlphaPoolPostWater = NULL;
+ break;
+
case LLDrawPool::POOL_AVATAR:
break; // Do nothing
@@ -3554,11 +3428,6 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mStarsPool = NULL;
break;
- case LLDrawPool::POOL_CLOUDS:
- llassert( poolp == mCloudsPool );
- mCloudsPool = NULL;
- break;
-
case LLDrawPool::POOL_WATER:
llassert( poolp == mWaterPool );
mWaterPool = NULL;
@@ -3569,11 +3438,6 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mGroundPool = NULL;
break;
- case LLDrawPool::POOL_HUD:
- llassert( poolp == mHUDPool );
- mHUDPool = NULL;
- break;
-
default:
llassert(0);
llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
@@ -3581,17 +3445,6 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
}
}
-void LLPipeline::flushAGPMemory()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- poolp->flushAGP();
- }
-}
-
void LLPipeline::resetDrawOrders()
{
// Iterate through all of the draw pools and rebuild them.
@@ -3602,346 +3455,6 @@ void LLPipeline::resetDrawOrders()
}
}
-//-------------------------------
-
-
-LLViewerObject *LLPipeline::nearestObjectAt(F32 yaw, F32 pitch)
-{
- // Stub to find nearest Object at given yaw and pitch
-
- /*
- LLEdge *vd = NULL;
-
- if (vd)
- {
- return (LLViewerObject*)vd->mDrawablep->getVObj();
- }
- */
-
- return NULL;
-}
-
-void LLPipeline::printPools()
-{
- /*
- // Iterate through all of the draw pools and rebuild them.
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (pool->mTexturep[0])
- {
- llinfos << "Op pool " << pool->mTexturep[0]->mID << llendflush;
- }
- else
- {
- llinfos << "Opaque pool NULL" << llendflush;
- }
- llinfos << " Vertices: \t" << pool->getVertexCount() << llendl;
- }
-
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- llinfos << "Al pool " << pool;
- llcont << " Vertices: \t" << pool->getVertexCount() << llendl;
- }
-
- pool = mHighlightPools.getFirst();
- llinfos << "Si pool " << pool;
- llcont << " Vertices: \t" << pool->getVertexCount() << llendl;
- */
-}
-
-
-void LLPipeline::displayPools()
-{
- // Needs to be fixed to handle chained pools - djs
- LLUI::setLineWidth(1.0);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLGLSNoTexture no_texture;
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- glScalef(2,2,1);
- glTranslatef(-0.5f,-0.5f,0);
-
- F32 x = 0.0f, y = 0.05f;
- F32 xs = 0.01f, ys = 0.01f;
- F32 xs2 = xs*0.1f, ys2 = ys * 0.1f;
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLGLSTexture gls_texture;
- LLDrawPool *poolp = *iter;
- if (poolp->getDebugTexture())
- {
- poolp->getDebugTexture()->bind();
- glColor4f(1,1,1,1);
- stamp(x,y,xs*4,ys*4);
- }
-
- LLGLSNoTexture no_texture;
-
- F32 a = 1.f - (F32)poolp->mRebuildTime / (F32)poolp->mRebuildFreq;
- glColor4f(a,a,a,1);
- stamp(x,y,xs,ys);
-
- x = (xs + xs2) * 4.0f;
-
- F32 h = ys * 0.5f;
-
- S32 total = 0;
-
- for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin();
- iter != poolp->mReferences.end(); iter++)
- {
- LLFace *face = *iter;
- F32 w = xs;
-
- if (!face || !face->getDrawable())
- {
- w = 16 / 3000.0f;
-
- stamp(x,y,w,h);
-
- if (x+w > 0.95f)
- {
- x = (xs + xs2) * 4.0f;
- y += h + ys2;
- }
- else
- {
- if (w) x += w + xs2;
- }
-
- continue;
- }
-
- if (face->getDrawable()->isVisible())
- {
- if (face->isState(LLFace::BACKLIST))
- {
- glColor4f(1,0,1,1);
- }
- else if (total > poolp->getMaxVertices())
- {
- glColor4f(1,0,0,1);
- }
- else
- {
- glColor4f(0,1,0,1);
- total += face->getGeomCount();
- }
- }
- else
- {
- if (face->isState(LLFace::BACKLIST))
- {
- glColor4f(0,0,1,1);
- }
- else
- {
- glColor4f(1,1,0,1);
- }
- }
-
- w = face->getGeomCount() / 3000.0f;
-
- stamp(x,y,w,h);
-
- if (x+w > 0.95f)
- {
- x = (xs + xs2) * 4.0f;
- y += h + ys2;
- }
- else
- {
- if (w) x += w + xs2;
- }
- }
-
- y += ys + ys2;
- x = 0;
- }
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-}
-
-static F32 xs = 0.01f, ys = 0.01f;
-static F32 xs2 = xs*0.1f, ys2 = ys * 0.1f;
-static F32 winx, winy;
-
-void displayDrawable(F32 &x, F32 &y, LLDrawable *drawable, F32 alpha = 0.5f)
-{
- F32 w = 0;
- F32 h = ys * 0.5f;
-
- if (drawable && !drawable->isDead())
- {
- for (S32 f=0;f < drawable->getNumFaces(); f++)
- {
- w += drawable->getFace(f)->getGeomCount() / 30000.0f;
- }
- w+=xs;
- glColor4f(1,1,0, alpha);
- }
- else
- {
- w = 0.01f;
- glColor4f(0,0,0,alpha);
- }
-
-// const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
-
-// U8 pcode = drawable->getVObj()->getPCode();
-
- //char *string = (char*)LLPrimitive::pCodeToString(pcode);
- //if (pcode == 0x3e) string = "terrain";
- //else if (pcode == 0x2e) string = "cloud";
- //string[3] = 0;
-
- stamp(x * winx,y * winy,w * winx,h * winy);
-
- /*
- glColor4f(0,0,0,1);
- font->render(string,x*winx+1,y*winy+1);
- LLGLSNoTexture no_texture;
- */
-
- if (x+w > 0.95f)
- {
- x = (xs + xs2) * 4.0f;
- y += h + ys2;
- }
- else
- {
- if (w) x += w + xs2;
- }
-
-}
-
-#if 0 // No longer up date
-
-void displayQueue(F32 &x, F32 &y, LLDynamicArray<LLDrawable*>& processed, LLDynamicQueuePtr<LLPointer<LLDrawable> >& remaining)
-{
- S32 i;
- for (i=0;i<processed.count();i++)
- {
- displayDrawable(x,y,processed[i],1);
- }
-
- x += xs * 2;
-
- S32 count = remaining.count();
- for (i=0;i<count;i++)
- {
- LLDrawable* drawablep = remaining[(i + remaining.getFirst()) % remaining.getMax()];
- if (drawablep && !drawablep->isDead())
- {
- displayDrawable(x,y,drawable,0.5);
- }
- }
-
- y += ys * 4;
- x = (xs + xs2) * 4.0f;
-
-}
-
-void LLPipeline::displayQueues()
-{
- LLUI::setLineWidth(1.0);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLGLSNoTexture no_texture;
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- glScalef(2,2,1);
- glTranslatef(-0.5f,-0.5f,0);
-
- winx = (F32)gViewerWindow->getWindowWidth();
- winy = (F32)gViewerWindow->getWindowHeight();
-
- glScalef(1.0f/winx,1.0f/winy,1);
-
- F32 x = (xs + xs2) * 4.0f;
- F32 y = 0.1f;
-
- const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF );
-
- font->renderUTF8("Build1", 0,0,(S32)(y*winy),LLColor4(1,1,1,1));
- displayQueue(x,y, gBuildProcessed, mBuildQ1);
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-
-}
-
-#endif
-
-// static
-void render_bbox(const LLVector3 &min, const LLVector3 &max)
-{
- S32 i;
- LLVector3 verticesp[16];
-
- verticesp[0].setVec(min.mV[0],min.mV[1],max.mV[2]);
- verticesp[1].setVec(min.mV[0],min.mV[1],min.mV[2]);
- verticesp[2].setVec(min.mV[0],max.mV[1],min.mV[2]);
- verticesp[3].setVec(min.mV[0],max.mV[1],max.mV[2]);
- verticesp[4].setVec(max.mV[0],max.mV[1],max.mV[2]);
- verticesp[5].setVec(max.mV[0],max.mV[1],min.mV[2]);
- verticesp[6].setVec(max.mV[0],min.mV[1],min.mV[2]);
- verticesp[7].setVec(max.mV[0],min.mV[1],max.mV[2]);
- verticesp[8 ] = verticesp[0];
- verticesp[9 ] = verticesp[1];
- verticesp[10] = verticesp[6];
- verticesp[11] = verticesp[7];
- verticesp[12] = verticesp[4];
- verticesp[13] = verticesp[5];
- verticesp[14] = verticesp[2];
- verticesp[15] = verticesp[3];
-
- LLGLSNoTexture gls_no_texture;
- {
- LLUI::setLineWidth(1.f);
- glBegin(GL_LINE_LOOP);
- for (i = 0; i < 16; i++)
- {
- glVertex3fv(verticesp[i].mV);
- }
- glEnd();
- }
- {
- LLGLDepthTest gls_depth(GL_TRUE);
- LLUI::setLineWidth(3.0f);
- glBegin(GL_LINE_LOOP);
- for (i = 0; i < 16; i++)
- {
- glVertex3fv(verticesp[i].mV);
- }
- glEnd();
- }
- LLUI::setLineWidth(1.0f);
-}
-
//============================================================================
// Once-per-frame setup of hardware lights,
// including sun/moon, avatar backlight, and up to 6 local lights
@@ -4153,8 +3666,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
{
const LLColor4 black(0,0,0,1);
- setLightingDetail(-1); // update
-
// Ambient
LLColor4 ambient = gSky.getTotalAmbientColor();
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
@@ -4410,16 +3921,6 @@ class LLVOBranch;
class LLVOLeaf;
class Foo;
-template<> char* LLAGPArray<U8>::sTypeName = "U8 [AGP]";
-template<> char* LLAGPArray<U32>::sTypeName = "U32 [AGP]";
-template<> char* LLAGPArray<F32>::sTypeName = "F32 [AGP]";
-template<> char* LLAGPArray<LLColor4>::sTypeName = "LLColor4 [AGP]";
-template<> char* LLAGPArray<LLColor4U>::sTypeName = "LLColor4U [AGP]";
-template<> char* LLAGPArray<LLVector4>::sTypeName = "LLVector4 [AGP]";
-template<> char* LLAGPArray<LLVector3>::sTypeName = "LLVector3 [AGP]";
-template<> char* LLAGPArray<LLVector2>::sTypeName = "LLVector2 [AGP]";
-template<> char* LLAGPArray<LLFace*>::sTypeName = "LLFace* [AGP]";
-
void scale_stamp(const F32 x, const F32 y, const F32 xs, const F32 ys)
{
stamp(0.25f + 0.5f*x,
@@ -4461,221 +3962,6 @@ void drawBars(const F32 begin, const F32 end, const F32 height = 1.f)
}
}
-void LLPipeline::displayAGP()
-{
- LLUI::setLineWidth(1.0);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- LLGLSPipelineAlpha gls_alpha;
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
- glScalef(2,2,1);
- glTranslatef(-0.5f,-0.5f,0);
-
- glColor4f(0,0,0,0.5f);
- scale_stamp(0,0,1,1);
-
- F32 x = 0.0f, y = 0.05f;
- F32 xs = 0.015f, ys = 0.015f;
- F32 xs2 = xs*0.1f, ys2 = ys * 0.1f;
- F32 w = xs+xs2, h = ys + ys2;
- S32 i=0;
-
- F32 agp_size = 1.f;
- if (mAGPMemPool)
- {
- agp_size = (F32)mAGPMemPool->getSize();
- }
-
- x = (xs + xs2) * 4.0f;
-
- static float c = 0.0f;
- c += 0.0001f;
-
- LLAGPMemBlock *blockp = mBufferMemory[mBufferIndex]->getAGPMemBlock();
-
- pool_set_t::iterator iter = mPools.begin();
- LLDrawPool *poolp = *iter;
-
- // Dump the shared AGP buffer
- if (blockp)
- {
- F32 begin = blockp->getOffset()/agp_size;
- F32 end = begin + (blockp->getSize()/agp_size);
- F32 used = begin + (poolp->mMemory.count()/agp_size);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
- drawBars(begin,used, 0.5f);
-
- glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
- drawBars(begin,end, 0.25f);
- }
-
- S32 used_bytes = 0;
- S32 total_bytes = 0;
- while (iter != mPools.end())
- {
- poolp = *iter++;
-
- BOOL synced = FALSE;
- i++;
- total_bytes += poolp->mMemory.getMax();
- used_bytes += poolp->mMemory.count();
- LLViewerImage *texturep = poolp->getDebugTexture();
-
-
- if (poolp->mMemory.mSynced)
- {
- poolp->mMemory.mSynced = FALSE;
- synced = TRUE;
- }
-
- LLAGPMemBlock *blockp = poolp->mMemory.getAGPMemBlock();
- if (blockp)
- {
- F32 begin = blockp->getOffset()/agp_size;
- F32 end = begin + (blockp->getSize()/agp_size);
- F32 used = begin + (poolp->mMemory.count()/agp_size);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(1.f, 0.5f, 0.5f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(texturep);
- glColor4f(1.f, 0.75f, 0.75f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(1.f, 0.75f, 0.75f, 1.f);
- drawBars(begin,used, 0.5f);
-
- glColor3fv(poolp->getDebugColor().mV);
- drawBars(begin,end, 0.25f);
-
- if (synced)
- {
- LLViewerImage::bindTexture(NULL);
- glColor4f(1.f, 1.f, 1.f, 0.4f);
- drawBars(begin,end);
- }
- }
-
- synced = FALSE;
- if (poolp->mWeights.mSynced)
- {
- poolp->mWeights.mSynced = FALSE;
- synced = TRUE;
- }
- blockp = poolp->mWeights.getAGPMemBlock();
- if (blockp)
- {
- F32 begin = blockp->getOffset()/agp_size;
- F32 end = begin + (blockp->getSize()/agp_size);
- F32 used = begin + (poolp->mWeights.count()*sizeof(float)/agp_size);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.0f, 0.f, 0.75f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(texturep);
- glColor4f(0.0, 0.f, 0.75f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.0, 0.f, 0.75f, 1.f);
- drawBars(begin,used, 0.5f);
-
- LLViewerImage::bindTexture(NULL);
- glColor3fv(poolp->getDebugColor().mV);
- drawBars(begin,end, 0.25f);
-
- if (synced)
- {
- LLViewerImage::bindTexture(NULL);
- glColor4f(1.f, 1.f, 1.f, 0.4f);
- drawBars(begin,end);
- }
- }
-
- synced = FALSE;
- if (poolp->mClothingWeights.mSynced)
- {
- poolp->mClothingWeights.mSynced = FALSE;
- synced = TRUE;
- }
- blockp = poolp->mClothingWeights.getAGPMemBlock();
- if (blockp)
- {
- F32 begin = blockp->getOffset()/agp_size;
- F32 end = begin + (blockp->getSize()/agp_size);
- F32 used = begin + (poolp->mClothingWeights.count()*sizeof(LLVector4)/agp_size);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.75f, 0.f, 0.75f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(texturep);
- glColor4f(0.75f, 0.f, 0.75f, 0.5f);
- drawBars(begin,end);
-
- LLViewerImage::bindTexture(NULL);
- glColor4f(0.75f, 0.f, 0.75f, 0.5f);
- drawBars(begin,used, 0.5f);
-
- LLViewerImage::bindTexture(NULL);
- glColor3fv(poolp->getDebugColor().mV);
- drawBars(begin,end, 0.25f);
-
- if (synced)
- {
- LLViewerImage::bindTexture(NULL);
- glColor4f(1.f, 1.f, 1.f, 0.5f);
- drawBars(begin,end);
- }
- }
-
- //
- // Stamps on bottom of screen
- //
- LLViewerImage::bindTexture(texturep);
- glColor4f(1.f, 1.f, 1.f, 1.f);
- stamp(x,y,xs,ys);
-
- LLViewerImage::bindTexture(NULL);
- glColor3fv(poolp->getDebugColor().mV);
- stamp(x,y,xs, ys*0.25f);
- if (x+w > 0.95f)
- {
- x = (xs + xs2) * 4.0f;
- y += h;
- }
- else
- {
- x += w + xs2;
- }
- }
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-}
-
void LLPipeline::findReferences(LLDrawable *drawablep)
{
if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) != mVisibleList.end())
@@ -4686,7 +3972,7 @@ void LLPipeline::findReferences(LLDrawable *drawablep)
{
llinfos << "In mLights" << llendl;
}
- if (mMovedList.find(drawablep) != mMovedList.end())
+ if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
{
llinfos << "In mMovedList" << llendl;
}
@@ -4698,18 +3984,14 @@ void LLPipeline::findReferences(LLDrawable *drawablep)
{
llinfos << "In mRetexturedList" << llendl;
}
- if (mRematerialedList.find(drawablep) != mRematerialedList.end())
- {
- llinfos << "In mRematerialedList" << llendl;
- }
-
+
if (mActiveQ.find(drawablep) != mActiveQ.end())
{
llinfos << "In mActiveQ" << llendl;
}
- if (mBuildQ1.find(drawablep) != mBuildQ1.end())
+ if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
{
- llinfos << "In mBuildQ2" << llendl;
+ llinfos << "In mBuildQ1" << llendl;
}
if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
{
@@ -4717,19 +3999,7 @@ void LLPipeline::findReferences(LLDrawable *drawablep)
}
S32 count;
- /*
- count = mStaticTree->count(drawablep);
- if (count)
- {
- llinfos << "In mStaticTree: " << count << " references" << llendl;
- }
-
- count = mDynamicTree->count(drawablep);
- if (count)
- {
- llinfos << "In mStaticTree: " << count << " references" << llendl;
- }
- */
+
count = gObjectList.findReferences(drawablep);
if (count)
{
@@ -4756,53 +4026,6 @@ BOOL LLPipeline::verify()
return ok;
}
-S32 LLPipeline::getAGPMemUsage()
-{
- if (mAGPMemPool)
- {
- return mAGPMemPool->getSize();
- }
- else
- {
- return 0;
- }
-}
-
-S32 LLPipeline::getMemUsage(const BOOL print)
-{
- S32 mem_usage = 0;
-
- if (mAGPMemPool)
- {
- S32 agp_usage = 0;
- agp_usage = mAGPMemPool->getSize();
- if (print)
- {
- llinfos << "AGP Mem: " << agp_usage << llendl;
- llinfos << "AGP Mem used: " << mAGPMemPool->getTotalAllocated() << llendl;
- }
- mem_usage += agp_usage;
- }
-
-
- S32 pool_usage = 0;
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- pool_usage += poolp->getMemUsage(print);
- }
-
- if (print)
- {
- llinfos << "Pool Mem: " << pool_usage << llendl;
- }
-
- mem_usage += pool_usage;
-
- return mem_usage;
-
-}
-
//////////////////////////////
//
// Collision detection
@@ -4913,8 +4136,8 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
}
else
{
- mLights.erase(drawablep);
drawablep->clearState(LLDrawable::LIGHT);
+ mLights.erase(drawablep);
}
markRelight(drawablep);
}
@@ -4933,9 +4156,16 @@ void LLPipeline::setActive(LLDrawable *drawablep, BOOL active)
}
//static
-void LLPipeline::toggleRenderType(void* data)
+void LLPipeline::toggleRenderType(U32 type)
{
- S32 type = (S32)(intptr_t)data;
+ U32 bit = (1<<type);
+ gPipeline.mRenderTypeMask ^= bit;
+}
+
+//static
+void LLPipeline::toggleRenderTypeControl(void* data)
+{
+ U32 type = (U32)(intptr_t)data;
U32 bit = (1<<type);
if (gPipeline.hasRenderType(type))
{
@@ -4945,13 +4175,13 @@ void LLPipeline::toggleRenderType(void* data)
{
llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
}
- gPipeline.mRenderTypeMask ^= bit;
+ gPipeline.toggleRenderType(type);
}
//static
-BOOL LLPipeline::toggleRenderTypeControl(void* data)
+BOOL LLPipeline::hasRenderTypeControl(void* data)
{
- S32 type = (S32)(intptr_t)data;
+ U32 type = (U32)(intptr_t)data;
return gPipeline.hasRenderType(type);
}
@@ -4990,14 +4220,6 @@ BOOL LLPipeline::toggleRenderDebugControl(void* data)
void LLPipeline::toggleRenderDebugFeature(void* data)
{
U32 bit = (U32)(intptr_t)data;
- if (gPipeline.hasRenderDebugFeatureMask(bit))
- {
- llinfos << "Toggling render debug feature mask " << std::hex << bit << " off" << std::dec << llendl;
- }
- else
- {
- llinfos << "Toggling render debug feature mask " << std::hex << bit << " on" << std::dec << llendl;
- }
gPipeline.mRenderDebugFeatureMask ^= bit;
}
@@ -5310,8 +4532,375 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision)
{
- LLDrawable* drawable = mObjectPartition->pickDrawable(start, end, collision);
+ LLDrawable* drawable = mObjectPartition[PARTITION_VOLUME]->pickDrawable(start, end, collision);
return drawable ? drawable->getVObj() : NULL;
}
+LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
+{
+ if (vobj)
+ {
+ return getSpatialPartition(vobj->getPartitionType());
+ }
+ return NULL;
+}
+
+LLSpatialPartition* LLPipeline::getSpatialPartition(U32 type)
+{
+ if (type < mObjectPartition.size())
+ {
+ return mObjectPartition[type];
+ }
+ return NULL;
+}
+
+void LLPipeline::clearRenderMap()
+{
+ for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
+ {
+ mRenderMap[i].clear();
+ }
+}
+
+
+void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
+{
+ for (S32 i = 0; i < drawable->getNumFaces(); i++)
+ {
+ LLFace* facep = drawable->getFace(i);
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ }
+}
+
+void LLPipeline::resetVertexBuffers()
+{
+ for (U32 i = 0; i < mObjectPartition.size(); ++i)
+ {
+ if (mObjectPartition[i])
+ {
+ mObjectPartition[i]->resetVertexBuffers();
+ }
+ }
+
+ resetDrawOrders();
+
+ if (gSky.mVOSkyp.notNull())
+ {
+ resetVertexBuffers(gSky.mVOSkyp->mDrawable);
+ resetVertexBuffers(gSky.mVOGroundp->mDrawable);
+ resetVertexBuffers(gSky.mVOStarsp->mDrawable);
+ markRebuild(gSky.mVOSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+
+ if (LLVertexBuffer::sGLCount > 0)
+ {
+ LLVertexBuffer::cleanupClass();
+ }
+}
+
+void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
+{
+ mSimplePool->renderStatic(type, mask, texture);
+ mSimplePool->renderActive(type, mask, texture);
+}
+
+void LLPipeline::setUseVBO(BOOL use_vbo)
+{
+ if (use_vbo != LLVertexBuffer::sEnableVBOs)
+ {
+ if (use_vbo)
+ {
+ llinfos << "Enabling VBO." << llendl;
+ }
+ else
+ {
+ llinfos << "Disabling VBO." << llendl;
+ }
+
+ resetVertexBuffers();
+ LLVertexBuffer::initClass(use_vbo);
+ }
+}
+
+void apply_cube_face_rotation(U32 face)
+{
+ switch (face)
+ {
+ case 0:
+ glRotatef(90.f, 0, 1, 0);
+ glRotatef(180.f, 1, 0, 0);
+ break;
+ case 2:
+ glRotatef(-90.f, 1, 0, 0);
+ break;
+ case 4:
+ glRotatef(180.f, 0, 1, 0);
+ glRotatef(180.f, 0, 0, 1);
+ break;
+ case 1:
+ glRotatef(-90.f, 0, 1, 0);
+ glRotatef(180.f, 1, 0, 0);
+ break;
+ case 3:
+ glRotatef(90, 1, 0, 0);
+ break;
+ case 5:
+ glRotatef(180, 0, 0, 1);
+ break;
+ }
+}
+void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, GLsizei res)
+{
+ //render dynamic cube map
+ U32 type_mask = gPipeline.getRenderTypeMask();
+ BOOL use_occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = FALSE;
+ LLPipeline::sSkipUpdate = TRUE;
+ static GLuint blur_tex = 0;
+ if (!blur_tex)
+ {
+ glGenTextures(1, &blur_tex);
+ }
+
+ BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ if (toggle_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_WATER) |
+ (1 << LLPipeline::RENDER_TYPE_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_TREE) |
+ (1 << LLDrawPool::POOL_ALPHA_POST_WATER) |
+ //(1 << LLPipeline::RENDER_TYPE_PARTICLES) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ //(1 << LLPipeline::RENDER_TYPE_STARS) |
+ //(1 << LLPipeline::RENDER_TYPE_AVATAR) |
+ (1 << LLPipeline::RENDER_TYPE_GRASS) |
+ (1 << LLPipeline::RENDER_TYPE_VOLUME) |
+ (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
+ (1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_GROUND);
+ LLDrawPoolWater::sSkipScreenCopy = TRUE;
+ cube_mask = cube_mask & type_mask;
+ gPipeline.setRenderTypeMask(cube_mask);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glViewport(0,0,res,res);
+
+ glClearColor(0,0,0,0);
+
+ U32 cube_face[] =
+ {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+ };
+
+ LLVector3 origin = cube_cam.getOrigin();
+
+ gPipeline.calcNearbyLights();
+
+ for (S32 i = 0; i < 6; i++)
+ {
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(90.f, 1.f, 0.1f, 1024.f);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ apply_cube_face_rotation(i);
+
+
+ glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
+ cube_cam.setOrigin(origin);
+ LLViewerCamera::updateFrustumPlanes(cube_cam);
+ cube_cam.setOrigin(gCamera->getOrigin());
+ gPipeline.updateCull(cube_cam);
+ gPipeline.stateSort(cube_cam);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ gPipeline.renderGeom(cube_cam);
+
+ cube_map->enable(0);
+ cube_map->bind();
+ glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, 0, res, res, 0);
+ cube_map->disable();
+ }
+
+ cube_cam.setOrigin(origin);
+ gPipeline.resetDrawOrders();
+ gPipeline.mShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ gPipeline.setRenderTypeMask(type_mask);
+ LLPipeline::sUseOcclusion = use_occlusion;
+ LLPipeline::sSkipUpdate = FALSE;
+
+ if (toggle_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ LLDrawPoolWater::sSkipScreenCopy = FALSE;
+}
+
+//send cube map vertices and texture coordinates
+void render_cube_map()
+{
+ if (gPipeline.mCubeList == 0)
+ {
+ gPipeline.mCubeList = glGenLists(1);
+ glNewList(gPipeline.mCubeList, GL_COMPILE);
+
+ U32 idx[36];
+
+ idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
+ idx[3] = 3; idx[4] = 2; idx[5] = 0;
+
+ idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
+ idx[9] = 0; idx[10] = 1; idx[11] = 5;
+
+ idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
+ idx[15] = 7; idx[16] = 6; idx[17] = 4;
+
+ idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
+ idx[21] = 2; idx[22] = 3; idx[23] = 7;
+
+ idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
+ idx[27] = 6; idx[28] = 3; idx[29] = 5;
+
+ idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
+ idx[33] = 2; idx[34] = 7; idx[35] = 1;
+
+ LLVector3 vert[8];
+ LLVector3 r = LLVector3(1,1,1);
+
+ vert[0] = r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front
+ vert[1] = r.scaledVec(LLVector3(1,1,1)); // 1 - right top front
+ vert[2] = r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front
+ vert[3] = r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front
+
+ vert[4] = r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back
+ vert[5] = r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back
+ vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back
+ vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
+
+ glBegin(GL_TRIANGLES);
+ for (U32 i = 0; i < 36; i++)
+ {
+ glTexCoord3fv(vert[idx[i]].mV);
+ glVertex3fv(vert[idx[i]].mV);
+ }
+ glEnd();
+
+ glEndList();
+ }
+
+ glCallList(gPipeline.mCubeList);
+
+}
+
+void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res)
+{
+ LLGLEnable cube(GL_TEXTURE_CUBE_MAP_ARB);
+ LLGLDepthTest depth(GL_FALSE);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glViewport(0, 0, res, res);
+ LLGLEnable blend(GL_BLEND);
+
+ S32 kernel = 2;
+ F32 step = 90.f/res;
+ F32 alpha = 1.f/((kernel*2+1));
+
+ glColor4f(1,1,1,alpha);
+
+ S32 x = 0;
+
+ U32 cube_face[] =
+ {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+ };
+
+ LLVector3 axis[] =
+ {
+ LLVector3(1,0,0),
+ LLVector3(0,1,0),
+ LLVector3(0,0,1)
+ };
+
+
+ glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
+ //3-axis blur
+ for (U32 j = 0; j < 3; j++)
+ {
+ glViewport(0,0,res, res*6);
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (j == 0)
+ {
+ cube_in->bind();
+ }
+
+ for (U32 i = 0; i < 6; i++)
+ {
+ glViewport(0,i*res, res, res);
+ glLoadIdentity();
+ apply_cube_face_rotation(i);
+ for (x = -kernel; x <= kernel; ++x)
+ {
+ glPushMatrix();
+ glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]);
+ render_cube_map();
+ glPopMatrix();
+ }
+ }
+
+ //readback
+ if (j == 0)
+ {
+ cube_out->bind();
+ }
+ for (U32 i = 0; i < 6; i++)
+ {
+ glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, i*res, res, res, 0);
+ }
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index f4144b6afa..af772fd60d 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -9,7 +9,6 @@
#ifndef LL_PIPELINE_H
#define LL_PIPELINE_H
-#include "llagparray.h"
#include "lldarrayptr.h"
#include "lldqueueptr.h"
#include "llstat.h"
@@ -31,8 +30,7 @@ class LLAgent;
class LLDisplayPrimitive;
class LLTextureEntry;
class LLRenderFunc;
-class LLAGPMemPool;
-class LLAGPMemBlock;
+class LLCubeMap;
typedef enum e_avatar_skinning_method
{
@@ -43,6 +41,7 @@ typedef enum e_avatar_skinning_method
BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here!
bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0);
BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
+BOOL setup_hud_matrices(BOOL for_select);
class LLGLSLShader
{
@@ -72,7 +71,6 @@ public:
void bind();
void unbind();
-
GLhandleARB mProgramObject;
std::vector<GLint> mAttribute;
std::vector<GLint> mUniform;
@@ -88,6 +86,11 @@ public:
void destroyGL();
void restoreGL();
+ void resetVertexBuffers();
+ void resetVertexBuffers(LLDrawable* drawable);
+ void setUseVBO(BOOL use_vbo);
+ void generateReflectionMap(LLCubeMap* cube_map, LLCamera& camera, GLsizei res);
+ void blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res);
void init();
void cleanup();
@@ -102,6 +105,7 @@ public:
/// @brief Figures out draw pool type from texture entry. Creates pool if necessary.
static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerImage* te_image);
+ static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep);
void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools!
void removePool( LLDrawPool* poolp );
@@ -111,28 +115,26 @@ public:
void unlinkDrawable(LLDrawable*);
// Object related methods
- void markVisible(LLDrawable *drawablep);
- void doOcclusion();
- void markNotCulled(LLDrawable* drawablep, LLCamera& camera);
+ void markVisible(LLDrawable *drawablep, LLCamera& camera);
+ void doOcclusion(LLCamera& camera);
+ void markNotCulled(LLSpatialGroup* group, LLCamera &camera, BOOL active = FALSE);
void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE);
void markShift(LLDrawable *drawablep);
void markTextured(LLDrawable *drawablep);
- void markMaterialed(LLDrawable *drawablep);
void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
+ void markRebuild(LLSpatialGroup* groupp);
void markRelight(LLDrawable *drawablep, const BOOL now = FALSE);
//get the object between start and end that's closest to start. Return the point of collision in collision.
LLViewerObject* pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision);
-
- void dirtyPoolObjectTextures(const LLViewerImage *texture); // Something about this texture has changed. Dirty it.
+
+ // Something about these textures has changed. Dirty them.
+ void dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures);
void resetDrawOrders();
U32 addObject(LLViewerObject *obj);
- BOOL usingAGP() const;
- void setUseAGP(const BOOL use_agp); // Attempt to use AGP;
-
void enableShadows(const BOOL enable_shadows);
// void setLocalLighting(const BOOL local_lighting);
@@ -155,61 +157,43 @@ public:
BOOL validateProgramObject(GLhandleARB obj);
GLhandleARB loadShader(const LLString& filename, S32 cls, GLenum type);
- void setUseOcclusionCulling(BOOL b) { mUseOcclusionCulling = b; }
- BOOL getUseOcclusionCulling() const { return mUseOcclusionCulling; }
-
- BOOL initAGP();
- void cleanupAGP();
- LLAGPMemBlock *allocAGPFromPool(const S32 bytes, const U32 target); // Static flag is ignored for now.
- void flushAGPMemory(); // Clear all AGP memory blocks (to pack & reduce fragmentation)
-
// phases
void resetFrameStats();
void updateMoveDampedAsync(LLDrawable* drawablep);
void updateMoveNormalAsync(LLDrawable* drawablep);
+ void updateMovedList(LLDrawable::drawable_vector_t& move_list);
void updateMove();
- void updateCull();
+ void updateCull(LLCamera& camera);
void updateGeom(F32 max_dtime);
- void stateSort();
+ //calculate pixel area of given box from vantage point of given camera
+ static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera);
- void renderGeom();
+ void stateSort(LLCamera& camera);
+ void stateSort(LLSpatialGroup* group, LLCamera& camera);
+ void stateSort(LLSpatialBridge* bridge, LLCamera& camera);
+ void stateSort(LLDrawable* drawablep, LLCamera& camera);
+ void postSort(LLCamera& camera);
+ void forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*));
+ void forAllVisibleDrawables(void (*func)(LLDrawable*));
+ static void highlightPhysical(LLDrawable* drawablep);
+
+ void renderObjects(U32 type, U32 mask, BOOL texture = TRUE);
+
+ void renderGeom(LLCamera& camera);
void renderHighlights();
void renderDebug();
+ void processGeometry(LLCamera& camera);
+ void processOcclusion(LLCamera& camera);
- void renderForSelect();
+ void renderForSelect(std::set<LLViewerObject*>& objects);
void renderFaceForUVSelect(LLFace* facep);
void rebuildPools(); // Rebuild pools
- // bindAGP and unbindAGP are used to bind AGP memory.
- // AGP should never be bound if you're writing/copying data to AGP.
- // bindAGP will do the correct thing if AGP rendering has been disabled globally.
- void bindAGP();
- void unbindAGP();
- inline BOOL isAGPBound() const { return mAGPBound; }
-
- void setupVisibility();
- void computeVisibility();
-
- LLViewerObject *nearestObjectAt(F32 yaw, F32 pitch); // CCW yaw from +X = 0 radians, pitch down from +Y = 0 radians, NULL if no object
-
- void displayPools();
- void displayAGP();
- void displayMap();
- void displaySSBB();
- void displayQueues();
- void printPools();
-
void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object
BOOL verify(); // Verify that all data in the pipeline is "correct"
- // just the AGP part
- S32 getAGPMemUsage();
-
- // all pools
- S32 getMemUsage(const BOOL print = FALSE);
-
S32 getVisibleCount() const { return mVisibleList.size(); }
S32 getLightCount() const { return mLights.size(); }
@@ -234,18 +218,15 @@ public:
BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; }
BOOL hasRenderFeatureMask(const U32 mask) const { return (mRenderFeatureMask & mask) ? TRUE : FALSE; }
BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; }
-
- // Vertex buffer stuff?
- U8* bufferGetScratchMemory(void);
- void bufferWaitFence(void);
- void bufferSendFence(void);
- void bufferRotate(void);
+ void setRenderTypeMask(const U32 mask) { mRenderTypeMask = mask; }
+ U32 getRenderTypeMask() const { return mRenderTypeMask; }
+ static void toggleRenderType(U32 type);
// For UI control of render features
- static void toggleRenderType(void* data);
+ static BOOL hasRenderTypeControl(void* data);
static void toggleRenderDebug(void* data);
static void toggleRenderDebugFeature(void* data);
- static BOOL toggleRenderTypeControl(void* data);
+ static void toggleRenderTypeControl(void* data);
static BOOL toggleRenderTypeControlNegated(void* data);
static BOOL toggleRenderDebugControl(void* data);
static BOOL toggleRenderDebugFeatureControl(void* data);
@@ -295,20 +276,17 @@ public:
RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND,
RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN,
RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE,
- RENDER_TYPE_MEDIA = LLDrawPool::POOL_MEDIA,
RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
- RENDER_TYPE_TREE_NEW = LLDrawPool::POOL_TREE_NEW,
RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
- RENDER_TYPE_CLOUDS = LLDrawPool::POOL_CLOUDS,
RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
- RENDER_TYPE_HUD = LLDrawPool::POOL_HUD,
-
// Following are object types (only used in drawable mRenderType)
+ RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES,
RENDER_TYPE_VOLUME,
RENDER_TYPE_GRASS,
RENDER_TYPE_PARTICLES,
+ RENDER_TYPE_CLOUDS,
};
enum LLRenderDebugFeatureMask
@@ -322,13 +300,12 @@ public:
RENDER_DEBUG_FEATURE_FOG = 0x0020,
RENDER_DEBUG_FEATURE_PALETTE = 0x0040,
RENDER_DEBUG_FEATURE_FR_INFO = 0x0080,
- RENDER_DEBUG_FEATURE_CHAIN_FACES = 0x0100
+ RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100,
};
enum LLRenderFeatureMask
{
- RENDER_FEATURE_AGP = 0x01,
-// RENDER_FEATURE_LOCAL_LIGHTING = 0x02,
+ RENDER_FEATURE_LOCAL_LIGHTING = 0x02,
RENDER_FEATURE_OBJECT_BUMP = 0x04,
RENDER_FEATURE_AVATAR_BUMP = 0x08,
// RENDER_FEATURE_SHADOWS = 0x10,
@@ -337,26 +314,44 @@ public:
enum LLRenderDebugMask
{
- RENDER_DEBUG_LIGHT_TRACE = 0x0001,
- RENDER_DEBUG_POOLS = 0x0002,
- RENDER_DEBUG_MAP = 0x0004,
- RENDER_DEBUG_AGP_MEM = 0x0008,
- RENDER_DEBUG_QUEUES = 0x0010,
- RENDER_DEBUG_COMPOSITION = 0x0020,
- RENDER_DEBUG_SSBB = 0x0040,
- RENDER_DEBUG_VERIFY = 0x0080,
- RENDER_DEBUG_SHADOW_MAP = 0x0100,
- RENDER_DEBUG_BBOXES = 0x0200,
- RENDER_DEBUG_OCTREE = 0x0400,
- RENDER_DEBUG_FACE_CHAINS = 0x0800,
- RENDER_DEBUG_OCCLUSION = 0x1000,
- RENDER_DEBUG_POINTS = 0x2000,
- RENDER_DEBUG_TEXTURE_PRIORITY = 0x4000,
+ RENDER_DEBUG_LIGHT_TRACE = 0x00001,
+ RENDER_DEBUG_COMPOSITION = 0x00020,
+ RENDER_DEBUG_VERIFY = 0x00080,
+ RENDER_DEBUG_SHADOW_MAP = 0x00100,
+ RENDER_DEBUG_BBOXES = 0x00200,
+ RENDER_DEBUG_OCTREE = 0x00400,
+ RENDER_DEBUG_PICKING = 0x00800,
+ RENDER_DEBUG_OCCLUSION = 0x01000,
+ RENDER_DEBUG_POINTS = 0x02000,
+ RENDER_DEBUG_TEXTURE_PRIORITY = 0x04000,
+ RENDER_DEBUG_TEXTURE_AREA = 0x08000,
+ RENDER_DEBUG_PARTICLES = 0x10000,
};
LLPointer<LLViewerImage> mAlphaSizzleImagep;
- LLSpatialPartition *mObjectPartition;
+ //MUST MATCH THE ORDER OF DECLARATION IN LLPipeline::init()
+ typedef enum
+ {
+ PARTITION_VOLUME = 0,
+ PARTITION_BRIDGE,
+ PARTITION_HUD,
+ PARTITION_TERRAIN,
+ PARTITION_WATER,
+ PARTITION_TREE,
+ PARTITION_PARTICLE,
+ PARTITION_CLOUD,
+ PARTITION_GRASS,
+ PARTITION_NONE,
+ NUM_PARTITIONS
+ } eObjectPartitions;
+
+private:
+ std::vector<LLSpatialPartition*> mObjectPartition;
+public:
+
+ LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj);
+ LLSpatialPartition* getSpatialPartition(U32 index);
BOOL mBackfaceCull;
S32 mTrianglesDrawn;
@@ -375,10 +370,16 @@ public:
LLStat mNumVisibleFacesStat;
LLStat mNumVisibleDrawablesStat;
- static S32 sAGPMaxPoolSize;
static S32 sCompiles;
- BOOL mUseVBO; // Use ARB vertex buffer objects, if available
+ static BOOL sShowHUDAttachments;
+ static BOOL sUseOcclusion;
+ static BOOL sSkipUpdate; //skip lod updates
+ static BOOL sDynamicReflections;
+
+ //cube map for anti-aliasing reflections
+ LLCubeMap* mCubeBuffer;
+ GLuint mCubeList;
class LLScatterShader
{
@@ -413,15 +414,25 @@ public:
GLSL_SPECULAR_MAP,
GLSL_BUMP_MAP,
GLSL_ENVIRONMENT_MAP,
- GLSL_SCATTER_MAP,
GLSL_END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
+ static const char* sShinyUniforms[];
+ static U32 sShinyUniformCount;
+
+ typedef enum
+ {
+ GLSL_SHINY_ORIGIN = GLSL_END_RESERVED_UNIFORMS
+ } eShinyUniforms;
+
+ LLVector4 mShinyOrigin;
+
//object shaders
LLGLSLShader mObjectSimpleProgram;
LLGLSLShader mObjectAlphaProgram;
LLGLSLShader mObjectBumpProgram;
-
+ LLGLSLShader mObjectShinyProgram;
+
//water parameters
static const char* sWaterUniforms[];
static U32 sWaterUniformCount;
@@ -496,15 +507,17 @@ public:
LLColor4 mSunDiffuse;
LLVector3 mSunDir;
+
+ LLSpatialGroup::sg_vector_t mActiveGroups;
+ std::vector<LLDrawInfo*> mRenderMap[LLRenderPass::NUM_RENDER_TYPES];
+ std::vector<LLSpatialGroup* > mAlphaGroups;
+ std::vector<LLSpatialGroup* > mAlphaGroupsPostWater;
+ LLSpatialGroup::sg_vector_t mVisibleGroups;
+ LLSpatialGroup::sg_vector_t mDrawableGroups;
+
+ void clearRenderMap();
protected:
- class SelectedFaceInfo
- {
- public:
- LLFace *mFacep;
- S32 mTE;
- };
-
BOOL mVertexShadersEnabled;
S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed
S32 mVertexShaderLevel[SHADER_COUNT];
@@ -515,12 +528,16 @@ protected:
U32 mRenderDebugFeatureMask;
U32 mRenderDebugMask;
+ U32 mOldRenderDebugMask;
+
/////////////////////////////////////////////
//
//
LLDrawable::drawable_vector_t mVisibleList;
- LLDrawable::drawable_set_t mMovedList;
-
+ LLSpatialBridge::bridge_vector_t mVisibleBridge;
+ LLSpatialBridge::bridge_vector_t mOccludedBridge;
+ LLDrawable::drawable_vector_t mMovedList;
+ LLDrawable::drawable_vector_t mMovedBridge;
LLDrawable::drawable_vector_t mShiftList;
/////////////////////////////////////////////
@@ -559,13 +576,13 @@ protected:
//
// Different queues of drawables being processed.
//
- LLDrawable::drawable_set_t mBuildQ1; // priority
+ LLDrawable::drawable_list_t mBuildQ1; // priority
LLDrawable::drawable_list_t mBuildQ2; // non-priority
+ LLSpatialGroup::sg_set_t mGroupQ; //spatial groups
LLDrawable::drawable_set_t mActiveQ;
LLDrawable::drawable_set_t mRetexturedList;
- LLDrawable::drawable_set_t mRematerialedList;
//////////////////////////////////////////////////
//
@@ -598,45 +615,27 @@ protected:
LLDrawPool* mLastRebuildPool;
// For quick-lookups into mPools (mapped by texture pointer)
- std::map<uintptr_t, LLDrawPool*> mSimplePools;
std::map<uintptr_t, LLDrawPool*> mTerrainPools;
std::map<uintptr_t, LLDrawPool*> mTreePools;
- std::map<uintptr_t, LLDrawPool*> mTreeNewPools;
- std::map<uintptr_t, LLDrawPool*> mBumpPools;
- std::map<uintptr_t, LLDrawPool*> mMediaPools;
LLDrawPool* mAlphaPool;
+ LLDrawPool* mAlphaPoolPostWater;
LLDrawPool* mSkyPool;
LLDrawPool* mStarsPool;
- LLDrawPool* mCloudsPool;
LLDrawPool* mTerrainPool;
LLDrawPool* mWaterPool;
LLDrawPool* mGroundPool;
- LLDrawPool* mHUDPool;
+ LLRenderPass* mSimplePool;
+ LLDrawPool* mBumpPool;
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
- LLDynamicArray<LLFace*> mHighlightFaces; // highlight faces on physical objects
- LLDynamicArray<SelectedFaceInfo> mSelectedFaces;
+ std::vector<LLFace*> mHighlightFaces; // highlight faces on physical objects
+ std::vector<LLFace*> mSelectedFaces;
LLPointer<LLViewerImage> mFaceSelectImagep;
LLPointer<LLViewerImage> mBloomImagep;
LLPointer<LLViewerImage> mBloomImage2p;
-
- BOOL mAGPBound;
- LLAGPMemPool *mAGPMemPool;
- U32 mGlobalFence;
-
- // Round-robin AGP buffers for use by the software skinner
- enum
- {
- kMaxBufferCount = 4
- };
- S32 mBufferIndex;
- S32 mBufferCount;
- LLAGPArray<U8> *mBufferMemory[kMaxBufferCount];
- U32 mBufferFence[kMaxBufferCount];
- BOOL mUseOcclusionCulling; // object-object occlusion culling
U32 mLightMask;
U32 mLightMovingMask;
S32 mLightingDetail;
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 9f6a001e4f..baa023cd4e 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -49,6 +49,8 @@ class ViewerManifest(LLManifest):
# XUI
if self.prefix(src="skins"):
+ # include the entire textures directory recursively
+ self.path("textures")
self.path("paths.xml")
self.path("xui/*/*.xml")
self.path('words.*.txt')
@@ -98,6 +100,8 @@ class WindowsManifest(ViewerManifest):
# *NOTE: these are the only two executable names that the crash reporter recognizes
if self.args['grid'] == '':
return "SecondLife.exe"
+ elif self.args['grid'] == 'firstlook':
+ return "SecondLifeFirstLook.exe"
else:
return "SecondLifePreview.exe"
# return "SecondLifePreview%s.exe" % (self.args['grid'], )
@@ -396,7 +400,7 @@ class Linux_i686Manifest(LinuxManifest):
self.path("libvorbis.so.0")
self.path("libvorbisfile.so.0")
self.path("libvorbisenc.so.0")
- self.path("libcurl.so.3")
+ self.path("libcurl.so.4")
self.path("libcrypto.so.0.9.7")
self.path("libssl.so.0.9.7")
self.path("libexpat.so.1")