commit 5384214
Michael Forney
·
2013-11-17 23:33:48 +0000 UTC
parent 365cdf2
drm: Add fallback dumb buffer support
7 files changed,
+330,
-22
+1,
-1
1@@ -13,7 +13,7 @@ libwld_la_SOURCES = color.c drawable.c font.c
2 libwld_la_LIBADD = $(fontconfig_LIBS) $(freetype_LIBS) $(pixman_LIBS)
3
4 if ENABLE_DRM
5- libwld_la_SOURCES += drm.c
6+ libwld_la_SOURCES += drm.c dumb.c
7 pkginclude_HEADERS += drm.h
8 endif
9
+1,
-0
1@@ -68,6 +68,7 @@ struct wld_drm_context
2 #if WITH_DRM_INTEL
3 extern const struct wld_drm_interface intel_drm;
4 #endif
5+extern const struct wld_drm_interface dumb_drm;
6
7 bool drm_initialize_context(struct wld_drm_context * context, int fd);
8 void drm_finalize_context(struct wld_drm_context * context);
M
drm.c
+7,
-1
1@@ -26,8 +26,9 @@
2
3 const static struct wld_drm_interface * drm_interfaces[] = {
4 #if WITH_DRM_INTEL
5- &intel_drm
6+ &intel_drm,
7 #endif
8+ &dumb_drm
9 };
10
11 static const struct wld_drm_interface * find_drm_interface(int fd)
12@@ -107,6 +108,11 @@ void wld_drm_destroy_context(struct wld_drm_context * drm)
13 free(drm);
14 }
15
16+bool wld_drm_is_dumb(struct wld_drm_context * drm)
17+{
18+ return drm->interface == &dumb_drm;
19+}
20+
21 struct wld_drawable * wld_drm_create_drawable(struct wld_drm_context * drm,
22 uint32_t width, uint32_t height,
23 uint32_t format)
M
drm.h
+3,
-0
1@@ -24,6 +24,7 @@
2 #ifndef WLD_DRM_H
3 #define WLD_DRM_H 1
4
5+#include <stdbool.h>
6 #include <stdint.h>
7
8 struct wld_drm_context;
9@@ -39,6 +40,8 @@ struct wld_drm_context * wld_drm_create_context(int fd);
10 */
11 void wld_drm_destroy_context(struct wld_drm_context * drm);
12
13+bool wld_drm_is_dumb(struct wld_drm_context * drm);
14+
15 /**
16 * Create a new DRM drawable.
17 */
A
dumb.c
+247,
-0
1@@ -0,0 +1,247 @@
2+/* wld: dumb.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * 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 THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, 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 DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#include "pixman.h"
26+#include "pixman-private.h"
27+#include "drm-private.h"
28+
29+#include <fcntl.h>
30+#include <sys/mman.h>
31+#include <xf86drm.h>
32+
33+#include <errno.h>
34+
35+struct dumb_context
36+{
37+ struct wld_pixman_context * pixman;
38+ int fd;
39+};
40+
41+struct dumb_drawable
42+{
43+ struct pixman_drawable pixman;
44+ struct dumb_context * context;
45+ uint32_t handle;
46+};
47+
48+/* DRM implementation */
49+static bool dumb_device_supported(uint32_t vendor_id, uint32_t device_id);
50+static struct dumb_context * dumb_create_context(int drm_fd);
51+static void dumb_destroy_context(struct dumb_context * context);
52+static struct wld_drawable * dumb_create_drawable
53+ (struct dumb_context * context, uint32_t width, uint32_t height,
54+ uint32_t format);
55+static struct wld_drawable * dumb_import
56+ (struct dumb_context * context, uint32_t width, uint32_t height,
57+ uint32_t format, int prime_fd, unsigned long pitch);
58+static struct wld_drawable * dumb_import_gem
59+ (struct dumb_context * context, uint32_t width, uint32_t height,
60+ uint32_t format, uint32_t gem_name, unsigned long pitch);
61+
62+/* DRM drawable */
63+static int dumb_export(struct wld_drawable * drawable);
64+static uint32_t dumb_get_handle(struct wld_drawable * drawable);
65+
66+static struct drm_draw_interface dumb_draw = {
67+ .export = &dumb_export,
68+ .get_handle = &dumb_get_handle
69+};
70+static bool dumb_draw_initialized;
71+
72+const struct wld_drm_interface dumb_drm = {
73+ .device_supported = &dumb_device_supported,
74+ .create_context = (drm_create_context_func_t) &dumb_create_context,
75+ .destroy_context = (drm_destroy_context_func_t) &dumb_destroy_context,
76+ .create_drawable = (drm_create_drawable_func_t) &dumb_create_drawable,
77+ .import = (drm_import_func_t) &dumb_import,
78+ .import_gem = (drm_import_gem_func_t) &dumb_import_gem,
79+};
80+
81+bool dumb_device_supported(uint32_t vendor_id, uint32_t device_id)
82+{
83+ return true;
84+}
85+
86+struct dumb_context * dumb_create_context(int drm_fd)
87+{
88+ struct dumb_context * context;
89+
90+ if (!(context = malloc(sizeof *context)))
91+ goto error0;
92+
93+ if (!(context->pixman = wld_pixman_create_context()))
94+ goto error1;
95+
96+ context->fd = drm_fd;
97+
98+ if (!dumb_draw_initialized)
99+ {
100+ dumb_draw.base = pixman_draw;
101+ dumb_draw_initialized = true;
102+ }
103+
104+ return context;
105+
106+ error1:
107+ free(context);
108+ error0:
109+ return NULL;
110+}
111+
112+void dumb_destroy_context(struct dumb_context * context)
113+{
114+ wld_pixman_destroy_context(context->pixman);
115+ free(context);
116+}
117+
118+static struct wld_drawable * new_drawable(struct dumb_context * context,
119+ uint32_t width, uint32_t height,
120+ uint32_t format, uint32_t handle,
121+ unsigned long pitch)
122+{
123+ struct dumb_drawable * drawable;
124+ struct drm_mode_map_dumb map_dumb_arg = { .handle = handle };
125+ void * data;
126+ size_t size = pitch * height;
127+ int ret;
128+
129+ if (!(drawable = malloc(sizeof *drawable)))
130+ goto error0;
131+
132+ ret = drmIoctl(context->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_arg);
133+
134+ if (ret != 0)
135+ goto error1;
136+
137+ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, context->fd,
138+ map_dumb_arg.offset);
139+
140+ if (data == MAP_FAILED)
141+ goto error1;
142+
143+ if (!pixman_initialize_drawable(context->pixman, &drawable->pixman,
144+ width, height, data, pitch, format))
145+ {
146+ goto error2;
147+ }
148+
149+ drawable->pixman.base.interface = (struct wld_draw_interface *) &dumb_draw;
150+ drawable->context = context;
151+ drawable->handle = handle;
152+
153+ return &drawable->pixman.base;
154+
155+ error2:
156+ munmap(data, size);
157+ error1:
158+ free(drawable);
159+ error0:
160+ return NULL;
161+}
162+
163+struct wld_drawable * dumb_create_drawable
164+ (struct dumb_context * context, uint32_t width, uint32_t height,
165+ uint32_t format)
166+{
167+ struct wld_drawable * drawable;
168+ struct drm_mode_create_dumb create_dumb_arg = {
169+ .height = height, .width = width,
170+ .bpp = format_bytes_per_pixel(format) * 8,
171+ };
172+ int ret;
173+
174+ ret = drmIoctl(context->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb_arg);
175+
176+ if (ret != 0)
177+ goto error0;
178+
179+ drawable = new_drawable(context, width, height, format,
180+ create_dumb_arg.handle, create_dumb_arg.pitch);
181+
182+ if (!drawable)
183+ goto error1;
184+
185+ return drawable;
186+
187+ error1:
188+ {
189+ struct drm_mode_destroy_dumb destroy_dumb_arg = {
190+ .handle = create_dumb_arg.handle
191+ };
192+
193+ drmIoctl(context->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb_arg);
194+ }
195+ error0:
196+ return NULL;
197+}
198+
199+struct wld_drawable * dumb_import(struct dumb_context * context,
200+ uint32_t width, uint32_t height,
201+ uint32_t format,
202+ int prime_fd, unsigned long pitch)
203+{
204+ int ret;
205+ uint32_t handle;
206+
207+ ret = drmPrimeFDToHandle(context->fd, prime_fd, &handle);
208+
209+ if (ret != 0)
210+ goto error0;
211+
212+ return new_drawable(context, width, height, format, handle, pitch);
213+
214+ error0:
215+ return NULL;
216+}
217+
218+struct wld_drawable * dumb_import_gem(struct dumb_context * context,
219+ uint32_t width, uint32_t height,
220+ uint32_t format,
221+ uint32_t gem_name, unsigned long pitch)
222+{
223+ DEBUG("dumb: import_gem is not supported\n");
224+
225+ return NULL;
226+}
227+
228+static int dumb_export(struct wld_drawable * drawable)
229+{
230+ struct dumb_drawable * dumb = (void *) drawable;
231+ int prime_fd, ret;
232+
233+ ret = drmPrimeHandleToFD(dumb->context->fd, dumb->handle,
234+ DRM_CLOEXEC, &prime_fd);
235+
236+ if (ret != 0)
237+ return -1;
238+
239+ return prime_fd;
240+}
241+
242+static uint32_t dumb_get_handle(struct wld_drawable * drawable)
243+{
244+ struct dumb_drawable * dumb = (void *) drawable;
245+
246+ return dumb->handle;
247+}
248+
+46,
-0
1@@ -0,0 +1,46 @@
2+/* wld: pixman-private.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * 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 THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, 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 DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef WLD_PIXMAN_PRIVATE_H
26+#define WLD_PIXMAN_PRIVATE_H
27+
28+#include "wld.h"
29+
30+struct wld_pixman_context;
31+
32+struct pixman_drawable
33+{
34+ struct wld_drawable base;
35+ pixman_image_t * image;
36+ struct wld_pixman_context * context;
37+};
38+
39+extern const struct wld_draw_interface pixman_draw;
40+
41+bool pixman_initialize_drawable
42+ (struct wld_pixman_context * context, struct pixman_drawable * drawable,
43+ uint32_t width, uint32_t height,
44+ void * data, uint32_t pitch, uint32_t format);
45+
46+#endif
47+
M
pixman.c
+25,
-20
1@@ -22,6 +22,7 @@
2 */
3
4 #include "pixman.h"
5+#include "pixman-private.h"
6 #include "wld-private.h"
7
8 #define PIXMAN_COLOR(c) { \
9@@ -36,13 +37,6 @@ struct wld_pixman_context
10 pixman_glyph_cache_t * glyph_cache;
11 };
12
13-struct pixman_drawable
14-{
15- struct wld_drawable base;
16- pixman_image_t * image;
17- struct wld_pixman_context * context;
18-};
19-
20 static void pixman_fill_rectangle(struct wld_drawable * drawable,
21 uint32_t color, int32_t x, int32_t y,
22 uint32_t width, uint32_t height);
23@@ -68,7 +62,7 @@ static pixman_image_t * pixman_map(struct wld_drawable * drawable);
24 static void pixman_flush(struct wld_drawable * drawable);
25 static void pixman_destroy(struct wld_drawable * drawable);
26
27-const static struct wld_draw_interface pixman_draw = {
28+const struct wld_draw_interface pixman_draw = {
29 .fill_rectangle = &pixman_fill_rectangle,
30 .fill_region = &pixman_fill_region,
31 .copy_rectangle = &pixman_copy_rectangle,
32@@ -100,6 +94,25 @@ void wld_pixman_destroy_context(struct wld_pixman_context * context)
33 free(context);
34 }
35
36+bool pixman_initialize_drawable
37+ (struct wld_pixman_context * context, struct pixman_drawable * drawable,
38+ uint32_t width, uint32_t height,
39+ void * data, uint32_t pitch, uint32_t format)
40+{
41+ drawable->base.interface = &pixman_draw;
42+ drawable->base.width = width;
43+ drawable->base.height = height;
44+ drawable->base.format = format;
45+ drawable->base.pitch = pitch;
46+
47+ drawable->context = context;
48+ drawable->image = pixman_image_create_bits(pixman_format(format),
49+ width, height,
50+ (uint32_t *) data, pitch);
51+
52+ return drawable->image != NULL;
53+}
54+
55 struct wld_drawable * wld_pixman_create_drawable
56 (struct wld_pixman_context * context, uint32_t width, uint32_t height,
57 void * data, uint32_t pitch, uint32_t format)
58@@ -111,19 +124,11 @@ struct wld_drawable * wld_pixman_create_drawable
59 if (!pixman)
60 goto error0;
61
62- pixman->base.interface = &pixman_draw;
63- pixman->base.width = width;
64- pixman->base.height = height;
65- pixman->base.format = format;
66- pixman->base.pitch = pitch;
67-
68- pixman->context = context;
69- pixman->image = pixman_image_create_bits(pixman_format(format),
70- width, height,
71- (uint32_t *) data, pitch);
72-
73- if (!pixman->image)
74+ if (!pixman_initialize_drawable(context, pixman, width, height,
75+ data, pitch, format))
76+ {
77 goto error1;
78+ }
79
80 return &pixman->base;
81