在调整大小时,OpenGL交换缓冲区会停止

时间:2014-05-31 04:54:17

标签: c++ windows opengl resize

我目前正在开发一个将标准win32转换为C ++类的OpenGL win32项目。在最初的实现过程中,我遇到了一个问题,当窗口调整大小时,框架冻结,窗口的大小变化非常缓慢,从一个大小跳到另一个大小。当窗口完成调整大小时,在窗口更新绘图表面之前会有明显的犹豫。

我正在使用WM_TIMER尽可能频繁地更新显示。在“正常”操作期间,程序清除屏幕,慢慢更新红色组件以在视觉上显示表面图纸的变化。考虑到测试的极其简单的设计,我无法想象在调整大小事件期间openGL代码是问题。我做了测试,看看是否通过按下鼠标按钮手动调整窗口大小,调用带有调整值的setwindowpos会导致相同的行为,并且确实如此。如果我保持大小相同并且调用SetWindowPos,则屏幕不会停止。这让我相信调整大小处理代码中的某些东西会以某种方式锁定HDC,从而阻止交换缓冲区以高速执行。可能在Win32调整代码的某个地方等待多线程锁定。

下面是一个小程序,它表现出与较大程序完全相同的行为。 只使用外部lib是opengl32.lib。

#include "stdafx.h"
#include "OpenGLTest.h"
#include <gl\GL.h>

#define MAX_LOADSTRING 100

HINSTANCE hInst;                    

TCHAR szTitle[MAX_LOADSTRING];              
TCHAR szWindowClass[MAX_LOADSTRING];            

ATOM MyRegisterClass(HINSTANCE hInstance,LPCTSTR strClassName,WNDPROC wndProc,HBRUSH brBackground);
BOOL InitInstance(HINSTANCE, int);

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

HWND _hWnd;
HDC _hDC;
HGLRC _glRC;

BOOL DrawWindow();

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR    lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_OPENGLTEST, szWindowClass, MAX_LOADSTRING);

MyRegisterClass(hInstance,szWindowClass,WndProc,NULL);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
    return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_OPENGLTEST));

// Main message loop:
bool bRun=true;
while (bRun)
{
    if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message==WM_QUIT) 
        {
            break;
        }
    }
}

return (int) msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance,LPCTSTR strClassName,WNDPROC wndProc,HBRUSH brBackground)
{
WNDCLASSEX wcex;

//Register Main Window Class
wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style          = CS_HREDRAW | CS_VREDRAW ;
wcex.lpfnWndProc    = wndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance      = hInstance;
wcex.hIcon          = NULL;
wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground  = brBackground;
wcex.lpszMenuName   = NULL;
wcex.lpszClassName  = strClassName;
wcex.hIconSm        = NULL;

return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance; // Store instance handle in our global variable

    _hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!_hWnd)
   {
  return FALSE;
   }

_hDC=GetDC(_hWnd);
if (_hDC!=nullptr)
{
    //Create OpenGL 3.2 context
    PIXELFORMATDESCRIPTOR pfd =
    {
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
            PFD_TYPE_RGBA,            //The kind of framebuffer. RGBA or palette.
            32,                        //Colordepth of the framebuffer.
            0, 0, 0, 0, 0, 0,
            0,
            0,
            0,
            0, 0, 0, 0,
            24,                        //Number of bits for the depthbuffer
            8,                        //Number of bits for the stencilbuffer
            0,                        //Number of Aux buffers in the framebuffer.
            PFD_MAIN_PLANE,
            0,
            0, 0, 0
    };

    int nPixelFormat=ChoosePixelFormat(_hDC,&pfd);
    SetPixelFormat(_hDC,nPixelFormat,&pfd);

    if ((_glRC=wglCreateContext(_hDC))!=nullptr)
    {
        //Make Context Current
        wglMakeCurrent(_hDC,_glRC);
    }
}

ShowWindow(_hWnd, nCmdShow);
UpdateWindow(_hWnd);

SetTimer(_hWnd, 0, 1, NULL);

return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
switch (message)
{
case WM_COMMAND:
    wmId    = LOWORD(wParam);
    wmEvent = HIWORD(wParam);
    // Parse the menu selections:
    switch (wmId)
    {
    case IDM_EXIT:
        DestroyWindow(hWnd);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    break;

case WM_TIMER:
        DrawWindow();
    break;

case WM_ERASEBKGND:
    return TRUE;

case WM_PAINT:
    BeginPaint(_hWnd,&ps);
    EndPaint(_hWnd,&ps);
    break;

case WM_DESTROY:
    PostQuitMessage(0);
    break;

default:
    return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

float fRed=0.0f;
BOOL DrawWindow()
{
RECT rc;
GetClientRect(_hWnd,&rc);
HDC hDC=GetDC(_hWnd);
if ((hDC!=nullptr)&&(_glRC!=nullptr))
{
    //Print Client Data to Window Title for debugging
    TCHAR strTitle[MAX_LOADSTRING];
    wsprintf(strTitle,L"%d, %d, %d, %d",rc.left,rc.top,rc.right,rc.bottom);
    SetWindowText(_hWnd,strTitle);

    wglMakeCurrent(hDC,_glRC);

    glViewport(rc.left,rc.top,(rc.right-rc.left),(rc.bottom-rc.top));

    glClearColor(fRed,1.0f,0.0f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    SwapBuffers(hDC);

    fRed+=0.1;
    if (fRed>1.0f) fRed=0.0f;

    ReleaseDC(_hWnd,hDC);
}
return TRUE;
}

编辑:问题是硬件问题而不是软件问题。我转移到另一个系统,问题不存在。谢谢你的帮助。

0 个答案:

没有答案