gbm_drm.c revision 2023bf996ed5c3797233b8d70670c28e15bdff75
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#include "util/u_memory.h"
29#include "util/u_inlines.h"
30
31#include "state_tracker/drm_driver.h"
32
33#include <unistd.h>
34#include <sys/types.h>
35
36#include "gbm_gallium_drmint.h"
37
38/* For importing wl_buffer */
39#if HAVE_WAYLAND_PLATFORM
40#include "../../../egl/wayland/wayland-drm/wayland-drm.h"
41#endif
42
43static INLINE enum pipe_format
44gbm_format_to_gallium(enum gbm_bo_format format)
45{
46   switch (format) {
47   case GBM_BO_FORMAT_XRGB8888:
48      return PIPE_FORMAT_B8G8R8X8_UNORM;
49   case GBM_BO_FORMAT_ARGB8888:
50      return PIPE_FORMAT_B8G8R8A8_UNORM;
51   default:
52      return PIPE_FORMAT_NONE;
53   }
54
55   return PIPE_FORMAT_NONE;
56}
57
58static INLINE uint
59gbm_usage_to_gallium(uint usage)
60{
61   uint resource_usage = 0;
62
63   if (usage & GBM_BO_USE_SCANOUT)
64      resource_usage |= PIPE_BIND_SCANOUT;
65
66   if (usage & GBM_BO_USE_RENDERING)
67      resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
68
69   if (usage & GBM_BO_USE_CURSOR_64X64)
70      resource_usage |= PIPE_BIND_CURSOR;
71
72   return resource_usage;
73}
74
75static int
76gbm_gallium_drm_is_format_supported(struct gbm_device *gbm,
77                                    enum gbm_bo_format format,
78                                    uint32_t usage)
79{
80   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
81   enum pipe_format pf;
82
83   pf = gbm_format_to_gallium(format);
84   if (pf == PIPE_FORMAT_NONE)
85      return 0;
86
87   if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0,
88                                          gbm_usage_to_gallium(usage)))
89      return 0;
90
91   if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888)
92      return 0;
93
94   return 1;
95}
96
97static void
98gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo)
99{
100   struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo);
101
102   pipe_resource_reference(&bo->resource, NULL);
103   free(bo);
104}
105
106static struct gbm_bo *
107gbm_gallium_drm_bo_import(struct gbm_device *gbm,
108                          uint32_t type, void *buffer, uint32_t usage)
109{
110   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
111   struct gbm_gallium_drm_bo *bo;
112   struct winsys_handle whandle;
113   struct pipe_resource *resource;
114
115   switch (type) {
116#if HAVE_WAYLAND_PLATFORM
117   case GBM_BO_IMPORT_WL_BUFFER:
118   {
119      struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer;
120
121      resource = wb->driver_buffer;
122      break;
123   }
124#endif
125
126   case GBM_BO_IMPORT_EGL_IMAGE:
127      if (!gdrm->lookup_egl_image)
128         return NULL;
129
130      resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, buffer);
131      if (resource == NULL)
132         return NULL;
133      break;
134
135   default:
136      return NULL;
137   }
138
139   bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
140   if (bo == NULL)
141      return NULL;
142
143   bo->base.base.gbm = gbm;
144   bo->base.base.width = resource->width0;
145   bo->base.base.height = resource->height0;
146
147   switch (resource->format) {
148   case PIPE_FORMAT_B8G8R8X8_UNORM:
149      bo->base.base.format = GBM_BO_FORMAT_XRGB8888;
150      break;
151   case PIPE_FORMAT_B8G8R8A8_UNORM:
152      bo->base.base.format = GBM_BO_FORMAT_ARGB8888;
153      break;
154   default:
155      FREE(bo);
156      return NULL;
157   }
158
159   pipe_resource_reference(&bo->resource, resource);
160
161   memset(&whandle, 0, sizeof(whandle));
162   whandle.type = DRM_API_HANDLE_TYPE_KMS;
163   gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
164
165   bo->base.base.handle.u32 = whandle.handle;
166   bo->base.base.stride      = whandle.stride;
167
168   return &bo->base.base;
169}
170
171static struct gbm_bo *
172gbm_gallium_drm_bo_create(struct gbm_device *gbm,
173                          uint32_t width, uint32_t height,
174                          enum gbm_bo_format format, uint32_t usage)
175{
176   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
177   struct gbm_gallium_drm_bo *bo;
178   struct pipe_resource templ;
179   struct winsys_handle whandle;
180   enum pipe_format pf;
181
182   bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
183   if (bo == NULL)
184      return NULL;
185
186   bo->base.base.gbm = gbm;
187   bo->base.base.width = width;
188   bo->base.base.height = height;
189   bo->base.base.format = format;
190
191   pf = gbm_format_to_gallium(format);
192   if (pf == PIPE_FORMAT_NONE)
193      return NULL;
194
195   memset(&templ, 0, sizeof(templ));
196   templ.bind = gbm_usage_to_gallium(usage);
197   templ.format = pf;
198   templ.target = PIPE_TEXTURE_2D;
199   templ.last_level = 0;
200   templ.width0 = width;
201   templ.height0 = height;
202   templ.depth0 = 1;
203   templ.array_size = 1;
204
205   bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ);
206   if (bo->resource == NULL) {
207      FREE(bo);
208      return NULL;
209   }
210
211   memset(&whandle, 0, sizeof(whandle));
212   whandle.type = DRM_API_HANDLE_TYPE_KMS;
213   gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
214
215   bo->base.base.handle.u32 = whandle.handle;
216   bo->base.base.stride      = whandle.stride;
217
218   return &bo->base.base;
219}
220
221static void
222gbm_gallium_drm_destroy(struct gbm_device *gbm)
223{
224   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
225
226   gallium_screen_destroy(gdrm);
227   FREE(gdrm);
228}
229
230struct gbm_device *
231gbm_gallium_drm_device_create(int fd)
232{
233   struct gbm_gallium_drm_device *gdrm;
234   int ret;
235
236   gdrm = calloc(1, sizeof *gdrm);
237
238   gdrm->base.base.fd = fd;
239   gdrm->base.base.bo_create = gbm_gallium_drm_bo_create;
240   gdrm->base.base.bo_import = gbm_gallium_drm_bo_import;
241   gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy;
242   gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported;
243   gdrm->base.base.destroy = gbm_gallium_drm_destroy;
244
245   gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM;
246   gdrm->base.base.name = "drm";
247
248   ret = gallium_screen_create(gdrm);
249   if (ret) {
250      free(gdrm);
251      return NULL;
252   }
253
254   return &gdrm->base.base;
255}
256