Home | History | Annotate | Download | only in drm_hwcomposer
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      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 #define LOG_TAG "hwc-platform-drm-generic"
     18 
     19 #include "drmresources.h"
     20 #include "platform.h"
     21 #include "platformdrmgeneric.h"
     22 
     23 #include <drm/drm_fourcc.h>
     24 #include <xf86drm.h>
     25 #include <xf86drmMode.h>
     26 
     27 #include <cutils/log.h>
     28 #include <gralloc_drm_handle.h>
     29 #include <hardware/gralloc.h>
     30 #include <EGL/eglext.h>
     31 
     32 namespace android {
     33 
     34 #ifdef USE_DRM_GENERIC_IMPORTER
     35 // static
     36 Importer *Importer::CreateInstance(DrmResources *drm) {
     37   DrmGenericImporter *importer = new DrmGenericImporter(drm);
     38   if (!importer)
     39     return NULL;
     40 
     41   int ret = importer->Init();
     42   if (ret) {
     43     ALOGE("Failed to initialize the nv importer %d", ret);
     44     delete importer;
     45     return NULL;
     46   }
     47   return importer;
     48 }
     49 #endif
     50 
     51 DrmGenericImporter::DrmGenericImporter(DrmResources *drm) : drm_(drm) {
     52 }
     53 
     54 DrmGenericImporter::~DrmGenericImporter() {
     55 }
     56 
     57 int DrmGenericImporter::Init() {
     58   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
     59                           (const hw_module_t **)&gralloc_);
     60   if (ret) {
     61     ALOGE("Failed to open gralloc module");
     62     return ret;
     63   }
     64   return 0;
     65 }
     66 
     67 uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) {
     68   switch (hal_format) {
     69     case HAL_PIXEL_FORMAT_RGB_888:
     70       return DRM_FORMAT_BGR888;
     71     case HAL_PIXEL_FORMAT_BGRA_8888:
     72       return DRM_FORMAT_ARGB8888;
     73     case HAL_PIXEL_FORMAT_RGBX_8888:
     74       return DRM_FORMAT_XBGR8888;
     75     case HAL_PIXEL_FORMAT_RGBA_8888:
     76       return DRM_FORMAT_ABGR8888;
     77     case HAL_PIXEL_FORMAT_RGB_565:
     78       return DRM_FORMAT_BGR565;
     79     case HAL_PIXEL_FORMAT_YV12:
     80       return DRM_FORMAT_YVU420;
     81     default:
     82       ALOGE("Cannot convert hal format to drm format %u", hal_format);
     83       return -EINVAL;
     84   }
     85 }
     86 
     87 EGLImageKHR DrmGenericImporter::ImportImage(EGLDisplay egl_display, buffer_handle_t handle) {
     88   gralloc_drm_handle_t *gr_handle = gralloc_drm_handle(handle);
     89   if (!gr_handle)
     90     return NULL;
     91   EGLint attr[] = {
     92     EGL_WIDTH, gr_handle->width,
     93     EGL_HEIGHT, gr_handle->height,
     94     EGL_LINUX_DRM_FOURCC_EXT, (EGLint)ConvertHalFormatToDrm(gr_handle->format),
     95     EGL_DMA_BUF_PLANE0_FD_EXT, gr_handle->prime_fd,
     96     EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
     97     EGL_DMA_BUF_PLANE0_PITCH_EXT, gr_handle->stride,
     98     EGL_NONE,
     99   };
    100   return eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr);
    101 }
    102 
    103 int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
    104   gralloc_drm_handle_t *gr_handle = gralloc_drm_handle(handle);
    105   if (!gr_handle)
    106     return -EINVAL;
    107 
    108   uint32_t gem_handle;
    109   int ret = drmPrimeFDToHandle(drm_->fd(), gr_handle->prime_fd, &gem_handle);
    110   if (ret) {
    111     ALOGE("failed to import prime fd %d ret=%d", gr_handle->prime_fd, ret);
    112     return ret;
    113   }
    114 
    115   memset(bo, 0, sizeof(hwc_drm_bo_t));
    116   bo->width = gr_handle->width;
    117   bo->height = gr_handle->height;
    118   bo->format = ConvertHalFormatToDrm(gr_handle->format);
    119   bo->pitches[0] = gr_handle->stride;
    120   bo->gem_handles[0] = gem_handle;
    121   bo->offsets[0] = 0;
    122 
    123   ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
    124                       bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
    125   if (ret) {
    126     ALOGE("could not create drm fb %d", ret);
    127     return ret;
    128   }
    129 
    130   return ret;
    131 }
    132 
    133 int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
    134   if (bo->fb_id)
    135     if (drmModeRmFB(drm_->fd(), bo->fb_id))
    136       ALOGE("Failed to rm fb");
    137 
    138   struct drm_gem_close gem_close;
    139   memset(&gem_close, 0, sizeof(gem_close));
    140   int num_gem_handles = sizeof(bo->gem_handles) / sizeof(bo->gem_handles[0]);
    141   for (int i = 0; i < num_gem_handles; i++) {
    142     if (!bo->gem_handles[i])
    143       continue;
    144 
    145     gem_close.handle = bo->gem_handles[i];
    146     int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
    147     if (ret)
    148       ALOGE("Failed to close gem handle %d %d", i, ret);
    149     else
    150       bo->gem_handles[i] = 0;
    151   }
    152   return 0;
    153 }
    154 
    155 #ifdef USE_DRM_GENERIC_IMPORTER
    156 std::unique_ptr<Planner> Planner::CreateInstance(DrmResources *) {
    157   std::unique_ptr<Planner> planner(new Planner);
    158   planner->AddStage<PlanStageGreedy>();
    159   return planner;
    160 }
    161 #endif
    162 }
    163