This topic provides an introduction to graphics composition surfaces, which are usually simply called surfaces. Surfaces are pixel buffers that have associated metadata describing the width, height, stride and pixel format and are used as input to the composition components. Surfaces can be multi-buffered and are identified by a 128-bit identifier (called the surface ID).

Variant: ScreenPlay. Target audience: Device creators.

Surfaces that are used as input to the composition engine are shared between at least two processes: the Window Server process (in which the composition engine runs) and a renderer, which is responsible for rendering the content to the surface. The camera viewfinder, the video renderer and EGL are examples of renderers. Each process needs to access the surface to read or write (draw) data. Other processes may also need one or both types of access. Each of these processes uses the surface ID to gain access to the surface or its properties.

The Surface Update component provides a two-way communication channel between the composition engine and the renderers. This allows a renderer to notify the composition engine when the content of a buffer within the surface has been updated and a scene composition is required. Similarly, the Surface Update Server allows the composition engine to notify the renderer of the composition status.

The surface ID

The surface ID is a 128-bit number used to identify a surface. It is represented by the TSurfaceId class which comprises four 32-bit integers. One byte is used to store a number representing the surface type. Symbian defines the following surface types:

  • An invalid surface (EInvalidSurface, type 0),

  • A screen surface (EScreenSurface, type 1)

  • A Surface Manager surface (ESurfaceManagerSurface, type 33).

In addition types 34 to 255 are available for device creators to define their own types of rendered surfaces. Screen surface types are enumerated in Surface.h. Rendered surface types are enumerated in SurfaceTypes.h.

The other 120 bits uniquely identify the surface and are used according to the surface type. Surface Manager IDs are generated automatically by the Surface Manager when new surfaces are created. The reference implementation generates them randomly in order to minimize the possibility of the IDs being guessed.

A typical life cycle

Creating a surface

Surfaces can be created by using the Surface Manager API. To do this, you first create an instance of the client-side class RSurfaceManager. This encapsulates the complexities of device driver communication, memory management and thread safety. To create a surface, you must specify the number of buffers and low-level properties, such as pixel format, stride and memory contiguity. See Creating a Graphics Surface Tutorial for more information.

Binding the surface to a window

You bind a surface to a window by calling RWindowBase::SetBackgroundSurface(). You can apply a number of configuration settings to the surface, such as viewport, rotation and extent. These crop, scale and rotate the surface content. If the configuration is not set, the entire surface is mapped to the window extent with normal orientation. See External Surfaces Overview for more information.

Rendering content to the surface and composition

The renderer renders the graphics content directly to a buffer within the surface. The renderer then sends a request to the composition engine through the Surface Update component to indicate that the surface is ready for composition. The renderer specifies the surface ID, the ID of the current buffer within the surface and optionally the dirty rectangle and the screen on which the surface is to be displayed. Alternatively the request can be broadcast to all screens (this is called a global surface update).

The composition engine then includes the surface in the next composition cycle. Because this can take some time, the composition engine carries out the composition asynchronously. The composition engine can notify the client when the buffer is available for rendering into again, in order to prevent tearing or artefacts. The composition engine can also notify the client when the buffer has been displayed a specified number of times, in order to ensure that each frame gets displayed for at least a given period of time. For more information, see Surface Update Component Overview.

Note: In graphics, the term artefact is used to refer to an error that occurs when displaying or drawing an image on the screen. Tearing is a particular type of error in which part of the current frame and part of the previous frame are seen on the screen at the same time. This makes the image appear torn. Tearing is considered a serious error.

Removing the surface from window

You remove a surface from a window by calling RWindowBase::RemoveBackgroundSurface(). This removes the surface and redraws the window.

Registering the surface for use on a screen

You can optionally register a surface as a separate step before adding it as a background to a window. This enables the client to send a surface update to set up the first buffer that will be displayed when the surface is attached to a window. You register a surface by using RWsSession::RegisterSurface().

A given surface can be registered in multiple sessions and on multiple screens. However, you must not call RWsSession::RegisterSurface() more than once per session for a given combination of surface and screen, without explicitly unregistering the surface first.

Explicitly registered surfaces can be unregistered in two ways:

When the session is closed, all of the surfaces explicitly registered with that session are unregistered. Closing a session also closes any windows associated with that session. Any surfaces directly assigned to those windows are also unregistered.