OSDN Git Service

drm_hwcomposer: Cache FB and gem in gralloc buffer
[android-x86/external-drm_hwcomposer.git] / hwcomposer_import_nv_gralloc.cpp
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  * Copyright (C) 2015 NVIDIA Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19 #include <cutils/log.h>
20 #include <hardware/gralloc.h>
21
22 #include <xf86drm.h>
23 #include <xf86drmMode.h>
24 #include "drm_hwcomposer.h"
25
26 #define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
27
28 struct hwc_import_context {
29         const gralloc_module_t *gralloc_module;
30 };
31
32 int hwc_import_init(struct hwc_import_context **ctx)
33 {
34         int ret;
35         struct hwc_import_context *import_ctx;
36
37         import_ctx = (struct hwc_import_context *)calloc(1,
38                                 sizeof(*import_ctx));
39         if (!ctx) {
40                 ALOGE("Failed to allocate gralloc import context");
41                 return -ENOMEM;
42         }
43
44         ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
45                         (const hw_module_t **)&import_ctx->gralloc_module);
46         if (ret) {
47                 ALOGE("Failed to open gralloc module");
48                 goto err;
49         }
50
51         if (!strcasecmp(import_ctx->gralloc_module->common.author, "NVIDIA"))
52                 ALOGW("Using non-NVIDIA gralloc module: %s\n",
53                         import_ctx->gralloc_module->common.name);
54
55         *ctx = import_ctx;
56
57         return 0;
58
59 err:
60         free(import_ctx);
61         return ret;
62 }
63
64 int hwc_import_destroy(struct hwc_import_context *ctx)
65 {
66         free(ctx);
67         return 0;
68 }
69
70 struct importer_priv
71 {
72         int drm_fd;
73         struct hwc_drm_bo bo;
74 };
75
76 static void free_priv(void *p)
77 {
78         struct importer_priv *priv = (struct importer_priv *)p;
79         struct drm_gem_close gem_close;
80         int i, ret;
81
82         if (priv->bo.fb_id) {
83                 ret = drmModeRmFB(priv->drm_fd, priv->bo.fb_id);
84                 if (ret)
85                         ALOGE("Failed to rm fb %d", ret);
86         }
87
88         memset(&gem_close, 0, sizeof(gem_close));
89         for (i = 0; i < ARRAY_SIZE(priv->bo.gem_handles); i++) {
90                 if (!priv->bo.gem_handles[i])
91                         continue;
92                 gem_close.handle = priv->bo.gem_handles[i];
93                 ret = drmIoctl(priv->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
94                 if (ret)
95                         ALOGE("Failed to close gem handle %d", ret);
96         }
97
98         free(priv);
99 }
100
101 static int
102 hwc_import_set_priv(hwc_import_context *ctx, buffer_handle_t handle, struct importer_priv *priv)
103 {
104         int ret;
105         const gralloc_module_t *g = ctx->gralloc_module;
106
107         return g->perform(g, GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle, free_priv, priv);
108 }
109
110 static struct importer_priv *
111 hwc_import_get_priv(hwc_import_context *ctx, buffer_handle_t handle)
112 {
113         int ret;
114         void *priv = NULL;
115         const gralloc_module_t *g = ctx->gralloc_module;
116
117         ret = g->perform(g, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE, handle, free_priv, &priv);
118         return ret ? NULL : (struct importer_priv *)priv;
119 }
120
121 int hwc_import_bo_create(int fd, hwc_import_context *ctx,
122                         buffer_handle_t handle, struct hwc_drm_bo *bo)
123 {
124         int ret = 0;
125         const gralloc_module_t *g = ctx->gralloc_module;
126
127         /* Get imported bo that is cached in gralloc buffer, or create a new one. */
128         struct importer_priv *priv = hwc_import_get_priv(ctx, handle);
129         if (!priv) {
130                 priv = (struct importer_priv *)calloc(1, sizeof(*priv));
131                 if (!priv)
132                         return -ENOMEM;
133                 priv->drm_fd = fd;
134
135                 ret = g->perform(g, GRALLOC_MODULE_PERFORM_DRM_IMPORT, fd, handle, &priv->bo);
136                 if (ret) {
137                         ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
138                         free_priv(priv);
139                         return ret;
140                 }
141
142                 ret = drmModeAddFB2(fd, priv->bo.width, priv->bo.height,
143                                     priv->bo.format, priv->bo.gem_handles,
144                                     priv->bo.pitches, priv->bo.offsets,
145                                     &priv->bo.fb_id, 0);
146                 if (ret) {
147                         ALOGE("Failed to add fb %d", ret);
148                         free_priv(priv);
149                         return ret;
150                 }
151
152                 ret = hwc_import_set_priv(ctx, handle, priv);
153                 if (ret) {
154                         /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
155                          * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
156                          * only one of which should be used by drm_hwcomposer). */
157                         ALOGE("Failed to register free callback for imported buffer %d", ret);
158                         free_priv(priv);
159                         return ret;
160                 }
161         }
162         *bo = priv->bo;
163         return ret;
164 }
165
166 bool hwc_import_bo_release(int fd, hwc_import_context *ctx,
167                         struct hwc_drm_bo *bo)
168 {
169         /* hwc may not close the gem handles, we own them */
170         return false;
171 }