1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) 19 #include <limits.h> 20 #include <errno.h> 21 #include <pthread.h> 22 #include <unistd.h> 23 #include <string.h> 24 #include <stdarg.h> 25 26 #include <sys/mman.h> 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 #include <sys/ioctl.h> 30 31 #include <cutils/log.h> 32 #include <cutils/atomic.h> 33 #include <utils/Trace.h> 34 35 #include <hardware/hardware.h> 36 #include <hardware/gralloc.h> 37 38 #include <gralloc1-adapter.h> 39 40 #include "gralloc_priv.h" 41 #include "gr.h" 42 #include "alloc_controller.h" 43 #include "memalloc.h" 44 #include <qdMetaData.h> 45 46 47 using namespace gralloc; 48 /*****************************************************************************/ 49 50 // Return the type of allocator - 51 // these are used for mapping/unmapping 52 static IMemAlloc* getAllocator(int flags) 53 { 54 IMemAlloc* memalloc; 55 IAllocController* alloc_ctrl = IAllocController::getInstance(); 56 memalloc = alloc_ctrl->getAllocator(flags); 57 return memalloc; 58 } 59 60 static int gralloc_map_metadata(buffer_handle_t handle) { 61 private_handle_t* hnd = (private_handle_t*)handle; 62 hnd->base_metadata = 0; 63 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 64 void *mappedAddress = MAP_FAILED; 65 unsigned int size = 0; 66 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 67 mappedAddress = MAP_FAILED; 68 size = ROUND_UP_PAGESIZE(sizeof(MetaData_t)); 69 int ret = memalloc->map_buffer(&mappedAddress, size, 70 hnd->offset_metadata, hnd->fd_metadata); 71 if(ret || mappedAddress == MAP_FAILED) { 72 ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)", 73 hnd, hnd->fd_metadata, strerror(errno)); 74 return -errno; 75 } 76 hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata; 77 } 78 return 0; 79 } 80 81 static int gralloc_map(gralloc_module_t const* module, 82 buffer_handle_t handle) 83 { 84 ATRACE_CALL(); 85 if(!module) 86 return -EINVAL; 87 88 private_handle_t* hnd = (private_handle_t*)handle; 89 unsigned int size = 0; 90 int err = 0; 91 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 92 void *mappedAddress = MAP_FAILED; 93 hnd->base = 0; 94 95 // Dont map framebuffer and secure buffers 96 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) && 97 !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) { 98 size = hnd->size; 99 err = memalloc->map_buffer(&mappedAddress, size, 100 hnd->offset, hnd->fd); 101 if(err || mappedAddress == MAP_FAILED) { 102 ALOGE("Could not mmap handle %p, fd=%d (%s)", 103 handle, hnd->fd, strerror(errno)); 104 return -errno; 105 } 106 107 hnd->base = uint64_t(mappedAddress) + hnd->offset; 108 } else { 109 // Cannot map secure buffers or framebuffers, but still need to map 110 // metadata for secure buffers. 111 // If mapping a secure buffers fails, the framework needs to get 112 // an error code. 113 err = -EACCES; 114 } 115 116 //Allow mapping of metadata for all buffers including secure ones, but not 117 //of framebuffer 118 int metadata_err = gralloc_map_metadata(handle); 119 if (!err) { 120 err = metadata_err; 121 } 122 return err; 123 } 124 125 static int gralloc_unmap(gralloc_module_t const* module, 126 buffer_handle_t handle) 127 { 128 ATRACE_CALL(); 129 int err = -EINVAL; 130 if(!module) 131 return err; 132 133 private_handle_t* hnd = (private_handle_t*)handle; 134 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 135 if(!memalloc) 136 return err; 137 138 if(hnd->base) { 139 err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset); 140 if (err) { 141 ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base, 142 strerror(errno)); 143 return -errno; 144 } 145 hnd->base = 0; 146 } 147 148 if(hnd->base_metadata) { 149 unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t)); 150 err = memalloc->unmap_buffer((void*)hnd->base_metadata, 151 size, hnd->offset_metadata); 152 if (err) { 153 ALOGE("Could not unmap memory at address %p, %s", 154 (void*) hnd->base_metadata, strerror(errno)); 155 return -errno; 156 } 157 hnd->base_metadata = 0; 158 } 159 160 return 0; 161 } 162 163 /*****************************************************************************/ 164 165 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; 166 167 /*****************************************************************************/ 168 169 int gralloc_register_buffer(gralloc_module_t const* module, 170 buffer_handle_t handle) 171 { 172 ATRACE_CALL(); 173 if (!module || private_handle_t::validate(handle) < 0) 174 return -EINVAL; 175 176 int err = gralloc_map(module, handle); 177 /* Do not fail register_buffer for secure buffers*/ 178 if (err == -EACCES) 179 err = 0; 180 return err; 181 } 182 183 int gralloc_unregister_buffer(gralloc_module_t const* module, 184 buffer_handle_t handle) 185 { 186 ATRACE_CALL(); 187 if (!module || private_handle_t::validate(handle) < 0) 188 return -EINVAL; 189 190 /* 191 * If the buffer has been mapped during a lock operation, it's time 192 * to un-map it. It's an error to be here with a locked buffer. 193 * NOTE: the framebuffer is handled differently and is never unmapped. 194 * Also base and base_metadata are reset. 195 */ 196 return gralloc_unmap(module, handle); 197 } 198 199 int terminateBuffer(gralloc_module_t const* module, 200 private_handle_t* hnd) 201 { 202 ATRACE_CALL(); 203 if(!module) 204 return -EINVAL; 205 206 /* 207 * If the buffer has been mapped during a lock operation, it's time 208 * to un-map it. It's an error to be here with a locked buffer. 209 * NOTE: the framebuffer is handled differently and is never unmapped. 210 * Also base and base_metadata are reset. 211 */ 212 return gralloc_unmap(module, hnd); 213 } 214 215 static int gralloc_map_and_invalidate (gralloc_module_t const* module, 216 buffer_handle_t handle, int usage) 217 { 218 ATRACE_CALL(); 219 if (!module || private_handle_t::validate(handle) < 0) 220 return -EINVAL; 221 222 int err = 0; 223 private_handle_t* hnd = (private_handle_t*)handle; 224 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { 225 if (hnd->base == 0) { 226 // we need to map for real 227 pthread_mutex_t* const lock = &sMapLock; 228 pthread_mutex_lock(lock); 229 err = gralloc_map(module, handle); 230 pthread_mutex_unlock(lock); 231 } 232 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and 233 hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) { 234 //Invalidate if CPU reads in software and there are non-CPU 235 //writers. No need to do this for the metadata buffer as it is 236 //only read/written in software. 237 if ((usage & GRALLOC_USAGE_SW_READ_MASK) and 238 (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER)) 239 { 240 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 241 err = memalloc->clean_buffer((void*)hnd->base, 242 hnd->size, hnd->offset, hnd->fd, 243 CACHE_INVALIDATE); 244 } 245 //Mark the buffer to be flushed after CPU write. 246 if (usage & GRALLOC_USAGE_SW_WRITE_MASK) { 247 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; 248 } 249 } 250 } 251 252 return err; 253 } 254 255 int gralloc_lock(gralloc_module_t const* module, 256 buffer_handle_t handle, int usage, 257 int /*l*/, int /*t*/, int /*w*/, int /*h*/, 258 void** vaddr) 259 { 260 ATRACE_CALL(); 261 private_handle_t* hnd = (private_handle_t*)handle; 262 int err = gralloc_map_and_invalidate(module, handle, usage); 263 if(!err) 264 *vaddr = (void*)hnd->base; 265 return err; 266 } 267 268 int gralloc_lock_ycbcr(gralloc_module_t const* module, 269 buffer_handle_t handle, int usage, 270 int /*l*/, int /*t*/, int /*w*/, int /*h*/, 271 struct android_ycbcr *ycbcr) 272 { 273 ATRACE_CALL(); 274 private_handle_t* hnd = (private_handle_t*)handle; 275 int err = gralloc_map_and_invalidate(module, handle, usage); 276 if(!err) 277 err = getYUVPlaneInfo(hnd, ycbcr); 278 return err; 279 } 280 281 int gralloc_unlock(gralloc_module_t const* module, 282 buffer_handle_t handle) 283 { 284 ATRACE_CALL(); 285 if (!module || private_handle_t::validate(handle) < 0) 286 return -EINVAL; 287 288 int err = 0; 289 private_handle_t* hnd = (private_handle_t*)handle; 290 291 IMemAlloc* memalloc = getAllocator(hnd->flags); 292 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { 293 err = memalloc->clean_buffer((void*)hnd->base, 294 hnd->size, hnd->offset, hnd->fd, 295 CACHE_CLEAN); 296 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; 297 } 298 299 return err; 300 } 301 302 /*****************************************************************************/ 303 304 static bool isYUV(private_handle_t* hnd) 305 { 306 bool is_yuv; 307 308 switch (hnd->format) { 309 //Semiplanar 310 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 311 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 312 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: 313 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS 314 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 315 case HAL_PIXEL_FORMAT_YCrCb_422_SP: 316 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: 317 case HAL_PIXEL_FORMAT_NV21_ZSL: 318 case HAL_PIXEL_FORMAT_RAW10: 319 case HAL_PIXEL_FORMAT_RAW16: 320 //Planar 321 case HAL_PIXEL_FORMAT_YV12: 322 is_yuv = true; 323 break; 324 //Unsupported formats 325 case HAL_PIXEL_FORMAT_YCbCr_422_I: 326 case HAL_PIXEL_FORMAT_YCrCb_422_I: 327 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: 328 default: 329 is_yuv = false; 330 break; 331 } 332 333 return is_yuv; 334 } 335 336 static void ycbcr_to_flexible_layout(const struct android_ycbcr* ycbcr, 337 struct android_flex_layout* layout) 338 { 339 layout->format = FLEX_FORMAT_YCbCr; 340 layout->num_planes = 3; 341 342 for (uint32_t i = 0; i < layout->num_planes; i++) { 343 layout->planes[i].bits_per_component = 8; 344 layout->planes[i].bits_used = 8; 345 layout->planes[i].h_increment = 1; 346 layout->planes[i].v_increment = 1; 347 layout->planes[i].h_subsampling = 2; 348 layout->planes[i].v_subsampling = 2; 349 } 350 351 layout->planes[0].top_left = (uint8_t*)ycbcr->y; 352 layout->planes[0].component = FLEX_COMPONENT_Y; 353 layout->planes[0].v_increment = (int32_t)ycbcr->ystride; 354 355 layout->planes[1].top_left = (uint8_t*)ycbcr->cb; 356 layout->planes[1].component = FLEX_COMPONENT_Cb; 357 layout->planes[1].h_increment = (int32_t)ycbcr->chroma_step; 358 layout->planes[1].v_increment = (int32_t)ycbcr->cstride; 359 360 layout->planes[2].top_left = (uint8_t*)ycbcr->cr; 361 layout->planes[2].component = FLEX_COMPONENT_Cr; 362 layout->planes[2].h_increment = (int32_t)ycbcr->chroma_step; 363 layout->planes[2].v_increment = (int32_t)ycbcr->cstride; 364 } 365 366 int gralloc_perform(struct gralloc_module_t const* module, 367 int operation, ... ) 368 { 369 int res = -EINVAL; 370 va_list args; 371 if(!module) 372 return res; 373 374 va_start(args, operation); 375 switch (operation) { 376 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: 377 { 378 int fd = va_arg(args, int); 379 unsigned int size = va_arg(args, unsigned int); 380 unsigned int offset = va_arg(args, unsigned int); 381 void* base = va_arg(args, void*); 382 int width = va_arg(args, int); 383 int height = va_arg(args, int); 384 int format = va_arg(args, int); 385 386 native_handle_t** handle = va_arg(args, native_handle_t**); 387 private_handle_t* hnd = (private_handle_t*)native_handle_create( 388 private_handle_t::sNumFds, private_handle_t::sNumInts()); 389 if (hnd) { 390 hnd->magic = private_handle_t::sMagic; 391 hnd->fd = fd; 392 hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; 393 hnd->size = size; 394 hnd->offset = offset; 395 hnd->base = uint64_t(base) + offset; 396 hnd->gpuaddr = 0; 397 hnd->width = width; 398 hnd->height = height; 399 hnd->format = format; 400 *handle = (native_handle_t *)hnd; 401 res = 0; 402 } 403 break; 404 405 } 406 case GRALLOC_MODULE_PERFORM_GET_STRIDE: 407 { 408 int width = va_arg(args, int); 409 int format = va_arg(args, int); 410 int *stride = va_arg(args, int *); 411 int alignedw = 0, alignedh = 0; 412 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, 413 0, format, 0, alignedw, alignedh); 414 *stride = alignedw; 415 res = 0; 416 } break; 417 418 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE: 419 { 420 const private_handle_t* hnd = va_arg(args, private_handle_t*); 421 int *stride = va_arg(args, int *); 422 if (private_handle_t::validate(hnd)) { 423 return res; 424 } 425 426 int alignedw = 0, alignedh = 0; 427 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh); 428 *stride = alignedw; 429 430 res = 0; 431 } break; 432 433 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE: 434 { 435 const private_handle_t* hnd = va_arg(args, private_handle_t*); 436 int *stride = va_arg(args, int *); 437 int *height = va_arg(args, int *); 438 if (private_handle_t::validate(hnd)) { 439 return res; 440 } 441 442 int alignedw = 0, alignedh = 0; 443 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh); 444 *stride = alignedw; 445 *height = alignedh; 446 447 res = 0; 448 } break; 449 450 case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES: 451 { 452 int width = va_arg(args, int); 453 int height = va_arg(args, int); 454 int format = va_arg(args, int); 455 int usage = va_arg(args, int); 456 int *alignedWidth = va_arg(args, int *); 457 int *alignedHeight = va_arg(args, int *); 458 int *tileEnabled = va_arg(args,int *); 459 *tileEnabled = isUBwcEnabled(format, usage) || 460 isMacroTileEnabled(format, usage); 461 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, 462 height, format, usage, *alignedWidth, *alignedHeight); 463 res = 0; 464 } break; 465 466 case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: 467 { 468 private_handle_t* hnd = va_arg(args, private_handle_t*); 469 int *color_space = va_arg(args, int *); 470 if (private_handle_t::validate(hnd)) { 471 return res; 472 } 473 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 474 if(metadata && metadata->operation & UPDATE_COLOR_SPACE) { 475 *color_space = metadata->colorSpace; 476 res = 0; 477 } 478 } break; 479 480 case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO: 481 { 482 private_handle_t* hnd = va_arg(args, private_handle_t*); 483 android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *); 484 if (!private_handle_t::validate(hnd)) { 485 res = getYUVPlaneInfo(hnd, ycbcr); 486 } 487 } break; 488 489 case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO: 490 { 491 private_handle_t* hnd = va_arg(args, private_handle_t*); 492 int *map_secure_buffer = va_arg(args, int *); 493 if (private_handle_t::validate(hnd)) { 494 return res; 495 } 496 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 497 if(metadata && metadata->operation & MAP_SECURE_BUFFER) { 498 *map_secure_buffer = metadata->mapSecureBuffer; 499 res = 0; 500 } else { 501 *map_secure_buffer = 0; 502 } 503 } break; 504 505 case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG: 506 { 507 private_handle_t* hnd = va_arg(args, private_handle_t*); 508 int *flag = va_arg(args, int *); 509 if (private_handle_t::validate(hnd)) { 510 return res; 511 } 512 *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED; 513 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 514 if (metadata && (metadata->operation & LINEAR_FORMAT)) { 515 *flag = 0; 516 } 517 res = 0; 518 } break; 519 520 case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: 521 { 522 private_handle_t* hnd = va_arg(args, private_handle_t*); 523 void** rgb_data = va_arg(args, void**); 524 if (!private_handle_t::validate(hnd)) { 525 res = getRgbDataAddress(hnd, rgb_data); 526 } 527 } break; 528 529 case GRALLOC_MODULE_PERFORM_GET_IGC: 530 { 531 private_handle_t* hnd = va_arg(args, private_handle_t*); 532 uint32_t *igc = va_arg(args, uint32_t *); 533 if (!private_handle_t::validate(hnd) && igc) { 534 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 535 if (metadata && (metadata->operation & SET_IGC)) { 536 *igc = metadata->igc; 537 res = 0; 538 } 539 } 540 } break; 541 542 case GRALLOC_MODULE_PERFORM_SET_IGC: 543 res = 0; 544 break; 545 546 case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE: 547 { 548 private_handle_t* hnd = va_arg(args, private_handle_t*); 549 uint32_t *enable = va_arg(args, uint32_t*); 550 if (!private_handle_t::validate(hnd)) { 551 setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable); 552 res = 0; 553 } 554 } break; 555 556 case GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR: 557 { 558 auto outMinorVersion = va_arg(args, int*); 559 *outMinorVersion = 1; // GRALLOC_MODULE_API_VERSION_0_1 560 } break; 561 562 case GRALLOC1_ADAPTER_PERFORM_SET_USAGES: 563 { 564 auto hnd = va_arg(args, private_handle_t*); 565 auto producerUsage = va_arg(args, int); 566 auto consumerUsage = va_arg(args, int); 567 hnd->producer_usage = producerUsage; 568 hnd->consumer_usage = consumerUsage; 569 } break; 570 571 case GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS: 572 { 573 auto hnd = va_arg(args, private_handle_t*); 574 auto outWidth = va_arg(args, int*); 575 auto outHeight = va_arg(args, int*); 576 *outWidth = hnd->original_width; 577 *outHeight = hnd->height; 578 } break; 579 580 case GRALLOC1_ADAPTER_PERFORM_GET_FORMAT: 581 { 582 auto hnd = va_arg(args, private_handle_t*); 583 auto outFormat = va_arg(args, int*); 584 *outFormat = hnd->original_format; 585 } break; 586 587 case GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE: 588 { 589 auto hnd = va_arg(args, private_handle_t*); 590 auto outUsage = va_arg(args, int*); 591 *outUsage = hnd->producer_usage; 592 } break; 593 594 case GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE: 595 { 596 auto hnd = va_arg(args, private_handle_t*); 597 auto outUsage = va_arg(args, int*); 598 *outUsage = hnd->consumer_usage; 599 } break; 600 601 case GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE: 602 { 603 auto hnd = va_arg(args, private_handle_t*); 604 auto outBackingStore = va_arg(args, uint64_t*); 605 *outBackingStore = hnd->backing_store; 606 } break; 607 608 case GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES: 609 { 610 auto hnd = va_arg(args, private_handle_t*); 611 auto outNumFlexPlanes = va_arg(args, int*); 612 613 (void) hnd; 614 // for simpilicity 615 *outNumFlexPlanes = 4; 616 } break; 617 618 case GRALLOC1_ADAPTER_PERFORM_GET_STRIDE: 619 { 620 auto hnd = va_arg(args, private_handle_t*); 621 auto outStride = va_arg(args, int*); 622 *outStride = hnd->width; 623 } break; 624 625 case GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX: 626 { 627 auto hnd = va_arg(args, private_handle_t*); 628 auto producerUsage = va_arg(args, int); 629 auto consumerUsage = va_arg(args, int); 630 auto left = va_arg(args, int); 631 auto top = va_arg(args, int); 632 auto width = va_arg(args, int); 633 auto height = va_arg(args, int); 634 auto outLayout = va_arg(args, android_flex_layout*); 635 // always -1 636 auto acquireFence = va_arg(args, int); 637 (void) acquireFence; 638 639 // TODO lock RGB as a flexible format 640 if (!isYUV(hnd)) { 641 return -EINVAL; 642 } 643 644 struct android_ycbcr ycbcr; 645 res = gralloc_lock_ycbcr(module, hnd, 646 producerUsage | consumerUsage, 647 left, top, width, height, &ycbcr); 648 if (res != 0) { 649 return res; 650 } 651 652 ycbcr_to_flexible_layout(&ycbcr, outLayout); 653 } break; 654 655 default: 656 break; 657 } 658 va_end(args); 659 return res; 660 } 661