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