Merge branch 'xa_branch'
[mesa.git] / src / gallium / state_trackers / gbm / gbm_drm.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 #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 static INLINE enum pipe_format
39 gbm_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
53 static INLINE uint
54 gbm_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
70 static int
71 gbm_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
92 static void
93 gbm_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
101 static struct gbm_bo *
102 gbm_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
139 static struct gbm_bo *
140 gbm_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
188 static void
189 gbm_gallium_drm_destroy(struct gbm_device *gbm)
190 {
191 struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
192
193 gdrm->screen->destroy(gdrm->screen);
194
195 FREE(gdrm->base.driver_name);
196
197 FREE(gdrm);
198 }
199
200 struct gbm_device *
201 gbm_gallium_drm_device_create(int fd)
202 {
203 struct gbm_gallium_drm_device *gdrm;
204 int ret;
205
206 gdrm = calloc(1, sizeof *gdrm);
207
208 gdrm->base.base.fd = fd;
209 gdrm->base.base.bo_create = gbm_gallium_drm_bo_create;
210 gdrm->base.base.bo_create_from_egl_image =
211 gbm_gallium_drm_bo_create_from_egl_image;
212 gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy;
213 gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported;
214 gdrm->base.base.destroy = gbm_gallium_drm_destroy;
215
216 gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM;
217 gdrm->base.base.name = "drm";
218
219 ret = gallium_screen_create(gdrm);
220 if (ret) {
221 free(gdrm);
222 return NULL;
223 }
224
225 return &gdrm->base.base;
226 }