Jump to content
  • Advertisement
Sign in to follow this  
jkstrong

OpenGL ATI SwapBuffers Performance with Occluding Non-Rectangular Windows

This topic is 4858 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to optimize an OpenGL application for multiple graphics cards and I've hit an unfortunate snag with all the ATI radeons I've tested. The app has a 100 pixel diameter circular window containing view manipulation controls (created with SetWindowRgn) which frequently overlaps the main OpenGL display. During frame buffer update, if the window overlaps the display, the performance drops precipitously (20-50x) on ATI while NVDIA shows a relatively small impact (0.1-0.5x). In a simple recreation scenario (code below) which spins a pyramid - I just got the following results with current display drivers Radeon 9550 with circular window: 27 FPS, w/o: 880 FPS (vsync disabled) NVDIA FX5600 with circular window: 230 FPS, w/o: 365 FPS (vsync disabled)
//Begin Sample code:

#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>	
#include <gl\glaux.h>
#include <stdio.h>

HDC			hDC=0;
HGLRC		hRC=0;
HWND		hWnd=0;
HINSTANCE	hInstance;
HWND hRoundWnd = 0;
bool	active=TRUE;

LRESULT CALLBACK RoundWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
		case WM_WINDOWPOSCHANGED:
				{
					HRGN hRgn = CreateEllipticRgn(0, 0, 100, 100);
					SetWindowRgn(hWnd, hRgn, TRUE);
					DefWindowProc(hWnd, message, wParam, lParam);
				}
				break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

void CreateRoundWindow()
{
	WNDCLASSEX wcex = {0};
	wcex.cbSize = sizeof(WNDCLASSEX); 
	wcex.style			= CS_SAVEBITS;
	wcex.lpfnWndProc	= (WNDPROC)RoundWndProc;
	wcex.hInstance		= GetModuleHandle(0);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszClassName	= "RoundWClass";
	RegisterClassEx(&wcex);
	hRoundWnd = CreateWindowEx(/*WS_EX_LAYERED |*/ WS_EX_TOPMOST, "RoundWClass", 
		"", WS_POPUP | WS_CLIPSIBLINGS,	100, 100, 100, 100, 0, NULL, wcex.hInstance, NULL);
//	HRGN hRgn = CreateEllipticRgn(0, 0, 100, 100);
//	BOOL rc = SetWindowRgn(hLWnd, hRgn, TRUE);
//	SetLayeredWindowAttributes(hLWnd, 0, 154, LWA_ALPHA);
}

GLfloat	rtri;				// Angle For The Triangle ( NEW )

LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
	if (height==0)		height=1;
	glViewport(0,0,width,height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	glLoadIdentity();									
	glTranslatef(-1.5f,0.0f,-6.0f);						
	glRotatef(rtri,0.0f,1.0f,0.0f);						
	glBegin(GL_TRIANGLES);								
		glColor3f(1.0f,0.0f,0.0f);						
		glVertex3f( 0.0f, 1.0f, 0.0f);					
		glColor3f(0.0f,1.0f,0.0f);						
		glVertex3f(-1.0f,-1.0f, 1.0f);					
		glColor3f(0.0f,0.0f,1.0f);						
		glVertex3f( 1.0f,-1.0f, 1.0f);					
		glColor3f(1.0f,0.0f,0.0f);						
		glVertex3f( 0.0f, 1.0f, 0.0f);					
		glColor3f(0.0f,0.0f,1.0f);						
		glVertex3f( 1.0f,-1.0f, 1.0f);					
		glColor3f(0.0f,1.0f,0.0f);						
		glVertex3f( 1.0f,-1.0f, -1.0f);					
		glColor3f(1.0f,0.0f,0.0f);						
		glVertex3f( 0.0f, 1.0f, 0.0f);					
		glColor3f(0.0f,1.0f,0.0f);						
		glVertex3f( 1.0f,-1.0f, -1.0f);					
		glColor3f(0.0f,0.0f,1.0f);						
		glVertex3f(-1.0f,-1.0f, -1.0f);					
		glColor3f(1.0f,0.0f,0.0f);						
		glVertex3f( 0.0f, 1.0f, 0.0f);					
		glColor3f(0.0f,0.0f,1.0f);						
		glVertex3f(-1.0f,-1.0f,-1.0f);					
		glColor3f(0.0f,1.0f,0.0f);						
		glVertex3f(-1.0f,-1.0f, 1.0f);					
	glEnd();											

	rtri+=2.0f;											
	return TRUE;										
}

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
	GLuint		PixelFormat;			
	WNDCLASS	wc = {0};						
	DWORD		dwExstyle;				
	DWORD		dwstyle;				
	RECT		WindowRect;				 
	WindowRect.left=(long)0;			
	WindowRect.right=(long)width;		
	WindowRect.top=(long)0;				
	WindowRect.bottom=(long)height;		

	hInstance			= GetModuleHandle(NULL);				
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	
	wc.lpfnWndProc		= (WNDPROC) WndProc;					
	wc.hInstance		= hInstance;							
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			
	wc.lpszClassName	= "OpenGL";								

	RegisterClass(&wc);
	dwExstyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
	dwstyle=WS_OVERLAPPEDWINDOW;
	AdjustWindowRectEx(&WindowRect, dwstyle, FALSE, dwExstyle);	
	// Create The Window
	hWnd=CreateWindowEx(	dwExstyle, "OpenGL", title,	dwstyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
		0, 0, WindowRect.right-WindowRect.left,	 WindowRect.bottom-WindowRect.top,	NULL, NULL, hInstance, NULL);
	static	PIXELFORMATDESCRIPTOR pfd=	
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,					
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER,	
		PFD_TYPE_RGBA,		
		bits,				
		0, 0, 0, 0, 0, 0,	
		0,					
		0,					
		0,					
		0, 0, 0, 0,			
		16,					
		0,					
		0,					
		PFD_MAIN_PLANE,		
		0,					
		0, 0, 0				
	};
	hDC=GetDC(hWnd);
	PixelFormat=ChoosePixelFormat(hDC,&pfd);
	SetPixelFormat(hDC,PixelFormat,&pfd);
	hRC=wglCreateContext(hDC);
	wglMakeCurrent(hDC,hRC);
	ShowWindow(hWnd,SW_SHOW);
	SetForegroundWindow(hWnd);
	SetFocus(hWnd);
	ReSizeGLScene(width, height);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);	
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);	
	return TRUE;
}

LRESULT CALLBACK WndProc(	HWND	hWnd,	UINT	uMsg,	WPARAM	wParam,	LPARAM	lParam)	
{
	switch (uMsg)
	{
		case WM_ACTIVATE:
		{
			if ((LOWORD(wParam) != WA_INACTIVE) && !((BOOL)HIWORD(wParam)))
				active=TRUE;
			else
				active=FALSE;
			return 0;
		}
		case WM_CLOSE:
			PostQuitMessage(0);
			return 0;
		case WM_KEYDOWN:
		{
			if (wParam == VK_F1)
			{
				RECT wr;
				GetWindowRect(hWnd, &wr);
				SetWindowPos(hRoundWnd, 0, wr.left + 100, wr.top + 100, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
				ShowWindow(hRoundWnd, IsWindowVisible(hRoundWnd) ? SW_HIDE : SW_SHOW);
				SetActiveWindow(hWnd);
			}
			return 0;
		}
		case WM_SIZE:
			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
			return 0;
	}
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain(	HINSTANCE	hInstance,			// Instance
					HINSTANCE	hPrevInstance,		// Previous Instance
					LPSTR		lpCmdLine,			// Command Line Parameters
					int			nCmdShow)			// Window Show State
{
	MSG	 msg;									// Windows Message Structure
	BOOL done=FALSE;								// Bool Variable To Exit Loop
	char title[256];
	int  nFrames = 0;

	// Create Our OpenGL Window
	sprintf(title, "OpenGL Test: FPS %d", nFrames);
	if (!CreateGLWindow(title,640,480,16,FALSE))
		return 0;									// Quit If Window Was Not Created
	CreateRoundWindow();
	SetWindowText(hWnd, title);
	DWORD baseclicks = GetTickCount();
	while(!done)									// Loop That Runs While done=FALSE
	{
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))	// Is There A Message Waiting?
		{
			if (msg.message==WM_QUIT)				// Have We Received A Quit Message?
				done=TRUE;							// If So done=TRUE
			else									// If Not, Deal With Window Messages
			{
				TranslateMessage(&msg);				// Translate The Message
				DispatchMessage(&msg);				// Dispatch The Message
			}
		}
		else										// If There Are No Messages
		{
			if ((active && !DrawGLScene()))	// Active?  Was There A Quit Received?
				done=TRUE;							// ESC or DrawGLScene Signalled A Quit
			else									// Not Time To Quit, Update Screen
			{
				DWORD clicks = GetTickCount();
				SwapBuffers(hDC);					// Swap Buffers (Double Buffering)
				nFrames++;
				if (clicks-baseclicks > 1000)
				{
					baseclicks = clicks;
					sprintf(title, "OpenGL Test: FPS %d", nFrames);
					SetWindowText(hWnd, title);
					nFrames = 0;
				}
			}
		}
	}
	if (hRC)											// Do We Have A Rendering Context?
	{
		wglMakeCurrent(NULL,NULL);
		wglDeleteContext(hRC);
	}
	return (msg.wParam);							// Exit The Program
}

//End Sample code:

Any ideas to workaround or fix this problem would be greatly appreciated. [Edited by - phantom on November 30, 2005 12:32:15 PM]

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!