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 "img_gralloc1_public.h"
27 
DRMFramebuffer(int drm_fd,buffer_handle_t handle,bool is_overlay)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 
~DRMFramebuffer()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