Initialize your application

Before we can display anything on the screen using the BlackBerry Native SDK for Tablet OS, we need to do some initialization. We'll initialize the screen so that we can draw on it, and we'll set up some initial data for the Hello Native SDK application.
  1. In the Project Explorer view, open the main.c file, located in the src folder in the project.
  2. In main(), create a screen context. We use this context to initialize EGL to use a window surface. EGL is an interface between standard rendering APIs (like OpenGL ES) and underlying windowing systems. We also use this context to receive screen events.

    screen_create_context(&screen_cxt, 0);

  3. Initialize the BlackBerry Platform Services (BPS) library. This allows the application to receive and process events. We must perform this step before we can call any other BlackBerry Platform Services functions.

    bps_initialize();

  4. Initialize EGL using the screen context that we created. To do this, we use a utility function called bbutil_init_egl(). This function is part of bbutil.h, which was included automatically when we created the project. The bbutil.h file is a collection of utility code that, among other things, handles EGL interactions that are typical for games and similar applications. You can take a look at bbutil_init_egl() to see how you can initialize a native surface. You don't have to use the functions in bbutil.h (you can work with EGL directly in your own applications, if you prefer), but they're provided as helper functions and are ready to use. If the EGL initialization doesn't succeed, we print an error to stderr, clean up the EGL surface by calling bbutil_terminate() (another utility function in bbutil.h), destroy the screen context, and close the application.

    if (EXIT_SUCCESS != bbutil_init_egl(screen_cxt)) {
        fprintf(stderr, "bbutil_init_egl failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        return 0;
    }

    Initialize the application data by calling initialize().

    if (EXIT_SUCCESS != initialize()) {
        fprintf(stderr, "initialize failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        return 0; 
    }

In initalize(), do the following:

  1. Initialize the vertices of the square in the application. Each pair of values represents the coordinates of a corner, or vertex, of the square.

    vertices[0] = -0.25f;
    vertices[1] = -0.25f;
    
    vertices[2] = 0.25f;
    vertices[3] = -0.25f;
    
    vertices[4] = -0.25f;
    vertices[5] = 0.25f;
    
    vertices[6] = 0.25f;
    vertices[7] = 0.25f;

  2. Initialize the colors of the square. Here, we're specifying the color of each vertex in the square using RGBA color components, so the first four values correspond to the color defined by R=1.0, G=0.0, B=1.0, and A=1.0.

    colors[0] = 1.0f;
    colors[1] = 0.0f;
    colors[2] = 1.0f;
    colors[3] = 1.0f;
    
    colors[4] = 1.0f;
    colors[5] = 1.0f;
    colors[6] = 0.0f;
    colors[7] = 1.0f;
    
    colors[8] = 0.0f;
    colors[9] = 1.0f;
    colors[10] = 1.0f;
    colors[11] = 1.0f;
    
    colors[12] = 0.0f;
    colors[13] = 1.0f;
    colors[14] = 1.0f;
    colors[15] = 1.0f;

  3. Obtain the width and height of the EGL surface that was created using the initialization functions in bbutil.h. We'll use these values to position the square on the screen. We also determine whether obtaining the width and height values resulted in any errors. Here, the return value of eglGetError() is compared against 0x3000 (EGL_SUCCESS) to determine whether any errors occurred.

    EGLint surface_width, surface_height;
    
    eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
    eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
    
    EGLint err = eglGetError();
    if (err != 0x3000) {
        fprintf(stderr, "Unable to query egl surface dimensions\n");
    		  return EXIT_FAILURE;
    }

  4. Call glShadeModel() to use smooth shading when the colors are computed between the square's vertices. Smooth shading causes the colors to be interpolated at runtime to provide a smooth transition between vertices.

    glShadeModel(GL_SMOOTH);
  5. Set the background color to white by calling glClearColor(). Setting it to white makes the square more visible.

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

  6. Initialize a simple orthographic projection for rendering.

    glViewport(0, 0, surface_width, surface_height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    glOrthof(0.0f, (float) (surface_width) / (float) (surface_height), 0.0f,
        1.0f, -1.0f, 1.0f);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glTranslatef((float) (surface_width) / (float) (surface_height) / 2, 0.5f,
        0.0f);
    
    return EXIT_SUCCESS;

In main(), we request events from the screen and the navigator so that the application can process them. We want our application to respond to touch events and navigator events. When we request screen and navigator events, we check to see whether the requests were successful. If not, we clean up and close the application.

if (BPS_SUCCESS != screen_request_events(screen_cxt)) {
    fprintf(stderr, "screen_request_events failed\n");
    bbutil_terminate();
    screen_destroy_context(screen_cxt);
    return 0;
}

if (BPS_SUCCESS != navigator_request_events(0)) {
    fprintf(stderr, "navigator_request_events failed\n");
    bbutil_terminate();
    screen_destroy_context(screen_cxt);
    return 0;
}

Indicate to the BlackBerry Platform Services library that we don't want to lock device orientation. At the result of this code block, BlackBerry Platform Services generates an orientation change event that you can handle in your code. Take a look at the orientation recipe for more details on orientation change handling.

if (BPS_SUCCESS != navigator_rotation_lock(false)) {
    fprintf(stderr, "navigator_rotation_lock failed\n");
    bbutil_terminate();
    screen_destroy_context(screen_cxt);
    return 0;
}