/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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, };