Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  *
     19  * @author Rama, Meka(v.meka (at) samsung.com)
     20            Sangwoo, Park(sw5771.park (at) samsung.com)
     21            Jamie Oh (jung-min.oh (at) samsung.com)
     22  * @date   2011-07-28
     23  *
     24  */
     25 
     26 #include <cutils/log.h>
     27 #include <cutils/atomic.h>
     28 #include <EGL/egl.h>
     29 #include <GLES/gl.h>
     30 #include "SecHWCUtils.h"
     31 
     32 static IMG_gralloc_module_public_t *gpsGrallocModule;
     33 
     34 static int hwc_device_open(const struct hw_module_t* module, const char* name,
     35                            struct hw_device_t** device);
     36 
     37 static struct hw_module_methods_t hwc_module_methods = {
     38     open: hwc_device_open
     39 };
     40 
     41 hwc_module_t HAL_MODULE_INFO_SYM = {
     42     common: {
     43         tag: HARDWARE_MODULE_TAG,
     44         version_major: 1,
     45         version_minor: 0,
     46         id: HWC_HARDWARE_MODULE_ID,
     47         name: "Samsung S5PC11X hwcomposer module",
     48         author: "SAMSUNG",
     49         methods: &hwc_module_methods,
     50     }
     51 };
     52 
     53 static void dump_layer(hwc_layer_t const* l) {
     54     LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
     55             l->compositionType, l->flags, l->handle, l->transform, l->blending,
     56             l->sourceCrop.left,
     57             l->sourceCrop.top,
     58             l->sourceCrop.right,
     59             l->sourceCrop.bottom,
     60             l->displayFrame.left,
     61             l->displayFrame.top,
     62             l->displayFrame.right,
     63             l->displayFrame.bottom);
     64 }
     65 
     66 static int set_src_dst_info(hwc_layer_t *cur,
     67                             struct hwc_win_info_t *win,
     68                             struct sec_img *src_img,
     69                             struct sec_img *dst_img,
     70                             struct sec_rect *src_rect,
     71                             struct sec_rect *dst_rect,
     72                             int win_idx)
     73 {
     74     IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
     75 
     76     // set src image
     77     src_img->w       = prev_handle->iWidth;
     78     src_img->h       = prev_handle->iHeight;
     79     src_img->format  = prev_handle->iFormat;
     80     src_img->base    = NULL;
     81     src_img->offset  = 0;
     82     src_img->mem_id  =0;
     83 
     84     src_img->mem_type = HWC_PHYS_MEM_TYPE;
     85     src_img->w = (src_img->w + 15) & (~15);
     86     src_img->h = (src_img->h + 1) & (~1) ;
     87 
     88     //set src rect
     89     src_rect->x = SEC_MAX(cur->sourceCrop.left, 0);
     90     src_rect->y = SEC_MAX(cur->sourceCrop.top, 0);
     91     src_rect->w = SEC_MAX(cur->sourceCrop.right - cur->sourceCrop.left, 0);
     92     src_rect->w = SEC_MIN(src_rect->w, src_img->w - src_rect->x);
     93     src_rect->h = SEC_MAX(cur->sourceCrop.bottom - cur->sourceCrop.top, 0);
     94     src_rect->h = SEC_MIN(src_rect->h, src_img->h - src_rect->y);
     95 
     96     //set dst image
     97     dst_img->w = win->lcd_info.xres;
     98     dst_img->h = win->lcd_info.yres;
     99 
    100     switch (win->lcd_info.bits_per_pixel) {
    101     case 32:
    102         dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
    103         break;
    104     default:
    105         dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
    106         break;
    107     }
    108 
    109     dst_img->base     = win->addr[win->buf_index];
    110     dst_img->offset   = 0;
    111     dst_img->mem_id   = 0;
    112     dst_img->mem_type = HWC_PHYS_MEM_TYPE;
    113 
    114     //set dst rect
    115     //fimc dst image will be stored from left top corner
    116     dst_rect->x = 0;
    117     dst_rect->y = 0;
    118     dst_rect->w = win->rect_info.w;
    119     dst_rect->h = win->rect_info.h;
    120 
    121     LOGV("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
    122             __func__, src_rect->x, src_rect->y, src_rect->w, src_rect->h,
    123             dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
    124 
    125     return 0;
    126 }
    127 
    128 static int get_hwc_compos_decision(hwc_layer_t* cur)
    129 {
    130     if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
    131         LOGV("%s::is_skip_layer %d cur->handle %x",
    132                 __func__, cur->flags & HWC_SKIP_LAYER, (uint32_t)cur->handle);
    133         return HWC_FRAMEBUFFER;
    134     }
    135 
    136     IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
    137     int compositionType = HWC_FRAMEBUFFER;
    138 
    139     /* check here....if we have any resolution constraints */
    140     if (((cur->sourceCrop.right - cur->sourceCrop.left) < 16) ||
    141         ((cur->sourceCrop.bottom - cur->sourceCrop.top) < 8))
    142         return compositionType;
    143 
    144     if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
    145         (cur->transform == HAL_TRANSFORM_ROT_270)) {
    146         if(((cur->displayFrame.right - cur->displayFrame.left) < 4)||
    147            ((cur->displayFrame.bottom - cur->displayFrame.top) < 8))
    148             return compositionType;
    149         } else if (((cur->displayFrame.right - cur->displayFrame.left) < 8) ||
    150                    ((cur->displayFrame.bottom - cur->displayFrame.top) < 4))
    151          return compositionType;
    152 
    153     if((prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG) &&
    154        (cur->blending == HWC_BLENDING_NONE))
    155         compositionType = HWC_OVERLAY;
    156     else
    157         compositionType = HWC_FRAMEBUFFER;
    158 
    159     LOGV("%s::compositionType %d bpp %d format %x usage %x",
    160             __func__,compositionType, prev_handle->uiBpp, prev_handle->iFormat,
    161             prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG);
    162 
    163     return  compositionType;
    164 }
    165 
    166 static int assign_overlay_window(struct hwc_context_t *ctx,
    167                                  hwc_layer_t *cur,
    168                                  int win_idx,
    169                                  int layer_idx)
    170 {
    171     struct hwc_win_info_t *win;
    172     sec_rect rect;
    173     int ret = 0;
    174 
    175     if(NUM_OF_WIN <= win_idx)
    176         return -1;
    177 
    178     win = &ctx->win[win_idx];
    179 
    180     rect.x = SEC_MAX(cur->displayFrame.left, 0);
    181     rect.y = SEC_MAX(cur->displayFrame.top, 0);
    182     rect.w = SEC_MIN(cur->displayFrame.right - rect.x, win->lcd_info.xres - rect.x);
    183     rect.h = SEC_MIN(cur->displayFrame.bottom - rect.y, win->lcd_info.yres - rect.y);
    184     win->set_win_flag = 0;
    185 
    186     if((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
    187        (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
    188             win->rect_info.x = rect.x;
    189             win->rect_info.y = rect.y;
    190             win->rect_info.w = rect.w;
    191             win->rect_info.h = rect.h;
    192             win->set_win_flag = 1;
    193             win->layer_prev_buf = 0;
    194     }
    195 
    196     win->layer_index = layer_idx;
    197     win->status = HWC_WIN_RESERVED;
    198 
    199     LOGV("%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d",
    200             __func__, win->rect_info.x, win->rect_info.y, win->rect_info.w,
    201             win->rect_info.h, win->layer_index, win_idx );
    202 
    203     return 0;
    204 }
    205 
    206 static void reset_win_rect_info(hwc_win_info_t *win)
    207 {
    208     win->rect_info.x = 0;
    209     win->rect_info.y = 0;
    210     win->rect_info.w = 0;
    211     win->rect_info.h = 0;
    212     return;
    213 }
    214 
    215 static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
    216 {
    217 
    218     struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
    219     int overlay_win_cnt = 0;
    220     int compositionType = 0;
    221     int ret;
    222 
    223     //if geometry is not changed, there is no need to do any work here
    224     if( !list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
    225         return 0;
    226 
    227     //all the windows are free here....
    228     for (int i = 0; i < NUM_OF_WIN; i++) {
    229         ctx->win[i].status = HWC_WIN_FREE;
    230         ctx->win[i].buf_index = 0;
    231     }
    232     ctx->num_of_hwc_layer = 0;
    233     ctx->num_of_fb_layer = 0;
    234     LOGV("%s:: hwc_prepare list->numHwLayers %d", __func__, list->numHwLayers);
    235 
    236     for (int i = 0; i < list->numHwLayers ; i++) {
    237         hwc_layer_t* cur = &list->hwLayers[i];
    238 
    239         if (overlay_win_cnt < NUM_OF_WIN) {
    240             compositionType = get_hwc_compos_decision(cur);
    241 
    242             if (compositionType == HWC_FRAMEBUFFER) {
    243                 cur->compositionType = HWC_FRAMEBUFFER;
    244                 ctx->num_of_fb_layer++;
    245             } else {
    246                 ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
    247                 if (ret != 0) {
    248                     cur->compositionType = HWC_FRAMEBUFFER;
    249                     ctx->num_of_fb_layer++;
    250                     continue;
    251                 }
    252 
    253                 cur->compositionType = HWC_OVERLAY;
    254                 cur->hints = HWC_HINT_CLEAR_FB;
    255                 overlay_win_cnt++;
    256                 ctx->num_of_hwc_layer++;
    257             }
    258         } else {
    259             cur->compositionType = HWC_FRAMEBUFFER;
    260             ctx->num_of_fb_layer++;
    261         }
    262     }
    263 
    264     if(list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
    265         LOGV("%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
    266                 __func__, list->numHwLayers, ctx->num_of_fb_layer,
    267                 ctx->num_of_hwc_layer);
    268 
    269     if (overlay_win_cnt < NUM_OF_WIN) {
    270         //turn off the free windows
    271         for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
    272             window_hide(&ctx->win[i]);
    273             reset_win_rect_info(&ctx->win[i]);
    274         }
    275     }
    276     return 0;
    277 }
    278 
    279 static int hwc_set(hwc_composer_device_t *dev,
    280                    hwc_display_t dpy,
    281                    hwc_surface_t sur,
    282                    hwc_layer_list_t* list)
    283 {
    284     struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
    285     unsigned int phyAddr[MAX_NUM_PLANES];
    286     int skipped_window_mask = 0;
    287     hwc_layer_t* cur;
    288     struct hwc_win_info_t *win;
    289     int ret;
    290     struct sec_img src_img;
    291     struct sec_img dst_img;
    292     struct sec_rect src_rect;
    293     struct sec_rect dst_rect;
    294 
    295 
    296     if (dpy == NULL && sur == NULL && list == NULL) {
    297         // release our resources, the screen is turning off
    298         // in our case, there is nothing to do.
    299         ctx->num_of_fb_layer_prev = 0;
    300         return 0;
    301     }
    302 
    303     bool need_swap_buffers = ctx->num_of_fb_layer > 0;
    304 
    305     /*
    306      * H/W composer documentation states:
    307      * There is an implicit layer containing opaque black
    308      * pixels behind all the layers in the list.
    309      * It is the responsibility of the hwcomposer module to make
    310      * sure black pixels are output (or blended from).
    311      *
    312      * Since we're using a blitter, we need to erase the frame-buffer when
    313      * switching to all-overlay mode.
    314      *
    315      */
    316     if (ctx->num_of_hwc_layer &&
    317         ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
    318         /* we're clearing the screen using GLES here, this is very
    319          * hack-ish, ideal we would use the fimc (if it can do it) */
    320         glDisable(GL_SCISSOR_TEST);
    321         glClearColor(0, 0, 0, 0);
    322         glClear(GL_COLOR_BUFFER_BIT);
    323         glEnable(GL_SCISSOR_TEST);
    324         need_swap_buffers = true;
    325     }
    326 
    327     ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
    328 
    329     if (need_swap_buffers || !list) {
    330         EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
    331         if (!sucess) {
    332             return HWC_EGL_ERROR;
    333         }
    334     }
    335 
    336     if (!list) {
    337         /* turn off the all windows */
    338         for (int i = 0; i < NUM_OF_WIN; i++) {
    339             window_hide(&ctx->win[i]);
    340             reset_win_rect_info(&ctx->win[i]);
    341             ctx->win[i].status = HWC_WIN_FREE;
    342         }
    343         ctx->num_of_hwc_layer = 0;
    344         return 0;
    345     }
    346 
    347     if(ctx->num_of_hwc_layer > NUM_OF_WIN)
    348         ctx->num_of_hwc_layer = NUM_OF_WIN;
    349 
    350     /* compose hardware layers here */
    351     for (uint32_t i = 0; i < ctx->num_of_hwc_layer; i++) {
    352         win = &ctx->win[i];
    353         if (win->status == HWC_WIN_RESERVED) {
    354             cur = &list->hwLayers[win->layer_index];
    355 
    356             if (cur->compositionType == HWC_OVERLAY) {
    357 
    358                 ret = gpsGrallocModule->GetPhyAddrs(gpsGrallocModule,
    359                         cur->handle, phyAddr);
    360                 if (ret) {
    361                     LOGE("%s::GetPhyAddrs fail : ret=%d\n", __func__, ret);
    362                     skipped_window_mask |= (1 << i);
    363                     continue;
    364                 }
    365 
    366                 /* initialize the src & dist context for fimc */
    367                 set_src_dst_info (cur, win, &src_img, &dst_img, &src_rect,
    368                         &dst_rect, i);
    369 
    370                 ret = runFimc(ctx, &src_img, &src_rect, &dst_img, &dst_rect,
    371                         phyAddr, cur->transform);
    372                 if (ret < 0){
    373                    LOGE("%s::runFimc fail : ret=%d\n", __func__, ret);
    374                    skipped_window_mask |= (1 << i);
    375                    continue;
    376                 }
    377 
    378                 if (win->set_win_flag == 1) {
    379                     /* turnoff the window and set the window position with new conf... */
    380                     if (window_set_pos(win) < 0) {
    381                         LOGE("%s::window_set_pos is failed : %s", __func__,
    382                                 strerror(errno));
    383                         skipped_window_mask |= (1 << i);
    384                         continue;
    385                     }
    386                     win->set_win_flag = 0;
    387                 }
    388 
    389                 /* is the frame didn't change, it needs to be composited
    390                  * because something else below it could have changed, however
    391                  * it doesn't need to be swapped.
    392                  */
    393                 if (win->layer_prev_buf != (uint32_t)cur->handle) {
    394                     win->layer_prev_buf = (uint32_t)cur->handle;
    395                     window_pan_display(win);
    396                     win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
    397                 }
    398 
    399                 if(win->power_state == 0)
    400                     window_show(win);
    401 
    402             } else {
    403                 LOGE("%s:: error : layer %d compositionType should have been \
    404                         HWC_OVERLAY", __func__, win->layer_index);
    405                 skipped_window_mask |= (1 << i);
    406                 continue;
    407             }
    408          } else {
    409              LOGE("%s:: error : window status should have been HWC_WIN_RESERVED \
    410                      by now... ", __func__);
    411              skipped_window_mask |= (1 << i);
    412              continue;
    413          }
    414     }
    415 
    416     if (skipped_window_mask) {
    417         //turn off the free windows
    418         for (int i = 0; i < NUM_OF_WIN; i++) {
    419             if (skipped_window_mask & (1 << i))
    420                 window_hide(&ctx->win[i]);
    421         }
    422     }
    423 
    424     return 0;
    425 }
    426 
    427 static int hwc_device_close(struct hw_device_t *dev)
    428 {
    429     struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
    430     int ret = 0;
    431     int i;
    432 
    433     if (ctx) {
    434         if (destroyFimc(&ctx->fimc) < 0) {
    435             LOGE("%s::destroyFimc fail", __func__);
    436             ret = -1;
    437         }
    438 
    439         for (i = 0; i < NUM_OF_WIN; i++) {
    440             if (window_close(&ctx->win[i]) < 0) {
    441                 LOGE("%s::window_close() fail", __func__);
    442                 ret = -1;
    443             }
    444         }
    445 
    446         free(ctx);
    447     }
    448     return ret;
    449 }
    450 
    451 static int hwc_device_open(const struct hw_module_t* module, const char* name,
    452         struct hw_device_t** device)
    453 {
    454     int status = 0;
    455     struct hwc_win_info_t *win;
    456 
    457     if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
    458                 (const hw_module_t**)&gpsGrallocModule))
    459         return -EINVAL;
    460 
    461     if(strcmp(gpsGrallocModule->base.common.author, "Imagination Technologies"))
    462         return -EINVAL;
    463 
    464     if (strcmp(name, HWC_HARDWARE_COMPOSER))
    465         return -EINVAL;
    466 
    467     struct hwc_context_t *dev;
    468     dev = (hwc_context_t*)malloc(sizeof(*dev));
    469 
    470     /* initialize our state here */
    471     memset(dev, 0, sizeof(*dev));
    472 
    473     /* initialize the procs */
    474     dev->device.common.tag = HARDWARE_DEVICE_TAG;
    475     dev->device.common.version = 0;
    476     dev->device.common.module = const_cast<hw_module_t*>(module);
    477     dev->device.common.close = hwc_device_close;
    478 
    479     dev->device.prepare = hwc_prepare;
    480     dev->device.set = hwc_set;
    481 
    482     *device = &dev->device.common;
    483 
    484     /* initializing */
    485     memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
    486 	dev->fimc.dev_fd = -1;
    487 
    488     /* open WIN0 & WIN1 here */
    489     for (int i = 0; i < NUM_OF_WIN; i++) {
    490         if (window_open(&(dev->win[i]), i) < 0) {
    491              LOGE("%s:: Failed to open window %d device ", __func__, i);
    492              status = -EINVAL;
    493              goto err;
    494         }
    495     }
    496 
    497     /* get default window config */
    498     if (window_get_global_lcd_info(&dev->lcd_info) < 0) {
    499         LOGE("%s::window_get_global_lcd_info is failed : %s",
    500 				__func__, strerror(errno));
    501         status = -EINVAL;
    502         goto err;
    503     }
    504 
    505     dev->lcd_info.yres_virtual = dev->lcd_info.yres * NUM_OF_WIN_BUF;
    506 
    507     /* initialize the window context */
    508     for (int i = 0; i < NUM_OF_WIN; i++) {
    509         win = &dev->win[i];
    510         memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
    511         memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
    512 
    513         win->rect_info.x = 0;
    514         win->rect_info.y = 0;
    515         win->rect_info.w = win->var_info.xres;
    516         win->rect_info.h = win->var_info.yres;
    517 
    518         if (window_set_pos(win) < 0) {
    519             LOGE("%s::window_set_pos is failed : %s",
    520 					__func__, strerror(errno));
    521             status = -EINVAL;
    522             goto err;
    523         }
    524 
    525         if (window_get_info(win) < 0) {
    526             LOGE("%s::window_get_info is failed : %s",
    527 					__func__, strerror(errno));
    528             status = -EINVAL;
    529             goto err;
    530         }
    531 
    532         win->size = win->fix_info.line_length * win->var_info.yres;
    533 
    534         if (!win->fix_info.smem_start){
    535             LOGE("%s:: win-%d failed to get the reserved memory", __func__, i);
    536             status = -EINVAL;
    537             goto err;
    538         }
    539 
    540         for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
    541             win->addr[j] = win->fix_info.smem_start + (win->size * j);
    542             LOGI("%s::win-%d add[%d] %x ", __func__, i, j, win->addr[j]);
    543         }
    544     }
    545 
    546     /* open pp */
    547     if (createFimc(&dev->fimc) < 0) {
    548         LOGE("%s::creatFimc() fail", __func__);
    549         status = -EINVAL;
    550         goto err;
    551     }
    552 
    553     LOGD("%s:: success\n", __func__);
    554 
    555     return 0;
    556 
    557 err:
    558     if (destroyFimc(&dev->fimc) < 0)
    559         LOGE("%s::destroyFimc() fail", __func__);
    560 
    561     for (int i = 0; i < NUM_OF_WIN; i++) {
    562         if (window_close(&dev->win[i]) < 0)
    563             LOGE("%s::window_close() fail", __func__);
    564     }
    565 
    566     return status;
    567 }
    568