ComputerWorld Part 2

LovePosted by Eskil Sat, December 18, 2010 00:24:55

Betray is an easy to use portability library that lets you build single window OpenGL applications. It can be compared to GLUT or SDL, but has a more streamlined interface and supports a few more things. A very important feature of Betray is that it lets you write a single application that supports many different modes of input and outputs. The idea is not just to make it easy for application developers to write portable applications, but also for people who either make, or have access to special hardware to write their own versions of betray, so that all existing betray applications will support the hardware. It makes it much easier for hardware or interface developers, to test out their hardware with existing software. Closed source applications like Betray will soon be released with an Open source betray DLL so that anyone can rewrite it to work with any kind of input and output devices. The file b_test.c is a simple example program using much of the Betray API.

I invite anyone who wants to, to use, test, debug or help me to port betray to other platforms or hardwares to do so. If you are interested E-mail me at eskil at obsession dot se


While its good for Betray implementations to support as much as possible of the Betray API, this isnt always possible. A particular hardware may lack features such as pointer device of multi touch. Even if a feature is not implemented it still needs to be present in terms of API entry's, and should return reasonable default values, to make it easier to support. By using the functions betray_support_context and betray_support_functionality you can ask the implementation functionality is active in the implementation.

To initialize betray and create a screen you call the following:

void betray_init(BContextType context_type, int argc, char **argv, uint window_size_x, uint window_size_y, boolean window_fullscreen, char *name);

Currently Betray only supports OpenGL contexts, but in the future it may be extended to support other rendering contexts too. Once betray has been initialized you can use the functions, betray_action_func_set to give betray a function pointer to the action function that will act as the programs main loop, then call betray_launch_main_loop to start the applications main loop. The Main loop function will be called with a pointer to the structure BInputState that contains useful input state. In this structure you will also find the member "mode" that can be set to either, BAM_DRAW, BAM_EVENT, or BAM_MAIN. This member indicates why the main loop has been called, to either redraw the screen, handle input or compute (the compute call is where time should be advanced, and will be called even if the program has been minimized and is therefor useful to keep things like network connections alive that are not dependent on either being displayed or requires input form the user). The reason for having a single entry point for all three is that you can build nice libraries of interface functions that can handle all 3 modes. Consider this function:

boolean my_button(BInputState *input, float pos_x, float pos_y, char *name)

This function can now handle both drawing and handling input, independently, and the user only have to add it once to the code base, even if it gets called multiple times for different reasons.


While betray_init immediately gets you a screen to draw to, you can at any time modify the screen mode using betray_screen_mode_set. By setting x_size and/or y_size to zero in either betray_screen_mode_set or betray_init betray will revert to the size of the desktop. To find out the current size and state of the draw surface you can call betray_screen_mode_get that will also return the aspect ratio of the screen. In order to support head tracking and stereoscopic (3D) programs should use betray_view_vantage betray_view_direction to retrieve the position of the eye in relation to the screen and any camera rotations or movements.

Betray has a few OpenGL specific functions like betray_gl_proc_address_get to get access to extension function pointers, and betray_gl_context_update_func_set where the user can give betray a function pointer that will be called if the current OpenGL state is lost (this usually happens when screen modes are changed). To make it possible for a Betray implementation to render the entire application to a texture using FBOs, the function betray_gl_screen_fbo_get exists. When ever the betray application is using FBOs and would like to reset the draw target to 0 (the screen) it should instead reset it to the value returned by betray_gl_screen_fbo_get.


The input is divided in to 3 different category's, pointers, axis and buttons and Betray can support any number of each. Pointers are 2 dimensional screen pointers with one or more buttons. You can read out their position, delta position and the position of their last primary click. The later can be very useful when implementing buttons since a button can check both if a pointer is on a button and if it was at the tim of the click, and that means buttons does not need to store state. Using betray_set_mouse_warp the application can hide and continually warp the mouse pointer to the center of the screen in order to avoiding hitting the edges, something very useful for first person mouse controls. Buttons on pointing devices show both their current state and the state they were in the last frame, and it is therefore possible to know if the button is being pressed, released or held. For all buttons you can use the betray_button_get_up_down to store your own state for any button you want. If the user is expected to type in text, it is good to call betray_button_keyboard to enable betray to show a on-screen keyboard on platforms without physical keyboards. Axis are essential any 1, 2 or 3 dimensional input such as joysticks, pedals, accelerometers and so on.


Betray also has a API for 3D sounds that lets you load sounds (using betray_audio_sound_create), set a listener (using betray_audio_listener) and then play the sounds (using betray_audio_sound_play). Once a sound has been started it can be modified using betray_audio_sound_set and betray_audio_sound_stop.


To help betray applications better integrate with the operating system it also supports accessing text strings from the clipboard, and the ability to launch open and save file requesters.


Finally betray supports basic thread functionality that lets you create threads and create, lock and unlock thread safe locks.


Betray has just been rewritten and I have yet to port over Love or any other applications to the new API. Seduce will be the first library that will be ported over to the new version of betray. At the moment Betray is only implemented for Win32, but other operating systems will soon follow. I hope to get as many developers as possible to use and contribute to Betray so that we can make multi platform development easier for everyone.

The library can be downloaded from
Or you can view the betray.h file at

  • Comments(5)//