2413 lines
68 KiB
C++
Executable file
2413 lines
68 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 <hardware/hardware.h>
|
|
#include <hardware/hwcomposer2.h>
|
|
#include <cutils/log.h>
|
|
#include <system/graphics.h>
|
|
#include <cutils/list.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/fb.h>
|
|
#include <fcntl.h>
|
|
#include <EGL/egl.h>
|
|
#include <hardware/hal_public.h>
|
|
#include <pthread.h>
|
|
#include <hardware/sunxi_metadata_def.h>
|
|
#include <sys/resource.h>
|
|
#include <utils/Trace.h>
|
|
#include <cutils/properties.h>
|
|
#include <math.h>
|
|
|
|
#ifdef HOMLET_PLATFORM
|
|
#include "other/homlet.h"
|
|
#endif
|
|
|
|
#define ION_IOC_SUNXI_PHYS_ADDR 7
|
|
#define HAL_PIXEL_FORMAT_AW_NV12 0x101
|
|
#define PIPE_NUM 4
|
|
#define DE_NUM 2
|
|
#define LAYER_BY_PIPE 4
|
|
|
|
#define VI_NUM 1
|
|
/*limited by atw hardware*/
|
|
#define ATW_DEVICE_MAX_EYE_BUFFER_WIDTH 1280
|
|
|
|
using namespace android;
|
|
|
|
extern DisplayOpr_t sunxiDisplayOpr;
|
|
bool isOutOfLineBuffer = false;
|
|
|
|
typedef enum PipeType {
|
|
NOTASSIGN = 0,
|
|
VIDEO,
|
|
UI,
|
|
UI_NO_ALPHA,
|
|
} PipeType_t;
|
|
|
|
typedef struct PipeInfo {
|
|
int layNum;
|
|
PipeType_t type;
|
|
float planeAlpha;
|
|
Layer_t *hwcLayer[LAYER_BY_PIPE];//Z-Order up
|
|
float scaleW;
|
|
float scaleH;
|
|
int curentMem;
|
|
}PipeInfo_t;
|
|
|
|
typedef struct DisplayPrivate {
|
|
hwc_rect_t ScreenCutOff;//left is cutted pixels from left,etc.
|
|
struct disp_output type;
|
|
}DisplayPrivate_t;
|
|
/*
|
|
* DELayerPrivate_t all the hw assigned data
|
|
*/
|
|
typedef struct DELayerPrivate {
|
|
int pipe;
|
|
int layerId;
|
|
int zOrder;
|
|
float pipeScaleW;
|
|
float pipeScaleH;
|
|
}DELayerPrivate_t;
|
|
|
|
/*
|
|
* hardware Layout:
|
|
* 0~fixVideoPipeNum-1 is video channel;
|
|
* fixVideoPipeNum ~ fixPipeNumber-1 is UI channel;
|
|
* Pipe[PIPE_NUM]:Z-Order is up.
|
|
*/
|
|
typedef struct DESource {
|
|
int fixPipeNumber;
|
|
int fixVideoPipeNum;
|
|
int currentPipe;
|
|
int usedViPipe;
|
|
int usedPiexlAlpha;
|
|
PipeInfo_t *Pipe;
|
|
disp_layer_config2 *layerInfo;
|
|
DisplayConfig_t currentConfig;
|
|
} DESource_t;
|
|
|
|
int dispFd;
|
|
int tdFd;
|
|
long long deFreq = 254000000;
|
|
|
|
DESource_t DESource[DE_NUM];
|
|
|
|
char displayName[5][10] = {
|
|
{"lcd"},
|
|
{"hdmi"},
|
|
{"tv"},
|
|
{"vga"},
|
|
{"default"},
|
|
};
|
|
|
|
tv_para_t hdmi_support[]=
|
|
{
|
|
/* 1'st is default */
|
|
{DISP_TV_MOD_1024_600P, 1024, 600, 60, 0},
|
|
{DISP_TV_MOD_1280_800P, 1280, 800, 60, 0},
|
|
{DISP_TV_MOD_720P_60HZ, 1280, 720, 60, 0},
|
|
{DISP_TV_MOD_1080P_60HZ, 1920, 1080, 60, 0},
|
|
|
|
{DISP_TV_MOD_480I, 720, 480, 60, 0},
|
|
{DISP_TV_MOD_576I, 720, 576, 60, 0},
|
|
{DISP_TV_MOD_480P, 720, 480, 60, 0},
|
|
{DISP_TV_MOD_576P, 720, 576, 60, 0},
|
|
{DISP_TV_MOD_720P_50HZ, 1280, 720, 50, 0},
|
|
|
|
{DISP_TV_MOD_1080P_24HZ, 1920, 1080, 24, 0},
|
|
{DISP_TV_MOD_1080P_50HZ, 1920, 1080, 50, 0},
|
|
|
|
{DISP_TV_MOD_1080I_50HZ, 1920, 1080, 50, 0},
|
|
{DISP_TV_MOD_1080I_60HZ, 1920, 1080, 60, 0},
|
|
{DISP_TV_MOD_3840_2160P_25HZ, 3840, 2160, 25, 0},
|
|
{DISP_TV_MOD_3840_2160P_24HZ, 3840, 2160, 24, 0},
|
|
{DISP_TV_MOD_3840_2160P_30HZ, 3840, 2160, 30, 0},
|
|
{DISP_TV_MOD_3840_2160P_60HZ, 3840, 2160, 60, 0},
|
|
{DISP_TV_MOD_3840_2160P_50HZ, 3840, 2160, 50, 0},
|
|
{DISP_TV_MOD_4096_2160P_60HZ, 4096, 2160, 60, 0},
|
|
{DISP_TV_MOD_4096_2160P_50HZ, 4096, 2160, 50, 0},
|
|
{DISP_TV_MOD_1080P_24HZ_3D_FP, 1920, 1080, 24, 0},
|
|
{DISP_TV_MOD_720P_50HZ_3D_FP, 1280, 720, 50, 0},
|
|
{DISP_TV_MOD_720P_60HZ_3D_FP, 1280, 720, 60, 0},
|
|
};
|
|
|
|
enum display_3d_mode hdmi_3D_mode = DISPLAY_2D_ORIGINAL;
|
|
|
|
extern char *dumpchar;
|
|
|
|
#define arraySizeOf(array) sizeof(array)/sizeof(array[0])
|
|
|
|
static inline DisplayPrivate_t* toHwDisplay(Display_t *display) {
|
|
DisplayPrivate_t *hwDisplay = NULL;
|
|
hwDisplay = (DisplayPrivate_t*)display->data;
|
|
return hwDisplay;
|
|
}
|
|
|
|
static inline DELayerPrivate_t* toHwLayer(Layer_t *layer) {
|
|
DELayerPrivate_t* hwLayer = NULL;
|
|
hwLayer = (DELayerPrivate_t*)layer->data;
|
|
return hwLayer;
|
|
}
|
|
|
|
static inline DisplayConfigPrivate_t* toHwConfig(DisplayConfig_t *config) {
|
|
DisplayConfigPrivate_t* hwconfig = NULL;
|
|
hwconfig = (DisplayConfigPrivate_t*)config->data;
|
|
return hwconfig;
|
|
}
|
|
|
|
void calcGlobleLayerFactor(Display_t *display, Layer_t *layer, float *width, float *hight)
|
|
{
|
|
DisplayPrivate_t *hwdiplay;
|
|
DisplayConfig *config;
|
|
DisplayConfigPrivate_t *hwConfig;
|
|
float screenW, screenH;
|
|
float layerW, layerH;
|
|
|
|
config = display->displayConfigList[display->activeConfigId];
|
|
|
|
hwConfig = toHwConfig(config);
|
|
screenW = hwConfig->screenDisplay.right - hwConfig->screenDisplay.left;
|
|
screenH = hwConfig->screenDisplay.bottom - hwConfig->screenDisplay.top;
|
|
screenW /= config->width;
|
|
screenH /= config->height;
|
|
calcLayerFactor(layer, &layerW, &layerH);
|
|
|
|
*width = screenW * layerW;
|
|
*hight = screenH * layerH;
|
|
|
|
}
|
|
|
|
bool layerCanScale(long long deFreq, Display_t *display, Layer_t *layer)
|
|
{
|
|
DisplayPrivate_t *hwdiplay;
|
|
DisplayConfig *config;
|
|
DisplayConfigPrivate_t *hwConfig;
|
|
long long layerLinePeroid, screenLinePeroid,vsyncPeroid;
|
|
int srcW, srcH, swap, screenW, dstW;
|
|
float widthScale, hightScale;
|
|
|
|
config = display->displayConfigList[display->activeConfigId];
|
|
|
|
hwConfig = toHwConfig(config);
|
|
screenW = hwConfig->screenDisplay.right - hwConfig->screenDisplay.left;
|
|
calcGlobleLayerFactor(display, layer, &widthScale, &hightScale);
|
|
if (!layerIsVideo(layer)) {
|
|
#if (TARGET_BOARD_PLATFORM != petrel)
|
|
return config->width < 2048;
|
|
#endif
|
|
}
|
|
|
|
srcW = layer->crop.right - layer->crop.left;
|
|
srcH = layer->crop.bottom - layer->crop.top;
|
|
if(layer->transform & HAL_TRANSFORM_ROT_90) {
|
|
swap = srcW;
|
|
srcW = srcH;
|
|
srcH = swap;
|
|
}
|
|
|
|
dstW = (int)ceilf(srcW * widthScale);
|
|
vsyncPeroid = (config->vsyncPeriod ? config->vsyncPeriod : (1000000000/60));
|
|
|
|
screenLinePeroid = vsyncPeroid / config->height;
|
|
layerLinePeroid = (srcW > dstW) ? (1000000*((long long)(screenW - dstW + srcW))/(deFreq/1000))
|
|
: (1000000*((long long)screenW)/(deFreq/1000));
|
|
|
|
if((screenLinePeroid *4/5) < layerLinePeroid)
|
|
return 0; //can't
|
|
else
|
|
return 1;//can
|
|
|
|
}
|
|
|
|
|
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
|
#define min(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
/*
|
|
* check if de can handle ui scale.
|
|
*
|
|
* input params:
|
|
* ovlw, ovlh : source size
|
|
* outw, outh : frame size
|
|
* lcdw, lcdh : screen size
|
|
* lcd_fps : frame rate in Hz
|
|
* de_freq : de clock freqence in Hz
|
|
*
|
|
* return:
|
|
* 1 -- can use de scale
|
|
* 0 -- can NOT use de scale
|
|
*/
|
|
static int de_scale_capability_detect(
|
|
unsigned int ovlw, unsigned int ovlh,
|
|
unsigned int outw, unsigned int outh,
|
|
unsigned long long lcdw,
|
|
unsigned long long lcdh,
|
|
unsigned long long lcd_fps,
|
|
unsigned long long de_freq)
|
|
{
|
|
unsigned long long de_freq_req;
|
|
unsigned long long lcd_freq;
|
|
unsigned long long layer_cycle_num;
|
|
unsigned int dram_efficience = 95;
|
|
|
|
/*
|
|
* ovlh > outh : vertical scale down
|
|
* ovlh < outh : vertical scale up
|
|
*/
|
|
if (ovlh > outh)
|
|
layer_cycle_num = max(ovlw, outw) + max((ovlh - outh) * ovlw / outh, lcdw - outw);
|
|
else
|
|
layer_cycle_num = max(ovlw, outw) + (lcdw - outw);
|
|
|
|
lcd_freq = (lcdh) * (lcdw) * (lcd_fps) * 10 / 9;
|
|
de_freq_req = lcd_freq * layer_cycle_num * 100 / dram_efficience;
|
|
de_freq_req = de_freq_req / lcdw;
|
|
|
|
if (de_freq > de_freq_req)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static int hwc_ui_scaler_check(Display_t *display, Layer_t *layer)
|
|
{
|
|
int src_w = ceil(layer->crop.right - layer->crop.left);
|
|
int src_h = ceil(layer->crop.bottom - layer->crop.top);
|
|
int out_w = layer->frame.right - layer->frame.left;
|
|
int out_h = layer->frame.bottom - layer->frame.top;
|
|
DisplayConfig_t *dispconfig;
|
|
|
|
dispconfig = display->displayConfigList[display->activeConfigId];
|
|
int InitDisplayWidth = dispconfig->width;
|
|
int InitDisplayHeight = dispconfig->height;
|
|
|
|
out_w = out_w * display->hpercent * display->VarDisplayWidth / InitDisplayWidth / 100;
|
|
out_h = out_h * display->vpercent * display->VarDisplayHeight / InitDisplayHeight / 100;
|
|
|
|
out_w = out_w == 0 ? 1 : out_w;
|
|
out_h = out_h == 0 ? 1 : out_h;
|
|
|
|
return de_scale_capability_detect(src_w, src_h, out_w, out_h,
|
|
display->VarDisplayWidth,
|
|
display->VarDisplayHeight, 60, 696000000);
|
|
}
|
|
|
|
|
|
static inline void resetLayer(Layer_t *layer)
|
|
{
|
|
DELayerPrivate_t *deLayer;
|
|
deLayer = toHwLayer(layer);
|
|
|
|
deLayer->pipe = -1;
|
|
deLayer->layerId = -1;
|
|
deLayer->zOrder = -1;
|
|
layer->typeChange = 0;
|
|
layer->clearClientTarget = 0;
|
|
layer->duetoFlag = HWC_LAYER;
|
|
if (layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET)
|
|
layer->duetoFlag = NOT_ASSIGN;
|
|
}
|
|
|
|
static void resetHwPipe(Display_t *display, int from, int to, bool first)
|
|
{
|
|
int i = 0, j = 0, cutVi = 0, cutUIAlpha = 0;
|
|
Layer_t *layer;
|
|
DESource_t *hw = &DESource[display->displayId];
|
|
|
|
if (to >= hw->fixPipeNumber)
|
|
to = hw->fixPipeNumber - 1;
|
|
|
|
for (i = from; i <= to; i++) {
|
|
if (hw->Pipe[i].type == VIDEO)
|
|
cutVi++;
|
|
if (hw->Pipe[i].type == UI)
|
|
cutUIAlpha++;
|
|
hw->Pipe[i].type = NOTASSIGN;
|
|
hw->Pipe[i].planeAlpha = 1.0;
|
|
hw->Pipe[i].scaleH = 1.0;
|
|
hw->Pipe[i].scaleW = 1.0;
|
|
for (j = 0; j < hw->Pipe[i].layNum; j++) {
|
|
layer = hw->Pipe[i].hwcLayer[j];
|
|
hw->Pipe[i].hwcLayer[j] = NULL;
|
|
if (layer != NULL && !first) {
|
|
memCtrlDealLayer(layer, false);
|
|
resetLayer(layer);
|
|
}
|
|
}
|
|
if (!first)
|
|
memCtrlDelCur(hw->Pipe[i].curentMem);
|
|
hw->Pipe[i].layNum = 0;
|
|
hw->Pipe[i].curentMem = 0;
|
|
}
|
|
if (from == 0) {
|
|
hw->usedViPipe = 0;
|
|
hw->currentPipe = 0;
|
|
hw->usedPiexlAlpha = 0;
|
|
} else {
|
|
hw->usedViPipe -= cutVi;
|
|
hw->usedPiexlAlpha -= cutUIAlpha;
|
|
if (hw->Pipe[from-1].layNum < LAYER_BY_PIPE)
|
|
hw->currentPipe = from-1;
|
|
else
|
|
hw->currentPipe = from;
|
|
}
|
|
}
|
|
|
|
void resetLayerList(Display_t *display)
|
|
{
|
|
struct listnode *node;
|
|
Layer_t *layer;
|
|
int hastr = 0;
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
layer = node_to_item(node, Layer_t, node);
|
|
resetLayer(layer);
|
|
hastr |= layer->transform;
|
|
}
|
|
if(!hastr)
|
|
trResetErr();
|
|
}
|
|
|
|
static int calc_point_byPercent(const unsigned char percent,
|
|
const int middle_point, const int src_point)
|
|
{
|
|
int condition = (src_point > middle_point) ? 1 : 0;
|
|
int length = condition ? (src_point - middle_point) : (middle_point - src_point);
|
|
length = length * percent / 100;
|
|
return condition ? (middle_point + length) : (middle_point - length);
|
|
}
|
|
|
|
void recomputeDisplayFrame(int screenRadio, const hwc_rect_t sourceCrop,
|
|
const int unitedFrameWidth, const int unitedFrameHeight, hwc_rect_t *displayFrame)
|
|
{
|
|
switch(screenRadio) {
|
|
case SCREEN_AUTO: {
|
|
unsigned int ratio_width, ratio_height;
|
|
int frame_width = sourceCrop.right - sourceCrop.left;
|
|
int frame_height = sourceCrop.bottom - sourceCrop.top;
|
|
if(frame_width >= unitedFrameWidth || frame_height >= unitedFrameHeight) {
|
|
// scale down
|
|
if(frame_width > unitedFrameWidth) {
|
|
frame_height = frame_height * unitedFrameWidth / frame_width;
|
|
frame_width = unitedFrameWidth;
|
|
}
|
|
if(frame_height > unitedFrameHeight) {
|
|
frame_width = frame_width * unitedFrameHeight / frame_height;
|
|
frame_height = unitedFrameHeight;
|
|
}
|
|
} else {
|
|
// scale up
|
|
ratio_width = frame_width * unitedFrameHeight;
|
|
ratio_height = frame_height * unitedFrameWidth;
|
|
if(ratio_width >= ratio_height) {
|
|
// scale up until frame_width equal unitedFrameWidth
|
|
frame_height = ratio_height / frame_width;
|
|
frame_width = unitedFrameWidth;
|
|
} else {
|
|
// scale up until frame_height equal unitedFrameHeight
|
|
frame_width = ratio_width / frame_height;
|
|
frame_height = unitedFrameHeight;
|
|
}
|
|
}
|
|
//ALOGD("###frame[%d,%d], unitedFrame[%d,%d], displayFrame[%d,%d,%d,%d]",
|
|
// frame_width, frame_height, unitedFrameWidth, unitedFrameHeight,
|
|
// displayFrame->left, displayFrame->right, displayFrame->top, displayFrame->bottom);
|
|
|
|
if(unitedFrameWidth > frame_width) {
|
|
ratio_width = frame_width * (displayFrame->right - displayFrame->left)
|
|
/ unitedFrameWidth;
|
|
displayFrame->left += (displayFrame->right - displayFrame->left - ratio_width) >> 1;
|
|
displayFrame->right = displayFrame->left + ratio_width;
|
|
}
|
|
if(unitedFrameHeight > frame_height) {
|
|
ratio_height = frame_height * (displayFrame->bottom - displayFrame->top)
|
|
/ unitedFrameHeight;
|
|
displayFrame->top += (displayFrame->bottom - displayFrame->top - ratio_height) >> 1;
|
|
displayFrame->bottom = displayFrame->top + ratio_height;
|
|
}
|
|
}
|
|
break;
|
|
case SCREEN_FULL:
|
|
// here do nothing because the frame of cmcc is allready and always full.
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static bool resize_layer(Display_t *display, disp_layer_info2 *layer_info , Layer_t *layer)
|
|
{
|
|
hwc_rect_t sourceCrop;
|
|
hwc_rect_t displayFrame;
|
|
DisplayPrivate_t *hwdisplay;
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
DisplayConfig_t *dispconfig;
|
|
|
|
dispconfig = display->displayConfigList[display->activeConfigId];
|
|
hwdisplay = toHwDisplay(display);
|
|
hwconfig = toHwConfig(dispconfig);
|
|
|
|
#if 0
|
|
int VarDisplayWidth = hwconfig->screenDisplay.right - hwconfig->screenDisplay.left;
|
|
int VarDisplayHeight = hwconfig->screenDisplay.bottom - hwconfig->screenDisplay.top;
|
|
int InitDisplayWidth = dispconfig->width;
|
|
int InitDisplayHeight = dispconfig->height;
|
|
#endif
|
|
|
|
int VarDisplayWidth = display->VarDisplayWidth;
|
|
int VarDisplayHeight = display->VarDisplayHeight;
|
|
int InitDisplayWidth = dispconfig->width;
|
|
int InitDisplayHeight = dispconfig->height;
|
|
|
|
sourceCrop.left = layer->crop.left < 0 ? 0 : layer->crop.left;
|
|
sourceCrop.right = layer->crop.right < 0 ? 0 : layer->crop.right;
|
|
sourceCrop.top = layer->crop.top < 0 ? 0 : layer->crop.top;
|
|
sourceCrop.bottom = layer->crop.bottom < 0 ? 0 : layer->crop.bottom;
|
|
|
|
layer_info->fb.crop.x = (long long)(((long long)(sourceCrop.left)) << 32);
|
|
layer_info->fb.crop.width = (long long)(((long long)(sourceCrop.right)) << 32);
|
|
layer_info->fb.crop.width -= layer_info->fb.crop.x;
|
|
layer_info->fb.crop.y = (long long)(((long long)(sourceCrop.top)) << 32);
|
|
layer_info->fb.crop.height = (long long)(((long long)(sourceCrop.bottom)) << 32);
|
|
layer_info->fb.crop.height -= layer_info->fb.crop.y;
|
|
|
|
memcpy((void *)&displayFrame, (void *)&(layer->frame), sizeof(hwc_rect_t));
|
|
|
|
if(layerIsVideo(layer)) {
|
|
int unitedFrameWidth = InitDisplayWidth;
|
|
int unitedFrameHeight = InitDisplayHeight;
|
|
recomputeDisplayFrame(display->screenRadio, sourceCrop,
|
|
unitedFrameWidth, unitedFrameHeight, &displayFrame);
|
|
}
|
|
|
|
layer_info->screen_win.x =
|
|
calc_point_byPercent(display->hpercent, InitDisplayWidth >> 1, displayFrame.left)
|
|
* VarDisplayWidth / InitDisplayWidth;
|
|
layer_info->screen_win.width =
|
|
calc_point_byPercent(display->hpercent, InitDisplayWidth >> 1, displayFrame.right)
|
|
* VarDisplayWidth / InitDisplayWidth;
|
|
layer_info->screen_win.width -= layer_info->screen_win.x;
|
|
layer_info->screen_win.width = (0 == layer_info->screen_win.width) ? 1 : layer_info->screen_win.width;
|
|
layer_info->screen_win.y =
|
|
calc_point_byPercent(display->vpercent, InitDisplayHeight >> 1, displayFrame.top)
|
|
* VarDisplayHeight / InitDisplayHeight;
|
|
layer_info->screen_win.height =
|
|
calc_point_byPercent(display->vpercent, InitDisplayHeight >> 1, displayFrame.bottom)
|
|
* VarDisplayHeight / InitDisplayHeight;
|
|
layer_info->screen_win.height -= layer_info->screen_win.y;
|
|
layer_info->screen_win.height = (0 == layer_info->screen_win.height) ? 1 : layer_info->screen_win.height;
|
|
/*
|
|
ALOGD("screen[%d,%d,%d,%d]", layer_info->screen_win.x, layer_info->screen_win.y,
|
|
layer_info->screen_win.width, layer_info->screen_win.height);
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
static bool check_hw_dataspace_mode(Display_t *display, Layer_t *layer)
|
|
{
|
|
if ((NULL == layer) || (NULL == display) || (display->displayId != 0))
|
|
return 0;
|
|
|
|
int dataspace_mode = 0;
|
|
|
|
if (DISPLAY_OUTPUT_DATASPACE_MODE_AUTO == display->dataspace_mode) {
|
|
int transfer = layer->dataspace & HAL_DATASPACE_TRANSFER_MASK;
|
|
int standard = layer->dataspace & HAL_DATASPACE_STANDARD_MASK;
|
|
if ((HAL_DATASPACE_TRANSFER_ST2084 == transfer)
|
|
|| (HAL_DATASPACE_TRANSFER_HLG == transfer))
|
|
dataspace_mode = DISPLAY_OUTPUT_DATASPACE_MODE_HDR;
|
|
else
|
|
dataspace_mode = DISPLAY_OUTPUT_DATASPACE_MODE_SDR;
|
|
} else {
|
|
dataspace_mode = display->dataspace_mode;
|
|
}
|
|
|
|
return (dataspace_mode == DISPLAY_OUTPUT_DATASPACE_MODE_HDR) ? true : false;
|
|
}
|
|
|
|
void reCalPipeForHDR(Display_t *display)
|
|
{
|
|
struct listnode *node;
|
|
Layer_t *layer;
|
|
int isHDR = 0;
|
|
DESource_t *deHw = &DESource[display->displayId];
|
|
|
|
deHw->fixPipeNumber = (display->displayId == 0) ? 4 : 2;
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
layer = node_to_item(node, Layer_t, node);
|
|
isHDR |= check_hw_dataspace_mode(display, layer);
|
|
}
|
|
|
|
if (isHDR) {
|
|
#ifdef HOMLET_PLATFORM
|
|
homlet_dataspace_change_callback(isHDR);
|
|
#endif
|
|
deHw->fixPipeNumber = 2;
|
|
}
|
|
}
|
|
|
|
void resetDisplayConfig(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
DisplayConfig_t *dispconfig;
|
|
|
|
dispconfig = display->displayConfigList[display->activeConfigId];
|
|
hwdisplay = toHwDisplay(display);
|
|
hwconfig = toHwConfig(dispconfig);
|
|
|
|
hwconfig->screenDisplay.left = hwdisplay->ScreenCutOff.left;
|
|
hwconfig->screenDisplay.right = dispconfig->width - hwdisplay->ScreenCutOff.right;
|
|
hwconfig->screenDisplay.top = hwdisplay->ScreenCutOff.top;
|
|
hwconfig->screenDisplay.bottom = dispconfig->height - hwdisplay->ScreenCutOff.bottom;
|
|
}
|
|
|
|
void resetDisplay(Display_t *display)
|
|
{
|
|
|
|
resetDisplayConfig(display);
|
|
/* */
|
|
display->needclientTarget = 0;
|
|
|
|
|
|
}
|
|
|
|
void addClinetTarget(Display_t *display)
|
|
{
|
|
if(!display->needclientTarget) {
|
|
memCtrlDealFBLayer(display->clientTargetLayer, true);
|
|
}
|
|
display->needclientTarget = 1;
|
|
}
|
|
|
|
static bool checkSamePipeScale(PipeInfo_t *pipe, Layer_t *layer)
|
|
{
|
|
float wFactor = 1;
|
|
float hFactor = 1;
|
|
if (checkSoildLayer(layer))
|
|
return true;
|
|
calcLayerFactor(layer, &wFactor, &hFactor);
|
|
return checkFloatSame(wFactor, pipe->scaleW) && checkFloatSame(hFactor, pipe->scaleH);
|
|
}
|
|
|
|
bool inline checkSupportTransform(Display_t *display, Layer_t *layer)
|
|
{
|
|
private_handle_t *handle = NULL;
|
|
handle = (private_handle_t *)layer->buffer;
|
|
switch(layer->transform) {
|
|
case 0:
|
|
return true;
|
|
case HAL_TRANSFORM_ROT_90:
|
|
case HAL_TRANSFORM_ROT_180:
|
|
case HAL_TRANSFORM_ROT_270:
|
|
break;// tmp not support rotate.
|
|
default:
|
|
return false;
|
|
}
|
|
if (handle == NULL)
|
|
return false;
|
|
|
|
switch (handle->format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
case HAL_PIXEL_FORMAT_AW_NV12:
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
|
case HAL_PIXEL_FORMAT_BGRX_8888:
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return supportTR(display, layer);
|
|
}
|
|
|
|
static inline int checkSupportFormat(Layer_t *layer)
|
|
{
|
|
private_handle_t *handle = NULL;
|
|
|
|
handle = (private_handle_t *)layer->buffer;
|
|
if (handle == NULL)
|
|
return 0;
|
|
switch(handle->format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
|
case HAL_PIXEL_FORMAT_BGRX_8888:
|
|
case HAL_PIXEL_FORMAT_AW_NV12:
|
|
#if DE_VERSION == 30
|
|
case HAL_PIXEL_FORMAT_AW_YV12_10bit:
|
|
case HAL_PIXEL_FORMAT_AW_I420_10bit:
|
|
case HAL_PIXEL_FORMAT_AW_NV21_10bit:
|
|
case HAL_PIXEL_FORMAT_AW_NV12_10bit:
|
|
case HAL_PIXEL_FORMAT_AW_P010_UV:
|
|
case HAL_PIXEL_FORMAT_AW_P010_VU:
|
|
#endif
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline bool checkSupportBlendingFormate(Layer_t *layer)
|
|
{
|
|
private_handle_t *handle = NULL;
|
|
|
|
handle = (private_handle_t *)layer->buffer;
|
|
if (handle == NULL)
|
|
return 0;
|
|
|
|
switch(handle->format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
case HAL_PIXEL_FORMAT_BGRX_8888:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool checkLayerPipeCross(PipeInfo_t *pipe, Layer_t *layer)
|
|
{
|
|
int i = 0;
|
|
bool cross = 0;
|
|
|
|
for (i = 0; i < pipe->layNum; i++) {
|
|
if (pipe->hwcLayer[i] != NULL)
|
|
cross |= checkLayerCross(pipe->hwcLayer[i], layer);
|
|
if (cross)
|
|
break;
|
|
}
|
|
return cross;
|
|
}
|
|
|
|
bool checkLayerClientCross(struct listnode *layerSortedByZorder, Layer_t *layer)
|
|
{
|
|
struct listnode *node;
|
|
Layer_t *layer2;
|
|
bool cross = 0;
|
|
DELayerPrivate_t *deLayer;
|
|
|
|
list_for_each(node, layerSortedByZorder) {
|
|
layer2 = node_to_item(node, Layer_t, node);
|
|
if (layer2->zorder >= layer->zorder || cross)
|
|
break;
|
|
deLayer = toHwLayer(layer2);
|
|
if (deLayer->pipe == -1)
|
|
cross |= checkLayerCross(layer2, layer);
|
|
}
|
|
return cross;
|
|
}
|
|
|
|
bool checkSimpleSupport(Display_t *display, Layer_t *layer)
|
|
{
|
|
if(layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET)
|
|
return true;
|
|
if (display->colorTransformHint != 0) {
|
|
layer->duetoFlag = COLORT_HINT;
|
|
return false;
|
|
}
|
|
if (display->forceClient){
|
|
layer->duetoFlag = FORCE_GPU;
|
|
return false;
|
|
}
|
|
if (checkSkipLayer(layer)){
|
|
layer->duetoFlag = SKIP_FLAGS;
|
|
return false;
|
|
}
|
|
if (!checkSoildLayer(layer) && checkNullBuffer(layer)) {
|
|
layer->duetoFlag = NO_BUFFER;
|
|
return false;
|
|
}
|
|
if (checkSoildLayer(layer)){
|
|
return true;
|
|
}
|
|
if (!checkSupportFormat(layer)) {
|
|
layer->duetoFlag = FORMAT_MISS;
|
|
return false;
|
|
}
|
|
if (layerIsScale(display, layer) && !layerCanScale(deFreq, display, layer)) {
|
|
layer->duetoFlag = SCALE_OUT;
|
|
return false;
|
|
}
|
|
if (!checkSupportTransform(display, layer)) {
|
|
layer->duetoFlag = TRANSFROM_RT;
|
|
return false;
|
|
}
|
|
|
|
// for afbc
|
|
private_handle_t *handle = (private_handle_t *)layer->buffer;
|
|
if (handle && is_afbc_buf(handle)) {
|
|
if (hwc_ui_scaler_check(display, layer) == 0) {
|
|
layer->duetoFlag = SCALE_OUT;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!checkDealContiMem(layer)){
|
|
#ifdef USE_IOMMU
|
|
return true;
|
|
#else
|
|
layer->duetoFlag = NOCONTIG_MEM;
|
|
return false;
|
|
#endif
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
bool checkSameConfig(DisplayConfig_t *src, DisplayConfig_t *dst)
|
|
{
|
|
DisplayConfigPrivate_t *srchwconfig;
|
|
DisplayConfigPrivate_t *dsthwconfig;
|
|
srchwconfig = toHwConfig(src);
|
|
dsthwconfig = toHwConfig(dst);
|
|
|
|
if (src->width != dst->width)
|
|
return false;
|
|
if (src->height != dst->height)
|
|
return false;
|
|
if (srchwconfig->mode != dsthwconfig->mode)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static bool canAssignSpecialPipe(DESource_t *deHw, Layer_t *layer, PipeType_t type)
|
|
{
|
|
unusedpara(layer);
|
|
if (type == VIDEO && deHw->usedViPipe < deHw->fixVideoPipeNum) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void assignLayerComType(Display_t *display)
|
|
{
|
|
Layer_t *layer;
|
|
DELayerPrivate_t *deLayer;
|
|
struct listnode *node;
|
|
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
layer = node_to_item(node, Layer_t, node);
|
|
deLayer = toHwLayer(layer);
|
|
if (layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET)
|
|
continue;
|
|
if (deLayer->pipe == -1) {
|
|
if (layer->compositionType != HWC2_COMPOSITION_CLIENT)
|
|
layer->typeChange = 1;
|
|
layer->compositionType = HWC2_COMPOSITION_CLIENT;
|
|
} else {
|
|
if (layer->compositionType == HWC2_COMPOSITION_CLIENT
|
|
|| layer->compositionType == HWC2_COMPOSITION_CURSOR
|
|
|| layer->compositionType == HWC2_COMPOSITION_SIDEBAND) {
|
|
layer->typeChange = 1;
|
|
/* JetCui: cursor--> device but dim layer not */
|
|
layer->compositionType = HWC2_COMPOSITION_DEVICE;
|
|
}
|
|
}
|
|
if (deLayer->pipe == -1) {
|
|
trCachePut(layer);
|
|
layer->trcache = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void reAssignHwPipeZorder(DESource_t *hw)
|
|
{
|
|
int i = 0, j = 0, z = 0, zOrder = 0, uiBigen = 1, viBigen = 0, pipe = 0;
|
|
Layer_t *layer = NULL;
|
|
DELayerPrivate_t *hwlayer = NULL;
|
|
PipeInfo_t *hwPipe = NULL;
|
|
|
|
for (i = 0; i < hw->fixPipeNumber; i++) {
|
|
if (hw->Pipe[i].type == NOTASSIGN)
|
|
continue;
|
|
/* the z=0 chanel must no alpha */
|
|
|
|
hwPipe = &hw->Pipe[i];
|
|
if (hw->Pipe[i].type == UI) {
|
|
pipe = uiBigen++;
|
|
} else if (hw->Pipe[i].type == VIDEO) {
|
|
pipe = viBigen++;
|
|
} else {
|
|
if (hw->usedViPipe >= hw->fixVideoPipeNum) {
|
|
pipe = uiBigen++;
|
|
} else {
|
|
pipe = viBigen++;
|
|
hw->usedViPipe++;
|
|
}
|
|
}
|
|
|
|
for (j = 0, z = 0; j < LAYER_BY_PIPE; j++) {
|
|
layer = hwPipe->hwcLayer[j];
|
|
if (layer != NULL) {
|
|
hwlayer = toHwLayer(layer);
|
|
hwlayer->pipe = pipe;
|
|
hwlayer->layerId = z;
|
|
hwlayer->zOrder = zOrder;
|
|
hwlayer->pipeScaleW = hwPipe->scaleW;
|
|
hwlayer->pipeScaleH = hwPipe->scaleH;
|
|
zOrder++;
|
|
z++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int siwtchDevice(Display_t *display, int mode)
|
|
{
|
|
int ret = 0;
|
|
unsigned long arg[4] = {0};
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = DISP_OUTPUT_TYPE_HDMI;
|
|
arg[2] = mode;
|
|
ioctl(dispFd, DISP_DEVICE_SWITCH, (unsigned long)arg);
|
|
return 0;
|
|
}
|
|
|
|
void setPipeScale(PipeInfo_t *Pipe, Layer_t *layer)
|
|
{
|
|
float w, h, tmp;
|
|
if (checkSoildLayer(layer)) {
|
|
Pipe->scaleH = 1.0;
|
|
Pipe->scaleW = 1.0;
|
|
return;
|
|
}
|
|
w = layer->crop.right - layer->crop.left;
|
|
h = layer->crop.bottom - layer->crop.top;
|
|
if (layer->transform & HAL_TRANSFORM_ROT_90) {
|
|
tmp = w;
|
|
w = h;
|
|
h = tmp;
|
|
}
|
|
Pipe->scaleW = (layer->frame.right - layer->frame.left) / w;
|
|
Pipe->scaleH = (layer->frame.bottom - layer->frame.top) / w;
|
|
}
|
|
|
|
bool matchPipeAttribute(Display_t *display, int i, Layer_t *uplayer)
|
|
{
|
|
DisplayPrivate_t *hwDisplay = toHwDisplay(display);
|
|
DESource_t *deHw = &DESource[display->displayId];
|
|
PipeInfo_t *Pipe = &deHw->Pipe[i];
|
|
|
|
if (display->needclientTarget
|
|
&& uplayer->compositionType != HWC2_COMPOSITION_CLIENT_TARGET
|
|
&& i >= deHw->fixPipeNumber - 1)
|
|
goto not_match;
|
|
|
|
if (Pipe->layNum == 0) {
|
|
if (layerIsVideo(uplayer)){
|
|
if (deHw->usedViPipe >= deHw->fixVideoPipeNum)
|
|
goto not_match;
|
|
}
|
|
if (layerIsPixelBlended(uplayer))
|
|
if (deHw->usedPiexlAlpha >= deHw->fixPipeNumber - deHw->fixVideoPipeNum )
|
|
goto not_match;
|
|
return true;
|
|
}
|
|
if (Pipe->layNum >= LAYER_BY_PIPE)
|
|
goto not_match;
|
|
|
|
if (!checkFloatSame(uplayer->planeAlpha, Pipe->planeAlpha))
|
|
goto not_match;
|
|
|
|
if (!checkSamePipeScale(Pipe, uplayer)) {
|
|
goto not_match;
|
|
}
|
|
|
|
if (Pipe->type == VIDEO) {
|
|
if(!isSameForamt(Pipe->hwcLayer[0], uplayer))
|
|
goto not_match;
|
|
}
|
|
|
|
if (layerIsBlended(uplayer)) {
|
|
if (checkLayerPipeCross(Pipe, uplayer))
|
|
goto not_match;
|
|
}
|
|
|
|
if (uplayer->stream)
|
|
goto not_match;
|
|
|
|
return true;
|
|
not_match:
|
|
return false;
|
|
}
|
|
|
|
Layer_t *reCalPipeForVideoLayer(PipeInfo_t *Pipe, Layer_t *videoLayer)
|
|
{
|
|
Layer_t *layer;
|
|
|
|
if(checkLayerPipeCross(Pipe, videoLayer)) {
|
|
videoLayer->clearClientTarget = 1;
|
|
return videoLayer;
|
|
}
|
|
layer = node_to_item(Pipe->hwcLayer[0]->node.prev, Layer_t, node);
|
|
/* do not == list head, so can use layer */
|
|
return layer;
|
|
}
|
|
|
|
/*
|
|
* assignLayersToPipe() return the last assigned layer...
|
|
*/
|
|
Layer_t* assignLayersToPipe(Display_t *display, Layer_t *layer)
|
|
{
|
|
int i = 0, matchId = -1;
|
|
PipeInfo_t *matchPipe = NULL;
|
|
Layer_t *assignedlayer = layer;
|
|
int resetedPipe = -1, resetto = -1;
|
|
DELayerPrivate_t *deLayer = toHwLayer(layer);
|
|
DisplayPrivate_t *hwDisplay = toHwDisplay(display);
|
|
DESource_t *deHw = &DESource[display->displayId];
|
|
enum sunnxi_dueto_flags duetoFlag = HWC_LAYER;
|
|
|
|
/* memCtrl only reserve mem for video and FB */
|
|
if (layerIsBlended(layer)
|
|
&& layer->compositionType != HWC2_COMPOSITION_CLIENT_TARGET) {
|
|
|
|
if (checkLayerClientCross(&display->layerSortedByZorder, layer)) {
|
|
layer->duetoFlag = CROSS_FB;
|
|
goto assigned;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < deHw->fixPipeNumber; i++) {
|
|
if (matchPipe == NULL && matchPipeAttribute(display, i, layer)) {
|
|
matchPipe = &deHw->Pipe[i];
|
|
matchId = i;
|
|
if (matchPipe->layNum == 0) {
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
if (deHw->Pipe[i].layNum == 0) {
|
|
i--;
|
|
break;
|
|
}
|
|
if (checkLayerPipeCross(&deHw->Pipe[i], layer)) {
|
|
matchPipe = NULL;
|
|
matchId = -1;
|
|
}
|
|
}
|
|
|
|
if (matchPipe == NULL) {
|
|
if (layerIsVideo(layer)) {
|
|
if (canAssignSpecialPipe(deHw, layer, VIDEO)) {
|
|
resetto = resetedPipe = deHw->currentPipe;
|
|
if (deHw->currentPipe == deHw->fixPipeNumber - 1
|
|
|| display->needclientTarget) {
|
|
resetedPipe = deHw->fixPipeNumber - 2;
|
|
addClinetTarget(display);
|
|
}
|
|
/* video is reserve mem so it can pass the memctrl */
|
|
assignedlayer = reCalPipeForVideoLayer(&deHw->Pipe[resetedPipe], layer);
|
|
resetHwPipe(display, resetedPipe, resetto, false);
|
|
matchId = resetedPipe;
|
|
matchPipe = &deHw->Pipe[resetedPipe];
|
|
}else{
|
|
layer->duetoFlag = NO_V_PIPE;
|
|
addClinetTarget(display);
|
|
}
|
|
}else{
|
|
layer->duetoFlag = NO_U_PIPE;
|
|
addClinetTarget(display);
|
|
}
|
|
assign_FB:
|
|
if (layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET) {
|
|
layer->duetoFlag = HWC_LAYER;
|
|
resetedPipe = deHw->currentPipe;
|
|
assignedlayer = deHw->Pipe[resetedPipe].hwcLayer[0];
|
|
if(assignedlayer != NULL)
|
|
assignedlayer = node_to_item(assignedlayer->node.prev, Layer_t, node);
|
|
else
|
|
assignedlayer = node_to_item(layer->node.prev, Layer_t, node);
|
|
resetHwPipe(display, resetedPipe, resetedPipe, false);
|
|
if (deHw->currentPipe > 0) {
|
|
deHw->currentPipe--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (matchPipe) {
|
|
int addmem;
|
|
bool memok;
|
|
deLayer = toHwLayer(layer);
|
|
deLayer->pipe = matchId;
|
|
memok = memCtrlAddLayer(display, layer, &addmem);
|
|
|
|
if(layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET) {
|
|
|
|
if (!memok && layer->duetoFlag == NOT_ASSIGN) {
|
|
layer->duetoFlag = HWC_LAYER;
|
|
memCtrlDealFBLayer(layer, true);
|
|
matchPipe = NULL;
|
|
goto assign_FB;
|
|
}
|
|
layer->duetoFlag = HWC_LAYER;
|
|
}else{
|
|
if (!memok) {
|
|
deLayer->layerId = -1;
|
|
deLayer->pipe = -1;
|
|
deLayer->zOrder = -2;
|
|
layer->duetoFlag = MEM_CTRL;
|
|
addClinetTarget(display);
|
|
goto assigned;
|
|
}
|
|
if (checkLayerClientCross(&display->layerSortedByZorder, layer)) {
|
|
layer->clearClientTarget = 1;
|
|
}
|
|
}
|
|
if (layerIsVideo(layer)) {
|
|
matchPipe->type = VIDEO;
|
|
if (matchPipe->layNum == 0)
|
|
deHw->usedViPipe++;
|
|
}else if (layerIsPixelBlended(layer) && matchId != 0) {
|
|
if (matchPipe->layNum == 0)
|
|
deHw->usedPiexlAlpha++;
|
|
matchPipe->type = UI;
|
|
}else {
|
|
matchPipe->type = UI_NO_ALPHA;
|
|
}
|
|
if (matchPipe->layNum == 0) {
|
|
setPipeScale(matchPipe, layer);
|
|
}
|
|
matchPipe->curentMem += addmem;
|
|
matchPipe->hwcLayer[matchPipe->layNum++] = layer;
|
|
|
|
}
|
|
|
|
if (matchPipe && matchId >= deHw->currentPipe) {
|
|
deHw->currentPipe = matchId;
|
|
}
|
|
|
|
assigned:
|
|
memCtrlDealLayer(layer, true);
|
|
|
|
return_layer:
|
|
return assignedlayer;
|
|
}
|
|
|
|
static void TryToAssignLayer(Display_t *display)
|
|
{
|
|
struct listnode *node;
|
|
Layer_t *layer;
|
|
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
layer = node_to_item(node, Layer_t, node);
|
|
if (!display->needclientTarget
|
|
&& layer->compositionType == HWC2_COMPOSITION_CLIENT_TARGET)
|
|
continue;
|
|
|
|
if (!checkSimpleSupport(display, layer)) {
|
|
memCtrlDealLayer(layer, true);
|
|
addClinetTarget(display);
|
|
continue;
|
|
}
|
|
layer = assignLayersToPipe(display, layer);
|
|
node = &layer->node;
|
|
}
|
|
}
|
|
|
|
int32_t de2AssignLayer(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *hwDisplay = toHwDisplay(display);
|
|
DESource_t *deHw = &DESource[display->displayId];
|
|
|
|
resetDisplay(display);
|
|
resetLayerList(display);
|
|
resetHwPipe(display, 0, deHw->fixPipeNumber - 1, true);
|
|
memResetPerframe(display);
|
|
|
|
reCalPipeForHDR(display);
|
|
|
|
TryToAssignLayer(display);
|
|
|
|
memContrlComplet(display);
|
|
reAssignHwPipeZorder(deHw);
|
|
assignLayerComType(display);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void setup3dMode(Display_t *display, disp_layer_info2 *info)
|
|
{
|
|
if (display->displayId < 0) {
|
|
/* not support. */
|
|
return;
|
|
}
|
|
|
|
switch(hdmi_3D_mode) {
|
|
case DISPLAY_2D_LEFT:
|
|
info->b_trd_out = 0;
|
|
info->fb.flags = DISP_BF_STEREO_SSH;
|
|
break;
|
|
case DISPLAY_2D_TOP:
|
|
info->b_trd_out = 0;
|
|
info->fb.flags = DISP_BF_STEREO_TB;
|
|
break;
|
|
case DISPLAY_3D_LEFT_RIGHT_HDMI:
|
|
info->b_trd_out = 1;
|
|
info->out_trd_mode = DISP_3D_OUT_MODE_FP;
|
|
info->fb.flags = DISP_BF_STEREO_SSH;
|
|
info->screen_win.x = 0;
|
|
info->screen_win.y = 0;
|
|
info->screen_win.width = 1920;
|
|
info->screen_win.height = 1080;
|
|
break;
|
|
case DISPLAY_3D_TOP_BOTTOM_HDMI:
|
|
info->b_trd_out = 1;
|
|
info->out_trd_mode = DISP_3D_OUT_MODE_FP;
|
|
info->fb.flags = DISP_BF_STEREO_TB;
|
|
info->screen_win.x = 0;
|
|
info->screen_win.y = 0;
|
|
info->screen_win.width = 1920;
|
|
info->screen_win.height = 1080;
|
|
break;
|
|
case DISPLAY_3D_DUAL_STREAM:
|
|
info->b_trd_out = 1;
|
|
info->out_trd_mode = DISP_3D_OUT_MODE_FP;
|
|
info->fb.flags = DISP_BF_STEREO_FP;
|
|
info->screen_win.x = 0;
|
|
info->screen_win.y = 0;
|
|
info->screen_win.width = 1920;
|
|
info->screen_win.height = 1080;
|
|
break;
|
|
case DISPLAY_2D_DUAL_STREAM:
|
|
default :
|
|
info->b_trd_out = 0;
|
|
info->fb.flags = DISP_BF_NORMAL;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
int setupSolidColorLayer(Layer_t *layer, disp_layer_config2 *layerConfig)
|
|
{
|
|
disp_layer_info2 *info = &layerConfig->info;
|
|
DELayerPrivate_t *hwlayer = toHwLayer(layer);
|
|
|
|
info->color = layer->color.a<<24
|
|
| layer->color.r<<16
|
|
| layer->color.g<<8
|
|
| layer->color.b;
|
|
info->mode = LAYER_MODE_COLOR;
|
|
info->fb.format = DISP_FORMAT_ARGB_8888;
|
|
info->screen_win.x = layer->frame.left < 0 ? 0 : layer->frame.left;
|
|
info->screen_win.y = layer->frame.top < 0 ? 0 : layer->frame.top;
|
|
info->screen_win.width = layer->frame.right - layer->frame.left;
|
|
info->screen_win.height = layer->frame.bottom - layer->frame.top;
|
|
info->fb.size[0].height = info->screen_win.height;
|
|
info->fb.size[0].width = info->screen_win.width;
|
|
info->fb.crop.x = ((long long)(info->screen_win.x) << 32);
|
|
info->fb.crop.y = ((long long)(info->screen_win.y) << 32);
|
|
info->fb.crop.width = ((long long)(info->screen_win.width / hwlayer->pipeScaleW) << 32);
|
|
info->fb.crop.height = ((long long)(info->screen_win.height / hwlayer->pipeScaleH) << 32);
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int setup_sunxi_metadata(Layer_t *layer, disp_layer_info2 *layer_info)
|
|
{
|
|
#if (GRALLOC_SUNXI_METADATA_BUF & (DE_VERSION == 30))
|
|
private_handle_t *handle = (private_handle_t *)layer->buffer;
|
|
|
|
/* Update handle->flags from metadata buffer */
|
|
handle->ion_metadata_flag &= ionGetMetadataFlag(layer->buffer);
|
|
|
|
layer_info->fb.metadata_flag = handle->ion_metadata_flag;
|
|
layer_info->fb.metadata_size = handle->ion_metadata_size;
|
|
layer_info->fb.metadata_fd = handle->metadata_fd;
|
|
if (is_afbc_buf(handle))
|
|
layer_info->fb.fbd_en = 1;
|
|
#if 0
|
|
ALOGD("fbd_en=%d, metadata_flag=0x%x, metadata_size=%d, metadata__buf[0x%llx, %x]",
|
|
layer_info->fb.fbd_en,
|
|
layer_info->fb.metadata_flag,
|
|
layer_info->fb.metadata_size,
|
|
layer_info->fb.metadata_buf,
|
|
get_ion_address(handle->metadata_fd));
|
|
#endif
|
|
#else
|
|
layer, layer_info;
|
|
#endif /* GRALLOC_SUNXI_METADATA_BUF */
|
|
return 0;
|
|
}
|
|
|
|
static int setup_layer_dataspace(
|
|
disp_layer_info2 *layer_info, int32_t dataspace)
|
|
{
|
|
#if (DE_VERSION == 30)
|
|
unsigned int transfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK)
|
|
>> HAL_DATASPACE_TRANSFER_SHIFT;
|
|
unsigned int standard = (dataspace & HAL_DATASPACE_STANDARD_MASK)
|
|
>> HAL_DATASPACE_STANDARD_SHIFT;
|
|
unsigned int range = (HAL_DATASPACE_RANGE_FULL
|
|
!= (dataspace & HAL_DATASPACE_RANGE_MASK)) ? 0 : 1; /* 0: limit. 1: full */
|
|
|
|
/* color space table [standard][range] */
|
|
const disp_color_space cs_table[][2] = {
|
|
{DISP_UNDEF, DISP_UNDEF_F},
|
|
{DISP_BT709, DISP_BT709_F},
|
|
{DISP_BT470BG, DISP_BT470BG_F},
|
|
{DISP_BT470BG, DISP_BT470BG_F},
|
|
{DISP_BT601, DISP_BT601_F},
|
|
{DISP_BT601, DISP_BT601_F},
|
|
{DISP_BT2020NC, DISP_BT2020NC_F},
|
|
{DISP_BT2020C, DISP_BT2020C_F},
|
|
{DISP_FCC, DISP_FCC_F},
|
|
{DISP_BT709, DISP_BT709_F},
|
|
{DISP_BT709, DISP_BT709_F},
|
|
{DISP_BT709, DISP_BT709_F},
|
|
};
|
|
if ((range < sizeof(cs_table[0]) / sizeof(cs_table[0][0]))
|
|
&& (standard < sizeof(cs_table) / sizeof(cs_table[0]))) {
|
|
layer_info->fb.color_space = cs_table[standard][range];
|
|
} else {
|
|
ALOGD("unknown dataspace standard(0x%x) range(0x%x)", standard, range);
|
|
layer_info->fb.color_space = range ? DISP_UNDEF_F : DISP_UNDEF;
|
|
}
|
|
|
|
const disp_eotf eotf_table[] = {
|
|
DISP_EOTF_UNDEF,
|
|
DISP_EOTF_LINEAR,
|
|
DISP_EOTF_IEC61966_2_1,
|
|
DISP_EOTF_BT601,
|
|
DISP_EOTF_GAMMA22,
|
|
DISP_EOTF_GAMMA28, /* HAL_DATASPACE_TRANSFER_GAMMA2_6 */
|
|
DISP_EOTF_GAMMA28,
|
|
DISP_EOTF_SMPTE2084,
|
|
DISP_EOTF_ARIB_STD_B67
|
|
};
|
|
if (transfer < sizeof(eotf_table) / sizeof(eotf_table[0])) {
|
|
layer_info->fb.eotf = eotf_table[transfer];
|
|
} else {
|
|
ALOGD("unknown dataspace Transfer(0x%x)", transfer);
|
|
layer_info->fb.eotf = DISP_EOTF_UNDEF;
|
|
}
|
|
/* ALOGD("layer_info_fb: eotf=%d, cs=%d",
|
|
layer_info->fb.eotf, layer_info->fb.color_space);
|
|
*/
|
|
#else
|
|
layer_info, dataspace;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int setupDisplayInfo(Display_t *display, Layer_t *layer, disp_layer_config2 *layerConfig, int zorder)
|
|
{
|
|
int i = 0;
|
|
private_handle_t *handle;
|
|
int swap, s_left, s_right, s_top, s_bottom;
|
|
int src_stride_w, src_stride_h,dst_stride_w, dst_stride_h;//all is pixel unit
|
|
int bpp0 = 4;
|
|
disp_layer_info2 *info = &layerConfig->info;
|
|
DisplayPrivate_t *hwdisplay;
|
|
unsigned long arg[4] = {0};
|
|
|
|
memset(info, 0, sizeof(disp_layer_info2));
|
|
|
|
info->zorder = zorder;
|
|
info->alpha_value = (int)ceilf(255 * layer->planeAlpha);
|
|
|
|
if (layerIsBlended(layer)) {
|
|
info->alpha_mode = 2;
|
|
} else {
|
|
info->alpha_mode = 1;
|
|
}
|
|
if (layerIsPremult(layer)) {
|
|
info->fb.pre_multiply = 1;
|
|
}
|
|
if (layerConfig->channel == 0) {
|
|
info->fb.pre_multiply = 0;
|
|
info->alpha_mode = 1;
|
|
}
|
|
|
|
if(layer->buffer == NULL) {
|
|
setupSolidColorLayer(layer, layerConfig);
|
|
return 0;
|
|
}
|
|
|
|
handle = (private_handle_t *)layer->buffer;
|
|
if (!handle) {
|
|
ALOGE("buffer handle is NULL , type is %d ", layer->compositionType);
|
|
return -1;
|
|
}
|
|
|
|
info->mode = LAYER_MODE_BUFFER;
|
|
info->fb.fd = handle->share_fd;
|
|
if (info->fb.fd < 0) {
|
|
ALOGE("%s: LINE:%d fb.fd err.", __func__, __LINE__);
|
|
goto err;
|
|
}
|
|
/* display now use ucnt = bpp so is piexl x bpp byte align
|
|
* pitch[1] = DISPALIGN(size[1] * ucnt, align[1]);
|
|
* means:
|
|
* DISPALIGN( info->fb.size[i].width *bpp,info->fb.align[i])
|
|
*/
|
|
switch(handle->format) {
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
bpp0 = 1;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
|
case HAL_PIXEL_FORMAT_AW_NV12:
|
|
bpp0 = 1;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
bpp0 = 3;
|
|
default:
|
|
ALOGV("RGB");
|
|
}
|
|
dst_stride_w = src_stride_w = handle->stride;
|
|
dst_stride_h = src_stride_h = handle->height;
|
|
/* HAL_TRANSFORM_ROT_180 = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H
|
|
* HAL_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_180 | HAL_TRANSFORM_ROT_90
|
|
*/
|
|
s_left = layer->crop.left;
|
|
s_top = layer->crop.top;
|
|
s_right = layer->crop.right;
|
|
s_bottom = layer->crop.bottom;
|
|
/*when rotate beginning must stride is pixel allign */
|
|
if (layer->transform != 0) {
|
|
dst_stride_w = HWC_ALIGN(handle->stride* bpp0, handle->aw_byte_align[0]) / bpp0;
|
|
dst_stride_h = HWC_ALIGN(handle->height* bpp0, handle->aw_byte_align[0]) / bpp0;
|
|
}
|
|
|
|
if((layer->transform & HAL_TRANSFORM_FLIP_V) == HAL_TRANSFORM_FLIP_V) {
|
|
s_top = (src_stride_h - layer->crop.bottom)>0 ? (src_stride_h - layer->crop.bottom) : 0;
|
|
s_bottom = (src_stride_h - layer->crop.top)>0 ? (src_stride_h - layer->crop.top) : src_stride_h;
|
|
}
|
|
|
|
if((layer->transform & HAL_TRANSFORM_FLIP_H) == HAL_TRANSFORM_FLIP_H) {
|
|
s_right = (src_stride_w - layer->crop.left)>0 ? (src_stride_w - layer->crop.left) : src_stride_w;
|
|
s_left = (src_stride_w - layer->crop.right)>0 ? (src_stride_w - layer->crop.right) : 0;
|
|
}
|
|
|
|
if((layer->transform & HAL_TRANSFORM_ROT_90) == HAL_TRANSFORM_ROT_90) {
|
|
swap = s_left;
|
|
s_left = (src_stride_h - s_bottom)>0 ? (src_stride_h - s_bottom) : 0;
|
|
s_bottom = s_right;
|
|
s_right = (src_stride_h - s_top)>0 ? (src_stride_h - s_top) : src_stride_h;
|
|
s_top = swap;
|
|
swap = dst_stride_w;
|
|
dst_stride_w = dst_stride_h;
|
|
dst_stride_h = swap;
|
|
}
|
|
|
|
layer->crop.left = s_left;
|
|
layer->crop.top = s_top;
|
|
layer->crop.right = s_right;
|
|
layer->crop.bottom = s_bottom;
|
|
|
|
info->fb.crop.x = ((long long)(s_left) << 32);
|
|
info->fb.crop.y = ((long long)(s_top) << 32);
|
|
info->fb.crop.width = ((long long)(s_right - s_left) << 32);
|
|
info->fb.crop.height = ((long long)(s_bottom - s_top) << 32);
|
|
|
|
info->screen_win.x = layer->frame.left < 0 ? 0 : layer->frame.left;
|
|
info->screen_win.y = layer->frame.top < 0 ? 0 : layer->frame.top;
|
|
info->screen_win.width = layer->frame.right - layer->frame.left;
|
|
info->screen_win.height = layer->frame.bottom - layer->frame.top;
|
|
|
|
resize_layer(display, info , layer);
|
|
|
|
info->fb.size[0].width = dst_stride_w;
|
|
info->fb.size[1].width = dst_stride_w / 2;
|
|
info->fb.size[2].width = dst_stride_w / 2;
|
|
info->fb.size[0].height = dst_stride_h;
|
|
info->fb.size[1].height = dst_stride_h / 2;
|
|
info->fb.size[2].height = dst_stride_h / 2;
|
|
info->fb.align[0] = handle->aw_byte_align[0];
|
|
info->fb.align[1] = handle->aw_byte_align[1];
|
|
info->fb.align[2] = handle->aw_byte_align[2];
|
|
switch(handle->format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
info->fb.format = DISP_FORMAT_ABGR_8888;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
info->fb.format = DISP_FORMAT_XBGR_8888;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
info->fb.format = DISP_FORMAT_ARGB_8888;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_BGRX_8888:
|
|
info->fb.format = DISP_FORMAT_XRGB_8888;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
info->fb.format = DISP_FORMAT_BGR_888;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
info->fb.format = DISP_FORMAT_RGB_565;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
info->fb.format = DISP_FORMAT_YUV420_P;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_VUVU;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_AW_NV12:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_UVUV;
|
|
break;
|
|
#if (DE_VERSION == 30)
|
|
case HAL_PIXEL_FORMAT_AW_YV12_10bit:
|
|
case HAL_PIXEL_FORMAT_AW_I420_10bit:
|
|
info->fb.format = DISP_FORMAT_YUV420_P;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_AW_NV21_10bit:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_VUVU;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_AW_NV12_10bit:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_UVUV;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_AW_P010_UV:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_UVUV_10BIT;
|
|
break;
|
|
case HAL_PIXEL_FORMAT_AW_P010_VU:
|
|
info->fb.format = DISP_FORMAT_YUV420_SP_VUVU_10BIT;
|
|
break;
|
|
#endif
|
|
default:
|
|
ALOGE("DO not support format 0x%x in %s", handle->format, __FUNCTION__);
|
|
goto err;
|
|
}
|
|
|
|
if (layerIsVideo(layer))
|
|
setup_sunxi_metadata(layer, info);
|
|
setup_layer_dataspace(info, layer->dataspace);
|
|
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
if(hwdisplay->type.mode == DISP_TV_MOD_1080P_24HZ_3D_FP) {
|
|
if (layerIsVideo(layer)) {
|
|
setup3dMode(display, info);
|
|
} else {
|
|
info->b_trd_out = 0;
|
|
info->fb.flags = DISP_BF_STEREO_2D_DEPTH;
|
|
info->fb.depth = 3;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
return -1;
|
|
}
|
|
|
|
int de2memCtrlAddLayer(Display_t *display, Layer_t *layer)
|
|
{
|
|
DESource_t *hw;
|
|
DELayerPrivate_t *hwlayer;
|
|
int i = 0;
|
|
PipeInfo_t *pipe;
|
|
hwc_rect_t rectx,rectx2,rectx3;
|
|
float withS, hightS;
|
|
float addmem;
|
|
rectx = {0,0,0,0};
|
|
rectx2 = rectx;
|
|
rectx3 = rectx;
|
|
|
|
hwlayer = toHwLayer(layer);
|
|
hw = &DESource[display->displayId];
|
|
pipe = &hw->Pipe[hwlayer->pipe];
|
|
if (layer->transform & HAL_TRANSFORM_ROT_90) {
|
|
withS = (layer->crop.top - layer->crop.bottom)/(layer->frame.right - layer->frame.left);
|
|
hightS = (layer->crop.right- layer->crop.left)/(layer->frame.top - layer->frame.bottom);
|
|
}else{
|
|
withS = (layer->crop.right - layer->crop.left)/(layer->frame.right - layer->frame.left);
|
|
hightS = (layer->crop.bottom - layer->crop.top)/(layer->frame.top - layer->frame.bottom);
|
|
}
|
|
addmem = ((layer->crop.right - layer->crop.left)
|
|
*(layer->crop.bottom - layer->crop.top)
|
|
* getBitsPerPixel(layer) / 8);
|
|
if (pipe->layNum == 0)
|
|
return (int)ceilf(addmem);
|
|
|
|
for (i = 0; i < pipe->layNum; i++) {
|
|
rectx2 = rectx;
|
|
if (regionCrossed(&layer->frame, &pipe->hwcLayer[i]->frame, &rectx))
|
|
addmem -= withS * (rectx.right - rectx.left) + hightS * (rectx.bottom - rectx.top);
|
|
if (regionCrossed(&rectx2, &rectx, &rectx2))
|
|
addmem += withS * (rectx2.right - rectx2.left) + hightS * (rectx2.bottom - rectx2.top);
|
|
rectx3 = rectx2;
|
|
if (i >= 2 && regionCrossed(&rectx3, &rectx, &rectx3))
|
|
addmem += withS * (rectx3.right - rectx3.left) + hightS * (rectx3.bottom - rectx3.top);
|
|
}
|
|
|
|
return (int)ceilf(addmem);
|
|
}
|
|
|
|
int de2SetupLayer(Display_t *display, LayerSubmit_t *submitLayer)
|
|
{
|
|
struct listnode *node;
|
|
DESource_t *hw;
|
|
Layer_t *layer;
|
|
disp_layer_config2 *layerConfig;
|
|
DELayerPrivate_t *hwlayer;
|
|
int i = 0;
|
|
int chn = display->displayId ? 2 : 4;
|
|
|
|
hw = &DESource[display->displayId];
|
|
layerConfig = hw->layerInfo;
|
|
for (i = 0; i < chn * 4; i++) {
|
|
layerConfig[i].enable = 0;
|
|
}
|
|
|
|
list_for_each(node, &submitLayer->layerNode) {
|
|
layer = node_to_item(node, Layer_t, node);
|
|
hwlayer = toHwLayer(layer);
|
|
layerConfig[hwlayer->pipe * 4 + hwlayer->layerId].enable = 1;
|
|
setupDisplayInfo(display, layer,
|
|
&layerConfig[hwlayer->pipe * 4 + hwlayer->layerId], hwlayer->zOrder);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int diplayToScreen(int disp, disp_layer_config2 *config, int num, unsigned int synccount)
|
|
{
|
|
int ret;
|
|
unsigned long arg[4] = {0};
|
|
|
|
arg[0] = disp;
|
|
arg[1] = 1;
|
|
ret = ioctl(dispFd, DISP_SHADOW_PROTECT, (unsigned long)arg);
|
|
if (ret) {
|
|
ALOGE("%d err: DISP_SHADOW_PROTECT failed", __LINE__);
|
|
goto err;
|
|
}
|
|
|
|
arg[0] = disp;
|
|
arg[1] = (unsigned long)(config);
|
|
arg[2] = num;
|
|
|
|
ret = ioctl(dispFd, DISP_LAYER_SET_CONFIG2, (unsigned long)arg);
|
|
if (ret) {
|
|
ALOGE("DISP_LAYER_SET_CONFIG failed !");
|
|
}
|
|
|
|
arg[0] = disp;
|
|
arg[1] = HWC_SUBMIT_FENCE;
|
|
arg[2] = synccount;
|
|
arg[3] = 0;
|
|
ret = ioctl(dispFd, DISP_HWC_COMMIT, (unsigned long)arg);
|
|
if (ret) {
|
|
ALOGE("fence commit err.");
|
|
}
|
|
|
|
arg[0] = disp;
|
|
arg[1] = 0;
|
|
ret = ioctl(dispFd, DISP_SHADOW_PROTECT, (unsigned long)arg);
|
|
if (ret) {
|
|
ALOGE("%d err: DISP_SHADOW_PROTECT failed", __LINE__);
|
|
goto err;
|
|
}
|
|
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
static int de2commitToDisplay(Display_t *display, LayerSubmit_t *submitLayer)
|
|
{
|
|
|
|
DisplayPrivate_t* hwdisplay;
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
DESource_t *hw;
|
|
disp_layer_config2 *layerConfig;
|
|
int pipe = display->displayId ? 2 : 4;
|
|
|
|
hwdisplay = toHwDisplay(display);
|
|
hw = &DESource[display->displayId];
|
|
layerConfig = hw->layerInfo;
|
|
|
|
if (!checkSameConfig(&hw->currentConfig, submitLayer->currentConfig)) {
|
|
hwconfig = toHwConfig(submitLayer->currentConfig);
|
|
if (hwconfig) {
|
|
/* TODO:Switch the mode for hdmi and other */
|
|
}
|
|
}
|
|
|
|
return diplayToScreen(display->displayId, layerConfig, pipe * 4, submitLayer->sync.count);
|
|
|
|
}
|
|
|
|
static int de2DelayDeal(Display_t *display, LayerSubmit_t *submitLayer)
|
|
{
|
|
unusedpara(display);
|
|
unusedpara(submitLayer);
|
|
return 0;
|
|
}
|
|
|
|
void showlayers(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
DELayerPrivate_t *hwlayer;
|
|
struct listnode *node;
|
|
Layer_t *lay;
|
|
private_handle_t *handle;
|
|
|
|
char mem[100];
|
|
memCtrlDump(mem);
|
|
|
|
ALOGI("dispy%d cur:%d-%d-%d mem:%s\n", display->displayId, display->frameCount,
|
|
display->commitThread->diplayCount, display->commitThread->SubmitCount,mem);
|
|
|
|
ALOGI(" layer | handle | format | color |"
|
|
"bl|space|TR|pAlp| crop "
|
|
"| frame |zOrder|hz|ch|id|duto\n"
|
|
"--------------------------------------------------------------------------"
|
|
"--------------------------------------------------------------------------\n");
|
|
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
lay = node_to_item(node, Layer_t, node);
|
|
if (lay->compositionType == HWC2_COMPOSITION_CLIENT_TARGET
|
|
&& !display->needclientTarget)
|
|
continue;
|
|
handle = (private_handle_t *)lay->buffer;
|
|
hwlayer = toHwLayer(lay);
|
|
ALOGI("%16p|%16p|%10d|%08x|%2d|%5d|%2d|%4.2f|[%6.1f,%6.1f,%6.1f,%6.1f]"
|
|
"|[%4d,%4d,%4d,%4d]|%6d|%2d|%2d|%2d|%s", lay,
|
|
lay->buffer, handle != NULL ? handle->format : 0,
|
|
(((unsigned int)lay->color.a<<24)|(unsigned int)(lay->color.r<<16)
|
|
|(unsigned int)(lay->color.g<<8)|(unsigned int)(lay->color.b)),
|
|
lay->blendMode, lay->dataspace, lay->transform, lay->planeAlpha,
|
|
lay->crop.left, lay->crop.top, lay->crop.right, lay->crop.bottom,
|
|
lay->frame.left, lay->frame.top, lay->frame.right, lay->frame.bottom,
|
|
lay->zorder, hwlayer->zOrder, hwlayer->pipe, hwlayer->layerId,
|
|
hwcPrintInfo(lay->duetoFlag));
|
|
}
|
|
hwc_mem_dump(NULL);
|
|
|
|
ALOGI("--------------------------------------------------------------------------"
|
|
"--------------------------------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
void de2Dump(Display_t *display, uint32_t* outSize, char* outBuffer, uint32_t max)
|
|
{
|
|
uint32_t count = *outSize;
|
|
DisplayPrivate_t *hwdisplay;
|
|
DELayerPrivate_t *hwlayer;
|
|
struct listnode *node;
|
|
Layer_t *lay;
|
|
private_handle_t *handle;
|
|
hwdisplay = toHwDisplay(display);
|
|
DESource_t *hw = &DESource[display->displayId];
|
|
if (outBuffer == NULL) {
|
|
*outSize += (display->nubmerLayer + display->needclientTarget + 3) * max;
|
|
return;
|
|
}
|
|
if(!display->plugIn) {
|
|
return;
|
|
}
|
|
|
|
list_for_each(node, &display->layerSortedByZorder) {
|
|
lay = node_to_item(node, Layer_t, node);
|
|
if (count > (max - 200)) {
|
|
count += sprintf(outBuffer + count, "++++++++++++++++++not end+++++++++++++++++++\n");
|
|
break;
|
|
}
|
|
if (lay->compositionType == HWC2_COMPOSITION_CLIENT_TARGET
|
|
&& !display->needclientTarget)
|
|
continue;
|
|
handle = (private_handle_t *)lay->buffer;
|
|
hwlayer = toHwLayer(lay);
|
|
count += sprintf(outBuffer + count, "%16p|", lay);
|
|
count += sprintf(outBuffer + count, "%16p|", lay->buffer);
|
|
count += sprintf(outBuffer + count, "%10d|", handle != NULL ? handle->format : 0);
|
|
count += sprintf(outBuffer + count, "%2d|", lay->blendMode);
|
|
count += sprintf(outBuffer + count, "%5d|", lay->dataspace);
|
|
count += sprintf(outBuffer + count, "%2d|", lay->transform);
|
|
count += sprintf(outBuffer + count, "%4.2f|", lay->planeAlpha);
|
|
if(handle != NULL)
|
|
count += sprintf(outBuffer + count, "[%6.1f,%6.1f,%6.1f,%6.1f]|", lay->crop.left,
|
|
lay->crop.top, lay->crop.right, lay->crop.bottom);
|
|
else
|
|
count += sprintf(outBuffer + count, "[%06x,%06x,%06x,%06x]|", lay->color.a,
|
|
lay->color.r, lay->color.g, lay->color.b);
|
|
count += sprintf(outBuffer + count, "[%4d,%4d,%4d,%4d]|", lay->frame.left,
|
|
lay->frame.top, lay->frame.right, lay->frame.bottom);
|
|
count += sprintf(outBuffer + count, "%6d|", lay->zorder);
|
|
count += sprintf(outBuffer + count, "%2d|", hwlayer->zOrder);
|
|
count += sprintf(outBuffer + count, "%2d|", hwlayer->pipe);
|
|
count += sprintf(outBuffer + count, "%2d|", hwlayer->layerId);
|
|
count += sprintf(outBuffer + count, "%s\n", hwcPrintInfo(lay->duetoFlag));
|
|
}
|
|
count += sprintf(outBuffer + count, "disp:%d cur:%d-%d ker:%d\n"
|
|
"--------------------------------------------------------------------------"
|
|
"--------------------------------------------------------------------------\n",
|
|
display->displayId, display->frameCount,display->commitThread->diplayCount, display->commitThread->SubmitCount);
|
|
count += memCtrlDump(outBuffer + count);
|
|
count += hwc_mem_dump(outBuffer + count);
|
|
*outSize = count;
|
|
}
|
|
|
|
int32_t de2PresentDisplay(Display_t *display, struct sync_info *sync, int *layerSize)
|
|
{
|
|
DisplayPrivate_t* hwdisplay;
|
|
DESource_t *hw;
|
|
unsigned long arg[4] = {0};
|
|
char* outBuffer = NULL;
|
|
uint32_t outSize = 0;
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = HWC_ACQUIRE_FENCE;
|
|
arg[2] = (unsigned long)sync;
|
|
arg[3] = 0;
|
|
if (ioctl(dispFd, DISP_HWC_COMMIT, (unsigned long)arg)) {
|
|
ALOGE("hwc get realease fence err!");
|
|
return -ENODEV;
|
|
}
|
|
*layerSize = sizeof(DELayerPrivate_t);
|
|
if (showLayers())
|
|
showlayers(display);
|
|
return 0;
|
|
}
|
|
|
|
static int setActiveConfig(Display_t *display, DisplayConfig_t *config)
|
|
{
|
|
unsigned long arg[4] = {0};
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
DisplayPrivate_t *hwdisplay;
|
|
hwconfig = toHwConfig(config);
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = hwdisplay->type.type;
|
|
arg[2] = hwconfig->mode;
|
|
hwdisplay->type.mode = hwconfig->mode;
|
|
|
|
ALOGD("%s:display:%d type: %d. mode: %d",
|
|
__FUNCTION__, display->displayId, hwdisplay->type.type, hwconfig->mode);
|
|
if (hwdisplay->type.type == DISP_OUTPUT_TYPE_LCD)
|
|
return 0;
|
|
|
|
#ifndef HOMLET_PLATFORM
|
|
if (ioctl(dispFd, DISP_DEVICE_SWITCH, (unsigned long)arg) == -1) {
|
|
ALOGE("switch device failed!\n");
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int switchDisplay(Display_t *display, int type, int mode)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
int i;
|
|
if (type != (int)hwdisplay->type.type)
|
|
/* if chang for cvbs etc ,will add code */
|
|
return -1;
|
|
|
|
for (i = 0; i < display->configNumber; i++) {
|
|
hwconfig = toHwConfig(display->displayConfigList[i]);
|
|
if (display->displayConfigList[i]
|
|
&& hwconfig->mode == mode)
|
|
break;
|
|
else
|
|
hwconfig = NULL;
|
|
}
|
|
if (hwconfig== NULL) {
|
|
ALOGE("%s:hwconfig is NULL", __func__);
|
|
return -1;
|
|
}
|
|
display->activeConfigId = i;
|
|
return setActiveConfig(display, display->displayConfigList[i]);
|
|
}
|
|
|
|
Layer_t* de2creatLayer(Display_t* display)
|
|
{
|
|
Layer_t *layer;
|
|
DELayerPrivate_t *deLayer;
|
|
unusedpara(display);
|
|
|
|
layer= layerCacheGet(sizeof(DELayerPrivate_t));
|
|
if (layer== NULL) {
|
|
ALOGE("creat layer err...");
|
|
return NULL;
|
|
}
|
|
deLayer = toHwLayer(layer);
|
|
deLayer->pipe = -1;
|
|
deLayer->layerId = -1;
|
|
deLayer->zOrder = -1;
|
|
return layer;
|
|
}
|
|
|
|
int initPermanentDisplay(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
int refreshRate, xdpi, ydpi, vsync_period;
|
|
int fbfd = -1;
|
|
DisplayConfig_t *config;
|
|
struct fb_var_screeninfo info;
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
fbfd = open("/dev/graphics/fb0", O_RDWR);
|
|
if (fbfd < 0) {
|
|
ALOGE( "Failed to open fb0 device, ret:%d, errno:%d\n", fbfd, errno);
|
|
return -1;
|
|
}
|
|
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &info) == -1) {
|
|
ALOGE("FBIOGET_VSCREENINFO ioctl failed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
config = (DisplayConfig_t*)hwc_malloc(sizeof(DisplayConfig_t) + sizeof(DisplayConfigPrivate_t));
|
|
if (config == NULL){
|
|
ALOGE("malloc display config err...");
|
|
return -1;
|
|
}
|
|
refreshRate = 1000000000000LLU /
|
|
(uint64_t(info.upper_margin + info.lower_margin + info.vsync_len + info.yres)
|
|
* ( info.left_margin + info.right_margin + info.hsync_len + info.xres)
|
|
* info.pixclock);
|
|
if (refreshRate == 0) {
|
|
ALOGW("invalid refresh rate, assuming 60 Hz");
|
|
refreshRate = 60;
|
|
}
|
|
if (info.width == 0)
|
|
config->dpiX = 160000;
|
|
else
|
|
config->dpiX = 1000 * (info.xres * 25.4f) / info.width;
|
|
|
|
if(info.height == 0)
|
|
config->dpiY = 160000;
|
|
else
|
|
config->dpiY = 1000 * (info.yres * 25.4f) / info.height;
|
|
display->displayConfigList = (DisplayConfig_t **)hwc_malloc(sizeof(DisplayConfig_t *));
|
|
if (display->displayConfigList == NULL) {
|
|
ALOGE("malloc lcd err...");
|
|
return -1;
|
|
}
|
|
config->vsyncPeriod = 1000000000 / refreshRate;
|
|
config->width = info.xres;
|
|
config->height = info.yres;
|
|
display->VarDisplayWidth = config->width;
|
|
display->VarDisplayHeight = config->height;
|
|
display->configNumber = 1;
|
|
display->activeConfigId = 0;
|
|
display->displayConfigList[0] = config;
|
|
display->clientTargetLayer->crop.left = 0;
|
|
display->clientTargetLayer->crop.right = config->width;
|
|
display->clientTargetLayer->crop.top = 0;
|
|
display->clientTargetLayer->crop.bottom = config->height;
|
|
display->clientTargetLayer->frame.left = 0;
|
|
display->clientTargetLayer->frame.right = config->width;
|
|
display->clientTargetLayer->frame.top = 0;
|
|
display->clientTargetLayer->frame.bottom = config->height;
|
|
return 0;
|
|
}
|
|
|
|
int initVariableHdmi(Display_t *display)
|
|
{
|
|
unsigned long arg[4] = {0};
|
|
int i = 0, num = 0, ret = -1, numbconfig = 0, j = 0, fix = -1;
|
|
DisplayConfig_t *displayconfig;
|
|
DisplayConfigPrivate_t *hwconfig;
|
|
bool all_support = 0;
|
|
DisplayConfig_t *Configtemp;
|
|
|
|
arg[0] = display->displayId;
|
|
num = arraySizeOf(hdmi_support);
|
|
loop:
|
|
for (i = 0; i < num; i++) {
|
|
if (!all_support) {
|
|
arg[1] = hdmi_support[i].mode;
|
|
ret = ioctl(dispFd, DISP_HDMI_SUPPORT_MODE, arg);
|
|
}
|
|
if((ret > 0) || all_support
|
|
|| (numbconfig && hdmi_support[i].mode == DISP_TV_MOD_1080P_24HZ_3D_FP)) {
|
|
hdmi_support[i].support = 1;
|
|
ALOGE("hdmi_support[%d] resolution support\n", i);
|
|
}
|
|
else {
|
|
hdmi_support[i].support = 0;
|
|
ALOGE("hdmi_support[%d] resolution not support\n", i);
|
|
continue;
|
|
}
|
|
|
|
if (hdmi_support[i].mode == display->default_mode) {
|
|
fix = numbconfig;
|
|
ALOGE("hdmi_support[%d] fix resolution\n", i);
|
|
}
|
|
numbconfig++;
|
|
}
|
|
if (numbconfig == 0) {
|
|
ALOGD("NO HDMI EDID can read, So we will all support");
|
|
all_support = 1;
|
|
goto loop;
|
|
}
|
|
|
|
display->displayConfigList = (DisplayConfig_t **)hwc_malloc(sizeof(DisplayConfig_t *) * numbconfig);
|
|
|
|
if (display->displayConfigList == NULL) {
|
|
ALOGE("initVariableHdmi malloc err...");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0,j = 0; i < numbconfig && j < num; i++, j++) {
|
|
while(!hdmi_support[j].support)
|
|
j++;
|
|
displayconfig = (DisplayConfig_t *)hwc_malloc((sizeof(DisplayConfig_t) + sizeof(DisplayConfigPrivate_t)));
|
|
if (displayconfig == NULL) {
|
|
ALOGE("hdmi config malloc err...");
|
|
/* to free the configs */
|
|
return -1;
|
|
}
|
|
/* Andorid O set the 1'st default. not the get active config to set default.
|
|
* Bug? so we must set 1'st is the active config.
|
|
*/
|
|
hwconfig = toHwConfig(displayconfig);
|
|
displayconfig->width = hdmi_support[j].width;
|
|
displayconfig->height = hdmi_support[j].height;
|
|
displayconfig->vsyncPeriod = 1000000000 / hdmi_support[j].refreshRate;
|
|
hwconfig->mode = hdmi_support[j].mode;
|
|
hwconfig->screenDisplay = {0, 0, displayconfig->width, displayconfig->height};
|
|
display->displayConfigList[i] = displayconfig;
|
|
}
|
|
|
|
if (fix == -1)
|
|
fix = 0;// 1'st is the default and the active config.see the up
|
|
display->configNumber = numbconfig;
|
|
|
|
hwconfig = toHwConfig(display->displayConfigList[fix]);
|
|
ALOGD("disp:%d active:%d mode:%d [%d x %d] maxid:%d", display->displayId, fix,
|
|
hwconfig->mode,display->displayConfigList[fix]->width,display->displayConfigList[fix]->height, numbconfig);
|
|
displayconfig = display->displayConfigList[0];
|
|
display->displayConfigList[0] = display->displayConfigList[fix];
|
|
display->displayConfigList[fix] = displayconfig;
|
|
display->activeConfigId = 0;
|
|
display->default_mode = hwconfig->mode;
|
|
display->VarDisplayWidth = display->displayConfigList[0]->width;
|
|
display->VarDisplayHeight = display->displayConfigList[0]->height;
|
|
|
|
setActiveConfig(display, display->displayConfigList[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int initVariableCvbs(Display_t *display)
|
|
{
|
|
display;
|
|
return 0;
|
|
}
|
|
|
|
extern int hdmifd;
|
|
int de2Init(Display_t* display)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
int ret = 0;
|
|
int fd;
|
|
int fb0Fd;
|
|
submitThread_t *submitThread;
|
|
unsigned long arg[4] = {0};
|
|
long long deFreqtmp;
|
|
char state;
|
|
struct disp_output pricfg;
|
|
|
|
pthread_mutex_lock(&display->listMutex);
|
|
|
|
if (!list_empty(&display->layerSortedByZorder)) {
|
|
ALOGE("%s:SurfaceFlinger do not destroyed the layer",__FUNCTION__);
|
|
clearList(&display->layerSortedByZorder, 1);
|
|
}
|
|
display->clientTargetLayer = layerCacheGet(sizeof(DELayerPrivate_t));
|
|
if(display->clientTargetLayer == NULL) {
|
|
ALOGE("%s:creat clientTargetLayer err",__FUNCTION__);
|
|
return -1;
|
|
}
|
|
list_init(&display->layerSortedByZorder);
|
|
display->clientTargetLayer->compositionType = HWC2_COMPOSITION_CLIENT_TARGET;
|
|
display->clientTargetLayer->zorder = CLIENT_TARGET_ZORDER;
|
|
insertLayerByZorder(display->clientTargetLayer, &display->layerSortedByZorder);
|
|
pthread_mutex_unlock(&display->listMutex);
|
|
|
|
if (display->plugIn == 1) {
|
|
display->retirfence = -1;
|
|
display->nubmerLayer = 0;
|
|
ALOGD("get a plug in display:%d", display->displayId);
|
|
return 0;
|
|
}
|
|
|
|
hwdisplay = toHwDisplay(display);
|
|
arg[0] = display->displayId;
|
|
arg[1] = (unsigned long)&hwdisplay->type;
|
|
ret = ioctl(dispFd, DISP_GET_OUTPUT, arg);
|
|
if (ret)
|
|
ALOGE("display get display type fail:%d...", ret);
|
|
|
|
if (display->displayId == 1) {
|
|
arg[0] = 0;
|
|
arg[1] = (unsigned long)&pricfg;
|
|
ioctl(dispFd, DISP_GET_OUTPUT, arg);
|
|
if (pricfg.type != DISP_OUTPUT_TYPE_HDMI) {
|
|
if (hdmifd > 0) {
|
|
lseek(hdmifd, 5, SEEK_SET);
|
|
read(hdmifd, &state, 1);
|
|
if (state == '1') {
|
|
hwdisplay->type.type = DISP_OUTPUT_TYPE_HDMI;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (hwdisplay->type.type) {
|
|
case DISP_OUTPUT_TYPE_LCD:
|
|
initPermanentDisplay(display);
|
|
break;
|
|
case DISP_OUTPUT_TYPE_HDMI:
|
|
initVariableHdmi(display);
|
|
break;
|
|
case DISP_OUTPUT_TYPE_TV:
|
|
initVariableCvbs(display);
|
|
break;
|
|
case DISP_OUTPUT_TYPE_VGA:
|
|
break;
|
|
default:
|
|
ALOGE("display get a dissupprt display type ...");
|
|
return -1;
|
|
}
|
|
|
|
display->nubmerLayer = 0;
|
|
display->vsyncEn = 1;
|
|
display->plugIn = 1;
|
|
display->retirfence = -1;
|
|
display->hpercent = 100;
|
|
display->vpercent = 100;
|
|
display->dataspace_mode = DISPLAY_OUTPUT_DATASPACE_MODE_SDR;
|
|
display->screenRadio = SCREEN_FULL;
|
|
|
|
debugInitDisplay(display);
|
|
|
|
submitThread = initSubmitThread(display);
|
|
submitThread->setupLayer = de2SetupLayer;
|
|
submitThread->commitToDisplay = de2commitToDisplay;
|
|
submitThread->delayDeal = de2DelayDeal;
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = HWC_NEW_CLIENT;
|
|
arg[2] = (unsigned long)&deFreqtmp;
|
|
if (ioctl(dispFd, DISP_HWC_COMMIT, (unsigned long)arg)) {
|
|
ALOGE("start devcomposer failed !!!");
|
|
}
|
|
|
|
if (deFreq == 254000000 && deFreqtmp != 254000000)
|
|
deFreq = deFreqtmp;
|
|
ALOGD("init a new display:%d", display->displayId);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int clearAllLayers(int displayId)
|
|
{
|
|
int ret = 0;
|
|
unsigned long arg[4] = {0};
|
|
unsigned int chn = displayId ? 2 : 4;
|
|
unsigned int ly = 4;
|
|
unsigned int i, j;
|
|
|
|
struct disp_layer_config2 layersSet[chn][ly];
|
|
memset(layersSet, 0, sizeof(layersSet));
|
|
for(i = 0; i < chn; i++) {
|
|
for(j = 0; j < ly; j++) {
|
|
layersSet[i][j].enable = false;
|
|
layersSet[i][j].channel = i;
|
|
layersSet[i][j].layer_id = j;
|
|
}
|
|
}
|
|
/* open protect. */
|
|
arg[0] = displayId;
|
|
arg[1] = 1;
|
|
|
|
ret = ioctl(dispFd, DISP_SHADOW_PROTECT, (unsigned long)arg);
|
|
if(ret != 0)
|
|
{
|
|
ALOGE("%d err: DISP_SHADOW_PROTECT failed", __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
arg[1] = (unsigned long)(&layersSet[0][0]);
|
|
arg[2] = chn * ly;
|
|
ret = ioctl(dispFd, DISP_LAYER_SET_CONFIG2, (unsigned long)arg);
|
|
if(ret != 0)
|
|
{
|
|
ALOGE("%d err: DISP_LAYER_SET_CONFIG2 failed", __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
arg[0] = displayId;
|
|
arg[1] = 0;
|
|
ret = ioctl(dispFd, DISP_SHADOW_PROTECT, (unsigned long)arg);
|
|
if(ret != 0)
|
|
{
|
|
ALOGE("%d err: DISP_SHADOW_PROTECT failed", __LINE__);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int de2Deinit(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *displayPri = NULL;
|
|
unsigned long arg[4] = {0};
|
|
|
|
displayPri = toHwDisplay(display);
|
|
deinitSubmitTread(display);
|
|
debugDeDisplay(display);
|
|
/* free the timeline */
|
|
display->plugIn = 0;
|
|
display->active = 0;
|
|
|
|
clearAllLayers(display->displayId);
|
|
|
|
pthread_mutex_lock(&display->listMutex);
|
|
while (display->configNumber--) {
|
|
if (display->displayConfigList[display->configNumber])
|
|
hwc_free(display->displayConfigList[display->configNumber]);
|
|
display->displayConfigList[display->configNumber] = NULL;
|
|
}
|
|
hwc_free(display->displayConfigList);
|
|
display->displayConfigList = NULL;
|
|
display->clientTargetLayer = NULL;
|
|
clearList(&display->layerSortedByZorder, 1);
|
|
pthread_mutex_unlock(&display->listMutex);
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = HWC_DESTROY_CLIENT;
|
|
|
|
if (ioctl(dispFd, DISP_HWC_COMMIT, (unsigned long)arg)) {
|
|
ALOGE("destroy a timeline %d !!!", display->displayId);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int32_t de2SetPowerMode(Display_t* display, int32_t mode)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
hwdisplay = toHwDisplay(display);
|
|
unsigned long arg[4] = {0};
|
|
int ret = 0;
|
|
unsigned long vsyncEn = 0;
|
|
arg[0] = display->displayId;
|
|
|
|
switch (mode) {
|
|
case HWC2_POWER_MODE_OFF:
|
|
arg[1] = 1;
|
|
vsyncEn = 0;
|
|
clearAllLayers(display->displayId);
|
|
break;
|
|
case HWC2_POWER_MODE_DOZE:
|
|
case HWC2_POWER_MODE_DOZE_SUSPEND:
|
|
case HWC2_POWER_MODE_ON:
|
|
arg[1] = 0;
|
|
vsyncEn = 1;
|
|
break;
|
|
}
|
|
ALOGD("set mode %d %ld",mode, vsyncEn);
|
|
if (ioctl(dispFd, DISP_BLANK, arg)) {
|
|
ALOGE("DISP_BLANK ioctl failed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
arg[1] = vsyncEn;
|
|
if (ioctl(dispFd, DISP_VSYNC_EVENT_EN, arg)) {
|
|
ALOGE("DISP_CMD_VSYNC_EVENT_EN ioctl failed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
display->vsyncEn = !!vsyncEn;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t de2SetVsyncEnabled(Display_t *display, int32_t enabled)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
unsigned long arg[4] = {0};
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
arg[0] = display->displayId;
|
|
arg[1] = (enabled == HWC2_VSYNC_ENABLE)?1:0;
|
|
arg[1] = 0;
|
|
ALOGV("set display%d vsync enable:%d",display->displayId, enabled);
|
|
if (ioctl(dispFd, DISP_VSYNC_EVENT_EN, arg)) {
|
|
ALOGE("DISP_CMD_VSYNC_EVENT_EN ioctl failed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
display->vsyncEn = !!enabled;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setDisplayName(Display_t *display)
|
|
{
|
|
DisplayPrivate_t *hwdisplay;
|
|
hwdisplay = toHwDisplay(display);
|
|
|
|
switch (hwdisplay->type.type) {
|
|
case DISP_OUTPUT_TYPE_LCD:
|
|
display->displayName = displayName[0];
|
|
break;
|
|
case DISP_OUTPUT_TYPE_HDMI:
|
|
display->displayName = displayName[1];
|
|
break;
|
|
case DISP_OUTPUT_TYPE_TV:
|
|
display->displayName = displayName[2];
|
|
break;
|
|
case DISP_OUTPUT_TYPE_VGA:
|
|
display->displayName = displayName[3];
|
|
break;
|
|
default:
|
|
display->displayName = displayName[1];
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int displayDeviceInit(Display_t ***display)
|
|
{
|
|
int i = 0, j = 0, ret = -1, fixdiplay = 0;
|
|
Display_t **dispArray, *disp;
|
|
struct disp_output outPut;
|
|
unsigned long arg[4] = {0};
|
|
DisplayPrivate_t *hwdisplay;
|
|
|
|
dispFd = open("/dev/disp", O_RDWR);
|
|
if (dispFd < 0) {
|
|
ALOGE("failed open disp device.");
|
|
return 0;
|
|
}
|
|
|
|
/* if we have LCD or other permanent, set it primer display */
|
|
dispArray = (Display_t **)hwc_malloc(DE_NUM * (sizeof(Display_t*)));
|
|
if(dispArray == NULL) {
|
|
ALOGE("Alloc display err, Can not initial the hwc module.");
|
|
return -1;
|
|
}
|
|
/* if support visual display will change the num
|
|
* for disp 's varable data, must remember.......
|
|
*/
|
|
for (i = 0; i < DE_NUM; i++) {
|
|
disp = (Display_t *)hwc_malloc(sizeof(Display_t) + sizeof(DisplayPrivate_t));
|
|
if (disp == NULL) {
|
|
ALOGE("Alloc display err, Can not initial the hwc module.");
|
|
return -1;
|
|
}
|
|
hwdisplay = toHwDisplay(disp);
|
|
disp->displayOpration = &sunxiDisplayOpr;
|
|
disp->displayId = i;
|
|
|
|
arg[0] = i;
|
|
arg[1] = (unsigned long)&hwdisplay->type;
|
|
ret = ioctl(dispFd, DISP_GET_OUTPUT, arg);
|
|
if (ret > 0)
|
|
ALOGV("get [Disp%d] output type is not NONE!\n", i);
|
|
else
|
|
ALOGE("get [Disp%d] output type is NONE!\n", i);
|
|
|
|
ALOGE("get [Disp%d] output type %d output mode %d \n", i, hwdisplay->type.type, hwdisplay->type.mode);
|
|
|
|
//bpi, get default mode from bsp
|
|
disp->default_mode = hwdisplay->type.mode;
|
|
|
|
if (hwdisplay->type.type == DISP_OUTPUT_TYPE_LCD) {
|
|
ALOGD("find Permanent display:%d", i);
|
|
fixdiplay = i + 1;
|
|
}
|
|
setDisplayName(disp);
|
|
DESource[i].fixPipeNumber = (i == 0 ? 4 : 2);
|
|
DESource[i].fixVideoPipeNum = 1;
|
|
DESource[i].currentPipe = 0;
|
|
|
|
DESource[i].layerInfo = (disp_layer_config2 *)hwc_malloc(DESource[i].fixPipeNumber * 4 * sizeof(disp_layer_config2));
|
|
DESource[i].Pipe = (PipeInfo_t*)hwc_malloc(DESource[i].fixPipeNumber * sizeof(PipeInfo_t));
|
|
|
|
if (DESource[i].layerInfo == NULL
|
|
|| DESource[i].Pipe == NULL ) {
|
|
ALOGE("Calloc DE resource err, Can not initial the hwc...");
|
|
return 0;
|
|
}
|
|
list_init(&disp->layerSortedByZorder);
|
|
pthread_mutex_init(&disp->listMutex, 0);
|
|
|
|
for (j = 0; j < DESource[i].fixPipeNumber * 4; j++) {
|
|
DESource[i].layerInfo[j].channel = j / 4;
|
|
DESource[i].layerInfo[j].layer_id = j % 4;
|
|
DESource[i].layerInfo[j].info.zorder = j;
|
|
}
|
|
dispArray[i] = disp;
|
|
}
|
|
if (!(fixdiplay & 1) && (fixdiplay & 2)){
|
|
/* the perminent disp is primory display */
|
|
disp = dispArray[0];
|
|
dispArray[0] = dispArray[1];
|
|
dispArray[1] = disp;
|
|
}
|
|
|
|
if (!strcmp(dispArray[0]->displayName, "hdmi"))
|
|
dispArray[1]->displayName = displayName[2];
|
|
|
|
|
|
ALOGD("display Id-Type:%d-%d and %d-%d", dispArray[0]->displayId, toHwDisplay(dispArray[0])->type.type,
|
|
dispArray[1]->displayId, toHwDisplay(dispArray[1])->type.type);
|
|
|
|
*display = dispArray;
|
|
return DE_NUM;
|
|
}
|
|
|
|
int displayDeviceDeInit(Display_t **display)
|
|
{
|
|
int i;
|
|
if (dispFd < 0) {
|
|
ALOGE("failed open disp device.");
|
|
return 0;
|
|
}
|
|
close(dispFd);
|
|
dispFd = -1;
|
|
for (i = 0; i < DE_NUM; i++) {
|
|
clearList(&display[i]->layerSortedByZorder, 1);
|
|
display[i]->clientTargetLayer = NULL;
|
|
hwc_free(DESource[i].layerInfo);
|
|
hwc_free(DESource[i].Pipe);
|
|
DESource[i].layerInfo = NULL;
|
|
DESource[i].Pipe = NULL;
|
|
deinitSubmitTread(display[i]);
|
|
hwc_free(display[i]);
|
|
}
|
|
hwc_free(display);
|
|
ALOGD(" displayDeviceDeInit ");
|
|
return 0;
|
|
}
|
|
|
|
DisplayOpr sunxiDisplayOpr = {
|
|
.createLayer = de2creatLayer,
|
|
.AssignLayer = de2AssignLayer,
|
|
.presentDisplay = de2PresentDisplay,
|
|
.dump = de2Dump,
|
|
.init = de2Init,
|
|
.deInit = de2Deinit,
|
|
.setPowerMode = de2SetPowerMode,
|
|
.setVsyncEnabled = de2SetVsyncEnabled,
|
|
.setActiveConfig = setActiveConfig,
|
|
.memCtrlAddLayer = de2memCtrlAddLayer,
|
|
};
|