Setting up OpenGL ES

There are three main APIs that you can use to create a basic OpenGL ES app: the native window (Screen API), EGL, and a version of OpenGL ES. To render OpenGL ES models to the native window, you need to connect the APIs. After you establish a connection between the native window and EGL, you can use OpenGL ES to render to EGL surfaces.

The native windowing system is used for both Cascades and core native C/C++ apps. Core native C/C++ apps can use the navigator service (life cycle and state manager) and BlackBerry Platform Services events. For more information, see Using EGL to connect a native window and OpenGL ES and Drawing with OpenGL ES.

Cascades apps handle life cycle events with other APIs. For more information, see Using OpenGL ES in Cascades.

Add a native window

The BlackBerry 10 OS and the BlackBerry PlayBook OS use the native windowing system that is defined by the Screen API (also known as libscreen). The Screen API is a resource manager that provides compositing and low-level windowing services. You can use this native windowing system and EGL to render OpenGL ES models to the screen.

Prerequisites

In the Momentics IDE for BlackBerry, link the Screen Graphics Subsystem (libscreen) library.

Set up a native window

To set up a native window, create a screen context and then create a window from that context.

Not applicable

Not applicable

#include <screen/screen.h>
    screen_context_t screen_ctx;
    screen_window_t screen_win;
    
    screen_create_context(&screen_ctx, 0);
    screen_create_window(&screen_win, screen_ctx);

You can set a usage variable for properties of the window depending on your app's needs. These properties are predefined enumerations from screen.h. For a basic native window, set the usage variable to SCREEN_USAGE_NATIVE. You must also set the usage property to correspond to the version of OpenGL ES that you're using. Use SCREEN_USAGE_OPENGL_ES1 for OpenGL ES 1.1, SCREEN_USAGE_OPENGL_ES2 for OpenGL ES 2.0, and SCREEN_USAGE_OPENGL_ES3 for OpenGL ES 3.0. To combine flags into a variable, use a bitwise OR. For example, you can use OpenGL ES 1.1 and allow screen rotations (usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION).

Not applicable

Not applicable

    const int usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION;
    screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);

And that's the basic window setup. Now, you can attach buffers to the window and post the window after the buffers are attached.

Add buffers to the window

You can call screen_create_window_buffers() to let libscreen create the buffers and attach them to the window.

Not applicable

Not applicable

    screen_create_window_buffers(screen_win, 2);

All BlackBerry 10 apps must use two window buffers to avoid visual faults, such as tearing. These faults can happen when the app changes state, such as from a maximized app to minimized app. The Screen API blends windows together because of transparency values of windows or when windows transition from the navigator. A single-buffered window that is actively drawing (at least 60 fps) might get visual glitches, because the app is rendering to the same buffer that the compositor is using.

When using a double-buffered window, the app renders to the back buffer and the compositor samples the front buffer.

Query the buffer and post the window

When you attach the buffers to the window, you can obtain the buffer to use by querying the SCREEN_PROPERTY_RENDER_BUFFERS bitmask. In the code sample below, the rect array acts as the bounds of the screen buffer: The first two values are the x and y coordinates of the upper-left corner, and the next two values are the x and y coordinates of the lower-right corner.

Not applicable

Not applicable

    int rect[4] = { 0, 0, 0, 0 };
        screen_buffer_t screen_buf = NULL;

    screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf);
    screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);

Now, you can change the buffer. To post the changes to the window, call the screen_post_window() function and pass in the window, the buffers, the number of bounding rectangles, the rect array, and any posting flags.

Not applicable

Not applicable

    screen_post_window(screen_win, screen_buf, 1, rect, 0);

Clean up your native window

When your app doesn't need the window and context anymore, clean them up by using the following code:

Not applicable

Not applicable

    screen_destroy_window(screen_win);
    screen_destroy_context(screen_ctx);

For more information about using the Screen API, see Screen Graphics Subsystem Library.

Add the life cycle manager

The navigator service, defined in navigator.h, manages your app's life cycle events. The Navigator API is a high-level windowing framework that handles many aspects of the app's life cycle including app window resizing, permissions, focus control, orientation changes, app start/termination, and more.

The navigator service is provided by the BlackBerry Platform Services library. The BlackBerry Platform Services library also contains an event API for some of its services, such as navigator and screen. You must include the BlackBerry Platform Services event API to obtain navigator and screen events. For more information about navigator events, including life cycle events, see App life cycle.

Prerequisites

In the Momentics IDE for BlackBerry, link the BlackBerry Platform Services (libbps) library.

Set up the navigator and event APIs

To add the navigator service to your app, call bps_initialize() to start the BlackBerry Platform Services. Then, start receiving navigator events using the navigator_request_events() function. A parameter of 0 indicates that all regular events are requested. To request screen events, call screen_request_events(), passing the initialized screen context.

Not applicable

Not applicable

#include <bps/navigator.h>
#include <bps/event.h>
#include <bps/screen.h>
#include <screen/screen.h>
screen_context_t screen_ctx;
bps_initialize();
navigator_request_events(0);
screen_request_events(screen_ctx);

Next, you need a main app loop to check for events. You can use a flag variable for the loop condition, which is set when the NAVIGATOR_EXIT event is received. You need a bps_event_t structure to hold the event, and then you can call bps_get_event() to obtain the event. Use a negative timeout value to block until an event is available.

Not applicable

Not applicable

    int check = 0;

    while ( check == 0 ) {
        int rc, domain;

        bps_event_t *event = NULL;
        
        rc = bps_get_event(&event, -1);

To process the event, get the event's domain code by calling bps_event_get_domain(event). Check the event against the domains you're looking for (for example, handle only navigator and screen domain events). To check for navigator and screen domains, verify if domain == navigator_get_domain() or if domain == screen_get_domain(), respectively, for each type.

If you have the proper domain, you have an event to handle. Obtain the event code by calling bps_event_get_code(event) and use a switch statement to separate the event cases. In the following code sample, for the navigator service, handle swipe down and exit events. For the Screen API, handle touch, move, and release events.

Not applicable

Not applicable

       if (event) {
            domain = bps_event_get_domain(event);
            if (domain == navigator_get_domain()) {
                switch (bps_event_get_code(event)) {
                case NAVIGATOR_SWIPE_DOWN:
                    fprintf(stderr,"Swipe down event");
                    break;
                case NAVIGATOR_EXIT:
                    fprintf(stderr,"Exit event");
                    check = 1;
                    break;
                default:
                    break;
                }
                fprintf(stderr,"\n");
            } else if (domain == screen_get_domain()) {
                    int screen_val;

                    screen_event_t screen_event = screen_event_get_event(event);
                    screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val);

                    switch (screen_val) {
                    case SCREEN_EVENT_MTOUCH_TOUCH:
                        fprintf(stderr,"Touch event");
                        break;
                    case SCREEN_EVENT_MTOUCH_MOVE:
                        fprintf(stderr,"Move event");
                        break;
                    case SCREEN_EVENT_MTOUCH_RELEASE:
                        fprintf(stderr,"Release event");
                        break;
                    default:
                        break;
                    }
                    fprintf(stderr,"\n");            }
            }
    }

For more information on the event codes for the navigator service, see API reference for data types, which contains main event codes, window state events, and other events.

For more information about the event codes for the Screen API, see Screen event types.

Clean up the navigator and event APIs

When you exit your main app loop, you should clean up your resources. In this case, you need to stop receiving screen events by calling screen_stop_events(screen_ctx) and turn off the BlackBerry Platform Services services, which also stops navigator events. If you're receiving other event types that are not included in this code sample, make sure that you request to stop receiving events for that type.

Not applicable

Not applicable

screen_stop_events(screen_ctx);
bps_shutdown();

For more information about the navigator service, see the Navigator API reference.

Add OpenGL ES libraries

When you use OpenGL ES in your app, you need to add the library to your code. You need to include EGL (libEGL) and Screen Graphics Subsystem (libscreen). You also need to include the appropriate OpenGL ES library depending on the version that you're using.

Prerequisites

Add the following include directives depending on your app:

EGL
#include <EGL/egl.h>
OpenGL ES 1.1 and extensions library
#include <GLES/gl.h>
#include <GLES/glext.h> /*OpenGL ES extensions library*/
OpenGL ES 2.0
#include <GLES2/gl2.h>
OpenGL ES 3.0
#include <GLES3/gl3.h>

In the Momentics IDE, link the OpenGL ES (libGLES_CM, libGLESsoftgl, libGLESv1_CL, libGLESv1_CM, libGLESv2) library that you need.

Use OpenGL ES templates

The Momentics IDE provides two sample OpenGL ES templates that you can use to build your app. Each template corresponds to an OpenGL ES version (1.1 or 2.0). The templates provide standard code to help you set up your app for OpenGL ES. For more information about creating a project using a template, see Managing projects.

Both OpenGL ES templates use a bbutil API that contains common utilities for OpenGL ES 1.1 and 2.0. If you import the bbutil API into a separate project, you must set a flag in your common.mk file or define a macro in your code to specify a version to use.

If you're using OpenGL ES 1.1, do one of the following:

  • Add the following line to your common.mk file: CCFLAGS+=-DUSING_GL11
  • Add the following line to bbutil.c immediately after the inclusion libraries: #define USING_GL11

If you're using OpenGL ES 2.0, do one of the following:

  • Add the following line to your common.mk file: CCFLAGS+=-DUSING_GL20
  • Add the following line to bbutil.c immediately after the inclusion libraries: #define USING_GL20

Last modified: 2015-05-07



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus