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

FortranGL and callbacks

larson__michael
Beginner
694 Views

Hi all,

Yesterday I cranked out a little hello world OpenGL library using my own interfaces for GLFW and GLEW, before I go any further can I get a suggestion on how to do GLUT like callbacks? I want to make it simple from the Fortran side and let the C side do all the heavy lifting.

I used pointer descriptors directly for routines like buffer data and buffer sub data, is this common and safe?

Can I use pointer descriptors directly for string routines so I can convert strings in C?

Is there any interest in OpenCL? (I wrote a big chunk of OpenCL 1.0)

 

I worked on OpenGL / OpenCL at Apple for 10 years and I hope to be able to fill this out into a library that people can grab and use / make their own. I am looking to expose as much of OpenGL 3.3 as I can (even though I like OpenGL 2.1 which was so easy). I don't intend to make this work on the Apple platform as OpenGL is now deprecated and has not been updated in over 6 years, but it works on Linux just fine.

If you want to grab a copy its at https://github.com/darkaegisagain/FortranGL

Thanks ahead of time

Mike

 

 

0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
694 Views

Callbacks are easy to do. When writing the interface for a routine with a callback argument, you can either use an INTERFACE block as the declaration of that dummy, or use PROCEDURE(abstract-interface-name). Can you show an example of what you want to do?

Fortran and OpenGL go a long way back. Intel Fortran on Windows includes extensive OpenGL interface modules as well as several examples. I have, in the past, ported at least one of the examples to Linux without too much effort.

As for OpenCL, there exists FortranCL. Some years ago I ported a simple OpenCL example to Fortran and it worked. I don't have this anymore.

As for pointers and C strings, check out https://j3-fortran.org/doc/year/18/18-258r2.txt which contains a Fortran implementation of a C_F_STRPOINTER intrinsic planned for the next revision to the standard.

0 Kudos
larson__michael
Beginner
694 Views

Thanks Steve,

GLUT has a number of callback functions you can use to capture events, example here is the window reshape function.

void glutReshapeFunc(void (*func)(int width, int height));

(https://www.opengl.org/resources/libraries/glut/spec3/node48.html#SECTION00083000000000000000)

You provide a function / subroutine and call glutReshapeFunc so GLUT calls this function

In C

void myReshape(int width, int height)

{

}

....

To set this call back in C

glutReshapeFunc(myReshape)

 

see https://stackoverflow.com/questions/17539132/what-is-the-use-of-reshape-function-in-glut#17539178

I should elaborate that this will be a C library calling back into Fortran but I need to set the callback function in Fortran through a C interface.

 

I know there is a version of GLUT that used to work with Fortran, it failed compilation on Linux and it was pretty old and the perl script failed to handle current OpenGL headers so decided I would write my own FortranGL and learn more Fortran rather than deal with all the other issues that come up.

Mike

 

 

0 Kudos
Steve_Lionel
Honored Contributor III
694 Views

Here's how this would look in Fortran:

abstract interface
  subroutine glutReshapeCallback_int (width, height) bind(C)
    use, intrinsic :: ISO_C_BINDING
    integer(C_INT), value :: width, height
  end subroutine glutReshapeCallback_int
end interface

interface
  subroutine glutReshapeFunc (func) bind(C,name="glutReshapeFunc")
    procedure(glutReshapeCallback_int) :: func
  end subroutine glutReshapeFunc
end interface

Then one writes a Fortran subroutine with the same interface as glutReshapeCallback_int and passes it as an argument to glutReshapeFunc.

Does this help? If you are writing your own C routine, you just copy this approach. Let me know if you are unfamiliar with any of the things I wrote above.

0 Kudos
larson__michael
Beginner
694 Views

This works for decoding Fortran strings in C, its probably an nightmare hack... but the CFI_cdesc_t isn't too hard to figure out for someone who spends lots of time in the OS kernel.

Take a Fortran call like this

ubo_block_index = glfUniformBlockIndex(program, "uniform_data")                                               |                                                                                        

And an interface defined like this

     function glfUniformBlockIndex(glsl_program, uniform_block_str) bind(C, name="glfUniformBlockIndex")                                                                                                                          
       use, intrinsic :: iso_c_binding                                                                                                                                                                                             
       implicit none                                                                                                                                                                                                               
       integer(c_int),intent(in),value :: glsl_program                                                                                                                                                                             
       character(len=*),intent(in) :: uniform_block_str                                                                                                                                                                            
       integer(c_int) :: glfUniformBlockIndex                                                                                                                                                                                      
     end function glfUniformBlockIndex                                                                                                                                                                                             

The C function is pretty simple, the fortran string length is held in data->elem_len and the characters in data->base_addr as a non-NULL terminated string

                                                                                                                                                                                                                      
GLuint glfUniformBlockIndex(GLuint program, CFI_cdesc_t *data)                                                                                                                                       {                                                                                                                                                                                                                                  
  assert(data);                                                                                                                                                                                                                    
  assert(data->base_addr);                                                                                                                                                                                                       GLuint index = 0;                                                                                                                                                                                                                
  char *fstr = data->base_addr;                                                                                                                                                                                              
  int max_len = data->elem_len;                                                                                                                                                                                                char *cstr = (char *)malloc(max_len + 1);                                                                                                                                                                              

// copy f string to c string

 for(int i=0; i<max_len; i++)                                                                                                                                                                                                    {                                                                                                                                                                                                                              
      cstr = fstr;                                                                                                                                                                                                           
 }                                                                                                                                                                                                                              
                                                                                                                                                                                                                                   
  cstr[max_len] = 0;                                                                                                                                                                                                      
                                                                                                                                                                                                                                   
  index = glGetUniformBlockIndex(program, cstr);                                                                                                                                                                                                                                                                                                                                                                                                    
  free(cstr);

                                                                                                                                                                                                                  
  return index;                                                                                                                                                                                                                    
}                

I could add more asserts to make sure the *data structure I am looking is actually a string.

 

0 Kudos
andrew_4619
Honored Contributor II
694 Views

An Interesting and worthwhile project IMO. I have searched in the past there are no GLEW resources for Fortran on the net and from a personal level it looked like quite a bit  of work to implement so I never started. Good luck with this project :-)

0 Kudos
larson__michael
Beginner
694 Views

I have uniform buffers working, GLSL programs and vertex descriptors will be done today... if you want to help or features give me a heads up...

I am still struggling with setting up event callbacks from GLFW, but I think I will let that cook for a bit.

Textures are on the list and then testing and examples.

0 Kudos
Reply