1 /* 2 * cl_memory.cpp - CL memory 3 * 4 * Copyright (c) 2015 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Wind Yuan <feng.yuan (at) intel.com> 19 */ 20 21 #include "cl_utils.h" 22 #include "cl_memory.h" 23 #if HAVE_LIBDRM 24 #include "intel/cl_va_memory.h" 25 #endif 26 27 namespace XCam { 28 29 CLImageDesc::CLImageDesc () 30 : format {CL_R, CL_UNORM_INT8} 31 , width (0) 32 , height (0) 33 , row_pitch (0) 34 , slice_pitch (0) 35 , array_size (0) 36 , size (0) 37 { 38 } 39 40 bool 41 CLImageDesc::operator == (const CLImageDesc& desc) const 42 { 43 if (desc.format.image_channel_data_type == this->format.image_channel_data_type && 44 desc.format.image_channel_order == this->format.image_channel_order && 45 desc.width == this->width && 46 desc.height == this->height && 47 desc.row_pitch == this->row_pitch && 48 desc.slice_pitch == this->slice_pitch && 49 desc.array_size == this->array_size)// && 50 //desc.size == this->size) 51 return true; 52 return false; 53 } 54 55 CLMemory::CLMemory (const SmartPtr<CLContext> &context) 56 : _context (context) 57 , _mem_id (NULL) 58 , _mem_fd (-1) 59 , _mem_need_destroy (true) 60 , _mapped_ptr (NULL) 61 { 62 XCAM_ASSERT (context.ptr () && context->is_valid ()); 63 } 64 65 CLMemory::~CLMemory () 66 { 67 release_fd (); 68 69 if (_mapped_ptr) 70 enqueue_unmap (_mapped_ptr); 71 72 if (_mem_id && _mem_need_destroy) { 73 _context->destroy_mem (_mem_id); 74 } 75 } 76 77 int32_t 78 CLMemory::export_fd () 79 { 80 if (_mem_fd >= 0) 81 return _mem_fd; 82 83 #if HAVE_LIBDRM 84 SmartPtr<CLIntelContext> context = _context.dynamic_cast_ptr<CLIntelContext> (); 85 _mem_fd = context->export_mem_fd (_mem_id); 86 #endif 87 if (_mem_fd < 0) 88 XCAM_LOG_ERROR ("invalid fd:%d", _mem_fd); 89 90 return _mem_fd; 91 } 92 93 void 94 CLMemory::release_fd () 95 { 96 if (_mem_fd <= 0) 97 return; 98 99 close (_mem_fd); 100 _mem_fd = -1; 101 } 102 103 XCamReturn 104 CLMemory::enqueue_unmap ( 105 void *ptr, 106 CLEventList &event_waits, 107 SmartPtr<CLEvent> &event_out) 108 { 109 SmartPtr<CLContext> context = get_context (); 110 cl_mem mem_id = get_mem_id (); 111 112 XCAM_ASSERT (is_valid ()); 113 if (!is_valid ()) 114 return XCAM_RETURN_ERROR_PARAM; 115 116 XCAM_ASSERT (ptr == _mapped_ptr); 117 if (ptr == _mapped_ptr) 118 _mapped_ptr = NULL; 119 120 return context->enqueue_unmap (mem_id, ptr, event_waits, event_out); 121 } 122 123 bool CLMemory::get_cl_mem_info ( 124 cl_image_info param_name, size_t param_size, 125 void *param, size_t *param_size_ret) 126 { 127 cl_mem mem_id = get_mem_id (); 128 cl_int error_code = CL_SUCCESS; 129 if (!mem_id) 130 return false; 131 132 error_code = clGetMemObjectInfo (mem_id, param_name, param_size, param, param_size_ret); 133 XCAM_FAIL_RETURN( 134 WARNING, 135 error_code == CL_SUCCESS, 136 false, 137 "clGetMemObjectInfo failed on param:%d, errno:%d", param_name, error_code); 138 return true; 139 } 140 141 CLBuffer::CLBuffer (const SmartPtr<CLContext> &context) 142 : CLMemory (context) 143 { 144 } 145 146 CLBuffer::CLBuffer ( 147 const SmartPtr<CLContext> &context, uint32_t size, 148 cl_mem_flags flags, void *host_ptr) 149 : CLMemory (context) 150 , _flags (flags) 151 , _size (size) 152 { 153 init_buffer (context, size, flags, host_ptr); 154 } 155 156 bool 157 CLBuffer::init_buffer ( 158 const SmartPtr<CLContext> &context, uint32_t size, 159 cl_mem_flags flags, void *host_ptr) 160 { 161 cl_mem mem_id = NULL; 162 163 mem_id = context->create_buffer (size, flags, host_ptr); 164 if (mem_id == NULL) { 165 XCAM_LOG_WARNING ("CLBuffer create buffer failed"); 166 return false; 167 } 168 169 set_mem_id (mem_id); 170 return true; 171 } 172 173 CLSubBuffer::CLSubBuffer ( 174 const SmartPtr<CLContext> &context, SmartPtr<CLBuffer> main_buf, 175 cl_mem_flags flags, uint32_t offset, uint32_t size) 176 : CLBuffer (context) 177 , _main_buf (main_buf) 178 , _flags (flags) 179 , _size (size) 180 { 181 init_sub_buffer (context, main_buf, flags, offset, size); 182 } 183 184 bool 185 CLSubBuffer::init_sub_buffer ( 186 const SmartPtr<CLContext> &context, 187 SmartPtr<CLBuffer> main_buf, 188 cl_mem_flags flags, 189 uint32_t offset, 190 uint32_t size) 191 { 192 cl_mem sub_mem = NULL; 193 cl_mem main_mem = main_buf->get_mem_id (); 194 XCAM_FAIL_RETURN (ERROR, main_mem != NULL, false, "get memory from main image failed"); 195 196 cl_buffer_region region; 197 region.origin = offset; 198 region.size = size; 199 200 sub_mem = context->create_sub_buffer (main_mem, region, flags); 201 if (sub_mem == NULL) { 202 XCAM_LOG_WARNING ("CLBuffer create sub buffer failed"); 203 return false; 204 } 205 206 set_mem_id (sub_mem); 207 return true; 208 } 209 210 XCamReturn 211 CLBuffer::enqueue_read ( 212 void *ptr, uint32_t offset, uint32_t size, 213 CLEventList &event_waits, 214 SmartPtr<CLEvent> &event_out) 215 { 216 SmartPtr<CLContext> context = get_context (); 217 cl_mem mem_id = get_mem_id (); 218 219 XCAM_ASSERT (is_valid ()); 220 if (!is_valid ()) 221 return XCAM_RETURN_ERROR_PARAM; 222 223 return context->enqueue_read_buffer (mem_id, ptr, offset, size, true, event_waits, event_out); 224 } 225 226 XCamReturn 227 CLBuffer::enqueue_write ( 228 void *ptr, uint32_t offset, uint32_t size, 229 CLEventList &event_waits, 230 SmartPtr<CLEvent> &event_out) 231 { 232 SmartPtr<CLContext> context = get_context (); 233 cl_mem mem_id = get_mem_id (); 234 235 XCAM_ASSERT (is_valid ()); 236 if (!is_valid ()) 237 return XCAM_RETURN_ERROR_PARAM; 238 239 return context->enqueue_write_buffer (mem_id, ptr, offset, size, true, event_waits, event_out); 240 } 241 242 XCamReturn 243 CLBuffer::enqueue_map ( 244 void *&ptr, uint32_t offset, uint32_t size, 245 cl_map_flags map_flags, 246 CLEventList &event_waits, 247 SmartPtr<CLEvent> &event_out) 248 { 249 SmartPtr<CLContext> context = get_context (); 250 cl_mem mem_id = get_mem_id (); 251 XCamReturn ret = XCAM_RETURN_NO_ERROR; 252 253 XCAM_ASSERT (is_valid ()); 254 if (!is_valid ()) 255 return XCAM_RETURN_ERROR_PARAM; 256 257 ret = context->enqueue_map_buffer (mem_id, ptr, offset, size, true, map_flags, event_waits, event_out); 258 XCAM_FAIL_RETURN ( 259 WARNING, 260 ret == XCAM_RETURN_NO_ERROR, 261 ret, 262 "enqueue_map failed "); 263 264 set_mapped_ptr (ptr); 265 return ret; 266 } 267 268 CLImage::CLImage (const SmartPtr<CLContext> &context) 269 : CLMemory (context) 270 { 271 } 272 273 uint32_t 274 CLImage::get_pixel_bytes () const 275 { 276 return calculate_pixel_bytes(_image_desc.format); 277 } 278 279 bool 280 CLImage::get_cl_image_info (cl_image_info param_name, size_t param_size, void *param, size_t *param_size_ret) 281 { 282 cl_mem mem_id = get_mem_id (); 283 cl_int error_code = CL_SUCCESS; 284 if (!mem_id) 285 return false; 286 287 error_code = clGetImageInfo (mem_id, param_name, param_size, param, param_size_ret); 288 XCAM_FAIL_RETURN( 289 WARNING, 290 error_code == CL_SUCCESS, 291 false, 292 "clGetImageInfo failed on param:%d, errno:%d", param_name, error_code); 293 return true; 294 } 295 296 uint32_t 297 CLImage::calculate_pixel_bytes (const cl_image_format &fmt) 298 { 299 uint32_t a = 0, b = 0; 300 switch (fmt.image_channel_order) { 301 case CL_R: 302 case CL_A: 303 case CL_Rx: 304 a = 1; 305 break; 306 case CL_RG: 307 case CL_RA: 308 case CL_RGx: 309 a = 2; 310 break; 311 case CL_RGB: 312 case CL_RGBx: 313 a = 3; 314 break; 315 case CL_RGBA: 316 case CL_BGRA: 317 case CL_ARGB: 318 a = 4; 319 break; 320 default: 321 XCAM_LOG_DEBUG ("calculate_pixel_bytes with wrong channel_order:0x%04x", fmt.image_channel_order); 322 return 0; 323 } 324 325 switch (fmt.image_channel_data_type) { 326 case CL_UNORM_INT8: 327 case CL_SNORM_INT8: 328 case CL_SIGNED_INT8: 329 case CL_UNSIGNED_INT8: 330 b = 1; 331 break; 332 case CL_SNORM_INT16: 333 case CL_UNORM_INT16: 334 case CL_SIGNED_INT16: 335 case CL_UNSIGNED_INT16: 336 case CL_HALF_FLOAT: 337 b = 2; 338 break; 339 case CL_UNORM_INT24: 340 b = 3; 341 break; 342 case CL_SIGNED_INT32: 343 case CL_UNSIGNED_INT32: 344 case CL_FLOAT: 345 b = 4; 346 break; 347 default: 348 XCAM_LOG_DEBUG ("calculate_pixel_bytes with wrong channel_data_type:0x%04x", fmt.image_channel_data_type); 349 return 0; 350 } 351 352 return a * b; 353 } 354 355 bool 356 CLImage::video_info_2_cl_image_desc ( 357 const VideoBufferInfo & video_info, 358 CLImageDesc &image_desc) 359 { 360 image_desc.width = video_info.width; 361 image_desc.height = video_info.height; 362 image_desc.array_size = 0; 363 image_desc.row_pitch = video_info.strides[0]; 364 XCAM_ASSERT (image_desc.row_pitch >= image_desc.width); 365 image_desc.slice_pitch = 0; 366 367 switch (video_info.format) { 368 case XCAM_PIX_FMT_RGB48: 369 //cl_image_info.fmt.image_channel_order = CL_RGB; 370 //cl_image_info.fmt.image_channel_data_type = CL_UNORM_INT16; 371 XCAM_LOG_WARNING ( 372 "video_info to cl_image_info doesn't support XCAM_PIX_FMT_RGB48, maybe try XCAM_PIX_FMT_RGBA64 instread\n" 373 " **** XCAM_PIX_FMT_RGB48 need check with cl implementation ****"); 374 return false; 375 break; 376 case V4L2_PIX_FMT_GREY: 377 image_desc.format.image_channel_order = CL_R; 378 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 379 break; 380 381 case XCAM_PIX_FMT_RGBA64: 382 image_desc.format.image_channel_order = CL_RGBA; 383 image_desc.format.image_channel_data_type = CL_UNORM_INT16; 384 break; 385 386 case V4L2_PIX_FMT_RGB24: 387 image_desc.format.image_channel_order = CL_RGB; 388 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 389 break; 390 391 case V4L2_PIX_FMT_RGB565: 392 image_desc.format.image_channel_order = CL_RGB; 393 image_desc.format.image_channel_data_type = CL_UNORM_SHORT_565; 394 break; 395 case V4L2_PIX_FMT_XBGR32: 396 case V4L2_PIX_FMT_ABGR32: 397 case V4L2_PIX_FMT_BGR32: 398 image_desc.format.image_channel_order = CL_BGRA; 399 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 400 break; 401 // cl doesn'tn support ARGB32 up to now, how about consider V4L2_PIX_FMT_RGBA32 402 case V4L2_PIX_FMT_RGB32: 403 case V4L2_PIX_FMT_ARGB32: 404 case V4L2_PIX_FMT_XRGB32: 405 image_desc.format.image_channel_order = CL_ARGB; 406 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 407 break; 408 409 case V4L2_PIX_FMT_RGBA32: 410 image_desc.format.image_channel_order = CL_RGBA; 411 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 412 break; 413 414 case V4L2_PIX_FMT_SBGGR10: 415 case V4L2_PIX_FMT_SGBRG10: 416 case V4L2_PIX_FMT_SGRBG10: 417 case V4L2_PIX_FMT_SRGGB10: 418 case V4L2_PIX_FMT_SBGGR12: 419 case V4L2_PIX_FMT_SGBRG12: 420 case V4L2_PIX_FMT_SGRBG12: 421 case V4L2_PIX_FMT_SRGGB12: 422 case V4L2_PIX_FMT_SBGGR16: 423 case XCAM_PIX_FMT_SGRBG16: 424 image_desc.format.image_channel_order = CL_R; 425 image_desc.format.image_channel_data_type = CL_UNORM_INT16; 426 break; 427 428 case V4L2_PIX_FMT_SBGGR8: 429 case V4L2_PIX_FMT_SGBRG8: 430 case V4L2_PIX_FMT_SGRBG8: 431 case V4L2_PIX_FMT_SRGGB8: 432 image_desc.format.image_channel_order = CL_R; 433 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 434 break; 435 436 case V4L2_PIX_FMT_NV12: 437 image_desc.format.image_channel_order = CL_R; 438 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 439 image_desc.array_size = 2; 440 image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; 441 break; 442 443 case V4L2_PIX_FMT_YUYV: 444 image_desc.format.image_channel_order = CL_RGBA; 445 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 446 image_desc.width /= 2; 447 break; 448 449 case XCAM_PIX_FMT_LAB: 450 image_desc.format.image_channel_order = CL_R; 451 image_desc.format.image_channel_data_type = CL_FLOAT; 452 break; 453 454 case XCAM_PIX_FMT_RGB48_planar: 455 case XCAM_PIX_FMT_RGB24_planar: 456 image_desc.format.image_channel_order = CL_RGBA; 457 if (XCAM_PIX_FMT_RGB48_planar == video_info.format) 458 image_desc.format.image_channel_data_type = CL_UNORM_INT16; 459 else 460 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 461 image_desc.width = video_info.aligned_width / 4; 462 image_desc.array_size = 3; 463 image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; 464 break; 465 466 case XCAM_PIX_FMT_SGRBG16_planar: 467 case XCAM_PIX_FMT_SGRBG8_planar: 468 image_desc.format.image_channel_order = CL_RGBA; 469 if (XCAM_PIX_FMT_SGRBG16_planar == video_info.format) 470 image_desc.format.image_channel_data_type = CL_UNORM_INT16; 471 else 472 image_desc.format.image_channel_data_type = CL_UNORM_INT8; 473 image_desc.width = video_info.aligned_width / 4; 474 image_desc.array_size = 4; 475 image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; 476 break; 477 478 default: 479 XCAM_LOG_WARNING ( 480 "video_info to cl_image_info doesn't support format:%s", 481 xcam_fourcc_to_string (video_info.format)); 482 return false; 483 } 484 485 return true; 486 } 487 488 void 489 CLImage::init_desc_by_image () 490 { 491 size_t width = 0, height = 0, row_pitch = 0, slice_pitch = 0, array_size = 0, mem_size = 0; 492 cl_image_format format = {CL_R, CL_UNORM_INT8}; 493 494 get_cl_image_info (CL_IMAGE_FORMAT, sizeof(format), &format); 495 get_cl_image_info (CL_IMAGE_WIDTH, sizeof(width), &width); 496 get_cl_image_info (CL_IMAGE_HEIGHT, sizeof(height), &height); 497 get_cl_image_info (CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch); 498 get_cl_image_info (CL_IMAGE_SLICE_PITCH, sizeof(slice_pitch), &slice_pitch); 499 get_cl_image_info (CL_IMAGE_ARRAY_SIZE, sizeof(array_size), &array_size); 500 get_cl_mem_info (CL_MEM_SIZE, sizeof(mem_size), &mem_size); 501 502 _image_desc.format = format; 503 _image_desc.width = width; 504 _image_desc.height = height; 505 _image_desc.row_pitch = row_pitch; 506 _image_desc.slice_pitch = slice_pitch; 507 _image_desc.array_size = array_size; 508 _image_desc.size = mem_size; 509 } 510 511 XCamReturn 512 CLImage::enqueue_map ( 513 void *&ptr, 514 size_t *origin, size_t *region, 515 size_t *row_pitch, size_t *slice_pitch, 516 cl_map_flags map_flags, 517 CLEventList &event_waits, 518 SmartPtr<CLEvent> &event_out) 519 { 520 SmartPtr<CLContext> context = get_context (); 521 cl_mem mem_id = get_mem_id (); 522 XCamReturn ret = XCAM_RETURN_NO_ERROR; 523 524 XCAM_ASSERT (is_valid ()); 525 if (!is_valid ()) 526 return XCAM_RETURN_ERROR_PARAM; 527 528 ret = context->enqueue_map_image (mem_id, ptr, origin, region, row_pitch, slice_pitch, true, map_flags, event_waits, event_out); 529 XCAM_FAIL_RETURN ( 530 WARNING, 531 ret == XCAM_RETURN_NO_ERROR, 532 ret, 533 "enqueue_map failed "); 534 535 set_mapped_ptr (ptr); 536 return ret; 537 } 538 539 CLImage2D::CLImage2D ( 540 const SmartPtr<CLContext> &context, 541 const VideoBufferInfo &video_info, 542 cl_mem_flags flags) 543 : CLImage (context) 544 { 545 CLImageDesc cl_desc; 546 547 if (!video_info_2_cl_image_desc (video_info, cl_desc)) { 548 XCAM_LOG_WARNING ("CLVaImage create va image failed on default videoinfo"); 549 return; 550 } 551 552 init_image_2d (context, cl_desc, flags); 553 } 554 555 CLImage2D::CLImage2D ( 556 const SmartPtr<CLContext> &context, 557 const CLImageDesc &cl_desc, 558 cl_mem_flags flags, 559 SmartPtr<CLBuffer> bind_buf) 560 : CLImage (context) 561 { 562 _bind_buf = bind_buf; 563 init_image_2d (context, cl_desc, flags); 564 } 565 566 bool CLImage2D::init_image_2d ( 567 const SmartPtr<CLContext> &context, 568 const CLImageDesc &desc, 569 cl_mem_flags flags) 570 { 571 cl_mem mem_id = 0; 572 cl_image_desc cl_desc; 573 574 xcam_mem_clear (cl_desc); 575 cl_desc.image_type = CL_MEM_OBJECT_IMAGE2D; 576 cl_desc.image_width = desc.width; 577 cl_desc.image_height = desc.height; 578 cl_desc.image_depth = 1; 579 cl_desc.image_array_size = 0; 580 cl_desc.image_row_pitch = 0; 581 cl_desc.image_slice_pitch = 0; 582 cl_desc.num_mip_levels = 0; 583 cl_desc.num_samples = 0; 584 cl_desc.buffer = NULL; 585 if (_bind_buf.ptr ()) { 586 if (desc.row_pitch) 587 cl_desc.image_row_pitch = desc.row_pitch; 588 else { 589 cl_desc.image_row_pitch = calculate_pixel_bytes(desc.format) * desc.width; 590 } 591 XCAM_ASSERT (cl_desc.image_row_pitch); 592 cl_desc.buffer = _bind_buf->get_mem_id (); 593 XCAM_ASSERT (cl_desc.buffer); 594 } 595 596 mem_id = context->create_image (flags, desc.format, cl_desc); 597 if (mem_id == NULL) { 598 XCAM_LOG_WARNING ("CLImage2D create image 2d failed"); 599 return false; 600 } 601 set_mem_id (mem_id); 602 init_desc_by_image (); 603 return true; 604 } 605 606 CLImage2DArray::CLImage2DArray ( 607 const SmartPtr<CLContext> &context, 608 const VideoBufferInfo &video_info, 609 cl_mem_flags flags, 610 uint32_t extra_array_size) 611 : CLImage (context) 612 { 613 CLImageDesc cl_desc; 614 615 XCAM_ASSERT (video_info.components >= 2); 616 617 if (!video_info_2_cl_image_desc (video_info, cl_desc)) { 618 XCAM_LOG_WARNING ("CLVaImage create va image failed on default videoinfo"); 619 return; 620 } 621 XCAM_ASSERT (cl_desc.array_size >= 2); 622 623 //special process for BYT platform for slice-pitch 624 //if (video_info.format == V4L2_PIX_FMT_NV12) 625 cl_desc.height = XCAM_ALIGN_UP (cl_desc.height, 16); 626 627 cl_desc.array_size += extra_array_size; 628 629 init_image_2d_array (context, cl_desc, flags); 630 } 631 632 bool CLImage2DArray::init_image_2d_array ( 633 const SmartPtr<CLContext> &context, 634 const CLImageDesc &desc, 635 cl_mem_flags flags) 636 { 637 cl_mem mem_id = 0; 638 cl_image_desc cl_desc; 639 640 xcam_mem_clear (cl_desc); 641 cl_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; 642 cl_desc.image_width = desc.width; 643 cl_desc.image_height = desc.height; 644 cl_desc.image_depth = 1; 645 cl_desc.image_array_size = desc.array_size; 646 cl_desc.image_row_pitch = 0; 647 cl_desc.image_slice_pitch = 0; 648 cl_desc.num_mip_levels = 0; 649 cl_desc.num_samples = 0; 650 cl_desc.buffer = NULL; 651 652 mem_id = context->create_image (flags, desc.format, cl_desc); 653 if (mem_id == NULL) { 654 XCAM_LOG_WARNING ("CLImage2D create image 2d failed"); 655 return false; 656 } 657 set_mem_id (mem_id); 658 init_desc_by_image (); 659 return true; 660 } 661 662 663 }; 664