summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/egl/common/native_wayland_drm_bufmgr.c
blob: 1603a3a71e24689592d942b4e2831fba45fe3985 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include <stdint.h>
#include <string.h>

#include "native.h"
#include "util/u_inlines.h"
#include "state_tracker/drm_driver.h"

#ifdef HAVE_WAYLAND_BACKEND

#include <wayland-server.h>
#include <wayland-drm-server-protocol.h>

#include "native_wayland_drm_bufmgr.h"

#include "wayland-drm.h"

struct wayland_drm_bufmgr {
   struct native_display_wayland_bufmgr base;

   struct wl_drm *wl_server_drm;
   char *device_name;

   void *user_data;

   wayland_drm_bufmgr_authenticate_func authenticate;
};

static INLINE struct wayland_drm_bufmgr *
wayland_drm_bufmgr(const struct native_display_wayland_bufmgr *base)
{
   return (struct wayland_drm_bufmgr *) base;
}

static int
wayland_drm_bufmgr_authenticate(void *user_data, uint32_t magic)
{
   struct native_display *ndpy = user_data;
   struct wayland_drm_bufmgr *bufmgr;

   bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);

   return bufmgr->authenticate(user_data, magic);
}

static void
wayland_drm_bufmgr_reference_buffer(void *user_data, uint32_t name, int fd,
                                    struct wl_drm_buffer *buffer)
{
   struct native_display *ndpy = user_data;
   struct pipe_resource templ;
   struct winsys_handle wsh;
   enum pipe_format pf;

   switch (buffer->format) {
   case WL_DRM_FORMAT_ARGB8888:
      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
      break;
   case WL_DRM_FORMAT_XRGB8888:
      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
      break;
   default:
      pf = PIPE_FORMAT_NONE;
      break;
   }

   if (pf == PIPE_FORMAT_NONE)
      return;

   memset(&templ, 0, sizeof(templ));
   templ.target = PIPE_TEXTURE_2D;
   templ.format = pf;
   templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
   templ.width0 = buffer->buffer.width;
   templ.height0 = buffer->buffer.height;
   templ.depth0 = 1;
   templ.array_size = 1;

   memset(&wsh, 0, sizeof(wsh));
   wsh.handle = name;
   wsh.stride = buffer->stride[0];

   buffer->driver_buffer =
      ndpy->screen->resource_from_handle(ndpy->screen, &templ, &wsh);
}

static void
wayland_drm_bufmgr_unreference_buffer(void *user_data,
                                      struct wl_drm_buffer *buffer)
{
   struct pipe_resource *resource = buffer->driver_buffer;

   pipe_resource_reference(&resource, NULL);
}

static struct wayland_drm_callbacks wl_drm_callbacks = {
   wayland_drm_bufmgr_authenticate,
   wayland_drm_bufmgr_reference_buffer,
   wayland_drm_bufmgr_unreference_buffer
};

static boolean
wayland_drm_bufmgr_bind_display(struct native_display *ndpy,
                                struct wl_display *wl_dpy)
{
   struct wayland_drm_bufmgr *bufmgr;

   bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);

   if (bufmgr->wl_server_drm)
      return FALSE;

   bufmgr->wl_server_drm = wayland_drm_init(wl_dpy, bufmgr->device_name,
         &wl_drm_callbacks, ndpy, 0);

   if (!bufmgr->wl_server_drm)
      return FALSE;

   return TRUE;
}

static boolean
wayland_drm_bufmgr_unbind_display(struct native_display *ndpy,
                                  struct wl_display *wl_dpy)
{
   struct wayland_drm_bufmgr *bufmgr;

   bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);

   if (!bufmgr->wl_server_drm)
      return FALSE;

   wayland_drm_uninit(bufmgr->wl_server_drm);
   bufmgr->wl_server_drm = NULL;

   return TRUE;
}

static struct pipe_resource *
wayland_drm_bufmgr_wl_buffer_get_resource(struct native_display *ndpy,
                                          struct wl_buffer *buffer)
{
   return wayland_drm_buffer_get_buffer(buffer);
}

static EGLBoolean
wayland_drm_bufmgr_query_buffer(struct native_display *ndpy,
                                struct wl_buffer *_buffer,
                                EGLint attribute, EGLint *value)
{
   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
   struct pipe_resource *resource = buffer->driver_buffer;

   if (!wayland_buffer_is_drm(&buffer->buffer))
      return EGL_FALSE;

   switch (attribute) {
   case EGL_TEXTURE_FORMAT:
      switch (resource->format) {
      case PIPE_FORMAT_B8G8R8A8_UNORM:
         *value = EGL_TEXTURE_RGBA;
         return EGL_TRUE;
      case PIPE_FORMAT_B8G8R8X8_UNORM:
         *value = EGL_TEXTURE_RGB;
         return EGL_TRUE;
      default:
         return EGL_FALSE;
      }
   case EGL_WIDTH:
      *value = buffer->buffer.width;
      return EGL_TRUE;
   case EGL_HEIGHT:
      *value = buffer->buffer.height;
      return EGL_TRUE;
   default:
      return EGL_FALSE;
   }
}


struct native_display_wayland_bufmgr *
wayland_drm_bufmgr_create(wayland_drm_bufmgr_authenticate_func authenticate,
                          void *user_data, char *device_name)
{
   struct wayland_drm_bufmgr *bufmgr;

   bufmgr = calloc(1, sizeof *bufmgr);
   if (!bufmgr)
      return NULL;

   bufmgr->user_data = user_data;
   bufmgr->authenticate = authenticate;
   bufmgr->device_name = strdup(device_name);

   bufmgr->base.bind_display = wayland_drm_bufmgr_bind_display;
   bufmgr->base.unbind_display = wayland_drm_bufmgr_unbind_display;
   bufmgr->base.buffer_get_resource = wayland_drm_bufmgr_wl_buffer_get_resource;
   bufmgr->base.query_buffer = wayland_drm_bufmgr_query_buffer;

   return &bufmgr->base;
}

void
wayland_drm_bufmgr_destroy(struct native_display_wayland_bufmgr *_bufmgr)
{
   struct wayland_drm_bufmgr *bufmgr = wayland_drm_bufmgr(_bufmgr);

   if (!bufmgr)
      return;

   free(bufmgr->device_name);
   free(bufmgr);
}

#endif