summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llrender/llcubemap.cpp6
-rw-r--r--indra/llrender/llrender.cpp252
-rw-r--r--indra/llrender/llrender.h10
-rw-r--r--indra/newview/llhudrender.cpp12
-rw-r--r--indra/newview/llselectmgr.cpp2
-rw-r--r--indra/newview/llviewercamera.cpp58
-rw-r--r--indra/newview/pipeline.cpp28
-rw-r--r--indra/newview/pipeline.h2
8 files changed, 213 insertions, 157 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index a75f01c708..45a3b18179 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -265,9 +265,9 @@ void LLCubeMap::setMatrix(S32 stage)
gGL.getTexUnit(stage)->activate();
}
- LLVector3 x(LLVector3d(gGLModelView+0));
- LLVector3 y(LLVector3d(gGLModelView+4));
- LLVector3 z(LLVector3d(gGLModelView+8));
+ LLVector3 x(gGLModelView+0);
+ LLVector3 y(gGLModelView+4);
+ LLVector3 z(gGLModelView+8);
LLMatrix3 mat3;
mat3.setRows(x,y,z);
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 942ad87566..c5a6859016 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -38,10 +38,10 @@
LLRender gGL;
// Handy copies of last good GL matrices
-F64 gGLModelView[16];
-F64 gGLLastModelView[16];
-F64 gGLLastProjection[16];
-F64 gGLProjection[16];
+F32 gGLModelView[16];
+F32 gGLLastModelView[16];
+F32 gGLLastProjection[16];
+F32 gGLProjection[16];
S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
@@ -1163,41 +1163,41 @@ void LLRender::syncMatrices()
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ static glh::matrix4f cached_mvp;
+ static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
+ static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
+
+ static glh::matrix4f cached_normal;
+ static U32 cached_normal_hash = 0xFFFFFFFF;
+
if (shader)
{
-
llassert(shader);
bool do_normal = false;
- bool do_mvp = false;
+ bool do_mvp = false;
- for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
- {
- if (mMatHash[i] != shader->mMatHash[i])
- {
- shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m);
- shader->mMatHash[i] = mMatHash[i];
+ bool mvp_done = false;
- if (i == MM_MODELVIEW)
- {
- do_normal = true;
- do_mvp = true;
- }
- else if (i == MM_PROJECTION)
- {
- do_mvp = true;
- }
- }
- }
+ U32 i = MM_MODELVIEW;
+ if (mMatHash[i] != shader->mMatHash[i])
+ { //update modelview, normal, and MVP
+ glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
- if (do_normal)
- {
+ shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
+ shader->mMatHash[i] = mMatHash[i];
+
+ //update normal matrix
S32 loc = shader->getUniformLocation("normal_matrix");
if (loc > -1)
{
- U32 i = MM_MODELVIEW;
+ if (cached_normal_hash != mMatHash[i])
+ {
+ cached_normal = mat.inverse().transpose();
+ cached_normal_hash = mMatHash[i];
+ }
- glh::matrix4f norm = mMatrix[i][mMatIdx[i]].inverse().transpose();
+ glh::matrix4f& norm = cached_normal;
F32 norm_mat[] =
{
@@ -1208,23 +1208,65 @@ void LLRender::syncMatrices()
shader->uniformMatrix3fv("normal_matrix", 1, GL_FALSE, norm_mat);
}
- }
- if (do_mvp)
- {
- S32 loc = shader->getUniformLocation("modelview_projection_matrix");
+ //update MVP matrix
+ mvp_done = true;
+ loc = shader->getUniformLocation("modelview_projection_matrix");
if (loc > -1)
{
- U32 mv = MM_MODELVIEW;
U32 proj = MM_PROJECTION;
- glh::matrix4f mvp = mMatrix[mv][mMatIdx[mv]];
- mvp.mult_left(mMatrix[proj][mMatIdx[proj]]);
-
- shader->uniformMatrix4fv("modelview_projection_matrix", 1, GL_FALSE, mvp.m);
+ if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
+ {
+ cached_mvp = mat;
+ cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]);
+ cached_mvp_mdv_hash = mMatHash[i];
+ cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
+ }
+
+ shader->uniformMatrix4fv("modelview_projection_matrix", 1, GL_FALSE, cached_mvp.m);
+ }
+ }
+
+
+ i = MM_PROJECTION;
+ if (mMatHash[i] != shader->mMatHash[i])
+ { //update projection matrix, normal, and MVP
+ glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
+
+ shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
+ shader->mMatHash[i] = mMatHash[i];
+
+ if (!mvp_done)
+ {
+ //update MVP matrix
+ S32 loc = shader->getUniformLocation("modelview_projection_matrix");
+ if (loc > -1)
+ {
+ if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
+ {
+ U32 mdv = MM_MODELVIEW;
+ cached_mvp = mat;
+ cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]);
+ cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW];
+ cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
+ }
+
+ shader->uniformMatrix4fv("modelview_projection_matrix", 1, GL_FALSE, cached_mvp.m);
+ }
}
}
+ for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
+ {
+ if (mMatHash[i] != shader->mMatHash[i])
+ {
+ shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m);
+ shader->mMatHash[i] = mMatHash[i];
+ }
+ }
+
+
if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting)
{ //also sync light state
syncLightState();
@@ -1261,116 +1303,121 @@ void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
- glh::matrix4f trans_mat(1,0,0,x,
- 0,1,0,y,
- 0,0,1,z,
- 0,0,0,1);
+ {
+ glh::matrix4f trans_mat(1,0,0,x,
+ 0,1,0,y,
+ 0,0,1,z,
+ 0,0,0,1);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat);
- mMatHash[mMatrixMode]++;
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
- glh::matrix4f scale_mat(x,0,0,0,
- 0,y,0,0,
- 0,0,z,0,
- 0,0,0,1);
+ {
+ glh::matrix4f scale_mat(x,0,0,0,
+ 0,y,0,0,
+ 0,0,z,0,
+ 0,0,0,1);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat);
- mMatHash[mMatrixMode]++;
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar)
{
flush();
- glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left),
- 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom),
- 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
- 0,0,0,1);
+ {
+
+ glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left),
+ 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom),
+ 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
+ 0,0,0,1);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
- mMatHash[mMatrixMode]++;
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
-
- F32 r = a * DEG_TO_RAD;
- F32 c = cosf(r);
- F32 s = sinf(r);
+ {
+ F32 r = a * DEG_TO_RAD;
+
+ F32 c = cosf(r);
+ F32 s = sinf(r);
- F32 ic = 1.f-c;
+ F32 ic = 1.f-c;
- glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0,
- x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0,
- x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0,
- 0,0,0,1);
+ glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0,
+ x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0,
+ x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0,
+ 0,0,0,1);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
- mMatHash[mMatrixMode]++;
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::pushMatrix()
{
flush();
- if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
{
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
- ++mMatIdx[mMatrixMode];
- }
- else
- {
- llwarns << "Matrix stack overflow." << llendl;
+ if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
+ {
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
+ ++mMatIdx[mMatrixMode];
+ }
+ else
+ {
+ llwarns << "Matrix stack overflow." << llendl;
+ }
}
}
void LLRender::popMatrix()
{
flush();
- if (mMatIdx[mMatrixMode] > 0)
- {
- --mMatIdx[mMatrixMode];
- mMatHash[mMatrixMode]++;
- }
- else
{
- llwarns << "Matrix stack underflow." << llendl;
+ if (mMatIdx[mMatrixMode] > 0)
+ {
+ --mMatIdx[mMatrixMode];
+ mMatHash[mMatrixMode]++;
+ }
+ else
+ {
+ llwarns << "Matrix stack underflow." << llendl;
+ }
}
}
void LLRender::loadMatrix(const GLfloat* m)
{
flush();
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m);
- mMatHash[mMatrixMode]++;
-}
-
-void LLRender::loadMatrix(const GLdouble* dm)
-{
- F32 m[16];
- for (U32 i = 0; i < 16; i++)
{
- m[i] = (F32) dm[i];
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m);
+ mMatHash[mMatrixMode]++;
}
-
- loadMatrix(m);
}
void LLRender::multMatrix(const GLfloat* m)
{
flush();
-
- glh::matrix4f mat((GLfloat*) m);
+ {
+ glh::matrix4f mat((GLfloat*) m);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat);
- mMatHash[mMatrixMode]++;
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::matrixMode(U32 mode)
@@ -1384,23 +1431,14 @@ void LLRender::matrixMode(U32 mode)
mMatrixMode = mode;
}
-void LLRender::multMatrix(const GLdouble* dm)
-{
- F32 m[16];
- for (U32 i = 0; i < 16; i++)
- {
- m[i] = (F32) dm[i];
- }
-
- multMatrix(m);
-}
-
void LLRender::loadIdentity()
{
flush();
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
- mMatHash[mMatrixMode]++;
+ {
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
+ mMatHash[mMatrixMode]++;
+ }
}
const glh::matrix4f& LLRender::getModelviewMatrix()
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 61e503d384..7581b9f908 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -343,10 +343,8 @@ public:
void pushMatrix();
void popMatrix();
void loadMatrix(const GLfloat* m);
- void loadMatrix(const GLdouble* m);
void loadIdentity();
void multMatrix(const GLfloat* m);
- void multMatrix(const GLdouble* m);
void matrixMode(U32 mode);
const glh::matrix4f& getModelviewMatrix();
@@ -470,10 +468,10 @@ private:
};
-extern F64 gGLModelView[16];
-extern F64 gGLLastModelView[16];
-extern F64 gGLLastProjection[16];
-extern F64 gGLProjection[16];
+extern F32 gGLModelView[16];
+extern F32 gGLLastModelView[16];
+extern F32 gGLLastProjection[16];
+extern F32 gGLProjection[16];
extern S32 gGLViewport[4];
extern LLRender gGL;
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index 607f7f7f4b..122711a86d 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -107,8 +107,18 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
viewport[1] = world_view_rect.mBottom;
viewport[2] = world_view_rect.getWidth();
viewport[3] = world_view_rect.getHeight();
+
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2],
- gGLModelView, gGLProjection, (GLint*) viewport,
+ mdlv, proj, (GLint*) viewport,
&winX, &winY, &winZ);
//fonts all render orthographically, set up projection``
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 3a50eeb1c9..2971ee710a 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -4838,7 +4838,7 @@ void LLSelectMgr::processForceObjectSelect(LLMessageSystem* msg, void**)
LLSelectMgr::getInstance()->highlightObjectAndFamily(objects);
}
-extern LLGLdouble gGLModelView[16];
+extern F32 gGLModelView[16];
void LLSelectMgr::updateSilhouettes()
{
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index c0ef4da1ff..a437a8b3b5 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -218,8 +218,15 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const
void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks)
{
GLint* viewport = (GLint*) gGLViewport;
- GLdouble* model = gGLModelView;
- GLdouble* proj = gGLProjection;
+ F64 model[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ model[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
GLdouble objX,objY,objZ;
LLVector3 frust[8];
@@ -420,7 +427,6 @@ 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
- //glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView);
for (U32 i = 0; i < 16; i++)
{
gGLModelView[i] = modelview.m[i];
@@ -428,14 +434,6 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
}
updateFrustumPlanes(*this);
-
- /*if (gSavedSettings.getBOOL("CameraOffset"))
- {
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.translatef(0,0,-50);
- gGL.rotatef(20.0,1,0,0);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }*/
}
@@ -443,11 +441,20 @@ 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,
- gGLModelView, gGLProjection, (GLint*)gGLViewport,
+ mdlv, proj, (GLint*)gGLViewport,
&x,
&y,
&z );
@@ -484,8 +491,17 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
viewport[2] = world_view_rect.getWidth();
viewport[3] = world_view_rect.getHeight();
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
- gGLModelView, gGLProjection, (GLint*)viewport,
+ mdlv, proj, (GLint*)viewport,
&x, &y, &z))
{
// convert screen coordinates to virtual UI coordinates
@@ -587,9 +603,19 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
viewport[2] = world_view_rect.getWidth();
viewport[3] = world_view_rect.getHeight();
GLdouble x, y, z; // object's window coords, GL-style
+
+ F64 mdlv[16];
+ F64 proj[16];
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ mdlv[i] = (F64) gGLModelView[i];
+ proj[i] = (F64) gGLProjection[i];
+ }
+
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
- pos_agent.mV[VZ], gGLModelView,
- gGLProjection, (GLint*)viewport,
+ pos_agent.mV[VZ], mdlv,
+ proj, (GLint*)viewport,
&x, &y, &z))
{
x /= gViewerWindow->getDisplayScale().mV[VX];
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index d28bb1f64e..42873dbca8 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -201,13 +201,10 @@ U32 nhpo2(U32 v)
return r;
}
-glh::matrix4f glh_copy_matrix(GLdouble* src)
+glh::matrix4f glh_copy_matrix(F32* src)
{
glh::matrix4f ret;
- for (U32 i = 0; i < 16; i++)
- {
- ret.m[i] = (F32) src[i];
- }
+ ret.set_value(src);
return ret;
}
@@ -231,7 +228,7 @@ glh::matrix4f glh_get_last_projection()
return glh_copy_matrix(gGLLastProjection);
}
-void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
+void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
{
for (U32 i = 0; i < 16; i++)
{
@@ -3171,19 +3168,6 @@ void LLPipeline::postSort(LLCamera& camera)
if (!sShadowRender)
{
- //sort by texture or bump map
- for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
- {
- if (i == LLRenderPass::PASS_BUMP)
- {
- std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
- }
- else
- {
- std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
- }
- }
-
std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
}
llpushcallstacks ;
@@ -3503,8 +3487,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
assertInitialized();
- F64 saved_modelview[16];
- F64 saved_projection[16];
+ F32 saved_modelview[16];
+ F32 saved_projection[16];
//HACK: preserve/restore matrices around HUD render
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
@@ -6768,7 +6752,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
{
cube_map->enable(channel);
cube_map->bind();
- F64* m = gGLModelView;
+ F32* m = gGLModelView;
F32 mat[] = { m[0], m[1], m[2],
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index d24bab747b..86579261ca 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -72,7 +72,7 @@ BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn
bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0);
BOOL setup_hud_matrices(); // use whole screen to render hud
BOOL setup_hud_matrices(const LLRect& screen_region); // specify portion of screen (in pixels) to render hud attachments from (for picking)
-glh::matrix4f glh_copy_matrix(GLdouble* src);
+glh::matrix4f glh_copy_matrix(F32* src);
glh::matrix4f glh_get_current_modelview();
void glh_set_current_modelview(const glh::matrix4f& mat);
glh::matrix4f glh_get_current_projection();