1 /* 2 * Copyright (C) Texas Instruments Incorporated - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <log/log.h> 18 #include <drm/drm_fourcc.h> 19 #include <hardware/hwcomposer.h> 20 21 #include <xf86drm.h> 22 #include <xf86drmMode.h> 23 24 #include "drmfb.h" 25 #include "format.h" 26 #include "hal_public.h" 27 28 DRMFramebuffer::DRMFramebuffer(int drm_fd, buffer_handle_t handle, bool is_overlay) : 29 bo(), pitches(), offsets() 30 { 31 if (!handle) 32 return; 33 34 uint32_t gem_handle; 35 IMG_native_handle_t* img_hnd = (IMG_native_handle_t*)handle; 36 int ret = drmPrimeFDToHandle(drm_fd, img_hnd->fd[0], &gem_handle); 37 if (ret) { 38 ALOGE("Failed to get DRM buffer object from handle"); 39 return; 40 } 41 42 this->width = img_hnd->iWidth; 43 this->height = img_hnd->iHeight; 44 this->format = convert_hal_to_drm_format(img_hnd->iFormat, true); 45 this->bo[0] = gem_handle; 46 this->pitches[0] = ALIGN(img_hnd->iWidth, HW_ALIGN) * get_format_bpp(img_hnd->iFormat) >> 3; 47 this->offsets[0] = 0; 48 this->drm_fd = drm_fd; 49 50 if (is_overlay) { 51 switch (this->format) { 52 case DRM_FORMAT_NV12: 53 this->bo[1] = gem_handle; 54 55 this->pitches[0] = ALIGN(img_hnd->iWidth, HW_ALIGN); 56 this->pitches[1] = this->pitches[0]; 57 58 this->offsets[1] = this->pitches[0] * img_hnd->iHeight; 59 break; 60 case DRM_FORMAT_ARGB8888: 61 case DRM_FORMAT_XRGB8888: 62 case DRM_FORMAT_RGB565: 63 break; 64 default: 65 ALOGE("Bad format for overlay"); 66 return; 67 } 68 } 69 70 ret = drmModeAddFB2(drm_fd, this->width, this->height, 71 this->format, this->bo, 72 this->pitches, this->offsets, 73 &this->fb_id, 0); 74 if (ret) { 75 ALOGE("Could not create DRM frame buffer %d", ret); 76 return; 77 } 78 } 79 80 DRMFramebuffer::~DRMFramebuffer() 81 { 82 if (this->fb_id) { 83 if (drmModeRmFB(this->drm_fd, this->fb_id)) 84 ALOGE("Failed to remove DRM frame buffer"); 85 } 86 87 for (size_t i = 0; i < 4; i++) { 88 if (this->bo[i]) { 89 struct drm_gem_close close_args = { 90 close_args.handle = this->bo[i], 91 close_args.pad = 0, 92 }; 93 int ret = drmIoctl(this->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_args); 94 if (ret) { 95 ALOGE("Failed to close GEM handle"); 96 return; 97 } 98 } 99 } 100 } 101