0

当我调用 glGetIntergerv 或任何其他 opengl 函数并在 gdb 中单步执行时,到达它后,gdb 将跳过几行并在代码中继续单步执行。

下面是加载opengl和windows的代码。它是在第一个 opengl 调用 glGetIntergerv 之前运行的唯一代码。

HWND window;
HDC dev_context;

HGLRC rend_context;
//Creating the Window
    char const *name = "Opengl Test";
    HINSTANCE inst = (HINSTANCE)GetModuleHandle(0);
    WNDCLASS windowClass;
    DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    windowClass.lpfnWndProc = (WNDPROC) WndProcedure;
    windowClass.cbClsExtra = 0;
    windowClass.cbWndExtra = 0;
    windowClass.hInstance = inst;
    windowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = NULL;
    windowClass.lpszMenuName = NULL;
    windowClass.lpszClassName = name;
    RegisterClass(&windowClass);

    window = CreateWindowEx(dwExStyle, name, name, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 0, 0, NULL, NULL, inst, NULL);

//Context
    dev_context = GetDC( window );
    std::cout << dev_context << std::endl;
    //Get pixel format
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize  = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion   = 1;
    pfd.dwFlags    = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

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

    HGLRC temp_rend_context = wglCreateContext( dev_context );
    wglMakeCurrent( dev_context, temp_rend_context );

    HGLRC (WINAPI *wglCreateContextAttribsARB) (HDC hDC, HGLRC hShareContext, const int *attribList) = (HGLRC (WINAPI *) (HDC hDC, HGLRC hShareContext, const int *attribList)) gl3wGetProcAddress("wglCreateContextAttribsARB");

    const int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3,  WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_FLAGS_ARB, /*WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB*/0, 0};

    rend_context = wglCreateContextAttribsARB(dev_context, 0, attribs);
    wglMakeCurrent(0,0);
    wglDeleteContext(temp_rend_context);
    wglMakeCurrent(dev_context, rend_context);

    gl3wInit();

    int glVersion[2] = {-1, -1};
    glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]); //First gl call
    glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);

下面是我的 WndProcedure 函数:

static LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam){
    switch(Msg){
        case WM_DESTROY:
            PostQuitMessage(WM_QUIT);
            return 0;
        default:
            return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
}

我正在使用 gl3w 库来加载 opengl 函数。

4

2 回答 2

1

听起来您在调用约定或参数列表或两者中都存在不匹配,这会破坏堆栈以破坏调用返回地址。

仔细检查您正在编译的 opengl .h 文件是否与您正在调用的 opengl .dll 的版本相匹配。仔细检查是否为 .h 文件定义并启用了 Windows 所需的任何条件定义。Win API 调用中调用约定的规范是 STDCALL。如果您在 .h 文件中没有看到 gl 函数的调用约定,请保持怀疑。

我隐约记得 STDCALL 和 cdecl 调用约定以相同的顺序(从右到左)将参数推入堆栈,但在调用后谁负责调整堆栈指针不同。我相信 STDCALL 期望被调用者弹出堆栈,而使用 cdecl 调用者在调用返回后恢复堆栈指针。

这意味着如果调用者正在进行 cdecl 调用,但被调用者实际上是 STDCALL,则参数将使其进入调用就好了,但所有地狱都会在返回时崩溃。根据不匹配运行的方式,堆栈指针根本不会调整,或者会过度调整(调整两次)。

于 2012-08-09T01:15:46.507 回答
0

Here is the code I use create a GL context and use GL3 features. Now I know this is C# but you get the picture. There is no reason to create two GL contexts to use OpenGL3... unless im totally missing what your saying.

void Init(IntPtr handle, bool fullscreen, bool vSync)
{
                this.handle = handle;
                #if WINDOWS
                //Get DC
                dc = WGL.GetDC(handle);
                WGL.SwapBuffers(dc);

                //Set BackBuffer format
                WGL.PIXELFORMATDESCRIPTOR pfd = new WGL.PIXELFORMATDESCRIPTOR();
                WGL.ZeroPixelDescriptor(ref pfd);
                pfd.nVersion        = 1;
                pfd.dwFlags         = WGL.PFD_DRAW_TO_WINDOW | WGL.PFD_SUPPORT_OPENGL | WGL.PFD_DOUBLEBUFFER;
                pfd.iPixelType      = (byte)WGL.PFD_TYPE_RGBA;
                pfd.cColorBits      = 24;
                pfd.cAlphaBits      = 8;
                pfd.cDepthBits      = 16;
                pfd.iLayerType      = (byte)WGL.PFD_MAIN_PLANE;
                unsafe{pfd.nSize = (ushort)sizeof(WGL.PIXELFORMATDESCRIPTOR);}

                int pixelFormatIndex = WGL.ChoosePixelFormat(dc, ref pfd);
                if (pixelFormatIndex == 0) Debug.ThrowError("Video", "ChoosePixelFormat failed");
                if (WGL.SetPixelFormat(dc, pixelFormatIndex, ref pfd) == 0) Debug.ThrowError("Video", "Failed to set PixelFormat");

                ctx = WGL.CreateContext(dc);
                if (ctx == IntPtr.Zero) Debug.ThrowError("Video", "Failed to create GL context");
                if (WGL.MakeCurrent(dc, ctx) == 0) Debug.ThrowError("Video", "Failed to make GL context current");

                WGL.Init();//<< load 'wglSwapIntervalEXT'
                WGL.SwapInterval(vSync ? 1 : 0);
}

And to load GL extensions:

public const string DLL = "opengl32";
[DllImport(DLL, EntryPoint = "wglGetProcAddress", ExactSpelling = true)]
private static extern IntPtr getProcAddress(string procedureName);
于 2012-08-15T01:59:03.117 回答