OSDN Git Service

drm_hwcomposer: add GLES compositor
[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 #include <cutils/log.h>
19 #include <hardware/gralloc.h>
20
21 #include <stdlib.h>
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   struct hwc_import_context *import_ctx = (struct hwc_import_context *)calloc(1, sizeof(*import_ctx));
34   if (!ctx) {
35     ALOGE("Failed to allocate gralloc import context");
36     return -ENOMEM;
37   }
38
39   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
40                       (const hw_module_t **)&import_ctx->gralloc_module);
41   if (ret) {
42     ALOGE("Failed to open gralloc module");
43     free(import_ctx);
44     return ret;
45   }
46
47   if (!strcasecmp(import_ctx->gralloc_module->common.author, "NVIDIA"))
48     ALOGW("Using non-NVIDIA gralloc module: %s\n",
49           import_ctx->gralloc_module->common.name);
50
51   *ctx = import_ctx;
52
53   return 0;
54 }
55
56 int hwc_import_destroy(struct hwc_import_context *ctx) {
57   free(ctx);
58   return 0;
59 }
60
61 struct importer_priv {
62   int drm_fd;
63   struct hwc_drm_bo bo;
64 };
65
66 static void free_priv(void *p) {
67   struct importer_priv *priv = (struct importer_priv *)p;
68   if (priv->bo.fb_id) {
69     int ret = drmModeRmFB(priv->drm_fd, priv->bo.fb_id);
70     if (ret)
71       ALOGE("Failed to rm fb %d", ret);
72   }
73
74   struct drm_gem_close gem_close;
75   memset(&gem_close, 0, sizeof(gem_close));
76   for (int i = 0; i < ARRAY_SIZE(priv->bo.gem_handles); i++) {
77     if (!priv->bo.gem_handles[i])
78       continue;
79     gem_close.handle = priv->bo.gem_handles[i];
80     int ret = drmIoctl(priv->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
81     if (ret)
82       ALOGE("Failed to close gem handle %d", ret);
83   }
84
85   free(priv);
86 }
87
88 static int hwc_import_set_priv(hwc_import_context *ctx, buffer_handle_t handle,
89                                struct importer_priv *priv) {
90   const gralloc_module_t *g = ctx->gralloc_module;
91   return g->perform(g, GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle,
92                     free_priv, priv);
93 }
94
95 static struct importer_priv *hwc_import_get_priv(hwc_import_context *ctx,
96                                                  buffer_handle_t handle) {
97   const gralloc_module_t *g = ctx->gralloc_module;
98   void *priv = NULL;
99   int ret = g->perform(g, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE, handle,
100                    free_priv, &priv);
101   return ret ? NULL : (struct importer_priv *)priv;
102 }
103
104 int hwc_import_bo_create(int fd, hwc_import_context *ctx,
105                          buffer_handle_t handle, struct hwc_drm_bo *bo) {
106   /* Get imported bo that is cached in gralloc buffer, or create a new one. */
107   struct importer_priv *priv = hwc_import_get_priv(ctx, handle);
108   if (priv) {
109     *bo = priv->bo;
110     return 0;
111   }
112
113   priv = (struct importer_priv *)calloc(1, sizeof(*priv));
114   if (!priv)
115     return -ENOMEM;
116   priv->drm_fd = fd;
117
118   const gralloc_module_t *g = ctx->gralloc_module;
119   int ret =
120       g->perform(g, GRALLOC_MODULE_PERFORM_DRM_IMPORT, fd, handle, &priv->bo);
121   if (ret) {
122     ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
123     free_priv(priv);
124     return ret;
125   }
126
127   ret = drmModeAddFB2(fd, priv->bo.width, priv->bo.height, priv->bo.format,
128                       priv->bo.gem_handles, priv->bo.pitches,
129                       priv->bo.offsets, &priv->bo.fb_id, 0);
130   if (ret) {
131     ALOGE("Failed to add fb %d", ret);
132     free_priv(priv);
133     return ret;
134   }
135
136   ret = hwc_import_set_priv(ctx, handle, priv);
137   if (ret) {
138     /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
139      * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
140      * only one of which should be used by drm_hwcomposer). */
141     ALOGE("Failed to register free callback for imported buffer %d", ret);
142     free_priv(priv);
143     return ret;
144   }
145   *bo = priv->bo;
146   return ret;
147 }
148
149 bool hwc_import_bo_release(int fd, hwc_import_context *ctx,
150                            struct hwc_drm_bo *bo) {
151   /* hwc may not close the gem handles, we own them */
152   return false;
153 }