BGE: Setting up the RAS_ICanvas interface as the primary way to alter the OpenGL

viewport. This helps to eliminate OpenGL calls in weird places like the physics
code and to reduce glGet calls, which are expensive.

There should be no functional changes (except maybe a very slight speed improvement).
This commit is contained in:
Mitchell Stokes
2012-10-08 03:28:11 +00:00
parent aa1e50be94
commit 244ce92dbd
15 changed files with 88 additions and 30 deletions

View File

@@ -33,6 +33,7 @@
#include "KX_BlenderCanvas.h"
#include "DNA_screen_types.h"
#include <stdio.h>
#include <assert.h>
KX_BlenderCanvas::KX_BlenderCanvas(struct wmWindow *win, RAS_Rect &rect, struct ARegion *ar) :
@@ -44,6 +45,8 @@ m_frame_rect(rect)
// area boundaries needed for mouse coordinates in Letterbox framing mode
m_area_left = ar->winrct.xmin;
m_area_top = ar->winrct.ymax;
glGetIntegerv(GL_VIEWPORT, (GLint*)m_viewport);
}
KX_BlenderCanvas::~KX_BlenderCanvas()
@@ -166,10 +169,31 @@ SetViewPort(
m_area_rect.SetRight(minx + x2);
m_area_rect.SetTop(miny + y2);
m_viewport[0] = minx+x1;
m_viewport[1] = miny+y1;
m_viewport[2] = vp_width;
m_viewport[3] = vp_height;
glViewport(minx + x1, miny + y1, vp_width, vp_height);
glScissor(minx + x1, miny + y1, vp_width, vp_height);
}
const int*
KX_BlenderCanvas::
GetViewPort() {
#ifdef DEBUG
// If we're in a debug build, we might as well make sure our values don't differ
// from what the gpu thinks we have. This could lead to nasty, hard to find bugs.
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
assert(viewport[0] == m_viewport[0]);
assert(viewport[1] == m_viewport[1]);
assert(viewport[2] == m_viewport[2]);
assert(viewport[3] == m_viewport[3]);
#endif
return m_viewport;
}
void KX_BlenderCanvas::SetMouseState(RAS_MouseState mousestate)
{

View File

@@ -61,6 +61,7 @@ private:
/** Rect that defines the area used for rendering,
relative to the context */
RAS_Rect m_displayarea;
int m_viewport[4];
public:
/* Construct a new canvas.
@@ -150,6 +151,8 @@ public:
int x1, int y1,
int x2, int y2
);
const int*
GetViewPort();
void
SetMouseState(

View File

@@ -57,6 +57,8 @@ GPC_Canvas::GPC_Canvas(
m_displayarea.m_y1 = 0;
m_displayarea.m_x2 = width;
m_displayarea.m_y2 = height;
glGetIntegerv(GL_VIEWPORT, (GLint*)m_viewport);
}
@@ -122,10 +124,30 @@ void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
*/
glEnable(GL_SCISSOR_TEST);
m_viewport[0] = x1;
m_viewport[1] = y1;
m_viewport[2] = x2-x1 + 1;
m_viewport[3] = y2-y1 + 1;
glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
};
const int *GPC_Canvas::GetViewPort()
{
#ifdef DEBUG
// If we're in a debug build, we might as well make sure our values don't differ
// from what the gpu thinks we have. This could lead to nasty, hard to find bugs.
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
assert(viewport[0] == m_viewport[0]);
assert(viewport[1] == m_viewport[1]);
assert(viewport[2] == m_viewport[2]);
assert(viewport[3] == m_viewport[3]);
#endif
return m_viewport;
}
void GPC_Canvas::ClearBuffer(
int type

View File

@@ -90,6 +90,8 @@ protected:
* relative to the context */
RAS_Rect m_displayarea;
int *m_viewport;
/** Storage for the banners to display. */
TBannerMap m_banners;
/** State of banner display. */
@@ -153,6 +155,7 @@ public:
);
void SetViewPort(int x1, int y1, int x2, int y2);
const int *GetViewPort();
void ClearColor(float r, float g, float b, float a);

View File

@@ -956,7 +956,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
}
}
GLint viewport[4];
const GLint *viewport;
GLdouble win[3];
GLdouble modelmatrix[16];
GLdouble projmatrix[16];
@@ -967,7 +967,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
m_modelmatrix.getValue(modelmatrix);
m_projmatrix.getValue(projmatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
@@ -999,7 +999,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
MT_Vector3 vect;
MT_Point3 campos, screenpos;
GLint viewport[4];
const GLint *viewport;
GLdouble win[3];
GLdouble modelmatrix[16];
GLdouble projmatrix[16];
@@ -1010,7 +1010,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
m_modelmatrix.getValue(modelmatrix);
m_projmatrix.getValue(projmatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
vect[0] = x * viewport[2];
vect[1] = y * viewport[3];

View File

@@ -90,8 +90,7 @@ KX_Dome::KX_Dome (
}
//setting the viewport size
GLuint viewport[4]={0};
glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
const int *viewport = m_canvas->GetViewPort();
SetViewPort(viewport);
@@ -178,7 +177,7 @@ KX_Dome::~KX_Dome (void)
glDeleteLists(dlistId, (GLsizei) m_numimages);
}
void KX_Dome::SetViewPort(GLuint viewport[4])
void KX_Dome::SetViewPort(const int viewport[4])
{
if (canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight())
{

View File

@@ -119,7 +119,7 @@ public:
void RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i);
void BindImages(int i);
void SetViewPort(GLuint viewport[4]);
void SetViewPort(const int viewport[4]);
void CalculateFrustum(KX_Camera* cam);
void RotateCamera(KX_Camera* cam, int i);

View File

@@ -275,8 +275,7 @@ void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf,
void KX_KetsjiEngine::RenderDome()
{
GLuint viewport[4]={0};
glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
const GLint *viewport = m_canvas->GetViewPort();
m_dome->SetViewPort(viewport);

View File

@@ -1502,7 +1502,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
planes[4].setValue(cplanes[2].getValue()); // top
planes[5].setValue(cplanes[3].getValue()); // bottom
CullingInfo info(layer);
dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res);
double mvmat[16] = {0};
cam->GetModelviewMatrix().getValue(mvmat);
double pmat[16] = {0};
cam->GetProjectionMatrix().getValue(pmat);
dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res,
KX_GetActiveEngine()->GetCanvas()->GetViewPort(),
mvmat, pmat);
}
if (!dbvt_culling) {
// the physics engine couldn't help us, do it the hard way

View File

@@ -57,7 +57,6 @@ btRaycastVehicle::btVehicleTuning gTuning;
#include "LinearMath/btAabbUtil2.h"
#include "MT_Matrix4x4.h"
#include "MT_Vector3.h"
#include "GL/glew.h"
#ifdef WIN32
void DrawRasterizerLine(const float* from,const float* to,int color);
@@ -1309,22 +1308,19 @@ struct OcclusionBuffer
m[14] = btScalar(m1[ 2]*m2[12]+m1[ 6]*m2[13]+m1[10]*m2[14]+m1[14]*m2[15]);
m[15] = btScalar(m1[ 3]*m2[12]+m1[ 7]*m2[13]+m1[11]*m2[14]+m1[15]*m2[15]);
}
void setup(int size)
void setup(int size, const int *view, double modelview[16], double projection[16])
{
m_initialized=false;
m_occlusion=false;
// compute the size of the buffer
GLint v[4];
GLdouble m[16],p[16];
int maxsize;
double ratio;
glGetIntegerv(GL_VIEWPORT,v);
maxsize = (v[2] > v[3]) ? v[2] : v[3];
maxsize = (view[2] > view[3]) ? view[2] : view[3];
assert(maxsize > 0);
ratio = 1.0/(2*maxsize);
// ensure even number
m_sizes[0] = 2*((int)(size*v[2]*ratio+0.5));
m_sizes[1] = 2*((int)(size*v[3]*ratio+0.5));
m_sizes[0] = 2*((int)(size*view[2]*ratio+0.5));
m_sizes[1] = 2*((int)(size*view[3]*ratio+0.5));
m_scales[0]=btScalar(m_sizes[0]/2);
m_scales[1]=btScalar(m_sizes[1]/2);
m_offsets[0]=m_scales[0]+0.5f;
@@ -1333,9 +1329,7 @@ struct OcclusionBuffer
// at this time of the rendering, the modelview matrix is the
// world to camera transformation and the projection matrix is
// camera to clip transformation. combine both so that
glGetDoublev(GL_MODELVIEW_MATRIX,m);
glGetDoublev(GL_PROJECTION_MATRIX,p);
CMmat4mul(m_wtc,p,m);
CMmat4mul(m_wtc, projection, modelview);
}
void initialize()
{
@@ -1795,7 +1789,7 @@ struct DbvtCullingCallback : btDbvt::ICollide
};
static OcclusionBuffer gOcb;
bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes)
bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16])
{
if (!m_cullingTree)
return false;
@@ -1812,7 +1806,7 @@ bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* user
// if occlusionRes != 0 => occlusion culling
if (occlusionRes)
{
gOcb.setup(occlusionRes);
gOcb.setup(occlusionRes, viewport, modelview, projection);
dispatcher.m_ocb = &gOcb;
// occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane
btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);

View File

@@ -188,7 +188,7 @@ protected:
btTypedConstraint* getConstraintById(int constraintId);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes);
virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]);
//Methods for gamelogic collision/physics callbacks

View File

@@ -73,7 +73,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) { return false; }
//gamelogic callbacks

View File

@@ -161,7 +161,7 @@ class PHY_IPhysicsEnvironment
//culling based on physical broad phase
// the plane number must be set as follow: near, far, left, right, top, botton
// the near plane must be the first one and must always be present, it is used to get the direction of the view
virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes) = 0;
virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) = 0;
//Methods for gamelogic collision/physics callbacks
//todo:

View File

@@ -398,8 +398,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
if (num_filters <= 0)
return;
GLuint viewport[4]={0};
glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
const GLint *viewport = canvas->GetViewPort();
RAS_Rect rect = canvas->GetWindowArea();
int rect_width = rect.GetWidth()+1, rect_height = rect.GetHeight()+1;

View File

@@ -180,6 +180,13 @@ public:
int x2, int y2
) = 0;
/**
* Get the visible viewport
*/
virtual
const int*
GetViewPort() = 0;
virtual
void
SetMouseState(