gbm_drm.c revision b52a0f22813c8e09747ece41173c21f22d4fc369
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
38static INLINE enum pipe_format
39gbm_format_to_gallium(enum gbm_bo_format format)
40{
41   switch (format) {
42   case GBM_BO_FORMAT_XRGB8888:
43      return PIPE_FORMAT_B8G8R8X8_UNORM;
44   case GBM_BO_FORMAT_ARGB8888:
45      return PIPE_FORMAT_B8G8R8A8_UNORM;
46   default:
47      return PIPE_FORMAT_NONE;
48   }
49
50   return PIPE_FORMAT_NONE;
51}
52
53static INLINE uint
54gbm_usage_to_gallium(uint usage)
55{
56   uint resource_usage = 0;
57
58   if (usage & GBM_BO_USE_SCANOUT)
59      resource_usage |= PIPE_BIND_SCANOUT;
60
61   if (usage & GBM_BO_USE_RENDERING)
62      resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
63
64   if (usage & GBM_BO_USE_CURSOR_64X64)
65      resource_usage |= PIPE_BIND_CURSOR;
66
67   return resource_usage;
68}
69
70static int
71gbm_gallium_drm_is_format_supported(struct gbm_device *gbm,
72                                    enum gbm_bo_format format,
73                                    uint32_t usage)
74{
75   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
76   enum pipe_format pf;
77
78   pf = gbm_format_to_gallium(format);
79   if (pf == PIPE_FORMAT_NONE)
80      return 0;
81
82   if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0,
83                                          gbm_usage_to_gallium(usage)))
84      return 0;
85
86   if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888)
87      return 0;
88
89   return 1;
90}
91
92static void
93gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo)
94{
95   struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo);
96
97   pipe_resource_reference(&bo->resource, NULL);
98   free(bo);
99}
100
101static struct gbm_bo *
102gbm_gallium_drm_bo_create_from_egl_image(struct gbm_device *gbm,
103                                         void *egl_dpy, void *egl_image,
104                                         uint32_t width, uint32_t height,
105                                         uint32_t usage)
106{
107   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
108   struct gbm_gallium_drm_bo *bo;
109   struct winsys_handle whandle;
110
111   if (!gdrm->lookup_egl_image)
112      return NULL;
113
114   bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
115   if (bo == NULL)
116      return NULL;
117
118   bo->resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data,
119                                         egl_image);
120   if (bo->resource == NULL) {
121      FREE(bo);
122      return NULL;
123   }
124
125   bo->base.base.gbm = gbm;
126   bo->base.base.width = width;
127   bo->base.base.height = height;
128
129   memset(&whandle, 0, sizeof(whandle));
130   whandle.type = DRM_API_HANDLE_TYPE_KMS;
131   gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
132
133   bo->base.base.handle.u32 = whandle.handle;
134   bo->base.base.pitch      = whandle.stride;
135
136   return &bo->base.base;
137}
138
139static struct gbm_bo *
140gbm_gallium_drm_bo_create(struct gbm_device *gbm,
141                          uint32_t width, uint32_t height,
142                          enum gbm_bo_format format, uint32_t usage)
143{
144   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
145   struct gbm_gallium_drm_bo *bo;
146   struct pipe_resource templ;
147   struct winsys_handle whandle;
148   enum pipe_format pf;
149
150   bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
151   if (bo == NULL)
152      return NULL;
153
154   bo->base.base.gbm = gbm;
155   bo->base.base.width = width;
156   bo->base.base.height = height;
157
158   pf = gbm_format_to_gallium(format);
159   if (pf == PIPE_FORMAT_NONE)
160      return NULL;
161
162   memset(&templ, 0, sizeof(templ));
163   templ.bind = gbm_usage_to_gallium(usage);
164   templ.format = pf;
165   templ.target = PIPE_TEXTURE_2D;
166   templ.last_level = 0;
167   templ.width0 = width;
168   templ.height0 = height;
169   templ.depth0 = 1;
170   templ.array_size = 1;
171
172   bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ);
173   if (bo->resource == NULL) {
174      FREE(bo);
175      return NULL;
176   }
177
178   memset(&whandle, 0, sizeof(whandle));
179   whandle.type = DRM_API_HANDLE_TYPE_KMS;
180   gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
181
182   bo->base.base.handle.u32 = whandle.handle;
183   bo->base.base.pitch      = whandle.stride;
184
185   return &bo->base.base;
186}
187
188static void
189gbm_gallium_drm_destroy(struct gbm_device *gbm)
190{
191   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
192
193   gallium_screen_destroy(gdrm);
194   FREE(gdrm);
195}
196
197struct gbm_device *
198gbm_gallium_drm_device_create(int fd)
199{
200   struct gbm_gallium_drm_device *gdrm;
201   int ret;
202
203   gdrm = calloc(1, sizeof *gdrm);
204
205   gdrm->base.base.fd = fd;
206   gdrm->base.base.bo_create = gbm_gallium_drm_bo_create;
207   gdrm->base.base.bo_create_from_egl_image =
208      gbm_gallium_drm_bo_create_from_egl_image;
209   gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy;
210   gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported;
211   gdrm->base.base.destroy = gbm_gallium_drm_destroy;
212
213   gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM;
214   gdrm->base.base.name = "drm";
215
216   ret = gallium_screen_create(gdrm);
217   if (ret) {
218      free(gdrm);
219      return NULL;
220   }
221
222   return &gdrm->base.base;
223}
224