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

304 lines
7.2 KiB
C++
Executable file

/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 "hwc.h"
#include <cutils/list.h>
#define LAYER_CACHE_SHRINK_NUM 16
static struct listnode cacheList;
static int cache_cout;
static pthread_mutex_t chaceMutex;
static struct listnode submitCacheList;
static int submit_cache_cout;
static pthread_mutex_t submitChaceMutex;
void layerCacheInit(void)
{
pthread_mutex_init(&chaceMutex, 0);
list_init(&cacheList);
cache_cout = 0;
pthread_mutex_init(&submitChaceMutex, 0);
list_init(&submitCacheList);
submit_cache_cout = 0;
}
void layerCacheDeinit(void)
{
Layer_t *layer = NULL;
LayerSubmit_t *submitLayer = NULL;
struct listnode *node = NULL;
list_for_each(node, &cacheList) {
layer = node_to_item(node, Layer_t, node);
hwc_free(layer);
}
list_for_each(node, &submitCacheList) {
submitLayer = node_to_item(node, LayerSubmit_t, node);
hwc_free(submitLayer);
}
cache_cout = 0;
submit_cache_cout = 0;
return;
}
void createList(struct listnode *list) {
list_init(list);
}
Layer_t* layerCacheGet(int size)
{
Layer_t *layer = NULL;
struct listnode *node = NULL;
pthread_mutex_lock(&chaceMutex);
if (cache_cout > 0) {
cache_cout--;
node = list_head(&cacheList);
list_remove(node);
list_init(node);
layer = node_to_item(node, Layer_t, node);
}
pthread_mutex_unlock(&chaceMutex);
if (layer != NULL)
goto deal;
layer = (Layer_t *)hwc_malloc(sizeof(Layer_t)+ size);
if (layer == NULL){
ALOGE("%s:malloc layer err...",__FUNCTION__);
return NULL;
}
deal:
memset(layer, 0, sizeof(Layer_t)+ size);
layer->releaseFence = -1;
layer->preReleaseFence = -1;
layer->acquireFence = -1;
layer->myselfHandle = 0;
layer->buffer = NULL;
layer->ref = 1;
list_init(&layer->node);
return layer;
}
LayerSubmit_t* submitLayerCacheGet(void)
{
LayerSubmit_t *submitLayer = NULL;
struct listnode *node = NULL;
pthread_mutex_lock(&submitChaceMutex);
if (submit_cache_cout > 0) {
submit_cache_cout--;
node = list_head(&submitCacheList);
list_remove(node);
list_init(node);
submitLayer = node_to_item(node, LayerSubmit_t, node);
}
pthread_mutex_unlock(&submitChaceMutex);
if (submitLayer != NULL)
goto deal;
submitLayer = (LayerSubmit_t *)hwc_malloc(sizeof(LayerSubmit_t));
deal:
list_init(&submitLayer->node);
list_init(&submitLayer->layerNode);
submitLayer->sync.fd = -1;
submitLayer->sync.count = 0;
submitLayer->currentConfig = NULL;
return submitLayer;
}
void layerCachePut(Layer_t *layer)
{
private_handle_t *handle;
handle = (private_handle_t *)layer->buffer;
/* other fd source.if nesesory,
* check if close surfaceFlinger's fd
*/
pthread_mutex_lock(&chaceMutex);
layer->ref--;
if (layer->ref > 0) {
pthread_mutex_unlock(&chaceMutex);
return;
}
pthread_mutex_unlock(&chaceMutex);
if (layer->myselfHandle) {
if (layer->buffer != NULL && handle->share_fd >= 0)
close(handle->share_fd);
layer->myselfHandle = 0;
hwc_free((void*)layer->buffer);
}
if (layer->releaseFence >= 0) {
close(layer->releaseFence);
layer->releaseFence = -1;
}
if (layer->acquireFence >= 0) {
close(layer->acquireFence);
layer->acquireFence = -1;
}
if (layer->preReleaseFence >= 0) {
close(layer->preReleaseFence);
layer->preReleaseFence = -1;
}
trCachePut(layer);
layer->buffer = NULL;
layer->memresrve = 0;
layer->trcache = NULL;
list_remove(&layer->node);
list_init(&layer->node);
pthread_mutex_lock(&chaceMutex);
if (cache_cout > LAYER_CACHE_SHRINK_NUM) {
hwc_free(layer);
pthread_mutex_unlock(&chaceMutex);
return;
}
cache_cout++;
list_add_tail(&cacheList, &layer->node);
pthread_mutex_unlock(&chaceMutex);
}
void submitLayerCachePut(LayerSubmit_t *submitLayer)
{
Layer_t *layer = NULL;
struct listnode *node, *node2;
list_for_each_safe(node, node2, &submitLayer->layerNode) {
layer = node_to_item(node, Layer_t, node);
list_remove(&layer->node);
list_init(&layer->node);
layerCachePut(layer);
}
if (submitLayer->sync.fd >= 0)
close(submitLayer->sync.fd);
submitLayer->sync.fd = -1;
list_remove(&submitLayer->node);
list_init(&submitLayer->node);
list_init(&submitLayer->layerNode);
pthread_mutex_lock(&submitChaceMutex);
if (submit_cache_cout > LAYER_CACHE_SHRINK_NUM) {
hwc_free(submitLayer);
pthread_mutex_unlock(&submitChaceMutex);
return;
}
submit_cache_cout++;
list_add_tail(&submitCacheList, &submitLayer->node);
pthread_mutex_unlock(&submitChaceMutex);
}
Layer_t* layerDup(Layer_t *layer, int priveSize)
{
Layer_t *duplayer = layerCacheGet(priveSize);
private_handle_t *handle = NULL, *handle2 = NULL;
memcpy(duplayer, layer, sizeof(Layer_t)+priveSize);
list_init(&duplayer->node);
if (layer->acquireFence >= 0)
duplayer->acquireFence = dup(layer->acquireFence);
/* dup the gralloc handle */
duplayer->myselfHandle = 0;
if (layer->buffer != NULL) {
duplayer->myselfHandle = 1;
handle2 = (private_handle_t *)hwc_malloc(sizeof(private_handle_t));
handle = (private_handle_t *)duplayer->buffer;
*handle2= *handle;
/* other fd source.if nesesory */
handle2->share_fd = dup(handle->share_fd);
duplayer->buffer = handle2;
}
duplayer->releaseFence = -1;
duplayer->preReleaseFence = -1;
duplayer->trcache = (void *)trCacheGet(layer);
duplayer->ref = 1;
return duplayer;
}
void clearList(struct listnode *list, bool lay)
{
struct listnode *node;
Layer_t *layer;
LayerSubmit_t *submitLayer;
while (!list_empty(list)) {
node = list_head(list);
list_remove(node);
if(lay) {
layer = node_to_item(node, Layer_t, node);
layerCachePut(layer);
}else{
submitLayer = node_to_item(node, LayerSubmit_t, node);
submitLayerCachePut(submitLayer);
}
}
}
bool insertLayerByZorder(Layer_t *element, struct listnode *list)
{
struct listnode *node;
Layer_t *layer;
int i = 0;
bool addone = 1;
if (list_empty(list)) {
list_add_tail(list, &element->node);
return addone;
}
list_for_each(node, list) {
layer = node_to_item(node, Layer_t, node);
if(layer == element)
addone = 0;
}
list_remove(&element->node);
list_for_each(node, list) {
layer = node_to_item(node, Layer_t, node);
if (layer->zorder > element->zorder){
break;
}else if (layer->zorder == element->zorder) {
/* when resident layers will reorder, not bug */
ALOGV("warning: there is same zoder in layer list.\n");
}
}
list_add_tail(node, &element->node);
return addone;
}
bool deletLayerByZorder(Layer_t *element, struct listnode *list)
{
struct listnode *node;
Layer_t *layer;
list_for_each(node, list) {
layer = node_to_item(node, Layer_t, node);
if (layer == element){
list_remove(&element->node);
list_init(&element->node);
return true;
}
}
return false;
}