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