allwinner_a64/android/hardware/aw/hwc2/other/rotate.cpp
2018-08-08 17:00:29 +08:00

849 lines
21 KiB
C++
Executable file

/*
* Copyright (C) Allwinner Tech All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <utils/Trace.h>
#include <cutils/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <cutils/uevent.h>
#include <system/graphics.h>
#include <cutils/properties.h>
#include "../hwc.h"
#include "sunxi_tr.h"
/* sync with submit thread ,may need 2 (waite sync afrer sbumit),
* may 3(wait sync befor submit)
*/
typedef struct {
unsigned long clienId;
int timeout;
int trErrCnt;
}tr_per_disp_t;
static int trfd = -1;
static int sw_sync_fd = -1;
static unsigned sw_sync_count = 0;
static unsigned inc_count = 0;
static int trCacheCnt = 0;
int trBitMap;
tr_per_disp_t *tr_disp;
static pthread_mutex_t trCacheMutex;
char thread_name[32];
int priority;
static pthread_t thread_id;
static struct listnode SubmitHead;
static Mutex *rotate_mutex;
static Condition *rotate_cond;
typedef struct rotate_info {
struct listnode node;
int waite_fence;
int dst_waite_fence;
unsigned int syncCount;
unsigned int gsyncCount;
Layer_t *layer2;
Display_t *disp;
}rotate_info_t;
#define TR_CACHE_SHRINK_NUM 16
static struct listnode rcacheList;
static int rcache_cout;
static pthread_mutex_t rchaceMutex;
#ifndef USE_IOMMU
bool mustconfig = 1;
#else
bool mustconfig = 0;
#endif
rotate_info_t* trlistCacheGet(void)
{
rotate_info_t *tr_info = NULL;
struct listnode *node = NULL;
pthread_mutex_lock(&rchaceMutex);
if (rcache_cout > 0) {
rcache_cout--;
node = list_head(&rcacheList);
list_remove(node);
list_init(node);
tr_info = node_to_item(node, rotate_info_t, node);
}
pthread_mutex_unlock(&rchaceMutex);
if (tr_info != NULL)
goto deal;
tr_info = (rotate_info_t *)hwc_malloc(sizeof(rotate_info_t));
if (tr_info == NULL){
ALOGE("%s:malloc tr_info err...",__FUNCTION__);
return NULL;
}
deal:
memset(tr_info, 0, sizeof(tr_info));
tr_info->dst_waite_fence = -1;
tr_info->waite_fence = -1;
tr_info->layer2 = NULL;
list_init(&tr_info->node);
return tr_info;
}
void trlistCachePut(rotate_info_t *tr_info)
{
if (tr_info->waite_fence >= 0) {
close(tr_info->waite_fence);
tr_info->waite_fence = -1;;
}
if (tr_info->dst_waite_fence >= 0) {
close(tr_info->dst_waite_fence);
tr_info->dst_waite_fence = -1;
}
list_remove(&tr_info->node);
list_init(&tr_info->node);
tr_info->layer2 = NULL;
pthread_mutex_lock(&rchaceMutex);
if (rcache_cout > TR_CACHE_SHRINK_NUM) {
hwc_free(tr_info);
pthread_mutex_unlock(&rchaceMutex);
return;
}
rcache_cout++;
list_add_tail(&rcacheList, &tr_info->node);
pthread_mutex_unlock(&rchaceMutex);
}
void* rotateThreadLoop(void *list);
static inline int trFormatToHal(unsigned char tr)
{
switch(tr) {
case TR_FORMAT_YUV420_SP_VUVU:
return HAL_PIXEL_FORMAT_YCrCb_420_SP;
case TR_FORMAT_YUV420_P:
return HAL_PIXEL_FORMAT_YV12;
case TR_FORMAT_YUV420_SP_UVUV:
return HAL_PIXEL_FORMAT_AW_NV12;
case TR_FORMAT_ABGR_8888:
return HAL_PIXEL_FORMAT_RGBA_8888;
case TR_FORMAT_XBGR_8888:
return HAL_PIXEL_FORMAT_RGBX_8888;
case TR_FORMAT_ARGB_8888:
return HAL_PIXEL_FORMAT_BGRA_8888;
case TR_FORMAT_XRGB_8888:
return HAL_PIXEL_FORMAT_BGRX_8888;
case TR_FORMAT_BGR_888:
return HAL_PIXEL_FORMAT_RGB_888;
case TR_FORMAT_BGR_565:
return DISP_FORMAT_RGB_565;
default :
return TR_FORMAT_YUV420_P;
}
}
static inline tr_pixel_format halToTRFormat(int halFformat)
{
switch(halFformat) {
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
return TR_FORMAT_YUV420_SP_VUVU;
case HAL_PIXEL_FORMAT_YV12:
return TR_FORMAT_YUV420_P;
case HAL_PIXEL_FORMAT_AW_NV12:
return TR_FORMAT_YUV420_SP_UVUV;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_BGRX_8888:
return TR_FORMAT_ARGB_8888;
case HAL_PIXEL_FORMAT_RGB_888:
return TR_FORMAT_RGB_888;
case HAL_PIXEL_FORMAT_RGB_565:
return TR_FORMAT_RGB_565;
default :
return TR_FORMAT_YUV420_P;
}
}
int hwc_rotate_query(unsigned long tr_handle)
{
unsigned long arg[4] = {0};
int ret = -1;
arg[0] = tr_handle;
ret = ioctl(trfd, TR_QUERY, (unsigned long)arg);
return ret;
}
bool hwc_rotate_request(unsigned long *clinet)
{
unsigned long arg[4] = {0};
int ret;
arg[0] = (unsigned long)clinet;
ret = ioctl(trfd, TR_REQUEST, (unsigned long)&arg);
if(ret < 0) {
ALOGE("request ratate module err");
return 0;
}
return 1;
}
bool hwc_rotate_commit(unsigned long client, tr_info *tr_info)
{
unsigned long arg[4] = {0};
int ret = -1;
arg[0] = client;
arg[1] = (unsigned long)tr_info;
ret = ioctl(trfd, TR_COMMIT, (unsigned long)arg);
if (ret < 0) {
ALOGE("commit rotate err");
return 0;
}
return !ret;
}
void hwc_rotate_release(unsigned long client)
{
unsigned long arg[4] = {0};
int ret = -1;
arg[0] = client;
ret = ioctl(trfd, TR_RELEASE, (unsigned long)arg);
if (ret < 0) {
ALOGD("release rotate err");
}
}
bool hwc_rotate_settimeout(unsigned long client, unsigned long ms_time)
{
unsigned long arg[4] = {0};
int ret = -1;
arg[0] = client;
arg[1] = ms_time;
ret = ioctl(trfd, TR_SET_TIMEOUT, (unsigned long)arg);
return !ret;
}
int rotateDeviceInit(void)
{
trfd = open("/dev/transform", O_RDWR);
if (trfd < 0) {
ALOGE("Failed to open transform device");
return -1;
}
tr_disp = (tr_per_disp_t *)hwc_malloc(sizeof(tr_per_disp_t));
if(tr_disp == NULL) {
close(trfd);
trfd = -1;
ALOGE("Failed to alloc client for hwc");
return -1;
}
sw_sync_fd = sw_sync_timeline_create();
if (sw_sync_fd < 0) {
close(trfd);
trfd = -1;
hwc_free(tr_disp);
tr_disp = NULL;
ALOGE("Failed to init sy_sync for hwc");
return -1;
}
rotate_mutex = new Mutex();
rotate_cond = new Condition();
pthread_mutex_init(&rchaceMutex, 0);
list_init(&rcacheList);
rcache_cout = 0;
list_init(&SubmitHead);
pthread_create(&thread_id, NULL, rotateThreadLoop, &SubmitHead);
pthread_mutex_init(&trCacheMutex, 0);
return 0;
}
int rotateDeviceDeInit(int num)
{
if(trfd < 0) {
return 0;
}
while(num--) {
if(tr_disp->clienId != 0)
hwc_rotate_release(tr_disp->clienId);
}
pthread_join(thread_id, NULL);
delete(rotate_mutex);
delete(rotate_cond);
close(sw_sync_fd);
close(trfd);
trfd = -1;
hwc_free(tr_disp);
tr_disp = NULL;
return 0;
}
static inline tr_mode toTrMode(unsigned int mode)
{
tr_mode ret = TR_ROT_0;
switch(mode)
{
case HAL_TRANSFORM_FLIP_H:
ret = TR_HFLIP;
break;
case HAL_TRANSFORM_FLIP_V:
ret = TR_VFLIP;
break;
case HAL_TRANSFORM_ROT_90:
ret = TR_ROT_90;
break;
case HAL_TRANSFORM_ROT_180:
ret = TR_ROT_180;
break;
case HAL_TRANSFORM_ROT_270:
ret = TR_ROT_270;
break;
case (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90):
ret = TR_VFLIP_ROT_90;
break;
case (HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90):
ret = TR_HFLIP_ROT_90;
break;
default:
ret = TR_ROT_0;
}
return ret;
}
int culateTimeout(Layer_t *layer)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
unsigned int dst = handle->width * handle->height;
if (dst > 2073600) {
return 100;
}
if (dst > 1024000) {
return 50;
}
return 32;
}
void trCachePut(Layer_t *layer)
{
tr_cache_Array *cache;
cache = (tr_cache_Array *)layer->trcache;
if (cache == NULL)
return;
pthread_mutex_lock(&trCacheMutex);
cache->ref--;
if (cache->ref > 0) {
pthread_mutex_unlock(&trCacheMutex);
return ;
}
pthread_mutex_unlock(&trCacheMutex);
for (int i = 0; i < NOMORL_CACHE_N; i++) {
close(cache->array[i].share_fd);
if(cache->array[i].releasefd >=0)
close(cache->array[i].releasefd);
}
hwc_free(cache);
layer->trcache = NULL;
}
void* trCacheGet(Layer_t *layer)
{
tr_cache_Array *cache;
cache = (tr_cache_Array *)layer->trcache;
if (cache == NULL)
return NULL;
cache->ref++;
return (void*)cache;
}
tr_cache_t* acquireLastValid(Layer_t *layer)
{
tr_cache_Array *aCache = (tr_cache_Array *)layer->trcache;
int i = 0;
tr_cache_t *ccache = NULL;
unsigned int last = 0;
for (i = 0; i < NOMORL_CACHE_N; i++) {
if (aCache->array[i].sync_cnt > last
&& aCache->array[i].valid) {
ccache = &aCache->array[i];
last = aCache->array[i].sync_cnt;
}
}
return ccache;
}
tr_cache_t* dequeueTrBuffer(Layer_t *layer, rotate_info_t *rt_info)
{
tr_cache_t *ccache = NULL;
tr_cache_Array *aCache = (tr_cache_Array *)layer->trcache;
int i;
unsigned int little = rt_info->gsyncCount;
ccache = &aCache->array[rt_info->gsyncCount%NOMORL_CACHE_N];
/*
if (ccache->sync_cnt + NOMORL_CACHE_N >= syncCount) {
no think roll 828 days will roll....
for (i = 0; i < NOMORL_CACHE_N; i++) {
if (aCache->array[i].sync_cnt < little) {
ccache = &aCache->array[i];
little = aCache->array[i].sync_cnt;
}
}
}
*/
if (ccache->releasefd >= 0) {
if (sync_wait((int)ccache->releasefd, 3000)) {
ALOGE("dequeueTrBuffer waite aquire fence err %d current:%u disp:%u",
ccache->releasefd, rt_info->gsyncCount,rt_info->disp->commitThread->diplayCount);
/* dump fence */
}
close(ccache->releasefd);
ccache->releasefd = -1;
}
return ccache;
}
void* dequeueTrCache(Layer_t *layer)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
tr_cache_Array *aCache = NULL, *yuCache = NULL;
int size, i, allin;
size = HWC_ALIGN(handle->width, ROTATE_ALIGN) * HWC_ALIGN(handle->height, ROTATE_ALIGN)
* getBitsPerPixel(layer) / 8;
size = HWC_ALIGN(size, 4096);
if (layer->trcache != NULL) {
yuCache =(tr_cache_Array *) layer->trcache;
if (yuCache->size >= size)
return layer->trcache;
trCachePut(layer);
}
aCache = (tr_cache_Array *)hwc_malloc(sizeof(tr_cache_Array));
if (aCache == NULL) {
ALOGE("malloc cache array err");
return NULL;
}
ALOGV("layer:%p: %p:size:%d x %d size:%d",layer, aCache,handle->width, handle->height, size);
memset(aCache, 0, sizeof(tr_cache_Array));
for (i= 0; i < NOMORL_CACHE_N; i++) {
aCache->array[i].share_fd= ionAllocBuffer(size, mustconfig, layerIsProtected(layer));
if (aCache->array[i].share_fd < 0)
goto err;
aCache->array[i].sync_cnt = -NOMORL_CACHE_N;
aCache->array[i].releasefd = -1;
}
aCache->ref = 1;
aCache->size = size;
return (void *)aCache;
err:
for (i= 0; i < NOMORL_CACHE_N; i++) {
if(aCache->array[i].share_fd >= 0)
close(aCache->array[i].share_fd);
}
hwc_free(aCache);
ALOGE("dequeueTrCache err for ion err");
return NULL;
}
void trResetErr(void)
{
if (trfd < 0)
return;
tr_disp->trErrCnt = 0;
}
bool trHarewareRistrict(Layer_t *layer)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
int stride0;
if (handle == NULL)
return false;
/* just for yuv stride*/
if (((long long)handle->width) * handle->height > 1100 * 1950)
return false;
stride0 = HWC_ALIGN(handle->width, handle->aw_byte_align[0]);
switch(handle->format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_BGRX_8888:
stride0 = HWC_ALIGN(handle->width * 4, handle->aw_byte_align[0]);
if (stride0 % 4)
return false;
break;
case HAL_PIXEL_FORMAT_RGB_565:
stride0 = HWC_ALIGN(handle->width * 2, handle->aw_byte_align[0]);
if (stride0 % 2)
return false;
break;
case HAL_PIXEL_FORMAT_YV12:
//if (stride0%4)
return false;
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_AW_NV12:
//if (stride0%2)
return false;
break;
case HAL_PIXEL_FORMAT_RGB_888:
stride0 = HWC_ALIGN(handle->width * 3, handle->aw_byte_align[0]);
/* display use info->fb.crop.x and x is pixel ,
* so if rotate, but the blank is the begin,
* but not pixel's allign,
*/
if (stride0%3)
return false;
break;
default:
return false;
}
return true;
}
bool supportTR(Display_t *display, Layer_t *layer)
{
if (trfd < 0)
return false;
if (tr_disp->trErrCnt > 3) {
ALOGV("display:%d rotate has 3 contig err", display->displayId);
return false;
}
if (!trHarewareRistrict(layer))
return false;
layer->trcache = dequeueTrCache(layer);
return layer->trcache != NULL;
}
bool layerToTrinfo(Layer_t *layer, tr_info *tr_inf, tr_cache_t *bCache)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
int i = 0;
int cnt = getPlanFormat(layer);
memset(tr_inf, 0, sizeof(tr_info));
tr_inf->src_frame.fmt = halToTRFormat(handle->format);
unsigned int w_stride, h_stride;
unsigned long addr = 0;
tr_inf->mode = toTrMode(layer->transform);
int wScale[3] = { 1,2,2};
int hScale[3] = {1,2,2};
int bpp[3] = { 4, 2, 1};
addr = ionGetPhyAddress(handle->share_fd);
if (addr == 0 && mustconfig) {
ALOGD("%p: %d get ion addr err....",handle, handle->share_fd);
return 0;
}
switch(handle->format) {
case HAL_PIXEL_FORMAT_YV12:
bpp[1] = 1;
bpp[0] = 1;
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_AW_NV12:
bpp[1] = 2;
bpp[0] = 1;
break;
case HAL_PIXEL_FORMAT_RGB_888:
bpp[0] = 3;
default:
ALOGV("RGB");
}
i = 0;
while (i < cnt) {
tr_inf->src_frame.haddr[i] = 0;
tr_inf->src_frame.laddr[i] = addr;
/* rotate is piexl cal
* pitch[0] = info->src_frame.pitch[0] * ycnt;
* pitch[1] = info->src_frame.pitch[1] * ucnt;
* pitch[2] = info->src_frame.pitch[2] * ucnt;
*/
tr_inf->src_frame.pitch[i] = HWC_ALIGN(handle->width * bpp[i] / wScale[i], handle->aw_byte_align[i]) / bpp[i];
tr_inf->src_frame.height[i] = handle->height/hScale[i];
addr += tr_inf->src_frame.pitch[i] * bpp[i] * tr_inf->src_frame.height[i];
i++;
}
if (cnt == 3) {//YV12
tr_inf->src_frame.laddr[2] = tr_inf->src_frame.laddr[0] +
tr_inf->src_frame.pitch[0] * tr_inf->src_frame.height[0];
tr_inf->src_frame.laddr[1] = tr_inf->src_frame.laddr[2] +
tr_inf->src_frame.pitch[2] * tr_inf->src_frame.height[2];
}
tr_inf->src_frame.fd = -1;
/* tr_inf->src_frame.fd = handle->share_fd;*/
tr_inf->src_rect.x = 0;
tr_inf->src_rect.y = 0;
tr_inf->src_rect.w = HWC_ALIGN(handle->width * bpp[0], handle->aw_byte_align[0])/ bpp[0];
tr_inf->src_rect.h = handle->height;
addr = ionGetPhyAddress(bCache->share_fd);
if (addr == 0 && mustconfig) {
ALOGD("get ion addr err....");
return 0;
}
tr_inf->dst_frame.fmt = halToTRFormat(handle->format);
if (cnt != 1) {
/* yuv only support TR_FORMAT_YUV420_P output*/
tr_inf->dst_frame.fmt = TR_FORMAT_YUV420_P;
}
tr_inf->dst_rect.x = 0;
tr_inf->dst_rect.y = 0;
if (layer->transform & HAL_TRANSFORM_ROT_90) {
w_stride =handle->height;
h_stride = handle->width;
} else {
w_stride = handle->width;
h_stride = handle->height;
}
w_stride = HWC_ALIGN(w_stride * bpp[0], ROTATE_ALIGN) / bpp[0];
h_stride = HWC_ALIGN(h_stride * bpp[0], ROTATE_ALIGN) / bpp[0];
tr_inf->dst_frame.pitch[0] = w_stride;
tr_inf->dst_frame.height[0] = h_stride;
if (cnt != 1) {
tr_inf->dst_frame.pitch[1] = w_stride/2;
tr_inf->dst_frame.height[1] = h_stride/2;
tr_inf->dst_frame.pitch[2] = w_stride/2;
tr_inf->dst_frame.height[2] = h_stride/2;
}
tr_inf->dst_rect.w = w_stride;
tr_inf->dst_rect.h = h_stride;
tr_inf->dst_frame.haddr[0] = 0;
tr_inf->dst_frame.haddr[1] = 0;
tr_inf->dst_frame.haddr[2] = 0;
tr_inf->dst_frame.laddr[0] = addr;
/*YUV format we only support YV12 --> TR_FORMAT_YUV420_P*/
/*tr_info->dst_frame.laddr[0] --> Y*/
/*tr_info->dst_frame.laddr[1] --> U*/
/*tr_info->dst_frame.laddr[2] --> V*/
if (cnt != 1) {
tr_inf->dst_frame.laddr[2] = tr_inf->dst_frame.laddr[0] +
tr_inf->dst_frame.pitch[0] * tr_inf->dst_frame.height[0];
tr_inf->dst_frame.laddr[1] = tr_inf->dst_frame.laddr[2] +
tr_inf->dst_frame.pitch[2] * tr_inf->dst_frame.height[2];
}
/* tr_inf->dst_frame.fd = bCache->share_fd; */
tr_inf->dst_frame.fd = -1;
return 1;
}
int trAflterDeal(Layer_t *layer, tr_cache_t *bCache, tr_info *trInfo)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
close(handle->share_fd);
handle->share_fd = dup(bCache->share_fd);
handle->aw_byte_align[0] = ROTATE_ALIGN;
handle->aw_byte_align[1] = ROTATE_ALIGN / 2;
handle->aw_byte_align[2] = ROTATE_ALIGN / 2;
if (trInfo->dst_frame.fmt == TR_FORMAT_YUV420_P)
handle->format = HAL_PIXEL_FORMAT_YV12;
return 0;
}
int submitTransformLayer(rotate_info_t *rt_info, unsigned int syncCount)
{
ATRACE_CALL();
Layer_t *layer;
private_handle_t *handle;
layer = rt_info->layer2;
handle = (private_handle_t *)layer->buffer;
tr_cache_t *bCache = NULL;
tr_info trInfo;
int timeout = 0, ret = -1, i = 0;
bool last = 1;
/* if 2 screen use the same tr layer, we must reduce this case
*/
if (tr_disp->clienId == 0) {
if(!hwc_rotate_request(&tr_disp->clienId)) {
tr_disp->trErrCnt = 99;
return -1;
}
}
/* maybe crach for aCache== NULL, but amost impossible ,so no care*/
bCache = dequeueTrBuffer(layer, rt_info);
if (!layerToTrinfo(layer, &trInfo, bCache)) {
goto last;
}
timeout = culateTimeout(layer);
if (tr_disp->timeout != timeout) {
hwc_rotate_settimeout(tr_disp->clienId, timeout);
tr_disp->timeout = timeout;
}
//ALOGD("before rotate:%u %d x %d ",syncCount,handle->width, handle->height);
if (!hwc_rotate_commit(tr_disp->clienId, &trInfo)) {
bCache->valid = 0;
tr_disp->trErrCnt++;
}
i = (timeout * 1000/16);//video 30 fps
while (ret != 0 && i > 0) {
ret = hwc_rotate_query(tr_disp->clienId);
if (ret == -1) {
break;
}
usleep(16);
i--;
}
if (i <= 0 || ret == -1) {
ALOGD("rotate timeout or err:%d %d ", i, ret);
tr_disp->trErrCnt++;
bCache->valid = 0;
goto last;
}
bCache->valid = 1;
last = 0;
bCache->sync_cnt = syncCount;
bCache->releasefd = dup(rt_info->dst_waite_fence);
tr_disp->trErrCnt = 0;;
last:
//ALOGD("after rotate:%u ",syncCount);
if (last)
bCache = acquireLastValid(layer);
if (!bCache) {
tr_disp->trErrCnt = 4;
/* here will screen display err */
return -1;
}
trAflterDeal(layer, bCache, &trInfo);
return 0;
}
int get_rotate_fence_fd(Layer_t *layer2,
Display_t *disp, int releasefence, unsigned int syncCount)
{
char name[20];
int count;
int fence_fd = -1;
rotate_info_t *tr_info;
tr_info = trlistCacheGet();
if (tr_info == NULL)
return -1;
count = sprintf(name, "tr_fence_%u\n", sw_sync_count);
name[count+1] ='0';
tr_info->syncCount = ++sw_sync_count;
fence_fd = sw_sync_fence_create(sw_sync_fd, name, tr_info->syncCount);
tr_info->waite_fence = layer2->acquireFence;
layer2->acquireFence = dup(fence_fd);
tr_info->layer2 = layer2;
tr_info->dst_waite_fence = dup(releasefence);
tr_info->gsyncCount = syncCount;
tr_info->disp = disp;
layer2->ref++;
if (inc_count + 2 < tr_info->syncCount)
ALOGV("hw rotate so slowly:%u %u",
tr_info->syncCount, inc_count);
rotate_mutex->lock();
list_add_tail(&SubmitHead, &tr_info->node);
rotate_cond->signal();
rotate_mutex->unlock();
return fence_fd;
}
void deal_rotate_fence(rotate_info_t *tr_info)
{
inc_count++;
if (inc_count != tr_info->syncCount)
ALOGD("some wrong about rotate fence:%d %d...", inc_count, tr_info->syncCount);
sw_sync_timeline_inc(sw_sync_fd, 1);
}
void* rotateThreadLoop(void *list)
{
struct listnode comHead, *commitHead, *node, *node2, *node3, *rotate_list;
rotate_info_t *tr_info;
rotate_list = (struct listnode*)list;
commitHead = &comHead;
list_init(commitHead);
ALOGD("new a rotate thread to commit the display");
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
while(1) {
rotate_mutex->lock();
if (list_empty(rotate_list))
rotate_cond->wait(*rotate_mutex);
commitHead->next = rotate_list->next;
rotate_list->next->prev = commitHead;
commitHead->prev = rotate_list->prev;
rotate_list->prev->next = commitHead;
list_init(rotate_list);
rotate_mutex->unlock();
list_for_each_safe(node, node2, commitHead) {
tr_info = node_to_item(node, rotate_info_t, node);
if (tr_info->waite_fence >= 0) {
if (sync_wait((int)tr_info->waite_fence, 3000)) {
ALOGE("rotateThreadLoop waite aquire fence err %d", tr_info->waite_fence);
/* dump fence */
}
}
submitTransformLayer(tr_info, tr_info->gsyncCount);
deal_rotate_fence(tr_info);
layerCachePut(tr_info->layer2);
trlistCachePut(tr_info);
}
list_init(commitHead);
}
}