2 * Mesa 3-D graphics library
4 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
26 #include <X11/Xutil.h>
27 #include "util/u_memory.h"
28 #include "util/u_math.h"
29 #include "util/u_format.h"
30 #include "pipe/p_compiler.h"
31 #include "util/u_inlines.h"
32 #include "state_tracker/xlib_sw_winsys.h"
33 #include "util/u_debug.h"
36 #include "common/native_helper.h"
37 #include "native_x11.h"
38 #include "x11_screen.h"
40 struct ximage_display
{
41 struct native_display base
;
45 const struct native_event_handler
*event_handler
;
47 struct x11_screen
*xscr
;
50 struct ximage_config
*configs
;
54 struct ximage_surface
{
55 struct native_surface base
;
57 enum pipe_format color_format
;
59 struct ximage_display
*xdpy
;
61 unsigned int server_stamp
;
62 unsigned int client_stamp
;
64 struct resource_surface
*rsurf
;
65 struct xlib_drawable xdraw
;
68 struct ximage_config
{
69 struct native_config base
;
70 const XVisualInfo
*visual
;
73 static INLINE
struct ximage_display
*
74 ximage_display(const struct native_display
*ndpy
)
76 return (struct ximage_display
*) ndpy
;
79 static INLINE
struct ximage_surface
*
80 ximage_surface(const struct native_surface
*nsurf
)
82 return (struct ximage_surface
*) nsurf
;
85 static INLINE
struct ximage_config
*
86 ximage_config(const struct native_config
*nconf
)
88 return (struct ximage_config
*) nconf
;
92 * Update the geometry of the surface. This is a slow functions.
95 ximage_surface_update_geometry(struct native_surface
*nsurf
)
97 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
101 unsigned int w
, h
, border
, depth
;
103 ok
= XGetGeometry(xsurf
->xdpy
->dpy
, xsurf
->drawable
,
104 &root
, &x
, &y
, &w
, &h
, &border
, &depth
);
105 if (ok
&& resource_surface_set_size(xsurf
->rsurf
, w
, h
))
106 xsurf
->server_stamp
++;
110 * Update the buffers of the surface.
113 ximage_surface_update_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
115 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
117 if (xsurf
->client_stamp
!= xsurf
->server_stamp
) {
118 ximage_surface_update_geometry(&xsurf
->base
);
119 xsurf
->client_stamp
= xsurf
->server_stamp
;
122 return resource_surface_add_resources(xsurf
->rsurf
, buffer_mask
);
126 * Emulate an invalidate event.
129 ximage_surface_invalidate(struct native_surface
*nsurf
)
131 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
132 struct ximage_display
*xdpy
= xsurf
->xdpy
;
134 xsurf
->server_stamp
++;
135 xdpy
->event_handler
->invalid_surface(&xdpy
->base
,
136 &xsurf
->base
, xsurf
->server_stamp
);
140 ximage_surface_flush_frontbuffer(struct native_surface
*nsurf
)
142 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
145 ret
= resource_surface_present(xsurf
->rsurf
,
146 NATIVE_ATTACHMENT_FRONT_LEFT
, (void *) &xsurf
->xdraw
);
147 /* force buffers to be updated in next validation call */
148 ximage_surface_invalidate(&xsurf
->base
);
154 ximage_surface_swap_buffers(struct native_surface
*nsurf
)
156 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
159 ret
= resource_surface_present(xsurf
->rsurf
,
160 NATIVE_ATTACHMENT_BACK_LEFT
, (void *) &xsurf
->xdraw
);
162 resource_surface_swap_buffers(xsurf
->rsurf
,
163 NATIVE_ATTACHMENT_FRONT_LEFT
, NATIVE_ATTACHMENT_BACK_LEFT
, TRUE
);
164 /* the front/back buffers have been swapped */
165 ximage_surface_invalidate(&xsurf
->base
);
171 ximage_surface_present(struct native_surface
*nsurf
,
172 const struct native_present_control
*ctrl
)
176 if (ctrl
->preserve
|| ctrl
->swap_interval
)
179 switch (ctrl
->natt
) {
180 case NATIVE_ATTACHMENT_FRONT_LEFT
:
181 ret
= ximage_surface_flush_frontbuffer(nsurf
);
183 case NATIVE_ATTACHMENT_BACK_LEFT
:
184 ret
= ximage_surface_swap_buffers(nsurf
);
195 ximage_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
196 unsigned int *seq_num
, struct pipe_resource
**textures
,
197 int *width
, int *height
)
199 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
202 if (!ximage_surface_update_buffers(&xsurf
->base
, attachment_mask
))
206 *seq_num
= xsurf
->client_stamp
;
209 resource_surface_get_resources(xsurf
->rsurf
, textures
, attachment_mask
);
211 resource_surface_get_size(xsurf
->rsurf
, &w
, &h
);
221 ximage_surface_wait(struct native_surface
*nsurf
)
223 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
224 XSync(xsurf
->xdpy
->dpy
, FALSE
);
225 /* TODO XGetImage and update the front texture */
229 ximage_surface_destroy(struct native_surface
*nsurf
)
231 struct ximage_surface
*xsurf
= ximage_surface(nsurf
);
233 resource_surface_destroy(xsurf
->rsurf
);
237 static struct ximage_surface
*
238 ximage_display_create_surface(struct native_display
*ndpy
,
240 const struct native_config
*nconf
)
242 struct ximage_display
*xdpy
= ximage_display(ndpy
);
243 struct ximage_config
*xconf
= ximage_config(nconf
);
244 struct ximage_surface
*xsurf
;
246 xsurf
= CALLOC_STRUCT(ximage_surface
);
251 xsurf
->color_format
= xconf
->base
.color_format
;
252 xsurf
->drawable
= drawable
;
254 xsurf
->rsurf
= resource_surface_create(xdpy
->base
.screen
,
256 PIPE_BIND_RENDER_TARGET
|
257 PIPE_BIND_SAMPLER_VIEW
|
258 PIPE_BIND_DISPLAY_TARGET
|
265 xsurf
->drawable
= drawable
;
266 xsurf
->visual
= *xconf
->visual
;
267 /* initialize the geometry */
268 ximage_surface_update_geometry(&xsurf
->base
);
270 xsurf
->xdraw
.visual
= xsurf
->visual
.visual
;
271 xsurf
->xdraw
.depth
= xsurf
->visual
.depth
;
272 xsurf
->xdraw
.drawable
= xsurf
->drawable
;
274 xsurf
->base
.destroy
= ximage_surface_destroy
;
275 xsurf
->base
.present
= ximage_surface_present
;
276 xsurf
->base
.validate
= ximage_surface_validate
;
277 xsurf
->base
.wait
= ximage_surface_wait
;
282 static struct native_surface
*
283 ximage_display_create_window_surface(struct native_display
*ndpy
,
284 EGLNativeWindowType win
,
285 const struct native_config
*nconf
)
287 struct ximage_surface
*xsurf
;
289 xsurf
= ximage_display_create_surface(ndpy
, (Drawable
) win
, nconf
);
290 return (xsurf
) ? &xsurf
->base
: NULL
;
293 static enum pipe_format
294 get_pixmap_format(struct native_display
*ndpy
, EGLNativePixmapType pix
)
296 struct ximage_display
*xdpy
= ximage_display(ndpy
);
297 enum pipe_format fmt
;
300 depth
= x11_drawable_get_depth(xdpy
->xscr
, (Drawable
) pix
);
304 fmt
= PIPE_FORMAT_B8G8R8A8_UNORM
;
307 fmt
= PIPE_FORMAT_B8G8R8X8_UNORM
;
310 fmt
= PIPE_FORMAT_B5G6R5_UNORM
;
313 fmt
= PIPE_FORMAT_NONE
;
320 static struct native_surface
*
321 ximage_display_create_pixmap_surface(struct native_display
*ndpy
,
322 EGLNativePixmapType pix
,
323 const struct native_config
*nconf
)
325 struct ximage_surface
*xsurf
;
327 /* find the config */
329 struct ximage_display
*xdpy
= ximage_display(ndpy
);
330 enum pipe_format fmt
= get_pixmap_format(&xdpy
->base
, pix
);
333 if (fmt
!= PIPE_FORMAT_NONE
) {
334 for (i
= 0; i
< xdpy
->num_configs
; i
++) {
335 if (xdpy
->configs
[i
].base
.color_format
== fmt
) {
336 nconf
= &xdpy
->configs
[i
].base
;
346 xsurf
= ximage_display_create_surface(ndpy
, (Drawable
) pix
, nconf
);
347 return (xsurf
) ? &xsurf
->base
: NULL
;
350 static enum pipe_format
351 choose_format(const XVisualInfo
*vinfo
)
353 enum pipe_format fmt
;
354 /* TODO elaborate the formats */
355 switch (vinfo
->depth
) {
357 fmt
= PIPE_FORMAT_B8G8R8A8_UNORM
;
360 fmt
= PIPE_FORMAT_B8G8R8X8_UNORM
;
363 fmt
= PIPE_FORMAT_B5G6R5_UNORM
;
366 fmt
= PIPE_FORMAT_NONE
;
373 static const struct native_config
**
374 ximage_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
376 struct ximage_display
*xdpy
= ximage_display(ndpy
);
377 const struct native_config
**configs
;
381 if (!xdpy
->configs
) {
382 const XVisualInfo
*visuals
;
383 int num_visuals
, count
;
385 visuals
= x11_screen_get_visuals(xdpy
->xscr
, &num_visuals
);
390 * Create two configs for each visual.
391 * One with depth/stencil buffer; one without
393 xdpy
->configs
= CALLOC(num_visuals
* 2, sizeof(*xdpy
->configs
));
398 for (i
= 0; i
< num_visuals
; i
++) {
399 struct ximage_config
*xconf
= &xdpy
->configs
[count
];
401 xconf
->visual
= &visuals
[i
];
402 xconf
->base
.color_format
= choose_format(xconf
->visual
);
403 if (xconf
->base
.color_format
== PIPE_FORMAT_NONE
)
406 xconf
->base
.buffer_mask
=
407 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
408 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
410 xconf
->base
.window_bit
= TRUE
;
411 xconf
->base
.pixmap_bit
= TRUE
;
413 xconf
->base
.native_visual_id
= xconf
->visual
->visualid
;
414 #if defined(__cplusplus) || defined(c_plusplus)
415 xconf
->base
.native_visual_type
= xconf
->visual
->c_class
;
417 xconf
->base
.native_visual_type
= xconf
->visual
->class;
423 xdpy
->num_configs
= count
;
426 configs
= MALLOC(xdpy
->num_configs
* sizeof(*configs
));
428 for (i
= 0; i
< xdpy
->num_configs
; i
++)
429 configs
[i
] = (const struct native_config
*) &xdpy
->configs
[i
];
431 *num_configs
= xdpy
->num_configs
;
437 ximage_display_get_pixmap_format(struct native_display
*ndpy
,
438 EGLNativePixmapType pix
,
439 enum pipe_format
*format
)
441 struct ximage_display
*xdpy
= ximage_display(ndpy
);
443 *format
= get_pixmap_format(&xdpy
->base
, pix
);
445 return (*format
!= PIPE_FORMAT_NONE
);
449 ximage_display_copy_to_pixmap(struct native_display
*ndpy
,
450 EGLNativePixmapType pix
,
451 struct pipe_resource
*src
)
453 /* fast path to avoid unnecessary allocation and resource_copy_region */
454 if (src
->bind
& PIPE_BIND_DISPLAY_TARGET
) {
455 struct ximage_display
*xdpy
= ximage_display(ndpy
);
456 enum pipe_format fmt
= get_pixmap_format(&xdpy
->base
, pix
);
457 const struct ximage_config
*xconf
= NULL
;
458 struct xlib_drawable xdraw
;
461 if (fmt
== PIPE_FORMAT_NONE
|| src
->format
!= fmt
)
464 for (i
= 0; i
< xdpy
->num_configs
; i
++) {
465 if (xdpy
->configs
[i
].base
.color_format
== fmt
) {
466 xconf
= &xdpy
->configs
[i
];
473 memset(&xdraw
, 0, sizeof(xdraw
));
474 xdraw
.visual
= xconf
->visual
->visual
;
475 xdraw
.depth
= xconf
->visual
->depth
;
476 xdraw
.drawable
= (Drawable
) pix
;
478 xdpy
->base
.screen
->flush_frontbuffer(xdpy
->base
.screen
,
479 src
, 0, 0, &xdraw
, NULL
);
484 return native_display_copy_to_pixmap(ndpy
, pix
, src
);
488 ximage_display_get_param(struct native_display
*ndpy
,
489 enum native_param_type param
)
494 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
495 /* private buffers are allocated */
498 case NATIVE_PARAM_PRESERVE_BUFFER
:
499 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
509 ximage_display_destroy(struct native_display
*ndpy
)
511 struct ximage_display
*xdpy
= ximage_display(ndpy
);
517 x11_screen_destroy(xdpy
->xscr
);
519 XCloseDisplay(xdpy
->dpy
);
524 ximage_display_init_screen(struct native_display
*ndpy
)
526 struct ximage_display
*xdpy
= ximage_display(ndpy
);
527 struct sw_winsys
*winsys
;
529 winsys
= xlib_create_sw_winsys(xdpy
->dpy
);
534 xdpy
->event_handler
->new_sw_screen(&xdpy
->base
, winsys
);
535 if (!xdpy
->base
.screen
) {
537 winsys
->destroy(winsys
);
544 struct native_display
*
545 x11_create_ximage_display(Display
*dpy
,
546 const struct native_event_handler
*event_handler
)
548 struct ximage_display
*xdpy
;
550 xdpy
= CALLOC_STRUCT(ximage_display
);
556 xdpy
->dpy
= XOpenDisplay(NULL
);
561 xdpy
->own_dpy
= TRUE
;
564 xdpy
->event_handler
= event_handler
;
566 xdpy
->xscr_number
= DefaultScreen(xdpy
->dpy
);
567 xdpy
->xscr
= x11_screen_create(xdpy
->dpy
, xdpy
->xscr_number
);
570 XCloseDisplay(xdpy
->dpy
);
575 xdpy
->base
.init_screen
= ximage_display_init_screen
;
576 xdpy
->base
.destroy
= ximage_display_destroy
;
577 xdpy
->base
.get_param
= ximage_display_get_param
;
579 xdpy
->base
.get_configs
= ximage_display_get_configs
;
580 xdpy
->base
.get_pixmap_format
= ximage_display_get_pixmap_format
;
581 xdpy
->base
.copy_to_pixmap
= ximage_display_copy_to_pixmap
;
582 xdpy
->base
.create_window_surface
= ximage_display_create_window_surface
;
583 xdpy
->base
.create_pixmap_surface
= ximage_display_create_pixmap_surface
;