Hybrid Rendering

When applications use a mix of rendering options, your application must ensure that there's synchronization between your rendering types (e.g., software rendering, Khronos APIs rendering, and blitting).

The following example demonstrates how you'd mix software rendering with Khronos rendering APIs. You need to follow these steps to set up your render target and context:

  1. Create your render target.
  2. Create a rendering context.
  3. Render.
  4. Post your image.
Note:

If you're using both software and Khronos API rendering, your hardware's driver must support the EGL_KHR_lock_surface extension if you want to use both software and this type of hardware rendering together.

Refer to Khronos's specifications on eglLockSurfaceKHR(), eglQuerySurface(), and eglUnlockSurfaceKHR() for more details on these functions (www.khronos.org).

Create your render target

Follow the same steps as you would to create a render target for hardware rendering using Khronos rendering APIs with the exception of setting the usage flag.

When using hybrid rendering, you need to ensure that the SCREEN_PROPERTY_USAGE flag is to indicate that the buffer associated with the render target will be rendered to by OpenGL ES as well as being written to by software:

...
int usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_WRITE;
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
...
                

Create a rendering context

Follow the same steps as you would to create a render context for hardware rendering using Khronos rendering APIs.

Render

Render as you would using OpenGL ES API calls until you intend to perform some rendering with software. At this point, you must get access to the buffer you want to render to through EGL, rather than through Screen.

Unlike when you use software rendering alone, you can't use the buffer of your render target that you retrieve with SCREEN_PROPERTY_RENDER_BUFFERS because your render target (e.g., native Screen window) is bound to an EGL rendering surface. As you perform GL operations, these rendering calls may be deferred and only rendered to the surface when there's a finish or lock command. The point in time when the rendering is complete on the surface may depend on your hardware. Other reasons that could cause your buffer to be indeterminate could be anti-aliasing, or cache coherency to name a few.

Because the status of the rendering and the buffer can't be determined at the time you want to render in software, you need to let the hardware know your intentions to write to the buffer. You do this by using eglLockSurfaceKHR() followed by eglQuerySurface().

Before any software rendering, call eglLockSurfaceKHR() on the surface you want to write to. This function notifies the hardware that you want access to the buffer. The rendering may or may not be rendered to the surface by the hardware at this time, but in the least, it will signify that no more rendering operations will be performed by the hardware at this point. Next, retrieve the pointer to the buffer (EGL_BITMAP_POINTER_KHR) by calling eglQuerySurface(). Some of the valid attributes you can retrieve through the eglQuerySurface() are:

The time it takes to lock the surface and to retrieve the pointer to the buffer depends entirely on the implementation of your driver.

Once you've locked the EGL surface and retrieved the buffer pointer from EGL, you can proceed to write to the buffer as your application sees fit. When you've completed writing to the buffer and wish to continue with more GL operations, then you need to unlock the surface before making any OpenGL ES rendering API calls. Unlock the surface by calling eglUnlockSurfaceKHR().

The order of rendering calls in your application should go something like this:

...
/* Render using some GL operations */
glClear((GL_COLOR_BUFFER_BIT);
glPushMatrix();
...
/* Now you want to render with software */
eglLockSurfaceKHR(egl_disp, egl_surf, (EGLint*)&egl_surf_attr);
...
/* Now get a pointer to the buffer you want to write to */
EGLint *buf_ptr = NULL;
eglQuerySurface(egl_disp, egl_surf, EGL_BITMAP_POINTER_KHR, buf_ptr); 
...
/* write to buffer */
...
/* Finished writing, unlock the surface */
eglUnlockSurfaceKHR(egl_disp, egl_surf);
...
/* Continue to render using GL operations if you wish */
...
            

Post your image

Follow the same steps as you would to post an image for hardware rendering using OpenGL ES (using eglSwapBuffers()).