1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2010 - 2014, The Linux Foundation. All rights reserved. 4 * 5 * Not a Contribution, Apache license notifications and license are retained 6 * for attribution purposes only. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21#include <cutils/log.h> 22 23#include <linux/msm_mdp.h> 24#include <linux/fb.h> 25 26#include <stdint.h> 27#include <string.h> 28#include <unistd.h> 29#include <errno.h> 30#include <fcntl.h> 31 32#include <sys/ioctl.h> 33#include <sys/types.h> 34#include <sys/mman.h> 35 36#include <copybit.h> 37 38#include "gralloc_priv.h" 39#include "software_converter.h" 40#include <qdMetaData.h> 41 42#define DEBUG_MDP_ERRORS 1 43 44/******************************************************************************/ 45 46#define MAX_SCALE_FACTOR (4) 47#define MAX_DIMENSION (4096) 48 49/******************************************************************************/ 50struct blitReq{ 51 struct mdp_buf_sync sync; 52 uint32_t count; 53 struct mdp_blit_req req[10]; 54}; 55 56/** State information for each device instance */ 57struct copybit_context_t { 58 struct copybit_device_t device; 59 int mFD; 60 uint8_t mAlpha; 61 int mFlags; 62 bool mBlitToFB; 63 int acqFence[MDP_MAX_FENCE_FD]; 64 int relFence; 65 struct mdp_buf_sync sync; 66 struct blitReq list; 67 uint8_t dynamic_fps; 68}; 69 70/** 71 * Common hardware methods 72 */ 73 74static int open_copybit(const struct hw_module_t* module, const char* name, 75 struct hw_device_t** device); 76 77static struct hw_module_methods_t copybit_module_methods = { 78open: open_copybit 79}; 80 81/* 82 * The COPYBIT Module 83 */ 84struct copybit_module_t HAL_MODULE_INFO_SYM = { 85common: { 86tag: HARDWARE_MODULE_TAG, 87 version_major: 1, 88 version_minor: 0, 89 id: COPYBIT_HARDWARE_MODULE_ID, 90 name: "QCT MSM7K COPYBIT Module", 91 author: "Google, Inc.", 92 methods: ©bit_module_methods 93 } 94}; 95 96/******************************************************************************/ 97 98/** min of int a, b */ 99static inline int min(int a, int b) { 100 return (a<b) ? a : b; 101} 102 103/** max of int a, b */ 104static inline int max(int a, int b) { 105 return (a>b) ? a : b; 106} 107 108/** scale each parameter by mul/div. Assume div isn't 0 */ 109static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) { 110 if (mul != div) { 111 *a = (mul * *a) / div; 112 *b = (mul * *b) / div; 113 } 114} 115 116/** Determine the intersection of lhs & rhs store in out */ 117static void intersect(struct copybit_rect_t *out, 118 const struct copybit_rect_t *lhs, 119 const struct copybit_rect_t *rhs) { 120 out->l = max(lhs->l, rhs->l); 121 out->t = max(lhs->t, rhs->t); 122 out->r = min(lhs->r, rhs->r); 123 out->b = min(lhs->b, rhs->b); 124} 125 126static bool validateCopybitRect(struct copybit_rect_t *rect) { 127 return ((rect->b > rect->t) && (rect->r > rect->l)) ; 128} 129 130/** convert COPYBIT_FORMAT to MDP format */ 131static int get_format(int format) { 132 switch (format) { 133 case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565; 134 case HAL_PIXEL_FORMAT_RGBA_5551: return MDP_RGBA_5551; 135 case HAL_PIXEL_FORMAT_RGBA_4444: return MDP_RGBA_4444; 136 case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888; 137 case HAL_PIXEL_FORMAT_BGRX_8888: return MDP_BGRX_8888; 138 case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888; 139 case HAL_PIXEL_FORMAT_RGBA_8888: return MDP_RGBA_8888; 140 case HAL_PIXEL_FORMAT_BGRA_8888: return MDP_BGRA_8888; 141 case HAL_PIXEL_FORMAT_YCrCb_422_I: return MDP_YCRYCB_H2V1; 142 case HAL_PIXEL_FORMAT_YCbCr_422_I: return MDP_YCBYCR_H2V1; 143 case HAL_PIXEL_FORMAT_YCrCb_422_SP: return MDP_Y_CRCB_H2V1; 144 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CRCB_H2V2; 145 case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; 146 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; 147 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO; 148 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_VENUS; 149 case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: return MDP_Y_CRCB_H2V2_VENUS; 150 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2; 151 case HAL_PIXEL_FORMAT_CbYCrY_422_I: return MDP_CBYCRY_H2V1; 152 case HAL_PIXEL_FORMAT_BGR_888: return MDP_BGR_888; 153 } 154 return -1; 155} 156 157/** convert from copybit image to mdp image structure */ 158static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) 159{ 160 private_handle_t* hnd = (private_handle_t*)rhs->handle; 161 if(hnd == NULL){ 162 ALOGE("copybit: Invalid handle"); 163 return; 164 } 165 img->width = rhs->w; 166 img->height = rhs->h; 167 img->format = get_format(rhs->format); 168 img->offset = (uint32_t)hnd->offset; 169 img->memory_id = hnd->fd; 170} 171/** setup rectangles */ 172static bool set_rects(struct copybit_context_t *dev, 173 struct mdp_blit_req *e, 174 const struct copybit_rect_t *dst, 175 const struct copybit_rect_t *src, 176 const struct copybit_rect_t *scissor) { 177 struct copybit_rect_t clip; 178 intersect(&clip, scissor, dst); 179 180 if (!validateCopybitRect(&clip)) 181 return false; 182 183 e->dst_rect.x = clip.l; 184 e->dst_rect.y = clip.t; 185 e->dst_rect.w = clip.r - clip.l; 186 e->dst_rect.h = clip.b - clip.t; 187 188 uint32_t W, H, delta_x, delta_y; 189 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { 190 delta_x = (clip.t - dst->t); 191 delta_y = (dst->r - clip.r); 192 e->src_rect.w = (clip.b - clip.t); 193 e->src_rect.h = (clip.r - clip.l); 194 W = dst->b - dst->t; 195 H = dst->r - dst->l; 196 } else { 197 delta_x = (clip.l - dst->l); 198 delta_y = (clip.t - dst->t); 199 e->src_rect.w = (clip.r - clip.l); 200 e->src_rect.h = (clip.b - clip.t); 201 W = dst->r - dst->l; 202 H = dst->b - dst->t; 203 } 204 205 MULDIV(&delta_x, &e->src_rect.w, src->r - src->l, W); 206 MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H); 207 208 e->src_rect.x = delta_x + src->l; 209 e->src_rect.y = delta_y + src->t; 210 211 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) { 212 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { 213 e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w); 214 }else{ 215 e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h); 216 } 217 } 218 219 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) { 220 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { 221 e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h); 222 }else{ 223 e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w); 224 } 225 } 226 return true; 227} 228 229/** setup mdp request */ 230static void set_infos(struct copybit_context_t *dev, 231 struct mdp_blit_req *req, int flags) 232{ 233 req->alpha = dev->mAlpha; 234 req->fps = dev->dynamic_fps; 235 req->transp_mask = MDP_TRANSP_NOP; 236 req->flags = dev->mFlags | flags; 237 // check if we are blitting to f/b 238 if (COPYBIT_ENABLE == dev->mBlitToFB) { 239 req->flags |= MDP_MEMORY_ID_TYPE_FB; 240 } 241#if defined(COPYBIT_QSD8K) 242 req->flags |= MDP_BLEND_FG_PREMULT; 243#endif 244} 245 246/** copy the bits */ 247static int msm_copybit(struct copybit_context_t *dev, void const *list) 248{ 249 int err; 250 if (dev->relFence != -1) { 251 close(dev->relFence); 252 dev->relFence = -1; 253 } 254 err = ioctl(dev->mFD, MSMFB_ASYNC_BLIT, 255 (struct mdp_async_blit_req_list const*)list); 256 ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno)); 257 if (err == 0) { 258 return 0; 259 } else { 260#if DEBUG_MDP_ERRORS 261 struct mdp_async_blit_req_list const* l = 262 (struct mdp_async_blit_req_list const*)list; 263 for (unsigned int i=0 ; i<l->count ; i++) { 264 ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" 265 " dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" 266 " flags=%08x, fps=%d" 267 , 268 i, 269 l->req[i].src.width, 270 l->req[i].src.height, 271 l->req[i].src.format, 272 l->req[i].src_rect.x, 273 l->req[i].src_rect.y, 274 l->req[i].src_rect.w, 275 l->req[i].src_rect.h, 276 l->req[i].dst.width, 277 l->req[i].dst.height, 278 l->req[i].dst.format, 279 l->req[i].dst_rect.x, 280 l->req[i].dst_rect.y, 281 l->req[i].dst_rect.w, 282 l->req[i].dst_rect.h, 283 l->req[i].flags, 284 l->req[i].fps 285 ); 286 } 287#endif 288 return -errno; 289 } 290} 291 292/*****************************************************************************/ 293 294/** Set a parameter to value */ 295static int set_parameter_copybit( 296 struct copybit_device_t *dev, 297 int name, 298 int value) 299{ 300 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 301 int status = 0; 302 if (ctx) { 303 switch(name) { 304 case COPYBIT_ROTATION_DEG: 305 switch (value) { 306 case 0: 307 ctx->mFlags &= ~0x7; 308 break; 309 case 90: 310 ctx->mFlags &= ~0x7; 311 ctx->mFlags |= MDP_ROT_90; 312 break; 313 case 180: 314 ctx->mFlags &= ~0x7; 315 ctx->mFlags |= MDP_ROT_180; 316 break; 317 case 270: 318 ctx->mFlags &= ~0x7; 319 ctx->mFlags |= MDP_ROT_270; 320 break; 321 default: 322 ALOGE("Invalid value for COPYBIT_ROTATION_DEG"); 323 status = -EINVAL; 324 break; 325 } 326 break; 327 case COPYBIT_PLANE_ALPHA: 328 if (value < 0) value = MDP_ALPHA_NOP; 329 if (value >= 256) value = 255; 330 ctx->mAlpha = (uint8_t)value; 331 break; 332 case COPYBIT_DYNAMIC_FPS: 333 ctx->dynamic_fps = (uint8_t)value; 334 break; 335 case COPYBIT_DITHER: 336 if (value == COPYBIT_ENABLE) { 337 ctx->mFlags |= MDP_DITHER; 338 } else if (value == COPYBIT_DISABLE) { 339 ctx->mFlags &= ~MDP_DITHER; 340 } 341 break; 342 case COPYBIT_BLUR: 343 if (value == COPYBIT_ENABLE) { 344 ctx->mFlags |= MDP_BLUR; 345 } else if (value == COPYBIT_DISABLE) { 346 ctx->mFlags &= ~MDP_BLUR; 347 } 348 break; 349 case COPYBIT_BLEND_MODE: 350 if(value == COPYBIT_BLENDING_PREMULT) { 351 ctx->mFlags |= MDP_BLEND_FG_PREMULT; 352 } else { 353 ctx->mFlags &= ~MDP_BLEND_FG_PREMULT; 354 } 355 break; 356 case COPYBIT_TRANSFORM: 357 ctx->mFlags &= ~0x7; 358 ctx->mFlags |= value & 0x7; 359 break; 360 case COPYBIT_BLIT_TO_FRAMEBUFFER: 361 if (COPYBIT_ENABLE == value) { 362 ctx->mBlitToFB = value; 363 } else if (COPYBIT_DISABLE == value) { 364 ctx->mBlitToFB = value; 365 } else { 366 ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d", 367 __FUNCTION__, value); 368 } 369 break; 370 case COPYBIT_FG_LAYER: 371 if(value == COPYBIT_ENABLE) { 372 ctx->mFlags |= MDP_IS_FG; 373 } else if (value == COPYBIT_DISABLE) { 374 ctx->mFlags &= ~MDP_IS_FG; 375 } 376 break ; 377 default: 378 status = -EINVAL; 379 break; 380 } 381 } else { 382 status = -EINVAL; 383 } 384 return status; 385} 386 387/** Get a static info value */ 388static int get(struct copybit_device_t *dev, int name) 389{ 390 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 391 int value; 392 if (ctx) { 393 switch(name) { 394 case COPYBIT_MINIFICATION_LIMIT: 395 value = MAX_SCALE_FACTOR; 396 break; 397 case COPYBIT_MAGNIFICATION_LIMIT: 398 value = MAX_SCALE_FACTOR; 399 break; 400 case COPYBIT_SCALING_FRAC_BITS: 401 value = 32; 402 break; 403 case COPYBIT_ROTATION_STEP_DEG: 404 value = 90; 405 break; 406 default: 407 value = -EINVAL; 408 } 409 } else { 410 value = -EINVAL; 411 } 412 return value; 413} 414 415static int set_sync_copybit(struct copybit_device_t *dev, 416 int acquireFenceFd) 417{ 418 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 419 if (acquireFenceFd != -1) { 420 if (ctx->list.sync.acq_fen_fd_cnt < (MDP_MAX_FENCE_FD - 1)) { 421 ctx->acqFence[ctx->list.sync.acq_fen_fd_cnt++] = acquireFenceFd; 422 } else { 423 int ret = -EINVAL; 424 struct blitReq *list = &ctx->list; 425 426 // Since fence is full kick off what is already in the list 427 ret = msm_copybit(ctx, list); 428 if (ret < 0) { 429 ALOGE("%s: Blit call failed", __FUNCTION__); 430 return -EINVAL; 431 } 432 list->count = 0; 433 list->sync.acq_fen_fd_cnt = 0; 434 ctx->acqFence[list->sync.acq_fen_fd_cnt++] = acquireFenceFd; 435 } 436 } 437 return 0; 438} 439 440/** do a stretch blit type operation */ 441static int stretch_copybit( 442 struct copybit_device_t *dev, 443 struct copybit_image_t const *dst, 444 struct copybit_image_t const *src, 445 struct copybit_rect_t const *dst_rect, 446 struct copybit_rect_t const *src_rect, 447 struct copybit_region_t const *region) 448{ 449 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 450 struct blitReq *list; 451 int status = 0; 452 private_handle_t *yv12_handle = NULL; 453 454 if (ctx) { 455 list = &ctx->list; 456 457 if (ctx->mAlpha < 255) { 458 switch (src->format) { 459 // we don't support plane alpha with RGBA formats 460 case HAL_PIXEL_FORMAT_RGBA_8888: 461 case HAL_PIXEL_FORMAT_BGRA_8888: 462 case HAL_PIXEL_FORMAT_RGBA_5551: 463 case HAL_PIXEL_FORMAT_RGBA_4444: 464 ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__, 465 src->format); 466 return -EINVAL; 467 } 468 } 469 470 if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w || 471 src_rect->t < 0 || (uint32_t)src_rect->b > src->h) { 472 // this is always invalid 473 ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\ 474 __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b); 475 476 return -EINVAL; 477 } 478 479 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) { 480 ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h); 481 return -EINVAL; 482 } 483 484 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { 485 ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h); 486 return -EINVAL; 487 } 488 489 if(src->format == HAL_PIXEL_FORMAT_YV12) { 490 int usage = 491 GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED; 492 if (0 == alloc_buffer(&yv12_handle,src->w,src->h, 493 src->format, usage)){ 494 if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){ 495 (const_cast<copybit_image_t *>(src))->format = 496 HAL_PIXEL_FORMAT_YCrCb_420_SP; 497 (const_cast<copybit_image_t *>(src))->handle = 498 yv12_handle; 499 (const_cast<copybit_image_t *>(src))->base = 500 (void *)yv12_handle->base; 501 } 502 else{ 503 ALOGE("Error copybit conversion from yv12 failed"); 504 if(yv12_handle) 505 free_buffer(yv12_handle); 506 return -EINVAL; 507 } 508 } 509 else{ 510 ALOGE("Error:unable to allocate memeory for yv12 software conversion"); 511 return -EINVAL; 512 } 513 } 514 const uint32_t maxCount = 515 (uint32_t)(sizeof(list->req)/sizeof(list->req[0])); 516 const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h }; 517 struct copybit_rect_t clip; 518 status = 0; 519 while ((status == 0) && region->next(region, &clip)) { 520 intersect(&clip, &bounds, &clip); 521 mdp_blit_req* req = &list->req[list->count]; 522 int flags = 0; 523 524 private_handle_t* src_hnd = (private_handle_t*)src->handle; 525 if(src_hnd != NULL && 526 (!(src_hnd->flags & private_handle_t::PRIV_FLAGS_CACHED))) { 527 flags |= MDP_BLIT_NON_CACHED; 528 } 529 530 // Set Color Space for MDP to configure CSC matrix 531 req->color_space = ITU_R_601; 532 MetaData_t *metadata = NULL; 533 534 if (src_hnd != NULL) 535 metadata = (MetaData_t *)src_hnd->base_metadata; 536 537 if (metadata && (metadata->operation & UPDATE_COLOR_SPACE)) { 538 req->color_space = metadata->colorSpace; 539 } 540 541 set_infos(ctx, req, flags); 542 set_image(&req->dst, dst); 543 set_image(&req->src, src); 544 if (set_rects(ctx, req, dst_rect, src_rect, &clip) == false) 545 continue; 546 547 if (req->src_rect.w<=0 || req->src_rect.h<=0) 548 continue; 549 550 if (req->dst_rect.w<=0 || req->dst_rect.h<=0) 551 continue; 552 553 if (++list->count == maxCount) { 554 status = msm_copybit(ctx, list); 555 list->sync.acq_fen_fd_cnt = 0; 556 list->count = 0; 557 } 558 } 559 if(yv12_handle) { 560 //Before freeing the buffer we need buffer passed through blit call 561 if (list->count != 0) { 562 status = msm_copybit(ctx, list); 563 list->sync.acq_fen_fd_cnt = 0; 564 list->count = 0; 565 } 566 free_buffer(yv12_handle); 567 } 568 } else { 569 ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__); 570 status = -EINVAL; 571 } 572 return status; 573} 574 575/** Perform a blit type operation */ 576static int blit_copybit( 577 struct copybit_device_t *dev, 578 struct copybit_image_t const *dst, 579 struct copybit_image_t const *src, 580 struct copybit_region_t const *region) 581{ 582 struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h }; 583 struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h }; 584 return stretch_copybit(dev, dst, src, &dr, &sr, region); 585} 586 587static int finish_copybit(struct copybit_device_t *dev) 588{ 589 // NOP for MDP copybit 590 if(!dev) 591 return -EINVAL; 592 593 return 0; 594} 595static int clear_copybit(struct copybit_device_t *dev, 596 struct copybit_image_t const *buf, 597 struct copybit_rect_t *rect) 598{ 599 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 600 uint32_t color = 0; // black color 601 602 if (!ctx) { 603 ALOGE ("%s: Invalid copybit context", __FUNCTION__); 604 return -EINVAL; 605 } 606 607 struct blitReq list1; 608 memset((char *)&list1 , 0 ,sizeof (struct blitReq) ); 609 list1.count = 1; 610 int my_tmp_get_fence = -1; 611 612 list1.sync.acq_fen_fd = ctx->acqFence; 613 list1.sync.rel_fen_fd = &my_tmp_get_fence; 614 list1.sync.acq_fen_fd_cnt = ctx->list.sync.acq_fen_fd_cnt; 615 mdp_blit_req* req = &list1.req[0]; 616 617 if(!req) { 618 ALOGE ("%s : Invalid request", __FUNCTION__); 619 return -EINVAL; 620 } 621 622 set_image(&req->dst, buf); 623 set_image(&req->src, buf); 624 625 if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > req->dst.width || 626 rect->t < 0 || (uint32_t)(rect->b - rect->t) > req->dst.height) { 627 ALOGE ("%s : Invalid rect : src_rect l %d t %d r %d b %d",\ 628 __FUNCTION__, rect->l, rect->t, rect->r, rect->b); 629 return -EINVAL; 630 } 631 632 req->dst_rect.x = rect->l; 633 req->dst_rect.y = rect->t; 634 req->dst_rect.w = rect->r - rect->l; 635 req->dst_rect.h = rect->b - rect->t; 636 637 req->src_rect = req->dst_rect; 638 639 req->const_color.b = (uint32_t)((color >> 16) & 0xff); 640 req->const_color.g = (uint32_t)((color >> 8) & 0xff); 641 req->const_color.r = (uint32_t)((color >> 0) & 0xff); 642 req->const_color.alpha = MDP_ALPHA_NOP; 643 644 req->transp_mask = MDP_TRANSP_NOP; 645 req->flags = MDP_SOLID_FILL | MDP_MEMORY_ID_TYPE_FB | MDP_BLEND_FG_PREMULT; 646 int status = msm_copybit(ctx, &list1); 647 648 ctx->list.sync.acq_fen_fd_cnt = 0; 649 if (my_tmp_get_fence != -1) 650 close(my_tmp_get_fence); 651 652 return status; 653} 654 655/** Fill the rect on dst with RGBA color **/ 656static int fill_color(struct copybit_device_t *dev, 657 struct copybit_image_t const *dst, 658 struct copybit_rect_t const *rect, 659 uint32_t color) 660{ 661 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 662 if (!ctx) { 663 ALOGE("%s: Invalid copybit context", __FUNCTION__); 664 return -EINVAL; 665 } 666 667 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { 668 ALOGE("%s: Invalid DST w=%d h=%d", __FUNCTION__, dst->w, dst->h); 669 return -EINVAL; 670 } 671 672 if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > dst->w || 673 rect->t < 0 || (uint32_t)(rect->b - rect->t) > dst->h) { 674 ALOGE("%s: Invalid destination rect: l=%d t=%d r=%d b=%d", 675 __FUNCTION__, rect->l, rect->t, rect->r, rect->b); 676 return -EINVAL; 677 } 678 679 int status = 0; 680 struct blitReq* list = &ctx->list; 681 mdp_blit_req* req = &list->req[list->count++]; 682 set_infos(ctx, req, MDP_SOLID_FILL); 683 set_image(&req->src, dst); 684 set_image(&req->dst, dst); 685 686 req->dst_rect.x = rect->l; 687 req->dst_rect.y = rect->t; 688 req->dst_rect.w = rect->r - rect->l; 689 req->dst_rect.h = rect->b - rect->t; 690 req->src_rect = req->dst_rect; 691 692 req->const_color.r = (uint32_t)((color >> 0) & 0xff); 693 req->const_color.g = (uint32_t)((color >> 8) & 0xff); 694 req->const_color.b = (uint32_t)((color >> 16) & 0xff); 695 req->const_color.alpha = (uint32_t)((color >> 24) & 0xff); 696 697 if (list->count == sizeof(list->req)/sizeof(list->req[0])) { 698 status = msm_copybit(ctx, list); 699 list->sync.acq_fen_fd_cnt = 0; 700 list->count = 0; 701 } 702 return status; 703} 704 705/*****************************************************************************/ 706 707/** Close the copybit device */ 708static int close_copybit(struct hw_device_t *dev) 709{ 710 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 711 if (ctx) { 712 close(ctx->mFD); 713 free(ctx); 714 } 715 return 0; 716} 717 718static int flush_get_fence(struct copybit_device_t *dev, int* fd) 719{ 720 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 721 struct blitReq *list = &ctx->list; 722 int ret = -EINVAL; 723 724 if (list->count) { 725 ret = msm_copybit(ctx, list); 726 if (ret < 0) 727 ALOGE("%s: Blit call failed", __FUNCTION__); 728 list->count = 0; 729 } 730 *fd = ctx->relFence; 731 list->sync.acq_fen_fd_cnt = 0; 732 ctx->relFence = -1; 733 return ret; 734} 735 736/** Open a new instance of a copybit device using name */ 737static int open_copybit(const struct hw_module_t* module, const char* name, 738 struct hw_device_t** device) 739{ 740 int status = -EINVAL; 741 742 if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) { 743 return COPYBIT_FAILURE; 744 } 745 copybit_context_t *ctx; 746 ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t)); 747 748 if (ctx == NULL ) { 749 return COPYBIT_FAILURE; 750 } 751 752 memset(ctx, 0, sizeof(*ctx)); 753 754 ctx->device.common.tag = HARDWARE_DEVICE_TAG; 755 ctx->device.common.version = 1; 756 ctx->device.common.module = const_cast<hw_module_t*>(module); 757 ctx->device.common.close = close_copybit; 758 ctx->device.set_parameter = set_parameter_copybit; 759 ctx->device.get = get; 760 ctx->device.blit = blit_copybit; 761 ctx->device.set_sync = set_sync_copybit; 762 ctx->device.stretch = stretch_copybit; 763 ctx->device.finish = finish_copybit; 764 ctx->device.fill_color = fill_color; 765 ctx->device.flush_get_fence = flush_get_fence; 766 ctx->device.clear = clear_copybit; 767 ctx->mAlpha = MDP_ALPHA_NOP; 768 //dynamic_fps is zero means default 769 //panel refresh rate for driver. 770 ctx->dynamic_fps = 0; 771 ctx->mFlags = 0; 772 ctx->sync.flags = 0; 773 ctx->relFence = -1; 774 for (int i=0; i < MDP_MAX_FENCE_FD; i++) { 775 ctx->acqFence[i] = -1; 776 } 777 ctx->sync.acq_fen_fd = ctx->acqFence; 778 ctx->sync.rel_fen_fd = &ctx->relFence; 779 ctx->list.count = 0; 780 ctx->list.sync.acq_fen_fd_cnt = 0; 781 ctx->list.sync.rel_fen_fd = ctx->sync.rel_fen_fd; 782 ctx->list.sync.acq_fen_fd = ctx->sync.acq_fen_fd; 783 ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0); 784 if (ctx->mFD < 0) { 785 status = errno; 786 ALOGE("Error opening frame buffer errno=%d (%s)", 787 status, strerror(status)); 788 status = -status; 789 } else { 790 status = 0; 791 *device = &ctx->device.common; 792 } 793 return status; 794} 795