From e1212c54cbc5931030aefba4132d67e07db49f0f Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 15 Jul 2016 09:06:13 -0700
Subject: [PATCH 01/26] Updated to deal with streaming out of both buffers

So gotta keep track of when finished streaming to network and
locally separately.  That means the State needed to be more of a
bitflag and less of an enum.
---
 libraries/audio-client/src/AudioClient.cpp |   1 -
 libraries/audio/src/AudioInjector.cpp      | 105 ++++++++++++++-------
 libraries/audio/src/AudioInjector.h        |  34 +++++--
 3 files changed, 95 insertions(+), 45 deletions(-)

diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp
index dd72125d93..bec30edb4e 100644
--- a/libraries/audio-client/src/AudioClient.cpp
+++ b/libraries/audio-client/src/AudioClient.cpp
@@ -954,7 +954,6 @@ void AudioClient::processReceivedSamples(const QByteArray& decodedBuffer, QByteA
     if (hasReverb) {
         assert(_outputFormat.channelCount() == 2);
         updateReverbOptions();
-        qDebug() << "handling reverb";
         _listenerReverb.render(outputSamples, outputSamples, numDeviceOutputSamples/2);
     }
 }
diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index 08143b8491..f94890ea7d 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -28,6 +28,15 @@
 
 int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
 
+AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs) {
+    return static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
+};
+
+AudioInjectorState& operator&= (AudioInjectorState& lhs, AudioInjectorState rhs) {
+    lhs = static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
+    return lhs;
+};
+
 AudioInjector::AudioInjector(QObject* parent) :
     QObject(parent)
 {
@@ -56,10 +65,26 @@ void AudioInjector::setOptions(const AudioInjectorOptions& options) {
     _options.stereo = currentlyStereo;
 }
 
+void AudioInjector::finishNetworkInjection() {
+    _state &= AudioInjectorState::NetworkInjectionFinished;
+    
+    // if we are already finished with local
+    // injection, then we are finished
+    if((_state & AudioInjectorState::LocalInjectionFinished) == AudioInjectorState::LocalInjectionFinished) {
+        finish();
+    }
+}
+
+void AudioInjector::finishLocalInjection() {
+    _state &= AudioInjectorState::LocalInjectionFinished;
+    if(_options.localOnly || ((_state & AudioInjectorState::NetworkInjectionFinished) == AudioInjectorState::NetworkInjectionFinished)) {
+        finish();
+    }
+}
 
 void AudioInjector::finish() {
-    bool shouldDelete = (_state == State::NotFinishedWithPendingDelete);
-    _state = State::Finished;
+    bool shouldDelete = ((_state & AudioInjectorState::PendingDelete) == AudioInjectorState::PendingDelete);
+    _state &= AudioInjectorState::Finished;
 
     emit finished();
 
@@ -121,23 +146,31 @@ void AudioInjector::restart() {
     _hasSentFirstFrame = false;
 
     // check our state to decide if we need extra handling for the restart request
-    if (_state == State::Finished) {
+    if ((_state & AudioInjectorState::Finished) == AudioInjectorState::Finished) {
         // we finished playing, need to reset state so we can get going again
         _hasSetup = false;
         _shouldStop = false;
-        _state = State::NotFinished;
+        _state = AudioInjectorState::NotFinished;
         
         // call inject audio to start injection over again
         setupInjection();
 
-        // if we're a local injector, just inject again 
-        if (_options.localOnly) {
-            injectLocally();
-        } else {
-            // wake the AudioInjectorManager back up if it's stuck waiting
-            if (!injectorManager->restartFinishedInjector(this)) {
-                _state = State::Finished; // we're not playing, so reset the state used by isPlaying.
+        // inject locally
+        if(injectLocally()) {
+        
+            // if not localOnly, wake the AudioInjectorManager back up if it is stuck waiting
+            if (!_options.localOnly) {
+
+                if (!injectorManager->restartFinishedInjector(this)) {
+                    // TODO: this logic seems to remove the pending delete,
+                    // which makes me wonder about the deleteLater calls
+                    _state = AudioInjectorState::Finished; // we're not playing, so reset the state used by isPlaying.
+                }
             }
+        } else {
+            // TODO: this logic seems to remove the pending delete,
+            // which makes me wonder about the deleteLater calls
+            _state = AudioInjectorState::Finished; // we failed to play, so we are finished again
         }
     }
 }
@@ -183,7 +216,7 @@ static const int64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = -1;
 static const int64_t NEXT_FRAME_DELTA_IMMEDIATELY = 0;
 
 int64_t AudioInjector::injectNextFrame() {
-    if (_state == AudioInjector::State::Finished) {
+    if ((_state & AudioInjectorState::NetworkInjectionFinished) == AudioInjectorState::NetworkInjectionFinished) {
         qDebug() << "AudioInjector::injectNextFrame called but AudioInjector has finished and was not restarted. Returning.";
         return NEXT_FRAME_DELTA_ERROR_OR_FINISHED;
     }
@@ -234,8 +267,10 @@ int64_t AudioInjector::injectNextFrame() {
             // pack the stereo/mono type of the stream
             audioPacketStream << _options.stereo;
 
-            // pack the flag for loopback
-            uchar loopbackFlag = (uchar)true;
+            // pack the flag for loopback.  Now, we don't loopback
+            // and _always_ play locally, so loopbackFlag should be 
+            // false always.
+            uchar loopbackFlag = (uchar)false;
             audioPacketStream << loopbackFlag;
 
             // pack the position for injected audio
@@ -333,7 +368,7 @@ int64_t AudioInjector::injectNextFrame() {
     }
 
     if (_currentSendOffset >= _audioData.size() && !_options.loop) {
-        finish();
+        finishNetworkInjection();
         return NEXT_FRAME_DELTA_ERROR_OR_FINISHED;
     }
 
@@ -372,10 +407,10 @@ void AudioInjector::triggerDeleteAfterFinish() {
         return;
     }
 
-    if (_state == State::Finished) {
+    if (_state == AudioInjectorState::Finished) {
         stopAndDeleteLater();
     } else {
-        _state = State::NotFinishedWithPendingDelete;
+        _state &= AudioInjectorState::PendingDelete;
     }
 }
 
@@ -421,7 +456,7 @@ AudioInjector* AudioInjector::playSoundAndDelete(const QByteArray& buffer, const
     AudioInjector* sound = playSound(buffer, options, localInterface);
 
     if (sound) {
-        sound->_state = AudioInjector::State::NotFinishedWithPendingDelete;
+        sound->_state &= AudioInjectorState::PendingDelete;
     }
 
     return sound;
@@ -438,21 +473,23 @@ AudioInjector* AudioInjector::playSound(const QByteArray& buffer, const AudioInj
     // setup parameters required for injection
     injector->setupInjection();
 
-    if (options.localOnly) {
-        if (injector->injectLocally()) {
-            // local injection succeeded, return the pointer to injector
-            return injector;
-        } else {
-            // unable to inject locally, return a nullptr
-            return nullptr;
-        }
-    } else {
-        // attempt to thread the new injector
-        if (injectorManager->threadInjector(injector)) {
-            return injector;
-        } else {
-            // we failed to thread the new injector (we are at the max number of injector threads)
-            return nullptr;
-        }
+    // we always inject locally
+    //
+    if (!injector->injectLocally()) {
+        // failed, so don't bother sending to server
+        qDebug() << "AudioInjector::playSound failed to inject locally";
+        return nullptr;
     }
+    // if localOnly, we are done, just return injector.
+    if (options.localOnly) {
+        return injector;
+    }
+
+    // send off to server for everyone else
+    if (!injectorManager->threadInjector(injector)) {
+        // we failed to thread the new injector (we are at the max number of injector threads)
+        qDebug() << "AudioInjector::playSound failed to thread injector";
+    }
+    return injector;
+
 }
diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h
index 1af733ace6..e13fc15c26 100644
--- a/libraries/audio/src/AudioInjector.h
+++ b/libraries/audio/src/AudioInjector.h
@@ -32,24 +32,35 @@
 class AbstractAudioInterface;
 class AudioInjectorManager;
 
+
+enum class AudioInjectorState : uint8_t {
+    NotFinished = 1,
+    Finished = 2,
+    PendingDelete = 4,
+    LocalInjectionFinished = 8,
+    NetworkInjectionFinished = 16
+};
+
+AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs);
+AudioInjectorState& operator&= (AudioInjectorState& lhs, AudioInjectorState rhs);
+
 // In order to make scripting cleaner for the AudioInjector, the script now holds on to the AudioInjector object
 // until it dies. 
-
 class AudioInjector : public QObject {
     Q_OBJECT
     
 public:
-    enum class State : uint8_t {
-        NotFinished,
-        NotFinishedWithPendingDelete,
-        Finished
-    };
-    
+    static const uint8_t NotFinished = 1;
+    static const uint8_t Finished = 2;
+    static const uint8_t PendingDelete = 4;
+    static const uint8_t LocalInjectionFinished = 8;
+    static const uint8_t NetworkInjectionFinished = 16;
+
     AudioInjector(QObject* parent);
     AudioInjector(const Sound& sound, const AudioInjectorOptions& injectorOptions);
     AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions);
     
-    bool isFinished() const { return _state == State::Finished; }
+    bool isFinished() const { return (_state & AudioInjectorState::Finished) == AudioInjectorState::Finished; }
     
     int getCurrentSendOffset() const { return _currentSendOffset; }
     void setCurrentSendOffset(int currentSendOffset) { _currentSendOffset = currentSendOffset; }
@@ -78,8 +89,10 @@ public slots:
     void setOptions(const AudioInjectorOptions& options);
     
     float getLoudness() const { return _loudness; }
-    bool isPlaying() const { return _state == State::NotFinished || _state == State::NotFinishedWithPendingDelete; }
+    bool isPlaying() const { return (_state & AudioInjectorState::NotFinished) == AudioInjectorState::NotFinished; }
     void finish();
+    void finishLocalInjection();
+    void finishNetworkInjection();
     
 signals:
     void finished();
@@ -92,7 +105,7 @@ private:
     
     QByteArray _audioData;
     AudioInjectorOptions _options;
-    State _state { State::NotFinished };
+    AudioInjectorState _state { AudioInjectorState::NotFinished };
     bool _hasSentFirstFrame { false };
     bool _hasSetup { false };
     bool _shouldStop { false };
@@ -111,4 +124,5 @@ private:
     friend class AudioInjectorManager;
 };
 
+    
 #endif // hifi_AudioInjector_h

From f0db7b9d39e5b2da679515aa3fe0a3c471d0055a Mon Sep 17 00:00:00 2001
From: Leonardo Murillo <leonardo@devops.cr>
Date: Fri, 15 Jul 2016 11:42:30 -0600
Subject: [PATCH 02/26] Checkpoint

---
 cmake/externals/hifiAudioCodec/CMakeLists.txt  | 8 +++-----
 cmake/macros/SetupHifiClientServerPlugin.cmake | 4 ++--
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt
index 3a8c714d79..642a58b685 100644
--- a/cmake/externals/hifiAudioCodec/CMakeLists.txt
+++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt
@@ -1,13 +1,13 @@
 include(ExternalProject)
 include(SelectLibraryConfigurations)
 
-set(EXTERNAL_NAME HiFiAudioCodec)
+set(EXTERNAL_NAME hifiAudioCodec)
 
 string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
 
 ExternalProject_Add(
   ${EXTERNAL_NAME}
-  URL https://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
+  URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
   URL_MD5 23ec3fe51eaa155ea159a4971856fc13
   CONFIGURE_COMMAND ""
   BUILD_COMMAND ""
@@ -27,7 +27,5 @@ if (WIN32)
 elseif(APPLE)
   set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
 elseif(NOT ANDROID)
-  # FIXME need to account for different architectures 
-  #set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux64/audio.so CACHE TYPE INTERNAL)
+  set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux64/audio.so CACHE TYPE INTERNAL)
 endif()
-
diff --git a/cmake/macros/SetupHifiClientServerPlugin.cmake b/cmake/macros/SetupHifiClientServerPlugin.cmake
index 8ba38a09c3..74ceaeb0ab 100644
--- a/cmake/macros/SetupHifiClientServerPlugin.cmake
+++ b/cmake/macros/SetupHifiClientServerPlugin.cmake
@@ -37,7 +37,7 @@ macro(SETUP_HIFI_CLIENT_SERVER_PLUGIN)
         ${CLIENT_PLUGIN_FULL_PATH}
     )
     # copy the client plugin binaries
-    add_custom_command(TARGET ${DIR} POST_BUILD
+    add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
         COMMAND "${CMAKE_COMMAND}" -E copy
         "$<TARGET_FILE:${TARGET_NAME}>"
         ${CLIENT_PLUGIN_FULL_PATH}
@@ -50,7 +50,7 @@ macro(SETUP_HIFI_CLIENT_SERVER_PLUGIN)
         ${SERVER_PLUGIN_FULL_PATH}
     )
     # copy the server plugin binaries
-    add_custom_command(TARGET ${DIR} POST_BUILD
+    add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
         COMMAND "${CMAKE_COMMAND}" -E copy
         "$<TARGET_FILE:${TARGET_NAME}>"
         ${SERVER_PLUGIN_FULL_PATH}

From 53d524eb2fe40668424aac9feb1a0d0c1cb01e15 Mon Sep 17 00:00:00 2001
From: Leonardo Murillo <leo@highfidelity.io>
Date: Fri, 15 Jul 2016 12:04:45 -0600
Subject: [PATCH 03/26] Checkpoint

---
 cmake/externals/hifiAudioCodec/CMakeLists.txt  |  2 +-
 .../macros/AddDependencyExternalProjects.cmake |  5 ++++-
 plugins/hifiCodec/CMakeLists.txt               | 18 +++++++-----------
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt
index 642a58b685..8a1b07253a 100644
--- a/cmake/externals/hifiAudioCodec/CMakeLists.txt
+++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt
@@ -23,7 +23,7 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
 set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
 
 if (WIN32)
-    set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
+  set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
 elseif(APPLE)
   set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
 elseif(NOT ANDROID)
diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake
index e35ca98959..3cbb961308 100644
--- a/cmake/macros/AddDependencyExternalProjects.cmake
+++ b/cmake/macros/AddDependencyExternalProjects.cmake
@@ -17,10 +17,12 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
     
     # has the user told us they specific don't want this as an external project?
     if (NOT USE_LOCAL_${_PROJ_NAME_UPPER})
+      message(STATUS "LEODEBUG: Looking for dependency ${_PROJ_NAME}")
       # have we already detected we can't have this as external project on this OS?
       if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT)
         # have we already setup the target?
         if (NOT TARGET ${_PROJ_NAME})
+          message(STATUS "LEODEBUG: We dont have a target with that name ${_PROJ_NAME} adding directory ${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME}")
           add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME})
           
           # did we end up adding an external project target?
@@ -35,6 +37,7 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
         endif ()
       
         if (TARGET ${_PROJ_NAME})
+          message(STATUS "LEODEBUG: We no have the target ${_PROJ_NAME}")
           add_dependencies(${TARGET_NAME} ${_PROJ_NAME})
         endif ()
         
@@ -43,4 +46,4 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
     
   endforeach()
 
-endmacro()
\ No newline at end of file
+endmacro()
diff --git a/plugins/hifiCodec/CMakeLists.txt b/plugins/hifiCodec/CMakeLists.txt
index 0af7e42ea1..b278e839e4 100644
--- a/plugins/hifiCodec/CMakeLists.txt
+++ b/plugins/hifiCodec/CMakeLists.txt
@@ -6,15 +6,11 @@
 #  See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
 #
 
-if (WIN32 OR APPLE)
-    set(TARGET_NAME hifiCodec)
-    setup_hifi_client_server_plugin()
-
-    link_hifi_libraries(audio shared plugins)
-
-    add_dependency_external_projects(HiFiAudioCodec)
-    target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
-    target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
-    install_beside_console()
-endif()
+set(TARGET_NAME hifiCodec)
+setup_hifi_client_server_plugin()
+link_hifi_libraries(audio shared plugins)
+add_dependency_external_projects(hifiAudioCodec)
+target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
+target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
+install_beside_console()
 

From b0c27a53e2b2d7c2dc0434484bb217638d1e4a50 Mon Sep 17 00:00:00 2001
From: Leonardo Murillo <leo@highfidelity.io>
Date: Fri, 15 Jul 2016 13:01:21 -0600
Subject: [PATCH 04/26] Linking to Linux only SDK

---
 cmake/externals/hifiAudioCodec/CMakeLists.txt | 32 +++++++++++++------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt
index 8a1b07253a..87b5044b42 100644
--- a/cmake/externals/hifiAudioCodec/CMakeLists.txt
+++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt
@@ -5,15 +5,27 @@ set(EXTERNAL_NAME hifiAudioCodec)
 
 string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
 
-ExternalProject_Add(
-  ${EXTERNAL_NAME}
-  URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
-  URL_MD5 23ec3fe51eaa155ea159a4971856fc13
-  CONFIGURE_COMMAND ""
-  BUILD_COMMAND ""
-  INSTALL_COMMAND ""
-  LOG_DOWNLOAD 1
-)
+if (WIN32 OR APPLE)
+  ExternalProject_Add(
+    ${EXTERNAL_NAME}
+    URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
+    URL_MD5 23ec3fe51eaa155ea159a4971856fc13
+    CONFIGURE_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    LOG_DOWNLOAD 1
+  )
+elseif(NOT ANDROID)
+  ExternalProject_Add(
+    ${EXTERNAL_NAME}
+    URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux.zip
+    URL_MD5 7d37914a18aa4de971d2f45dd3043bde
+    CONFIGURE_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    LOG_DOWNLOAD 1
+  )
+endif()
 
 # Hide this external target (for ide users)
 set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
@@ -27,5 +39,5 @@ if (WIN32)
 elseif(APPLE)
   set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
 elseif(NOT ANDROID)
-  set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux64/audio.so CACHE TYPE INTERNAL)
+  set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
 endif()

From ce67d57279209593daa18c033c1e601450273f0f Mon Sep 17 00:00:00 2001
From: Leonardo Murillo <leo@highfidelity.io>
Date: Fri, 15 Jul 2016 13:03:40 -0600
Subject: [PATCH 05/26] Removing Debugs

---
 cmake/macros/AddDependencyExternalProjects.cmake | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake
index 3cbb961308..99b8317fd7 100644
--- a/cmake/macros/AddDependencyExternalProjects.cmake
+++ b/cmake/macros/AddDependencyExternalProjects.cmake
@@ -17,12 +17,10 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
     
     # has the user told us they specific don't want this as an external project?
     if (NOT USE_LOCAL_${_PROJ_NAME_UPPER})
-      message(STATUS "LEODEBUG: Looking for dependency ${_PROJ_NAME}")
       # have we already detected we can't have this as external project on this OS?
       if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT)
         # have we already setup the target?
         if (NOT TARGET ${_PROJ_NAME})
-          message(STATUS "LEODEBUG: We dont have a target with that name ${_PROJ_NAME} adding directory ${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME}")
           add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME})
           
           # did we end up adding an external project target?
@@ -37,7 +35,6 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
         endif ()
       
         if (TARGET ${_PROJ_NAME})
-          message(STATUS "LEODEBUG: We no have the target ${_PROJ_NAME}")
           add_dependencies(${TARGET_NAME} ${_PROJ_NAME})
         endif ()
         

From 8df4ed01d92b26411f1d7c2e7e565792aa411dc3 Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 15 Jul 2016 16:22:41 -0700
Subject: [PATCH 06/26] fixed typo

which oddly I was sure I already did.  Seems I didn't push it?  OK
now it is pushed.
---
 libraries/audio/src/AudioInjector.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index f94890ea7d..0b0be9353b 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -29,7 +29,7 @@
 int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
 
 AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs) {
-    return static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
+    return static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
 };
 
 AudioInjectorState& operator&= (AudioInjectorState& lhs, AudioInjectorState rhs) {

From fb99828e30302f2c615e74926dbe62a647def972 Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 15 Jul 2016 17:09:27 -0700
Subject: [PATCH 07/26] PR feedback

Code a bit more readable.  Sadly (and I guess it makes sense), a
enum class XXX is not a class, so you cannot have member functions
for it.  I can imagine no way to have a vtable if you are really
representing it as a uint8_t or whatever.  So, I put a stateHas
function in the AudioInjector instead.  Definite improvement.
---
 libraries/audio/src/AudioInjector.cpp | 15 +++++++++------
 libraries/audio/src/AudioInjector.h   |  5 +++--
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index 0b0be9353b..e992e3c541 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -57,6 +57,10 @@ AudioInjector::AudioInjector(const QByteArray& audioData, const AudioInjectorOpt
 
 }
 
+bool AudioInjector::stateHas(AudioInjectorState state) const {
+    return (_state & state) == state;
+}
+
 void AudioInjector::setOptions(const AudioInjectorOptions& options) {
     // since options.stereo is computed from the audio stream, 
     // we need to copy it from existing options just in case.
@@ -70,20 +74,19 @@ void AudioInjector::finishNetworkInjection() {
     
     // if we are already finished with local
     // injection, then we are finished
-    if((_state & AudioInjectorState::LocalInjectionFinished) == AudioInjectorState::LocalInjectionFinished) {
+    if(stateHas(AudioInjectorState::LocalInjectionFinished)) {
         finish();
     }
 }
 
 void AudioInjector::finishLocalInjection() {
     _state &= AudioInjectorState::LocalInjectionFinished;
-    if(_options.localOnly || ((_state & AudioInjectorState::NetworkInjectionFinished) == AudioInjectorState::NetworkInjectionFinished)) {
+    if(_options.localOnly || stateHas(AudioInjectorState::NetworkInjectionFinished)) {
         finish();
     }
 }
 
 void AudioInjector::finish() {
-    bool shouldDelete = ((_state & AudioInjectorState::PendingDelete) == AudioInjectorState::PendingDelete);
     _state &= AudioInjectorState::Finished;
 
     emit finished();
@@ -94,7 +97,7 @@ void AudioInjector::finish() {
         _localBuffer = NULL;
     }
 
-    if (shouldDelete) {
+    if (stateHas(AudioInjectorState::PendingDelete)) {
         // we've been asked to delete after finishing, trigger a deleteLater here
         deleteLater();
     }
@@ -146,7 +149,7 @@ void AudioInjector::restart() {
     _hasSentFirstFrame = false;
 
     // check our state to decide if we need extra handling for the restart request
-    if ((_state & AudioInjectorState::Finished) == AudioInjectorState::Finished) {
+    if (stateHas(AudioInjectorState::Finished)) {
         // we finished playing, need to reset state so we can get going again
         _hasSetup = false;
         _shouldStop = false;
@@ -216,7 +219,7 @@ static const int64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = -1;
 static const int64_t NEXT_FRAME_DELTA_IMMEDIATELY = 0;
 
 int64_t AudioInjector::injectNextFrame() {
-    if ((_state & AudioInjectorState::NetworkInjectionFinished) == AudioInjectorState::NetworkInjectionFinished) {
+    if (stateHas(AudioInjectorState::NetworkInjectionFinished)) {
         qDebug() << "AudioInjector::injectNextFrame called but AudioInjector has finished and was not restarted. Returning.";
         return NEXT_FRAME_DELTA_ERROR_OR_FINISHED;
     }
diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h
index e13fc15c26..ce0c88247e 100644
--- a/libraries/audio/src/AudioInjector.h
+++ b/libraries/audio/src/AudioInjector.h
@@ -60,7 +60,7 @@ public:
     AudioInjector(const Sound& sound, const AudioInjectorOptions& injectorOptions);
     AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions);
     
-    bool isFinished() const { return (_state & AudioInjectorState::Finished) == AudioInjectorState::Finished; }
+    bool isFinished() const { return (stateHas(AudioInjectorState::Finished)); }
     
     int getCurrentSendOffset() const { return _currentSendOffset; }
     void setCurrentSendOffset(int currentSendOffset) { _currentSendOffset = currentSendOffset; }
@@ -74,6 +74,7 @@ public:
     bool isStereo() const { return _options.stereo; }
     void setLocalAudioInterface(AbstractAudioInterface* localAudioInterface) { _localAudioInterface = localAudioInterface; }
 
+    bool stateHas(AudioInjectorState state) const ;
     static AudioInjector* playSoundAndDelete(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface);
     static AudioInjector* playSound(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface);
     static AudioInjector* playSound(SharedSoundPointer sound, const float volume, const float stretchFactor, const glm::vec3 position);
@@ -89,7 +90,7 @@ public slots:
     void setOptions(const AudioInjectorOptions& options);
     
     float getLoudness() const { return _loudness; }
-    bool isPlaying() const { return (_state & AudioInjectorState::NotFinished) == AudioInjectorState::NotFinished; }
+    bool isPlaying() const { return stateHas(AudioInjectorState::NotFinished); }
     void finish();
     void finishLocalInjection();
     void finishNetworkInjection();

From 8c0eb1e4d27f4d925317a09fedf7632138f9172e Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 15 Jul 2016 19:48:15 -0700
Subject: [PATCH 08/26] Fixed some bad logic

When I "fixed" my or instead of and issue, I did it in the wrong
direction.  But it looked right :)  Now it is.  Sigh.  Long story
how it got there, but it seems good now.
---
 libraries/audio/src/AudioInjector.cpp | 14 +++++++-------
 libraries/audio/src/AudioInjector.h   |  2 +-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index e992e3c541..9c49ce66d8 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -32,8 +32,8 @@ AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs) {
     return static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
 };
 
-AudioInjectorState& operator&= (AudioInjectorState& lhs, AudioInjectorState rhs) {
-    lhs = static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
+AudioInjectorState& operator|= (AudioInjectorState& lhs, AudioInjectorState rhs) {
+    lhs = static_cast<AudioInjectorState>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
     return lhs;
 };
 
@@ -70,7 +70,7 @@ void AudioInjector::setOptions(const AudioInjectorOptions& options) {
 }
 
 void AudioInjector::finishNetworkInjection() {
-    _state &= AudioInjectorState::NetworkInjectionFinished;
+    _state |= AudioInjectorState::NetworkInjectionFinished;
     
     // if we are already finished with local
     // injection, then we are finished
@@ -80,14 +80,14 @@ void AudioInjector::finishNetworkInjection() {
 }
 
 void AudioInjector::finishLocalInjection() {
-    _state &= AudioInjectorState::LocalInjectionFinished;
+    _state |= AudioInjectorState::LocalInjectionFinished;
     if(_options.localOnly || stateHas(AudioInjectorState::NetworkInjectionFinished)) {
         finish();
     }
 }
 
 void AudioInjector::finish() {
-    _state &= AudioInjectorState::Finished;
+    _state |= AudioInjectorState::Finished;
 
     emit finished();
 
@@ -413,7 +413,7 @@ void AudioInjector::triggerDeleteAfterFinish() {
     if (_state == AudioInjectorState::Finished) {
         stopAndDeleteLater();
     } else {
-        _state &= AudioInjectorState::PendingDelete;
+        _state |= AudioInjectorState::PendingDelete;
     }
 }
 
@@ -459,7 +459,7 @@ AudioInjector* AudioInjector::playSoundAndDelete(const QByteArray& buffer, const
     AudioInjector* sound = playSound(buffer, options, localInterface);
 
     if (sound) {
-        sound->_state &= AudioInjectorState::PendingDelete;
+        sound->_state |= AudioInjectorState::PendingDelete;
     }
 
     return sound;
diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h
index ce0c88247e..9bdfcacb5c 100644
--- a/libraries/audio/src/AudioInjector.h
+++ b/libraries/audio/src/AudioInjector.h
@@ -42,7 +42,7 @@ enum class AudioInjectorState : uint8_t {
 };
 
 AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs);
-AudioInjectorState& operator&= (AudioInjectorState& lhs, AudioInjectorState rhs);
+AudioInjectorState& operator|= (AudioInjectorState& lhs, AudioInjectorState rhs);
 
 // In order to make scripting cleaner for the AudioInjector, the script now holds on to the AudioInjector object
 // until it dies. 

From 4b2fb546eb1615ad68200d441c556594e56f9644 Mon Sep 17 00:00:00 2001
From: Anthony Thibault <ajt@hyperlogic.org>
Date: Sat, 16 Jul 2016 12:21:08 -0700
Subject: [PATCH 09/26] Re-enable storing of attach points in user settings

* bug fix, use localOffset property of grabbed entity, which is dynamically updated as
  the near grab action moves the entity.
---
 .../system/controllers/handControllerGrab.js    | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index 66c9e10795..36b0725f45 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -271,8 +271,7 @@ function propsArePhysical(props) {
     return isPhysical;
 }
 
-// currently disabled.
-var USE_ATTACH_POINT_SETTINGS = false;
+var USE_ATTACH_POINT_SETTINGS = true;
 
 var ATTACH_POINT_SETTINGS = "io.highfidelity.attachPoints";
 function getAttachPointSettings() {
@@ -2091,16 +2090,10 @@ function MyController(hand) {
     this.holdExit = function () {
         // store the offset attach points into preferences.
         if (USE_ATTACH_POINT_SETTINGS && this.grabbedHotspot && this.grabbedEntity) {
-            entityPropertiesCache.addEntity(this.grabbedEntity);
-            var props = entityPropertiesCache.getProps(this.grabbedEntity);
-            var entityXform = new Xform(props.rotation, props.position);
-            var avatarXform = new Xform(MyAvatar.orientation, MyAvatar.position);
-            var handRot = (this.hand === RIGHT_HAND) ? MyAvatar.getRightPalmRotation() : MyAvatar.getLeftPalmRotation();
-            var avatarHandPos = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition;
-            var palmXform = new Xform(handRot, avatarXform.xformPoint(avatarHandPos));
-            var offsetXform = Xform.mul(palmXform.inv(), entityXform);
-
-            storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, offsetXform.pos, offsetXform.rot);
+            var props = Entities.getEntityProperties(this.grabbedEntity, ["localPosition", "localRotation"]);
+            if (props && props.localPosition && props.localRotation) {
+                storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, props.localPosition, props.localRotation);
+            }
         }
     };
 

From c7c804623166b5ed64a96103053bf8d5271c4e83 Mon Sep 17 00:00:00 2001
From: Anthony Thibault <ajt@hyperlogic.org>
Date: Sat, 16 Jul 2016 14:58:21 -0700
Subject: [PATCH 10/26] De-equip goes into a near grab instead of dropping the
 object.

---
 .../system/controllers/handControllerGrab.js  | 35 +++++++++++--------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index 36b0725f45..f622bf9217 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -228,7 +228,7 @@ function colorPow(color, power) {
     return {
         red: Math.pow(color.red / 255.0, power) * 255,
         green: Math.pow(color.green / 255.0, power) * 255,
-        blue: Math.pow(color.blue / 255.0, power) * 255,
+        blue: Math.pow(color.blue / 255.0, power) * 255
     };
 }
 
@@ -764,9 +764,8 @@ function MyController(hand) {
         }
     };
 
-    var SEARCH_SPHERE_ALPHA = 0.5;
     this.searchSphereOn = function (location, size, color) {
-        
+
         var rotation = Quat.lookAt(location, Camera.getPosition(), Vec3.UP);
         var brightColor = colorPow(color, 0.06);
         if (this.searchSphere === null) {
@@ -789,7 +788,7 @@ function MyController(hand) {
                 position: location,
                 rotation: rotation,
                 innerColor: brightColor,
-                outerColor: color,  
+                outerColor: color,
                 innerAlpha: 1.0,
                 outerAlpha: 0.0,
                 outerRadius: size * 1.2,
@@ -1960,12 +1959,12 @@ function MyController(hand) {
         this.currentObjectRotation = grabbedProperties.rotation;
         this.currentVelocity = ZERO_VEC;
         this.currentAngularVelocity = ZERO_VEC;
+
+        this.prevDropDetected = false;
     };
 
     this.nearGrabbing = function (deltaTime, timestamp) {
 
-        var dropDetected = this.dropGestureProcess(deltaTime);
-
         if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
             this.callEntityMethodOnGrabbed("releaseGrab");
             this.setState(STATE_OFF, "trigger released");
@@ -1974,6 +1973,16 @@ function MyController(hand) {
 
         if (this.state == STATE_HOLD) {
 
+            var dropDetected = this.dropGestureProcess(deltaTime);
+
+            if (this.triggerSmoothedReleased()) {
+                this.waitForTriggerRelease = false;
+            }
+
+            if (dropDetected && this.prevDropDetected != dropDetected) {
+                this.waitForTriggerRelease = true;
+            }
+
             // highlight the grabbed hotspot when the dropGesture is detected.
             if (dropDetected) {
                 entityPropertiesCache.addEntity(this.grabbedHotspot.entityID);
@@ -1981,17 +1990,15 @@ function MyController(hand) {
                 equipHotspotBuddy.highlightHotspot(this.grabbedHotspot);
             }
 
-            if (dropDetected && this.triggerSmoothedGrab()) {
+            if (dropDetected && !this.waitForTriggerRelease && this.triggerSmoothedGrab()) {
                 this.callEntityMethodOnGrabbed("releaseEquip");
-                this.setState(STATE_OFF, "drop gesture detected");
-                return;
-            }
-
-            if (this.thumbPressed()) {
-                this.callEntityMethodOnGrabbed("releaseEquip");
-                this.setState(STATE_OFF, "drop via thumb press");
+                var grabbedEntity = this.grabbedEntity;
+                this.release();
+                this.grabbedEntity = grabbedEntity;
+                this.setState(STATE_NEAR_GRABBING, "drop gesture detected");
                 return;
             }
+            this.prevDropDetected = dropDetected;
         }
 
         this.heartBeat(this.grabbedEntity);

From 0f240d39b61905313bd76127752d393cf65b6ff4 Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Mon, 18 Jul 2016 11:21:09 -0700
Subject: [PATCH 11/26] Actually delete textures we're not using

---
 libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp
index ed931437b7..74428b53f5 100644
--- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp
+++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp
@@ -187,7 +187,11 @@ GLTexture::~GLTexture() {
         }
     }
 
-    Backend::decrementTextureGPUCount();
+    if (_id) {
+        glDeleteTextures(1, &_id);
+        const_cast<GLuint&>(_id) = 0;
+        Backend::decrementTextureGPUCount();
+    }
     Backend::updateTextureGPUMemoryUsage(_size, 0);
     Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0);
 }

From 3df373252f8cbe7ae7e227e5bd545a7472085886 Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Mon, 18 Jul 2016 14:00:41 -0700
Subject: [PATCH 12/26] Several minor things

We could only partially fill the _scratchBuffer - .wav files may not
be exactly N frames long.  Doh.

While at it, I needed to call finishLocalInjection() after local
injectors are done, and the access to the injector vector needs to
be locked, given that we do a QtDirectConnection with the networking
and thus the outputLocalInjectors is on a different thread.

The clicking was just 0-ing out the _scratchBuffer.
---
 libraries/audio-client/src/AudioClient.cpp | 9 +++++++--
 libraries/audio-client/src/AudioClient.h   | 5 +++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp
index b5a7c8c0cf..7cf8574529 100644
--- a/libraries/audio-client/src/AudioClient.cpp
+++ b/libraries/audio-client/src/AudioClient.cpp
@@ -862,6 +862,9 @@ void AudioClient::mixLocalAudioInjectors(int16_t* inputBuffer) {
     static const float INT16_TO_FLOAT_SCALE_FACTOR = 1/32768.0f;
 
     bool injectorsHaveData = false;
+    
+    // lock the injector vector
+    Lock lock(_injectorsMutex);
 
     for (AudioInjector* injector : getActiveLocalAudioInjectors()) {
         if (injector->getLocalBuffer()) {
@@ -871,6 +874,7 @@ void AudioClient::mixLocalAudioInjectors(int16_t* inputBuffer) {
                 AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
 
             // get one frame from the injector (mono or stereo)
+            memset(_scratchBuffer, 0, sizeof(_scratchBuffer));
             if (0 < injector->getLocalBuffer()->readData((char*)_scratchBuffer, samplesToRead)) {
                 
                 injectorsHaveData = true;
@@ -894,14 +898,14 @@ void AudioClient::mixLocalAudioInjectors(int16_t* inputBuffer) {
             } else {
                 
                 qDebug() << "injector has no more data, marking finished for removal";
-                injector->finish();
+                injector->finishLocalInjection();
                 injectorsToRemove.append(injector);
             }
 
         } else {
             
             qDebug() << "injector has no local buffer, marking as finished for removal";
-            injector->finish();
+            injector->finishLocalInjection();
             injectorsToRemove.append(injector);
         }
     }
@@ -1003,6 +1007,7 @@ void AudioClient::setIsStereoInput(bool isStereoInput) {
 
 
 bool AudioClient::outputLocalInjector(bool isStereo, AudioInjector* injector) {
+    Lock lock(_injectorsMutex);
     if (injector->getLocalBuffer() && _audioInput ) {
         // just add it to the vector of active local injectors, if 
         // not already there.
diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h
index 3e4aa931a6..472092163b 100644
--- a/libraries/audio-client/src/AudioClient.h
+++ b/libraries/audio-client/src/AudioClient.h
@@ -15,6 +15,7 @@
 #include <fstream>
 #include <memory>
 #include <vector>
+#include <mutex>
 
 #include <QtCore/qsystemdetection.h>
 #include <QtCore/QByteArray>
@@ -83,6 +84,9 @@ public:
     using AudioPositionGetter = std::function<glm::vec3()>;
     using AudioOrientationGetter = std::function<glm::quat()>;
 
+    using Mutex = std::mutex;
+    using Lock = std::unique_lock<Mutex>;
+    
     class AudioOutputIODevice : public QIODevice {
     public:
         AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream, AudioClient* audio) :
@@ -219,6 +223,7 @@ private:
     float azimuthForSource(const glm::vec3& relativePosition);
     float gainForSource(float distance, float volume);
 
+    Mutex _injectorsMutex;
     QByteArray firstInputFrame;
     QAudioInput* _audioInput;
     QAudioFormat _desiredInputFormat;

From 659e1ff9845b80a9b0da64019adc77ff8015dc95 Mon Sep 17 00:00:00 2001
From: "Anthony J. Thibault" <tony@highfidelity.io>
Date: Mon, 18 Jul 2016 14:17:06 -0700
Subject: [PATCH 13/26] remove debug prints

---
 scripts/system/controllers/handControllerGrab.js | 2 --
 1 file changed, 2 deletions(-)

diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index f622bf9217..43152f763f 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -277,7 +277,6 @@ var ATTACH_POINT_SETTINGS = "io.highfidelity.attachPoints";
 function getAttachPointSettings() {
     try {
         var str = Settings.getValue(ATTACH_POINT_SETTINGS);
-        print("getAttachPointSettings = " + str);
         if (str === "false") {
             return {};
         } else {
@@ -290,7 +289,6 @@ function getAttachPointSettings() {
 }
 function setAttachPointSettings(attachPointSettings) {
     var str = JSON.stringify(attachPointSettings);
-    print("setAttachPointSettings = " + str);
     Settings.setValue(ATTACH_POINT_SETTINGS, str);
 }
 function getAttachPointForHotspotFromSettings(hotspot, hand) {

From 69500643f3592ab3a669f12ed39879941b7ee87d Mon Sep 17 00:00:00 2001
From: "Anthony J. Thibault" <tony@highfidelity.io>
Date: Mon, 18 Jul 2016 14:17:32 -0700
Subject: [PATCH 14/26] bugfix for saving attach points

The feature to add transition from equip -> near-grab, in inadvertently broke attach point saving.
---
 .../system/controllers/handControllerGrab.js  | 22 +++++++++----------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index 43152f763f..cf8146fba9 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -202,8 +202,7 @@ CONTROLLER_STATE_MACHINE[STATE_NEAR_GRABBING] = {
 CONTROLLER_STATE_MACHINE[STATE_HOLD] = {
     name: "hold",
     enterMethod: "nearGrabbingEnter",
-    updateMethod: "nearGrabbing",
-    exitMethod: "holdExit"
+    updateMethod: "nearGrabbing"
 };
 CONTROLLER_STATE_MACHINE[STATE_NEAR_TRIGGER] = {
     name: "trigger",
@@ -1990,6 +1989,15 @@ function MyController(hand) {
 
             if (dropDetected && !this.waitForTriggerRelease && this.triggerSmoothedGrab()) {
                 this.callEntityMethodOnGrabbed("releaseEquip");
+
+                // store the offset attach points into preferences.
+                if (USE_ATTACH_POINT_SETTINGS && this.grabbedHotspot && this.grabbedEntity) {
+                    var props = Entities.getEntityProperties(this.grabbedEntity, ["localPosition", "localRotation"]);
+                    if (props && props.localPosition && props.localRotation) {
+                        storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, props.localPosition, props.localRotation);
+                    }
+                }
+
                 var grabbedEntity = this.grabbedEntity;
                 this.release();
                 this.grabbedEntity = grabbedEntity;
@@ -2092,16 +2100,6 @@ function MyController(hand) {
         }
     };
 
-    this.holdExit = function () {
-        // store the offset attach points into preferences.
-        if (USE_ATTACH_POINT_SETTINGS && this.grabbedHotspot && this.grabbedEntity) {
-            var props = Entities.getEntityProperties(this.grabbedEntity, ["localPosition", "localRotation"]);
-            if (props && props.localPosition && props.localRotation) {
-                storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, props.localPosition, props.localRotation);
-            }
-        }
-    };
-
     this.nearTriggerEnter = function () {
 
         this.clearEquipHaptics();

From 2d73b23c5693d48cee876752b61dd63e4095b59f Mon Sep 17 00:00:00 2001
From: Seth Alves <seth@highfidelity.io>
Date: Mon, 18 Jul 2016 14:44:41 -0700
Subject: [PATCH 15/26] when deciding on the release velocity of something
 thrown, don't include a zero velocity caused by seeing the same controller
 data as last frame

---
 interface/src/avatar/AvatarActionHold.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp
index bac3b1e02f..5acee052f2 100644
--- a/interface/src/avatar/AvatarActionHold.cpp
+++ b/interface/src/avatar/AvatarActionHold.cpp
@@ -207,8 +207,10 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
     }
 
     withWriteLock([&]{
-        if (_previousSet) {
+        if (_previousSet &&
+            _positionalTarget != _previousPositionalTarget) { // don't average in a zero velocity if we get the same data
             glm::vec3 oneFrameVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep;
+
             _measuredLinearVelocities[_measuredLinearVelocitiesIndex++] = oneFrameVelocity;
             if (_measuredLinearVelocitiesIndex >= AvatarActionHold::velocitySmoothFrames) {
                 _measuredLinearVelocitiesIndex = 0;
@@ -228,9 +230,9 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
             //     3 -- ignore i of 0 1 2
             //     4 -- ignore i of 1 2 3
             //     5 -- ignore i of 2 3 4
-            if ((i + 1) % 6 == _measuredLinearVelocitiesIndex ||
-                (i + 2) % 6 == _measuredLinearVelocitiesIndex ||
-                (i + 3) % 6 == _measuredLinearVelocitiesIndex) {
+            if ((i + 1) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
+                (i + 2) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
+                (i + 3) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex) {
                 continue;
             }
             measuredLinearVelocity += _measuredLinearVelocities[i];

From df615b1503ab554682cf6f383461b0008745d90b Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Mon, 18 Jul 2016 16:02:02 -0700
Subject: [PATCH 16/26] NotFinished never should have had its own bit

Since there is a Finished flag too.  So now, it is just 0, used as
a starting point, and we check for !hasState(Finished).  <sigh>
---
 libraries/audio/src/AudioInjector.h | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h
index 9bdfcacb5c..b872800e15 100644
--- a/libraries/audio/src/AudioInjector.h
+++ b/libraries/audio/src/AudioInjector.h
@@ -34,11 +34,11 @@ class AudioInjectorManager;
 
 
 enum class AudioInjectorState : uint8_t {
-    NotFinished = 1,
-    Finished = 2,
-    PendingDelete = 4,
-    LocalInjectionFinished = 8,
-    NetworkInjectionFinished = 16
+    NotFinished = 0,
+    Finished = 1,
+    PendingDelete = 2,
+    LocalInjectionFinished = 4,
+    NetworkInjectionFinished = 8
 };
 
 AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs);
@@ -50,12 +50,6 @@ class AudioInjector : public QObject {
     Q_OBJECT
     
 public:
-    static const uint8_t NotFinished = 1;
-    static const uint8_t Finished = 2;
-    static const uint8_t PendingDelete = 4;
-    static const uint8_t LocalInjectionFinished = 8;
-    static const uint8_t NetworkInjectionFinished = 16;
-
     AudioInjector(QObject* parent);
     AudioInjector(const Sound& sound, const AudioInjectorOptions& injectorOptions);
     AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions);
@@ -90,7 +84,7 @@ public slots:
     void setOptions(const AudioInjectorOptions& options);
     
     float getLoudness() const { return _loudness; }
-    bool isPlaying() const { return stateHas(AudioInjectorState::NotFinished); }
+    bool isPlaying() const { return !stateHas(AudioInjectorState::Finished); }
     void finish();
     void finishLocalInjection();
     void finishNetworkInjection();

From 2a89fa25bbc64f69bd5717e84af9bee3e5120962 Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Mon, 18 Jul 2016 16:22:12 -0700
Subject: [PATCH 17/26] Removing comments

Since I looked into it, seems ok
---
 libraries/audio/src/AudioInjector.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index 9c49ce66d8..58122fee3c 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -165,14 +165,10 @@ void AudioInjector::restart() {
             if (!_options.localOnly) {
 
                 if (!injectorManager->restartFinishedInjector(this)) {
-                    // TODO: this logic seems to remove the pending delete,
-                    // which makes me wonder about the deleteLater calls
                     _state = AudioInjectorState::Finished; // we're not playing, so reset the state used by isPlaying.
                 }
             }
         } else {
-            // TODO: this logic seems to remove the pending delete,
-            // which makes me wonder about the deleteLater calls
             _state = AudioInjectorState::Finished; // we failed to play, so we are finished again
         }
     }

From a8dd06ad38914045f282a63bcf1be1b5552f3ae9 Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Mon, 18 Jul 2016 19:24:43 -0700
Subject: [PATCH 18/26] Better groupint of the diffuseion of the curvature for
 easier fix for mini mirror

---
 .../render-utils/src/RenderDeferredTask.cpp   |  9 +++++---
 .../render-utils/src/SurfaceGeometryPass.cpp  | 22 +++++++++++++++----
 .../render-utils/src/SurfaceGeometryPass.h    |  5 ++++-
 libraries/render/src/render/BlurTask.cpp      |  6 ++---
 libraries/render/src/render/BlurTask.h        |  4 +++-
 5 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index 32c6cab40d..aa226e60bc 100755
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -134,18 +134,21 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
     const auto surfaceGeometryPassOutputs = addJob<SurfaceGeometryPass>("SurfaceGeometry", surfaceGeometryPassInputs);
     const auto surfaceGeometryFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(0);
     const auto curvatureFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(1);
+    const auto midCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(2);
+    const auto lowCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(3);
 
-    const auto curvatureRangeTimer = addJob<BeginGPURangeTimer>("BeginCurvatureRangeTimer");
+    const auto scatteringResource = addJob<SubsurfaceScattering>("Scattering");
+
+/*    const auto curvatureRangeTimer = addJob<BeginGPURangeTimer>("BeginCurvatureRangeTimer");
 
     // TODO: Push this 2 diffusion stages into surfaceGeometryPass as they are working together
     const auto diffuseCurvaturePassInputs = BlurGaussianDepthAware::Inputs(curvatureFramebuffer, halfLinearDepthTexture).hasVarying();
     const auto midCurvatureNormalFramebuffer = addJob<render::BlurGaussianDepthAware>("DiffuseCurvatureMid", diffuseCurvaturePassInputs);
     const auto lowCurvatureNormalFramebuffer = addJob<render::BlurGaussianDepthAware>("DiffuseCurvatureLow", diffuseCurvaturePassInputs, true); // THis blur pass generates it s render resource
 
-    const auto scatteringResource = addJob<SubsurfaceScattering>("Scattering");
 
     addJob<EndGPURangeTimer>("CurvatureRangeTimer", curvatureRangeTimer);
-
+*/
     // AO job
     addJob<AmbientOcclusionEffect>("AmbientOcclusion");
 
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp
index f60fd3f3f8..3e1930f6ba 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.cpp
+++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp
@@ -319,7 +319,10 @@ void SurfaceGeometryFramebuffer::setResolutionLevel(int resolutionLevel) {
     }
 }
 
-SurfaceGeometryPass::SurfaceGeometryPass() {
+SurfaceGeometryPass::SurfaceGeometryPass() :
+    _firstBlurPass(false),
+    _secondBlurPass(true, _firstBlurPass.getParameters())
+{
     Parameters parameters;
     _parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
 }
@@ -365,7 +368,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
   //  auto normalTexture = deferredFramebuffer->getDeferredNormalTexture();
     auto normalTexture = linearDepthFramebuffer->getHalfNormalTexture();
 
-    auto curvatureFBO = _surfaceGeometryFramebuffer->getCurvatureFramebuffer();
+    auto curvatureFramebuffer = _surfaceGeometryFramebuffer->getCurvatureFramebuffer();
 #ifdef USE_STENCIL_TEST
     if (curvatureFBO->getDepthStencilBuffer() != deferredFramebuffer->getPrimaryDepthTexture()) {
         curvatureFBO->setDepthStencilBuffer(deferredFramebuffer->getPrimaryDepthTexture(), deferredFramebuffer->getPrimaryDepthTexture()->getTexelFormat());
@@ -374,7 +377,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
     auto curvatureTexture = _surfaceGeometryFramebuffer->getCurvatureTexture();
 
     outputs.edit0() = _surfaceGeometryFramebuffer;
-    outputs.edit1() = curvatureFBO;
+    outputs.edit1() = curvatureFramebuffer;
 
     auto curvaturePipeline = getCurvaturePipeline();
 
@@ -396,7 +399,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
         batch.setUniformBuffer(SurfaceGeometryPass_ParamsSlot, _parametersBuffer);
 
         // Curvature pass
-        batch.setFramebuffer(curvatureFBO);
+        batch.setFramebuffer(curvatureFramebuffer);
  
         // We can avoid the clear by drawing the same clear vallue from the makeCurvature shader. same performances or no worse
       
@@ -416,6 +419,17 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
         _gpuTimer.end(batch);
     });
 
+    const auto diffuseCurvaturePassInputs = render::BlurGaussianDepthAware::Inputs(curvatureFramebuffer, linearDepthTexture);
+    gpu::FramebufferPointer midBlurredFramebuffer;
+    _firstBlurPass.run(sceneContext, renderContext, diffuseCurvaturePassInputs, midBlurredFramebuffer);
+
+    gpu::FramebufferPointer lowBlurredFramebuffer;
+    _secondBlurPass.run(sceneContext, renderContext, diffuseCurvaturePassInputs, lowBlurredFramebuffer);
+    
+ 
+    outputs.edit2() = midBlurredFramebuffer;
+    outputs.edit3() = lowBlurredFramebuffer;
+
     auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
     config->gpuTime = _gpuTimer.getAverage();
 }
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h
index 3f42a7ab1f..d0f79dad76 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.h
+++ b/libraries/render-utils/src/SurfaceGeometryPass.h
@@ -15,6 +15,7 @@
 #include <DependencyManager.h>
 
 #include "render/DrawTask.h"
+#include "render/BlurTask.h"
 #include "DeferredFrameTransform.h"
 #include "DeferredFramebuffer.h"
 
@@ -162,7 +163,7 @@ signals:
 class SurfaceGeometryPass {
 public:
     using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
-    using Outputs = render::VaryingSet2<SurfaceGeometryFramebufferPointer, gpu::FramebufferPointer>;
+    using Outputs = render::VaryingSet4<SurfaceGeometryFramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer>;
     using Config = SurfaceGeometryPassConfig;
     using JobModel = render::Job::ModelIO<SurfaceGeometryPass, Inputs, Outputs, Config>;
 
@@ -196,6 +197,8 @@ private:
 
     gpu::PipelinePointer _curvaturePipeline;
 
+    render::BlurGaussianDepthAware _firstBlurPass;
+    render::BlurGaussianDepthAware _secondBlurPass;
 
     gpu::RangeTimer _gpuTimer;
 };
diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp
index 862c08bcbb..ddaaa82e31 100644
--- a/libraries/render/src/render/BlurTask.cpp
+++ b/libraries/render/src/render/BlurTask.cpp
@@ -258,10 +258,10 @@ void BlurGaussian::run(const SceneContextPointer& sceneContext, const RenderCont
 
 
 
-BlurGaussianDepthAware::BlurGaussianDepthAware(bool generateOutputFramebuffer) :
-    _inOutResources(generateOutputFramebuffer)
+BlurGaussianDepthAware::BlurGaussianDepthAware(bool generateOutputFramebuffer, const BlurParamsPointer& params) :
+    _inOutResources(generateOutputFramebuffer),
+    _parameters((params ? params : std::make_shared<BlurParams>()))
 {
-    _parameters = std::make_shared<BlurParams>();
 }
 
 gpu::PipelinePointer BlurGaussianDepthAware::getBlurVPipeline() {
diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h
index 7d8fb62fbc..b54e494a80 100644
--- a/libraries/render/src/render/BlurTask.h
+++ b/libraries/render/src/render/BlurTask.h
@@ -138,11 +138,13 @@ public:
     using Config = BlurGaussianDepthAwareConfig;
     using JobModel = Job::ModelIO<BlurGaussianDepthAware, Inputs, gpu::FramebufferPointer, Config>;
 
-    BlurGaussianDepthAware(bool generateNewOutput = false);
+    BlurGaussianDepthAware(bool generateNewOutput = false, const BlurParamsPointer& params = BlurParamsPointer());
 
     void configure(const Config& config);
     void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& SourceAndDepth, gpu::FramebufferPointer& blurredFramebuffer);
 
+    const BlurParamsPointer& getParameters() const { return _parameters; }
+
 protected:
 
     BlurParamsPointer _parameters;

From cbbb2a7975b7276170f5fd85c7473fdc9d8eedf5 Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Mon, 18 Jul 2016 19:04:17 -0700
Subject: [PATCH 19/26] Properly delete GL context and offscreen surfaces

---
 libraries/gl/src/gl/OffscreenGLCanvas.cpp     |  8 ++++++++
 libraries/gl/src/gl/OffscreenGLCanvas.h       |  4 ++--
 libraries/gl/src/gl/QOpenGLContextWrapper.cpp | 15 ++++++++-------
 libraries/gl/src/gl/QOpenGLContextWrapper.h   |  2 ++
 4 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
index eec3d2bf6b..a6b5a03ff6 100644
--- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp
+++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
@@ -36,7 +36,15 @@ OffscreenGLCanvas::~OffscreenGLCanvas() {
         delete _logger;
         _logger = nullptr;
     }
+    
     _context->doneCurrent();
+    delete _context;
+    _context = nullptr;
+
+    _offscreenSurface->destroy();
+    delete _offscreenSurface;
+    _offscreenSurface = nullptr;
+
 }
 
 bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.h b/libraries/gl/src/gl/OffscreenGLCanvas.h
index 69210f638d..8def09796d 100644
--- a/libraries/gl/src/gl/OffscreenGLCanvas.h
+++ b/libraries/gl/src/gl/OffscreenGLCanvas.h
@@ -34,8 +34,8 @@ public:
     
 protected:
     std::once_flag _reportOnce;
-    QOpenGLContext* _context;
-    QOffscreenSurface* _offscreenSurface;
+    QOpenGLContext* _context{ nullptr };
+    QOffscreenSurface* _offscreenSurface{ nullptr };
     QOpenGLDebugLogger* _logger{ nullptr };
 };
 
diff --git a/libraries/gl/src/gl/QOpenGLContextWrapper.cpp b/libraries/gl/src/gl/QOpenGLContextWrapper.cpp
index bc8afc3927..0b153a5ae8 100644
--- a/libraries/gl/src/gl/QOpenGLContextWrapper.cpp
+++ b/libraries/gl/src/gl/QOpenGLContextWrapper.cpp
@@ -28,16 +28,17 @@ QOpenGLContext* QOpenGLContextWrapper::currentContext() {
     return QOpenGLContext::currentContext();
 }
 
-
 QOpenGLContextWrapper::QOpenGLContextWrapper() :
-_context(new QOpenGLContext)
-{
-}
-
+    _ownContext(true), _context(new QOpenGLContext) { }
 
 QOpenGLContextWrapper::QOpenGLContextWrapper(QOpenGLContext* context) :
-    _context(context)
-{
+    _context(context) { }
+
+QOpenGLContextWrapper::~QOpenGLContextWrapper() {
+    if (_ownContext) {
+        delete _context;
+        _context = nullptr;
+    }
 }
 
 void QOpenGLContextWrapper::setFormat(const QSurfaceFormat& format) {
diff --git a/libraries/gl/src/gl/QOpenGLContextWrapper.h b/libraries/gl/src/gl/QOpenGLContextWrapper.h
index d097284e68..b09ad1a4c3 100644
--- a/libraries/gl/src/gl/QOpenGLContextWrapper.h
+++ b/libraries/gl/src/gl/QOpenGLContextWrapper.h
@@ -23,6 +23,7 @@ class QOpenGLContextWrapper {
 public:
     QOpenGLContextWrapper();
     QOpenGLContextWrapper(QOpenGLContext* context);
+    virtual ~QOpenGLContextWrapper();
     void setFormat(const QSurfaceFormat& format);
     bool create();
     void swapBuffers(QSurface* surface);
@@ -40,6 +41,7 @@ public:
 
     
 private:
+    bool _ownContext { false };
     QOpenGLContext* _context { nullptr };
 };
 

From ff132fa7128acf44d73136f8e348f13524052d90 Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 02:11:22 -0700
Subject: [PATCH 20/26] Gathering the diffusion passes in the
 SUrfaceGEometryPAss job

---
 interface/src/Application.cpp                 |   2 +
 .../render-utils/src/SurfaceGeometryPass.cpp  | 145 ++++++++++++++----
 .../render-utils/src/SurfaceGeometryPass.h    |  24 ++-
 libraries/render/src/render/BlurTask.cpp      |  11 +-
 libraries/render/src/render/BlurTask.h        |   6 +-
 .../developer/utilities/render/statsGPU.qml   |   5 -
 .../utilities/render/surfaceGeometryPass.qml  |  19 +--
 7 files changed, 146 insertions(+), 66 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index bc65977beb..a29ac19f97 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -305,6 +305,8 @@ public:
                 // Don't actually crash in debug builds, in case this apparent deadlock is simply from
                 // the developer actively debugging code
                 #ifdef NDEBUG
+
+
                     deadlockDetectionCrash();
                 #endif
             }
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp
index 3e1930f6ba..95557c99e3 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.cpp
+++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp
@@ -282,6 +282,10 @@ void SurfaceGeometryFramebuffer::updateLinearDepth(const gpu::TexturePointer& li
 void SurfaceGeometryFramebuffer::clear() {
     _curvatureFramebuffer.reset();
     _curvatureTexture.reset();
+    _lowCurvatureFramebuffer.reset();
+    _lowCurvatureTexture.reset();
+    _blurringFramebuffer.reset();
+    _blurringTexture.reset();
 }
 
 gpu::TexturePointer SurfaceGeometryFramebuffer::getLinearDepthTexture() {
@@ -293,9 +297,17 @@ void SurfaceGeometryFramebuffer::allocate() {
     auto width = _frameSize.x;
     auto height = _frameSize.y;
 
-    _curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width >> getResolutionLevel(), height >> getResolutionLevel(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
+    _curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
     _curvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
     _curvatureFramebuffer->setRenderBuffer(0, _curvatureTexture);
+
+    _lowCurvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
+    _lowCurvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
+    _lowCurvatureFramebuffer->setRenderBuffer(0, _lowCurvatureTexture);
+
+    _blurringTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
+    _blurringFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
+    _blurringFramebuffer->setRenderBuffer(0, _blurringTexture);
 }
 
 gpu::FramebufferPointer SurfaceGeometryFramebuffer::getCurvatureFramebuffer() {
@@ -312,6 +324,34 @@ gpu::TexturePointer SurfaceGeometryFramebuffer::getCurvatureTexture() {
     return _curvatureTexture;
 }
 
+gpu::FramebufferPointer SurfaceGeometryFramebuffer::getLowCurvatureFramebuffer() {
+    if (!_lowCurvatureFramebuffer) {
+        allocate();
+    }
+    return _lowCurvatureFramebuffer;
+}
+
+gpu::TexturePointer SurfaceGeometryFramebuffer::getLowCurvatureTexture() {
+    if (!_lowCurvatureTexture) {
+        allocate();
+    }
+    return _lowCurvatureTexture;
+}
+
+gpu::FramebufferPointer SurfaceGeometryFramebuffer::getBlurringFramebuffer() {
+    if (!_blurringFramebuffer) {
+        allocate();
+    }
+    return _blurringFramebuffer;
+}
+
+gpu::TexturePointer SurfaceGeometryFramebuffer::getBlurringTexture() {
+    if (!_blurringTexture) {
+        allocate();
+    }
+    return _blurringTexture;
+}
+
 void SurfaceGeometryFramebuffer::setResolutionLevel(int resolutionLevel) {
     if (resolutionLevel != getResolutionLevel()) {
         clear();
@@ -320,8 +360,7 @@ void SurfaceGeometryFramebuffer::setResolutionLevel(int resolutionLevel) {
 }
 
 SurfaceGeometryPass::SurfaceGeometryPass() :
-    _firstBlurPass(false),
-    _secondBlurPass(true, _firstBlurPass.getParameters())
+    _diffusePass(false)
 {
     Parameters parameters;
     _parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
@@ -345,6 +384,10 @@ void SurfaceGeometryPass::configure(const Config& config) {
         _surfaceGeometryFramebuffer = std::make_shared<SurfaceGeometryFramebuffer>();
     }
     _surfaceGeometryFramebuffer->setResolutionLevel(config.resolutionLevel);
+
+    _diffusePass.getParameters()->setFilterRadiusScale(config.diffuseFilterScale);
+    _diffusePass.getParameters()->setDepthThreshold(config.diffuseDepthThreshold);
+    
 }
 
 
@@ -358,33 +401,52 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
     const auto deferredFramebuffer = inputs.get1();
     const auto linearDepthFramebuffer = inputs.get2();
 
-    auto linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
+
+    auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
+    auto normalTexture = deferredFramebuffer->getDeferredNormalTexture();
+    auto sourceViewport = args->_viewport;
+    auto curvatureViewport = sourceViewport;
+
+    if (_surfaceGeometryFramebuffer->getResolutionLevel() > 0) {
+        linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
+        normalTexture = linearDepthFramebuffer->getHalfNormalTexture();
+        curvatureViewport = curvatureViewport >> _surfaceGeometryFramebuffer->getResolutionLevel();
+    }
 
     if (!_surfaceGeometryFramebuffer) {
         _surfaceGeometryFramebuffer = std::make_shared<SurfaceGeometryFramebuffer>();
     }
     _surfaceGeometryFramebuffer->updateLinearDepth(linearDepthTexture);
 
-  //  auto normalTexture = deferredFramebuffer->getDeferredNormalTexture();
-    auto normalTexture = linearDepthFramebuffer->getHalfNormalTexture();
-
     auto curvatureFramebuffer = _surfaceGeometryFramebuffer->getCurvatureFramebuffer();
+    auto curvatureTexture = _surfaceGeometryFramebuffer->getCurvatureTexture();
 #ifdef USE_STENCIL_TEST
-    if (curvatureFBO->getDepthStencilBuffer() != deferredFramebuffer->getPrimaryDepthTexture()) {
-        curvatureFBO->setDepthStencilBuffer(deferredFramebuffer->getPrimaryDepthTexture(), deferredFramebuffer->getPrimaryDepthTexture()->getTexelFormat());
+    if (curvatureFramebuffer->getDepthStencilBuffer() != deferredFramebuffer->getPrimaryDepthTexture()) {
+        curvatureFramebuffer->setDepthStencilBuffer(deferredFramebuffer->getPrimaryDepthTexture(), deferredFramebuffer->getPrimaryDepthTexture()->getTexelFormat());
     }
 #endif
-    auto curvatureTexture = _surfaceGeometryFramebuffer->getCurvatureTexture();
+
+    auto lowCurvatureFramebuffer = _surfaceGeometryFramebuffer->getLowCurvatureFramebuffer();
+    auto lowCurvatureTexture = _surfaceGeometryFramebuffer->getLowCurvatureTexture();
+ 
+    auto blurringFramebuffer = _surfaceGeometryFramebuffer->getBlurringFramebuffer();
+    auto blurringTexture = _surfaceGeometryFramebuffer->getBlurringTexture();
 
     outputs.edit0() = _surfaceGeometryFramebuffer;
     outputs.edit1() = curvatureFramebuffer;
+    outputs.edit2() = curvatureFramebuffer;
+    outputs.edit3() = lowCurvatureFramebuffer;
 
     auto curvaturePipeline = getCurvaturePipeline();
+    auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
+    auto diffuseHPipeline = _diffusePass.getBlurHPipeline();
 
-    auto depthViewport = args->_viewport;
-    auto curvatureViewport = depthViewport >> 1;
-  //  >> _surfaceGeometryFramebuffer->getResolutionLevel();
+    glm::ivec2 textureSize(curvatureTexture->getDimensions());
+    _diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport));
+    _diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
+    _diffusePass.getParameters()->setLinearDepthPosFar(args->getViewFrustum().getFarClip());
 
+ 
     gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
         _gpuTimer.begin(batch);
         batch.enableStereo(false);
@@ -393,43 +455,58 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
         batch.setViewTransform(Transform());
 
         batch.setViewportTransform(curvatureViewport);
-        batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_surfaceGeometryFramebuffer->getCurvatureFrameSize(), curvatureViewport));
-
-        batch.setUniformBuffer(SurfaceGeometryPass_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
-        batch.setUniformBuffer(SurfaceGeometryPass_ParamsSlot, _parametersBuffer);
+        batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_surfaceGeometryFramebuffer->getSourceFrameSize(), curvatureViewport));
 
         // Curvature pass
+        batch.setUniformBuffer(SurfaceGeometryPass_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
+        batch.setUniformBuffer(SurfaceGeometryPass_ParamsSlot, _parametersBuffer);
         batch.setFramebuffer(curvatureFramebuffer);
- 
-        // We can avoid the clear by drawing the same clear vallue from the makeCurvature shader. same performances or no worse
-      
+        // We can avoid the clear by drawing the same clear vallue from the makeCurvature shader. same performances or no worse     
 #ifdef USE_STENCIL_TEST
         // Except if stenciling out
         batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
 #endif
-
         batch.setPipeline(curvaturePipeline);
         batch.setResourceTexture(SurfaceGeometryPass_DepthMapSlot, linearDepthTexture);
         batch.setResourceTexture(SurfaceGeometryPass_NormalMapSlot, normalTexture);
         batch.draw(gpu::TRIANGLE_STRIP, 4);
 
-        batch.setResourceTexture(SurfaceGeometryPass_DepthMapSlot, nullptr);
-        batch.setResourceTexture(SurfaceGeometryPass_NormalMapSlot, nullptr);
+        // Diffusion pass
+        const int BlurTask_ParamsSlot = 0;
+        const int BlurTask_SourceSlot = 0;
+        const int BlurTask_DepthSlot = 1;
+        batch.setUniformBuffer(BlurTask_ParamsSlot, _diffusePass.getParameters()->_parametersBuffer);
+
+        batch.setResourceTexture(BlurTask_DepthSlot, linearDepthTexture);
+
+        batch.setFramebuffer(blurringFramebuffer);     
+        batch.setPipeline(diffuseVPipeline);
+        batch.setResourceTexture(BlurTask_SourceSlot, curvatureTexture);
+        batch.draw(gpu::TRIANGLE_STRIP, 4);
+
+        batch.setFramebuffer(curvatureFramebuffer);
+        batch.setPipeline(diffuseHPipeline);
+        batch.setResourceTexture(BlurTask_SourceSlot, blurringTexture);
+        batch.draw(gpu::TRIANGLE_STRIP, 4);
+
+        batch.setFramebuffer(blurringFramebuffer);     
+        batch.setPipeline(diffuseVPipeline);
+        batch.setResourceTexture(BlurTask_SourceSlot, curvatureTexture);
+        batch.draw(gpu::TRIANGLE_STRIP, 4);
+
+        batch.setFramebuffer(lowCurvatureFramebuffer);
+        batch.setPipeline(diffuseHPipeline);
+        batch.setResourceTexture(BlurTask_SourceSlot, blurringTexture);
+        batch.draw(gpu::TRIANGLE_STRIP, 4);
+
+        batch.setResourceTexture(BlurTask_SourceSlot, nullptr);
+        batch.setResourceTexture(BlurTask_DepthSlot, nullptr);
+        batch.setUniformBuffer(BlurTask_ParamsSlot, nullptr);
 
         _gpuTimer.end(batch);
     });
-
-    const auto diffuseCurvaturePassInputs = render::BlurGaussianDepthAware::Inputs(curvatureFramebuffer, linearDepthTexture);
-    gpu::FramebufferPointer midBlurredFramebuffer;
-    _firstBlurPass.run(sceneContext, renderContext, diffuseCurvaturePassInputs, midBlurredFramebuffer);
-
-    gpu::FramebufferPointer lowBlurredFramebuffer;
-    _secondBlurPass.run(sceneContext, renderContext, diffuseCurvaturePassInputs, lowBlurredFramebuffer);
-    
+       
  
-    outputs.edit2() = midBlurredFramebuffer;
-    outputs.edit3() = lowBlurredFramebuffer;
-
     auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
     config->gpuTime = _gpuTimer.getAverage();
 }
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h
index d0f79dad76..9a7ff7d964 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.h
+++ b/libraries/render-utils/src/SurfaceGeometryPass.h
@@ -112,12 +112,17 @@ public:
 
     gpu::FramebufferPointer getCurvatureFramebuffer();
     gpu::TexturePointer getCurvatureTexture();
+  
+    gpu::FramebufferPointer getLowCurvatureFramebuffer();
+    gpu::TexturePointer getLowCurvatureTexture();
+
+    gpu::FramebufferPointer getBlurringFramebuffer();
+    gpu::TexturePointer getBlurringTexture();
 
     // Update the source framebuffer size which will drive the allocation of all the other resources.
     void updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
     gpu::TexturePointer getLinearDepthTexture();
     const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
-    glm::ivec2 getCurvatureFrameSize() const { return _frameSize >> _resolutionLevel; }
 
     void setResolutionLevel(int level);
     int getResolutionLevel() const { return _resolutionLevel; }
@@ -131,6 +136,12 @@ protected:
     gpu::FramebufferPointer _curvatureFramebuffer;
     gpu::TexturePointer _curvatureTexture;
 
+    gpu::FramebufferPointer _blurringFramebuffer;
+    gpu::TexturePointer _blurringTexture;
+
+    gpu::FramebufferPointer _lowCurvatureFramebuffer;
+    gpu::TexturePointer _lowCurvatureTexture;
+
     glm::ivec2 _frameSize;
     int _resolutionLevel{ 0 };
 };
@@ -143,6 +154,10 @@ class SurfaceGeometryPassConfig : public render::Job::Config {
     Q_PROPERTY(float basisScale MEMBER basisScale NOTIFY dirty)
     Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
     Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel NOTIFY dirty)
+
+    Q_PROPERTY(float diffuseFilterScale MEMBER diffuseFilterScale NOTIFY dirty)
+    Q_PROPERTY(float diffuseDepthThreshold MEMBER diffuseDepthThreshold NOTIFY dirty)
+
     Q_PROPERTY(double gpuTime READ getGpuTime)
 public:
     SurfaceGeometryPassConfig() : render::Job::Config(true) {}
@@ -151,6 +166,8 @@ public:
     float basisScale{ 1.0f };
     float curvatureScale{ 10.0f };
     int resolutionLevel{ 0 };
+    float diffuseFilterScale{ 0.2f };
+    float diffuseDepthThreshold{ 1.0f };
 
     double getGpuTime() { return gpuTime; }
 
@@ -191,14 +208,15 @@ private:
     };
     gpu::BufferView _parametersBuffer;
 
+
     SurfaceGeometryFramebufferPointer _surfaceGeometryFramebuffer;
 
     const gpu::PipelinePointer& getCurvaturePipeline();
 
     gpu::PipelinePointer _curvaturePipeline;
+    
+    render::BlurGaussianDepthAware _diffusePass;
 
-    render::BlurGaussianDepthAware _firstBlurPass;
-    render::BlurGaussianDepthAware _secondBlurPass;
 
     gpu::RangeTimer _gpuTimer;
 };
diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp
index ddaaa82e31..3849adf588 100644
--- a/libraries/render/src/render/BlurTask.cpp
+++ b/libraries/render/src/render/BlurTask.cpp
@@ -337,24 +337,23 @@ void BlurGaussianDepthAware::run(const SceneContextPointer& sceneContext, const
     auto blurHPipeline = getBlurHPipeline();
 
     auto sourceViewport = args->_viewport;
-    auto blurViewport = sourceViewport >> 1;
 
-    _parameters->setWidthHeight(blurViewport.z, blurViewport.w, args->_context->isStereo());
+    _parameters->setWidthHeight(sourceViewport.z, sourceViewport.w, args->_context->isStereo());
     glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions());
-    _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, blurViewport));
+    _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, sourceViewport));
     _parameters->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
     _parameters->setLinearDepthPosFar(args->getViewFrustum().getFarClip());
 
     gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
         batch.enableStereo(false);
-        batch.setViewportTransform(blurViewport);
+        batch.setViewportTransform(sourceViewport);
 
         batch.setUniformBuffer(BlurTask_ParamsSlot, _parameters->_parametersBuffer);
 
         batch.setResourceTexture(BlurTask_DepthSlot, depthTexture);
 
         batch.setFramebuffer(blurringResources.blurringFramebuffer);
-      //  batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
+        // batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
 
         batch.setPipeline(blurVPipeline);
         batch.setResourceTexture(BlurTask_SourceSlot, blurringResources.sourceTexture);
@@ -362,7 +361,7 @@ void BlurGaussianDepthAware::run(const SceneContextPointer& sceneContext, const
 
         batch.setFramebuffer(blurringResources.finalFramebuffer);
         if (_inOutResources._generateOutputFramebuffer) {
-     //       batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
+            // batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
         }
 
         batch.setPipeline(blurHPipeline);
diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h
index b54e494a80..f820947d98 100644
--- a/libraries/render/src/render/BlurTask.h
+++ b/libraries/render/src/render/BlurTask.h
@@ -144,6 +144,9 @@ public:
     void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& SourceAndDepth, gpu::FramebufferPointer& blurredFramebuffer);
 
     const BlurParamsPointer& getParameters() const { return _parameters; }
+ 
+    gpu::PipelinePointer getBlurVPipeline();
+    gpu::PipelinePointer getBlurHPipeline();
 
 protected:
 
@@ -152,9 +155,6 @@ protected:
     gpu::PipelinePointer _blurVPipeline;
     gpu::PipelinePointer _blurHPipeline;
 
-    gpu::PipelinePointer getBlurVPipeline();
-    gpu::PipelinePointer getBlurHPipeline();
-
     BlurInOutResource _inOutResources;
 };
 
diff --git a/scripts/developer/utilities/render/statsGPU.qml b/scripts/developer/utilities/render/statsGPU.qml
index 44ea4c4597..74bd376a00 100644
--- a/scripts/developer/utilities/render/statsGPU.qml
+++ b/scripts/developer/utilities/render/statsGPU.qml
@@ -53,11 +53,6 @@ Item {
                    prop: "gpuTime",
                    label: "SurfaceGeometry",
                    color: "#00FFFF"
-               },{
-                   object: Render.getConfig("CurvatureRangeTimer"),
-                   prop: "gpuTime",
-                   label: "Curvature",
-                   color: "#00FF00"
                },
                {
                    object: Render.getConfig("RenderDeferred"),
diff --git a/scripts/developer/utilities/render/surfaceGeometryPass.qml b/scripts/developer/utilities/render/surfaceGeometryPass.qml
index ad5a9dd03d..3f06e63719 100644
--- a/scripts/developer/utilities/render/surfaceGeometryPass.qml
+++ b/scripts/developer/utilities/render/surfaceGeometryPass.qml
@@ -41,16 +41,11 @@ Column {
                     min: 0.0
                 }
             }
-        }
-
-        Column{
-            CheckBox {
-                text: "Diffuse Curvature Mid"
-                checked: true
-                onCheckedChanged: { Render.getConfig("DiffuseCurvatureMid").enabled = checked }
-            }        
+    
             Repeater {
-                model: [ "Blur Scale:DiffuseCurvatureMid:filterScale:2.0", "Blur Depth Threshold:DiffuseCurvatureMid:depthThreshold:1.0", "Blur Scale2:DiffuseCurvatureLow:filterScale:2.0", "Blur Depth Threshold 2:DiffuseCurvatureLow:depthThreshold:1.0"]
+                model: [ "Diffusion Scale:SurfaceGeometry:diffuseFilterScale:2.0",
+                         "Diffusion Depth Threshold:SurfaceGeometry:diffuseDepthThreshold:1.0"
+                ]
                 ConfigSlider {
                     label: qsTr(modelData.split(":")[0])
                     integral: false
@@ -60,12 +55,6 @@ Column {
                     min: 0.0
                 }
             }
-
-            CheckBox {
-                text: "Diffuse Curvature Low"
-                checked: true
-                onCheckedChanged: { Render.getConfig("DiffuseCurvatureLow").enabled = checked }
-            }
         }
     }
 }

From d98ae1ba9ce229df8d2ec8f329f439384abc0ccd Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Tue, 19 Jul 2016 07:10:34 -0700
Subject: [PATCH 21/26] Ensure the pause overlay is unlit (emissive)

---
 scripts/system/away.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/system/away.js b/scripts/system/away.js
index 04263d4223..25c330738f 100644
--- a/scripts/system/away.js
+++ b/scripts/system/away.js
@@ -34,6 +34,7 @@ var OVERLAY_DATA_HMD = {
     color: {red: 255, green: 255, blue: 255},
     alpha: 1,
     scale: 2,
+    emissive: true,
     isFacingAvatar: true,
     drawInFront: true
 };

From 36d58a2b823e37542c45381d61c422d3ddfcfdde Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 10:34:06 -0700
Subject: [PATCH 22/26] Finish the integration of the diffusion pass in the
 SurfaceGeometryPass job, clean up ui

---
 libraries/render-utils/src/DeferredBuffer.slh | 51 ++-----------------
 .../render-utils/src/RenderDeferredTask.cpp   | 11 +---
 .../render-utils/src/SurfaceGeometryPass.cpp  |  4 ++
 .../render-utils/src/SurfaceGeometryPass.h    |  6 ++-
 .../src/surfaceGeometry_makeCurvature.slf     | 37 ++++----------
 .../utilities/render/surfaceGeometryPass.qml  |  6 ++-
 6 files changed, 29 insertions(+), 86 deletions(-)

diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh
index 5f80354585..a4b69bd70e 100755
--- a/libraries/render-utils/src/DeferredBuffer.slh
+++ b/libraries/render-utils/src/DeferredBuffer.slh
@@ -11,6 +11,8 @@
 <@if not DEFERRED_BUFFER_SLH@>
 <@def DEFERRED_BUFFER_SLH@>
 
+<@include gpu/PackedNormal.slh@>
+
 // Unpack the metallic-mode value
 const float FRAG_PACK_SHADED_NON_METALLIC = 0.0;
 const float FRAG_PACK_SHADED_METALLIC = 0.1;
@@ -63,44 +65,7 @@ float packUnlit() {
     return FRAG_PACK_UNLIT;
 }
 
-
-vec2 signNotZero(vec2 v) {
-    return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
-}
-
-vec2 float32x3_to_oct(in vec3 v) {
-    vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
-    return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);
-}
-
-
-vec3 oct_to_float32x3(in vec2 e) {
-    vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
-    if (v.z < 0) {
-        v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
-    }
-    return normalize(v);
-}
-
-vec3 snorm12x2_to_unorm8x3(vec2 f) {
-    vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));
-    float t = floor(u.y / 256.0);
-
-    return floor(vec3(
-        u.x / 16.0,
-        fract(u.x / 16.0) * 256.0 + t,
-        u.y - t * 256.0
-        )) / 255.0;
-}
-
-vec2 unorm8x3_to_snorm12x2(vec3 u) {
-    u *= 255.0;
-    u.y *= (1.0 / 16.0);
-    vec2 s = vec2(  u.x * 16.0 + floor(u.y),
-                    fract(u.y) * (16.0 * 256.0) + u.z);
-    return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));
-}
-
+<!
 uniform sampler2D normalFittingMap;
 
 vec3 bestFitNormal(vec3 normal) {
@@ -119,14 +84,6 @@ vec3 bestFitNormal(vec3 normal) {
 
     return (cN * 0.5 + 0.5);
 }
-
-vec3 packNormal(in vec3 n) {
-    return snorm12x2_to_unorm8x3(float32x3_to_oct(n));
-}
-
-vec3 unpackNormal(in vec3 p) {
-    return oct_to_float32x3(unorm8x3_to_snorm12x2(p));
-}
-
+!>
 
 <@endif@>
diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index aa226e60bc..bb7adf3f80 100755
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -137,18 +137,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
     const auto midCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(2);
     const auto lowCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(3);
 
+    // Simply update the scattering resource
     const auto scatteringResource = addJob<SubsurfaceScattering>("Scattering");
 
-/*    const auto curvatureRangeTimer = addJob<BeginGPURangeTimer>("BeginCurvatureRangeTimer");
-
-    // TODO: Push this 2 diffusion stages into surfaceGeometryPass as they are working together
-    const auto diffuseCurvaturePassInputs = BlurGaussianDepthAware::Inputs(curvatureFramebuffer, halfLinearDepthTexture).hasVarying();
-    const auto midCurvatureNormalFramebuffer = addJob<render::BlurGaussianDepthAware>("DiffuseCurvatureMid", diffuseCurvaturePassInputs);
-    const auto lowCurvatureNormalFramebuffer = addJob<render::BlurGaussianDepthAware>("DiffuseCurvatureLow", diffuseCurvaturePassInputs, true); // THis blur pass generates it s render resource
-
-
-    addJob<EndGPURangeTimer>("CurvatureRangeTimer", curvatureRangeTimer);
-*/
     // AO job
     addJob<AmbientOcclusionEffect>("AmbientOcclusion");
 
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp
index 95557c99e3..26063ba30c 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.cpp
+++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp
@@ -383,7 +383,11 @@ void SurfaceGeometryPass::configure(const Config& config) {
     if (!_surfaceGeometryFramebuffer) {
         _surfaceGeometryFramebuffer = std::make_shared<SurfaceGeometryFramebuffer>();
     }
+
     _surfaceGeometryFramebuffer->setResolutionLevel(config.resolutionLevel);
+    if (config.resolutionLevel != getResolutionLevel()) {
+        _parametersBuffer.edit<Parameters>().resolutionInfo.w = config.resolutionLevel;
+    }
 
     _diffusePass.getParameters()->setFilterRadiusScale(config.diffuseFilterScale);
     _diffusePass.getParameters()->setDepthThreshold(config.diffuseDepthThreshold);
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h
index 9a7ff7d964..24f0c56cdd 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.h
+++ b/libraries/render-utils/src/SurfaceGeometryPass.h
@@ -165,7 +165,7 @@ public:
     float depthThreshold{ 5.0f }; // centimeters
     float basisScale{ 1.0f };
     float curvatureScale{ 10.0f };
-    int resolutionLevel{ 0 };
+    int resolutionLevel{ 1 };
     float diffuseFilterScale{ 0.2f };
     float diffuseDepthThreshold{ 1.0f };
 
@@ -189,9 +189,11 @@ public:
     void configure(const Config& config);
     void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
     
+
     float getCurvatureDepthThreshold() const { return _parametersBuffer.get<Parameters>().curvatureInfo.x; }
     float getCurvatureBasisScale() const { return _parametersBuffer.get<Parameters>().curvatureInfo.y; }
     float getCurvatureScale() const { return _parametersBuffer.get<Parameters>().curvatureInfo.w; }
+    int getResolutionLevel() const { return (int)_parametersBuffer.get<Parameters>().resolutionInfo.w; }
 
 private:
     typedef gpu::BufferView UniformBufferView;
@@ -200,7 +202,7 @@ private:
     class Parameters {
     public:
         // Resolution info
-        glm::vec4 resolutionInfo { -1.0f, 0.0f, 0.0f, 0.0f };
+        glm::vec4 resolutionInfo { 0.0f, 0.0f, 0.0f, 1.0f }; // Default Curvature & Diffusion is running half res
         // Curvature algorithm
         glm::vec4 curvatureInfo{ 0.0f };
 
diff --git a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf
index bf8ca6abf3..e96ac60b45 100644
--- a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf
+++ b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf
@@ -12,6 +12,8 @@
 <@include DeferredTransform.slh@>
 <$declareDeferredFrameTransform()$>
 
+<@include gpu/PackedNormal.slh@>
+
 struct SurfaceGeometryParams {
     // Resolution info
     vec4 resolutionInfo;
@@ -35,6 +37,10 @@ float getCurvatureScale() {
     return params.curvatureInfo.w;
 }
 
+bool isFullResolution() {
+    return params.resolutionInfo.w == 0.0;
+}
+
 
 uniform sampler2D linearDepthMap;
 float getZEye(ivec2 pixel) {
@@ -44,29 +50,6 @@ float getZEyeLinear(vec2 texcoord) {
     return -texture(linearDepthMap, texcoord).x;
 }
 
-vec2 signNotZero(vec2 v) {
-    return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
-}
-
-vec3 oct_to_float32x3(in vec2 e) {
-    vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
-    if (v.z < 0) {
-        v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
-    }
-    return normalize(v);
-}
-
-vec2 unorm8x3_to_snorm12x2(vec3 u) {
-    u *= 255.0;
-    u.y *= (1.0 / 16.0);
-    vec2 s = vec2(  u.x * 16.0 + floor(u.y),
-    fract(u.y) * (16.0 * 256.0) + u.z);
-    return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));
-}
-vec3 unpackNormal(in vec3 p) {
-    return oct_to_float32x3(unorm8x3_to_snorm12x2(p));
-}
-
 vec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) {
     return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y);
 }
@@ -78,10 +61,12 @@ vec3 getRawNormal(vec2 texcoord) {
 }
 
 vec3 getWorldNormal(vec2 texcoord) {
-  //  vec3 rawNormal = getRawNormal(texcoord);
-   // return unpackNormal(rawNormal);
     vec3 rawNormal = getRawNormal(texcoord);
-    return normalize((rawNormal - vec3(0.5)) * 2.0);
+    if (isFullResolution()) {
+        return unpackNormal(rawNormal);
+    } else {
+        return normalize((rawNormal - vec3(0.5)) * 2.0);
+    }
 }
 
 vec3 getWorldNormalDiff(vec2 texcoord, vec2 delta) {
diff --git a/scripts/developer/utilities/render/surfaceGeometryPass.qml b/scripts/developer/utilities/render/surfaceGeometryPass.qml
index 3f06e63719..1ff0efa15d 100644
--- a/scripts/developer/utilities/render/surfaceGeometryPass.qml
+++ b/scripts/developer/utilities/render/surfaceGeometryPass.qml
@@ -30,7 +30,6 @@ Column {
                 model: [
                     "Basis Scale:basisScale:2.0:false",
                     "Curvature Scale:curvatureScale:100.0:false",
-                    "Downscale:resolutionLevel:4:true"
                 ]
                 ConfigSlider {
                     label: qsTr(modelData.split(":")[0])
@@ -41,6 +40,11 @@ Column {
                     min: 0.0
                 }
             }
+            CheckBox {
+                    text: "Half Resolution"
+                    checked: Render.getConfig("SurfaceGeometry")["resolutionLevel"]
+                    onCheckedChanged: { Render.getConfig("SurfaceGeometry")["resolutionLevel"] = checked }
+            }
     
             Repeater {
                 model: [ "Diffusion Scale:SurfaceGeometry:diffuseFilterScale:2.0",

From 4742f40128235ac35815fcdb1ba4becfc92fac6f Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 12:23:57 -0700
Subject: [PATCH 23/26] Separating the normal packing into it s own file and
 make sure to sclae the filter radius correctly dpeending on the resolution of
 diffusion

---
 libraries/gpu/src/gpu/PackedNormal.slh        | 61 +++++++++++++++++++
 .../render-utils/src/DebugDeferredBuffer.cpp  |  2 +-
 .../src/DeferredLightingEffect.cpp            |  3 +-
 .../render-utils/src/SurfaceGeometryPass.cpp  | 15 ++++-
 libraries/render-utils/src/simple.slf         |  2 +-
 .../surfaceGeometry_downsampleDepthNormal.slf | 57 ++---------------
 libraries/render/src/render/BlurTask.slh      |  6 +-
 7 files changed, 86 insertions(+), 60 deletions(-)
 create mode 100644 libraries/gpu/src/gpu/PackedNormal.slh

diff --git a/libraries/gpu/src/gpu/PackedNormal.slh b/libraries/gpu/src/gpu/PackedNormal.slh
new file mode 100644
index 0000000000..ecb383fc30
--- /dev/null
+++ b/libraries/gpu/src/gpu/PackedNormal.slh
@@ -0,0 +1,61 @@
+<!
+//  PackedNormal.slh
+//  libraries/gpu/src
+//
+//  Created by Sam Gateau on 7/19/16.
+//  Copyright 2013 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+!>
+<@if not PACKED_NORMAL_SLH@>
+<@def PACKED_NORMAL_SLH@>
+
+vec2 signNotZero(vec2 v) {
+    return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
+}
+
+vec2 float32x3_to_oct(in vec3 v) {
+    vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
+    return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);
+}
+
+
+vec3 oct_to_float32x3(in vec2 e) {
+    vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+    if (v.z < 0) {
+        v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
+    }
+    return normalize(v);
+}
+
+vec3 snorm12x2_to_unorm8x3(vec2 f) {
+    vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));
+    float t = floor(u.y / 256.0);
+
+    return floor(vec3(
+        u.x / 16.0,
+        fract(u.x / 16.0) * 256.0 + t,
+        u.y - t * 256.0
+        )) / 255.0;
+}
+
+vec2 unorm8x3_to_snorm12x2(vec3 u) {
+    u *= 255.0;
+    u.y *= (1.0 / 16.0);
+    vec2 s = vec2(  u.x * 16.0 + floor(u.y),
+                    fract(u.y) * (16.0 * 256.0) + u.z);
+    return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));
+}
+
+
+// Recommended function to pack/unpack vec3<float> normals to vec3<uint8> rgb with best efficiency
+vec3 packNormal(in vec3 n) {
+    return snorm12x2_to_unorm8x3(float32x3_to_oct(n));
+}
+
+vec3 unpackNormal(in vec3 p) {
+    return oct_to_float32x3(unorm8x3_to_snorm12x2(p));
+}
+
+<@endif@>
diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp
index 672bb00cc8..9d0e38027e 100644
--- a/libraries/render-utils/src/DebugDeferredBuffer.cpp
+++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp
@@ -414,7 +414,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
         batch.setResourceTexture(HalfNormal, linearDepthTarget->getHalfNormalTexture());
 
         batch.setResourceTexture(Curvature, surfaceGeometryFramebuffer->getCurvatureTexture());
-        batch.setResourceTexture(DiffusedCurvature, diffusedCurvatureFramebuffer->getRenderBuffer(0));
+        batch.setResourceTexture(DiffusedCurvature, surfaceGeometryFramebuffer->getLowCurvatureTexture());
         if (DependencyManager::get<DeferredLightingEffect>()->isAmbientOcclusionEnabled()) {
             batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture());
         } else {
diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index 9d8c1ef200..6f202f6200 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -448,7 +448,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c
             batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, surfaceGeometryFramebuffer->getCurvatureTexture());
         }
         if (lowCurvatureNormalFramebuffer) {
-            batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, lowCurvatureNormalFramebuffer->getRenderBuffer(0));
+           // batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, lowCurvatureNormalFramebuffer->getRenderBuffer(0));
+            batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, surfaceGeometryFramebuffer->getLowCurvatureTexture());
         }
         if (subsurfaceScatteringResource) {
             batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, subsurfaceScatteringResource->getParametersBuffer());
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp
index 26063ba30c..fd778d30be 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.cpp
+++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp
@@ -367,9 +367,10 @@ SurfaceGeometryPass::SurfaceGeometryPass() :
 }
 
 void SurfaceGeometryPass::configure(const Config& config) {
+    const float CM_TO_M = 0.01f;
 
-    if ((config.depthThreshold * 100.0f) != getCurvatureDepthThreshold()) {
-        _parametersBuffer.edit<Parameters>().curvatureInfo.x = config.depthThreshold * 100.0f;
+    if ((config.depthThreshold * CM_TO_M) != getCurvatureDepthThreshold()) {
+        _parametersBuffer.edit<Parameters>().curvatureInfo.x = config.depthThreshold * CM_TO_M;
     }
 
     if (config.basisScale != getCurvatureBasisScale()) {
@@ -389,7 +390,8 @@ void SurfaceGeometryPass::configure(const Config& config) {
         _parametersBuffer.edit<Parameters>().resolutionInfo.w = config.resolutionLevel;
     }
 
-    _diffusePass.getParameters()->setFilterRadiusScale(config.diffuseFilterScale);
+    auto filterRadius = (getResolutionLevel() > 0 ? config.diffuseFilterScale / 2.0f : config.diffuseFilterScale);
+    _diffusePass.getParameters()->setFilterRadiusScale(filterRadius);
     _diffusePass.getParameters()->setDepthThreshold(config.diffuseDepthThreshold);
     
 }
@@ -445,6 +447,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
     auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
     auto diffuseHPipeline = _diffusePass.getBlurHPipeline();
 
+    _diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->_context->isStereo());
     glm::ivec2 textureSize(curvatureTexture->getDimensions());
     _diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport));
     _diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
@@ -475,6 +478,12 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
         batch.setResourceTexture(SurfaceGeometryPass_NormalMapSlot, normalTexture);
         batch.draw(gpu::TRIANGLE_STRIP, 4);
 
+
+        batch.setResourceTexture(SurfaceGeometryPass_DepthMapSlot, nullptr);
+        batch.setResourceTexture(SurfaceGeometryPass_NormalMapSlot, nullptr);
+        batch.setUniformBuffer(SurfaceGeometryPass_ParamsSlot, nullptr);
+        batch.setUniformBuffer(SurfaceGeometryPass_FrameTransformSlot, nullptr);
+
         // Diffusion pass
         const int BlurTask_ParamsSlot = 0;
         const int BlurTask_SourceSlot = 0;
diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf
index 4a16c1c46a..dd5faf40db 100644
--- a/libraries/render-utils/src/simple.slf
+++ b/libraries/render-utils/src/simple.slf
@@ -41,7 +41,7 @@ void main(void) {
 #ifdef PROCEDURAL_V1
     specular = getProceduralColor().rgb;
     // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
-    specular = pow(specular, vec3(2.2));
+    //specular = pow(specular, vec3(2.2));
     emissiveAmount = 1.0;
 #else 
     emissiveAmount = getProceduralColors(diffuse, specular, shininess);
diff --git a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
index af371d53a8..533073b224 100644
--- a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
+++ b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
@@ -10,35 +10,11 @@
 //
 
 
-
+<@include gpu/PackedNormal.slh@>
 
 uniform sampler2D linearDepthMap;
 uniform sampler2D normalMap;
 
-
-vec2 signNotZero(vec2 v) {
-    return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
-}
-
-vec3 oct_to_float32x3(in vec2 e) {
-    vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
-    if (v.z < 0) {
-        v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
-    }
-    return normalize(v);
-}
-
-vec2 unorm8x3_to_snorm12x2(vec3 u) {
-    u *= 255.0;
-    u.y *= (1.0 / 16.0);
-    vec2 s = vec2(  u.x * 16.0 + floor(u.y),
-    fract(u.y) * (16.0 * 256.0) + u.z);
-    return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));
-}
-vec3 unpackNormal(in vec3 p) {
-    return oct_to_float32x3(unorm8x3_to_snorm12x2(p));
-}
-
 in vec2 varTexCoord0;
 
 out vec4 outLinearDepth;
@@ -46,43 +22,22 @@ out vec4 outNormal;
 
 void main(void) {
     // Gather 2 by 2 quads from texture
-    vec4 Zeyes = textureGather(linearDepthMap, varTexCoord0, 0);
+
+    // Try different filters for Z
+//    vec4 Zeyes = textureGather(linearDepthMap, varTexCoord0, 0);
+  //  float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));
+    float Zeye = texture(linearDepthMap, varTexCoord0).x;
 
     vec4 rawNormalsX = textureGather(normalMap, varTexCoord0, 0);
     vec4 rawNormalsY = textureGather(normalMap, varTexCoord0, 1);
     vec4 rawNormalsZ = textureGather(normalMap, varTexCoord0, 2);
 
-    float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));
 
     vec3 normal = vec3(0.0);
     normal += unpackNormal(vec3(rawNormalsX[0], rawNormalsY[0], rawNormalsZ[0]));
     normal += unpackNormal(vec3(rawNormalsX[1], rawNormalsY[1], rawNormalsZ[1]));
     normal += unpackNormal(vec3(rawNormalsX[2], rawNormalsY[2], rawNormalsZ[2]));
     normal += unpackNormal(vec3(rawNormalsX[3], rawNormalsY[3], rawNormalsZ[3]));
-    /*
-    ivec2 texpos = ivec2(gl_FragCoord.xy) * 2;
-
-    vec4 Zeyes;
-    Zeyes[0] = texelFetch(linearDepthMap, texpos, 0).x;
-    Zeyes[1] = texelFetch(linearDepthMap, texpos + ivec2(0, 1), 0).x;
-    Zeyes[2] = texelFetch(linearDepthMap, texpos + ivec2(1, 0), 0).x;
-    Zeyes[3] = texelFetch(linearDepthMap, texpos + ivec2(1, 1), 0).x;
-
-    vec3 rawNormals[4];
-    rawNormals[0] = texelFetch(normalMap, texpos, 0).xyz;
-    rawNormals[1] = texelFetch(normalMap, texpos + ivec2(0, 1), 0).xyz;
-    rawNormals[2] = texelFetch(normalMap, texpos + ivec2(1, 0), 0).xyz;
-    rawNormals[3] = texelFetch(normalMap, texpos + ivec2(1, 1), 0).xyz;
-
-    float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));
-
-    vec3 normal = vec3(0.0);
-
-    normal += unpackNormal(rawNormals[0]);
-    normal += unpackNormal(rawNormals[1]);
-    normal += unpackNormal(rawNormals[2]);
-    normal += unpackNormal(rawNormals[3]);
-*/
 
     normal = normalize(normal);
 
diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh
index d40aca4a76..de2614eb51 100644
--- a/libraries/render/src/render/BlurTask.slh
+++ b/libraries/render/src/render/BlurTask.slh
@@ -126,7 +126,7 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep
     // Accumulate the center sample
     vec4 srcBlurred = gaussianDistributionCurve[0] * sampleCenter;
 
-/*     for(int i = 1; i < NUM_TAPS; i++) {
+     for(int i = 1; i < NUM_TAPS; i++) {
         // Fetch color and depth for current sample.
         vec2 sampleCoord = texcoord + (gaussianDistributionOffset[i] * finalStep);
         float srcDepth = texture(depthMap, sampleCoord).x;
@@ -139,8 +139,8 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep
         // Accumulate.
         srcBlurred += gaussianDistributionCurve[i] * srcSample;
     }   
-*/
 
+     /*
     for(int i = 1; i < NUM_HALF_TAPS; i++) {
         // Fetch color and depth for current sample.
         vec2 texcoordOffset = (gaussianDistributionOffsetHalf[i] * finalStep);
@@ -159,7 +159,7 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep
 
         // Accumulate.
         srcBlurred += gaussianDistributionCurveHalf[i] * (srcSampleP + srcSampleN);
-    }
+    }*/
     
     return srcBlurred;
 }

From 3e7126f5bea5a41601fe8b984832218843c20741 Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 13:06:26 -0700
Subject: [PATCH 24/26] Removed reference to LIghtingModel.slh in teh
 DefereedBufferWrite.slh to avoid side effects

---
 libraries/render-utils/src/DeferredBufferWrite.slh | 10 ++--------
 libraries/render-utils/src/LightingModel.slh       |  2 +-
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh
index 9adb7948df..3153a851fb 100755
--- a/libraries/render-utils/src/DeferredBufferWrite.slh
+++ b/libraries/render-utils/src/DeferredBufferWrite.slh
@@ -12,7 +12,6 @@
 <@def DEFERRED_BUFFER_WRITE_SLH@>
 
 <@include DeferredBuffer.slh@>
-<@include LightingModel.slh@>
 
 
 layout(location = 0) out vec4 _fragColor0;
@@ -40,7 +39,6 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness
     if (alpha != 1.0) {
         discard;
     }
-    emissive *= isEmissiveEnabled();
     _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));
     _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
     _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);
@@ -48,7 +46,6 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness
     _fragColor3 = vec4(emissive, 1.0);
 }
 
-
 void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {
     if (alpha != 1.0) {
         discard;
@@ -57,11 +54,8 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
     _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));
     _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
     _fragColor2 = vec4(lightmap, 1.0);
-    
-    _fragColor3 = vec4(lightmap * isLightmapEnabled(), 1.0);
-    if (isAlbedoEnabled() > 0.0) {
-        _fragColor3.rgb *= albedo;
-    }
+
+    _fragColor3 = vec4(lightmap * albedo, 1.0);
 }
 
 void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh
index c0722945bc..f36b2d8131 100644
--- a/libraries/render-utils/src/LightingModel.slh
+++ b/libraries/render-utils/src/LightingModel.slh
@@ -20,7 +20,7 @@ struct LightingModel {
     vec4 _ShowContourObscuranceSpare2;
 };
 
-uniform lightingModelBuffer {
+uniform lightingModelBuffer{
     LightingModel lightingModel;
 };
 

From 7f169b8e4f79bf3efc6e827517c9e7ae951b75fa Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 13:20:19 -0700
Subject: [PATCH 25/26] Adjust qml positions and fix one shader bug

---
 libraries/render-utils/src/model_unlit.slf                   | 1 +
 .../developer/utilities/render/debugSurfaceGeometryPass.js   | 5 ++---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf
index c64f9a07d7..750b51fe8c 100644
--- a/libraries/render-utils/src/model_unlit.slf
+++ b/libraries/render-utils/src/model_unlit.slf
@@ -13,6 +13,7 @@
 //
 
 <@include DeferredBufferWrite.slh@>
+<@include LightingModel.slh@>
 <@include model/Material.slh@>
 
 <@include MaterialTextures.slh@>
diff --git a/scripts/developer/utilities/render/debugSurfaceGeometryPass.js b/scripts/developer/utilities/render/debugSurfaceGeometryPass.js
index b28bb5269e..44df10e690 100644
--- a/scripts/developer/utilities/render/debugSurfaceGeometryPass.js
+++ b/scripts/developer/utilities/render/debugSurfaceGeometryPass.js
@@ -13,8 +13,7 @@ var qml = Script.resolvePath('surfaceGeometryPass.qml');
 var window = new OverlayWindow({
     title: 'Surface Geometry Pass',
     source: qml,
-    width: 400, height: 300,
+    width: 400, height: 170,
 });
-window.setPosition(250, 400);
+window.setPosition(Window.innerWidth - 420, 50 + 550 + 50);
 window.closed.connect(function() { Script.stop(); });
-

From 8f663f20e0c2cb30a867ad85894dbccef73261cd Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Tue, 19 Jul 2016 13:24:03 -0700
Subject: [PATCH 26/26] FIx warnings

---
 libraries/render-utils/src/DebugDeferredBuffer.cpp | 1 -
 libraries/render/src/render/BlurTask.h             | 4 +---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp
index 9d0e38027e..8118df5435 100644
--- a/libraries/render-utils/src/DebugDeferredBuffer.cpp
+++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp
@@ -379,7 +379,6 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
     auto& deferredFramebuffer = inputs.get0();
     auto& linearDepthTarget = inputs.get1();
     auto& surfaceGeometryFramebuffer = inputs.get2();
-    auto& diffusedCurvatureFramebuffer = inputs.get3();
 
     gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
         batch.enableStereo(false);
diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h
index f820947d98..a00a444af7 100644
--- a/libraries/render/src/render/BlurTask.h
+++ b/libraries/render/src/render/BlurTask.h
@@ -149,13 +149,11 @@ public:
     gpu::PipelinePointer getBlurHPipeline();
 
 protected:
-
-    BlurParamsPointer _parameters;
-
     gpu::PipelinePointer _blurVPipeline;
     gpu::PipelinePointer _blurHPipeline;
 
     BlurInOutResource _inOutResources;
+    BlurParamsPointer _parameters;
 };
 
 }