• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3  * Copyright (C) 2010-2011 LunarG Inc.
4  * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #define LOG_TAG "GRALLOC-GBM"
26 
27 #include <cutils/log.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <pthread.h>
32 #include <errno.h>
33 
34 #include <hardware/gralloc.h>
35 #include <system/graphics.h>
36 
37 #include <gbm.h>
38 
39 #include "gralloc_drm.h"
40 #include "gralloc_gbm_priv.h"
41 
42 struct gbm_module_t {
43 	gralloc_module_t base;
44 
45 	pthread_mutex_t mutex;
46 	struct gbm_device *gbm;
47 };
48 
49 /*
50  * Initialize the DRM device object
51  */
gbm_init(struct gbm_module_t * dmod)52 static int gbm_init(struct gbm_module_t *dmod)
53 {
54 	int err = 0;
55 
56 	pthread_mutex_lock(&dmod->mutex);
57 	if (!dmod->gbm) {
58 		dmod->gbm = gbm_dev_create();
59 		if (!dmod->gbm)
60 			err = -EINVAL;
61 	}
62 	pthread_mutex_unlock(&dmod->mutex);
63 
64 	return err;
65 }
66 
gbm_mod_perform(const struct gralloc_module_t * mod,int op,...)67 static int gbm_mod_perform(const struct gralloc_module_t *mod, int op, ...)
68 {
69 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
70 	va_list args;
71 	int err;
72 	uint32_t uop = static_cast<uint32_t>(op);
73 
74 	err = gbm_init(dmod);
75 	if (err)
76 		return err;
77 
78 	va_start(args, op);
79 	switch (uop) {
80 	case GRALLOC_MODULE_PERFORM_GET_DRM_FD:
81 		{
82 			int *fd = va_arg(args, int *);
83 			*fd = gbm_device_get_fd(dmod->gbm);
84 			err = 0;
85 		}
86 		break;
87 	default:
88 		err = -EINVAL;
89 		break;
90 	}
91 	va_end(args);
92 
93 	return err;
94 }
95 
gbm_mod_register_buffer(const gralloc_module_t * mod,buffer_handle_t handle)96 static int gbm_mod_register_buffer(const gralloc_module_t *mod,
97 		buffer_handle_t handle)
98 {
99 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
100 	int err;
101 
102 	err = gbm_init(dmod);
103 	if (err)
104 		return err;
105 
106 	pthread_mutex_lock(&dmod->mutex);
107 	err = gralloc_gbm_handle_register(handle, dmod->gbm);
108 	pthread_mutex_unlock(&dmod->mutex);
109 
110 	return err;
111 }
112 
gbm_mod_unregister_buffer(const gralloc_module_t * mod,buffer_handle_t handle)113 static int gbm_mod_unregister_buffer(const gralloc_module_t *mod,
114 		buffer_handle_t handle)
115 {
116 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
117 	int err;
118 
119 	pthread_mutex_lock(&dmod->mutex);
120 	err = gralloc_gbm_handle_unregister(handle);
121 	pthread_mutex_unlock(&dmod->mutex);
122 
123 	return err;
124 }
125 
gbm_mod_lock(const gralloc_module_t * mod,buffer_handle_t handle,int usage,int x,int y,int w,int h,void ** ptr)126 static int gbm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle,
127 		int usage, int x, int y, int w, int h, void **ptr)
128 {
129 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
130 	int err;
131 
132 	pthread_mutex_lock(&dmod->mutex);
133 
134 	err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, ptr);
135 	ALOGV("buffer %p lock usage = %08x", handle, usage);
136 
137 	pthread_mutex_unlock(&dmod->mutex);
138 	return err;
139 }
140 
gbm_mod_unlock(const gralloc_module_t * mod,buffer_handle_t handle)141 static int gbm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle)
142 {
143 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
144 	int err;
145 
146 	pthread_mutex_lock(&dmod->mutex);
147 	err = gralloc_gbm_bo_unlock(handle);
148 	pthread_mutex_unlock(&dmod->mutex);
149 
150 	return err;
151 }
152 
gbm_mod_close_gpu0(struct hw_device_t * dev)153 static int gbm_mod_close_gpu0(struct hw_device_t *dev)
154 {
155 	struct gbm_module_t *dmod = (struct gbm_module_t *)dev->module;
156 	struct alloc_device_t *alloc = (struct alloc_device_t *) dev;
157 
158 	gbm_dev_destroy(dmod->gbm);
159 	delete alloc;
160 
161 	return 0;
162 }
163 
gbm_mod_free_gpu0(alloc_device_t * dev,buffer_handle_t handle)164 static int gbm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle)
165 {
166 	struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module;
167 
168 	pthread_mutex_lock(&dmod->mutex);
169 	gbm_free(handle);
170 	native_handle_close(handle);
171 	delete handle;
172 
173 	pthread_mutex_unlock(&dmod->mutex);
174 	return 0;
175 }
176 
gbm_mod_alloc_gpu0(alloc_device_t * dev,int w,int h,int format,int usage,buffer_handle_t * handle,int * stride)177 static int gbm_mod_alloc_gpu0(alloc_device_t *dev,
178 		int w, int h, int format, int usage,
179 		buffer_handle_t *handle, int *stride)
180 {
181 	struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module;
182 	int err = 0;
183 
184 	pthread_mutex_lock(&dmod->mutex);
185 
186 	*handle = gralloc_gbm_bo_create(dmod->gbm, w, h, format, usage, stride);
187 	if (!*handle)
188 		err = -errno;
189 
190 	ALOGV("buffer %p usage = %08x", *handle, usage);
191 	pthread_mutex_unlock(&dmod->mutex);
192 	return err;
193 }
194 
gbm_mod_open_gpu0(struct gbm_module_t * dmod,hw_device_t ** dev)195 static int gbm_mod_open_gpu0(struct gbm_module_t *dmod, hw_device_t **dev)
196 {
197 	struct alloc_device_t *alloc;
198 	int err;
199 
200 	err = gbm_init(dmod);
201 	if (err)
202 		return err;
203 
204 	alloc = new alloc_device_t();
205 	if (!alloc)
206 		return -EINVAL;
207 
208 	alloc->common.tag = HARDWARE_DEVICE_TAG;
209 	alloc->common.version = 0;
210 	alloc->common.module = &dmod->base.common;
211 	alloc->common.close = gbm_mod_close_gpu0;
212 
213 	alloc->alloc = gbm_mod_alloc_gpu0;
214 	alloc->free = gbm_mod_free_gpu0;
215 
216 	*dev = &alloc->common;
217 
218 	return 0;
219 }
220 
gbm_mod_open(const struct hw_module_t * mod,const char * name,struct hw_device_t ** dev)221 static int gbm_mod_open(const struct hw_module_t *mod,
222 		const char *name, struct hw_device_t **dev)
223 {
224 	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
225 	int err;
226 
227 	if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0)
228 		err = gbm_mod_open_gpu0(dmod, dev);
229 	else
230 		err = -EINVAL;
231 
232 	return err;
233 }
234 
235 static struct hw_module_methods_t gbm_mod_methods = {
236 	.open = gbm_mod_open
237 };
238 
239 struct gbm_module_t HAL_MODULE_INFO_SYM = {
240 	.base = {
241 		.common = {
242 			.tag = HARDWARE_MODULE_TAG,
243 			.version_major = 1,
244 			.version_minor = 0,
245 			.id = GRALLOC_HARDWARE_MODULE_ID,
246 			.name = "GBM Memory Allocator",
247 			.author = "Rob Herring - Linaro",
248 			.methods = &gbm_mod_methods
249 		},
250 		.registerBuffer = gbm_mod_register_buffer,
251 		.unregisterBuffer = gbm_mod_unregister_buffer,
252 		.lock = gbm_mod_lock,
253 		.unlock = gbm_mod_unlock,
254 		.perform = gbm_mod_perform
255 	},
256 
257 	.mutex = PTHREAD_MUTEX_INITIALIZER,
258 	.gbm = NULL,
259 };
260