gbm: track buffer format through DRI drivers
[mesa.git] / src / gbm / main / gbm.c
1 /*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Benjamin Franzke <benjaminfranzke@googlemail.com>
26 */
27
28 #define _BSD_SOURCE
29
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdint.h>
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39
40 #include "gbm.h"
41 #include "gbmint.h"
42 #include "common.h"
43 #include "backend.h"
44
45 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
46
47 struct gbm_device *devices[16];
48
49 static int device_num = 0;
50
51 /** Returns the file description for the gbm device
52 *
53 * \return The fd that the struct gbm_device was created with
54 */
55 GBM_EXPORT int
56 gbm_device_get_fd(struct gbm_device *gbm)
57 {
58 return gbm->fd;
59 }
60
61 /* FIXME: maybe superfluous, use udev subclass from the fd? */
62 /** Get the backend name for the given gbm device
63 *
64 * \return The backend name string - this belongs to the device and must not
65 * be freed
66 */
67 GBM_EXPORT const char *
68 gbm_device_get_backend_name(struct gbm_device *gbm)
69 {
70 return gbm->name;
71 }
72
73 /** Test if a format is supported for a given set of usage flags.
74 *
75 * \param gbm The created buffer manager
76 * \param format The format to test
77 * \param usage A bitmask of the usages to test the format against
78 * \return 1 if the format is supported otherwise 0
79 *
80 * \sa enum gbm_bo_flags for the list of flags that the format can be
81 * tested against
82 *
83 * \sa enum gbm_bo_format for the list of formats
84 */
85 int
86 gbm_device_is_format_supported(struct gbm_device *gbm,
87 enum gbm_bo_format format,
88 uint32_t usage)
89 {
90 return gbm->is_format_supported(gbm, format, usage);
91 }
92
93 /** Destroy the gbm device and free all resources associated with it.
94 *
95 * \param gbm The device created using gbm_create_device()
96 */
97 GBM_EXPORT void
98 gbm_device_destroy(struct gbm_device *gbm)
99 {
100 gbm->refcount--;
101 if (gbm->refcount == 0)
102 gbm->destroy(gbm);
103 }
104
105 GBM_EXPORT struct gbm_device *
106 _gbm_mesa_get_device(int fd)
107 {
108 struct gbm_device *gbm = NULL;
109 struct stat buf;
110 dev_t dev;
111 int i;
112
113 if (fd < 0 || fstat(fd, &buf) < 0 || !S_ISCHR(buf.st_mode)) {
114 fprintf(stderr, "_gbm_mesa_get_device: invalid fd: %d\n", fd);
115 return NULL;
116 }
117
118 for (i = 0; i < device_num; ++i) {
119 dev = devices[i]->stat.st_rdev;
120 if (major(dev) == major(buf.st_rdev) &&
121 minor(dev) == minor(buf.st_rdev)) {
122 gbm = devices[i];
123 gbm->refcount++;
124 break;
125 }
126 }
127
128 return gbm;
129 }
130
131 /** Create a gbm device for allocating buffers
132 *
133 * The file descriptor passed in is used by the backend to communicate with
134 * platform for allocating the memory. For allocations using DRI this would be
135 * the file descriptor returned when opening a device such as \c
136 * /dev/dri/card0
137 *
138 * \param fd The file descriptor for an backend specific device
139 * \return The newly created struct gbm_device. The resources associated with
140 * the device should be freed with gbm_device_destroy() when it is no longer
141 * needed. If the creation of the device failed NULL will be returned.
142 */
143 GBM_EXPORT struct gbm_device *
144 gbm_create_device(int fd)
145 {
146 struct gbm_device *gbm = NULL;
147 struct stat buf;
148
149 if (fd < 0 || fstat(fd, &buf) < 0 || !S_ISCHR(buf.st_mode)) {
150 fprintf(stderr, "gbm_create_device: invalid fd: %d\n", fd);
151 return NULL;
152 }
153
154 if (device_num == 0)
155 memset(devices, 0, sizeof devices);
156
157 gbm = _gbm_create_device(fd);
158 if (gbm == NULL)
159 return NULL;
160
161 gbm->dummy = gbm_create_device;
162 gbm->stat = buf;
163 gbm->refcount = 1;
164
165 if (device_num < ARRAY_SIZE(devices)-1)
166 devices[device_num++] = gbm;
167
168 return gbm;
169 }
170
171 /** Get the width of the buffer object
172 *
173 * \param bo The buffer object
174 * \return The width of the allocated buffer object
175 *
176 */
177 GBM_EXPORT unsigned int
178 gbm_bo_get_width(struct gbm_bo *bo)
179 {
180 return bo->width;
181 }
182
183 /** Get the height of the buffer object
184 *
185 * \param bo The buffer object
186 * \return The height of the allocated buffer object
187 */
188 GBM_EXPORT unsigned int
189 gbm_bo_get_height(struct gbm_bo *bo)
190 {
191 return bo->height;
192 }
193
194 /** Get the stride of the buffer object
195 *
196 * This is calculated by the backend when it does the allocation in
197 * gbm_bo_create()
198 *
199 * \param bo The buffer object
200 * \return The stride of the allocated buffer object
201 */
202 GBM_EXPORT uint32_t
203 gbm_bo_get_pitch(struct gbm_bo *bo)
204 {
205 return bo->pitch;
206 }
207
208 /** Get the format of the buffer object
209 *
210 * The format of the pixels in the buffer.
211 *
212 * \param bo The buffer object
213 * \return The format of buffer object, on of the GBM_FORMAT_* codes
214 */
215 GBM_EXPORT uint32_t
216 gbm_bo_get_format(struct gbm_bo *bo)
217 {
218 return bo->format;
219 }
220
221 /** Get the handle of the buffer object
222 *
223 * This is stored in the platform generic union gbm_bo_handle type. However
224 * the format of this handle is platform specific.
225 *
226 * \param bo The buffer object
227 * \return Returns the handle of the allocated buffer object
228 */
229 GBM_EXPORT union gbm_bo_handle
230 gbm_bo_get_handle(struct gbm_bo *bo)
231 {
232 return bo->handle;
233 }
234
235 /**
236 * Destroys the given buffer object and frees all resources associated with
237 * it.
238 *
239 * \param bo The buffer object
240 */
241 GBM_EXPORT void
242 gbm_bo_destroy(struct gbm_bo *bo)
243 {
244 bo->gbm->bo_destroy(bo);
245 }
246
247 /**
248 * Allocate a buffer object for the given dimensions
249 *
250 * \param gbm The gbm device returned from gbm_create_device()
251 * \param width The width for the buffer
252 * \param height The height for the buffer
253 * \param format The format to use for the buffer
254 * \param usage The union of the usage flags for this buffer
255 *
256 * \return A newly allocated buffer that should be freed with gbm_bo_destroy()
257 * when no longer needed. If an error occurs during allocation %NULL will be
258 * returned.
259 *
260 * \sa enum gbm_bo_format for the list of formats
261 * \sa enum gbm_bo_flags for the list of usage flags
262 */
263 GBM_EXPORT struct gbm_bo *
264 gbm_bo_create(struct gbm_device *gbm,
265 uint32_t width, uint32_t height,
266 enum gbm_bo_format format, uint32_t usage)
267 {
268 if (width == 0 || height == 0)
269 return NULL;
270
271 if (usage & GBM_BO_USE_CURSOR_64X64 &&
272 (width != 64 || height != 64))
273 return NULL;
274
275 return gbm->bo_create(gbm, width, height, format, usage);
276 }
277
278 /**
279 * Create a buffer object representing the contents of an EGLImage
280 *
281 * \param gbm The gbm device returned from gbm_create_device()
282 * \param egl_dpy The EGLDisplay on which the EGLImage was created
283 * \param egl_image The EGLImage to create the buffer from
284 * \param width The width to use in the creation of the buffer object
285 * \param height The height to use in the creation of the buffer object
286 * \param usage The union of the usage flags for this buffer
287 *
288 * \return A newly allocated buffer object that should be freed with
289 * gbm_bo_destroy() when no longer needed.
290 *
291 * \sa enum gbm_bo_flags for the list of usage flags
292 *
293 * \note The expectation is that this function will use an efficient method
294 * for making the contents of the EGLImage available as a buffer object.
295 */
296 GBM_EXPORT struct gbm_bo *
297 gbm_bo_create_from_egl_image(struct gbm_device *gbm,
298 void *egl_dpy, void *egl_image,
299 uint32_t width, uint32_t height,
300 uint32_t usage)
301 {
302 if (width == 0 || height == 0)
303 return NULL;
304
305 return gbm->bo_create_from_egl_image(gbm, egl_dpy, egl_image,
306 width, height, usage);
307 }