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