3.0 Porting Guide/Graphics and UI/TDM

From Tizen Wiki
Jump to: navigation, search

Read Tizen Display Manager (TDM) first to get the general information of TDM and TDM backend.

The display server composites and shows the client's buffers on screen. The display server sometimes needs to convert or scale an image to a different size or format. To make it possible for various chipset devices, the display server needs the display hardware resource information and control them. Tizen Display Manager (TDM) offers these functionalities for the display server with the unified interface for various chipset devices.

Tdm-backend.png

With TDM, the display server can do the mode setting, the DPMS control and showing a buffer (framebuffer or video buffer) on the screen in the most efficient way. If the hardware supports the m2m converting and capture device, the display server can also convert an image and dump a screen including all hardware overlays with no compositing.

The vendor has to implement the TDM backend module. The TDM backend module has the responsibility to let the TDM frontend know the display hardware resource information. The display server gets this information and control hardware devices via the TDM frontend APIs. TDM already has several backends for reference, such as libtdm-drm and libtdm-fbdev.

The TDM backend is implemented as a shared library and the TDM frontend finds the libtdm-default.so file and loads it in the /usr/lib/tdm directory at runtime.

sh-3.2# ls -l /usr/lib/tdm
total 40
lrwxrwxrwx 1 root root    14 Jul 28  2016 libtdm-default.so -> libtdm-drm.so
-rwxr-xr-x 1 root root 37152 Jul 12  2016 libtdm-drm.so

The TDM backend module must define the global data symbol with the name tdm_backend_module_data. The TDM frontend reads this symbol at the initialization time. TDM calls the init() function of the tdm_backend_module_data. For more information, see tdm_backend.h.

typedef struct _tdm_backend_module {
    const char *name; /* The module name of the backend module */
    const char *vendor; /* The vendor name of the backend module */
    unsigned long abi_version; /* The ABI version of the backend module */
    tdm_backend_data *(*init)(tdm_display *dpy, tdm_error *error);
    void (*deinit)(tdm_backend_data *bdata);
} tdm_backend_module;
#include <tdm_backend.h>

static tdm_drm_data *drm_data;

tdm_backend_data*
tdm_drm_init(tdm_display *dpy, tdm_error *error)
{
    drm_data = calloc(1, sizeof(tdm_drm_data));

    return (tdm_backend_data*)drm_data;
}

void
tdm_drm_deinit(tdm_backend_data *bdata)
{
    free(bdata);
}

tdm_backend_module tdm_backend_module_data =
{
    "drm",  
    "Samsung",
    TDM_BACKEND_SET_ABI_VERSION(1,1),
    tdm_drm_init,
    tdm_drm_deinit
};

The TDM backend must register the tdm_func_display(), tdm_func_output(), and tdm_func_layer() functions with the tdm_backend_register_func_display(), tdm_backend_register_func_output(), and tdm_backend_register_func_layer() functions in the tdm_backend_module_data init() function.

#include <tdm_backend.h>

tdm_backend_data*
tdm_drm_init(tdm_display *dpy, tdm_error *error)
{
    memset(&drm_func_display, 0, sizeof(drm_func_display));
    drm_func_display.display_get_capability = drm_display_get_capability;
    drm_func_display.display_get_pp_capability = drm_display_get_pp_capability;
    drm_func_display.display_get_outputs = drm_display_get_outputs;
    drm_func_display.display_get_fd = drm_display_get_fd;
    drm_func_display.display_handle_events = drm_display_handle_events;
    drm_func_display.display_create_pp = drm_display_create_pp;
    ret = tdm_backend_register_func_display(dpy, &drm_func_display);
    if (ret != TDM_ERROR_NONE)
        goto failed;

    memset(&drm_func_output, 0, sizeof(drm_func_output));
    drm_func_output.output_get_capability = drm_output_get_capability;
    
    ret = tdm_backend_register_func_output(dpy, &drm_func_output);
    if (ret != TDM_ERROR_NONE)
        goto failed;

    memset(&drm_func_layer, 0, sizeof(drm_func_layer));
    drm_func_layer.layer_get_capability = drm_layer_get_capability;

    ret = tdm_backend_register_func_layer(dpy, &drm_func_layer);
    if (ret != TDM_ERROR_NONE)
        goto failed;

   if (tdm_hwc) {
        ret = tdm_backend_register_func_hwc(dpy, &drm_func_hwc);
	if (ret != TDM_ERROR_NONE)
		goto failed_l;

	ret = tdm_backend_register_func_hwc_window(dpy, &drm_func_hwc_window);
	if (ret != TDM_ERROR_NONE)
		goto failed_l;
   }

    return (tdm_backend_data*)drm_data;
}

After loading the TDM backend module, the TDM frontend calls the display_get_capability(), display_get_outputs(), output_get_capability() to get the specific information of the hardware. The TDM backend module has to set the TDM_OUTPUT_CAPABILITY_HWC on the output when it supports TDM HWC(HardWare Compositing). In Tizen 5.5 or later, TDM recommends that the TDM backend module supports TDM HWC which means that it has to registers the tdm_func_hwc and tdm_func_hwc_window. If TDM backend module does not support TDM HWC, the TDM backend module implements the output_get_layers(), and the layer_get_capability() functions and register tdm_func_layer.

In addition, if a target has a memory-to-memory converting hardware device and the capture hardware device, the TDM backend module can register the tdm_func_pp() and tdm_func_capture() functions with the tdm_backend_register_func_pp() and tdm_backend_register_func_capture() functions.

Porting OAL Interface

TDM provides the header files to implement the TDM backend module.

Header file Description
tdm_backend.h This file defines the TDM backend interface.
tdm_log.h This file to print logs in frontend and backend modules.
tdm_helper.h This file to help TDM backend/frontend user to implement.

The display backend interface is mandatory. For more information, see tdm_backend.h.

Function Description
display_get_capability() Gets the display capabilities of the backend module.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. If the hardware has the restriction of the number of max usable layer count, the backend module can set the max count to max_layer_count of the tdm_caps_display structure. Otherwise, set -1.

Mandatory
display_get_pp_capability() Gets the pp capabilities of the backend module.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. The backend module does not need to implement this function if the hardware does not have the memory-to-memory converting device. Otherwise, the backend module must fill the tdm_caps_pp data. The tdm_caps_pp contains the hardware restriction information which a converting device can handle, such as format and size.

Optional
display_get_capture_capability() Gets the capture capabilities of the backend module.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. The backend module does not need to implement this function if the hardware does not have the capture device. Otherwise, the backend module must fill the tdm_caps_capture data. The tdm_caps_capture contains the hardware restriction information which a capture device can handle, such as format and size.

Optional
display_get_outputs() Gets an output array of the backend module.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. The backend module must return the newly-allocated array which contains tdm_output* data. It is freed in the frontend.

Mandatory
display_get_fd() Gets the file descriptor of the backend module.

The backend module can return the epoll's fd.

Optional
display_handle_events() Handles the events which happens on the fd of the backend module. Optional
display_create_pp() Creates a pp object of the backend module.

The backend module does not need to implement this function if the hardware does not have the memory-to-memory converting device

Optional

The output backend interface is mandatory. For more information, see tdm_backend.h.

Function Description
output_get_capability() Gets the capabilities of a output object.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. The tdm_caps_output contains connection status, modes, available properties, and size restriction information.

Mandatory
output_get_layers() Gets a layer array of a output object.

TDM calls this function not only at the initialization, but also at the update time when new output is connected. The backend module must return the newly-allocated array which contains tdm_layer* data. It is freed in the frontend.

Mandatory
output_set_property() Sets the property with a given ID. Optional
output_get_property() Gets the property with a given ID. Optional
output_wait_vblank() Waits for VBLANK.

If this function returns TDM_ERROR_NONE, the backend module must call a user vblank handler with the user data of this function after interval vblanks.

Mandatory
output_set_vblank_handler() Sets the user vblank handler. Mandatory
output_commit() Commits the changes for an output object.

When this function is called, the backend module must apply all changes of the given output object to screen as well as the layer changes of this output. If this function returns TDM_ERROR_NONE, the backend module must call a user commit handler with the user data of this function after all changes of the given output object are applied.

Mandatory
output_set_commit_handler() Sets a user commit handler. Mandatory
output_set_dpms() Sets the DPMS of an output object. Optional
output_get_dpms() Gets the DPMS of an output object Optional
output_set_mode() Sets one of the available modes of an output object. Mandatory
output_get_mode() Gets the current mode of an output object. Mandatory
output_create_capture() Creates a capture object of an output object.

The backend module does not need to implement this function if the hardware does not have a capture device.

Optional
output_set_status_handler() Sets an output connection status handler.

The backend module must call the output status handler when the output connection status has been changed to let the TDM frontend know the change.

Optional
output_set_dpms_handler() Sets an output DPMS handler.

The backend module must call the output DPMS handler when the output DPMS has been changed to let the TDM frontend know the change.

Optional
output_get_hwc() Get a hwc object of a output object.

The backend module returns the hwc object when the output has TDM_OUTPUT_CAPABILITY_HWC.

Mandatory

The hwc backend interface is mandatory in Tizen 5.5 or later. For more information, see tdm_backend.h.

Function Description
hwc_create_window() Create a new window on the given hwc.

The backend module must implement this function. The backend creates a private tdm_hwc_window and returns the handle of it.

Mandatory
hwc_get_video_supported_formats() Get video the supported format array for the hwc windows of a hwc object. Mandatory
hwc_get_video_available_properties() Get the available video property array of a hwc object.

The backend returns the video properties which is predefined in the backend module.

Mandatory
hwc_get_capabilities() Get the hwc capabilities

The backend returns the multiple of the tdm_hwc_capability which the backend can support.

Mandatory
hwc_get_available_properties() Get the available property array of a hwc object.

The backend returns the properties which is predefined in the backend module.

Mandatory
hwc_get_client_target_buffer_queue() Get a target buffer queue

The backend returns the tbm_surface_queue_h.

Mandatory
hwc_set_client_target_buffer() Set the client(relative to the TDM) target buffer

The target buffer is from the tbm_surface_queue_h which contains the result of the gl composition with the tdm_hwc_windows which marked as TDM_HWC_WIN_COMPOSITION_CLIENT.

Mandatory
hwc_validate() Validate the hwc

The backend inspects all of the hw layer state and determine if there are any composition type changes necessary before committing the hwc.

Mandatory
hwc_get_changed_composition_types() Get changed composition types

The backend returns the tdm_hwc_windows of which composition type is changed through the hwc_validate.

Mandatory
hwc_accept_validation() Accepts the validation required by the backend

The backend can know the decided tdm_hwc_window_compositions at this validation. The backend can commit the set of thetdm_hwc_windows with this accepted tdm_hwc_window_compositions.

Mandatory
hwc_commit() Commit changes for a hwc object

The backend can commits the output(layers) associated with the accepted validation of this hwc on the display output device.

Mandatory
hwc_set_commit_handler() Set a user commit handler

The backend has to the tdm_hwc_commit_handler function after finishing the hwc_commit.

Mandatory
hwc_set_property() Set the property which has a given id on the hwc object. Mandatory
hwc_get_property() Get the property which has a given id on the hwc object. Mandatory

The hwc_window backend interface is mandatory in Tizen 5.5 or later. For more information, see tdm_backend.h.

Function Description
hwc_window_destroy() Destroys the given window.

The backend module must implement this function. The backend destorys a private tdm_hwc_window.

Mandatory
hwc_window_acquire_buffer_queue() Acquire a buffer queue for the window object

These buffers are used to composite by hardware a client content in the nocomp mode. This function can be used when the backend has the TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE.

Optional
hwc_window_release_buffer_queue() Release a buffer queue for the window object

The backend releases the buffer queue when the client does not use buferrs of queue anymore. This function can be used when the backend has the TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE.

Optional
hwc_window_set_composition_type() Get the composition type of the window object.

The backend sets the tdm_hwc_window_composition.

Mandatory
hwc_window_set_buffer_damage() Set the buffer damage.

The backend sets the buffer damage.

Mandatory
hwc_window_set_info() Set the information to a window object

The information will be applied when the hwc object is committed.

Mandatory
hwc_window_set_buffer() Set a TDM buffer to a window object

A TDM buffer will be applied when the hwc object

Mandatory
hwc_window_set_property() Set the property which has a given id. Mandatory
hwc_window_get_property() Get the property which has a given id. Mandatory
hwc_window_get_constraints() Get the constraints of hwc_window

The backend returns the tdm_hwc_window_constraint.

Mandatory
hwc_window_set_name() Set the name of hwc_window

The backend can get the name of the hwc_window from the tdm client.

Mandatory
hwc_window_set_cursor_image() Set the cursor memory information associated with the hwc_window Mandatory

The layer backend interface is mandatory in Tizen 5.5 or earlier. For more information, see tdm_backend.h.

Function Description
layer_get_capability() Get the capabilities of a layer object.

The backend module must implement this function. TDM calls this function not only at the initialization, but also at the update time when new output is connected. The tdm_caps_layer contains available formats/properties, and zpos information.

Mandatory
layer_set_property() Sets the property with a given ID. Optional
layer_get_property() Gets the property with a given ID. Optional
layer_set_info() Sets the geometry information to a layer object.

The backend module applies the geometry information when the output object of a layer object is committed.

Mandatory
layer_get_info() Gets the geometry information to a layer object. Mandatory
layer_set_buffer() Sets a TDM buffer to a layer object.

The backend module shows a TDM buffer on the screen when the output object of a layer object is committed.

Mandatory
layer_unset_buffer() Unset a TDM buffer from a layer object.

The backend module must remove the current showing buffer from screen.

Mandatory
layer_set_video_pos() Sets the zpos for a video layer object.

The backend module does not need to implement this function if the backend module does not have video layers. The zpos of the video layer is changeable.

Optional
layer_create_capture() Creates a capture object of a layer object.

The backend module does not need to implement this function if the hardware does not have a capture device.

Optional
layer_get_buffer_flags() Gets the buffer flags which the layer can support. Optional

The pp backend interface is optional. For more information, see tdm_backend.h.

Function Description
pp_destroy() Destroys a pp object. Optional
pp_set_info() Sets the geometry information to a pp object.

The backend module applies the geometry information when committed.

Optional
pp_attach() Attaches a source buffer and a destination buffer to a pp object.

The backend module converts the image of a source buffer to a destination buffer when committed. The size/crop/transform information is set using the pp_set_info() function of tdm_func_pp. When done, the backend module must return the source/destination buffer using the tdm_pp_done_handler() function.

Optional
pp_commit() Commits changes for a pp object. Optional
pp_set_done_handler() Sets a user done handler to a pp object.

The backend module must call the tdm_pp_done_handler() function when image conversion is done.

Optional

The capture backend interface is optional. For more information, see tdm_backend.h.

Function Description
capture_destroy() Destroys a capture object. Optional
capture_set_info() Sets the geometry information to a capture object.

The backend module applies the geometry information when committed.

Optional
capture_attach() Attaches a TDM buffer to a capture object.

When the capture_commit() function is called, the backend module starts to dump a output or a layer to a TDM buffer. The backend module starts to dump an output or a layer to a TDM buffer when committed. The size/crop/transform information is set using the capture_set_info() function of the tdm_func_capture. When done, the backend module must return the TDM buffer using the tdm_capture_done_handler() function.

Optional
capture_commit() Commits changes for a capture object. Optional
capture_set_done_handler() Sets a user done handler to a capture object.

The backend module must call the tdm_capture_done_handler() function when capture operation is done.

Optional

TDM backends

There are several backends which can be referred to implement the TDM backend.

Backend Project (http://review.tizen.org) Description
libtdm-drm platform/adaptation/libtdm-drm
  • The backend for the target device which supports the DRM interface, such as the Tizen SDK emulator
  • No PP & Capture capability
libtdm-fbdev platform/adaptation/libtdm-fbdev
  • The backend for the target device which supports the FBDEV interface
  • No PP & Capture capability
libtdm-exynos platform/adaptation/samsung_exynos/libtdm-exynos
  • The backend for the target device which uses the exynos chipset
  • Using the DRM interface
  • Has PP & Capture capability
  • Using the exynos-specific DRM interface to support PP
libtdm-sprd platform/adaptation/spreadtrum/libtdm-sprd
  • The backend for the target device which uses the Spreadtrum chipset
  • Using the sptreadtrum-specific ioctl
  • Using the DRM interface to support vblank
  • Has PP capability, but no capture capability

How to test the porting result simply

Basically TDM offers the tdm-test-server tool for developers to test the porting result. tdm-test-server tool is included in libtdm-tools package. libtdm-tools package can be downloaded from which the platform binary's snapshot repository. Make sure that porting TBM should be done before using below commands because TDM works base on TBM.

$ systemctl stop display-manager  (stop the display server)
$ export XDG_RUNTIME_DIR=/run
$ export TBM_DISPLAY_SERVER=1
$ tdm-test-server                 (show all options)
$ tdm-test-server -a              (test all layers)
$ tdm-test-server -a -v           (test all layers with vblank events)

Below is the result of tdm-test-server -a. The fullscreen buffer is set to the PRIMARY layer. And the small buffer is set to the OVERLAY layer.

Tdm-test-server-result.png

How to check TDM log messages

TDM uses dlog to print debug messages. Below command shows TDM runtime log messages.

$ dlogutil -v threadtime TDM

References

For detailed information about the TDM and TDM backend, see Tizen Display Manager (TDM).