2 * Mesa 3-D graphics library
5 * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 #include "util/u_memory.h"
27 #include "util/u_inlines.h"
29 #include "pipe/p_compiler.h"
30 #include "pipe/p_screen.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "state_tracker/drm_driver.h"
36 #include "native_wayland.h"
38 static const struct native_event_handler
*wayland_event_handler
;
41 sync_callback(void *data
)
49 force_roundtrip(struct wl_display
*display
)
53 wl_display_sync_callback(display
, sync_callback
, &done
);
54 wl_display_iterate(display
, WL_DISPLAY_WRITABLE
);
56 wl_display_iterate(display
, WL_DISPLAY_READABLE
);
59 static const struct native_config
**
60 wayland_display_get_configs (struct native_display
*ndpy
, int *num_configs
)
62 struct wayland_display
*display
= wayland_display(ndpy
);
63 const struct native_config
**configs
;
66 if (!display
->config
) {
67 struct native_config
*nconf
;
68 display
->config
= CALLOC(2, sizeof(*display
->config
));
72 for (i
= 0; i
< 2; ++i
) {
73 nconf
= &display
->config
[i
].base
;
76 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
77 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
79 nconf
->window_bit
= TRUE
;
80 nconf
->pixmap_bit
= TRUE
;
83 display
->config
[0].base
.color_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
84 display
->config
[1].base
.color_format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
87 configs
= MALLOC(2 * sizeof(*configs
));
89 configs
[0] = &display
->config
[0].base
;
90 configs
[1] = &display
->config
[1].base
;
99 wayland_display_get_param(struct native_display
*ndpy
,
100 enum native_param_type param
)
105 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
106 case NATIVE_PARAM_PRESERVE_BUFFER
:
107 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
117 wayland_display_get_pixmap_format(struct native_display
*ndpy
,
118 EGLNativePixmapType pix
,
119 enum pipe_format
*format
)
121 /* all wl_egl_pixmaps are supported */
122 *format
= PIPE_FORMAT_NONE
;
128 wayland_pixmap_destroy(struct wl_egl_pixmap
*egl_pixmap
)
130 struct pipe_resource
*resource
= egl_pixmap
->driver_private
;
134 pipe_resource_reference(&resource
, NULL
);
135 if (egl_pixmap
->buffer
) {
136 wl_buffer_destroy(egl_pixmap
->buffer
);
137 egl_pixmap
->buffer
= NULL
;
140 egl_pixmap
->driver_private
= NULL
;
141 egl_pixmap
->destroy
= NULL
;
145 wayland_pixmap_surface_initialize(struct wayland_surface
*surface
)
147 struct wayland_display
*display
= wayland_display(&surface
->display
->base
);
148 const enum native_attachment front_natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
150 if (surface
->pix
->buffer
!= NULL
)
153 surface
->pix
->buffer
= display
->create_buffer(display
, surface
, front_natt
);
154 surface
->pix
->destroy
= wayland_pixmap_destroy
;
155 surface
->pix
->driver_private
=
156 resource_surface_get_single_resource(surface
->rsurf
, front_natt
);
160 wayland_release_pending_resource(void *data
)
162 struct wayland_surface
*surface
= data
;
164 /* FIXME: print internal error */
165 if (!surface
->pending_resource
)
168 pipe_resource_reference(&surface
->pending_resource
, NULL
);
172 wayland_window_surface_handle_resize(struct wayland_surface
*surface
)
174 struct wayland_display
*display
= surface
->display
;
175 struct pipe_resource
*front_resource
;
176 const enum native_attachment front_natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
179 front_resource
= resource_surface_get_single_resource(surface
->rsurf
,
181 if (resource_surface_set_size(surface
->rsurf
,
182 surface
->win
->width
, surface
->win
->height
)) {
184 if (surface
->pending_resource
)
185 force_roundtrip(display
->dpy
);
187 if (front_resource
) {
188 surface
->pending_resource
= front_resource
;
189 front_resource
= NULL
;
190 wl_display_sync_callback(display
->dpy
,
191 wayland_release_pending_resource
, surface
);
194 for (i
= 0; i
< WL_BUFFER_COUNT
; ++i
) {
195 if (surface
->buffer
[i
])
196 wl_buffer_destroy(surface
->buffer
[i
]);
197 surface
->buffer
[i
] = NULL
;
200 surface
->dx
= surface
->win
->dx
;
201 surface
->dy
= surface
->win
->dy
;
203 pipe_resource_reference(&front_resource
, NULL
);
207 wayland_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
208 unsigned int *seq_num
, struct pipe_resource
**textures
,
209 int *width
, int *height
)
211 struct wayland_surface
*surface
= wayland_surface(nsurf
);
213 if (surface
->type
== WL_WINDOW_SURFACE
)
214 wayland_window_surface_handle_resize(surface
);
216 if (!resource_surface_add_resources(surface
->rsurf
, attachment_mask
|
217 surface
->attachment_mask
))
221 resource_surface_get_resources(surface
->rsurf
, textures
, attachment_mask
);
224 *seq_num
= surface
->sequence_number
;
226 resource_surface_get_size(surface
->rsurf
, (uint
*) width
, (uint
*) height
);
228 if (surface
->type
== WL_PIXMAP_SURFACE
)
229 wayland_pixmap_surface_initialize(surface
);
235 wayland_frame_callback(struct wl_surface
*surf
, void *data
, uint32_t time
)
237 struct wayland_surface
*surface
= data
;
239 surface
->block_swap_buffers
= FALSE
;
243 wayland_buffers_swap(struct wl_buffer
**buffer
,
244 enum wayland_buffer_type buf1
,
245 enum wayland_buffer_type buf2
)
247 struct wl_buffer
*tmp
= buffer
[buf1
];
248 buffer
[buf1
] = buffer
[buf2
];
253 wayland_surface_swap_buffers(struct native_surface
*nsurf
)
255 struct wayland_surface
*surface
= wayland_surface(nsurf
);
256 struct wayland_display
*display
= surface
->display
;
258 while (surface
->block_swap_buffers
)
259 wl_display_iterate(display
->dpy
, WL_DISPLAY_READABLE
);
261 surface
->block_swap_buffers
= TRUE
;
262 wl_display_frame_callback(display
->dpy
, surface
->win
->surface
,
263 wayland_frame_callback
, surface
);
265 if (surface
->type
== WL_WINDOW_SURFACE
) {
266 resource_surface_swap_buffers(surface
->rsurf
,
267 NATIVE_ATTACHMENT_FRONT_LEFT
,
268 NATIVE_ATTACHMENT_BACK_LEFT
, FALSE
);
270 wayland_buffers_swap(surface
->buffer
, WL_BUFFER_FRONT
, WL_BUFFER_BACK
);
272 if (surface
->buffer
[WL_BUFFER_FRONT
] == NULL
)
273 surface
->buffer
[WL_BUFFER_FRONT
] =
274 display
->create_buffer(display
, surface
,
275 NATIVE_ATTACHMENT_FRONT_LEFT
);
277 wl_surface_attach(surface
->win
->surface
, surface
->buffer
[WL_BUFFER_FRONT
],
278 surface
->dx
, surface
->dy
);
280 resource_surface_get_size(surface
->rsurf
,
281 (uint
*) &surface
->win
->attached_width
,
282 (uint
*) &surface
->win
->attached_height
);
287 surface
->sequence_number
++;
288 wayland_event_handler
->invalid_surface(&display
->base
,
290 surface
->sequence_number
);
296 wayland_surface_present(struct native_surface
*nsurf
,
297 enum native_attachment natt
,
301 struct wayland_surface
*surface
= wayland_surface(nsurf
);
305 if (preserve
|| swap_interval
)
309 case NATIVE_ATTACHMENT_FRONT_LEFT
:
312 case NATIVE_ATTACHMENT_BACK_LEFT
:
313 ret
= wayland_surface_swap_buffers(nsurf
);
320 if (surface
->type
== WL_WINDOW_SURFACE
) {
321 resource_surface_get_size(surface
->rsurf
, &width
, &height
);
322 wl_buffer_damage(surface
->buffer
[WL_BUFFER_FRONT
], 0, 0, width
, height
);
323 wl_surface_damage(surface
->win
->surface
, 0, 0, width
, height
);
330 wayland_surface_wait(struct native_surface
*nsurf
)
336 wayland_surface_destroy(struct native_surface
*nsurf
)
338 struct wayland_surface
*surface
= wayland_surface(nsurf
);
339 enum wayland_buffer_type buffer
;
341 for (buffer
= 0; buffer
< WL_BUFFER_COUNT
; ++buffer
) {
342 if (surface
->buffer
[buffer
])
343 wl_buffer_destroy(surface
->buffer
[buffer
]);
346 resource_surface_destroy(surface
->rsurf
);
352 static struct native_surface
*
353 wayland_create_pixmap_surface(struct native_display
*ndpy
,
354 EGLNativePixmapType pix
,
355 const struct native_config
*nconf
)
357 struct wayland_display
*display
= wayland_display(ndpy
);
358 struct wayland_surface
*surface
;
359 struct wl_egl_pixmap
*egl_pixmap
= (struct wl_egl_pixmap
*) pix
;
360 enum native_attachment natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
361 uint bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
|
362 PIPE_BIND_DISPLAY_TARGET
| PIPE_BIND_SCANOUT
;
364 surface
= CALLOC_STRUCT(wayland_surface
);
368 surface
->display
= display
;
370 surface
->pending_resource
= NULL
;
371 surface
->type
= WL_PIXMAP_SURFACE
;
372 surface
->pix
= egl_pixmap
;
375 surface
->color_format
= nconf
->color_format
;
376 else /* FIXME: derive format from wl_visual */
377 surface
->color_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
379 surface
->attachment_mask
= (1 << NATIVE_ATTACHMENT_FRONT_LEFT
);
381 surface
->rsurf
= resource_surface_create(display
->base
.screen
,
382 surface
->color_format
, bind
);
384 if (!surface
->rsurf
) {
389 resource_surface_set_size(surface
->rsurf
,
390 egl_pixmap
->width
, egl_pixmap
->height
);
392 /* the pixmap is already allocated, so import it */
393 if (surface
->pix
->buffer
!= NULL
)
394 resource_surface_import_resource(surface
->rsurf
, natt
,
395 surface
->pix
->driver_private
);
397 surface
->base
.destroy
= wayland_surface_destroy
;
398 surface
->base
.present
= wayland_surface_present
;
399 surface
->base
.validate
= wayland_surface_validate
;
400 surface
->base
.wait
= wayland_surface_wait
;
402 return &surface
->base
;
406 static struct native_surface
*
407 wayland_create_window_surface(struct native_display
*ndpy
,
408 EGLNativeWindowType win
,
409 const struct native_config
*nconf
)
411 struct wayland_display
*display
= wayland_display(ndpy
);
412 struct wayland_config
*config
= wayland_config(nconf
);
413 struct wayland_surface
*surface
;
414 uint bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
|
415 PIPE_BIND_DISPLAY_TARGET
| PIPE_BIND_SCANOUT
;
417 surface
= CALLOC_STRUCT(wayland_surface
);
421 surface
->display
= display
;
422 surface
->color_format
= config
->base
.color_format
;
424 surface
->win
= (struct wl_egl_window
*) win
;
426 surface
->pending_resource
= NULL
;
427 surface
->block_swap_buffers
= FALSE
;
428 surface
->type
= WL_WINDOW_SURFACE
;
430 surface
->buffer
[WL_BUFFER_FRONT
] = NULL
;
431 surface
->buffer
[WL_BUFFER_BACK
] = NULL
;
432 surface
->attachment_mask
= (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
433 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
435 surface
->rsurf
= resource_surface_create(display
->base
.screen
,
436 surface
->color_format
, bind
);
438 if (!surface
->rsurf
) {
443 surface
->base
.destroy
= wayland_surface_destroy
;
444 surface
->base
.present
= wayland_surface_present
;
445 surface
->base
.validate
= wayland_surface_validate
;
446 surface
->base
.wait
= wayland_surface_wait
;
448 return &surface
->base
;
451 static struct native_display
*
452 native_create_display(void *dpy
, boolean use_sw
)
454 struct wayland_display
*display
= NULL
;
455 boolean own_dpy
= FALSE
;
457 use_sw
= use_sw
|| debug_get_bool_option("EGL_SOFTWARE", FALSE
);
460 dpy
= wl_display_connect(NULL
);
467 _eglLog(_EGL_INFO
, "use software fallback");
468 display
= wayland_create_shm_display((struct wl_display
*) dpy
,
469 wayland_event_handler
);
471 display
= wayland_create_drm_display((struct wl_display
*) dpy
,
472 wayland_event_handler
);
478 display
->base
.get_param
= wayland_display_get_param
;
479 display
->base
.get_configs
= wayland_display_get_configs
;
480 display
->base
.get_pixmap_format
= wayland_display_get_pixmap_format
;
481 display
->base
.copy_to_pixmap
= native_display_copy_to_pixmap
;
482 display
->base
.create_window_surface
= wayland_create_window_surface
;
483 display
->base
.create_pixmap_surface
= wayland_create_pixmap_surface
;
485 display
->own_dpy
= own_dpy
;
487 return &display
->base
;
490 static const struct native_platform wayland_platform
= {
491 "wayland", /* name */
492 native_create_display
495 const struct native_platform
*
496 native_get_wayland_platform(const struct native_event_handler
*event_handler
)
498 wayland_event_handler
= event_handler
;
499 return &wayland_platform
;
502 /* vim: set sw=3 ts=8 sts=3 expandtab: */