Keyboard and Mouse library for GL


9 posts
by jmacey » Wed Jun 13, 2012 8:45 pm
I'm in the process of porting loads of code based on Qt and want a simple lightweight mouse and keyboard library for the demos (basically EGL windows using OpenGL)

I know Qt is available on the pi but want to reduce overhead etc so I have a couple of options that I've been exploring but am having issues with,

1) SDL, I can use SDL for basic mouse / kbd input but it has issues as you have to initialise video to access the event sub system and this doesn't play well with EGL at present (I'm considering hacking the code and removing all the video stuff and use my own EGL window but this is quite a big task)

2) Using ncurses but again quite a lot of redundant code / dependancies.

3) write my own mouse and kbd low level processing (I've done a basic mouse routine but it's not a proper buffered event handler)

Does anyone have their own C/C++ mouse and kbd code they wish to share or know of any lightweight libraries to handle mouse and kbd?

Ideally I would like it to be event driven so I can query things like Key Up/Down Mouse Move, Mouse button up / down etc so it would make porting the Qt code quicker.

If you have any ideas please let me know, else I will write my own event queue similar to the SDL one (which is quite a good exercise in itself).

cheers

Jon
Posts: 135
Joined: Thu May 31, 2012 1:05 pm
by jmacey » Thu Jun 14, 2012 6:27 pm
I spoke too soon, I've now managed to get SDL and EGL working fairly well together I do get the occasional crash but not sure if that's my code or SDL at present. For anyone else trying to mix the two the process is as follows

1). create an exit function incase SDL crashes and register it with atexit (I do bcm deinit as well)

Code: Select all
void exitfunc()
{
SDL_Quit();
bcm_host_deinit();
}

Then in main do the following
Code: Select all
bcm_host_init();
atexit(exitfunc);

if ( SDL_Init(SDL_INIT_EVERYTHING) < 0 )
{
   std::cerr<<"Unable to init SDL: "<<SDL_GetError()<<"\n";
   exit(EXIT_FAILURE);
}
SDL_Surface* myVideoSurface = SDL_SetVideoMode(800,800, 16, SDL_HWSURFACE | SDL_SWSURFACE);
// Print out some information about the video surface
if (myVideoSurface != NULL)
{
   std::cout << "The current video surface bits per pixel is " << (int)myVideoSurface->format->BitsPerPixel << std::endl;
}
/// now do the EGL stuff to create the OpenGL context and do your drawing etc
Posts: 135
Joined: Thu May 31, 2012 1:05 pm
by Nitori » Thu Jun 14, 2012 7:13 pm
If you're trying to get every bit of performance out of the system, you can actually create a 0x0 window that is strictly software and all of the input events seem to work fine. Something like:
Code: Select all
SDL_SetVideoMode(0, 0, 32, SDL_SWSURFACE);
Apparently SDL can operate without the use of X somehow (trying to lauch it without X causes it to try to access the device framebuffer). If I can ever get it to work, that would be even more overhead removed.

And for someone who happens to stumble onto this thread in a search, here is a basic EGL init function (it took me several hours to figure out to check the hello_triangles example file, not realizing that the raspi doesn't have a standard EGL init process). Note this will init a GLES 2 context. Set screen_width and screen_height to 0 to get the maximum size, otherwise the passed width and height are used, and the surface is centered on the screen.
Code: Select all
void initEGL(EGLDisplay& display, EGLSurface& surface, EGLContext& context,
          Uint32& screen_width, Uint32& screen_height) {
    bcm_host_init();
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;
    static const EGLint attribute_list[] =
      {
   EGL_RED_SIZE, 8,
   EGL_GREEN_SIZE, 8,
   EGL_BLUE_SIZE, 8,
   EGL_ALPHA_SIZE, 8,
   EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
   EGL_NONE
      };

    static const EGLint context_attributes[] =
      {
   EGL_CONTEXT_CLIENT_VERSION, 2,
   EGL_NONE
      };   
    EGLConfig config;

    // get an EGL display connection
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    context = eglCreateContext(display, config, EGL_NO_CONTEXT,
                context_attributes);
    assert(context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    Uint32 maxW, maxH;
    success = graphics_get_display_size(0 /* LCD */, &maxW,
               &maxH);
    assert( success >= 0 );
    if(screen_width == 0) {
      screen_width = maxW; screen_height = maxH;
      dst_rect.x = 0;
      dst_rect.y = 0;
    } else {
      dst_rect.x = (maxW - screen_width)/2;
      dst_rect.y = (maxH - screen_height)/2;
    }
    dst_rect.width = screen_width;
    dst_rect.height = screen_height;
 
    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = screen_width << 16;
    src_rect.height = screen_height << 16;       

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
         
    dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
                     0, &dst_rect, 0, &src_rect,
                     DISPMANX_PROTECTION_NONE, 0, 0,
                     (DISPMANX_TRANSFORM_T)0);
     
    nativewindow.element = dispman_element;
    nativewindow.width = screen_width;
    nativewindow.height = screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );
     
    surface = eglCreateWindowSurface(display, config, &nativewindow, NULL );
    assert(surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(display, surface, surface, context);
    assert(EGL_FALSE != result);
  }
Posts: 1
Joined: Thu Jun 14, 2012 6:58 pm
by jmacey » Thu Jun 14, 2012 8:24 pm
thanks, for the suggestion of the 0 SDL window that does seem to improve things a little, I've got my own EGLWindow class that I use similar to the code you posted (however I have a EGLConfig class passed to the window creation) There are some demos here http://nccastaff.bournemouth.ac.uk/jmacey/GraphicsLib/piNGL/index.html
and here
http://jonmacey.blogspot.co.uk/2012/06/eglwindow-class.html

I'm not using X at all just running from the terminal and creating a full screen context.

Whilst the GPU processing is really fast I've found that the cpu side of things can be really slow (just testing a particle system that does updates on the software side and can only do 200-300 particles at any speed)
Posts: 135
Joined: Thu May 31, 2012 1:05 pm
by chris_c » Fri Jun 29, 2012 2:13 am
i've already done a low level keyboard routine for the rpi sections of my gles2framework (see github)

does raw keycode up and down into an array of bools

feel free to nick stuff, I'll be adding some kind of mouse support before long, but happy to hear ideas ....
Posts: 119
Joined: Sun May 06, 2012 10:23 am
by garethlewis » Fri Jun 29, 2012 4:47 pm
Hi chris,

did you do anything to stop the key presses from being echoed to the tty?

Gareth.
Posts: 6
Joined: Thu Jun 28, 2012 9:18 pm
by chris_c » Fri Jun 29, 2012 10:29 pm
i dont remember seeing any keys on the console you'd have to try...

in any case I use GPU scaling to scale a small-ish GLES context to fullscreen size so you can't see the console.
Posts: 119
Joined: Sun May 06, 2012 10:23 am
by chris_c » Sat Jun 30, 2012 8:05 am
just checked it consumes the keystrokes - nothing ever reaches the console afaict
Posts: 119
Joined: Sun May 06, 2012 10:23 am
by Peerlow » Fri Aug 24, 2012 11:05 am
Hello,

I have adapted one of the OpenGL demos included with the Debian Squeeze distro (the "official" one as of July 2012, when I received my Pi), and have integrated a threaded, queued mouse handler.

You can check it at:
http://www.virtualcode.es/article/mouse_opengles_integration_demo

Regards.
Posts: 2
Joined: Fri Aug 24, 2012 10:39 am