Hi!
I have downloaded NeHe’s lesson33 (GLX version) and compiled it.
But when running this source code (some modification done by me, but shouldn’t be significant changes anyway), I get different CPU load depending on the resolution I select.
If I select resolution to be 1920x1200 (my desktop resolution) then my CPU is only using about 2-4%, but if I select it to be something else (i.e: 1024x768) my CPU is about 70-80%. This I measured with command utility “top”.
Why is my program using so much of the CPU ?
Thanks in advance
Kim
/*
* IMPORTANT: install "libxxf86vm-dev" package before compiling.
*
* TO COMPILE:
* gcc -Os -Wall -ansi -pedantic -ffloat-store -c -g -o main.o main.c
* gcc -g -o lesson33 main.o -L/usr/X11R6/lib -lm -lGL -lXxf86vm
*
* Nehe Lesson 33 Code (ported to Linux//GLX by Patrick Schubert 2003
* with help from the lesson 1 basecode for Linux/GLX by Mihael Vrbanec)
*/
#include <GL/glx.h>
#include <GL/gl.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
/* Application size */
static int desk_size_x = 1920; /* 1024; <--- Changing size affects CPU, why? */
static int desk_size_y = 1200; /* 768; <--- Low CPU load if your desktop resolution, but */
/* <--- high CPU load if not. Why 2-4% to 70-80% CPU load??? */
/* <--- Used "top" to messaure */
typedef struct
{
Display *dpy;
int screen;
Window win;
GLXContext ctx;
XSetWindowAttributes attr;
Bool fs;
XF86VidModeModeInfo deskMode;
int x, y;
unsigned int width, height;
unsigned int depth;
} GLWindow;
static GLWindow GLWin;
static XEvent event;
static int running;
float spin; /* Spin Variable */
static void initGL(void);
static void resizeGLScene(void);
static void swapBuffers(void);
void createGLWindow(const char*,int,int,int,int);
void killGLWindow(void);
void MessageHandler(void);
void run(void);
int drawGLScene(GLvoid) /* Here's Where We Do All The Drawing */
{
int loop;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Clear The Screen And The Depth Buffer */
glLoadIdentity(); /* Reset The Modelview Matrix */
glTranslatef(0.0f,0.0f,-10.0f); /* Translate 20 Units Into The Screen */
spin += 0.05f; /* Increase Spin */
for(loop = 0;loop < 20;loop++) /* Loop Of 20 */
{
glPushMatrix(); /* Push The Matrix */
glRotatef(spin+loop*18.0f,1.0f,0.0f,0.0f); /* Rotate On The X-Axis (Up - Down) */
glTranslatef(-2.0f,2.0f,0.0f); /* Translate 2 Units Left And 2 Up */
glBegin(GL_QUADS); /* Draw Our Quad */
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd(); /* Done Drawing The Quad */
glPopMatrix(); /* Pop The Matrix */
}
return True; /* Keep Going */
}
int main(void)
{
createGLWindow("NeHe's Lesson 33",desk_size_x,desk_size_y,24,False); /* Create our window*/
run(); /* Start Event-Loop */
killGLWindow(); /* shutdown window */
return 0;
}
/* Create our window */
void createGLWindow(const char* title,int width,int height,int bits,int fullscreen)
{
int attrListSgl[] = { GLX_RGBA, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None};
int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None};
XVisualInfo *vi;
Colormap cmap;
int dpyWidth, dpyHeight;
int i;
int vidModeMajorVersion, vidModeMinorVersion;
XF86VidModeModeInfo **modes;
int modeNum;
int bestMode;
Atom wmDelete;
Window winDummy;
unsigned int borderDummy;
GLWin.fs = fullscreen;
bestMode = 0;
GLWin.dpy = XOpenDisplay(0);
GLWin.screen = DefaultScreen(GLWin.dpy);
XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion);
XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes);
GLWin.deskMode = *modes[0];
for (i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height))
{
bestMode = i;
}
}
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
if(NULL == vi)
{
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl);
printf("Singlebuffered : true
");
}
else
{
printf("Doublebuffered : true
");
}
GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE);
cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),vi->visual, AllocNone);
GLWin.attr.colormap = cmap;
GLWin.attr.border_pixel = 0;
if(GLWin.fs)
{
XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]);
XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
dpyWidth = modes[bestMode]->hdisplay;
dpyHeight = modes[bestMode]->vdisplay;
XFree(modes);
GLWin.attr.override_redirect = True;
GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
&GLWin.attr);
XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0);
XMapRaised(GLWin.dpy, GLWin.win);
XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync,GrabModeAsync, CurrentTime);
XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime);
}
else
{
GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1);
XSetStandardProperties(GLWin.dpy, GLWin.win, title, title, None, NULL, 0, NULL);
XMapRaised(GLWin.dpy, GLWin.win);
}
glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx);
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
printf("Direct Rendering: %s
",glXIsDirect(GLWin.dpy, GLWin.ctx) ? "true" : "false");
printf("Running in %s mode
",GLWin.fs ? "fullscreen" : "window");
initGL();
}
/* Release our window */
void killGLWindow(void)
{
if(GLWin.ctx)
{
if(!glXMakeCurrent(GLWin.dpy, None, NULL))
{
printf("Error releasing drawing context : killGLWindow
");
}
glXDestroyContext(GLWin.dpy, GLWin.ctx);
GLWin.ctx = NULL;
}
if(GLWin.fs)
{
XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode);
XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
}
XCloseDisplay(GLWin.dpy);
}
void MessageHandler()
{
switch(event.type)
{
case Expose:
if (event.xexpose.count != 0)
break;
break;
case ConfigureNotify:
if ((event.xconfigure.width != GLWin.width) ||
(event.xconfigure.height != GLWin.height))
{
GLWin.width = event.xconfigure.width;
GLWin.height = event.xconfigure.height;
resizeGLScene();
}
break;
case KeyPress:
switch(XLookupKeysym(&event.xkey,0))
{
case XK_Escape: /* Quit application */
running = 0;
break;
case XK_F1: /* Switch fullscreen<->window mode */
killGLWindow();
createGLWindow("NeHe's Lesson 33",desk_size_x,desk_size_y,24,!GLWin.fs);
break;
}
break;
case ClientMessage:
if (*XGetAtomName(GLWin.dpy, event.xclient.message_type) == *"WM_PROTOCOLS")
{
running = 0;
}
break;
default:
break;
}
return;
}
/* Our event loop */
void run(void)
{
running = 1;
while(running)
{
while(XPending(GLWin.dpy))
{
XNextEvent(GLWin.dpy, &event);
MessageHandler();
}
drawGLScene();
swapBuffers();
}
}
/* Setup basic Opengl stuff */
static void initGL(void)
{
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
resizeGLScene();
glFlush();
}
/* Resize,set viewport,frustum */
static void resizeGLScene(void)
{
float width,height;
if(GLWin.height == 0)
GLWin.height = 1;
if(GLWin.width == 0)
GLWin.width = 1;
glViewport(0,0,GLWin.width,GLWin.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
width = 0.5f;
height = 0.5f * ((float)(GLWin.height)/GLWin.width);
glFrustum(-width,width,-height,height,1.0f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
/* Swap Buffers */
static void swapBuffers(void)
{
glXSwapBuffers(GLWin.dpy, GLWin.win);
}