[hwc] add impl of HWC API 92/157392/9 accepted/tizen/unified/20171030.161648 submit/tizen/20171030.021003
authorRoman Marchenko <r.marchenko@samsung.com>
Fri, 26 May 2017 09:54:14 +0000 (12:54 +0300)
committerRoman Marchenko <r.marchenko@samsung.com>
Fri, 27 Oct 2017 06:48:36 +0000 (09:48 +0300)
  add the output functions for a backend module:
     - output_hwc_window_create;
     - output_hwc_window_destroy;
     - output_hwc_validate;
     - output_hwc_get_changed_composition_types;
     - output_hwc_accept_changes;
     - output_hwc_get_target_surface_queue;
     - output_hwc_set_client_target_buffer;

  create the window functions for a backend module
     - hwc_window_get_tbm_surface_queue;
     - hwc_window_set_buffer;
     - hwc_window_set_composition_type;
     - hwc_window_set_info;
     - hwc_window_set_surface_damage;
     - hwc_window_set_zpos;
     - hwc_window_set_flags;
     - hwc_window_unset_flags;
     - hwc_window_video_get_capability;
     - hwc_window_video_get_supported_format;

Change-Id: I464fd37e5ce6e2f1548b210e935e98d3541b43cd
Signed-off-by: Roman Marchenko <r.marchenko@samsung.com>
include/tdm.h
include/tdm_backend.h
include/tdm_common.h
include/tdm_types.h
src/Makefile.am
src/tdm.c
src/tdm_backend.c
src/tdm_hwc_window.c [new file with mode: 0644]
src/tdm_output.c
src/tdm_private.h
src/tdm_thread.c

index a7695c1..56d7dea 100644 (file)
@@ -62,6 +62,7 @@ extern "C" {
 typedef enum {
        TDM_DISPLAY_CAPABILITY_PP       = (1 << 0), /**< if hardware supports pp operation */
        TDM_DISPLAY_CAPABILITY_CAPTURE  = (1 << 1), /**< if hardware supports capture operation */
+       TDM_DISPLAY_CAPABILITY_HWC      = (1 << 2), /**< if hardware supports hwc operation @since 2.0.0*/
 } tdm_display_capability;
 
 /**
@@ -569,6 +570,152 @@ tdm_capture *
 tdm_output_create_capture(tdm_output *output, tdm_error *error);
 
 /**
+ * @brief Creates a new window on the given display.
+ * @param[in] output A output object
+ * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @return A created window object
+ * @since 2.0.0
+ */
+tdm_hwc_window *
+tdm_output_hwc_create_window(tdm_output *output, tdm_error *error);
+
+/**
+ * @brief Destroys the given window.
+ * @param[in] output A output object
+ * @param[in] window the pointer of the window to destroy
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_destroy_window(tdm_output *output, tdm_hwc_window *hwc_window);
+
+/**
+ * @brief Set the client(relative to the TDM) target buffer
+ * @details Sets the buffer which will receive the output of client composition.
+ * Window marked as TDM_COMPOSITION_CLIENT or TDM_COMPOSITION_DEVICE_CANDIDATE
+ * will be composited into this buffer prior to the call to tdm_output_commit(),
+ * and windows not marked as TDM_COMPOSITION_CLIENT and
+ * TDM_COMPOSITION_DEVICE_CANDIDATE should be composited with this buffer by the
+ * device.
+ *
+ * The buffer handle provided may be null if no windows are being composited by
+ * the client. This must not result in an error (unless an invalid display
+ * handle is also provided).
+ *
+ * The damage parameter describes a buffer damage region as defined in the
+ * description of tdm_hwc_window_set_buffer_damage().
+ *
+ * Will be called before tdm_output_commit() if any of the layers are marked as
+ * TDM_COMPOSITION_CLIENT or TDM_COMPOSITION_DEVICE_CANDIDATE. If no layers are
+ * so marked, then it is not necessary to call this function. It is not necessary
+ * to call tdm_output_hwc_validate() after changing the target through this function.
+ * @param[in] output A output object
+ * @param[in] target The new target buffer
+ * @param[in] damage The buffer damage region
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target_buffer,
+                                                                       tdm_hwc_region damage);
+
+/**
+ * @brief Validate the output
+ * @details Instructs the device to inspect all of the layer state and
+ * determine if there are any composition type changes necessary before
+ * presenting the output. Permitted changes are described in the definition
+ * of tdm_hwc_window_composition_t above.
+ * @param[in] output A output object
+ * @param[out] num_types The number of composition type changes required by
+ * the device; if greater than 0, the client must either set and validate new
+ * types, or call tdm_output_hwc_accept_changes() to accept the changes returned by
+ * tdm_output_hwc_get_changed_composition_types(); must be the same as the number of
+ * changes returned by tdm_output_hwc_get_changed_composition_types (see the
+ * declaration of that function for more information); pointer will be non-NULL
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types);
+
+/**
+ * @brief Set the 'need to validate' handler for the 'output'
+ *
+ * @details During backend's work it may need to ask for the revalidation
+ * (make client (E20) do tdm_output_hwc_validate() again), so a 'hndl' will
+ * be called as such need happen. Only one handler per output is supported.
+ *
+ * @param[in] output The output object a hndl is going to be registered for.
+ * @param[in] hndl The handler which will be called on the 'need to validate' event.
+ *
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_set_need_validate_handler(tdm_output *output,
+               tdm_output_need_validate_handler hndl);
+
+/**
+ * @brief Get changed composition types
+ * @details Retrieves the windows for which the device requires a different
+ * composition type than had been set prior to the last call to tdm_output_hwc_validate().
+ * The client will either update its state with these types and call
+ * tdm_output_hwc_accept_changes, or will set new types and attempt to validate the
+ * display again.
+ * windows and types may be NULL to retrieve the number of elements which
+ * will be returned. The number of elements returned must be the same as the
+ * value returned in num_types from the last call to tdm_output_hwc_validate().
+ * @param[in] output A output object
+ * @param[out] num_elements If windows or types were NULL, the number of layers
+ * and types which would have been returned; if both were non-NULL, the
+ * number of elements returned in layers and types, which must not exceed
+ * the value stored in num_elements prior to the call; pointer will be
+ * non-NULL
+ * @param[in] output A output object
+ * @param[out] windows An array of windows
+ * @param[out] composition_types An array of composition types, each corresponding
+ * to an element of windows
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_get_changed_composition_types(tdm_output *output,uint32_t *num_elements,
+                                                                                tdm_hwc_window **hwc_window,
+                                                                                tdm_hwc_window_composition *composition_types);
+
+/**
+ * @brief Accepts the changes required by the device
+ * @details Accepts the changes required by the device from the previous
+ * tdm_output_hwc_validate() call (which may be queried using
+ * tdm_output_get_chaged_composition_types()) and revalidates the display. This
+ * function is equivalent to requesting the changed types from
+ * tdm_output_get_chaged_composition_types(), setting those types on the
+ * corresponding windows, and then calling tdm_output_hwc_validate again.
+ * After this call it must be valid to present this display. Calling this after
+ * tdm_output_hwc_validate() returns 0 changes must succeed with TDM_ERROR_NONE, but
+ * should have no other effect.
+ * @param[in] output A output object
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_output_hwc_accept_changes(tdm_output *output);
+
+/**
+ * @brief Get a target buffer queue
+ * @details Buffers from target buffer queue will receive the output of
+ * client composition. Window marked as TDM_COMPOSITION_CLIENT or
+ * TDM_COMPOSITION_DEVICE_CANDIDATE will be composited into this buffers
+ * prior to the call to tdm_output_commit().
+ * @param[in] output A output object
+ * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @return A buffer queue
+ * @since 2.0.0
+ */
+tbm_surface_queue_h
+tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error);
+
+/**
  * @brief Get the capabilities of a layer object.
  * @param[in] layer A layer object
  * @param[out] capabilities The capabilities of a layer object
@@ -788,6 +935,135 @@ tdm_error
 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags);
 
 /**
+ * @brief Get a buffer queue for the window object
+ * @details These buffers are used to composite by hardware a client content in
+ * the nocomp mode.
+ * @param[in] hwc_window A window object
+ * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @return A tbm buffer queue
+ * @since 2.0.0
+ */
+tbm_surface_queue_h
+tdm_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error);
+
+/**
+ * @brief Sets the desired Z order of the given window. A window with
+ * a greater Z value occludes a window with a lesser Z value.
+ * @param[in] hwc_window A window object
+ * @param[in] z the new Z order
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_zpos(tdm_hwc_window *hwc_window, uint32_t zpos);
+
+/**
+ * @brief Sets the desired composition type of the given window.
+ * @details During tdm_output_hwc_validate(), the device may request changes to
+ * the composition types of any of the layers as described in the definition
+ * of tdm_hwc_window_composition_t above.
+ * @param[in] hwc_window A window object
+ * @param[in] composition_type The new composition type
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition composition_type);
+
+/**
+ * @brief Set the buffer damage
+ * @details Provides the region of the source buffer which has been modified
+ * since the last frame. This region does not need to be validated before
+ * calling tdm_output_commit().
+ * Once set through this function, the damage region remains the same until a
+ * subsequent call to this function.
+ * If damage.num_rects > 0, then it may be assumed that any portion of the source
+ * buffer not covered by one of the rects has not been modified this frame. If
+ * damage.num_rects == 0, then the whole source buffer must be treated as if it
+ * has been modified.
+ * If the layer's contents are not modified relative to the prior frame, damage
+ * will contain exactly one empty rect([0, 0, 0, 0]).
+ * The damage rects are relative to the pre-transformed buffer, and their origin
+ * is the top-left corner. They will not exceed the dimensions of the latched
+ * buffer.
+ * @param[in] hwc_window A window object
+ * @param[in] damage The new buffer damage region
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage);
+
+/**
+ * @brief Set the information to a window object
+ * @details The information will be applied when the output object of a window
+ * object is committed.
+ * @param[in] hwc_window A window object
+ * @param[in] info The information
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+
+/**
+ * @brief Set a TBM buffer to a window object
+ * @details A TBM buffer will be applied when the output object of a layer
+ * object is committed.
+ * @param[in] hwc_window A window object
+ * @param[in] buffer A TDM buffer
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer);
+
+/**
+ * @brief Set a flags to a window object
+ * @param[in] hwc_window A window object
+ * @param[in] flags A hwc_window flags
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_set_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags);
+
+/**
+ * @brief Unset a flags from a window object
+ * @param[in] hwc_window A window object
+ * @param[in] flags A hwc_window flags
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags);
+
+/**
+ * @brief Get the window video capability
+ * @param[in] hwc_window A window object
+ * @param[out] video_capability A hwc window video capability
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_video_get_capability(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_video_capability *video_capability);
+
+/**
+ * @brief Get the window video supported format
+ * @param[in] hwc_window A window object
+ * @param[out] formats A hwc window supported formats
+ * @param[out] count A number of the hwc window supported formats
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_hwc_window_video_get_supported_format(tdm_hwc_window *hwc_window,
+                                                                                 const tbm_format **formats,
+                                                                                 int *count);
+
+/**
  * @brief Destroy a pp object
  * @param[in] pp A pp object
  * @see tdm_display_create_pp
index 2de8c7b..f189d43 100644 (file)
@@ -37,6 +37,7 @@
 #define _TDM_BACKEND_H_
 
 #include <tbm_surface.h>
+#include <tbm_surface_queue.h>
 
 #include "tdm_types.h"
 
@@ -541,6 +542,124 @@ typedef struct _tdm_func_output {
         */
        tdm_error (*output_set_dpms_async)(tdm_output *output, tdm_output_dpms dpms_value);
 
+       /**
+        * @brief Creates a new window on the given display.
+        * @param[in] output A output object
+        * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @return A created window object
+        * @since 2.0.0
+        */
+       tdm_hwc_window *(*output_hwc_create_window)(tdm_output *output, tdm_error *error);
+
+       /**
+        * @brief Destroys the given window.
+        * @param[in] output A output object
+        * @param[in] window the pointer of the window to destroy
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 2.0.0
+        */
+       tdm_error (*output_hwc_destroy_window)(tdm_output *output, tdm_hwc_window *hwc_window);
+
+       /**
+        * @brief Set the client(relative to the TDM) target buffer
+        * @details Sets the buffer which will receive the output of client composition.
+        * Window marked as TDM_COMPOSITION_CLIENT or TDM_COMPOSITION_DEVICE_CANDIDATE
+        * will be composited into this buffer prior to the call to output_commit(),
+        * and windows not marked as TDM_COMPOSITION_CLIENT and
+        * TDM_COMPOSITION_DEVICE_CANDIDATE should be composited with this buffer by the
+        * device.
+        *
+        * The buffer handle provided may be null if no windows are being composited by
+        * the client. This must not result in an error (unless an invalid display
+        * handle is also provided).
+        *
+        * The damage parameter describes a buffer damage region as defined in the
+        * description of hwc_window_set_buffer_damage().
+        *
+        * Will be called before output_commit() if any of the layers are marked as
+        * TDM_COMPOSITION_CLIENT or TDM_COMPOSITION_DEVICE_CANDIDATE. If no layers are
+        * so marked, then it is not necessary to call this function. It is not necessary
+        * to call output_hwc_validate() after changing the target through this function.
+        * @param[in] output A output object
+        * @param[in] target The new target buffer
+        * @param[in] damage The buffer damage region
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 2.0.0
+        */
+       tdm_error (*output_hwc_set_client_target_buffer)(tdm_output *output, tbm_surface_h target_buffer,
+                                                                                                tdm_hwc_region damage);
+
+       /**
+        * @brief Validate the output
+        * @details Instructs the device to inspect all of the layer state and
+        * determine if there are any composition type changes necessary before
+        * presenting the output. Permitted changes are described in the definition
+        * of tdm_composition_t above.
+        * @param[in] output A output object
+        * @param[out] num_types The number of composition type changes required by
+        * the device; if greater than 0, the client must either set and validate new
+        * types, or call output_hwc_accept_changes() to accept the changes returned by
+        * output_hwc_get_changed_composition_types(); must be the same as the number of
+        * changes returned by output_hwc_get_changed_composition_types (see the
+        * declaration of that function for more information); pointer will be non-NULL
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 2.0.0
+        */
+       tdm_error (*output_hwc_validate)(tdm_output *output, uint32_t *num_types);
+
+       /**
+        * @brief Get changed composition types
+        * @details Retrieves the windows for which the device requires a different
+        * composition type than had been set prior to the last call to output_hwc_validate().
+        * The client will either update its state with these types and call
+        * output_hwc_accept_changes, or will set new types and attempt to validate the
+        * display again.
+        * layers and types may be NULL to retrieve the number of elements which
+        * will be returned. The number of elements returned must be the same as the
+        * value returned in num_types from the last call to output_hwc_validate().
+        * @param[in] output A output object
+        * @param[out] num_elements If windows or types were NULL, the number of layers
+        * and types which would have been returned; if both were non-NULL, the
+        * number of elements returned in layers and types, which must not exceed
+        * the value stored in num_elements prior to the call; pointer will be
+        * non-NULL
+        * @param[out] windows An array of windows
+        * @param[out] composition_types An array of composition types, each
+        * corresponding to an element of windows
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 2.0.0
+        */
+       tdm_error (*output_hwc_get_changed_composition_types)(tdm_output *output,
+                                                                                                         uint32_t *num_elements,
+                                                                                                         tdm_hwc_window **hwc_window,
+                                                                                                         tdm_hwc_window_composition *composition_types);
+       /**
+        * @brief Accepts the changes required by the device
+        * @details Accepts the changes required by the device from the previous
+        * output_hwc_validate() call (which may be queried using
+        * output_get_chaged_composition_types()) and revalidates the display. This
+        * function is equivalent to requesting the changed types from
+        * output_get_chaged_composition_types(), setting those types on the
+        * corresponding windows, and then calling output_hwc_validate again.
+        * After this call it must be valid to present this display. Calling this after
+        * output_hwc_validate() returns 0 changes must succeed with TDM_ERROR_NONE, but
+        * should have no other effect.
+        * @param[in] output A output object
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 2.0.0
+        */
+       tdm_error (*output_hwc_accept_changes)(tdm_output *output);
+
+       /**
+        * @brief Get a target buffer queue
+        * @param[in] output A output object
+        * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @return A buffer queue
+        * @since 2.0.0
+        */
+       tbm_surface_queue_h (*output_hwc_get_target_buffer_queue)(tdm_output *output,
+                                                                                                                  tdm_error *error);
+
        void (*reserved3)(void);
        void (*reserved4)(void);
        void (*reserved5)(void);
@@ -679,6 +798,125 @@ typedef struct _tdm_func_layer {
 } tdm_func_layer;
 
 /**
+ * @brief The window functions for a backend module.
+ * @since 2.0.0
+ */
+typedef struct _tdm_func_window {
+       /**
+        * @brief Get a buffer queue for the window object
+        * @param[in] hwc_window A window object
+        * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @return A buffer queue
+        */
+       tbm_surface_queue_h (*hwc_window_get_tbm_buffer_queue)(tdm_hwc_window *hwc_window,
+                                                                                                                       tdm_error *error);
+
+       /**
+        * @brief Sets the desired Z order (height) of the given window. A window with
+        * a greater Z value occludes a window with a lesser Z value.
+        * @param[in] hwc_window A window object
+        * @param[in] z the new Z order
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_zpos)(tdm_hwc_window *hwc_window, uint32_t zpos);
+
+       /**
+        * @brief Sets the desired composition type of the given window.
+        * @details During output_hwc_validate(), the device may request changes to
+        * the composition types of any of the layers as described in the definition
+        * of tdm_hwc_window_composition_t above.
+        * @param[in] hwc_window A window object
+        * @param[in] composition_type The new composition type
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_composition_type)(tdm_hwc_window *hwc_window,
+                                                                                                tdm_hwc_window_composition composition_type);
+
+       /**
+        * @brief Set the buffer damage
+        * @details Provides the region of the source buffer which has been modified
+        * since the last frame. This region does not need to be validated before
+        * calling output_commit().
+        * Once set through this function, the damage region remains the same until a
+        * subsequent call to this function.
+        * If damage.num_rects > 0, then it may be assumed that any portion of the source
+        * buffer not covered by one of the rects has not been modified this frame. If
+        * damage.num_rects == 0, then the whole source buffer must be treated as if it
+        * has been modified.
+        * If the layer's contents are not modified relative to the prior frame, damage
+        * will contain exactly one empty rect([0, 0, 0, 0]).
+        * The damage rects are relative to the pre-transformed buffer, and their origin
+        * is the top-left corner. They will not exceed the dimensions of the latched
+        * buffer.
+        * @param[in] hwc_window A window object
+        * @param[in] damage The new buffer damage region
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_buffer_damage)(tdm_hwc_window *hwc_window,
+                                                                                          tdm_hwc_region damage);
+
+       /**
+        * @brief Set the information to a window object
+        * @details The information will be applied when the output object
+        * of a layer object is committed.
+        * @param[in] hwc_window A window object
+        * @param[in] info The geometry information
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_info)(tdm_hwc_window *hwc_window,
+                                                                        tdm_hwc_window_info *info);
+
+       /**
+        * @brief Set a TDM buffer to a window object
+        * @details A TDM buffer will be applied when the output object
+        * of a layer object is committed.
+        * @param[in] hwc_window A window object
+        * @param[in] buffer A TDM buffer
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_buffer)(tdm_hwc_window *hwc_window,
+                                                                          tbm_surface_h buffer);
+
+       /**
+        * @brief Set a flags to a window object
+        * @param[in] hwc_window A window object
+        * @param[in] flags A hwc_window flags
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_set_flags)(tdm_hwc_window *hwc_window,
+                                                                         tdm_hwc_window_flag flags);
+
+       /**
+        * @brief Unset a flags from a window object
+        * @param[in] hwc_window A window object
+        * @param[in] flags A hwc_window flags
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_unset_flags)(tdm_hwc_window *hwc_window,
+                                                                               tdm_hwc_window_flag flags);
+
+       /**
+        * @brief Get the window video capability
+        * @param[in] hwc_window A window object
+        * @param[out] video_capability A hwc window video capability
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_video_get_capability)(tdm_hwc_window *hwc_window,
+                                                                                               tdm_hwc_window_video_capability *video_capability);
+
+       /**
+        * @brief Get the window video supported format
+        * @param[in] hwc_window A window object
+        * @param[out] formats A hwc window supported formats
+        * @param[out] count A number of the hwc window supported formats
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        */
+       tdm_error (*hwc_window_video_get_supported_format)(tdm_hwc_window *hwc_window,
+                                                                                                          const tbm_format **formats,
+                                                                                                          int *count);
+} tdm_func_hwc_window;
+
+/**
  * @brief The pp functions for a backend module.
  */
 typedef struct _tdm_func_pp {
@@ -933,6 +1171,19 @@ tdm_error
 tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer);
 
 /**
+ * @brief Register the backend hwc_window functions to a display
+ * @param[in] dpy A display object
+ * @param[in] func_hwc_window hwc_window functions
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @see tdm_backend_register_func_display, tdm_backend_register_func_output
+ * @remarks
+ * A backend module @b SHOULD set the backend hwc_window functions at least.
+ * @since 2.0.0
+ */
+tdm_error
+tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func_hwc_window);
+
+/**
  * @brief Register the backend pp functions to a display
  * @param[in] dpy A display object
  * @param[in] func_pp pp functions
@@ -1076,6 +1327,16 @@ tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int m
 void
 tdm_event_loop_source_remove(tdm_event_loop_source *source);
 
+/**
+ * @brief Trigger a 'need to validate' event.
+ * @param[in] output The output the event should be triggered for.
+ * @note The global display lock has to be locked before the call to this function.
+ * @see #tdm_output_hwc_set_need_validate_handler
+ * @since 2.0.0
+ */
+tdm_error
+tdm_backend_trigger_need_validate_event(tdm_output *output);
+
 #ifdef __cplusplus
 }
 #endif
index 054cb5e..6ba2784 100644 (file)
@@ -130,6 +130,16 @@ typedef enum {
 } tdm_layer_capability;
 
 /**
+ * @brief The hwc window capability enumeration
+ * @since 2.0.0
+ */
+typedef enum {
+       TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCALE          = (1 << 1), /**< if a hwc window video has scale capability  */
+       TDM_HWC_WINDOW_VIDEO_CAPABILITY_TRANSFORM      = (1 << 2), /**< if a hwc window video has transform capability  */
+       TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCANOUT        = (1 << 3), /**< if a hwc_window video allows a scanout buffer only */
+} tdm_hwc_window_video_capability;
+
+/**
  * @brief The pp capability enumeration
  */
 typedef enum {
@@ -262,6 +272,11 @@ typedef struct _tdm_pos {
        unsigned int h;
 } tdm_pos;
 
+typedef struct _tdm_hwc_region {
+       unsigned int num_rects;
+       tdm_pos const *rects;
+} tdm_hwc_region;
+
 /**
  * @brief The tdm value type enumeration
  */
@@ -285,6 +300,14 @@ typedef union {
        uint64_t u64;
 } tdm_value;
 
+/**
+ * @brief The hwc window flag enumeration
+ * @since 2.0.0
+ */
+typedef enum {
+       TDM_HWC_WINDOW_FLAG_SKIP     = (1 << 0),
+} tdm_hwc_window_flag;
+
 #ifdef __cplusplus
 }
 #endif
index 2cda6d6..58a787f 100644 (file)
@@ -107,6 +107,16 @@ typedef struct _tdm_info_layer {
 } tdm_info_layer;
 
 /**
+ * @brief The hwc window info structure
+ * @since 2.0.0
+ */
+typedef struct _tdm_hwc_window_info {
+       tdm_info_config src_config;
+       tdm_pos dst_pos;
+       tdm_transform transform;
+} tdm_hwc_window_info;
+
+/**
  * @brief The pp info structre
  */
 typedef struct _tdm_info_pp {
@@ -129,6 +139,93 @@ typedef struct _tdm_info_capture {
 } tdm_info_capture;
 
 /**
+ * @brief Possible composition types for a given window
+ * @since 2.0.0
+ */
+typedef enum {
+       /** The client will composite this window into the client target window
+        *
+        * User can choose this type for window to avoid a hardware composition for
+        * this window.
+        *
+        * User has to set this type for the window which has the TDM_COMPOSITION_CLIENT_CANDIDATE
+        * type. (see the TDM_COMPOSITION_CLIENT_CANDIDATE type)
+        *
+        * The device must not request any composition type changes for windows of
+        * this type.
+        */
+       TDM_COMPOSITION_CLIENT = 0,
+
+       /* Set by the HWC after tdm_output_hwc_validate().
+        *
+        * If the HWC decided that it doesn't want/can't to continue the composition for
+        * the window through a hardware overlay or other similar way it'll change
+        * a type to the TDM_COMPOSITION_CLIENT_CANDIDATE type.
+        *
+        * This transition can happen only if the window has the TDM_COMPOSITION_DEVICE
+        * or the TDM_COMPOSITION_VIDEO type already.
+        *
+        * If an user changed type of a window from the TDM_COMPOSITION_DEVICE or the
+        * TDM_COMPOSITION_VIDEO type to the the TDM_COMPOSITION_CLIENT type, the type
+        * will be rejected to the TDM_COMPOSITION_CLIENT_CANDIDATE type.
+        *
+        * The user has to composite this window itself.
+        *
+        * The underlying hardware overlay is owned by this window till a type being
+        * changed to the TDM_COMPOSITION_CLIENT type, but it's not possible to set a
+        * buffer for this window after a type's been changed to the
+        * TDM_COMPOSITION_CLIENT_CANDIDATE type.
+        *
+        * This transitional state is used to get rid of blinking at a transition from
+        * the TDM_COMPOSITION_DEVICE/TDM_COMPOSITION_VIDEO type to the
+        * TDM_COMPOSITION_CLIENT type where the hw     has to wait till a buffer, which was
+        * on a hw overlay, get composited to the fb_target and only after this happens
+        * unset(or set another window on) this hw overlay.
+        *
+        * User has to inform the HWC (the HWC got no way to know when it happens) after a buffer,
+        * which was on a hw overlay, get composited to the fb_target by setting a type of this
+        * window to the TDM_COMPOSITION_CLIENT type, it causes a type of this window being changed
+        * to TDM_COMPOSITION_CLIENT.
+        */
+       TDM_COMPOSITION_CLIENT_CANDIDATE = 5,
+
+       /** Set by the client before tdm_output_hwc_validate().
+        *
+        * Upon tdm_output_hwc_validate(), the device may request a change from this type to
+        * TDM_COMPOSITION_DEVICE or TDM_COMPOSITION_CLIENT. */
+       TDM_COMPOSITION_DEVICE_CANDIDATE = 2,
+
+       /** Set by the HWC after tdm_output_hwc_validate().
+        *
+        * The device will handle the composition of this window through a hardware
+        * overlay or other similar means.
+        *
+        * Upon tdm_output_hwc_validate(), the device may request a change from this type to
+        * TDM_COMPOSITION_CLIENT or TDM_COMPOSITION_DEVICE_CANDIDATE. */
+       TDM_COMPOSITION_DEVICE = 1,
+
+       /** Similar to DEVICE, but the position of this layer may also be set
+        * asynchronously through layer_set_cursor_position. If this functionality is not
+        * supported on a layer that the client sets to TDM_COMPOSITION_CURSOR, the
+        * device must request that the composition type of that layer is changed to
+        * TDM_COMPOSITION_CLIENT upon the next call to tdm_output_hwc_validate().
+        *
+        * Upon tdm_output_hwc_validate(), the device may request a change from this type to
+        * either TDM_COMPOSITION_DEVICE or TDM_COMPOSITION_CLIENT. Changing to
+        * TDM_COMPOSITION_DEVICE will prevent the use of layer_set_cursor_position but
+        * still permit the device to composite the layer. */
+       TDM_COMPOSITION_CURSOR = 3,
+
+       /** The device will handle the composition of this layer through a hardware
+        * overlay or other similar means.
+        *
+        * Upon tdm_output_hwc_validate(), the device may request a change from this type to
+        * either TDM_COMPOSITION_DEVICE or TDM_COMPOSITION_CLIENT, but it is
+        * unlikely that content will display correctly in these cases. */
+       TDM_COMPOSITION_VIDEO = 4,
+} tdm_hwc_window_composition;
+
+/**
  * @brief The tdm display object
  */
 typedef void tdm_display;
@@ -144,6 +241,12 @@ typedef void tdm_output;
 typedef void tdm_layer;
 
 /**
+ * @brief The tdm window object
+ * @since 2.0.0
+ */
+typedef void tdm_hwc_window;
+
+/**
  * @brief The tdm capture object
  */
 typedef void tdm_capture;
@@ -193,6 +296,12 @@ typedef void (*tdm_pp_done_handler)(tdm_pp *pp, tbm_surface_h src,
 typedef void (*tdm_capture_done_handler)(tdm_capture *capture,
                                                                                 tbm_surface_h buffer, void *user_data);
 
+/**
+ * @brief The 'need to validate' handler of an output object
+ * @since 2.0.0
+ */
+typedef void (*tdm_output_need_validate_handler)(tdm_output *output);
+
 #ifdef __cplusplus
 }
 #endif
index 87169ff..8542130 100644 (file)
@@ -22,6 +22,7 @@ libtdm_la_SOURCES = \
        tdm_display.c \
        tdm_output.c \
        tdm_layer.c \
+       tdm_hwc_window.c \
        tdm_pp.c \
        tdm_capture.c \
        tdm_monitor_server.c \
index 5db2923..bb737bb 100644 (file)
--- a/src/tdm.c
+++ b/src/tdm.c
@@ -152,6 +152,7 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
 {
        tdm_private_display *private_display = private_output->private_display;
        tdm_private_layer *l = NULL, *ll = NULL;
+       tdm_private_hwc_window *hw = NULL, *hww = NULL;
        tdm_private_capture *c = NULL, *cc = NULL;
        tdm_private_vblank_handler *v = NULL, *vv = NULL;
        tdm_private_output_commit_handler *om = NULL, *omm = NULL;
@@ -202,6 +203,9 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
        LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
        tdm_capture_destroy_internal(c);
 
+       LIST_FOR_EACH_ENTRY_SAFE(hw, hww, &private_output->hwc_window_list, link)
+       tdm_hwc_window_destroy_internal(hw);
+
        LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
        _tdm_display_destroy_private_layer(l);
 
@@ -402,6 +406,7 @@ tdm_display_update_output(tdm_private_display *private_display,
                private_output->index = pipe;
 
                LIST_INITHEAD(&private_output->layer_list);
+               LIST_INITHEAD(&private_output->hwc_window_list);
                LIST_INITHEAD(&private_output->capture_list);
                LIST_INITHEAD(&private_output->vblank_handler_list);
                LIST_INITHEAD(&private_output->output_commit_handler_list);
@@ -945,6 +950,13 @@ tdm_display_init(tdm_error *error)
                tdm_display_enable_commit_per_vblank(private_display, enable);
        }
 
+       str = getenv("TDM_HWC");
+       if (str) {
+               char *end;
+               int enable = strtol(str, &end, 10);
+               private_display->hwc_enable = enable;
+       }
+
        if (pthread_mutex_init(&private_display->lock, NULL)) {
                ret = TDM_ERROR_OPERATION_FAILED;
                TDM_ERR("mutex init failed: %m");
@@ -969,6 +981,9 @@ tdm_display_init(tdm_error *error)
        if (ret != TDM_ERROR_NONE)
                goto failed_load;
 
+       if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_HWC))
+               private_display->hwc_enable = 0;
+
        stamp2 = tdm_helper_get_time();
        TDM_DBG("loading backend time: %.3f ms", (stamp2 - stamp1) * 1000.0);
        stamp1 = stamp2;
@@ -1006,6 +1021,12 @@ tdm_display_init(tdm_error *error)
        private_display->init_count = 1;
        private_display->commit_type = TDM_COMMIT_TYPE_NONE;
 
+       if (private_display->hwc_enable) {
+               tdm_private_output *o = NULL;
+               LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link)
+                       tdm_output_need_validate_event_init(o);
+       }
+
        g_private_display = private_display;
 
        if (error)
@@ -1210,6 +1231,8 @@ tdm_display_enable_dump(tdm_private_display *private_display, const char *dump_s
                        tdm_debug_dump |= TDM_DUMP_FLAG_PP;
                } else if (!strncmp(arg, "capture", 7)) {
                        tdm_debug_dump |= TDM_DUMP_FLAG_CAPTURE;
+               } else if (!strncmp(arg, "window", 6)) {
+                       tdm_debug_dump |= TDM_DUMP_FLAG_WINDOW;
                } else
                        goto done;
 
index acbde8e..b5e50c6 100644 (file)
@@ -128,6 +128,27 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer)
 }
 
 EXTERN tdm_error
+tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func_hwc_window)
+{
+       tdm_backend_module *module;
+
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
+
+       BACKEND_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(func_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       module = private_display->module_data;
+       if (_check_abi_version(module, 2, 0) < 0)
+               return TDM_ERROR_BAD_MODULE;
+
+       private_display->capabilities |= TDM_DISPLAY_CAPABILITY_HWC;
+       private_display->func_hwc_window = *func_hwc_window;
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
 tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp)
 {
        TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
@@ -160,3 +181,23 @@ tdm_backend_register_func_capture(tdm_display *dpy,
        return TDM_ERROR_NONE;
 }
 
+EXTERN tdm_error
+tdm_backend_trigger_need_validate_event(tdm_output *output)
+{
+       tdm_private_output *private_output;
+       uint64_t value;
+       int res;
+
+       TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       private_output = (tdm_private_output*)output;
+       value = 1;
+
+       /* do not lock the global display lock here */
+
+       res = write(private_output->need_validate.event_fd, &value, sizeof(value));
+       if (res < 0)
+               return TDM_ERROR_OPERATION_FAILED;
+
+       return TDM_ERROR_NONE;
+}
diff --git a/src/tdm_hwc_window.c b/src/tdm_hwc_window.c
new file mode 100644 (file)
index 0000000..0fffd7d
--- /dev/null
@@ -0,0 +1,454 @@
+/**************************************************************************
+ *
+ * libtdm
+ *
+ * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
+ *          JinYoung Jeon <jy0.jeon@samsung.com>,
+ *          Taeheon Kim <th908.kim@samsung.com>,
+ *          YoungJun Cho <yj44.cho@samsung.com>,
+ *          SooChan Lim <sc1.lim@samsung.com>,
+ *          Boram Park <sc1.lim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tdm.h"
+#include "tdm_backend.h"
+#include "tdm_private.h"
+#include "tdm_helper.h"
+
+#define COUNT_MAX   10
+
+#define HWC_WINDOW_FUNC_ENTRY() \
+       tdm_private_display *private_display; \
+       tdm_private_output *private_output; \
+       tdm_private_hwc_window *private_hwc_window; \
+       tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
+       TDM_RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER); \
+       private_hwc_window = (tdm_private_hwc_window*)hwc_window; \
+       private_output = private_hwc_window->private_output; \
+       private_display = private_output->private_display
+
+#define HWC_WINDOW_FUNC_ENTRY_ERROR() \
+       tdm_private_display *private_display; \
+       tdm_private_output *private_output; \
+       tdm_private_hwc_window *private_hwc_window; \
+       tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
+       private_hwc_window = (tdm_private_hwc_window*)hwc_window; \
+       private_output = private_hwc_window->private_output; \
+       private_display = private_output->private_display
+
+#define HWC_WINDOW_FUNC_ENTRY_VOID_RETURN() \
+       tdm_private_display *private_display; \
+       tdm_private_output *private_output; \
+       tdm_private_hwc_window *private_hwc_window; \
+       tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
+       TDM_RETURN_IF_FAIL(hwc_window != NULL); \
+       private_hwc_window = (tdm_private_hwc_window*)hwc_window; \
+       private_output = private_hwc_window->private_output; \
+       private_display = private_output->private_display
+
+tbm_surface_queue_h
+tdm_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+       tbm_surface_queue_h queue = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY_ERROR();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_get_tbm_buffer_queue) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               if (error)
+                       *error = TDM_ERROR_NOT_IMPLEMENTED;
+               return NULL;
+       }
+
+       queue = func_hwc_window->hwc_window_get_tbm_buffer_queue(private_hwc_window->hwc_window_backend, error);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return queue;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_set_zpos(tdm_hwc_window *hwc_window, uint32_t zpos)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_zpos) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_set_zpos(private_hwc_window->hwc_window_backend, zpos);
+       if (ret == TDM_ERROR_NONE)
+               private_hwc_window->zpos = zpos;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition composition_type)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_composition_type) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_set_composition_type(private_hwc_window->hwc_window_backend, composition_type);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_buffer_damage) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_set_buffer_damage(private_hwc_window->hwc_window_backend, damage);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+
+EXTERN tdm_error
+tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+       char fmtstr[128];
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_info) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       if (info->src_config.format)
+               snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
+       else
+               snprintf(fmtstr, 128, "NONE");
+
+       TDM_INFO("hwc_window(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
+                        private_hwc_window, info->src_config.size.h, info->src_config.size.v,
+                        info->src_config.pos.x, info->src_config.pos.y,
+                        info->src_config.pos.w, info->src_config.pos.h,
+                        fmtstr,
+                        info->dst_pos.x, info->dst_pos.y,
+                        info->dst_pos.w, info->dst_pos.h,
+                        info->transform);
+
+       ret = func_hwc_window->hwc_window_set_info(private_hwc_window->hwc_window_backend, info);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+static void
+_tdm_window_dump_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer)
+{
+       tdm_private_hwc_window *private_window = (tdm_private_hwc_window *)hwc_window;
+       tdm_private_output *private_output = private_window->private_output;
+       unsigned int pipe;
+       uint32_t zpos;
+       char fname[PATH_MAX];
+
+       pipe = private_output->pipe;
+       zpos = private_window->zpos;
+
+       snprintf(fname, sizeof(fname), "tdm_%d_win_%d", pipe, zpos);
+
+       tbm_surface_internal_dump_buffer(buffer, fname);
+       TDM_DBG("%s dump excute", fname);
+
+       return;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer)
+{
+       tdm_func_hwc_window *func_hwc_window;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if ((tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) && buffer) {
+               char str[TDM_PATH_LEN];
+               static int i;
+               snprintf(str, TDM_PATH_LEN, "window_%d_%d_%03d",
+                                private_output->index, private_hwc_window->zpos, i++);
+               tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
+       }
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_buffer) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       /* dump buffer */
+       if (tdm_dump_enable && buffer)
+               _tdm_window_dump_buffer(hwc_window, buffer);
+
+       ret = func_hwc_window->hwc_window_set_buffer(private_hwc_window->hwc_window_backend, buffer);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+INTERN tdm_hwc_window *
+tdm_hwc_window_create_internal(tdm_private_output *private_output,
+                                                                  tdm_error *error)
+{
+       tdm_private_display *private_display = private_output->private_display;
+       tdm_func_output *func_output = &private_display->func_output;
+       tdm_private_hwc_window *private_hwc_window = NULL;
+       tdm_hwc_window *hwc_window_backend = NULL;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
+
+       if (!func_output->output_hwc_create_window) {
+               if (error)
+                       *error = TDM_ERROR_BAD_MODULE;
+               return NULL;
+       }
+
+       hwc_window_backend = func_output->output_hwc_create_window(
+                                                private_output->output_backend, &ret);
+       if (ret != TDM_ERROR_NONE) {
+               if (error)
+                       *error = ret;
+               return NULL;
+       }
+
+       private_hwc_window = calloc(1, sizeof(tdm_private_capture));
+       if (!private_hwc_window) {
+               TDM_ERR("failed: alloc memory");
+               func_output->output_hwc_destroy_window(private_output->output_backend, hwc_window_backend);
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               return NULL;
+       }
+
+       LIST_ADD(&private_hwc_window->link, &private_output->hwc_window_list);
+
+       private_hwc_window->private_display = private_display;
+       private_hwc_window->private_output = private_output;
+       private_hwc_window->hwc_window_backend = hwc_window_backend;
+
+       TDM_DBG("hwc_window(%p) create", private_hwc_window);
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return private_hwc_window;
+}
+
+INTERN tdm_error
+tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window)
+{
+       tdm_private_display *private_display;
+       tdm_private_output *private_output;
+       tdm_func_output *func_output;
+
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
+
+       if (!private_hwc_window)
+               return TDM_ERROR_OPERATION_FAILED;
+
+       private_display = private_hwc_window->private_display;
+       private_output = private_hwc_window->private_output;
+
+       LIST_DEL(&private_hwc_window->link);
+
+       func_output = &private_display->func_output;
+       func_output->output_hwc_destroy_window(private_output->output_backend, private_hwc_window->hwc_window_backend);
+
+       free(private_hwc_window);
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_set_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_set_flags) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_set_flags(private_hwc_window->hwc_window_backend, flags);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_unset_flags) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_unset_flags(private_hwc_window->hwc_window_backend, flags);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_video_get_capability(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_video_capability *video_capability)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_video_get_capability) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_video_get_capability(private_hwc_window->hwc_window_backend,
+                                                                                                                  video_capability);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_hwc_window_video_get_supported_format(tdm_hwc_window *hwc_window,
+                                                                                 const tbm_format **formats,
+                                                                                 int *count)
+{
+       tdm_func_hwc_window *func_hwc_window = NULL;
+
+       HWC_WINDOW_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_hwc_window = &private_display->func_hwc_window;
+
+       if (!func_hwc_window->hwc_window_video_get_supported_format) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_hwc_window->hwc_window_video_get_supported_format(private_hwc_window->hwc_window_backend,
+                                                                                                                                formats, count);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
index 2374a36..98b1a5a 100644 (file)
        private_output = (tdm_private_output*)output; \
        private_display = private_output->private_display
 
+
+static tdm_private_hwc_window *
+_tdm_output_find_private_hwc_window(tdm_private_output *private_output,
+                                                               tdm_hwc_window *hwc_window_backend)
+{
+       tdm_private_hwc_window *private_hwc_window = NULL;
+
+       LIST_FOR_EACH_ENTRY(private_hwc_window, &private_output->hwc_window_list, link) {
+               if (private_hwc_window->hwc_window_backend == hwc_window_backend)
+                       return private_hwc_window;
+       }
+
+       return NULL;
+}
+
 EXTERN tdm_error
 tdm_output_get_model_info(tdm_output *output, const char **maker,
                                                  const char **model, const char **name)
@@ -283,6 +298,12 @@ tdm_output_get_layer_count(tdm_output *output, int *count)
 
        _pthread_mutex_lock(&private_display->lock);
 
+       if (private_display->hwc_enable) {
+               *count = 0;
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
        *count = 0;
        LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
        (*count)++;
@@ -309,6 +330,13 @@ tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
        if (error)
                *error = TDM_ERROR_NONE;
 
+       if (private_display->hwc_enable) {
+               _pthread_mutex_unlock(&private_display->lock);
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
        LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
                if (private_layer->index == index) {
                        _pthread_mutex_unlock(&private_display->lock);
@@ -1310,6 +1338,250 @@ tdm_output_create_capture(tdm_output *output, tdm_error *error)
        return capture;
 }
 
+EXTERN tdm_hwc_window *
+tdm_output_hwc_create_window(tdm_output *output, tdm_error *error)
+{
+       tdm_hwc_window *hwc_window = NULL;
+
+       OUTPUT_FUNC_ENTRY_ERROR();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if (private_display->hwc_enable)
+               hwc_window = (tdm_hwc_window *)tdm_hwc_window_create_internal(private_output, error);
+       else
+               if (error)
+                       *error = TDM_ERROR_BAD_REQUEST;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return hwc_window;
+}
+
+EXTERN tdm_error
+tdm_output_hwc_destroy_window(tdm_output *output, tdm_hwc_window *hwc_window)
+{
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       ret = tdm_hwc_window_destroy_internal(hwc_window);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types)
+{
+       tdm_func_output *func_output = NULL;
+
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_output = &private_display->func_output;
+
+       if (!func_output->output_hwc_validate) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_output->output_hwc_validate(private_output->output_backend, num_types);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_output_hwc_set_need_validate_handler(tdm_output *output,
+               tdm_output_need_validate_handler hndl)
+{
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(hndl != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       /* there's no reason to allow this */
+       if (private_output->need_validate.hndl) {
+
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       private_output->need_validate.hndl = hndl;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_output_hwc_get_changed_composition_types(tdm_output *output,
+                                                                                uint32_t *num_elements,
+                                                                                tdm_hwc_window **hwc_window,
+                                                                                tdm_hwc_window_composition *composition_types)
+{
+       tdm_func_output *func_output = NULL;
+       tdm_private_hwc_window * private_hwc_window = NULL;
+       int i = 0;
+
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_output = &private_display->func_output;
+
+       if (!func_output->output_hwc_get_changed_composition_types) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_output->output_hwc_get_changed_composition_types(private_output->output_backend,
+                                                       num_elements, hwc_window, composition_types);
+       if (ret != TDM_ERROR_NONE) {
+               _pthread_mutex_unlock(&private_display->lock);
+               return ret;
+       }
+
+       if (hwc_window == NULL || composition_types == NULL) {
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
+       for (i = 0; i < *num_elements; i++) {
+
+               private_hwc_window = _tdm_output_find_private_hwc_window(private_output, hwc_window[i]);
+
+               if (private_hwc_window == NULL) {
+                       TDM_ERR("failed! This should never happen!");
+                       func_output->output_hwc_destroy_window(private_output->output_backend, hwc_window[i]);
+                       *num_elements = 0;
+                       _pthread_mutex_unlock(&private_display->lock);
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               hwc_window[i] = (tdm_hwc_window*)private_hwc_window;
+       }
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+tdm_error
+tdm_output_hwc_accept_changes(tdm_output *output)
+{
+       tdm_func_output *func_output = NULL;
+
+       OUTPUT_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_output = &private_display->func_output;
+
+       if (!func_output->output_hwc_validate) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       ret = func_output->output_hwc_accept_changes(private_output->output_backend);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+tbm_surface_queue_h
+tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error)
+{
+       tdm_func_output *func_output = NULL;
+       tbm_surface_queue_h queue = NULL;
+
+       OUTPUT_FUNC_ENTRY_ERROR();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       func_output = &private_display->func_output;
+
+       if (!func_output->output_hwc_get_target_buffer_queue) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return NULL;
+       }
+
+       queue = func_output->output_hwc_get_target_buffer_queue(private_output->output_backend, error);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return queue;
+}
+
+static void
+_tdm_target_window_dump_buffer(tdm_private_output *private_output, tbm_surface_h buffer)
+{
+       unsigned int pipe;
+       char fname[PATH_MAX];
+
+       pipe = private_output->pipe;
+
+       snprintf(fname, sizeof(fname), "tdm_%d_target_win", pipe);
+
+       tbm_surface_internal_dump_buffer(buffer, fname);
+       TDM_DBG("%s dump excute", fname);
+
+       return;
+}
+
+EXTERN tdm_error
+tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target_buffer,
+                                                                       tdm_hwc_region damage)
+{
+       tdm_func_output *func_output = NULL;
+
+       OUTPUT_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if (tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) {
+               char str[TDM_PATH_LEN];
+               static int i;
+               snprintf(str, TDM_PATH_LEN, "target_window_%d_%03d",
+                                private_output->index, i++);
+               tdm_helper_dump_buffer_str(target_buffer, tdm_debug_dump_dir, str);
+       }
+
+       func_output = &private_display->func_output;
+
+       if (!func_output->output_hwc_set_client_target_buffer) {
+               _pthread_mutex_unlock(&private_display->lock);
+               TDM_ERR("not implemented!!");
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       /* dump buffer */
+       if (tdm_dump_enable)
+               _tdm_target_window_dump_buffer((tdm_private_output *)output, target_buffer);
+
+       ret = func_output->output_hwc_set_client_target_buffer(private_output->output_backend, target_buffer, damage);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
 INTERN void
 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
                                                                                struct list_head *change_handler_list,
@@ -1346,3 +1618,65 @@ tdm_output_call_change_handler_internal(tdm_private_output *private_output,
                _pthread_mutex_lock(&private_display->lock);
        }
 }
+
+
+/* gets called on behalf of the ecore-main-loop thread */
+INTERN tdm_error
+tdm_output_cb_need_validate(tdm_private_output *private_output)
+{
+       TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_INFO("tdm-backend asks for revalidation for the output:%p.", private_output);
+
+       if (private_output->need_validate.hndl)
+               private_output->need_validate.hndl((tdm_output*)private_output);
+
+       return TDM_ERROR_NONE;
+}
+
+/* gets called on behalf of the tdm-thread */
+static tdm_error
+_need_validate_handler(int fd, tdm_event_loop_mask mask, void *user_data)
+{
+       tdm_thread_cb_need_validate ev;
+       tdm_private_output *private_output;
+       tdm_error ret;
+
+       private_output = (tdm_private_output *)user_data;
+
+       ev.base.type = TDM_THREAD_CB_NEED_VALIDATE;
+       ev.base.length = sizeof ev;
+       ev.o = private_output;
+
+       ret = tdm_thread_send_cb(private_output->private_display->private_loop, &ev.base);
+       TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       TDM_INFO("tdm-thread: get a 'need to revalidate' event for the ouptut:%p.", private_output);
+
+       /* who cares about this? */
+       return TDM_ERROR_NONE;
+}
+
+INTERN tdm_error
+tdm_output_need_validate_event_init(tdm_output *output)
+{
+       int fd;
+
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
+
+       /* build in eventfd fds into event_loop listened & handled by the tdm-thread */
+       fd = eventfd(0, 0);
+       TDM_WARNING_IF_FAIL(fd >= 0);
+
+       tdm_event_loop_add_fd_handler(private_display, fd,      TDM_EVENT_LOOP_READABLE,
+                       _need_validate_handler, private_output, &ret);
+       TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       private_output->need_validate.event_fd = fd;
+
+       TDM_INFO("register an output:%p for the revalidation, event_fd:%d.", private_output, fd);
+
+       return ret;
+}
index 522ae57..6bfbe10 100644 (file)
@@ -52,6 +52,7 @@
 #include <poll.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
+#include <sys/eventfd.h>
 #include <math.h>
 #include <grp.h>
 
@@ -110,6 +111,7 @@ enum {
        TDM_DUMP_FLAG_LAYER   = (1 << 0),
        TDM_DUMP_FLAG_PP      = (1 << 1),
        TDM_DUMP_FLAG_CAPTURE = (1 << 2),
+       TDM_DUMP_FLAG_WINDOW = (1 << 3),
 };
 
 #define TDM_DUMP_DIR    "/tmp"
@@ -123,6 +125,7 @@ typedef enum {
 typedef struct _tdm_private_display tdm_private_display;
 typedef struct _tdm_private_output tdm_private_output;
 typedef struct _tdm_private_layer tdm_private_layer;
+typedef struct _tdm_private_hwc_window tdm_private_hwc_window;
 typedef struct _tdm_private_pp tdm_private_pp;
 typedef struct _tdm_private_capture tdm_private_capture;
 typedef struct _tdm_private_loop tdm_private_loop;
@@ -152,6 +155,7 @@ struct _tdm_private_display {
        tdm_func_display func_display;
        tdm_func_output func_output;
        tdm_func_layer func_layer;
+       tdm_func_hwc_window func_hwc_window;
        tdm_func_pp func_pp;
        tdm_func_capture func_capture;
 
@@ -177,6 +181,8 @@ struct _tdm_private_display {
        int commit_per_vblank;
        tdm_commit_type commit_type;
 
+       int hwc_enable;
+
        int print_fps;
 };
 
@@ -202,6 +208,7 @@ struct _tdm_private_output {
        int regist_dpms_cb;
 
        struct list_head layer_list;
+       struct list_head hwc_window_list;
        struct list_head capture_list;
        struct list_head vblank_handler_list;
        struct list_head output_commit_handler_list;
@@ -220,6 +227,12 @@ struct _tdm_private_output {
 
        /* TODO: temp solution for handling DPMS things in sub-htread */
        tdm_event_loop_source *dpms_changed_timer;
+
+       struct {
+               /* look at the tdm_output_set_need_revalidate_handler() declaration for the details */
+               tdm_output_need_validate_handler hndl;
+               int event_fd;
+       } need_validate;
 };
 
 struct _tdm_private_layer {
@@ -257,6 +270,19 @@ struct _tdm_private_layer {
        unsigned int fps_count;
 };
 
+struct _tdm_private_hwc_window {
+       struct list_head link;
+
+       int index;
+       uint32_t zpos;
+
+       tdm_private_display *private_display;
+       tdm_private_output *private_output;
+
+       tdm_hwc_window *hwc_window_backend;
+};
+
+
 struct _tdm_private_pp {
        struct list_head link;
 
@@ -427,6 +453,9 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
 void
 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms,
                                   void *user_data);
+INTERN tdm_error
+tdm_output_cb_need_validate(tdm_private_output *private_output);
+
 tdm_error
 tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
                                                                 tdm_output_vblank_handler func, void *user_data);
@@ -435,6 +464,9 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl
 tdm_error
 tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value);
 
+tdm_error
+tdm_output_need_validate_event_init(tdm_output *output);
+
 void
 tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data);
 void
@@ -476,6 +508,11 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error);
 void
 tdm_pp_destroy_internal(tdm_private_pp *private_pp);
 
+tdm_hwc_window *
+tdm_hwc_window_create_internal(tdm_private_output *private_output, tdm_error *error);
+tdm_error
+tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window);
+
 tdm_private_capture *
 tdm_capture_create_output_internal(tdm_private_output *private_output,
                                                                   tdm_error *error);
@@ -523,6 +560,7 @@ typedef enum {
        TDM_THREAD_CB_PP_DONE,
        TDM_THREAD_CB_CAPTURE_DONE,
        TDM_THREAD_CB_VBLANK_SW,
+       TDM_THREAD_CB_NEED_VALIDATE,
 } tdm_thread_cb_type;
 
 typedef struct _tdm_thread_cb_base tdm_thread_cb_base;
@@ -533,6 +571,7 @@ typedef struct _tdm_thread_cb_output_dpms tdm_thread_cb_output_dpms;
 typedef struct _tdm_thread_cb_pp_done tdm_thread_cb_pp_done;
 typedef struct _tdm_thread_cb_capture_done tdm_thread_cb_capture_done;
 typedef struct _tdm_thread_cb_vblank_sw tdm_thread_cb_vblank_sw;
+typedef struct _tdm_thread_cb_need_validate tdm_thread_cb_need_validate;
 
 struct _tdm_thread_cb_base {
        tdm_thread_cb_type type;
@@ -582,6 +621,11 @@ struct _tdm_thread_cb_vblank_sw {
        double vblank_stamp;
 };
 
+struct _tdm_thread_cb_need_validate {
+       tdm_thread_cb_base base;
+       tdm_private_output *o;
+};
+
 tdm_error
 tdm_thread_init(tdm_private_loop *private_loop);
 void
@@ -706,7 +750,6 @@ tdm_display_enable_fps(tdm_private_display *private_display, int enable);
 void
 tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len);
 
-
 struct argument_details {
        char type;
        int nullable;
index 4659740..8f624e1 100644 (file)
@@ -356,6 +356,11 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop)
                        tdm_vblank_cb_vblank_SW(NULL, vblank_sw->vblank_stamp);
                        break;
                }
+               case TDM_THREAD_CB_NEED_VALIDATE: {
+                       tdm_thread_cb_need_validate *ev = (tdm_thread_cb_need_validate*)base;
+                       tdm_output_cb_need_validate(ev->o);
+                       break;
+               }
                default:
                        break;
                }