OSDN Git Service

drm_hwcomposer: Don't compile all importers at once
[android-x86/external-drm_hwcomposer.git] / nvimporter.cpp
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-nv-importer"
18
19 #include "drmresources.h"
20 #include "importer.h"
21 #include "nvimporter.h"
22
23 #include <xf86drm.h>
24 #include <xf86drmMode.h>
25
26 #include <cutils/log.h>
27 #include <hardware/gralloc.h>
28
29 namespace android {
30
31 #ifdef USE_NVIDIA_IMPORTER
32 // static
33 Importer *Importer::CreateInstance(DrmResources *drm) {
34   NvImporter *importer = new NvImporter(drm);
35   if (!importer)
36     return NULL;
37
38   int ret = importer->Init();
39   if (ret) {
40     ALOGE("Failed to initialize the nv importer %d", ret);
41     delete importer;
42     return NULL;
43   }
44   return importer;
45 }
46 #endif
47
48 NvImporter::NvImporter(DrmResources *drm) : drm_(drm) {
49 }
50
51 NvImporter::~NvImporter() {
52 }
53
54 int NvImporter::Init() {
55   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
56                           (const hw_module_t **)&gralloc_);
57   if (ret) {
58     ALOGE("Failed to open gralloc module %d", ret);
59     return ret;
60   }
61
62   if (strcasecmp(gralloc_->common.author, "NVIDIA"))
63     ALOGW("Using non-NVIDIA gralloc module: %s/%s\n", gralloc_->common.name,
64           gralloc_->common.author);
65
66   return 0;
67 }
68
69 int NvImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
70   memset(bo, 0, sizeof(hwc_drm_bo_t));
71   NvBuffer_t *buf = GrallocGetNvBuffer(handle);
72   if (buf) {
73     *bo = buf->bo;
74     return 0;
75   }
76
77   buf = new NvBuffer_t();
78   if (!buf) {
79     ALOGE("Failed to allocate new NvBuffer_t");
80     return -ENOMEM;
81   }
82   buf->importer = this;
83
84   int ret = gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_DRM_IMPORT,
85                               drm_->fd(), handle, &buf->bo);
86   if (ret) {
87     ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
88     delete buf;
89     return ret;
90   }
91
92   ret = drmModeAddFB2(drm_->fd(), buf->bo.width, buf->bo.height, buf->bo.format,
93                       buf->bo.gem_handles, buf->bo.pitches, buf->bo.offsets,
94                       &buf->bo.fb_id, 0);
95   if (ret) {
96     ALOGE("Failed to add fb %d", ret);
97     ReleaseBufferImpl(&buf->bo);
98     delete buf;
99     return ret;
100   }
101
102   ret = GrallocSetNvBuffer(handle, buf);
103   if (ret) {
104     /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
105      * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
106      * only one of which should be used by drm_hwcomposer). */
107     ALOGE("Failed to register free callback for imported buffer %d", ret);
108     ReleaseBufferImpl(&buf->bo);
109     delete buf;
110     return ret;
111   }
112   *bo = buf->bo;
113   return 0;
114 }
115
116 int NvImporter::ReleaseBuffer(hwc_drm_bo_t * /* bo */) {
117   /* Stub this out since we don't want hwc releasing buffers */
118   return 0;
119 }
120
121 // static
122 void NvImporter::ReleaseBufferCallback(void *nv_buffer) {
123   NvBuffer_t *buf = (NvBuffer_t *)nv_buffer;
124   buf->importer->ReleaseBufferImpl(&buf->bo);
125   delete buf;
126 }
127
128 void NvImporter::ReleaseBufferImpl(hwc_drm_bo_t *bo) {
129   if (bo->fb_id) {
130     int ret = drmModeRmFB(drm_->fd(), bo->fb_id);
131     if (ret)
132       ALOGE("Failed to rm fb %d", ret);
133   }
134
135   struct drm_gem_close gem_close;
136   memset(&gem_close, 0, sizeof(gem_close));
137   int num_gem_handles = sizeof(bo->gem_handles) / sizeof(bo->gem_handles[0]);
138   for (int i = 0; i < num_gem_handles; i++) {
139     if (!bo->gem_handles[i])
140       continue;
141
142     gem_close.handle = bo->gem_handles[i];
143     int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
144     if (ret)
145       ALOGE("Failed to close gem handle %d %d", i, ret);
146     else
147       bo->gem_handles[i] = 0;
148   }
149 }
150
151 NvImporter::NvBuffer_t *NvImporter::GrallocGetNvBuffer(buffer_handle_t handle) {
152   void *priv = NULL;
153   int ret =
154       gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE,
155                         handle, ReleaseBufferCallback, &priv);
156   return ret ? NULL : (NvBuffer_t *)priv;
157 }
158
159 int NvImporter::GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf) {
160   return gralloc_->perform(gralloc_,
161                            GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle,
162                            ReleaseBufferCallback, buf);
163 }
164 }