This topic provides information about the points that the EGL specification explicitly states are platform-specific. This information is aimed at both users and implementers of EGL on the Symbian platform.
Applications can find out whether ScreenPlay (also known as the New Graphics Architecture or NGA) is supported on the device at runtime.
To do this, call eglQueryString(display, EGL_EXTENSIONS) and search for the string EGL_SYMBIAN_COMPOSITION within the string returned. If EGL_SYMBIAN_COMPOSITION is present, it means that ScreenPlay is supported. For further information, see EGL Functions with Symbian-Specific Behavior.
By checking for the presence of the EGL_SYMBIAN_COMPOSITION string, you can create applications that can work on both ScreenPlay devices and those with the non-ScreenPlay architecture.
EGL window surfaces are on-screen rendering surfaces that are tied to Symbian windows. The RWindow class is a client-side handle to a Symbian Window Server window. You must create the RWindow before creating the EGL window surface for on-screen rendering.
Because the EGL window surface is implemented differently depending on whether ScreenPlay is in use, there are some differences in how you create an EGL window surface:
In ScreenPlay, the pixel format of the EGL window surface is determined entirely by the EGL config passed to eglCreateWindowSurface() and not by the properties of the RWindow.
On a non-ScreenPlay device, the display mode of the RWindow must match the buffer size of the EGL window surface. You can call RWindowBase::DisplayMode() const to retrieve the window’s display mode and use it to determine the buffer size when retrieving the EGL config to pass to eglCreateWindowSurface().
Threading. Because of the limitations of the Window Server API, clients must create and use an EGL window surface in the thread in which its RWindow was created. This means that the following are not supported and will lead to undefined behavior:
Creating an EGL window surface in thread B using an RWindow that was created in thread A.
Using an EGL window surface in thread B when that EGL window surface and its RWindow were created in thread A.
For example, in the second scenario, EGL in thread B will fail (with a WSERV panic) when it attempts to get the window size from the RWindow in thread A.
Buffer handling. By default EGL window surfaces have multiple buffers, which means that the client can draw to a back buffer, while the front buffer is being composed to the screen. The client must call eglSwapBuffers() to post the back buffer to the screen.
EGL 1.4 introduces a preserve buffer feature, which enables the content of the front buffer to be preserved from one frame to the next. This means that the client can provide incremental drawing operations rather than the entire drawing operations for each frame. This feature is usually off by default. This means that legacy applications that do not expect this feature are not slowed down by the unnecessary copying of the buffer contents.
Window resizing. The size of an application’s view can be changed by a variety of external events, such as a UI layout switch, a change in the size of the status pane or the rotation of the screen. An application can also resize a window directly, such as through a call to RWindow::SetExtent(), CCoeControl::SetExtent() or CCoeControl::SetExtentToWholeScreen().
When there is a change in the size of a window that is bound to an EGL window surface, the application must take appropriate action in its CCoeControl::SizeChanged() or CCoeControl::HandleResourceChange() implementation. The action depends on the nature of the application but might include clipping or scaling the contents to fit the resized window.
On the Symbian platform, EGL handles the window resize in the next call to eglSwapBuffers(), which resizes the surface to match the new window size. If the preserve buffer option is in use, this function also copies across all the pixels from the old surface that overlap the new surface, although the exact details depend on the implementation.
If the surface resize fails, eglSwapBuffers() returns EGL_FALSE and an EGL_BAD_ALLOC error is raised. This may mean that the implementation does not support the resizing of a surface or that there is not enough memory available (on a platform with GPU, this would be GPU rather than system memory). Applications must always monitor whether eglSwapBuffers() fails after a window resize. When it does fail, the application should do the following:
Call eglDestroySurface() to destroy the current EGL window surface.
Call eglCreateWindowSurface() to recreate the EGL window surface.
This may cause a noticeable flicker and so should be done only when necessary.
Screen rotation. There is no specific EGL handling for screen rotation—instead screen rotation is handled in the same way as a change of screen resolution. An application typically handles changes in screen resolution and rotation in its CCoeAppUi::HandleScreenDeviceChangedL() or CCoeControl::HandleResourceChange(TInt) implementation. When there is a change in screen rotation, the application may need to resize its windows and update the content accordingly.
The EGL implementation updates the surface size on the next call to eglSwapBuffers(). However, the interim frames appear in the new orientation, and so an application may want to adjust the contents to minimize flicker. If the application wants to accept the system rotation, it does not need to rotate its content. However, some applications may require a fixed physical orientation. These need to rotate the window content in order to counteract the physical rotation.
Sometimes a screen rotation simply results in the swapping of the window’s width and height dimensions—for example, when the application is running in full screen mode and the device is rotated from portrait to landscape or vice versa. This is guaranteed to succeed on all Symbian EGL implementations.
In other situations the screen rotation must be treated like a window resize and the application must monitor whether eglSwapBuffers() succeeds and take appropriate action if it fails, as described above. For example, if the application is not in full screen mode, rotating the device from portrait to landscape may not result in the swapping of the width and height of the window.
UI content. Applications that want to make use of the ScreenPlay ability to place semi-transparent CWindowGc rendering above the EGL window surface should check whether ScreenPlay is supported on the device as described above.
On ScreenPlay devices, you can combine CWindowGc drawing and OpenVG/OpenGL ES drawing in the same window, provided the CWindowGc content is drawn using a semi-transparent pen or brush color or bitmap. It is also possible to create semi-transparent CWindowGc drawing in another Symbian window placed over the EGL window. To do this, make the Symbian window semi-transparent by calling RWindow::SetTransparencyAlphaChannel(). Transparent Windows has more detail on implementing semi-transparent windows.
On non-ScreenPlay devices, you need to place the CWindowGc drawing in an opaque child window over the EGL window surface or implement the UI by using OpenVG/OpenGL ES drawing that is directed to the EGL window surface itself.
Window lifetime. Clients must maintain the RWindow associated with the EGL window surface for the lifetime of that window surface, provided they follow the good practice guidelines of unbinding the EGL window surface from the current context before destroying it. If these guidelines are not followed, it may be necessary to maintain the RWindow for the entire duration of EGL usage within the client application.
For example, the following pseudocode demonstrates good practice. The RWindow must be valid until eglDestroySurface() is called:
// Unbind the window surface from the current context. eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // Destroy the window surface. eglDestroySurface(display, surface); ... eglTerminate(display)
When the application does not follow this good practice and destroys the surface before unbinding it from the current context, the RWindow must be valid for longer. For example in the following pseudocode, RWindow must be valid until after eglMakeCurrent() is called:
eglDestroySurface(display, surface); eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); ... eglTerminate(display)
If eglMakeCurrent() is not called with a null surface and null context at all, the RWindow must be valid until eglTerminate() is called.
An EGL implementation can support the CFbsBitmap pointer as an EGLNativePixmapType. This means that it is possible to create an EGLSurface to render to a CFbsBitmap. However, it is not guaranteed to be supported on all EGL implementations.
Most EGL calls include an EGLDisplay parameter. The EGL specification describes this as "the abstract display on which graphics are drawn". On some systems, this corresponds to a physical screen. However, the details are platform specific and on Symbian systems, it does not correspond to a physical screen. When working on the Symbian platform, it is generally more useful to think of an EGLDisplay as the EGL session.
On Symbian systems, you usually use a single EGLDisplay. You get this by a call to eglGetDisplay() and passing EGL_DEFAULT_DISPLAY as the <display id> parameter.
The physical screen on which the content is displayed is determined by the window's parent window group. In Symbian, every window (RWindow) has a parent window group (RWindowGroup), as shown in the following diagram. When you create a window group, you can specify the screen on which it is to be shown.
When you create a window surface in EGL using eglCreateWindowSurface, you pass in the RWindow as an argument. The window surface is then displayed on the screen associated with that window's parent window group. Currently a window can exist on only one screen.
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.