wglCreateContext вызывает исключение INVALID_OPERATION

Предположим, что у меня есть класс COpenGLControl, загруженный здесь из codeguru, при условии, что первый обработчик событий, запущенный при создании окна OpenGL, - это OnCreate, я попытался отследить ошибки этого класса. Вот код, используемый для создания окна в файлах.h и.cpp моего диалога:

MyOpenGLTestDlg.h

COpenGLControl m_oglWindow;  

MyOpenGLTestDlg.cpp

CRect rect;

// Get size and position of the picture control
GetDlgItem(ID_OPENGL)->GetWindowRect(rect);

// Convert screen coordinates to client coordinates
ScreenToClient(rect);  

знать, я думаю, что функция OnCreate был вызван. На самом деле, я думаю, что строка кода COpenGLControl m_oglWindow; вызывает эту функцию для вызова! но я не уверен, поэтому я буду признателен, если вы меня об этом поведете?
Во всяком случае, я не сделал много изменений в классе:

OpenGLControl.h

#pragma once
#include "afxwin.h"
#include "WinBase.h"

#include <gl/gl.h>
#include <gl/glu.h>

class COpenGLControl : public CWnd
{
public:
    /******************/
    /* Public Members */
    /******************/
    UINT_PTR m_unpTimer;
    // View information variables
    float    m_fLastX;
    float    m_fLastY;
    float    m_fPosX;
    float    m_fPosY;
    float    m_fZoom;
    float    m_fRotX;
    float    m_fRotY;
    bool     m_bIsMaximized;

private:
    /*******************/
    /* Private Members */
    /*******************/
    // Window information
    CWnd  *hWnd;     //window handle
    HDC   hdc;       //device context handle    
    HGLRC hrc;       //handle to GL Rendering Context
    int   m_nPixelFormat;
    CRect m_rect;
    CRect m_oldWindow;
    CRect m_originalRect;

public:
    COpenGLControl(void);
    virtual ~COpenGLControl(void);

    void oglCreate(CRect rect, CWnd *parent);
    void oglInitialize(void);
    void oglDrawScene(void);

    // Added message classes:
    afx_msg void OnPaint();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDraw(CDC *pDC);
    afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);

    DECLARE_MESSAGE_MAP()
};  

OpenGLControl.cpp

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;

    oglInitialize();

    return 0;
}  
void COpenGLControl::oglInitialize(void)
{
    // Initial Setup:
    //
    static PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32, // bit depth
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24, // z-buffer depth
        8,0,PFD_MAIN_PLANE, 0, 0, 0, 0,
    };

    // Get device context only once.
    hdc = GetDC()->m_hDC;
    // Pixel format.
    m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, m_nPixelFormat, &pfd);
    // Create the OpenGL Rendering Context.
    hrc = wglCreateContext(hdc);
    GLenum error13 = glGetError();
    wglMakeCurrent(hdc, hrc);

   // Basic Setup:
   //
   // Set color to use when clearing the background.
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
   glClearDepth(1.0f);
   // Turn on backface culling
   glFrontFace(GL_CCW);
   glCullFace(GL_BACK);
   // Turn on depth testing
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   // Send draw request
   OnDraw(NULL);
}  

Как видите, я написал код GLenum error13 = glGetError(); сразу после hrc = wglCreateContext(hdc); поймать любую возможную ошибку, которую он выдает, и да, значение для error13 1282 что значит INVALID_OPERATION так что я думаю handle for OpenGL rendering context не создан должным образом!
кроме того, если вы проверите значения для hdc а также hrc Вы сталкиваетесь с этим:

HDC -> не используется =??? (Ошибка: выражение не может быть оценено)
hrc -> unused = 0

Не могли бы вы помочь мне выяснить, почему это так? и в чем проблема?

2 ответа

Решение

Результаты совершенно не определены, если вы вызываете функции GL (например, glGetError() сам) без текущего контекста GL.

wglCreateContext() является частью Win33 API (а не GL API) и будет сигнализировать об ошибках, возвращая NULL указатель. Вы можете вызвать функцию Windows API GetLastError() если вам нужны подробности в этом случае, как и в большинстве других функций Windows API.

Не вызывайте функцию API OpenGL, пока у вас не будет "текущего контекста" для вызывающего потока в Win32. Операции будут неопределенными.

Чтобы исправить эту проблему, просто переместите вызов на wglMakeCurrent (...) одна линия, так что это до вызова glGetError (...),

Обратите внимание, что вы должны сделать это для каждого потока, и в Win32 только один поток может получить доступ к контексту OpenGL в любой момент времени. Если вы когда-нибудь захотите выполнить многопоточный рендеринг в Win32, вам придется либо получить / освободить контекст и выполнить синхронизацию между потоками, либо использовать несколько контекстов, которые "разделяют списки" (wglShareLists (...)).

Как упомянуто derhass, если вы хотите получить информацию об ошибке, сгенерированной WGL API, используйте GetLastError (...), WGL является частью оконной системы, которая построена на основе Win32 API, поэтому она будет сообщать вам о своих ошибках по традиционным каналам Win32.


Кстати, старайтесь не печатать значения ошибок GL в десятичной форме. Они всегда перечисляются в gl.h как шестнадцатеричные константы, поэтому было бы легче найти соответствующий перечислитель, если бы вы сделали это:

printf ("OpenGL Error: 0x%X\n", err);

То же самое касается всех перечисляемых констант в OpenGL. Если у вас нет функции, которая отображает их в удобочитаемую строку, вы должны использовать шестнадцатеричное значение для их поиска.

Другие вопросы по тегам