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