typedef struct _E_Output_Capture E_Output_Capture;
typedef struct _E_Output_Layer E_Output_Layer;
+typedef struct _E_Output_Stream_Capture_Mask_Data E_Output_Stream_Capture_Mask_Data;
struct _E_Output_Capture
{
int zpos;
};
+struct _E_Output_Stream_Capture_Mask_Data
+{
+ Evas_Object *eo;
+ Eina_Stringshare *file;
+ Eina_Rectangle geometry;
+ Eina_Bool saved_hwc_deactive;
+};
+
static int _e_output_hooks_delete = 0;
static int _e_output_hooks_walking = 0;
[E_OUTPUT_INTERCEPT_HOOK_DPMS_OFF] = NULL,
};
+/* Use hash mechanism to avoid ABI break.
+ * It can be widely used like private data for E_Output, if there will be need
+ * for more use case.*/
+static Eina_Hash *_mask_data_hash = NULL;
+
static Eina_Bool _e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate);
static void _e_output_vblank_handler(tdm_output *output, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec, void *data);
+static E_Output_Stream_Capture_Mask_Data *_e_output_stream_capture_mask_data_get(E_Output *output);
+static void _e_output_stream_capture_mask_data_hash_cb_data_free(void *data);
+static void _e_output_stream_capture_mask_image_activate(E_Output *output);
+static void _e_output_stream_capture_mask_image_deactivate(E_Output *output);
+
static unsigned int
_e_output_aligned_width_get(E_Output *output, tbm_surface_h tsurface)
{
EINTERN Eina_Bool
e_output_init(void)
{
- /* nothing */
+ _mask_data_hash =
+ eina_hash_pointer_new(_e_output_stream_capture_mask_data_hash_cb_data_free);
+
return EINA_TRUE;
}
EINTERN void
e_output_shutdown(void)
{
- ;
+ E_FREE_FUNC(_mask_data_hash, eina_hash_free);
}
static char *
EINA_LIST_FREE(output->info.modes, m) free(m);
EINA_LIST_FREE(output->planes, plane) e_plane_free(plane);
+
+ eina_hash_del_by_key(_mask_data_hash, &output);
+
free(output);
}
output->stream_capture.start = EINA_TRUE;
+ _e_output_stream_capture_mask_image_activate(output);
+
if (output->stream_capture.possible_tdm_capture)
{
if (e_output_dpms_get(output))
output->stream_capture.start = EINA_FALSE;
+ _e_output_stream_capture_mask_image_deactivate(output);
+
if (eina_list_count(output->stream_capture.data) == 0)
{
if (!output->stream_capture.timer)
return EINA_TRUE;
}
+
+E_API Eina_Bool
+e_output_stream_capture_mask_image_file_set(E_Output *output, const char *file)
+{
+ E_Output_Stream_Capture_Mask_Data *md;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+ EOINF("set mask image file for stream capture : %s", output, file);
+
+ md = _e_output_stream_capture_mask_data_get(output);
+ if (!md)
+ {
+ EOERR("failed to get mask data", output);
+ return EINA_FALSE;
+ }
+
+ if (eina_streq(md->file, file))
+ return EINA_TRUE;
+
+ eina_stringshare_replace(&md->file, file);
+
+ if (output->stream_capture.start)
+ {
+ _e_output_stream_capture_mask_image_deactivate(output);
+
+ if (md->file)
+ _e_output_stream_capture_mask_image_activate(output);
+ }
+
+ return EINA_TRUE;
+}
+
+E_API Eina_Bool
+e_output_stream_capture_mask_image_geometry_set(E_Output *output, int x, int y, int w, int h)
+{
+ E_Output_Stream_Capture_Mask_Data *md;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 0, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(h > 0, EINA_FALSE);
+
+ EOINF("set geometry of mask image object: %d,%d (%dx%d)",
+ output, x, y, w, h);
+
+ md = _e_output_stream_capture_mask_data_get(output);
+ if (!md)
+ {
+ EOERR("failed to get mask data", output);
+ return EINA_FALSE;
+ }
+
+ EINA_RECTANGLE_SET(&md->geometry, x, y, w, h);
+
+ if (output->stream_capture.start)
+ {
+ if (md->eo)
+ evas_object_geometry_set(md->eo, x, y, w, h);
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_output_stream_capture_mask_data_hash_cb_data_free(void *data)
+{
+ free(data);
+}
+
+static E_Output_Stream_Capture_Mask_Data *
+_e_output_stream_capture_mask_data_get(E_Output *output)
+{
+ E_Output_Stream_Capture_Mask_Data *md;
+
+ md = eina_hash_find(_mask_data_hash, &output);
+ if (!md)
+ {
+ md = E_NEW(E_Output_Stream_Capture_Mask_Data, 1);
+ if (!md)
+ {
+ EOERR("failed to alloc memory for mask data", output);
+ return NULL;
+ }
+
+ md->geometry.w = 1;
+ md->geometry.h = 1;
+
+ eina_hash_add(_mask_data_hash, &output, md);
+ }
+
+ return md;
+}
+
+static void
+_e_output_stream_capture_mask_image_activate(E_Output *output)
+{
+ E_Output_Stream_Capture_Mask_Data *md;
+ Evas_Object *eo;
+ Evas_Load_Error err;
+ Eina_Bool hwc_deactive;
+
+ md = eina_hash_find(_mask_data_hash, &output);
+ if (!md)
+ {
+ /* It can be null if any api for mask image is not called. */
+ EOINF("not found mask data", output);
+ return;
+ }
+
+ if (!md->file)
+ {
+ EOINF("no file name for mask image", output);
+ return;
+ }
+
+ if (md->eo)
+ {
+ EOERR("mask image object is already exist.", output);
+ return;
+ }
+
+ eo = evas_object_image_filled_add(e_comp->evas);
+
+ evas_object_image_file_set(eo, md->file, NULL);
+ err = evas_object_image_load_error_get(eo);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ EOERR("failed to load image %s : %s", output,
+ md->file, evas_load_error_str(err));
+ evas_object_del(eo);
+ return;
+ }
+
+ evas_object_geometry_set(eo,
+ md->geometry.x, md->geometry.y,
+ md->geometry.w, md->geometry.h);
+
+ evas_object_pass_events_set(eo, EINA_TRUE);
+ evas_object_layer_set(eo, EVAS_LAYER_MAX);
+ evas_object_raise(eo);
+ evas_object_show(eo);
+
+ md->eo = eo;
+
+ /* Deactive HWC to display mask image on evas. it's saved for restoring.
+ *
+ * WARNING: Restoring deactive status won't work as expected if deactive
+ * status of HWC changes after it. It may cause undefined behavior. */
+ hwc_deactive = e_hwc_deactive_get(output->hwc);
+ if (!hwc_deactive)
+ e_hwc_deactive_set(output->hwc, EINA_TRUE);
+
+ md->saved_hwc_deactive = hwc_deactive;
+}
+
+static void
+_e_output_stream_capture_mask_image_deactivate(E_Output *output)
+{
+ E_Output_Stream_Capture_Mask_Data *md;
+
+ md = eina_hash_find(_mask_data_hash, &output);
+ if (!md)
+ {
+ EOINF("not found mask data", output);
+ return;
+ }
+
+ E_FREE_FUNC(md->eo, evas_object_del);
+
+ /* restore hwc deactive status. */
+ if (!md->saved_hwc_deactive)
+ e_hwc_deactive_set(output->hwc, EINA_FALSE);
+}