Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

fwglGetProcAddress (OpenGL + Windows + Intel Fortran)

Russell_G_
Beginner
655 Views

I am trying to use OpenGL functions that are not directly supported by Windows, which only supports GL functions up to OpenGL 1.1. Supposedly the  the wglGetProcAddress function allows access to functions supported by the graphics hardware from following versions of OpenGL.

Here's what I'm trying to do....

 
      hWnd = CreateOpenGLWindow( ... )
      hDC  = GetDC(hWnd)
      hRC  = fwglCreateContext(hDC)
      hret = fwglMakeCurrent(hDC, hRC)
      anam = 'glGenVertexArray'C
      f    = fwglGetProcAddress(LOC(anam))

 

When I run this code I get f = zero, which indicates (I think) that function is not supported. I've tried this with various functions with similar results. This particular one is an OpenGL 3.0 function, and my graphics card is a relatively modern AMD Radeon which claims to support up to OpenGL 4.1. so it should be available. Questions:

  1.  Am I calling fwglGetProcAddress correctly (should I use C_LOC instead)?
  2.  If I did get a function address back from this call to fwglGetProcAddress - how would I then call that function?   It would still need some sort of C++ interface in order to call it from Fortran, correct?

Basic system info: I'm using Intel(R) Visual Fortran Composer XE 2013 and Microsoft Visual Studio* 2010, on Windows 7.

 

Thanks

 

 

 

0 Kudos
10 Replies
Steven_L_Intel1
Employee
655 Views

You're calling the function correctly - C_LOC would not work because the argument is INTEGER(GLvoid), not C_PTR. Other than that, I have no clue whether this ought to work. I did find http://stackoverflow.com/questions/21769427/wglgetprocaddress-returns-null which seems relevant and possibly helpful.

Yes, you will need an interface. I suggest you look at the DLL\DynamicLoad sample provided by Intel Visual Fortran for an example of how to do this.

0 Kudos
Robert_van_Amerongen
New Contributor III
655 Views

Maybe there is a typo: glGenVertexArrays (Mind the "s"). Does this help?

Robert

 

0 Kudos
andrew_4619
Honored Contributor II
655 Views

Case and spelling needs to match you could also call GetLastError. if null is returned.

0 Kudos
Russell_G_
Beginner
655 Views

Robert van Amerongen wrote:

Maybe there is a typo: glGenVertexArrays (Mind the "s"). Does this help?

Robert

 

No, good catch but that doesn't help.  I also made sure I've got a current display context:

 

hWnd  = CreateOpenGLWindow(        "foo", &
            0, 0, 1024, 700, color, buffer, WindowProc) 
hDC   = GetDC(hWnd) 
hRC   = fwglCreateContext(hDC) 
hret  = fwglMakeCurrent(hDC, hRC) 
icurr = fwglGetCurrentContext()
anam  = 'glGenVertexArrays'C
ifunc = fwglGetProcAddress(LOC(anam)) 
PRINT *, 'current context: ', icurr, ' procedure handle: ', ifunc

this prints:

 current context:        65536  procedure handle:            0

I will check the GetError return next...

0 Kudos
Russell_G_
Beginner
655 Views
anam = 'glGenVertexArrays'C
ifunc = fwglGetProcAddress(LOC(anam)) 
ierr = GetLastError()
PRINT ('(A10, Z)'), 'Error is ', ierr

this prints:

 

 Error is           7F

 

which translates to "ERROR_PROC_NOT_FOUND"

according to the MS system error code webpage.

 

 

 

0 Kudos
Steven_L_Intel1
Employee
655 Views

Well, there's your answer.... I don't think it's sufficient for just the hardware to support the function.

0 Kudos
JVanB
Valued Contributor II
655 Views

There wasn't enough context for me to easily make a full compilable example, so I started with Rings.f90 from the Samples directory. I made the following changes:

! Set up the OpenGL context
!
hDC = GetDC(hWnd)
hRC = fwglCreateContext(hDC)
hret = fwglMakeCurrent(hDC, hRC)
! Test stuff here:
BLOCK
    character(80) anam
    integer(HANDLE) f
    character(80) msg
    integer iret
    interface
       function wglGetProcAddress(name) bind(C,name='wglGetProcAddress')
          use ISO_C_BINDING, only: C_CHAR
          import
          implicit none
          integer(HANDLE) :: wglGetProcAddress
!DEC$ ATTRIBUTES STDCALL :: wglGetProcAddress
          character(kind=C_CHAR), intent(in) :: name(*)
       end function wglGetProcAddress
    end interface
      anam = 'glGenVertexArrays'C
      !f    = fwglGetProcAddress(LOC(anam))
      f    = wglGetProcAddress(anam)
      write(msg,'(i0,a)') f,achar(0)
      iret = MessageBox(NULL,msg,NULL,0)
END BLOCK
bret = ShowWindow(hWND, SW_SHOW)
bret = UpdateWindow(hWnd)
call Init

With the result:

fortcom: Fatal: There has been an internal compiler error (C0000005).
compilation aborted for Rings.f90 (code 1)

Even though this seemed unpromising, I tried instead:

! Set up the OpenGL context
!
hDC = GetDC(hWnd)
hRC = fwglCreateContext(hDC)
hret = fwglMakeCurrent(hDC, hRC)
! Test stuff here:
BLOCK
    character(80) anam
    integer(HANDLE) f
    character(80) msg
    integer iret
!    interface
!       function wglGetProcAddress(name) bind(C,name='wglGetProcAddress')
!          use ISO_C_BINDING, only: C_CHAR
!          import
!          implicit none
!          integer(HANDLE) :: wglGetProcAddress
!!DEC$ ATTRIBUTES STDCALL :: wglGetProcAddress
!          character(kind=C_CHAR), intent(in) :: name(*)
!       end function wglGetProcAddress
!    end interface
      anam = 'glGenVertexArrays'C
      f    = fwglGetProcAddress(LOC(anam))
      !f    = wglGetProcAddress(anam)
      write(msg,'(i0,a)') f,achar(0)
      iret = MessageBox(NULL,msg,NULL,0)
END BLOCK
bret = ShowWindow(hWND, SW_SHOW)
bret = UpdateWindow(hWnd)
call Init

And now build.bat ran without error and the resulting Rings.exe said "1808564752" in its MessageBox. So I think the first thing I would try is to modify Rings.f90 the same way and see if it works OK on your computer. If so the point of failure may lie in setting up the OpenGL context (which is really hard to do properly) and not in the wglGetProcAddress call.

 

0 Kudos
Russell_G_
Beginner
655 Views

Thanks for posting working code.  I hate to admit it but the error was nothing to do with OpenGL -

 

! CHARACTER :: anam ='glCreateProgram'C

CHARACTER(80):: anam ='glCreateProgram'C

 

I forgot to put a string length for the procedure name, so it was looking for a procedure called "g".

 

Incidentally, the "BLOCK" construct doesn't compile on my IVF (Composer XE 2013) - is that a recently implemented feature?

thanks again!

0 Kudos
Steven_L_Intel1
Employee
655 Views

Yes, BLOCK is new in the 2015 (15.0) compiler. It is a Fortran 2008 feature.

I will check out the compiler error.

0 Kudos
Steven_L_Intel1
Employee
655 Views

The compiler error RO found in #8 has been fixed for a release later this year.

0 Kudos
Reply