From 17049381e35541c226ff98c852ac6d257b07404a Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Mon, 25 Jan 2021 22:47:23 -0500
Subject: [PATCH] Replace usage of gluProject and gluUnproject

---
 indra/llmath/CMakeLists.txt      |   1 +
 indra/llmath/alglmath.h          | 135 +++++++++++++++++++++++++
 indra/llrender/llpostprocess.cpp |  42 ++++----
 indra/llrender/llrender.cpp      |  35 -------
 indra/llrender/llrender.h        |   2 -
 indra/newview/llface.cpp         |   3 +-
 indra/newview/llhudrender.cpp    |  28 ++----
 indra/newview/llviewercamera.cpp | 163 ++++++++++---------------------
 indra/newview/llviewerwindow.h   |   6 +-
 9 files changed, 225 insertions(+), 190 deletions(-)
 create mode 100644 indra/llmath/alglmath.h

diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index abd464f2d30..888c48f940a 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -51,6 +51,7 @@ set(llmath_SOURCE_FILES
 set(llmath_HEADER_FILES
     CMakeLists.txt
 
+    alglmath.h
     camera.h
     coordframe.h
     llbbox.h
diff --git a/indra/llmath/alglmath.h b/indra/llmath/alglmath.h
new file mode 100644
index 00000000000..0ad8cb30756
--- /dev/null
+++ b/indra/llmath/alglmath.h
@@ -0,0 +1,135 @@
+#pragma once
+
+#include "llmath.h"
+#include "llrect.h"
+#include "llvector4a.h"
+#include "llmatrix4a.h"
+
+namespace ALGLMath
+{
+	inline LLMatrix4a genRot(const float a, const LLVector4a& axis)
+	{
+		F32 r = a * DEG_TO_RAD;
+
+		F32 c = cosf(r);
+		F32 s = sinf(r);
+
+		F32 ic = 1.f - c;
+
+		const LLVector4a add1(c, axis[VZ] * s, -axis[VY] * s);	//1,z,-y
+		const LLVector4a add2(-axis[VZ] * s, c, axis[VX] * s);	//-z,1,x
+		const LLVector4a add3(axis[VY] * s, -axis[VX] * s, c);	//y,-x,1
+
+		LLVector4a axis_x;
+		axis_x.splat<0>(axis);
+		LLVector4a axis_y;
+		axis_y.splat<1>(axis);
+		LLVector4a axis_z;
+		axis_z.splat<2>(axis);
+
+		LLVector4a c_axis;
+		c_axis.setMul(axis, ic);
+
+		LLMatrix4a rot_mat;
+		rot_mat.getRow<0>().setMul(c_axis, axis_x);
+		rot_mat.getRow<0>().add(add1);
+		rot_mat.getRow<1>().setMul(c_axis, axis_y);
+		rot_mat.getRow<1>().add(add2);
+		rot_mat.getRow<2>().setMul(c_axis, axis_z);
+		rot_mat.getRow<2>().add(add3);
+		rot_mat.setRow<3>(LLVector4a(0, 0, 0, 1));
+
+		return rot_mat;
+	}
+
+	inline LLMatrix4a genRot(const float a, const float x, const float y, const float z) { return genRot(a, LLVector4a(x, y, z)); }
+
+	inline bool projectf(const LLVector3& object, const LLMatrix4a& modelview, const LLMatrix4a& projection, const LLRect& viewport, LLVector3& windowCoordinate)
+	{
+		//Begin SSE intrinsics
+
+		// Declare locals
+		const LLVector4a obj_vector(object.mV[VX], object.mV[VY], object.mV[VZ]);
+		const LLVector4a one(1.f);
+		LLVector4a temp_vec;								//Scratch vector
+		LLVector4a w;										//Splatted W-component.
+
+		modelview.affineTransform(obj_vector, temp_vec);	//temp_vec = modelview * obj_vector;
+
+		//Passing temp_matrix as v and res is safe. res not altered until after all other calculations
+		projection.rotate4(temp_vec, temp_vec);				//temp_vec = projection * temp_vec
+
+		w.splat<3>(temp_vec);								//w = temp_vec.wwww
+
+		//If w == 0.f, use 1.f instead.
+		LLVector4a div;
+		div.setSelectWithMask(w.equal(_mm_setzero_ps()), one, w);	//float div = (w[N] == 0.f ? 1.f : w[N]);
+		temp_vec.div(div);									//temp_vec /= div;
+
+		//Map x, y to range 0-1
+		temp_vec.mul(.5f);
+		temp_vec.add(.5f);
+
+		LLVector4Logical mask = temp_vec.equal(_mm_setzero_ps());
+		if (mask.areAllSet(LLVector4Logical::MASK_W))
+			return false;
+
+		//End SSE intrinsics
+
+		//Window coordinates
+		windowCoordinate[0] = temp_vec[VX] * viewport.getWidth() + viewport.mLeft;
+		windowCoordinate[1] = temp_vec[VY] * viewport.getHeight() + viewport.mBottom;
+		//This is only correct when glDepthRange(0.0, 1.0)
+		windowCoordinate[2] = temp_vec[VZ];
+
+		return true;
+	}
+
+	inline bool unprojectf(const LLVector3& windowCoordinate, const LLMatrix4a& modelview, const LLMatrix4a& projection, const LLRect& viewport, LLVector3& object)
+	{
+		//Begin SSE intrinsics
+
+		// Declare locals
+		static const LLVector4a one(1.f);
+		static const LLVector4a two(2.f);
+		LLVector4a norm_view(
+			((windowCoordinate.mV[VX] - (F32)viewport.mLeft) / (F32)viewport.getWidth()),
+			((windowCoordinate.mV[VY] - (F32)viewport.mBottom) / (F32)viewport.getHeight()),
+			windowCoordinate.mV[VZ],
+			1.f);
+
+		LLMatrix4a inv_mat;								//Inverse transformation matrix
+		LLVector4a temp_vec;							//Scratch vector
+		LLVector4a w;									//Splatted W-component.
+
+		inv_mat.setMul(projection, modelview);			//inv_mat = projection*modelview
+
+		float det = inv_mat.invert();
+
+		//Normalize. -1.0 : +1.0
+		norm_view.mul(two);								// norm_view *= vec4(.2f)
+		norm_view.sub(one);								// norm_view -= vec4(1.f)
+
+		inv_mat.rotate4(norm_view, temp_vec);			//inv_mat * norm_view
+
+		w.splat<3>(temp_vec);							//w = temp_vec.wwww
+
+		//If w == 0.f, use 1.f instead. Defer return if temp_vec.w == 0.f until after all SSE intrinsics.
+		LLVector4a div;
+		div.setSelectWithMask(w.equal(_mm_setzero_ps()), one, w);	//float div = (w[N] == 0.f ? 1.f : w[N]);
+		temp_vec.div(div);								//temp_vec /= div;
+
+		LLVector4Logical mask = temp_vec.equal(_mm_setzero_ps());
+		if (mask.areAllSet(LLVector4Logical::MASK_W))
+			return false;
+
+		//End SSE intrinsics
+
+		if (det == 0.f)
+			return false;
+
+		object.set(temp_vec.getF32ptr());
+
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index f00fdc06671..de0b2c8b44b 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -531,28 +531,28 @@ void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
 
 bool LLPostProcess::checkError(void)
 {
-	GLenum glErr;
+//	GLenum glErr;
     bool    retCode = false;
 
-    glErr = glGetError();
-    while (glErr != GL_NO_ERROR)
-    {
-		// shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
-		char const * err_str_raw = (const char *) gluErrorString(glErr);
-
-		if(err_str_raw == NULL)
-		{
-			std::ostringstream err_builder;
-			err_builder << "unknown error number " << glErr;
-			mShaderErrorString = err_builder.str();
-		}
-		else
-		{
-			mShaderErrorString = err_str_raw;
-		}
-
-        retCode = true;
-        glErr = glGetError();
-    }
+  //  glErr = glGetError();
+  //  while (glErr != GL_NO_ERROR)
+  //  {
+		//// shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
+		//char const * err_str_raw = (const char *) gluErrorString(glErr);
+
+		//if(err_str_raw == NULL)
+		//{
+		//	std::ostringstream err_builder;
+		//	err_builder << "unknown error number " << glErr;
+		//	mShaderErrorString = err_builder.str();
+		//}
+		//else
+		//{
+		//	mShaderErrorString = err_str_raw;
+		//}
+
+  //      retCode = true;
+  //      glErr = glGetError();
+  //  }
     return retCode;
 }
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index cd4d8f62fe1..22e3a71f9ed 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1423,41 +1423,6 @@ void LLRender::syncMatrices()
 	stop_glerror();
 }
 
-LLMatrix4a LLRender::genRot(const GLfloat& a, const LLVector4a& axis) const
-{
-	F32 r = a * DEG_TO_RAD;
-
-	F32 c = cosf(r);
-	F32 s = sinf(r);
-
-	F32 ic = 1.f-c;
-
-	const LLVector4a add1(c,axis[VZ]*s,-axis[VY]*s);	//1,z,-y
-	const LLVector4a add2(-axis[VZ]*s,c,axis[VX]*s);	//-z,1,x
-	const LLVector4a add3(axis[VY]*s,-axis[VX]*s,c);	//y,-x,1
-
-	LLVector4a axis_x;
-	axis_x.splat<0>(axis);
-	LLVector4a axis_y;
-	axis_y.splat<1>(axis);
-	LLVector4a axis_z;
-	axis_z.splat<2>(axis);
-
-	LLVector4a c_axis;
-	c_axis.setMul(axis,ic);
-
-	LLMatrix4a rot_mat;
-	rot_mat.getRow<0>().setMul(c_axis,axis_x);
-	rot_mat.getRow<0>().add(add1);
-	rot_mat.getRow<1>().setMul(c_axis,axis_y);
-	rot_mat.getRow<1>().add(add2);
-	rot_mat.getRow<2>().setMul(c_axis,axis_z);
-	rot_mat.getRow<2>().add(add3);
-	rot_mat.setRow<3>(LLVector4a(0,0,0,1));
-
-	return rot_mat;
-}
-
 void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
 {
 	flush();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 00e5b8e9bb1..0a966932d8a 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -376,8 +376,6 @@ class LLRender
 	// Needed when the render context has changed and invalidated the current state
 	void refreshState(void);
 
-	LLMatrix4a genRot(const GLfloat& a, const LLVector4a& axis) const;
-	LLMatrix4a genRot(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z) const { return genRot(a,LLVector4a(x,y,z)); }
 	void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
 	void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
 	void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 75233e85312..2fdde73749e 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -59,6 +59,7 @@
 // [RLVa:KB] - Checked: RLVa-2.0.0
 #include "rlvhandler.h"
 // [/RLVa:KB]
+#include "alglmath.h"
 
 #if LL_LINUX
 // Work-around spurious used before init warning on Vector4a
@@ -2007,7 +2008,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				LLVector4a tangent_out = *src;
 				if (rotate_tangent && src2 < end2)
 				{
-					gGL.genRot(rot, *src2++).rotate(tangent_out, tangent_out);
+					ALGLMath::genRot(rot, *src2++).rotate(tangent_out, tangent_out);
 				}
 				mat_tan.rotate(tangent_out, tangent_out);
 				tangent_out.normalize3fast();
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index dff310ecf93..5a7257012c2 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -37,6 +37,7 @@
 #include "llglheaders.h"
 #include "llviewerwindow.h"
 #include "llui.h"
+#include "alglmath.h"
 
 void hud_render_utf8text(const std::string &str, const LLVector3 &pos_agent,
 					 const LLFontGL &font,
@@ -99,27 +100,18 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
 	LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis);
 
 	//get the render_pos in screen space
-	
-	F64 winX, winY, winZ;
-	LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
-	S32	viewport[4];
-	viewport[0] = world_view_rect.mLeft;
-	viewport[1] = world_view_rect.mBottom;
-	viewport[2] = world_view_rect.getWidth();
-	viewport[3] = world_view_rect.getHeight();
+	LLMatrix4a modelview, projection;
+	modelview.loadu(gGLModelView);
+	projection.loadu(gGLProjection);
 
-	F64 mdlv[16];
-	F64 proj[16];
+	LLVector3 window_coordinates;
+	F32& winX = window_coordinates.mV[VX];
+	F32& winY = window_coordinates.mV[VY];
+	F32& winZ = window_coordinates.mV[VZ];
 
-	for (U32 i = 0; i < 16; i++)
-	{
-		mdlv[i] = (F64) gGLModelView[i];
-		proj[i] = (F64) gGLProjection[i];
-	}
+	const LLRect& world_view_rect = gViewerWindow->getWorldViewRectRaw();
 
-	gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2],
-				mdlv, proj, (GLint*) viewport,
-				&winX, &winY, &winZ);
+	ALGLMath::projectf(render_pos, modelview, projection, world_view_rect, window_coordinates);
 		
 	//fonts all render orthographically, set up projection``
 	gGL.matrixMode(LLRender::MM_PROJECTION);
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 791023eca9b..c486e40d612 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -46,6 +46,7 @@
 // [/RLVa:KB]
 
 // Linden library includes
+#include "alglmath.h"
 #include "lldrawable.h"
 #include "llface.h"
 #include "llgl.h"
@@ -198,59 +199,37 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const
 //static
 void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks)
 {
-	GLint* viewport = (GLint*) gGLViewport;
-	F64 model[16];
-	F64 proj[16];
-
-	for (U32 i = 0; i < 16; i++)
-	{
-		model[i] = (F64) gGLModelView[i];
-		proj[i] = (F64) gGLProjection[i];
-	}
+	LLVector3 frust[8];
 
-	GLdouble objX,objY,objZ;
+	LLMatrix4a modelview, projection;
+	modelview.loadu(gGLModelView);
+	projection.loadu(gGLProjection);
 
-	LLVector3 frust[8];
+	LLRect view_port(gGLViewport[0], gGLViewport[1] + gGLViewport[3], gGLViewport[0] + gGLViewport[2], gGLViewport[1]);
 
 	if (no_hacks)
 	{
-		gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
-
-		gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[4].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[5].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[6].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f), modelview, projection, view_port, frust[0]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f), modelview, projection, view_port, frust[1]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f), modelview, projection, view_port, frust[2]);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f), modelview, projection, view_port, frust[3]);
+
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 1.f), modelview, projection, view_port, frust[4]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 1.f), modelview, projection, view_port, frust[5]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mTop, 1.f), modelview, projection, view_port, frust[6]);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 1.f), modelview, projection, view_port, frust[7]);
 	}
 	else if (zflip)
 	{
-		gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
-
-		gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[4].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[5].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[6].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
-		frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f), modelview, projection, view_port, frust[0]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f), modelview, projection, view_port, frust[1]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f), modelview, projection, view_port, frust[2]);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f), modelview, projection, view_port, frust[3]);
+
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 1.f), modelview, projection, view_port, frust[4]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mTop, 1.f), modelview, projection, view_port, frust[5]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 1.f), modelview, projection, view_port, frust[6]);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 1.f), modelview, projection, view_port, frust[7]);
 
 		for (U32 i = 0; i < 4; i++)
 		{
@@ -261,14 +240,10 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli
 	}
 	else
 	{
-		gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
-		gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
-		frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mBottom, 0.f), modelview, projection, view_port, frust[0]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mBottom, 0.f), modelview, projection, view_port, frust[1]);
+		ALGLMath::unprojectf(LLVector3(view_port.mRight, view_port.mTop, 0.f), modelview, projection, view_port, frust[2]);
+		ALGLMath::unprojectf(LLVector3(view_port.mLeft, view_port.mTop, 0.f), modelview, projection, view_port, frust[3]);
 		
 		if (ortho)
 		{
@@ -412,10 +387,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
 	if (!for_selection && mZoomFactor == 1.f)
 	{
 		// Save GL matrices for access elsewhere in code, especially project_world_to_screen
-		for (U32 i = 0; i < 16; i++)
-		{
-			gGLModelView[i] = modelview.m[i];
-		}
+		set_current_modelview(modelview);
 	}
 
 	updateFrustumPlanes(*this);
@@ -426,24 +398,14 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
 // screen coordinates to the agent's region.
 void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 screen_y, LLVector3* pos_agent) const
 {
-	GLdouble x, y, z;
-
-	F64 mdlv[16];
-	F64 proj[16];
-
-	for (U32 i = 0; i < 16; i++)
-	{
-		mdlv[i] = (F64) gGLModelView[i];
-		proj[i] = (F64) gGLProjection[i];
-	}
-
-	gluUnProject(
-		GLdouble(screen_x), GLdouble(screen_y), 0.0,
-		mdlv, proj, (GLint*)gGLViewport,
-		&x,
-		&y,
-		&z );
-	pos_agent->setVec( (F32)x, (F32)y, (F32)z );
+	LLMatrix4a modelview, projection;
+	modelview.loadu(gGLModelView);
+	projection.loadu(gGLProjection);
+
+	ALGLMath::unprojectf(
+		LLVector3(screen_x, screen_y, 0.f), modelview, projection, 
+		LLRect(gGLViewport[0], gGLViewport[1] + gGLViewport[3], gGLViewport[0] + gGLViewport[2], gGLViewport[1]),
+		*pos_agent);
 }
 
 // Uses the last GL matrices set in set_perspective to project a point from
@@ -452,7 +414,7 @@ void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 scree
 BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp) const
 {
 	BOOL in_front = TRUE;
-	GLdouble	x, y, z;			// object's window coords, GL-style
+	LLVector3 window_coordinates;
 
 	LLVector3 dir_to_point = pos_agent - getOrigin();
 	dir_to_point /= dir_to_point.magVec();
@@ -469,26 +431,17 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
 		}
 	}
 
-	LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
-	S32	viewport[4];
-	viewport[0] = world_view_rect.mLeft;
-	viewport[1] = world_view_rect.mBottom;
-	viewport[2] = world_view_rect.getWidth();
-	viewport[3] = world_view_rect.getHeight();
+	LLMatrix4a modelview, projection;
+	modelview.loadu(gGLModelView);
+	projection.loadu(gGLProjection);
 
-	F64 mdlv[16];
-	F64 proj[16];
+	const LLRect& world_view_rect = gViewerWindow->getWorldViewRectRaw();
 
-	for (U32 i = 0; i < 16; i++)
+	if (ALGLMath::projectf(pos_agent, modelview, projection, world_view_rect, window_coordinates))
 	{
-		mdlv[i] = (F64) gGLModelView[i];
-		proj[i] = (F64) gGLProjection[i];
-	}
+		F32 &x = window_coordinates.mV[VX];
+		F32 &y = window_coordinates.mV[VY];
 
-	if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
-								mdlv, proj, (GLint*)viewport,
-								&x, &y, &z))
-	{
 		// convert screen coordinates to virtual UI coordinates
 		x /= gViewerWindow->getDisplayScale().mV[VX];
 		y /= gViewerWindow->getDisplayScale().mV[VY];
@@ -581,28 +534,18 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
 		in_front = FALSE;
 	}
 
-	LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
-	S32	viewport[4];
-	viewport[0] = world_view_rect.mLeft;
-	viewport[1] = world_view_rect.mBottom;
-	viewport[2] = world_view_rect.getWidth();
-	viewport[3] = world_view_rect.getHeight();
-	GLdouble	x, y, z;			// object's window coords, GL-style
+	LLMatrix4a modelview, projection;
+	modelview.loadu(gGLModelView);
+	projection.loadu(gGLProjection);
 
-	F64 mdlv[16];
-	F64 proj[16];
+	const LLRect& world_view_rect = gViewerWindow->getWorldViewRectRaw();
+	LLVector3 window_coordinates;
 
-	for (U32 i = 0; i < 16; i++)
+	if (ALGLMath::projectf(pos_agent, modelview, projection, world_view_rect, window_coordinates))
 	{
-		mdlv[i] = (F64) gGLModelView[i];
-		proj[i] = (F64) gGLProjection[i];
-	}
+		F32 &x = window_coordinates.mV[VX];
+		F32 &y = window_coordinates.mV[VY];
 
-	if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
-							  pos_agent.mV[VZ], mdlv,
-							  proj, (GLint*)viewport,
-							  &x, &y, &z))
-	{
 		x /= gViewerWindow->getDisplayScale().mV[VX];
 		y /= gViewerWindow->getDisplayScale().mV[VY];
 		// should now have the x,y coords of grab_point in screen space
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 6e8614e5168..dececd63944 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -240,17 +240,17 @@ class LLViewerWindow final : public LLWindowCallbacks
 	S32				getWorldViewWidthScaled() const;
 
 	// 3D world area, in raw unscaled pixels
-	LLRect			getWorldViewRectRaw() const		{ return mWorldViewRectRaw; }
+	const LLRect&   getWorldViewRectRaw() const		{ return mWorldViewRectRaw; }
 	S32 			getWorldViewHeightRaw() const;
 	S32 			getWorldViewWidthRaw() const;
 
 	// Window in scaled pixels (via UI scale), use for most UI computations
-	LLRect			getWindowRectScaled() const		{ return mWindowRectScaled; }
+	const LLRect&   getWindowRectScaled() const		{ return mWindowRectScaled; }
 	S32				getWindowHeightScaled() const;
 	S32				getWindowWidthScaled() const;
 
 	// Window in raw pixels as seen on screen.
-	LLRect			getWindowRectRaw() const		{ return mWindowRectRaw; }
+	const LLRect&   getWindowRectRaw() const		{ return mWindowRectRaw; }
 	S32				getWindowHeightRaw() const;
 	S32				getWindowWidthRaw() const;
 
-- 
GitLab