Merge branch 'master' of git://github.com/Shyotl/SingularityViewer

This commit is contained in:
Latif Khalifa
2013-10-17 05:25:02 +02:00
7 changed files with 113 additions and 62 deletions

View File

@@ -284,13 +284,14 @@ void LLAudioEngine::updateChannels()
checkStates();
}
typedef std::pair<LLAudioSource*,F32> audio_source_t;
struct SourcePriorityComparator
{
bool operator() (const audio_source_t& lhs, const audio_source_t& rhs) const
bool operator() (const LLAudioSource* lhs, const LLAudioSource* rhs) const
{
//Sort by priority value. If equal, sync masters get higher priority.
return lhs.second < rhs.second || (lhs.second == rhs.second && !lhs.first->isSyncMaster() && rhs.first->isSyncMaster());
if(rhs->getPriority() != lhs->getPriority())
return rhs->getPriority() > lhs->getPriority();
else
return ((rhs->isSyncMaster() && !lhs->isSyncMaster()) || (rhs->isSyncSlave() && (!lhs->isSyncMaster() && !lhs->isSyncSlave())));
}
};
@@ -319,10 +320,21 @@ void LLAudioEngine::idle(F32 max_decode_time)
LLAudioSource *sync_masterp = NULL; //Highest priority syncmaster
LLAudioSource *sync_slavep = NULL; //Highest priority syncslave
//Priority queue that will be filled with soundsources that have a high likeleyhood of being able to start [re]playing this idle tick.
//Sort order: Primary: priority. Secondary: syncmaster. Tertiary: syncslave
std::priority_queue<LLAudioSource*,std::vector<LLAudioSource*,boost::pool_allocator<LLAudioSource*> >,SourcePriorityComparator> queue;
//Have to put syncslaves into a temporary list until the syncmaster state is determined.
//If the syncmaster might be started, or just looped, insert all pending/looping syncslaves into the priority queue.
//If the there is no active syncmaster, then stop any currently looping syncslaves and add none to the priority queue.
//This is necessary as any looping soundsources to be stopped, MUST be stopped before iterating down the priority queue.
static std::vector<LLAudioSource*> slave_list;
slave_list.clear();
//Iterate over all sources. Update their decode or 'done' state, as well as their priorities.
//Also add sources that might be able to start playing to a priority queue.
//Only sources without channels, or are waiting for a syncmaster, should be added to this queue.
std::priority_queue<audio_source_t,std::vector<audio_source_t,boost::pool_allocator<audio_source_t> >,SourcePriorityComparator> queue;
//Also add sources that might be able to start playing to the priority queue.
//Only sources without channels should be added to priority queue.
//Syncslaves must put into the slave list instead of the priority queue.
for (source_map::iterator iter = mAllSources.begin(); iter != mAllSources.end();)
{
LLAudioSource *sourcep = iter->second;
@@ -360,34 +372,32 @@ void LLAudioEngine::idle(F32 max_decode_time)
{
if(!sync_masterp || sourcep->getPriority() > sync_masterp->getPriority())
{
if(sync_masterp && !sync_masterp->getChannel())
queue.push(sync_masterp); //Add lower-priority soundmaster to the queue as a normal sound.
sync_masterp = sourcep;
//Don't add master to the queue yet.
//Add it after highest-priority sound slave is found so we can outrank its priority.
continue;
}
//This is a hack. Don't add master to the queue yet.
//Add it after highest-priority sound slave is found so we can outrank its priority.
continue;
//Else fall through like a normal sound.
}
else if(sourcep->isSyncSlave())
{
//Only care about syncslaves without channel, or are looping.
if(!sourcep->getChannel() || sourcep->isLoop() )
if(!sync_slavep || sourcep->getPriority() > sync_slavep->getPriority())
{
if(!sync_slavep || sourcep->getPriority() > sync_slavep->getPriority())
{
sync_slavep = sourcep;
}
}
else
{
continue;
sync_slavep = sourcep;
}
//Don't add to the priority queue quite yet. Best primary syncmaster candidate may not have been determined yet.
slave_list.push_back(sourcep);
continue;
}
else if(sourcep->getChannel())
if(sourcep->getChannel())
{
//If this is just a regular sound and is currently playing then do nothing special.
continue;
}
//Add to our queue. Highest priority will be at the front.
queue.push(std::make_pair(sourcep,sourcep->getPriority()));
queue.push(sourcep);
}
// Do this BEFORE we update the channels
@@ -395,47 +405,71 @@ void LLAudioEngine::idle(F32 max_decode_time)
// such as changing what sound was playing.
updateChannels();
//Syncmaster must have priority greater than or equal to priority of highest priority syncslave.
if(sync_masterp && !sync_masterp->getChannel())
//Loop over all syncsaves. If no syncmaster, stop looping ones, else add ones that need [re]started to the priority queue.
//Normally there are zero to one syncslaves, so this loop isn't typically expensive.
for(std::vector<LLAudioSource*>::iterator iter=slave_list.begin();iter!=slave_list.end();++iter)
{
if(!sync_masterp)
{
//Stop any looping syncslaves. I'm not sure this behavior is correct, but letting looping syncslaves run
//off on their own seems wrong. The lsl documentation is unclear.
if((*iter)->getChannel() && (*iter)->isLoop())
{
(*iter)->getChannel()->cleanup();
}
}
//If the syncmaster already has a channel and hasn't looped, then we can skip syncslaves this idle tick (there's nothing to do).
else if((!sync_masterp->getChannel() || sync_masterp->getChannel()->mLoopedThisFrame))
{
//Add syncslaves that we might want to [re]start.
if(!(*iter)->getChannel() || (*iter)->isLoop())
queue.push((*iter));
}
}
if(sync_masterp)
{
//Syncmaster must have priority greater than or equal to priority of highest priority syncslave.
//The case of slave priority equaling master priority is handled in the comparator (SourcePriorityComparator).
//Could have added an arbiturary small value to the priority, but the extra logic in the comparator is more correct.
if(sync_slavep)
queue.push(std::make_pair(sync_masterp, llmax(sync_slavep->getPriority(), sync_masterp->getPriority())));
else
queue.push(std::make_pair(sync_masterp, sync_masterp->getPriority()));
sync_masterp->setPriority(sync_slavep->getPriority());
if(!sync_masterp->getChannel())
{
queue.push(sync_masterp);
}
}
// Dispatch all soundsources.
bool syncmaster_started = false;
bool syncmaster_started = sync_masterp && sync_masterp->getChannel() && sync_masterp->getChannel()->mLoopedThisFrame;
while(!queue.empty())
{
// This is lame, instead of this I could actually iterate through all the sources
// attached to each channel, since only those with active channels
// can have anything interesting happen with their queue? (Maybe not true)
LLAudioSource *sourcep = queue.top().first;
LLAudioSource *sourcep = queue.top();
queue.pop();
if (sourcep->isSyncSlave())
//If the syncmaster hasn't just started playing, or hasn't just looped then skip this soundslave,
//as there's nothing to do with it yet.
if (sourcep->isSyncSlave() && !syncmaster_started)
{
//If the syncmaster hasn't just started playing, or hasn't just looped then skip this soundslave.
if(!sync_masterp || (!syncmaster_started && !(sync_masterp->getChannel() && sync_masterp->getChannel()->mLoopedThisFrame)))
continue;
continue;
}
LLAudioChannel *channelp = sourcep->getChannel();
if (!channelp)
{
if(!(channelp = gAudiop->getFreeChannel(sourcep->getPriority())))
continue; //No more channels. Don't abort the whole loop, however. Soundslaves might want to start up!
//If this is the syncmaster that just started then we need to update non-playing syncslaves.
if(sourcep == sync_masterp)
//No more channels. We can break here, as in theory, any lower priority sounds should have had their
//channel already stolen. There should be nothing playing, nor playable, when iterating beyond this point.
if(!(channelp = getFreeChannel(sourcep->getPriority())))
{
syncmaster_started = true;
break;
}
channelp->setSource(sourcep); //setSource calls updateBuffer and update3DPosition, and resets the source mAgeTimer
//If this is the primary syncmaster that we just started, then [re]start syncslaves further down in the priority queue.
//Due to sorting and priority fudgery, the syncmaster is ALWAYS before any syncslaves in this loop.
syncmaster_started |= (sourcep == sync_masterp);
//setSource calls updateBuffer and update3DPosition, and resets the source mAgeTimer
channelp->setSource(sourcep);
}
if(sourcep->isSyncSlave())
@@ -594,7 +628,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
}
}
if (min_priority > priority || !min_channelp)
if (!min_channelp || min_priority >= priority)
{
// All playing channels have higher priority, return.
return NULL;
@@ -1411,11 +1445,11 @@ void LLAudioSource::updatePriority()
{
if (isAmbient())
{
mPriority = 1.f;
setPriority(1.f);
}
else if (isMuted())
{
mPriority = 0.f;
setPriority(0.f);
}
else
{
@@ -1425,7 +1459,7 @@ void LLAudioSource::updatePriority()
dist_vec -= gAudiop->getListenerPos();
F32 dist_squared = llmax(1.f, dist_vec.magVecSquared());
mPriority = mGain / dist_squared;
setPriority(mGain / dist_squared);
}
}

View File

@@ -316,6 +316,7 @@ public:
LLVector3d getPositionGlobal() const { return mPositionGlobal; }
LLVector3 getVelocity() const { return mVelocity; }
F32 getPriority() const { return mPriority; }
void setPriority(F32 priority) { mPriority = priority; }
// Gain should always be clamped between 0 and 1.
F32 getGain() const { return mGain; }

View File

@@ -590,6 +590,7 @@ void LLAudioChannelFMOD::cleanup()
}
mChannelID = 0;
mLastSamplePos = 0;
}

View File

@@ -810,6 +810,7 @@ void LLAudioChannelFMODEX::cleanup()
Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
mChannelp = NULL;
mLastSamplePos = 0;
}

View File

@@ -338,6 +338,7 @@ void LLAudioBufferOpenAL::cleanup()
LL_WARNS("OpenAL") << "Error: " << alutGetErrorString( error ) << " when cleaning up a buffer" << LL_ENDL;
}
mALBuffer = AL_NONE;
mLastSamplePos = 0;
}
}

View File

@@ -51,7 +51,7 @@ void check_framebuffer_status()
}
bool LLRenderTarget::sUseFBO = false;
U32 LLRenderTarget::sCurFBO = 0;
LLRenderTarget* LLRenderTarget::sCurFBO = 0;
LLRenderTarget::LLRenderTarget() :
mResX(0),
@@ -161,7 +161,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
}
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
}
stop_glerror();
@@ -248,7 +248,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
}
mTex.push_back(tex);
@@ -343,7 +343,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
target.mUseDepth = true;
}
@@ -365,6 +365,7 @@ void LLRenderTarget::release()
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}
LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);
stop_glerror();
@@ -386,6 +387,7 @@ void LLRenderTarget::release()
{ //attached as a texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER,0);
mUseDepth = false;
}
@@ -414,17 +416,18 @@ void LLRenderTarget::bindTarget()
if (mFBO)
{
stop_glerror();
mPreviousFBO = sCurFBO;
if (mSampleBuffer)
{
mSampleBuffer->bindTarget(this);
sCurFBO = mSampleBuffer->mFBO;
sCurFBO = mSampleBuffer;
stop_glerror();
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
sCurFBO = mFBO;
sCurFBO = this;
stop_glerror();
if (gGLManager.mHasDrawBuffers)
@@ -577,8 +580,18 @@ void LLRenderTarget::flush(bool fetch_depth)
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO ? mPreviousFBO->getFBO() : 0);
sCurFBO = mPreviousFBO;
if(mPreviousFBO)
{
glViewport(0, 0, mPreviousFBO->mResX, mPreviousFBO->mResY);
mPreviousFBO = NULL;
}
else
{
glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]);
}
stop_glerror();
}
}
@@ -613,7 +626,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
stop_glerror();
glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
stop_glerror();
}
else
@@ -636,7 +649,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
stop_glerror();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
stop_glerror();
}
}
@@ -670,7 +683,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
if(mask)
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
stop_glerror();
}
}
@@ -819,7 +832,7 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
}
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
stop_glerror();
@@ -898,7 +911,7 @@ bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO ? sCurFBO->getFBO() : 0);
}
mTex.push_back(tex);

View File

@@ -65,7 +65,7 @@ public:
//whether or not to use FBO implementation
static bool sUseFBO;
static U32 sBytesAllocated;
static U32 sCurFBO;
static LLRenderTarget* sCurFBO;
LLRenderTarget();
virtual ~LLRenderTarget();
@@ -154,7 +154,7 @@ protected:
std::vector<U32> mTex;
std::vector<U32> mInternalFormat;
U32 mFBO;
U32 mPreviousFBO;
LLRenderTarget* mPreviousFBO;
U32 mDepth;
bool mStencil;
bool mUseDepth;