From: Boram Park Date: Fri, 2 Sep 2016 07:47:27 +0000 (+0900) Subject: correct the wrong behavior when the sequence value reaches the MAX(4,294,967,295) X-Git-Tag: submit/tizen/20160905.105032~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a839cbdd816b1153003f16a9a6b3c4ca129b1602;p=platform%2Fcore%2Fuifw%2Flibtdm.git correct the wrong behavior when the sequence value reaches the MAX(4,294,967,295) - The sequence value of tdm client vblank will start 1 always. - When the sequence reaches MAX, then it will become 0 at the next vblank. Change-Id: Ie66cf5ac717246e309e6e2d86eb5c0b1fc2e71c7 --- diff --git a/client/tdm_client.h b/client/tdm_client.h index 1c2ef7d..e7df780 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -385,8 +385,6 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli * #tdm_client_vblank_set_enable_fake sets true. Once #tdm_client_vblank_wait_seq * returns TDM_ERROR_NONE, the user client vblank handler(#tdm_client_vblank_handler) * SHOULD be called on reaching the target sequence. - * If the sequence value is 0, the result will be the same with calling - * #tdm_client_vblank_wait with (interval = 1). * @param[in] vblank The client vblank object * @param[in] sequence The target sequence number * @param[in] func The user client vblank handler diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 8ff13e5..777a5ff 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -52,6 +52,16 @@ * - use a tdm_event_loop_source object only. */ +#define TDM_VBLANK_UINT_MAX 4294967295U +#define TDM_VBLANK_UINT_1Q 1073741823U /* UINT_MAX / 4 */ +#define TDM_VBLANK_UINT_3Q 3221225471U /* UINT_MAX / 4 * 3 */ + +/* (seq < TDM_VBLANK_UINT_1Q && TDM_VBLANK_UINT_3Q < last_seq) means + * that the sequence value has reached the max value and started from 0 again. + */ +#define TDM_VBLANK_SEQ_REACHED_MAX(seq, last_seq) \ + ((seq) < TDM_VBLANK_UINT_1Q && TDM_VBLANK_UINT_3Q < (last_seq)) + #define VER(fmt, arg...) TDM_ERR("[%p] "fmt, private_vblank, ##arg) #define VWR(fmt, arg...) TDM_WRN("[%p] "fmt, private_vblank, ##arg) #define VIN(fmt, arg...) TDM_INFO("[%p] "fmt, private_vblank, ##arg) @@ -89,7 +99,6 @@ typedef struct _tdm_private_vblank { /* for HW */ double HW_vblank_gap; struct list_head HW_wait_list; - unsigned int HW_seq_margin; /* for SW */ tdm_event_loop_source *SW_timer; @@ -508,24 +517,6 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, return; } - /* sequence is the relative value of fps. If fps = 10, sequence should be - * increased by 10 during 1 second. - */ - sequence /= private_vblank->quotient; - - /* If VBLANK_TYPE_SW_FAKE, HW sequeuce can become less than SW sequeuce. - * so we will correct it with HW_seq_margin. - */ - if (private_vblank->last_seq > sequence) { - unsigned long last, tv; - last = (unsigned long)private_vblank->last_tv_sec * 1000000 + private_vblank->last_tv_usec; - tv = (unsigned long)tv_sec * 1000000 + tv_usec; - private_vblank->HW_seq_margin = ((tv - last) / (unsigned long)private_vblank->vblank_gap) + 1; - private_vblank->HW_seq_margin += private_vblank->last_seq - sequence; - } - - sequence += private_vblank->HW_seq_margin; - if (wait_info->type == VBLANK_TYPE_HW_SW) { unsigned long target; tdm_error ret; @@ -535,7 +526,6 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, target = (unsigned long)tv_sec * 1000000 + tv_usec; target += (private_vblank->offset * 1000); - wait_info->target_seq = sequence; wait_info->target_sec = target / 1000000; wait_info->target_usec = target % 1000000; @@ -554,14 +544,14 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, } if (tdm_debug_module & TDM_DEBUG_VBLANK) - VIN("wait(%p) sequence(%u) done", wait_info, sequence); + VIN("wait(%p) sequence(%u) done", wait_info, wait_info->target_seq); - private_vblank->last_seq = sequence; + private_vblank->last_seq = wait_info->target_seq; private_vblank->last_tv_sec = tv_sec; private_vblank->last_tv_usec = tv_usec; if (wait_info->func) - wait_info->func(private_vblank, TDM_ERROR_NONE, sequence, + wait_info->func(private_vblank, TDM_ERROR_NONE, wait_info->target_seq, tv_sec, tv_usec, wait_info->user_data); LIST_DEL(&wait_info->link); @@ -580,10 +570,11 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) hw_interval = wait_info->interval * private_vblank->quotient; - if (private_vblank->last_tv_sec != 0) { - unsigned long last, prev, req, curr; + if (private_vblank->last_tv_sec == 0) + wait_info->target_seq = 1; + else { + unsigned long last, prev, req, curr, target; unsigned int skip = 0; - unsigned int hw_skip; last = (unsigned long)private_vblank->last_tv_sec * 1000000 + private_vblank->last_tv_usec; req = (unsigned long)wait_info->req_sec * 1000000 + wait_info->req_usec; @@ -592,9 +583,14 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) prev = last + skip * private_vblank->vblank_gap; curr = tdm_helper_get_time_in_micros(); - hw_skip = (unsigned int)((curr - prev) / private_vblank->HW_vblank_gap); + target = prev; + while (target < curr) + target += private_vblank->vblank_gap; + + hw_interval = (unsigned int)((target - curr) / private_vblank->HW_vblank_gap) + 1; - hw_interval -= hw_skip; + wait_info->target_seq = private_vblank->last_seq; + wait_info->target_seq += (target - last) / (unsigned long)private_vblank->vblank_gap; if (tdm_debug_module & TDM_DEBUG_VBLANK) VIN("wait(%p) last(%4lu) req(%4lu) prev(%4lu) curr(%4lu) skip(%d) hw_interval(%d)", @@ -602,9 +598,6 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) skip, hw_interval); } - if (hw_interval < 1) - hw_interval = 1; - ret = tdm_output_wait_vblank(private_vblank->output, hw_interval, 0, _tdm_vblank_cb_vblank_HW, wait_info); @@ -802,12 +795,13 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - if (sequence == 0) { - interval = 1; - } else if (private_vblank->last_seq == 0) { + /* if the sequence of vblank reaches the max value, sequence can be 0. */ + + if (private_vblank->last_seq == 0) { TDM_WRN("can't calculate interval with sequence(%u)", sequence); interval = 1; - } else if (sequence > private_vblank->last_seq) { + } else if (sequence > private_vblank->last_seq || + TDM_VBLANK_SEQ_REACHED_MAX(sequence, private_vblank->last_seq)) { unsigned long last, curr, seq_target; last = (unsigned long)private_vblank->last_tv_sec * 1000000 + private_vblank->last_tv_usec;