From 74ac4ae0ebc52ad76366bb688ba9c9635b26d6c2 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 18 Feb 2022 19:41:54 +0200
Subject: SL-16811 Shape preview images do not display all of the attachments.

---
 indra/newview/lltoolmorph.cpp |  13 +---
 indra/newview/pipeline.cpp    | 161 ++++++++++++++++++++++++++++++++++++++++++
 indra/newview/pipeline.h      |   1 +
 3 files changed, 164 insertions(+), 11 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index b2e8348ffd..b5eb2880ae 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -239,17 +239,8 @@ BOOL LLVisualParamHint::render()
 
 	LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
 
-	if (gAgentAvatarp->mDrawable.notNull() &&
-		gAgentAvatarp->mDrawable->getFace(0))
-	{
-		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool();
-		LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
-        gGL.flush();
-		gGL.setSceneBlendType(LLRender::BT_REPLACE);
-		avatarPoolp->renderAvatars(gAgentAvatarp);  // renders only one avatar
-		gGL.setSceneBlendType(LLRender::BT_ALPHA);
-        gGL.flush();
-	}
+    gPipeline.previewAvatar(gAgentAvatarp);
+
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
 	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
 	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index ac242c2bf7..5fe883b714 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -11133,6 +11133,167 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 	LLGLState::checkTextureChannels();
 }
 
+static LLTrace::BlockTimerStatHandle FTM_PREVIEW_AVATAR("Preview Avatar");
+
+void LLPipeline::previewAvatar(LLVOAvatar* avatar)
+{
+    LL_RECORD_BLOCK_TIME(FTM_PREVIEW_AVATAR);
+
+    LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+    gGL.flush();
+    gGL.setSceneBlendType(LLRender::BT_REPLACE);
+
+    LLGLState::checkStates();
+    LLGLState::checkTextureChannels();
+
+    static LLCullResult result;
+    result.clear();
+    grabReferences(result);
+
+    if (!avatar || !avatar->mDrawable)
+    {
+        LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL;
+        return;
+    }
+    LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL;
+
+    assertInitialized();
+
+    pushRenderTypeMask();
+
+    {
+        //hide world geometry
+        clearRenderTypeMask(
+            RENDER_TYPE_SKY,
+            RENDER_TYPE_WL_SKY,
+            RENDER_TYPE_GROUND,
+            RENDER_TYPE_TERRAIN,
+            RENDER_TYPE_GRASS,
+            RENDER_TYPE_CONTROL_AV, // Animesh
+            RENDER_TYPE_TREE,
+            RENDER_TYPE_VOIDWATER,
+            RENDER_TYPE_WATER,
+            RENDER_TYPE_PASS_GRASS,
+            RENDER_TYPE_HUD,
+            RENDER_TYPE_PARTICLES,
+            RENDER_TYPE_CLOUDS,
+            RENDER_TYPE_HUD_PARTICLES,
+            END_RENDER_TYPES
+        );
+    }
+
+    S32 occlusion = sUseOcclusion;
+    sUseOcclusion = 0;
+
+    sReflectionRender = !sRenderDeferred;
+
+    sShadowRender = true;
+    sImpostorRender = true; // Likely not needed for previews
+
+    LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
+
+    {
+        markVisible(avatar->mDrawable, *viewer_camera);
+
+        LLVOAvatar::attachment_map_t::iterator iter;
+        for (iter = avatar->mAttachmentPoints.begin();
+            iter != avatar->mAttachmentPoints.end();
+            ++iter)
+        {
+            LLViewerJointAttachment *attachment = iter->second;
+            for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+                attachment_iter != attachment->mAttachedObjects.end();
+                ++attachment_iter)
+            {
+                if (LLViewerObject* attached_object = attachment_iter->get())
+                {
+                    markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+                }
+            }
+        }
+    }
+
+    stateSort(*LLViewerCamera::getInstance(), result);
+
+    LLCamera camera = *viewer_camera;
+
+    F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
+
+    if (LLPipeline::sRenderDeferred)
+    {
+        renderGeomDeferred(camera);
+
+        renderGeomPostDeferred(camera);
+    }
+    else
+    {
+        renderGeom(camera);
+    }
+
+    LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
+
+    { //create alpha mask based on depth buffer
+        if (LLPipeline::sRenderDeferred)
+        {
+            GLuint buff = GL_COLOR_ATTACHMENT0;
+            LL_PROFILER_GPU_ZONEC("gl.DrawBuffersARB", 0x8000FF);
+            glDrawBuffersARB(1, &buff);
+        }
+
+        LLGLDisable blend(GL_BLEND);
+
+        gGL.setColorMask(false, true);
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+        LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
+
+        gGL.flush();
+
+        gGL.pushMatrix();
+        gGL.loadIdentity();
+        gGL.matrixMode(LLRender::MM_PROJECTION);
+        gGL.pushMatrix();
+        gGL.loadIdentity();
+
+        static const F32 clip_plane = 0.99999f;
+
+        gDebugProgram.bind();
+
+        gGL.begin(LLRender::QUADS);
+        gGL.vertex3f(-1, -1, clip_plane);
+        gGL.vertex3f(1, -1, clip_plane);
+        gGL.vertex3f(1, 1, clip_plane);
+        gGL.vertex3f(-1, 1, clip_plane);
+        gGL.end();
+        gGL.flush();
+
+        gDebugProgram.unbind();
+
+        gGL.popMatrix();
+        gGL.matrixMode(LLRender::MM_MODELVIEW);
+        gGL.popMatrix();
+    }
+
+    sUseOcclusion = occlusion;
+    sReflectionRender = false;
+    sImpostorRender = false;
+    sShadowRender = false;
+    popRenderTypeMask();
+
+    gGL.matrixMode(LLRender::MM_PROJECTION);
+    gGL.popMatrix();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.popMatrix();
+
+    LLVertexBuffer::unbind();
+    LLGLState::checkStates();
+    LLGLState::checkTextureChannels();
+
+    gGL.setSceneBlendType(LLRender::BT_ALPHA);
+    gGL.flush();
+}
+
 bool LLPipeline::hasRenderBatches(const U32 type) const
 {
 	return sCull->getRenderMapSize(type) > 0;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 6114aa4f6c..df5c060417 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -135,6 +135,7 @@ public:
 	
 	void resetVertexBuffers(LLDrawable* drawable);
 	void generateImpostor(LLVOAvatar* avatar);
+    void previewAvatar(LLVOAvatar* avatar);
 	void bindScreenToTexture();
 	void renderFinalize();
 
-- 
cgit v1.2.3