diff --git a/indra/aistatemachine/CMakeLists.txt b/indra/aistatemachine/CMakeLists.txt
index 6db29a007..806261201 100644
--- a/indra/aistatemachine/CMakeLists.txt
+++ b/indra/aistatemachine/CMakeLists.txt
@@ -21,6 +21,7 @@ set(aistatemachine_SOURCE_FILES
aistatemachine.cpp
aistatemachinethread.cpp
aitimer.cpp
+ aicondition.cpp
)
set(aistatemachine_HEADER_FILES
@@ -29,6 +30,7 @@ set(aistatemachine_HEADER_FILES
aistatemachine.h
aistatemachinethread.h
aitimer.h
+ aicondition.h
)
set_source_files_properties(${aistatemachine_HEADER_FILES}
diff --git a/indra/aistatemachine/aicondition.cpp b/indra/aistatemachine/aicondition.cpp
new file mode 100644
index 000000000..2c9a4f8e8
--- /dev/null
+++ b/indra/aistatemachine/aicondition.cpp
@@ -0,0 +1,89 @@
+/**
+ * @file aicondition.cpp
+ * @brief Implementation of AICondition
+ *
+ * Copyright (c) 2013, Aleric Inglewood.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution.
+ *
+ * CHANGELOG
+ * and additional copyright holders.
+ *
+ * 14/10/2013
+ * Initial version, written by Aleric Inglewood @ SL
+ */
+
+#include "sys.h"
+#include "aicondition.h"
+#include "aistatemachine.h"
+
+void AIConditionBase::wait(AIStateMachine* state_machine)
+{
+ // The condition must be locked before calling AIStateMachine::wait().
+ llassert(mutex().isSelfLocked());
+ // Add the new state machine at the end.
+ mWaitingStateMachines.push_back(state_machine);
+}
+
+void AIConditionBase::remove(AIStateMachine* state_machine)
+{
+ mutex().lock();
+ // Remove all occurances of state_machine from the queue.
+ queue_t::iterator const end = mWaitingStateMachines.end();
+ queue_t::iterator last = end;
+ for (queue_t::iterator iter = mWaitingStateMachines.begin(); iter != last; ++iter)
+ {
+ if (iter->get() == state_machine)
+ {
+ if (--last == iter)
+ {
+ break;
+ }
+ queue_t::value_type::swap(*iter, *last);
+ }
+ }
+ // This invalidates all iterators involved, including end, but not any iterators to the remaining elements.
+ mWaitingStateMachines.erase(last, end);
+ mutex().unlock();
+}
+
+void AIConditionBase::signal(int n)
+{
+ // The condition must be locked before calling AICondition::signal or AICondition::broadcast.
+ llassert(mutex().isSelfLocked());
+ // Signal n state machines.
+ while (n > 0 && !mWaitingStateMachines.empty())
+ {
+ LLPointer state_machine = mWaitingStateMachines.front();
+ bool success = state_machine->signalled();
+ // Only state machines that are actually still blocked should be in the queue:
+ // they are removed from the queue by calling AICondition::remove whenever
+ // they are unblocked for whatever reason...
+ llassert(success);
+ if (success)
+ {
+ ++n;
+ }
+ else
+ {
+ // We never get here...
+ remove(state_machine.get());
+ }
+ }
+}
+
diff --git a/indra/aistatemachine/aicondition.h b/indra/aistatemachine/aicondition.h
new file mode 100644
index 000000000..05dd9ea42
--- /dev/null
+++ b/indra/aistatemachine/aicondition.h
@@ -0,0 +1,110 @@
+/**
+ * @file aicondition.h
+ * @brief Condition variable for statemachines.
+ *
+ * Copyright (c) 2013, Aleric Inglewood.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution.
+ *
+ * CHANGELOG
+ * and additional copyright holders.
+ *
+ * 14/10/2013
+ * Initial version, written by Aleric Inglewood @ SL
+ */
+
+#ifndef AICONDITION_H
+#define AICONDITION_H
+
+#include
+#include
+#include "aithreadsafe.h"
+
+class AIStateMachine;
+class LLMutex;
+
+// class AICondition
+//
+// Call AIStateMachine::wait(AICondition&) in the multiplex_impl of a state machine to
+// make the state machine go idle until some thread calls AICondition::signal().
+//
+// If the state machine is no longer running or wasn't waiting anymore because
+// something else woke it up, then AICondition::signal() will wake up another
+// state machine (if any).
+//
+// Usage:
+//
+// struct Foo { bool met(); }; // Returns true when the condition is met.
+// AICondition Condition_t;
+// AIAccess Condition_wat;
+//
+// // Some thread-safe condition variable.
+// Condition_t condition;
+//
+// // Inside the state machine:
+// {
+// ...
+// state WAIT_FOR_CONDITION:
+// {
+// // Lock condition and check it. Wait if condition is not met yet.
+// {
+// Condition_wat condition_w(condition);
+// if (!condition_w->met())
+// {
+// wait(condition);
+// break;
+// }
+// }
+// set_state(CONDITION_MET);
+// break;
+// }
+// CONDITION_MET:
+// {
+//
+
+class AIConditionBase
+{
+ public:
+ virtual ~AIConditionBase() { }
+
+ void signal(int n = 1); // Call this when the condition was met to release n state machines.
+ void broadcast(void) { signal(mWaitingStateMachines.size()); } // Release all blocked state machines.
+
+ private:
+ // These functions are called by AIStateMachine.
+ friend class AIStateMachine;
+ void wait(AIStateMachine* state_machine);
+ void remove(AIStateMachine* state_machine);
+
+ protected:
+ virtual LLMutex& mutex(void) = 0;
+
+ protected:
+ typedef std::deque > queue_t;
+ queue_t mWaitingStateMachines;
+};
+
+template
+class AICondition : public AIThreadSafeSimpleDC, public AIConditionBase
+{
+ protected:
+ /*virtual*/ LLMutex& mutex(void) { return this->mMutex; }
+};
+
+#endif
+
diff --git a/indra/aistatemachine/aistatemachine.cpp b/indra/aistatemachine/aistatemachine.cpp
index bf867fffd..fcdb2d9c8 100644
--- a/indra/aistatemachine/aistatemachine.cpp
+++ b/indra/aistatemachine/aistatemachine.cpp
@@ -33,6 +33,7 @@
#include "linden_common.h"
#include "aistatemachine.h"
+#include "aicondition.h"
#include "lltimer.h"
//==================================================================
@@ -283,7 +284,7 @@ char const* HelloWorld::state_str_impl(state_type run_state) const
void AIEngine::add(AIStateMachine* state_machine)
{
- Dout(dc::statemachine, "Adding state machine [" << (void*)state_machine << "] to " << mName);
+ Dout(dc::statemachine(state_machine->mSMDebug), "Adding state machine [" << (void*)state_machine << "] to " << mName);
engine_state_type_wat engine_state_w(mEngineState);
engine_state_w->list.push_back(QueueElement(state_machine));
if (engine_state_w->waiting)
@@ -330,7 +331,7 @@ void AIEngine::mainloop(void)
engine_state_type_wat engine_state_w(mEngineState);
if (!active)
{
- Dout(dc::statemachine, "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
+ Dout(dc::statemachine(state_machine.mSMDebug), "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
engine_state_w->list.erase(queued_element++);
}
else
@@ -392,7 +393,7 @@ void AIStateMachine::multiplex(event_type event)
// If this fails then you are using a pointer to a state machine instead of an LLPointer.
llassert(event == initial_run || getNumRefs() > 0);
- DoutEntering(dc::statemachine, "AIStateMachine::multiplex(" << event_str(event) << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::multiplex(" << event_str(event) << ") [" << (void*)this << "]");
base_state_type state;
state_type run_state;
@@ -407,7 +408,7 @@ void AIStateMachine::multiplex(event_type event)
llassert(!mMultiplexMutex.isSelfLocked()); // We may never enter recursively!
if (!mMultiplexMutex.tryLock())
{
- Dout(dc::statemachine, "Leaving because it is already being run [" << (void*)this << "]");
+ Dout(dc::statemachine(mSMDebug), "Leaving because it is already being run [" << (void*)this << "]");
return;
}
@@ -421,7 +422,7 @@ void AIStateMachine::multiplex(event_type event)
// we should indeed run, again.
if (event == schedule_run && !sub_state_type_rat(mSubState)->need_run)
{
- Dout(dc::statemachine, "Leaving because it was already being run [" << (void*)this << "]");
+ Dout(dc::statemachine(mSMDebug), "Leaving because it was already being run [" << (void*)this << "]");
return;
}
@@ -440,9 +441,9 @@ void AIStateMachine::multiplex(event_type event)
{
#ifdef CWDEBUG
if (state == bs_multiplex)
- Dout(dc::statemachine, "Running state bs_multiplex / " << state_str_impl(run_state) << " [" << (void*)this << "]");
+ Dout(dc::statemachine(mSMDebug), "Running state bs_multiplex / " << state_str_impl(run_state) << " [" << (void*)this << "]");
else
- Dout(dc::statemachine, "Running state " << state_str(state) << " [" << (void*)this << "]");
+ Dout(dc::statemachine(mSMDebug), "Running state " << state_str(state) << " [" << (void*)this << "]");
#endif
#ifdef SHOW_ASSERT
@@ -503,7 +504,7 @@ void AIStateMachine::multiplex(event_type event)
// run of bs_reset is not a problem because it happens to be a NoOp.
state = (state == bs_initialize) ? bs_reset : bs_abort;
#ifdef CWDEBUG
- Dout(dc::statemachine, "Late abort detected! Running state " << state_str(state) << " instead [" << (void*)this << "]");
+ Dout(dc::statemachine(mSMDebug), "Late abort detected! Running state " << state_str(state) << " instead [" << (void*)this << "]");
#endif
}
#ifdef SHOW_ASSERT
@@ -665,7 +666,7 @@ void AIStateMachine::multiplex(event_type event)
#ifdef CWDEBUG
if (state != state_w->base_state)
- Dout(dc::statemachine, "Base state changed from " << state_str(state) << " to " << state_str(state_w->base_state) <<
+ Dout(dc::statemachine(mSMDebug), "Base state changed from " << state_str(state) << " to " << state_str(state_w->base_state) <<
"; need_new_run = " << (need_new_run ? "true" : "false") << " [" << (void*)this << "]");
#endif
}
@@ -699,11 +700,15 @@ void AIStateMachine::multiplex(event_type event)
// Mark that we're added to this engine, and at the same time, that we're not added to the previous one.
state_w->current_engine = engine;
}
+#ifdef SHOW_ASSERT
+ // We are leaving the loop, but we're not idle. The statemachine should re-enter the loop again.
+ mDebugShouldRun = true;
+#endif
}
else
{
- // Remove this state machine from any engine.
- // Cause the engine to remove us.
+ // Remove this state machine from any engine,
+ // causing the engine to remove us.
state_w->current_engine = NULL;
}
@@ -749,7 +754,7 @@ void AIStateMachine::multiplex(event_type event)
AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state)
{
- DoutEntering(dc::statemachine, "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]");
sub_state_type_wat sub_state_w(mSubState);
// Honor a subsequent call to idle() (only necessary in bs_multiplex, but it doesn't hurt to reset this flag in other states too).
@@ -759,7 +764,7 @@ AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state
// Honor previous calls to advance_state() (once run_state is initialized).
if (base_state == bs_multiplex && sub_state_w->advance_state > sub_state_w->run_state)
{
- Dout(dc::statemachine, "Copying advance_state to run_state, because it is larger [" << state_str_impl(sub_state_w->advance_state) << " > " << state_str_impl(sub_state_w->run_state) << "]");
+ Dout(dc::statemachine(mSMDebug), "Copying advance_state to run_state, because it is larger [" << state_str_impl(sub_state_w->advance_state) << " > " << state_str_impl(sub_state_w->run_state) << "]");
sub_state_w->run_state = sub_state_w->advance_state;
}
#ifdef SHOW_ASSERT
@@ -789,7 +794,7 @@ AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state
void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent, bool on_abort_signal_parent, AIEngine* default_engine)
{
- DoutEntering(dc::statemachine, "AIStateMachine::run(" <<
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::run(" <<
(void*)parent << ", " <<
(parent ? parent->state_str_impl(new_parent_state) : "NA") <<
", abort_parent = " << (abort_parent ? "true" : "false") <<
@@ -839,7 +844,7 @@ void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bo
void AIStateMachine::run(callback_type::signal_type::slot_type const& slot, AIEngine* default_engine)
{
- DoutEntering(dc::statemachine, "AIStateMachine::run(, default_engine = " << default_engine->name() << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::run(, default_engine = " << default_engine->name() << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
@@ -874,7 +879,7 @@ void AIStateMachine::run(callback_type::signal_type::slot_type const& slot, AIEn
void AIStateMachine::callback(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::callback() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::callback() [" << (void*)this << "]");
bool aborted = sub_state_type_rat(mSubState)->aborted;
if (mParent)
@@ -920,7 +925,7 @@ void AIStateMachine::force_killed(void)
void AIStateMachine::kill(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::kill() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::kill() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -937,7 +942,7 @@ void AIStateMachine::kill(void)
void AIStateMachine::reset()
{
- DoutEntering(dc::statemachine, "AIStateMachine::reset() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::reset() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
mDebugAborted = false;
mDebugContPending = false;
@@ -960,6 +965,8 @@ void AIStateMachine::reset()
sub_state_w->reset = true;
// Start running.
sub_state_w->idle = false;
+ // We're not waiting for a condition.
+ sub_state_w->blocked = NULL;
// Keep running till we reach at least bs_multiplex.
sub_state_w->need_run = true;
}
@@ -972,7 +979,7 @@ void AIStateMachine::reset()
void AIStateMachine::set_state(state_type new_state)
{
- DoutEntering(dc::statemachine, "AIStateMachine::set_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::set_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -983,6 +990,8 @@ void AIStateMachine::set_state(state_type new_state)
}
#endif
sub_state_type_wat sub_state_w(mSubState);
+ // It should never happen that set_state() is called while we're blocked.
+ llassert(!sub_state_w->blocked);
// Force current state to the requested state.
sub_state_w->run_state = new_state;
// Void last call to advance_state.
@@ -999,13 +1008,13 @@ void AIStateMachine::set_state(state_type new_state)
void AIStateMachine::advance_state(state_type new_state)
{
- DoutEntering(dc::statemachine, "AIStateMachine::advance_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::advance_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
{
sub_state_type_wat sub_state_w(mSubState);
// Ignore call to advance_state when the currently queued state is already greater or equal to the requested state.
if (sub_state_w->advance_state >= new_state)
{
- Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->advance_state) << " >= " << state_str_impl(new_state) << ".");
+ Dout(dc::statemachine(mSMDebug), "Ignored, because " << state_str_impl(sub_state_w->advance_state) << " >= " << state_str_impl(new_state) << ".");
return;
}
// Ignore call to advance_state when the current state is greater than the requested state: the new state would be
@@ -1014,7 +1023,7 @@ void AIStateMachine::advance_state(state_type new_state)
// the state change is and should be being ignored: the statemachine would start running it's current state (again).
if (sub_state_w->run_state > new_state)
{
- Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->run_state) << " > " << state_str_impl(new_state) << " (current state).");
+ Dout(dc::statemachine(mSMDebug), "Ignored, because " << state_str_impl(sub_state_w->run_state) << " > " << state_str_impl(new_state) << " (current state).");
return;
}
// Increment state.
@@ -1023,6 +1032,13 @@ void AIStateMachine::advance_state(state_type new_state)
sub_state_w->idle = false;
// Ignore a call to idle if it occurs before we leave multiplex_impl().
sub_state_w->skip_idle = true;
+ // No longer say we woke up when signalled() is called.
+ if (sub_state_w->blocked)
+ {
+ Dout(dc::statemachine(mSMDebug), "Removing statemachine from condition " << (void*)sub_state_w->blocked);
+ sub_state_w->blocked->remove(this);
+ sub_state_w->blocked = NULL;
+ }
// Mark that a re-entry of multiplex() is necessary.
sub_state_w->need_run = true;
#ifdef SHOW_ASSERT
@@ -1048,7 +1064,7 @@ void AIStateMachine::advance_state(state_type new_state)
void AIStateMachine::idle(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::idle() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::idle() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1066,7 +1082,7 @@ void AIStateMachine::idle(void)
// Ignore call to idle() when advance_state() was called since last call to set_state().
if (sub_state_w->skip_idle)
{
- Dout(dc::statemachine, "Ignored, because skip_idle is true (advance_state() was called last).");
+ Dout(dc::statemachine(mSMDebug), "Ignored, because skip_idle is true (advance_state() was called last).");
return;
}
// Mark that we are idle.
@@ -1075,13 +1091,54 @@ void AIStateMachine::idle(void)
mSleep = 0;
}
+// This function is very much like idle().
+void AIStateMachine::wait(AIConditionBase& condition)
+{
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::wait(" << (void*)&condition << ") [" << (void*)this << "]");
+#ifdef SHOW_ASSERT
+ {
+ multiplex_state_type_rat state_r(mState);
+ // wait() may only be called multiplex_impl().
+ llassert(state_r->base_state == bs_multiplex);
+ // May only be called by the thread that is holding mMultiplexMutex.
+ llassert(mThreadId.equals_current_thread());
+ }
+ // wait() following set_state() cancels the reason to run because of the call to set_state.
+ mDebugSetStatePending = false;
+#endif
+ sub_state_type_wat sub_state_w(mSubState);
+ // As wait() may only be called from within the state machine, it should never happen that the state machine is already idle.
+ llassert(!sub_state_w->idle);
+ // Ignore call to wait() when advance_state() was called since last call to set_state().
+ if (sub_state_w->skip_idle)
+ {
+ Dout(dc::statemachine(mSMDebug), "Ignored, because skip_idle is true (advance_state() was called last).");
+ return;
+ }
+ // Register ourselves with the condition object.
+ condition.wait(this);
+ // Mark that we are idle.
+ sub_state_w->idle = true;
+ // Mark that we are waiting for a condition.
+ sub_state_w->blocked = &condition;
+ // Not sleeping (anymore).
+ mSleep = 0;
+}
+
void AIStateMachine::cont(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::cont() [" << (void*)this << "]");
{
sub_state_type_wat sub_state_w(mSubState);
// Void last call to idle(), if any.
sub_state_w->idle = false;
+ // No longer say we woke up when signalled() is called.
+ if (sub_state_w->blocked)
+ {
+ Dout(dc::statemachine(mSMDebug), "Removing statemachine from condition " << (void*)sub_state_w->blocked);
+ sub_state_w->blocked->remove(this);
+ sub_state_w->blocked = NULL;
+ }
// Mark that a re-entry of multiplex() is necessary.
sub_state_w->need_run = true;
#ifdef SHOW_ASSERT
@@ -1095,15 +1152,56 @@ void AIStateMachine::cont(void)
}
}
+// This function is very much like cont(), except that it has no effect when we are not in a blocked state.
+// Returns true if the state machine was unblocked, false if it was already unblocked.
+bool AIStateMachine::signalled(void)
+{
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::signalled() [" << (void*)this << "]");
+ {
+ sub_state_type_wat sub_state_w(mSubState);
+ // Test if we are blocked or not.
+ if (sub_state_w->blocked)
+ {
+ Dout(dc::statemachine(mSMDebug), "Removing statemachine from condition " << (void*)sub_state_w->blocked);
+ sub_state_w->blocked->remove(this);
+ sub_state_w->blocked = NULL;
+ }
+ else
+ {
+ return false;
+ }
+ // Void last call to wait().
+ sub_state_w->idle = false;
+ // Mark that a re-entry of multiplex() is necessary.
+ sub_state_w->need_run = true;
+#ifdef SHOW_ASSERT
+ // From this moment.
+ mDebugContPending = true;
+#endif
+ }
+ if (!mMultiplexMutex.isSelfLocked())
+ {
+ multiplex(schedule_run);
+ }
+ return true;
+}
+
void AIStateMachine::abort(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::abort() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::abort() [" << (void*)this << "]");
bool is_waiting = false;
{
multiplex_state_type_rat state_r(mState);
sub_state_type_wat sub_state_w(mSubState);
// Mark that we are aborted, iff we didn't already finish.
sub_state_w->aborted = !sub_state_w->finished;
+ // No longer say we woke up when signalled() is called.
+ if (sub_state_w->blocked)
+ {
+ Dout(dc::statemachine(mSMDebug), "Removing statemachine from condition " << (void*)sub_state_w->blocked);
+ sub_state_w->blocked->remove(this);
+ sub_state_w->blocked = NULL;
+ }
// Mark that a re-entry of multiplex() is necessary.
sub_state_w->need_run = true;
// Schedule a new run when this state machine is waiting.
@@ -1128,7 +1226,7 @@ void AIStateMachine::abort(void)
void AIStateMachine::finish(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::finish() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::finish() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1147,7 +1245,7 @@ void AIStateMachine::finish(void)
void AIStateMachine::yield(void)
{
- DoutEntering(dc::statemachine, "AIStateMachine::yield() [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield() [" << (void*)this << "]");
multiplex_state_type_rat state_r(mState);
// yield() may only be called from multiplex_impl().
llassert(state_r->base_state == bs_multiplex);
@@ -1160,7 +1258,7 @@ void AIStateMachine::yield(void)
void AIStateMachine::yield(AIEngine* engine)
{
llassert(engine);
- DoutEntering(dc::statemachine, "AIStateMachine::yield(" << engine->name() << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield(" << engine->name() << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1173,9 +1271,19 @@ void AIStateMachine::yield(AIEngine* engine)
mYieldEngine = engine;
}
+bool AIStateMachine::yield_if_not(AIEngine* engine)
+{
+ if (engine && multiplex_state_type_rat(mState)->current_engine != engine)
+ {
+ yield(engine);
+ return true;
+ }
+ return false;
+}
+
void AIStateMachine::yield_frame(unsigned int frames)
{
- DoutEntering(dc::statemachine, "AIStateMachine::yield_frame(" << frames << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield_frame(" << frames << ") [" << (void*)this << "]");
mSleep = -(S64)frames;
// Sleeping is always done from the main thread.
yield(&gMainThreadEngine);
@@ -1183,7 +1291,7 @@ void AIStateMachine::yield_frame(unsigned int frames)
void AIStateMachine::yield_ms(unsigned int ms)
{
- DoutEntering(dc::statemachine, "AIStateMachine::yield_ms(" << ms << ") [" << (void*)this << "]");
+ DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield_ms(" << ms << ") [" << (void*)this << "]");
mSleep = get_clock_count() + calc_clock_frequency() * ms / 1000;
// Sleeping is always done from the main thread.
yield(&gMainThreadEngine);
@@ -1233,7 +1341,7 @@ void AIEngine::threadloop(void)
engine_state_type_wat engine_state_w(mEngineState);
if (!active)
{
- Dout(dc::statemachine, "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
+ Dout(dc::statemachine(state_machine.mSMDebug), "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
engine_state_w->list.erase(queued_element++);
}
else
diff --git a/indra/aistatemachine/aistatemachine.h b/indra/aistatemachine/aistatemachine.h
index 2b019c91f..047fe0515 100644
--- a/indra/aistatemachine/aistatemachine.h
+++ b/indra/aistatemachine/aistatemachine.h
@@ -39,6 +39,7 @@
#include
#include
+class AIConditionBase;
class AIStateMachine;
class AIEngine
@@ -132,6 +133,7 @@ class AIStateMachine : public LLThreadSafeRefCount
struct sub_state_type {
state_type run_state;
state_type advance_state;
+ AIConditionBase* blocked;
bool reset;
bool need_run;
bool idle;
@@ -195,20 +197,36 @@ class AIStateMachine : public LLThreadSafeRefCount
bool mDebugAdvanceStatePending; // True while advance_state() was called by not handled yet.
bool mDebugRefCalled; // True when ref() is called (or will be called within the critial area of mMultiplexMutex).
#endif
+#ifdef CWDEBUG
+ protected:
+ bool mSMDebug; // Print debug output only when true.
+#endif
+ private:
U64 mRuntime; // Total time spent running in the main thread (in clocks).
public:
- AIStateMachine(void) : mCallback(NULL), mDefaultEngine(NULL), mYieldEngine(NULL),
+ AIStateMachine(CWD_ONLY(bool debug)) : mCallback(NULL), mDefaultEngine(NULL), mYieldEngine(NULL),
#ifdef SHOW_ASSERT
mThreadId(AIThreadID::none), mDebugLastState(bs_killed), mDebugShouldRun(false), mDebugAborted(false), mDebugContPending(false),
mDebugSetStatePending(false), mDebugAdvanceStatePending(false), mDebugRefCalled(false),
+#endif
+#ifdef CWDEBUG
+ mSMDebug(debug),
#endif
mRuntime(0)
{ }
protected:
- // The user should call finish() (or abort(), or kill() from the call back when finish_impl() calls run()), not delete a class derived from AIStateMachine directly.
- virtual ~AIStateMachine() { llassert(multiplex_state_type_rat(mState)->base_state == bs_killed); }
+ // The user should call finish() (or abort(), or kill() from the call back when finish_impl() calls run()),
+ // not delete a class derived from AIStateMachine directly. Deleting it directly before calling run() is
+ // ok however.
+ virtual ~AIStateMachine()
+ {
+#ifdef SHOW_ASSERT
+ base_state_type state = multiplex_state_type_rat(mState)->base_state;
+ llassert(state == bs_killed || state == bs_reset);
+#endif
+ }
public:
// These functions may be called directly after creation, or from within finish_impl(), or from the call back function.
@@ -224,11 +242,13 @@ class AIStateMachine : public LLThreadSafeRefCount
void set_state(state_type new_state); // Run this state the NEXT loop.
// These functions can only be called from within multiplex_impl().
void idle(void); // Go idle unless cont() or advance_state() were called since the start of the current loop, or until they are called.
+ void wait(AIConditionBase& condition); // The same as idle(), but wake up when AICondition::signal() is called.
void finish(void); // Mark that the state machine finished and schedule the call back.
void yield(void); // Yield to give CPU to other state machines, but do not go idle.
void yield(AIEngine* engine); // Yield to give CPU to other state machines, but do not go idle. Continue running from engine 'engine'.
void yield_frame(unsigned int frames); // Run from the main-thread engine after at least 'frames' frames have passed.
void yield_ms(unsigned int ms); // Run from the main-thread engine after roughly 'ms' miliseconds have passed.
+ bool yield_if_not(AIEngine* engine); // Do not really yield, unless the current engine is not 'engine'. Returns true if it switched engine.
public:
// This function can be called from multiplex_imp(), but also by a child state machine and
@@ -236,11 +256,12 @@ class AIStateMachine : public LLThreadSafeRefCount
// to access this state machine.
void abort(void); // Abort the state machine (unsuccessful finish).
- // These are the only two functions that can be called by any thread at any moment.
+ // These are the only three functions that can be called by any thread at any moment.
// Those threads should use an LLPointer to access this state machine.
void cont(void); // Guarantee at least one full run of multiplex() after this function is called. Cancels the last call to idle().
void advance_state(state_type new_state); // Guarantee at least one full run of multiplex() after this function is called
// iff new_state is larger than the last state that was processed.
+ bool signalled(void); // Call cont() iff this state machine is still blocked after a call to wait(). Returns false if it already unblocked.
public:
// Accessors.
diff --git a/indra/aistatemachine/aistatemachinethread.h b/indra/aistatemachine/aistatemachinethread.h
index 780060bb6..2891cbb77 100644
--- a/indra/aistatemachine/aistatemachinethread.h
+++ b/indra/aistatemachine/aistatemachinethread.h
@@ -181,7 +181,11 @@ class AIStateMachineThreadBase : public AIStateMachine {
static state_type const max_state = wait_stopped + 1;
protected:
- AIStateMachineThreadBase(void) { }
+ AIStateMachineThreadBase(CWD_ONLY(bool debug))
+#ifdef CWDEBUG
+ : AIStateMachine(debug)
+#endif
+ { }
private:
// Handle initializing the object.
@@ -217,7 +221,10 @@ class AIStateMachineThread : public AIStateMachineThreadBase {
public:
// Constructor.
- AIStateMachineThread(void)
+ AIStateMachineThread(CWD_ONLY(bool debug))
+#ifdef CWDEBUG
+ : AIStateMachineThreadBase(debug)
+#endif
{
*AIThreadImpl::StateMachineThread_wat(mThreadImpl.mStateMachineThread) = this;
}
diff --git a/indra/aistatemachine/aitimer.h b/indra/aistatemachine/aitimer.h
index 5b028c6e0..3ee510007 100644
--- a/indra/aistatemachine/aitimer.h
+++ b/indra/aistatemachine/aitimer.h
@@ -76,7 +76,11 @@ class AITimer : public AIStateMachine {
F64 mInterval; //!< Input variable: interval after which the event will be generated, in seconds.
public:
- AITimer(void) : mInterval(0) { DoutEntering(dc::statemachine, "AITimer(void) [" << (void*)this << "]"); }
+ AITimer(CWD_ONLY(bool debug = false)) :
+#ifdef CWDEBUG
+ AIStateMachine(debug),
+#endif
+ mInterval(0) { DoutEntering(dc::statemachine(mSMDebug), "AITimer(void) [" << (void*)this << "]"); }
/**
* @brief Set the interval after which the timer should expire.
@@ -96,7 +100,7 @@ class AITimer : public AIStateMachine {
protected:
// Call finish() (or abort()), not delete.
- /*virtual*/ ~AITimer() { DoutEntering(dc::statemachine, "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); }
+ /*virtual*/ ~AITimer() { DoutEntering(dc::statemachine(mSMDebug), "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); }
// Handle initializing the object.
/*virtual*/ void initialize_impl(void);
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index a45c07f69..c2458b098 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -46,6 +46,10 @@ if (WINDOWS)
set(MSVC_DIR 10.0)
set(MSVC_SUFFIX 100)
endif (MSVC10)
+ if (MSVC11)
+ set(MSVC_DIR 11.0)
+ set(MSVC_SUFFIX 110)
+ endif (MSVC11)
# Remove default /Zm1000 flag that cmake inserts
string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
@@ -78,11 +82,17 @@ if (WINDOWS)
/W3
/c
/Zc:forScope
- /Zc:wchar_t-
+ /Zc:wchar_t-
/nologo
/Oy-
- /arch:SSE2
)
+
+ # SSE2 is implied on win64
+ if(WORD_SIZE EQUAL 32)
+ add_definitions(/arch:SSE2)
+ else(WORD_SIZE EQUAL 32)
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4267 /wd4250 /wd4244")
+ endif(WORD_SIZE EQUAL 32)
# configure win32 API for windows XP+ compatibility
set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
diff --git a/indra/cmake/CopyWinLibs.cmake b/indra/cmake/CopyWinLibs.cmake
index 9d52499a1..afd4d31f7 100644
--- a/indra/cmake/CopyWinLibs.cmake
+++ b/indra/cmake/CopyWinLibs.cmake
@@ -6,6 +6,14 @@
include(CMakeCopyIfDifferent)
+if(WORD_SIZE EQUAL 32)
+ set(debug_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+ set(release_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+else(WORD_SIZE EQUAL 32)
+ set(debug_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/x86_64-win/lib/debug")
+ set(release_libs_dir "${CMAKE_SOURCE_DIR}/../libraries/x86_64-win/lib/release")
+endif(WORD_SIZE EQUAL 32)
+
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32")
set(vivox_files
SLVoice.exe
@@ -23,7 +31,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
-set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+set(debug_src_dir "${debug_libs_dir}")
set(debug_files
libhunspell.dll
libapr-1.dll
@@ -44,7 +52,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Debug config runtime files required for the plugin test mule
-set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+set(plugintest_debug_src_dir "${debug_libs_dir}")
set(plugintest_debug_files
libeay32.dll
qtcored4.dll
@@ -63,7 +71,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Debug config runtime files required for the plugin test mule (Qt image format plugins)
-set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats")
+set(plugintest_debug_src_dir "${debug_libs_dir}/imageformats")
set(plugintest_debug_files
qgifd4.dll
qicod4.dll
@@ -89,7 +97,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugin test mule
-set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+set(plugintest_release_src_dir "${release_libs_dir}")
set(plugintest_release_files
libeay32.dll
qtcore4.dll
@@ -116,7 +124,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
-set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats")
+set(plugintest_release_src_dir "${release_libs_dir}/imageformats")
set(plugintest_release_files
qgif4.dll
qico4.dll
@@ -158,7 +166,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Debug config runtime files required for the plugins
-set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+set(plugins_debug_src_dir "${debug_libs_dir}")
set(plugins_debug_files
libeay32.dll
qtcored4.dll
@@ -177,7 +185,7 @@ copy_if_different(
set(all_targets ${all_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugins
-set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+set(plugins_release_src_dir "${release_libs_dir}")
set(plugins_release_files
libeay32.dll
qtcore4.dll
@@ -203,9 +211,9 @@ copy_if_different(
)
set(all_targets ${all_targets} ${out_targets})
-set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+
+set(release_src_dir "${release_libs_dir}")
set(release_files
- libtcmalloc_minimal.dll
libhunspell.dll
libapr-1.dll
libaprutil-1.dll
@@ -216,8 +224,21 @@ set(release_files
glod.dll
)
+if(WORD_SIZE EQUAL 32)
+ set(release_files ${release_files}
+ libtcmalloc_minimal.dll
+ )
+endif(WORD_SIZE EQUAL 32)
+
+
if(FMODEX)
- find_path(FMODEX_BINARY_DIR fmodex.dll
+ if (WORD_SIZE EQUAL 32)
+ set(fmodex_dll_file "fmodex.dll")
+ else (WORD_SIZE EQUAL 32)
+ set(fmodex_dll_file "fmodex64.dll")
+ endif (WORD_SIZE EQUAL 32)
+
+ find_path(FMODEX_BINARY_DIR "${fmodex_dll_file}"
"${release_src_dir}"
"${FMODEX_SDK_DIR}/api"
"${FMODEX_SDK_DIR}"
@@ -225,11 +246,11 @@ if(FMODEX)
)
if(FMODEX_BINARY_DIR)
- copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmodex.dll)
+ copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets "${fmodex_dll_file}")
set(all_targets ${all_targets} ${out_targets})
- copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmodex.dll)
+ copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets "${fmodex_dll_file}")
set(all_targets ${all_targets} ${out_targets})
- copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmodex.dll)
+ copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets "${fmodex_dll_file}")
set(all_targets ${all_targets} ${out_targets})
endif(FMODEX_BINARY_DIR)
endif(FMODEX)
@@ -285,105 +306,6 @@ copy_if_different(
)
set(all_targets ${all_targets} ${out_targets})
-# Copy MS C runtime dlls, required for packaging.
-# *TODO - Adapt this to support VC9
-if (MSVC80)
- FIND_PATH(debug_msvc8_redist_path msvcr80d.dll
- PATHS
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/Debug_NonRedist/x86/Microsoft.VC80.DebugCRT
- NO_DEFAULT_PATH
- NO_DEFAULT_PATH
- )
-
- if(EXISTS ${debug_msvc8_redist_path})
- set(debug_msvc8_files
- msvcr80d.dll
- msvcp80d.dll
- Microsoft.VC80.DebugCRT.manifest
- )
-
- copy_if_different(
- ${debug_msvc8_redist_path}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug"
- out_targets
- ${debug_msvc8_files}
- )
- set(all_targets ${all_targets} ${out_targets})
-
- set(debug_appconfig_file ${CMAKE_CURRENT_BINARY_DIR}/Debug/${VIEWER_BINARY_NAME}.exe.config)
- add_custom_command(
- OUTPUT ${debug_appconfig_file}
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/build_win32_appConfig.py
- ${CMAKE_CURRENT_BINARY_DIR}/Debug/Microsoft.VC80.DebugCRT.manifest
- ${CMAKE_CURRENT_SOURCE_DIR}/SecondLifeDebug.exe.config
- ${debug_appconfig_file}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Debug/Microsoft.VC80.DebugCRT.manifest
- COMMENT "Creating debug app config file"
- )
-
- endif (EXISTS ${debug_msvc8_redist_path})
-
- FIND_PATH(release_msvc8_redist_path msvcr80.dll
- PATHS
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC80.CRT
- NO_DEFAULT_PATH
- NO_DEFAULT_PATH
- )
-
- if(EXISTS ${release_msvc8_redist_path})
- set(release_msvc8_files
- msvcr80.dll
- msvcp80.dll
- Microsoft.VC80.CRT.manifest
- )
-
- copy_if_different(
- ${release_msvc8_redist_path}
- "${CMAKE_CURRENT_BINARY_DIR}/Release"
- out_targets
- ${release_msvc8_files}
- )
- set(all_targets ${all_targets} ${out_targets})
-
- copy_if_different(
- ${release_msvc8_redist_path}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
- out_targets
- ${release_msvc8_files}
- )
- set(all_targets ${all_targets} ${out_targets})
-
- set(release_appconfig_file ${CMAKE_CURRENT_BINARY_DIR}/Release/${VIEWER_BINARY_NAME}.exe.config)
- add_custom_command(
- OUTPUT ${release_appconfig_file}
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/build_win32_appConfig.py
- ${CMAKE_CURRENT_BINARY_DIR}/Release/Microsoft.VC80.CRT.manifest
- ${CMAKE_CURRENT_SOURCE_DIR}/SecondLife.exe.config
- ${release_appconfig_file}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Release/Microsoft.VC80.CRT.manifest
- COMMENT "Creating release app config file"
- )
-
- set(relwithdebinfo_appconfig_file ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/${VIEWER_BINARY_NAME}.exe.config)
- add_custom_command(
- OUTPUT ${relwithdebinfo_appconfig_file}
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/build_win32_appConfig.py
- ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/Microsoft.VC80.CRT.manifest
- ${CMAKE_CURRENT_SOURCE_DIR}/SecondLife.exe.config
- ${relwithdebinfo_appconfig_file}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/Microsoft.VC80.CRT.manifest
- COMMENT "Creating relwithdebinfo app config file"
- )
-
- endif (EXISTS ${release_msvc8_redist_path})
-endif (MSVC80)
-
add_custom_target(copy_win_libs ALL
DEPENDS
${all_targets}
diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake
index dbac0ebac..f3425f1b2 100644
--- a/indra/cmake/FMODEX.cmake
+++ b/indra/cmake/FMODEX.cmake
@@ -16,7 +16,7 @@ if (NOT FMODEX_LIBRARY)
)
elseif(WORD_SIZE EQUAL 64)
find_library(FMODEX_LIBRARY
- fmodex64 fmodexL64
+ fmodex64_vc fmodexL64_vc fmodex64 fmodexL64
PATHS
"${FMODEX_SDK_DIR}/api/lib"
"${FMODEX_SDK_DIR}/api"
@@ -25,21 +25,31 @@ if (NOT FMODEX_LIBRARY)
)
endif(WORD_SIZE EQUAL 32)
endif(FMODEX_SDK_DIR)
- if(WINDOWS AND NOT FMODEX_LIBRARY)
- set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows")
- find_library(FMODEX_LIBRARY
- fmodex_vc fmodexL_vc
- PATHS
- "${FMODEX_PROG_DIR}/api/lib"
- "${FMODEX_PROG_DIR}/api"
- "${FMODEX_PROG_DIR}"
- )
+ if(WINDOWS AND NOT FMODEX_SDK_DIR)
+ GET_FILENAME_COMPONENT(FMODEX_PROG_DIR [HKEY_CURRENT_USER\\Software\\FMOD\ Programmers\ API\ Windows] ABSOLUTE CACHE)
+ if(WORD_SIZE EQUAL 32)
+ find_library(FMODEX_LIBRARY
+ fmodex_vc fmodexL_vc
+ PATHS
+ "${FMODEX_PROG_DIR}/api/lib"
+ "${FMODEX_PROG_DIR}/api"
+ "${FMODEX_PROG_DIR}"
+ )
+ else(WORD_SIZE EQUAL 32)
+ find_library(FMODEX_LIBRARY
+ fmodex64_vc fmodexL64_vc
+ PATHS
+ "${FMODEX_PROG_DIR}/api/lib"
+ "${FMODEX_PROG_DIR}/api"
+ "${FMODEX_PROG_DIR}"
+ )
+ endif(WORD_SIZE EQUAL 32)
if(FMODEX_LIBRARY)
message(STATUS "Found fmodex in ${FMODEX_PROG_DIR}")
set(FMODEX_SDK_DIR "${FMODEX_PROG_DIR}")
set(FMODEX_SDK_DIR "${FMODEX_PROG_DIR}" CACHE PATH "Path to the FMOD Ex SDK." FORCE)
endif(FMODEX_LIBRARY)
- endif(WINDOWS AND NOT FMODEX_LIBRARY)
+ endif(WINDOWS AND NOT FMODEX_SDK_DIR)
endif (NOT FMODEX_LIBRARY)
find_path(FMODEX_INCLUDE_DIR fmod.hpp
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 10dd25ac2..70d025d85 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -37,10 +37,15 @@ set(LIBS_PREBUILT_DIR ${CMAKE_SOURCE_DIR}/../libraries CACHE PATH
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(WINDOWS ON BOOL FORCE)
- set(ARCH i686)
- set(LL_ARCH ${ARCH}_win32)
- set(LL_ARCH_DIR ${ARCH}-win32)
- set(WORD_SIZE 32)
+ if (WORD_SIZE EQUAL 32)
+ set(ARCH i686)
+ set(LL_ARCH ${ARCH}_win32)
+ set(LL_ARCH_DIR ${ARCH}-win32)
+ elseif (WORD_SIZE EQUAL 64)
+ set(ARCH x86_64)
+ set(LL_ARCH ${ARCH}_win)
+ set(LL_ARCH_DIR ${ARCH}-win)
+ endif (WORD_SIZE EQUAL 32)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
@@ -119,15 +124,17 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LL_ARCH_DIR universal-darwin)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-if (WINDOWS)
+if (WINDOWS AND WORD_SIZE EQUAL 32)
set(PREBUILT_TYPE windows)
+elseif (WINDOWS AND WORD_SIZE EQUAL 64)
+ set(PREBUILT_TYPE windows64)
elseif(DARWIN)
set(PREBUILT_TYPE darwin)
elseif(LINUX AND WORD_SIZE EQUAL 32)
set(PREBUILT_TYPE linux)
elseif(LINUX AND WORD_SIZE EQUAL 64)
set(PREBUILT_TYPE linux64)
-endif(WINDOWS)
+endif(WINDOWS AND WORD_SIZE EQUAL 32)
# Default deploy grid
set(GRID agni CACHE STRING "Target Grid")
diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h
index 4167813ea..d3c4e686b 100644
--- a/indra/cwdebug/debug.h
+++ b/indra/cwdebug/debug.h
@@ -144,6 +144,7 @@ extern LL_COMMON_API fake_channel const snapshot;
#define CWDEBUG_MARKER 0
#define BACKTRACE do { } while(0)
+#define CWD_ONLY(...)
#endif // !DOXYGEN
@@ -180,6 +181,7 @@ extern LL_COMMON_API fake_channel const snapshot;
#include
#define CWD_API __attribute__ ((visibility("default")))
+#define CWD_ONLY(...) __VA_ARGS__
//! Debug specific code.
namespace debug {
diff --git a/indra/develop.py b/indra/develop.py
index 853c37e14..4e93c27e9 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -443,9 +443,15 @@ class WindowsSetup(PlatformSetup):
'vc100' : {
'gen' : r'Visual Studio 10',
'ver' : r'10.0'
+ },
+ 'vc110' : {
+ 'gen' : r'Visual Studio 11',
+ 'ver' : r'11.0'
}
}
+
gens['vs2010'] = gens['vc100']
+ gens['vs2012'] = gens['vc110']
search_path = r'C:\windows'
exe_suffixes = ('.exe', '.bat', '.com')
@@ -503,6 +509,9 @@ class WindowsSetup(PlatformSetup):
project_name=self.project_name,
word_size=self.word_size,
)
+ if self.word_size == 64:
+ args["generator"] += r' Win64'
+
#if simple:
# return 'cmake %(opts)s "%(dir)s"' % args
return ('cmake -G "%(generator)s" '
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 11945a239..1522e3e9a 100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -192,6 +192,8 @@ def usage(srctree=""):
arg['description'] % nd)
def main():
+ print "cwd:", os.getcwd()
+ print " ".join(sys.argv)
option_names = [arg['name'] + '=' for arg in ARGUMENTS]
option_names.append('help')
options, remainder = getopt.getopt(sys.argv[1:], "", option_names)
@@ -266,7 +268,7 @@ class LLManifest(object):
__metaclass__ = LLManifestRegistry
manifests = {}
def for_platform(self, platform, arch = None):
- if arch:
+ if arch and platform != "windows":
platform = platform + '_' + arch
return self.manifests[platform.lower()]
for_platform = classmethod(for_platform)
diff --git a/indra/libhacd/hacdHACD.h b/indra/libhacd/hacdHACD.h
index 0c9f11653..2ca9a4ae7 100644
--- a/indra/libhacd/hacdHACD.h
+++ b/indra/libhacd/hacdHACD.h
@@ -22,7 +22,9 @@
#include
#include
#include
-
+#if defined(_MSC_VER) && _MSC_VER >= 1700
+#include
+#endif
namespace HACD
{
const double sc_pi = 3.14159265;
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index eea39f0c1..92a0b27e9 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -611,8 +611,10 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl;
mCurrentDecodep->flushBadFile();
LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
- adp->setHasValidData(false);
- adp->setHasCompletedDecode(true);
+ if(adp)
+ {
+ adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
+ }
mCurrentDecodep = NULL;
done = TRUE;
}
@@ -634,10 +636,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
}
else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
{
- adp->setHasCompletedDecode(true);
- adp->setHasDecodedData(true);
- adp->setHasValidData(true);
-
+ adp->setLoadState(LLAudioData::STATE_LOAD_READY);
// 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.
@@ -645,7 +644,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
}
else
{
- adp->setHasCompletedDecode(true);
+ adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
llinfos << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << llendl;
}
mCurrentDecodep = NULL;
@@ -688,8 +687,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
LLAudioData *adp = gAudiop->getAudioData(uuid);
if(adp)
{
- adp->setHasValidData(false);
- adp->setHasCompletedDecode(true);
+ adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
}
mCurrentDecodep = NULL;
}
@@ -715,23 +713,13 @@ void LLAudioDecodeMgr::processQueue(const F32 num_secs)
mImpl->processQueue(num_secs);
}
-BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
+bool LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
{
- if (gAudiop->hasDecodedFile(uuid))
- {
- // Already have a decoded version, don't need to decode it.
- //llinfos << "addDecodeRequest for " << uuid << " has decoded file already" << llendl;
- return TRUE;
- }
-
- if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
- {
- // Just put it on the decode queue.
- //llinfos << "addDecodeRequest for " << uuid << " has local asset file already" << llendl;
- mImpl->mDecodeQueue.push(uuid);
- return TRUE;
- }
-
- //llinfos << "addDecodeRequest for " << uuid << " no file available" << llendl;
- return FALSE;
+ if(!uuid.notNull())
+ return false;
+ else if (!gAssetStorage || !gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
+ return false;
+
+ mImpl->mDecodeQueue.push(uuid);
+ return true;
}
diff --git a/indra/llaudio/llaudiodecodemgr.h b/indra/llaudio/llaudiodecodemgr.h
index e42fe8a40..917511daa 100644
--- a/indra/llaudio/llaudiodecodemgr.h
+++ b/indra/llaudio/llaudiodecodemgr.h
@@ -44,7 +44,7 @@ public:
~LLAudioDecodeMgr();
void processQueue(const F32 num_secs = 0.005);
- BOOL addDecodeRequest(const LLUUID &uuid);
+ bool addDecodeRequest(const LLUUID &uuid);
void addAudioRequest(const LLUUID &uuid);
protected:
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index c1f362d32..6aed74daf 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -113,6 +113,8 @@ void LLAudioEngine::setDefaults()
for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++)
mSecondaryGain[i] = 1.0f;
+ mCurrentTransfer = NULL;
+
mAllowLargeSounds = false;
}
@@ -354,6 +356,11 @@ void LLAudioEngine::idle(F32 max_decode_time)
// Increment iter here (it is not used anymore), so we can use continue below to move on to the next source.
++iter;
+ if(!sourcep->isLoop() && sourcep->mPlayedOnce && (!sourcep->mChannelp || !sourcep->mChannelp->isPlaying()))
+ {
+ continue;
+ }
+
LLAudioData *adp = sourcep->getCurrentData();
//If there is no current data at all, or if it hasn't loaded, we must skip this source.
if (!adp || !adp->getBuffer())
@@ -509,9 +516,8 @@ void LLAudioEngine::idle(F32 max_decode_time)
// Decode audio files
gAudioDecodeMgrp->processQueue(max_decode_time);
- // Call this every frame, just in case we somehow
- // missed picking it up in all the places that can add
- // or request new data.
+ // Just call here every frame. It makes little sense to call elsewhere,
+ // as it's throttled to one active preloading loading sound at a time anyhow
startNextTransfer();
updateInternetStream();
@@ -660,10 +666,7 @@ bool LLAudioEngine::preloadSound(const LLUUID &uuid)
if(uuid.isNull())
return false;
- gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure
- // that we have an entry, which will mean that the audio engine knows about this
-
- if (gAudioDecodeMgrp->addDecodeRequest(uuid))
+ if(getAudioData(uuid)->getLoadState() >= LLAudioData::STATE_LOAD_DECODING)
{
// This means that we do have a local copy, and we're working on decoding it.
return true;
@@ -1064,29 +1067,39 @@ bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
}
}
-
-bool LLAudioEngine::hasLocalFile(const LLUUID &uuid)
-{
- // See if it's in the VFS.
- return gVFS->getExists(uuid, LLAssetType::AT_SOUND);
-}
-
-
void LLAudioEngine::startNextTransfer()
{
//LL_INFOS("AudioEngine") << "LLAudioEngine::startNextTransfer()" << LL_ENDL;
- if (!gAssetStorage->isUpstreamOK() || mCurrentTransfer.notNull() || getMuted())
+ if (getMuted())
{
- //LL_INFOS("AudioEngine") << "Transfer in progress, aborting" << LL_ENDL;
return;
}
+ else if(mCurrentTransferTimer.getElapsedTimeF32() <= .1f)
+ {
+ return;
+ }
+ else if(mCurrentTransfer && mCurrentTransfer->isInPreload())
+ {
+ //Keep updating until it either errors out or completes.
+ mCurrentTransfer->updateLoadState();
+ return;
+ }
+ else
+ {
+ mCurrentTransfer = NULL;
+ }
+
+ //Technically, mCurrentTransfer could end up pointing to an audiodata object that's already
+ //being transmitted/decoded if such was spawned via needing it for playback immediately.
+ //This will effectively block us from choosing a lower priority audiodata object until the
+ //immediate ones are done, but it's not a real problem.
// Get the ID for the next asset that we want to transfer.
// Pick one in the following order:
- LLUUID asset_id;
S32 i;
LLAudioSource *asp = NULL;
LLAudioData *adp = NULL;
+ LLAudioData *cur_adp = NULL;
data_map::iterator data_iter;
// Check all channels for currently playing sounds.
@@ -1119,15 +1132,15 @@ void LLAudioEngine::startNextTransfer()
continue;
}
- if (!adp->hasLocalData() && adp->hasValidData())
+ if (adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
}
}
// Check all channels for currently queued sounds.
- if (asset_id.isNull())
+ if (!cur_adp)
{
max_pri = -1.f;
for (i = 0; i < MAX_CHANNELS; i++)
@@ -1155,16 +1168,16 @@ void LLAudioEngine::startNextTransfer()
continue;
}
- if (!adp->hasLocalData() && adp->hasValidData())
+ if (adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
}
}
}
// Check all live channels for other sounds (preloads).
- if (asset_id.isNull())
+ if (!cur_adp)
{
max_pri = -1.f;
for (i = 0; i < MAX_CHANNELS; i++)
@@ -1195,17 +1208,17 @@ void LLAudioEngine::startNextTransfer()
continue;
}
- if (!adp->hasLocalData() && adp->hasValidData())
+ if (adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
}
}
}
}
// Check all sources
- if (asset_id.isNull())
+ if (!cur_adp)
{
max_pri = -1.f;
source_map::iterator source_iter;
@@ -1223,18 +1236,18 @@ void LLAudioEngine::startNextTransfer()
}
adp = asp->getCurrentData();
- if (adp && !adp->hasLocalData() && adp->hasValidData())
+ if (adp && adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
continue;
}
adp = asp->getQueuedData();
- if (adp && !adp->hasLocalData() && adp->hasValidData())
+ if (adp && adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
continue;
}
@@ -1246,35 +1259,41 @@ void LLAudioEngine::startNextTransfer()
continue;
}
- if (!adp->hasLocalData() && adp->hasValidData())
+ if (adp->isInPreload())
{
- asset_id = adp->getID();
max_pri = asp->getPriority();
+ cur_adp = adp;
break;
}
}
}
}
- if (asset_id.isNull() && !mPreloadSystemList.empty())
+ if (!cur_adp)
{
- asset_id = mPreloadSystemList.front();
- mPreloadSystemList.pop_front();
+ while(!mPreloadSystemList.empty())
+ {
+ adp = getAudioData(mPreloadSystemList.front());
+ mPreloadSystemList.pop_front();
+ if(adp->isInPreload())
+ {
+ cur_adp = adp;
+ break;
+ }
+ }
}
- else if(asset_id.notNull())
+ else if(cur_adp)
{
- std::list::iterator it = std::find(mPreloadSystemList.begin(),mPreloadSystemList.end(),asset_id);
+ std::list::iterator it = std::find(mPreloadSystemList.begin(),mPreloadSystemList.end(),cur_adp->getID());
if(it != mPreloadSystemList.end())
mPreloadSystemList.erase(it);
}
- if (asset_id.notNull())
+ if (cur_adp)
{
- LL_DEBUGS("AudioEngine") << "Getting asset data for: " << asset_id << LL_ENDL;
- gAudiop->mCurrentTransfer = asset_id;
- gAudiop->mCurrentTransferTimer.reset();
- gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
- assetCallback, NULL);
+ mCurrentTransfer = cur_adp;
+ mCurrentTransferTimer.reset();
+ mCurrentTransfer->updateLoadState();
}
else
{
@@ -1289,22 +1308,20 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
if(!gAudiop)
return;
+ LLAudioData *adp = gAudiop->getAudioData(uuid);
+
if (result_code)
{
LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << LL_ENDL;
// Need to mark data as bad to avoid constant rerequests.
- LLAudioData *adp = gAudiop->getAudioData(uuid);
+
if (adp)
- { // Make sure everything is cleared
- adp->setHasValidData(false);
- adp->setHasLocalData(false);
- adp->setHasDecodedData(false);
- adp->setHasCompletedDecode(true);
+ {
+ adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
}
}
else
{
- LLAudioData *adp = gAudiop->getAudioData(uuid);
if (!adp)
{
// Should never happen
@@ -1313,13 +1330,11 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
else
{
// LL_INFOS("AudioEngine") << "Got asset callback with good audio data for " << uuid << ", making decode request" << LL_ENDL;
- adp->setHasValidData(true);
- adp->setHasLocalData(true);
- gAudioDecodeMgrp->addDecodeRequest(uuid);
+ adp->setLoadState(LLAudioData::STATE_LOAD_REQ_DECODE);
+ //Immediate decode.
+ adp->updateLoadState();
}
}
- gAudiop->mCurrentTransfer = LLUUID::null;
- gAudiop->startNextTransfer();
}
@@ -1411,32 +1426,29 @@ void LLAudioSource::update()
//Make sure this source looks like its brand new again to prevent removal.
mPlayedOnce = false;
mAgeTimer.reset();
-
- gAudiop->startNextTransfer();
}
LLAudioData *adp = getCurrentData();
if (adp && !adp->getBuffer())
{
- // Update the audio buffer first - load a sound if we have it.
- // Note that this could potentially cause us to waste time updating buffers
- // for sounds that actually aren't playing, although this should be mitigated
- // by the fact that we limit the number of buffers, and we flush buffers based
- // on priority.
- if (adp->hasDecodedData())
+ if(adp->getLoadState() == LLAudioData::STATE_LOAD_ERROR)
{
- if(!adp->load() && adp->hasCompletedDecode())
- {
- LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << LL_ENDL;
- mCorrupted = true ;
- }
+ LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << LL_ENDL;
+ mCorrupted = true ;
}
- else if (adp->hasLocalData() && adp->hasValidData())
+ else if(adp->getLoadState() == LLAudioData::STATE_LOAD_READY)
{
- if (adp->getID().notNull())
- {
- gAudioDecodeMgrp->addDecodeRequest(adp->getID());
- }
+ // Update the audio buffer first - load a sound if we have it.
+ // Note that this could potentially cause us to waste time updating buffers
+ // for sounds that actually aren't playing, although this should be mitigated
+ // by the fact that we limit the number of buffers, and we flush buffers based
+ // on priority.
+ adp->load(); //If it fails, just try again next update.
+ }
+ else
+ {
+ //The sound wasn't preloaded yet... so we must kick off the process.
+ adp->updateLoadState();
}
}
}
@@ -1524,9 +1536,6 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
mCurrentDatap = adp;
- // Make sure the audio engine knows that we want to request this sound.
- gAudiop->startNextTransfer();
-
return true;
}
@@ -1536,7 +1545,6 @@ bool LLAudioSource::isDone() const
static const F32 MAX_AGE = 60.f;
static const F32 MAX_UNPLAYED_AGE = 15.f;
static const F32 MAX_MUTED_AGE = 11.f;
-
if(mCorrupted)
{
// If we decode bad data then just kill this source entirely.
@@ -1570,7 +1578,7 @@ bool LLAudioSource::isDone() const
LLAudioData* adp = mCurrentDatap;
//Still decoding.
- if(adp && !adp->hasDecodedData() && adp->hasValidData())
+ if(adp && adp->isInPreload())
return false;
// We don't have a channel assigned, and it's been
@@ -1599,7 +1607,6 @@ void LLAudioSource::preload(const LLUUID &audio_id)
{
// Add it to the preload list.
mPreloadMap[audio_id] = gAudiop->getAudioData(audio_id);
- gAudiop->startNextTransfer();
}
}
@@ -1617,7 +1624,7 @@ bool LLAudioSource::hasPendingPreloads() const
{
continue;
}
- if (!adp->hasDecodedData() && adp->hasValidData())
+ if (adp->isInPreload())
{
// This source is still waiting for a preload
return true;
@@ -1734,27 +1741,42 @@ bool LLAudioChannel::updateBuffer()
LLAudioData::LLAudioData(const LLUUID &uuid) :
mID(uuid),
mBufferp(NULL),
- mHasLocalData(false),
- mHasDecodedData(false),
- mHasCompletedDecode(false),
- mHasValidData(true)
+ mLoadState(STATE_LOAD_ERROR)
{
if (uuid.isNull())
{
// This is a null sound.
return;
}
-
- if (gAudiop && gAudiop->hasDecodedFile(uuid))
+
+ if(gAudiop->hasDecodedFile(getID()))
+ mLoadState = STATE_LOAD_READY;
+ else if(gAssetStorage && gAssetStorage->hasLocalAsset(getID(), LLAssetType::AT_SOUND))
+ mLoadState = STATE_LOAD_REQ_DECODE;
+ else
+ mLoadState = STATE_LOAD_REQ_FETCH;
+}
+
+void LLAudioData::updateLoadState()
+{
+ if(mLoadState == STATE_LOAD_REQ_DECODE && gAudioDecodeMgrp)
{
- // Already have a decoded version, don't need to decode it.
- setHasLocalData(true);
- setHasDecodedData(true);
- setHasCompletedDecode(true);
+ if( gAudioDecodeMgrp->addDecodeRequest(getID()) )
+ {
+ setLoadState(STATE_LOAD_DECODING);
+ LL_INFOS("AudioEngine") << "Decoding asset data for: " << getID() << LL_ENDL;
+ }
+ else
+ {
+ setLoadState(STATE_LOAD_ERROR);
+ }
}
- else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
+ else if(mLoadState == STATE_LOAD_REQ_FETCH && gAssetStorage && gAssetStorage->isUpstreamOK())
{
- setHasLocalData(true);
+ LL_INFOS("AudioEngine") << "Fetching asset data for: " << getID() << LL_ENDL;
+ setLoadState(STATE_LOAD_FETCHING);
+
+ gAssetStorage->getAssetData(getID(), LLAssetType::AT_SOUND, LLAudioEngine::assetCallback, NULL);
}
}
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 4067f23a7..717e688df 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -177,7 +177,6 @@ public:
void cleanupBuffer(LLAudioBuffer *bufferp);
bool hasDecodedFile(const LLUUID &uuid);
- bool hasLocalFile(const LLUUID &uuid);
void setAllowLargeSounds(bool allow) { mAllowLargeSounds = allow ;}
bool getAllowLargeSounds() const {return mAllowLargeSounds;}
@@ -227,7 +226,7 @@ protected:
S32 mNumChannels;
bool mEnableWind;
- LLUUID mCurrentTransfer; // Audio file currently being transferred by the system
+ LLAudioData* mCurrentTransfer; // Audio file currently being transferred by the system
LLFrameTimer mCurrentTransferTimer;
// A list of all audio sources that are known to the viewer at this time.
@@ -400,25 +399,27 @@ public:
LLUUID getID() const { return mID; }
LLAudioBuffer *getBuffer() const { return mBufferp; }
- bool hasLocalData() const { return mHasLocalData; }
- bool hasDecodedData() const { return mHasDecodedData; }
- bool hasCompletedDecode() const { return mHasCompletedDecode; }
- bool hasValidData() const { return mHasValidData; }
+ enum ELoadState
+ {
+ STATE_LOAD_ERROR,
+ STATE_LOAD_REQ_FETCH,
+ STATE_LOAD_FETCHING,
+ STATE_LOAD_REQ_DECODE,
+ STATE_LOAD_DECODING,
+ STATE_LOAD_READY
+ };
+ ELoadState getLoadState() const { return mLoadState; }
+ ELoadState setLoadState(ELoadState state) { return mLoadState = state; }
+ bool isInPreload() const { return mLoadState > STATE_LOAD_ERROR && mLoadState < STATE_LOAD_READY; }
- void setHasLocalData(const bool hld) { mHasLocalData = hld; }
- void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; }
- void setHasCompletedDecode(const bool hcd) { mHasCompletedDecode = hcd; }
- void setHasValidData(const bool hvd) { mHasValidData = hvd; }
+ void updateLoadState();
friend class LLAudioEngine; // Severe laziness, bad.
protected:
LLUUID mID;
LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here.
- bool mHasLocalData; // Set true if the sound asset file is available locally
- bool mHasDecodedData; // Set true if the sound file has been decoded
- bool mHasCompletedDecode; // Set true when the sound is decoded
- bool mHasValidData; // Set false if decoding failed, meaning the sound asset is bad
+ ELoadState mLoadState;
};
diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp
index 300264d91..972725171 100644
--- a/indra/llaudio/llaudioengine_fmodex.cpp
+++ b/indra/llaudio/llaudioengine_fmodex.cpp
@@ -59,8 +59,13 @@ bool attemptDelayLoad()
{
__try
{
+#if defined(_WIN64)
+ if( FAILED( __HrLoadAllImportsForDll( "fmodex64.dll" ) ) )
+ return false;
+#else
if( FAILED( __HrLoadAllImportsForDll( "fmodex.dll" ) ) )
return false;
+#endif
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 472831e64..2b4c37be0 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -231,6 +231,7 @@ set(llcommon_HEADER_FILES
llstrider.h
llstring.h
llstringtable.h
+ llstaticstringtable.h
llsys.h
llthread.h
llthreadsafequeue.h
diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h
index 964b6d87a..14e25e78d 100644
--- a/indra/llcommon/llalignedarray.h
+++ b/indra/llcommon/llalignedarray.h
@@ -41,7 +41,11 @@ public:
~LLAlignedArray();
void push_back(const T& elem);
- U32 size() const { return mElementCount; }
+ void pop_back() { if(!!mElementCount) --mElementCount; }
+ bool empty() const { return !mElementCount; }
+ T& front() { return operator[](0); }
+ T& back() { return operator[](mElementCount-1); }
+ U32 size() const { return mElementCount; }
void resize(U32 size);
T* append(S32 N);
T& operator[](int idx);
diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index 07ea31a5a..e753fe309 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -184,7 +184,7 @@ LLMutex* LLFastTimer::sLogLock = NULL;
std::queue LLFastTimer::sLogQueue;
const int LLFastTimer::NamedTimer::HISTORY_NUM = 300;
-#if LL_WINDOWS
+#if defined(LL_WINDOWS) && !defined(_WIN64)
#define USE_RDTSC 1
#endif
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 5d73c2e8f..084f9780c 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -663,14 +663,6 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr)
#endif
#endif
-LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
-
-#ifdef SHOW_ASSERT
-#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast(ptr),((U32)alignment))
-#else
-#define ll_assert_aligned(ptr,alignment)
-#endif
-
//EVENTUALLY REMOVE THESE:
#include "llpointer.h"
#include "llsingleton.h"
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index ce2c593c5..a7d2eac67 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -416,7 +416,7 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)
unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
int iCurThreadPriority = GetThreadPriority(hThread);
unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
- GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
+ GetProcessAffinityMask(hProcess, (PDWORD_PTR)&dwProcessMask, (PDWORD_PTR)&dwSystemMask);
SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h
new file mode 100644
index 000000000..f3c46e749
--- /dev/null
+++ b/indra/llcommon/llstaticstringtable.h
@@ -0,0 +1,82 @@
+/**
+ * @file llstringtable.h
+ * @brief The LLStringTable class provides a _fast_ method for finding
+ * unique copies of strings.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_STATIC_STRING_TABLE_H
+#define LL_STATIC_STRING_TABLE_H
+
+#include "lldefs.h"
+#include
+#include "llstl.h"
+
+class LLStaticHashedString
+{
+public:
+
+ LLStaticHashedString(const std::string& s)
+ {
+ string_hash = makehash(s);
+ string = s;
+ }
+
+ const std::string& String() const { return string; }
+ size_t Hash() const { return string_hash; }
+
+ bool operator==(const LLStaticHashedString& b) const { return String() == b.String(); }
+
+protected:
+
+ size_t makehash(const std::string& s)
+ {
+ size_t len = s.size();
+ const char* c = s.c_str();
+ size_t hashval = 0;
+ for (size_t i=0; i
+class LLStaticStringTable
+ : public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
+{
+};
+
+#endif
+
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 6f3deba0c..2e0531263 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -299,10 +299,15 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
++sRawImageCount;
}
-LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
+LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
: LLImageBase(), mCacheEntries(0)
{
- if(allocateDataSize(width, height, components) && data)
+
+ if(no_copy)
+ {
+ setDataAndSize(data, width, height, components);
+ }
+ else if(allocateDataSize(width, height, components) && data)
{
memcpy(getData(), data, width*height*components);
}
@@ -762,8 +767,17 @@ void LLImageRaw::fill( const LLColor4U& color )
}
}
+LLPointer LLImageRaw::duplicate()
+{
+ if(getNumRefs() < 2)
+ {
+ return this; //nobody else refences to this image, no need to duplicate.
+ }
-
+ //make a duplicate
+ LLPointer dup = new LLImageRaw(getData(), getWidth(), getHeight(), getComponents());
+ return dup;
+}
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 012031338..1e94f49f4 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -173,7 +173,7 @@ protected:
public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
- LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
+ LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
@@ -204,6 +204,9 @@ public:
// Copy operations
+ //duplicate this raw image if refCount > 1.
+ LLPointer duplicate();
+
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void copy( LLImageRaw* src );
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 6d3f06710..274663643 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -140,7 +140,7 @@ inline F64 llabs(const F64 a)
inline S32 lltrunc( F32 f )
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER )
+#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && !defined(_WIN64)
// Avoids changing the floating point control word.
// Add or subtract 0.5 - epsilon and then round
const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF };
@@ -166,7 +166,7 @@ inline S32 lltrunc( F64 f )
inline S32 llfloor( F32 f )
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER )
+#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && !defined(_WIN64)
// Avoids changing the floating point control word.
// Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version.
// Add -(0.5 - epsilon) and then round
diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h
index cebd2ace7..798795a8b 100644
--- a/indra/llmath/llsimdmath.h
+++ b/indra/llmath/llsimdmath.h
@@ -31,7 +31,7 @@
#error "Please include llmath.h before this file."
#endif
-#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 ) )
+#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 ) && !defined(_WIN64) )
#error SSE2 not enabled. LLVector4a and related class will not compile.
#endif
diff --git a/indra/llmessage/aicurleasyrequeststatemachine.cpp b/indra/llmessage/aicurleasyrequeststatemachine.cpp
index 0437055f5..294f41586 100644
--- a/indra/llmessage/aicurleasyrequeststatemachine.cpp
+++ b/indra/llmessage/aicurleasyrequeststatemachine.cpp
@@ -250,10 +250,13 @@ void AICurlEasyRequestStateMachine::finish_impl(void)
}
}
-AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(void) :
+AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(CWD_ONLY(bool debug)) :
+#ifdef CWDEBUG
+ AIStateMachine(debug),
+#endif
mTotalDelayTimeout(AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout().getTotalDelay())
{
- Dout(dc::statemachine, "Calling AICurlEasyRequestStateMachine(void) [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
+ Dout(dc::statemachine(mSMDebug), "Calling AICurlEasyRequestStateMachine(void) [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
AICurlInterface::Stats::AICurlEasyRequestStateMachine_count++;
}
@@ -264,7 +267,7 @@ void AICurlEasyRequestStateMachine::setTotalDelayTimeout(F32 totalDelayTimeout)
AICurlEasyRequestStateMachine::~AICurlEasyRequestStateMachine()
{
- Dout(dc::statemachine, "Calling ~AICurlEasyRequestStateMachine() [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
+ Dout(dc::statemachine(mSMDebug), "Calling ~AICurlEasyRequestStateMachine() [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
--AICurlInterface::Stats::AICurlEasyRequestStateMachine_count;
}
diff --git a/indra/llmessage/aicurleasyrequeststatemachine.h b/indra/llmessage/aicurleasyrequeststatemachine.h
index 662efbe20..9bab7166b 100644
--- a/indra/llmessage/aicurleasyrequeststatemachine.h
+++ b/indra/llmessage/aicurleasyrequeststatemachine.h
@@ -52,7 +52,7 @@
// Construction of a AICurlEasyRequestStateMachine might throw AICurlNoEasyHandle.
class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHandleEvents {
public:
- AICurlEasyRequestStateMachine(void);
+ AICurlEasyRequestStateMachine(CWD_ONLY(bool debug = false));
// Transparent access.
AICurlEasyRequest mCurlEasyRequest;
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 446028b0f..5aa33696e 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -49,7 +49,7 @@ set_source_files_properties(${llplugin_HEADER_FILES}
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ # add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index dcde319d2..9c5ffeb7d 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -727,7 +727,8 @@ bool LLGLManager::initGL()
}
stop_glerror();
-
+
+ //Singu Note: Multisampled texture stuff in v3 is dead, however we DO use multisampled FBOs.
if (mHasFramebufferMultisample)
{
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index b8827db9e..7dcce3e76 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -91,11 +91,22 @@ LLShaderFeatures::LLShaderFeatures()
// LLGLSL Shader implementation
//===============================
LLGLSLShader::LLGLSLShader(S32 shader_class)
-: mProgramObject(0), mShaderClass(shader_class), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE)
+ : mProgramObject(0),
+ mShaderClass(shader_class),
+ mAttributeMask(0),
+ mTotalUniformSize(0),
+ mActiveTextureChannels(0),
+ mShaderLevel(0),
+ mShaderGroup(SG_DEFAULT),
+ mUniformsDirty(FALSE)
{
LLShaderMgr::getGlobalShaderList().push_back(this);
}
+LLGLSLShader::~LLGLSLShader()
+{
+
+}
void LLGLSLShader::unload()
{
stop_glerror();
@@ -103,6 +114,7 @@ void LLGLSLShader::unload()
mTexture.clear();
mUniform.clear();
mShaderFiles.clear();
+ mDefines.clear();
if (mProgramObject)
{
@@ -127,8 +139,8 @@ void LLGLSLShader::unload()
stop_glerror();
}
-BOOL LLGLSLShader::createShader(vector * attributes,
- vector * uniforms,
+BOOL LLGLSLShader::createShader(std::vector * attributes,
+ std::vector * uniforms,
U32 varying_count,
const char** varyings)
{
@@ -151,7 +163,7 @@ BOOL LLGLSLShader::createShader(vector * attributes,
vector< pair >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
+ GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle > 0)
{
@@ -217,7 +229,8 @@ BOOL LLGLSLShader::createShader(vector * attributes,
for (S32 i = 0; i < channel_count; i++)
{
- uniform1i(llformat("tex%d", i), i);
+ LLStaticHashedString uniName(llformat("tex%d", i));
+ uniform1i(uniName, i);
}
S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
@@ -290,7 +303,7 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
}
}
-BOOL LLGLSLShader::mapAttributes(const vector * attributes)
+BOOL LLGLSLShader::mapAttributes(const std::vector * attributes)
{
//before linking, make sure reserved attributes always have consistent locations
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
@@ -309,6 +322,8 @@ BOOL LLGLSLShader::mapAttributes(const vector * attributes)
if (res)
{ //read back channel locations
+ mAttributeMask = 0;
+
//read back reserved channels first
for (U32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
@@ -317,6 +332,7 @@ BOOL LLGLSLShader::mapAttributes(const vector * attributes)
if (index != -1)
{
mAttribute[i] = index;
+ mAttributeMask |= 1 << i;
LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
}
}
@@ -324,7 +340,7 @@ BOOL LLGLSLShader::mapAttributes(const vector * attributes)
{
for (U32 i = 0; i < numAttributes; i++)
{
- const char* name = (*attributes)[i].c_str();
+ const char* name = (*attributes)[i].String().c_str();
S32 index = glGetAttribLocationARB(mProgramObject, name);
if (index != -1)
{
@@ -340,7 +356,7 @@ BOOL LLGLSLShader::mapAttributes(const vector * attributes)
return FALSE;
}
-void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
+void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
{
if (index == -1)
{
@@ -349,11 +365,55 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
GLenum type;
GLsizei length;
- GLint size;
+ GLint size = -1;
char name[1024]; /* Flawfinder: ignore */
name[0] = 0;
glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
+#if !LL_DARWIN
+ if (size > 0)
+ {
+ switch(type)
+ {
+ case GL_FLOAT_VEC2: size *= 2; break;
+ case GL_FLOAT_VEC3: size *= 3; break;
+ case GL_FLOAT_VEC4: size *= 4; break;
+ case GL_DOUBLE: size *= 2; break;
+ case GL_DOUBLE_VEC2: size *= 2; break;
+ case GL_DOUBLE_VEC3: size *= 6; break;
+ case GL_DOUBLE_VEC4: size *= 8; break;
+ case GL_INT_VEC2: size *= 2; break;
+ case GL_INT_VEC3: size *= 3; break;
+ case GL_INT_VEC4: size *= 4; break;
+ case GL_UNSIGNED_INT_VEC2: size *= 2; break;
+ case GL_UNSIGNED_INT_VEC3: size *= 3; break;
+ case GL_UNSIGNED_INT_VEC4: size *= 4; break;
+ case GL_BOOL_VEC2: size *= 2; break;
+ case GL_BOOL_VEC3: size *= 3; break;
+ case GL_BOOL_VEC4: size *= 4; break;
+ case GL_FLOAT_MAT2: size *= 4; break;
+ case GL_FLOAT_MAT3: size *= 9; break;
+ case GL_FLOAT_MAT4: size *= 16; break;
+ case GL_FLOAT_MAT2x3: size *= 6; break;
+ case GL_FLOAT_MAT2x4: size *= 8; break;
+ case GL_FLOAT_MAT3x2: size *= 6; break;
+ case GL_FLOAT_MAT3x4: size *= 12; break;
+ case GL_FLOAT_MAT4x2: size *= 8; break;
+ case GL_FLOAT_MAT4x3: size *= 12; break;
+ case GL_DOUBLE_MAT2: size *= 8; break;
+ case GL_DOUBLE_MAT3: size *= 18; break;
+ case GL_DOUBLE_MAT4: size *= 32; break;
+ case GL_DOUBLE_MAT2x3: size *= 12; break;
+ case GL_DOUBLE_MAT2x4: size *= 16; break;
+ case GL_DOUBLE_MAT3x2: size *= 12; break;
+ case GL_DOUBLE_MAT3x4: size *= 24; break;
+ case GL_DOUBLE_MAT4x2: size *= 16; break;
+ case GL_DOUBLE_MAT4x3: size *= 24; break;
+ }
+ mTotalUniformSize += size;
+ }
+#endif
+
S32 location = glGetUniformLocationARB(mProgramObject, name);
if (location != -1)
{
@@ -365,7 +425,10 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
is_array[0] = 0;
}
- mUniformMap[name] = location;
+ LLStaticHashedString hashedName(name);
+ mUniformNameMap[location] = name;
+ mUniformMap[hashedName] = location;
+
LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
//find the index of this uniform
@@ -386,7 +449,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
for (U32 i = 0; i < uniforms->size(); i++)
{
if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
- && ((*uniforms)[i] == name))
+ && ((*uniforms)[i].String() == name))
{
//found it
mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
@@ -396,7 +459,17 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms)
}
}
}
- }
+}
+
+void LLGLSLShader::addPermutation(std::string name, std::string value)
+{
+ mDefines[name] = value;
+}
+
+void LLGLSLShader::removePermutation(std::string name)
+{
+ mDefines[name].erase();
+}
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
@@ -410,13 +483,15 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
return -1;
}
-BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
+BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
{
BOOL res = TRUE;
+ mTotalUniformSize = 0;
mActiveTextureChannels = 0;
mUniform.clear();
mUniformMap.clear();
+ mUniformNameMap.clear();
mTexture.clear();
mValue.clear();
//initialize arrays
@@ -437,6 +512,7 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
unbind();
+ LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << llendl;
return res;
}
@@ -495,6 +571,58 @@ void LLGLSLShader::bindNoShader(void)
}
}
+S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return bindTexture(channel, texture, mode);
+}
+
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->bind(texture, mode);
+ }
+
+ return uniform;
+}
+
+S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return unbindTexture(channel);
+}
+
+S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->unbind(mode);
+ }
+
+ return uniform;
+}
+
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (uniform < 0 || uniform >= (S32)mTexture.size())
@@ -817,18 +945,18 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
}
}
-GLint LLGLSLShader::getUniformLocation(const string& uniform)
+GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
{
GLint ret = -1;
if (mProgramObject > 0)
{
- std::map::iterator iter = mUniformMap.find(uniform);
+ LLStaticStringTable::iterator iter = mUniformMap.find(uniform);
if (iter != mUniformMap.end())
{
if (gDebugGL)
{
stop_glerror();
- if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str()))
+ if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))
{
llerrs << "Uniform does not match." << llendl;
}
@@ -865,7 +993,7 @@ GLint LLGLSLShader::getAttribLocation(U32 attrib)
}
}
-void LLGLSLShader::uniform1i(const string& uniform, GLint v)
+void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
{
GLint location = getUniformLocation(uniform);
@@ -881,7 +1009,24 @@ void LLGLSLShader::uniform1i(const string& uniform, GLint v)
}
}
-void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
+void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map::iterator iter = mValue.find(location);
+ LLVector4 vec(i,j,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform2iARB(location, i, j);
+ mValue[location] = vec;
+ }
+ }
+}
+
+
+void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
{
GLint location = getUniformLocation(uniform);
@@ -897,7 +1042,7 @@ void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
}
}
-void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
+void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)
{
GLint location = getUniformLocation(uniform);
@@ -914,7 +1059,7 @@ void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
}
-void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z)
+void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)
{
GLint location = getUniformLocation(uniform);
@@ -930,23 +1075,7 @@ void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloa
}
}
-void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GLint location = getUniformLocation(uniform);
-
- if (location >= 0)
- {
- std::map::iterator iter = mValue.find(location);
- LLVector4 vec(x,y,z,w);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
- {
- glUniform4fARB(location, x,y,z,w);
- mValue[location] = vec;
- }
- }
-}
-
-void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v)
+void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@@ -962,7 +1091,7 @@ void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v
}
}
-void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v)
+void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@@ -978,7 +1107,7 @@ void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v
}
}
-void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v)
+void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@@ -994,7 +1123,7 @@ void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v
}
}
-void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v)
+void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@@ -1012,27 +1141,7 @@ void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v
}
}
-void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
-{
- GLint location = getUniformLocation(uniform);
-
- if (location >= 0)
- {
- glUniformMatrix2fvARB(location, count, transpose, v);
- }
-}
-
-void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
-{
- GLint location = getUniformLocation(uniform);
-
- if (location >= 0)
- {
- glUniformMatrix3fvARB(location, count, transpose, v);
- }
-}
-
-void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
+void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index a5817ce28..1f134a881 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -29,6 +29,7 @@
#include "llgl.h"
#include "llrender.h"
+#include "llstaticstringtable.h"
class LLShaderFeatures
{
@@ -68,6 +69,7 @@ public:
};
LLGLSLShader(S32 shader_class);
+ ~LLGLSLShader();
static GLhandleARB sCurBoundShader;
static LLGLSLShader* sCurBoundShaderPtr;
@@ -75,16 +77,16 @@ public:
static bool sNoFixedFunction;
void unload();
- BOOL createShader(std::vector * attributes,
- std::vector * uniforms,
+ BOOL createShader(std::vector * attributes,
+ std::vector * uniforms,
U32 varying_count = 0,
const char** varyings = NULL);
BOOL attachObject(std::string object);
void attachObject(GLhandleARB object);
void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
- BOOL mapAttributes(const std::vector * attributes);
- BOOL mapUniforms(const std::vector * uniforms);
- void mapUniform(GLint index, const std::vector * uniforms);
+ BOOL mapAttributes(const std::vector * attributes);
+ BOOL mapUniforms(const std::vector *);
+ void mapUniform(GLint index, const std::vector *);
void uniform1i(U32 index, GLint i);
void uniform1f(U32 index, GLfloat v);
void uniform2f(U32 index, GLfloat x, GLfloat y);
@@ -95,34 +97,35 @@ public:
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
void uniform4fv(U32 index, U32 count, const GLfloat* v);
- void uniform1i(const std::string& uniform, GLint i);
- void uniform1f(const std::string& uniform, GLfloat v);
- void uniform2f(const std::string& uniform, GLfloat x, GLfloat y);
- void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
- void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void uniform1iv(const std::string& uniform, U32 count, const GLint* i);
- void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v);
- void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v);
- void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v);
- void uniform4fv(const std::string& uniform, U32 count, const GLfloat* v);
+ void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix2fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniform1i(const LLStaticHashedString& uniform, GLint i);
+ void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
+ void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
+ void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
+ void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void setMinimumAlpha(F32 minimum);
void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(U32 index, GLfloat* v);
- GLint getUniformLocation(const std::string& uniform);
+ //GLint getUniformLocation(const std::string& uniform);
+ GLint getUniformLocation(const LLStaticHashedString& uniform);
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
+ void addPermutation(std::string name, std::string value);
+ void removePermutation(std::string name);
+
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
@@ -130,6 +133,13 @@ public:
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ // bindTexture returns the texture unit we've bound the texture to.
+ // You can reuse the return value to unbind a texture when required.
+ S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+
BOOL link(BOOL suppress_errors = FALSE);
void bind();
void unbind();
@@ -142,10 +152,13 @@ public:
GLhandleARB mProgramObject;
std::vector mAttribute; //lookup table of attribute enum to attribute channel
+ U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
std::vector mUniform; //lookup table of uniform enum to uniform location
- std::map mUniformMap; //lookup map of uniform name to uniform location
+ LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location
+ std::map mUniformNameMap; //lookup map of uniform location to uniform name
std::map mValue; //lookup map of uniform location to last known value
std::vector mTexture;
+ S32 mTotalUniformSize;
S32 mActiveTextureChannels;
S32 mShaderClass;
S32 mShaderLevel;
@@ -154,6 +167,7 @@ public:
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
+ std::map mDefines;
};
//UI shader (declared here so llui_libtest will link properly)
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 69c52d67b..ce95d9c69 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1099,6 +1099,26 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
intformat = GL_RGBA8;
}
+ if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
+ { //GL_LUMINANCE is deprecated, convert to GL_RGBA
+ use_scratch = true;
+ scratch = new U32[width*height];
+
+ U32 pixel_count = (U32) (width*height);
+ for (U32 i = 0; i < pixel_count; i++)
+ {
+ U8 lum = ((U8*) pixels)[i];
+
+ U8* pix = (U8*) &scratch[i];
+ pix[0] = pix[1] = pix[2] = lum;
+ pix[3] = 1.f;
+ }
+
+ pixformat = GL_RGBA;
+ intformat = GL_RGBA8;
+ }
+
+
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
use_scratch = true;
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index 494774117..2d1909600 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -51,6 +51,28 @@ extern LLGLSLShader gPostPosterizeProgram;
extern LLGLSLShader gPostMotionBlurProgram;
extern LLGLSLShader gPostVignetteProgram;
+static LLStaticHashedString sGamma("gamma");
+static LLStaticHashedString sBrightness("brightness");
+static LLStaticHashedString sContrast("contrast");
+static LLStaticHashedString sContrastBase("contrastBase");
+static LLStaticHashedString sSaturation("saturation");
+static LLStaticHashedString sBrightMult("brightMult");
+static LLStaticHashedString sNoiseStrength("noiseStrength");
+static LLStaticHashedString sLayerCount("layerCount");
+
+static LLStaticHashedString sVignetteStrength("vignette_strength");
+static LLStaticHashedString sVignettRadius("vignette_radius");
+static LLStaticHashedString sVignetteDarkness("vignette_darkness");
+static LLStaticHashedString sVignetteDesaturation("vignette_desaturation");
+static LLStaticHashedString sVignetteChromaticAberration("vignette_chromatic_aberration");
+static LLStaticHashedString sScreenRes("screen_res");
+
+static LLStaticHashedString sHorizontalPass("horizontalPass");
+
+static LLStaticHashedString sPrevProj("prev_proj");
+static LLStaticHashedString sInvProj("inv_proj");
+static LLStaticHashedString sBlurStrength("blur_strength");
+
static const unsigned int NOISE_SIZE = 512;
static const char * const XML_FILENAME = "postprocesseffects.xml";
@@ -155,16 +177,16 @@ public:
/*virtual*/ QuadType preDraw()
{
- getShader().uniform1f("gamma", mGamma);
- getShader().uniform1f("brightness", mBrightness);
- getShader().uniform1f("contrast", mContrast);
+ getShader().uniform1f(sGamma, mGamma);
+ getShader().uniform1f(sBrightness, mBrightness);
+ getShader().uniform1f(sContrast, mContrast);
float baseI = (mContrastBase.get()[VX] + mContrastBase.get()[VY] + mContrastBase.get()[VZ]) / 3.0f;
baseI = mContrastBase.get()[VW] / llmax(baseI,0.001f);
float baseR = mContrastBase.get()[VX] * baseI;
float baseG = mContrastBase.get()[VY] * baseI;
float baseB = mContrastBase.get()[VZ] * baseI;
- getShader().uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
- getShader().uniform1f("saturation", mSaturation);
+ getShader().uniform3fv(sContrastBase, 1, LLVector3(baseR, baseG, baseB).mV);
+ getShader().uniform1f(sSaturation, mSaturation);
return QUAD_NORMAL;
}
@@ -187,8 +209,8 @@ public:
{
LLPostProcess::getInstance()->bindNoise(1);
- getShader().uniform1f("brightMult", mBrightnessMult);
- getShader().uniform1f("noiseStrength", mNoiseStrength);
+ getShader().uniform1f(sBrightMult, mBrightnessMult);
+ getShader().uniform1f(sNoiseStrength, mNoiseStrength);
return QUAD_NOISE;
}
@@ -206,7 +228,7 @@ public:
}
/*virtual*/ QuadType preDraw()
{
- getShader().uniform1i("layerCount", mNumLayers);
+ getShader().uniform1i(sLayerCount, mNumLayers);
return QUAD_NORMAL;
}
};
@@ -232,12 +254,13 @@ public:
/*virtual*/ QuadType preDraw()
{
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
- getShader().uniform1f("vignette_strength", mStrength);
- getShader().uniform1f("vignette_radius", mRadius);
- getShader().uniform1f("vignette_darkness", mDarkness);
- getShader().uniform1f("vignette_desaturation", mDesaturation);
- getShader().uniform1f("vignette_chromatic_aberration", mChromaticAberration);
- getShader().uniform2fv("screen_res", 1, screen_rect.mV);
+
+ getShader().uniform1f(sVignetteStrength, mStrength);
+ getShader().uniform1f(sVignettRadius, mRadius);
+ getShader().uniform1f(sVignetteDarkness, mDarkness);
+ getShader().uniform1f(sVignetteDesaturation, mDesaturation);
+ getShader().uniform1f(sVignetteChromaticAberration, mChromaticAberration);
+ getShader().uniform2fv(sScreenRes, 1, screen_rect.mV);
return QUAD_NORMAL;
}
};
@@ -259,7 +282,7 @@ public:
/*virtual*/ S32 getDepthChannel() const { return -1; }
/*virtual*/ QuadType preDraw()
{
- mPassLoc = getShader().getUniformLocation("horizontalPass");
+ mPassLoc = getShader().getUniformLocation(sHorizontalPass);
return QUAD_NORMAL;
}
/*virtual*/ bool draw(U32 pass)
@@ -295,10 +318,10 @@ public:
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
- getShader().uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m);
- getShader().uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m);
- getShader().uniform2fv("screen_res", 1, screen_rect.mV);
- getShader().uniform1i("blur_strength", mStrength);
+ getShader().uniformMatrix4fv(sPrevProj, 1, GL_FALSE, prev_proj.m);
+ getShader().uniformMatrix4fv(sInvProj, 1, GL_FALSE, inv_proj.m);
+ getShader().uniform2fv(sScreenRes, 1, screen_rect.mV);
+ getShader().uniform1i(sBlurStrength, mStrength);
return QUAD_NORMAL;
}
@@ -312,7 +335,7 @@ public:
LLPostProcess::LLPostProcess(void) :
mVBO(NULL),
mDepthTexture(0),
- mNoiseTexture(NULL),
+ mNoiseTexture(0),
mScreenWidth(0),
mScreenHeight(0),
mNoiseTextureScale(0.f),
@@ -407,7 +430,10 @@ void LLPostProcess::createScreenTextures()
stop_glerror();
if(mDepthTexture)
+ {
LLImageGL::deleteTextures(1, &mDepthTexture);
+ mDepthTexture = 0;
+ }
for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it)
{
@@ -434,16 +460,25 @@ void LLPostProcess::createNoiseTexture()
}
}
- mNoiseTexture = new LLImageGL(FALSE) ;
- if(mNoiseTexture->createGLTexture())
+ if(mNoiseTexture)
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture->getTexName());
- LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RED, NOISE_SIZE, NOISE_SIZE, GL_RED, GL_UNSIGNED_BYTE, &buffer[0]);
- stop_glerror();
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
- stop_glerror();
+ LLImageGL::deleteTextures(1, &mNoiseTexture);
+ mNoiseTexture = 0;
}
+
+ LLImageGL::generateTextures(1, &mNoiseTexture);
+ stop_glerror();
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture);
+ stop_glerror();
+
+ if(gGLManager.mGLVersion >= 4.f)
+ LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_R8, NOISE_SIZE, NOISE_SIZE, GL_RED, GL_UNSIGNED_BYTE, &buffer[0], false);
+ else
+ LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE8, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0], false);
+ stop_glerror();
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+ stop_glerror();
}
void LLPostProcess::destroyGL()
@@ -453,7 +488,9 @@ void LLPostProcess::destroyGL()
if(mDepthTexture)
LLImageGL::deleteTextures(1, &mDepthTexture);
mDepthTexture=0;
- mNoiseTexture = NULL ;
+ if(mNoiseTexture)
+ LLImageGL::deleteTextures(1, &mNoiseTexture);
+ mNoiseTexture=0 ;
mVBO = NULL ;
}
@@ -467,6 +504,7 @@ void LLPostProcess::copyFrameBuffer()
{
mRenderTarget[!!mRenderTarget[0].getFBO()].bindTexture(0,0);
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight);
+ stop_glerror();
if(mDepthTexture)
{
@@ -476,6 +514,7 @@ void LLPostProcess::copyFrameBuffer()
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture);
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight);
+ stop_glerror();
break;
}
}
@@ -485,7 +524,7 @@ void LLPostProcess::copyFrameBuffer()
void LLPostProcess::bindNoise(U32 channel)
{
- gGL.getTexUnit(channel)->bind(mNoiseTexture);
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE,mNoiseTexture);
}
void LLPostProcess::renderEffects(unsigned int width, unsigned int height)
@@ -508,8 +547,7 @@ void LLPostProcess::doEffects(void)
{
LLVertexBuffer::unbind();
- mNoiseTextureScale = 0.001f + ((100.f - mSelectedEffectInfo["noise_size"].asFloat()) / 100.f);
- mNoiseTextureScale *= (mScreenHeight / NOISE_SIZE);
+ mNoiseTextureScale = (1.f - (mSelectedEffectInfo["noise_size"].asFloat() - 1.f) *(9.f/990.f)) / (float)NOISE_SIZE;
/// Copy the screen buffer to the render texture
copyFrameBuffer();
@@ -562,13 +600,19 @@ void LLPostProcess::applyShaders(void)
QuadType quad = (*it)->preDraw();
while((*it)->draw(pass++))
{
- mRenderTarget[!primary_rendertarget].bindTarget();
+ LLRenderTarget& write_target = mRenderTarget[!primary_rendertarget];
+ LLRenderTarget& read_target = mRenderTarget[mRenderTarget[0].getFBO() ? primary_rendertarget : !primary_rendertarget];
+ write_target.bindTarget();
if(color_channel >= 0)
- mRenderTarget[mRenderTarget[0].getFBO() ? primary_rendertarget : !primary_rendertarget].bindTexture(0,color_channel);
+ read_target.bindTexture(0,color_channel);
drawOrthoQuad(quad);
- mRenderTarget[!primary_rendertarget].flush();
+
+ if(color_channel >= 0 && !mRenderTarget[0].getFBO())
+ gGL.getTexUnit(color_channel)->unbind(read_target.getUsage());
+
+ write_target.flush();
if(mRenderTarget[0].getFBO())
primary_rendertarget = !primary_rendertarget;
}
@@ -593,8 +637,13 @@ void LLPostProcess::drawOrthoQuad(QuadType type)
LLStrider uv2;
mVBO->getTexCoord1Strider(uv2);
- float offs[2] = {(float) rand() / (float) RAND_MAX, (float) rand() / (float) RAND_MAX};
- float scale[2] = {mScreenWidth * mNoiseTextureScale / mScreenHeight, mNoiseTextureScale};
+ float offs[2] = {
+ llround(((float) rand() / (float) RAND_MAX) * (float)NOISE_SIZE)/float(NOISE_SIZE),
+ llround(((float) rand() / (float) RAND_MAX) * (float)NOISE_SIZE)/float(NOISE_SIZE) };
+ float scale[2] = {
+ (float)mScreenWidth * mNoiseTextureScale,
+ (float)mScreenHeight * mNoiseTextureScale };
+
uv2[0] = LLVector2(offs[0],offs[1]);
uv2[1] = LLVector2(offs[0],offs[1]+scale[1]);
uv2[2] = LLVector2(offs[0]+scale[0],offs[1]);
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
index 6c3da675e..57bd58ef0 100644
--- a/indra/llrender/llpostprocess.h
+++ b/indra/llrender/llpostprocess.h
@@ -90,7 +90,7 @@ private:
// However this is ONLY the case if fbos are actually supported, else swapping isn't needed.
LLRenderTarget mRenderTarget[2];
U32 mDepthTexture;
- LLPointer mNoiseTexture ;
+ U32 mNoiseTexture ;
U32 mScreenWidth;
U32 mScreenHeight;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index bbf70b9de..782562886 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1496,7 +1496,7 @@ void LLRender::translateUI(F32 x, F32 y, F32 z)
}
LLVector4a add(x,y,z);
- mUIOffset.back()->add(add);
+ mUIOffset.back().add(add);
}
void LLRender::scaleUI(F32 x, F32 y, F32 z)
@@ -1507,33 +1507,27 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z)
}
LLVector4a scale(x,y,z);
- mUIScale.back()->mul(scale);
+ mUIScale.back().mul(scale);
}
void LLRender::pushUIMatrix()
{
if (mUIOffset.empty())
{
- mUIOffset.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a))));
- mUIOffset.back()->splat(0.f);
+ mUIOffset.push_back(LLVector4a(0.f));
}
else
{
- const LLVector4a* last_entry = mUIOffset.back();
- mUIOffset.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a))));
- *mUIOffset.back() = *last_entry;
+ mUIOffset.push_back(mUIOffset.back());
}
if (mUIScale.empty())
{
- mUIScale.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a))));
- mUIScale.back()->splat(1.f);
+ mUIScale.push_back(LLVector4a(1.f));
}
else
{
- const LLVector4a* last_entry = mUIScale.back();
- mUIScale.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a))));
- *mUIScale.back() = *last_entry;
+ mUIScale.push_back(mUIScale.back());
}
}
@@ -1543,9 +1537,7 @@ void LLRender::popUIMatrix()
{
llerrs << "UI offset stack blown." << llendl;
}
- ll_aligned_free_16(mUIOffset.back());
mUIOffset.pop_back();
- ll_aligned_free_16(mUIScale.back());
mUIScale.pop_back();
}
@@ -1555,7 +1547,7 @@ LLVector3 LLRender::getUITranslation()
{
return LLVector3(0,0,0);
}
- return LLVector3(mUIOffset.back()->getF32ptr());
+ return LLVector3(mUIOffset.back().getF32ptr());
}
LLVector3 LLRender::getUIScale()
@@ -1564,7 +1556,7 @@ LLVector3 LLRender::getUIScale()
{
return LLVector3(1,1,1);
}
- return LLVector3(mUIScale.back()->getF32ptr());
+ return LLVector3(mUIScale.back().getF32ptr());
}
@@ -1574,8 +1566,8 @@ void LLRender::loadUIIdentity()
{
llerrs << "Need to push UI translation frame before clearing offset." << llendl;
}
- mUIOffset.back()->splat(0.f);
- mUIScale.back()->splat(1.f);
+ mUIOffset.back().splat(0.f);
+ mUIScale.back().splat(1.f);
}
void LLRender::setColorMask(bool writeColor, bool writeAlpha)
@@ -1977,8 +1969,8 @@ void LLRender::vertex4a(const LLVector4a& vertex)
else
{
//LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
- mVerticesp[mCount].setAdd(vertex,*mUIOffset.back());
- mVerticesp[mCount].mul(*mUIScale.back());
+ mVerticesp[mCount].setAdd(vertex,mUIOffset.back());
+ mVerticesp[mCount].mul(mUIScale.back());
}
if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile)
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index d8f01a75a..2ca28c669 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -38,6 +38,7 @@
#include "v3math.h"
#include "v4coloru.h"
#include "v4math.h"
+#include "llalignedarray.h"
#include "llstrider.h"
#include "llpointer.h"
#include "llglheaders.h"
@@ -466,9 +467,8 @@ private:
F32 mMaxAnisotropy;
- std::vector mUIOffset;
- std::vector mUIScale;
-
+ LLAlignedArray mUIOffset;
+ LLAlignedArray mUIScale;
};
extern F32 gGLModelView[16];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 20a7999ce..6e47a9acd 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -72,7 +72,7 @@ LLRenderTarget::~LLRenderTarget()
release();
}
-void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)
+void LLRenderTarget::resize(U32 resx, U32 resy)
{
//for accounting, get the number of pixels added/subtracted
S32 pix_diff = (resx*resy)-(mResX*mResY);
@@ -80,10 +80,12 @@ void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)
mResX = resx;
mResY = resy;
+ llassert(mInternalFormat.size() == mTex.size());
+
for (U32 i = 0; i < mTex.size(); ++i)
{ //resize color attachments
gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
sBytesAllocated += pix_diff*4;
}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index f2401eed4..a0f409334 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -79,7 +79,7 @@ public:
// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
// DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
- void resize(U32 resx, U32 resy, U32 color_fmt);
+ void resize(U32 resx, U32 resy);
//provide this render target with a multisample resource.
void setSampleBuffer(LLMultisampleBuffer* buffer);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 23ef0c989..5fa601124 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -528,7 +528,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines, S32 texture_index_channels)
{
std::pair::iterator, std::multimap::iterator> range;
range = mShaderObjects.equal_range(filename);
@@ -683,12 +683,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if(SHPackDeferredNormals)
text[count++] = strdup("#define PACK_NORMALS\n");
- //copy preprocessor definitions into buffer
- for (std::map::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
+ if(defines)
+ {
+ for (std::map::iterator iter = defines->begin(); iter != defines->end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
text[count++] = (GLcharARB *) strdup(define.c_str());
}
+ }
if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
{
@@ -938,7 +940,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
- return loadShaderFile(filename,shader_level,type,texture_index_channels);
+ return loadShaderFile(filename,shader_level,type, defines, texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}
@@ -1058,7 +1060,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_matrix1");
mReservedUniforms.push_back("texture_matrix2");
mReservedUniforms.push_back("texture_matrix3");
- llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_MATRIX3+1);
+ mReservedUniforms.push_back("object_plane_s");
+ mReservedUniforms.push_back("object_plane_t");
+ llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);
mReservedUniforms.push_back("viewport");
@@ -1199,7 +1203,47 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("lightMap");
mReservedUniforms.push_back("bloomMap");
mReservedUniforms.push_back("projectionMap");
+ mReservedUniforms.push_back("norm_mat");
+ mReservedUniforms.push_back("matrixPalette");
+
+ mReservedUniforms.push_back("screenTex");
+ mReservedUniforms.push_back("screenDepth");
+ mReservedUniforms.push_back("refTex");
+ mReservedUniforms.push_back("eyeVec");
+ mReservedUniforms.push_back("time");
+ mReservedUniforms.push_back("d1");
+ mReservedUniforms.push_back("d2");
+ mReservedUniforms.push_back("lightDir");
+ mReservedUniforms.push_back("specular");
+ mReservedUniforms.push_back("lightExp");
+ mReservedUniforms.push_back("waterFogColor");
+ mReservedUniforms.push_back("waterFogDensity");
+ mReservedUniforms.push_back("waterFogKS");
+ mReservedUniforms.push_back("refScale");
+ mReservedUniforms.push_back("waterHeight");
+ mReservedUniforms.push_back("waterPlane");
+ mReservedUniforms.push_back("normScale");
+ mReservedUniforms.push_back("fresnelScale");
+ mReservedUniforms.push_back("fresnelOffset");
+ mReservedUniforms.push_back("blurMultiplier");
+ mReservedUniforms.push_back("sunAngle");
+ mReservedUniforms.push_back("scaledAngle");
+ mReservedUniforms.push_back("sunAngle2");
+
+ mReservedUniforms.push_back("camPosLocal");
+
+ mReservedUniforms.push_back("gWindDir");
+ mReservedUniforms.push_back("gSinWaveParams");
+ mReservedUniforms.push_back("gGravity");
+
+ mReservedUniforms.push_back("detail_0");
+ mReservedUniforms.push_back("detail_1");
+ mReservedUniforms.push_back("detail_2");
+ mReservedUniforms.push_back("detail_3");
+ mReservedUniforms.push_back("alpha_ramp");
+
+ mReservedUniforms.push_back("origin");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
std::set dupe_check;
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 7e30e75f0..6d4582ec3 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -47,6 +47,8 @@ public:
TEXTURE_MATRIX1,
TEXTURE_MATRIX2,
TEXTURE_MATRIX3,
+ OBJECT_PLANE_S,
+ OBJECT_PLANE_T,
VIEWPORT,
LIGHT_POSITION,
LIGHT_DIRECTION,
@@ -164,6 +166,45 @@ public:
DEFERRED_LIGHT,
DEFERRED_BLOOM,
DEFERRED_PROJECTION,
+ DEFERRED_NORM_MATRIX,
+
+ AVATAR_MATRIX,
+ WATER_SCREENTEX,
+ WATER_SCREENDEPTH,
+ WATER_REFTEX,
+ WATER_EYEVEC,
+ WATER_TIME,
+ WATER_WAVE_DIR1,
+ WATER_WAVE_DIR2,
+ WATER_LIGHT_DIR,
+ WATER_SPECULAR,
+ WATER_SPECULAR_EXP,
+ WATER_FOGCOLOR,
+ WATER_FOGDENSITY,
+ WATER_FOGKS,
+ WATER_REFSCALE,
+ WATER_WATERHEIGHT,
+ WATER_WATERPLANE,
+ WATER_NORM_SCALE,
+ WATER_FRESNEL_SCALE,
+ WATER_FRESNEL_OFFSET,
+ WATER_BLUR_MULTIPLIER,
+ WATER_SUN_ANGLE,
+ WATER_SCALED_ANGLE,
+ WATER_SUN_ANGLE2,
+
+ WL_CAMPOSLOCAL,
+
+ AVATAR_WIND,
+ AVATAR_SINWAVE,
+ AVATAR_GRAVITY,
+
+ TERRAIN_DETAIL0,
+ TERRAIN_DETAIL1,
+ TERRAIN_DETAIL2,
+ TERRAIN_DETAIL3,
+ TERRAIN_ALPHARAMP,
+ SHINY_ORIGIN,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
@@ -176,7 +217,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 5710585fd..219b0dfec 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -207,9 +207,6 @@ public:
void setImageFlash(LLPointer image);
void setImagePressed(LLPointer image);
- void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
- BOOL getCommitOnReturn() const { return mCommitOnReturn; }
-
static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
void setHelpURLCallback(const std::string &help_url);
const std::string& getHelpURL() const { return mHelpURL; }
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 7817fd0d5..e5242f7db 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -366,6 +366,20 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* f
}
}
+bool LLFocusMgr::keyboardFocusHasAccelerators() const
+{
+ LLView* focus_view = dynamic_cast(mKeyboardFocus);
+ while(focus_view)
+ {
+ if (focus_view->hasAccelerators())
+ {
+ return true;
+ }
+
+ focus_view = focus_view->getParent();
+ }
+ return false;
+}
void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
{
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 5f1466f5d..7e5e50dfb 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -121,6 +121,7 @@ public:
void unlockFocus();
BOOL focusLocked() const { return mLockedView != NULL; }
+ bool keyboardFocusHasAccelerators() const;
struct Impl;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index c501d865c..7761f5eb8 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -626,12 +626,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask)
{
// the menu items are in the child list in bottom up order
LLView* prev_menu_item = parent_menu->findNextSibling(this);
- return prev_menu_item ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
+ return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
LLView* next_menu_item = parent_menu->findPrevSibling(this);
- return next_menu_item ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE;
+ return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE;
}
}
@@ -641,12 +641,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask)
if (y > getRect().getHeight() / 2)
{
LLView* prev_menu_item = parent_menu->findNextSibling(this);
- return prev_menu_item ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
+ return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
LLView* next_menu_item = parent_menu->findPrevSibling(this);
- return next_menu_item ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE;
+ return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE;
}
}
@@ -4630,10 +4630,13 @@ BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
}
else
{
- //highlight first enabled one
- if(pMenu->highlightNextItem(NULL))
+ if (key == KEY_UP || key == KEY_DOWN) // Singu Note: Only highlight if the user actually meant to navigate through the menu
{
- handled = true;
+ //highlight first enabled one
+ if (pMenu->highlightNextItem(NULL))
+ {
+ handled = true;
+ }
}
}
}
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index 07b811f71..1db97fe7c 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -187,7 +187,8 @@ BOOL LLMultiFloater::closeAllFloaters()
//Tab did not actually close, possibly due to a pending Save Confirmation dialog..
//so try and close the next one in the list...
tabToClose++;
- }else
+ }
+ else
{
//Tab closed ok.
lastTabCount = mTabContainer->getTabCount();
@@ -252,7 +253,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
else if (floaterp->getHost())
{
// floaterp is hosted by somebody else and
- // this is adding it, so remove it from it's old host
+ // this is adding it, so remove it from its old host
floaterp->getHost()->removeFloater(floaterp);
}
else if (floaterp->getParent() == gFloaterView)
@@ -302,8 +303,21 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
{
floaterp->setVisible(FALSE);
}
+
+ // Tabs sometimes overlap resize handle
+ moveResizeHandlesToFront();
}
+void LLMultiFloater::updateFloaterTitle(LLFloater* floaterp)
+{
+ S32 index = mTabContainer->getIndexForPanel(floaterp);
+ if (index != -1)
+ {
+ mTabContainer->setPanelTitle(index, floaterp->getShortTitle());
+ }
+}
+
+
/**
BOOL selectFloater(LLFloater* floaterp)
@@ -329,8 +343,9 @@ void LLMultiFloater::selectPrevFloater()
mTabContainer->selectPrevTab();
}
-void LLMultiFloater::showFloater(LLFloater* floaterp)
+void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point)
{
+ if(!floaterp) return;
// we won't select a panel that already is selected
// it is hard to do this internally to tab container
// as tab selection is handled via index and the tab at a given
@@ -338,7 +353,7 @@ void LLMultiFloater::showFloater(LLFloater* floaterp)
if (floaterp != mTabContainer->getCurrentPanel() &&
!mTabContainer->selectTabPanel(floaterp))
{
- addFloater(floaterp, TRUE);
+ addFloater(floaterp, TRUE, insertion_point);
}
}
@@ -417,6 +432,13 @@ BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
if (floater && floater->canClose() && floater->isCloseable())
{
floater->close();
+
+ // EXT-5695 (Tabbed IM window loses focus if close any tabs by Ctrl+W)
+ // bring back focus on tab container if there are any tab left
+ if(mTabContainer->getTabCount() > 0)
+ {
+ mTabContainer->setFocus(TRUE);
+ }
}
return TRUE;
}
@@ -468,12 +490,17 @@ void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
void LLMultiFloater::onTabSelected()
{
- tabOpen((LLFloater*)mTabContainer->getCurrentPanel());
+ LLFloater* floaterp = dynamic_cast(mTabContainer->getCurrentPanel());
+ if (floaterp)
+ {
+ tabOpen(floaterp);
+ }
}
void LLMultiFloater::setCanResize(BOOL can_resize)
{
LLFloater::setCanResize(can_resize);
+ if (!mTabContainer) return;
if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
@@ -510,16 +537,9 @@ void LLMultiFloater::updateResizeLimits()
// initialize minimum size constraint to the original xml values.
S32 new_min_width = mOrigMinWidth;
S32 new_min_height = mOrigMinHeight;
- // possibly increase minimum size constraint due to children's minimums.
- for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
- {
- LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
- if (floaterp)
- {
- new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
- new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
- }
- }
+
+ computeResizeLimits(new_min_width, new_min_height);
+
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = getRect().getHeight();
@@ -545,3 +565,17 @@ void LLMultiFloater::updateResizeLimits()
gFloaterView->adjustToFitScreen(this, TRUE);
}
}
+
+void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height)
+{
+ // possibly increase minimum size constraint due to children's minimums.
+ for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
+ {
+ LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
+ if (floaterp)
+ {
+ new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
+ new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
+ }
+ }
+}
diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h
index e56b387bc..b18ff292a 100644
--- a/indra/llui/llmultifloater.h
+++ b/indra/llui/llmultifloater.h
@@ -56,7 +56,7 @@ public:
virtual void growToFit(S32 content_width, S32 content_height);
virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
- virtual void showFloater(LLFloater* floaterp);
+ virtual void showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
virtual void removeFloater(LLFloater* floaterp);
virtual void tabOpen(LLFloater* opened_floater);
@@ -76,6 +76,7 @@ public:
void onTabSelected();
virtual void updateResizeLimits();
+ virtual void updateFloaterTitle(LLFloater* floaterp);
protected:
struct LLFloaterData
@@ -94,6 +95,9 @@ protected:
LLTabContainer::TabPosition mTabPos;
BOOL mAutoResize;
S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
+
+private:
+ virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height);
};
#endif // LL_MULTI_FLOATER_H
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index d9e1c7e94..c6ff2fa03 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -159,8 +159,12 @@ void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
void LLPanel::removeBorder()
{
- delete mBorder;
- mBorder = NULL;
+ if (mBorder)
+ {
+ removeChild(mBorder);
+ delete mBorder;
+ mBorder = NULL;
+ }
}
@@ -277,7 +281,7 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
// handle user hitting ESC to defocus
if (key == KEY_ESCAPE && mask == MASK_NONE)
{
- gFocusMgr.setKeyboardFocus(NULL);
+ setFocus(FALSE);
return TRUE;
}
else if( (mask == MASK_SHIFT) && (KEY_TAB == key))
@@ -304,29 +308,25 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
}
}
}
-
- // If we have a default button, click it when
- // return is pressed, unless current focus is a return-capturing button
- // in which case *that* button will handle the return key
- LLButton* focused_button = dynamic_cast(cur_focus);
- if (cur_focus && !(focused_button && focused_button->getCommitOnReturn()))
+
+ // If RETURN was pressed and something has focus, call onCommit()
+ if (!handled && cur_focus && key == KEY_RETURN && mask == MASK_NONE)
{
- // RETURN key means hit default button in this case
- if (key == KEY_RETURN && mask == MASK_NONE
- && mDefaultBtn != NULL
- && mDefaultBtn->getVisible()
- && mDefaultBtn->getEnabled())
+ if (cur_focus->getCommitOnReturn())
{
+ // current focus is a return-capturing element,
+ // let *that* element handle the return key
+ handled = FALSE;
+ }
+ else if (mDefaultBtn && mDefaultBtn->getVisible() && mDefaultBtn->getEnabled())
+ {
+ // If we have a default button, click it when return is pressed
mDefaultBtn->onCommit();
handled = TRUE;
}
- }
-
- if (key == KEY_RETURN && mask == MASK_NONE)
- {
- // set keyboard focus to self to trigger commitOnFocusLost behavior on current ctrl
- if (cur_focus && cur_focus->acceptsTextInput())
+ else if (cur_focus->acceptsTextInput())
{
+ // call onCommit for text input handling control
cur_focus->onCommit();
handled = TRUE;
}
@@ -363,34 +363,16 @@ void LLPanel::handleVisibilityChange ( BOOL new_visibility )
void LLPanel::setFocus(BOOL b)
{
- if( b )
+ if( b && !hasFocus())
{
- if (!gFocusMgr.childHasKeyboardFocus(this))
- {
- //refresh();
- if (!focusFirstItem())
- {
- LLUICtrl::setFocus(TRUE);
- }
- onFocusReceived();
- }
+ // give ourselves focus preemptively, to avoid infinite loop
+ LLUICtrl::setFocus(TRUE);
+ // then try to pass to first valid child
+ focusFirstItem();
}
else
{
- if( this == gFocusMgr.getKeyboardFocus() )
- {
- gFocusMgr.setKeyboardFocus( NULL );
- }
- else
- {
- //RN: why is this here?
- LLView::ctrl_list_t ctrls = getCtrlList();
- for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
- {
- LLUICtrl* ctrl = *ctrl_it;
- ctrl->setFocus( FALSE );
- }
- }
+ LLUICtrl::setFocus(b);
}
}
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index b70737c27..56bac0e92 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -56,7 +56,8 @@ LLUICtrl::LLUICtrl() :
mDoubleClickSignal(NULL),
mTentative(FALSE),
mTabStop(TRUE),
- mIsChrome(FALSE)
+ mIsChrome(FALSE),
+ mCommitOnReturn(FALSE)
{
}
@@ -78,7 +79,8 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque
mDoubleClickSignal(NULL),
mTentative( FALSE ),
mTabStop( TRUE ),
- mIsChrome(FALSE)
+ mIsChrome(FALSE),
+ mCommitOnReturn(FALSE)
{
if(commit_callback)
setCommitCallback(commit_callback);
@@ -178,6 +180,13 @@ BOOL LLUICtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
return handled;
}
+// can't tab to children of a non-tab-stop widget
+BOOL LLUICtrl::canFocusChildren() const
+{
+ return TRUE;//hasTabStop();
+}
+
+
void LLUICtrl::onCommit()
{
if (mCommitSignal)
@@ -528,7 +537,8 @@ BOOL LLUICtrl::focusNextItem(BOOL text_fields_only)
{
// this assumes that this method is called on the focus root.
LLCtrlQuery query = getTabOrderQuery();
- if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
+ static LLUICachedControl tab_to_text_fields_only ("TabToTextFieldsOnly", false);
+ if(text_fields_only || tab_to_text_fields_only)
{
query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
}
@@ -540,7 +550,8 @@ BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only)
{
// this assumes that this method is called on the focus root.
LLCtrlQuery query = getTabOrderQuery();
- if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
+ static LLUICachedControl tab_to_text_fields_only ("TabToTextFieldsOnly", false);
+ if(text_fields_only || tab_to_text_fields_only)
{
query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
}
@@ -552,7 +563,7 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot()
{
LLUICtrl* focus_root = NULL;
LLUICtrl* next_view = this;
- while(next_view)
+ while(next_view/* && next_view->hasTabStop()*/)
{
if (next_view->isFocusRoot())
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index b7ebc5bcc..ba6acc98e 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -70,6 +70,7 @@ public:
/*virtual*/ BOOL isCtrl() const;
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL canFocusChildren() const;
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
@@ -132,6 +133,9 @@ public:
LLUICtrl* getParentUICtrl() const;
+ void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
+ BOOL getCommitOnReturn() const { return mCommitOnReturn; }
+
//Start using these!
boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );
boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb );
@@ -198,6 +202,8 @@ private:
BOOL mIsChrome;
BOOL mTentative;
+ bool mCommitOnReturn;
+
class DefaultTabGroupFirstSorter;
};
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 6d2ae643a..12c6ef34d 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1377,7 +1377,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft;
S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom;
viewp->translate( delta_x, delta_y );
- viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight())
+ {
+ viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ }
}
}
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index b009bab41..cc7ce21eb 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -357,6 +357,11 @@ public:
BOOL focusNextRoot();
BOOL focusPrevRoot();
+ // Normally we want the app menus to get priority on accelerated keys
+ // However, sometimes we want to give specific views a first chance
+ // at handling them. (eg. the script editor)
+ virtual bool hasAccelerators() const { return false; }
+
virtual void deleteAllChildren();
virtual void setTentative(BOOL b);
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index a93c833ba..c3a042247 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -363,7 +363,11 @@ std::string LLDir::buildSLOSCacheDir() const
}
else
{
+#if defined(_WIN64)
+ res = add(getOSCacheDir(), "SingularityViewer64");
+#else
res = add(getOSCacheDir(), "SingularityViewer");
+#endif
}
return res;
}
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 78f54a7a4..807c547bd 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -749,7 +749,7 @@ void LLWindowWin32::close()
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
// Don't process events in our mainWindowProc any longer.
- SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL);
// Make sure we don't leave a blank toolbar button.
ShowWindow(mWindowHandle, SW_HIDE);
@@ -1660,7 +1660,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
}
- SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this);
// register this window as handling drag/drop events from the OS
DragAcceptFiles( mWindowHandle, TRUE );
@@ -1983,7 +1983,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// This helps prevent avatar walking after maximizing the window by double-clicking the title bar.
static bool sHandleLeftMouseUp = true;
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr(h_wnd, GWLP_USERDATA);
if (NULL != window_imp)
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index d7dbce179..0ebcc899f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -47,6 +47,8 @@ include(LLAppearance)
if (WINDOWS)
include(CopyWinLibs)
+ set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP)
+ include(InstallRequiredSystemLibraries)
endif (WINDOWS)
include_directories(
@@ -1437,11 +1439,7 @@ set(PACKAGE ${PACKAGE_DEFAULT} CACHE BOOL
"Add a package target that builds an installer package.")
if (WINDOWS)
- if(MSVC10)
- set(release_flags "/MAPRelease/${VIEWER_BINARY_NAME}.map")
- else(MSVC10)
- set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map")
- endif(MSVC10)
+ set(release_flags "/MAPRelease/${VIEWER_BINARY_NAME}.map")
if (FMOD)
if(MANIFEST_LIBRARIES)
@@ -1451,12 +1449,18 @@ if (WINDOWS)
endif(MANIFEST_LIBRARIES)
endif (FMOD)
if (FMODEX)
+ if (WORD_SIZE EQUAL 32)
+ set(fmodex_dll_file "fmodex.dll")
+ else (WORD_SIZE EQUAL 32)
+ set(fmodex_dll_file "fmodex64.dll")
+ endif (WORD_SIZE EQUAL 32)
+
if(MANIFEST_LIBRARIES)
- set(MANIFEST_LIBRARIES "${MANIFEST_LIBRARIES}|${FMODEX_BINARY_DIR}/fmodex.dll")
+ set(MANIFEST_LIBRARIES "${MANIFEST_LIBRARIES}|${FMODEX_BINARY_DIR}/${fmodex_dll_file}")
else(MANIFEST_LIBRARIES)
- set(MANIFEST_LIBRARIES "--extra_libraries=${FMODEX_BINARY_DIR}/fmodex.dll")
+ set(MANIFEST_LIBRARIES "--extra_libraries=${FMODEX_BINARY_DIR}/${fmodex_dll_file}")
endif(MANIFEST_LIBRARIES)
- set(EXTRA_LINKER_FLAGS "/DELAYLOAD:fmodex.dll")
+ set(EXTRA_LINKER_FLAGS "/DELAYLOAD:${fmodex_dll_file}")
endif (FMODEX)
set_target_properties(${VIEWER_BINARY_NAME}
@@ -1514,6 +1518,7 @@ if (WINDOWS)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--branding_id=${VIEWER_BRANDING_ID}
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -1535,6 +1540,7 @@ if (WINDOWS)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--actions=copy
--branding_id=${VIEWER_BRANDING_ID}
@@ -1855,6 +1861,21 @@ endif (LL_TESTS)
# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py
if (WINDOWS)
+ IF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
+ FOREACH(RUNTIME_LIB ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
+ add_custom_command(
+ TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ copy_if_different
+ ${RUNTIME_LIB}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Copying ${RUNTIME_LIB} to the runtime folder."
+ )
+ ENDFOREACH(RUNTIME_LIB ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
+ ENDIF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
+
get_target_property(BUILT_LLCOMMON llcommon LOCATION)
set_target_properties(llcommon
@@ -1910,7 +1931,7 @@ if (WINDOWS)
COMMENT "Copying Quicktime Plugin to the runtime folder."
)
- get_target_property(BUILT_FILEPICKER_PLUGIN basic_plugin_filepicker LOCATION)
+ get_target_property(BUILT_FILEPICKER_PLUGIN basic_plugin_filepicker LOCATION)
add_custom_command(
TARGET ${VIEWER_BINARY_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND}
@@ -1922,7 +1943,9 @@ if (WINDOWS)
COMMENT "Copying filepicker Plugin to the runtime folder."
)
- get_target_property(BUILT_WINMM_SHIM_PLUGIN winmm_shim LOCATION)
+# winmm doesn't build on windows 64
+ if(WORD_SIZE EQUAL 32)
+ get_target_property(BUILT_WINMM_SHIM_PLUGIN winmm_shim LOCATION)
add_custom_command(
TARGET ${VIEWER_BINARY_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND}
@@ -1933,6 +1956,8 @@ if (WINDOWS)
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
COMMENT "Copying winmm.dll to the runtime folder."
)
+ endif(WORD_SIZE EQUAL 32)
+
# Copying the mime_types.xml file to app_settings
set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us")
set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings")
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c1f005aba..c3f3f2aa8 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -210,17 +210,6 @@
100
- zmm_deffov
-
zmm_mlfov
- zmm_isinml
-
- zmm_rightmousedown
-
AllowLargeSounds
+ LiruMouselookMenu
+
LiruNewARCLimit
+ windows64
+
SDL
@@ -126,6 +133,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/apr_suite-1.4.2-windows-20110504.tar.bz2
+ windows64
+
ares
@@ -166,6 +180,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/ares-1.7.1-windows-20110504.tar.bz2
+ windows64
+
boost
@@ -206,6 +227,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/boost-1.52.0-windows-20130221.tar.bz2
+ windows64
+
colladadom
@@ -246,6 +274,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/colladadom-2.2-windows-20131006.tar.bz2
+ windows64
+
curl
@@ -286,6 +321,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/curl-7.21.1-windows-20110504.tar.bz2
+ windows64
+
db
@@ -400,6 +442,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/expat-2.0.1-windows-20110215.tar.bz2
+ windows64
+
fontconfig
@@ -441,6 +490,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/freeglut-2.6.0-windows-20110214.tar.bz2
+ windows64
+
freetype
@@ -481,6 +537,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/freetype-2.4.4-windows-20110218.tar.bz2
+ windows64
+
glext
@@ -496,21 +559,28 @@
linux
linux64
windows
+ windows64
+
@@ -560,6 +630,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/glui-2.36-windows-20110214.tar.bz2
+ windows64
+
google_breakpad
@@ -596,6 +673,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/google_breakpad-0.0.0-rev1099-windows-20131002.tar.bz2
+ windows64
+
gperftools
@@ -710,6 +794,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/hunspell-windows-20120704.tar.bz2
+ windows64
+
jpeglib
@@ -750,6 +841,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/jpeglib-8c-windows-20120704.tar.bz2
+ windows64
+
jsoncpp
@@ -790,6 +888,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/jsoncpp-0.5.0-windows-20120704.tar.bz2
+ windows64
+
libpng
@@ -830,6 +935,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/libpng-1.5.2-windows-20120704.tar.bz2
+ windows64
+
libuuid
@@ -914,6 +1026,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/llqtwebkit-4.7.1-windows-20120228.tar.bz2
+ windows64
+
mesa
@@ -980,6 +1099,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/libndofdev-windows-20120704.tar.bz2
+ windows64
+
ogg-vorbis
@@ -1020,6 +1146,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/ogg_vorbis-1.2.2-1.3.2-windows-20110510.tar.bz2
+ windows64
+
openSSL
@@ -1056,6 +1189,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/openssl-1.0.0g-windows-20120207.tar.bz2
+ windows64
+
openal-soft
@@ -1089,6 +1229,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/openal-1.12.854-1.1.0-windows-20110301.tar.bz2
+ windows64
+
pcre
@@ -1205,6 +1352,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/vivox-2.1.3010.6270-windows-20090309.tar.bz2
+ windows64
+
xmlrpc-epi
@@ -1245,6 +1399,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/xmlrpc_epi-0.54.1-windows-20120704.tar.bz2
+ windows64
+
zlib
@@ -1285,6 +1446,13 @@
url
https://bitbucket.org/SingularityViewer/libraries/downloads/zlib-1.2.5-windows-20120704.tar.bz2
+ windows64
+
diff --git a/scripts/repackage.sh b/scripts/repackage.sh
index 6865ca08f..59e71173f 100755
--- a/scripts/repackage.sh
+++ b/scripts/repackage.sh
@@ -5,7 +5,7 @@ usage() {
echo "Usage: repackage PLATFORM FILEIN.tar.bz2 [FILEOUT.tar.bz2]
Repackage an archive from llautobuild format into singularity format
-PLATFORM can be one of windows, linux, linux64, mac.
+PLATFORM can be one of windows, windows64 linux, linux64, mac.
"
exit 0
}
@@ -30,6 +30,13 @@ case "$1" in
INCPATH="libraries/i686-win32/include"
BINPATH="libraries/i686-win32/bin"
;;
+ --windows64|-w64|windows64|win64)
+ MODE=windows64
+ LIBPATH="libraries/x86_64-win/lib/release"
+ LIBDPATH="libraries/x86_64-win/lib/debug"
+ INCPATH="libraries/x86_64-win/include"
+ BINPATH="libraries/x86_64-win/bin"
+ ;;
--mac|--osx|--darwin|-x|mac|osx|darwin)
MODE=osx
LIBPATH="libraries/universal-darwin/lib/release"
@@ -82,7 +89,7 @@ case "$FILEIN" in
http\:\/\/*|https\:\/\/*)
echo " Downloading..."
cd "$TMP"
- wget "$FILEIN" -O package.tar.bz2
+ curl -L "$FILEIN" > package.tar.bz2
echo " Unpacking..."
tar -xjvf package.tar.bz2
rm package.tar.bz2