summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/egl/x11
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/egl/x11')
-rw-r--r--src/gallium/state_trackers/egl/x11/native_dri2.c510
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.c9
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.h7
-rw-r--r--src/gallium/state_trackers/egl/x11/native_ximage.c476
-rw-r--r--src/gallium/state_trackers/egl/x11/sw_winsys.c231
-rw-r--r--src/gallium/state_trackers/egl/x11/sw_winsys.h40
-rw-r--r--src/gallium/state_trackers/egl/x11/x11_screen.c68
-rw-r--r--src/gallium/state_trackers/egl/x11/x11_screen.h10
8 files changed, 675 insertions, 676 deletions
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index 5f2fd412604..98399792311 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -26,6 +26,7 @@
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
+#include "util/u_hash_table.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
@@ -47,12 +48,18 @@ struct dri2_display {
Display *dpy;
boolean own_dpy;
+ struct native_event_handler *event_handler;
+
struct drm_api *api;
struct x11_screen *xscr;
int xscr_number;
+ const char *dri_driver;
+ int dri_major, dri_minor;
struct dri2_config *configs;
int num_configs;
+
+ struct util_hash_table *surfaces;
};
struct dri2_surface {
@@ -62,10 +69,16 @@ struct dri2_surface {
enum pipe_format color_format;
struct dri2_display *dri2dpy;
- struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
- boolean have_back, have_fake;
+ unsigned int server_stamp;
+ unsigned int client_stamp;
int width, height;
- unsigned int sequence_number;
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ uint valid_mask;
+
+ boolean have_back, have_fake;
+
+ struct x11_drawable_buffer *last_xbufs;
+ int last_num_xbufs;
};
struct dri2_config {
@@ -90,110 +103,103 @@ dri2_config(const struct native_config *nconf)
return (struct dri2_config *) nconf;
}
-static boolean
-dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
+/**
+ * Process the buffers returned by the server.
+ */
+static void
+dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
+ struct x11_drawable_buffer *xbufs,
+ int num_xbufs)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+ struct pipe_texture templ;
+ struct winsys_handle whandle;
+ uint valid_mask;
+ int i;
- /* pbuffer is private */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
- return TRUE;
+ /* free the old textures */
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
+ pipe_texture_reference(&dri2surf->textures[i], NULL);
+ dri2surf->valid_mask = 0x0;
- /* copy to real front buffer */
- if (dri2surf->have_fake)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+ dri2surf->have_back = FALSE;
+ dri2surf->have_fake = FALSE;
- return TRUE;
-}
+ if (!xbufs)
+ return;
-static boolean
-dri2_surface_swap_buffers(struct native_surface *nsurf)
-{
- struct dri2_surface *dri2surf = dri2_surface(nsurf);
- struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ templ.depth0 = 1;
+ templ.format = dri2surf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- /* pbuffer is private */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
- return TRUE;
+ valid_mask = 0x0;
+ for (i = 0; i < num_xbufs; i++) {
+ struct x11_drawable_buffer *xbuf = &xbufs[i];
+ const char *desc;
+ enum native_attachment natt;
- /* copy to front buffer */
- if (dri2surf->have_back)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferBackLeft, DRI2BufferFrontLeft);
+ switch (xbuf->attachment) {
+ case DRI2BufferFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Front Buffer";
+ break;
+ case DRI2BufferFakeFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Fake Front Buffer";
+ dri2surf->have_fake = TRUE;
+ break;
+ case DRI2BufferBackLeft:
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ desc = "DRI2 Back Buffer";
+ dri2surf->have_back = TRUE;
+ break;
+ default:
+ desc = NULL;
+ break;
+ }
- /* and update fake front buffer */
- if (dri2surf->have_fake)
- x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
- 0, 0, dri2surf->width, dri2surf->height,
- DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+ if (!desc || dri2surf->textures[natt]) {
+ if (!desc)
+ _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
+ else
+ _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
+ continue;
+ }
- return TRUE;
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.stride = xbuf->pitch;
+ whandle.handle = xbuf->name;
+ dri2surf->textures[natt] = dri2dpy->base.screen->texture_from_handle(
+ dri2dpy->base.screen, &templ, &whandle);
+ if (dri2surf->textures[natt])
+ valid_mask |= 1 << natt;
+ }
+
+ dri2surf->valid_mask = valid_mask;
}
-static boolean
-dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
- unsigned int *seq_num, struct pipe_texture **textures,
- int *width, int *height)
+/**
+ * Get the buffers from the server.
+ */
+static void
+dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
- struct pipe_texture templ;
+ int num_ins, num_outs, att;
struct x11_drawable_buffer *xbufs;
- int num_ins, num_outs, att, i;
-
- if (attachment_mask) {
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D;
- templ.last_level = 0;
- templ.width0 = dri2surf->width;
- templ.height0 = dri2surf->height;
- templ.depth0 = 1;
- templ.format = dri2surf->color_format;
- templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
- if (textures)
- memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
- }
-
- /* create textures for pbuffer */
- if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
- struct pipe_screen *screen = dri2dpy->base.screen;
-
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
-
- /* delay the allocation */
- if (!native_attachment_mask_test(attachment_mask, att))
- continue;
-
- if (!ptex) {
- ptex = screen->texture_create(screen, &templ);
- dri2surf->pbuffer_textures[att] = ptex;
- }
-
- if (textures)
- pipe_texture_reference(&textures[att], ptex);
- }
-
- if (seq_num)
- *seq_num = dri2surf->sequence_number;
- if (width)
- *width = dri2surf->width;
- if (height)
- *height = dri2surf->height;
-
- return TRUE;
- }
/* prepare the attachments */
num_ins = 0;
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- if (native_attachment_mask_test(attachment_mask, att)) {
+ if (native_attachment_mask_test(buffer_mask, att)) {
unsigned int dri2att;
switch (att) {
@@ -220,79 +226,178 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
}
}
- dri2surf->have_back = FALSE;
- dri2surf->have_fake = FALSE;
-
- /* remember old geometry */
- templ.width0 = dri2surf->width;
- templ.height0 = dri2surf->height;
-
xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
&dri2surf->width, &dri2surf->height,
dri2atts, FALSE, num_ins, &num_outs);
- if (!xbufs)
- return FALSE;
- if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
- /* are there cases where the buffers change and the geometry doesn't? */
- dri2surf->sequence_number++;
+ /* we should be able to do better... */
+ if (xbufs && dri2surf->last_num_xbufs == num_outs &&
+ memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
+ free(xbufs);
+ dri2surf->client_stamp = dri2surf->server_stamp;
+ return;
+ }
+
+ dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
+ dri2surf->server_stamp++;
+ dri2surf->client_stamp = dri2surf->server_stamp;
+
+ if (dri2surf->last_xbufs)
+ free(dri2surf->last_xbufs);
+ dri2surf->last_xbufs = xbufs;
+ dri2surf->last_num_xbufs = num_outs;
+}
+
+/**
+ * Update the buffers of the surface. This is a slow function due to the
+ * round-trip to the server.
+ */
+static boolean
+dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* create textures for pbuffer */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
+ struct pipe_screen *screen = dri2dpy->base.screen;
+ struct pipe_texture templ;
+ uint new_valid = 0x0;
+ int att;
+
+ buffer_mask &= ~dri2surf->valid_mask;
+ if (!buffer_mask)
+ return TRUE;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
templ.width0 = dri2surf->width;
templ.height0 = dri2surf->height;
- }
-
- for (i = 0; i < num_outs; i++) {
- struct x11_drawable_buffer *xbuf = &xbufs[i];
- const char *desc;
- enum native_attachment natt;
+ templ.depth0 = 1;
+ templ.format = dri2surf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- switch (xbuf->attachment) {
- case DRI2BufferFrontLeft:
- natt = NATIVE_ATTACHMENT_FRONT_LEFT;
- desc = "DRI2 Front Buffer";
- break;
- case DRI2BufferFakeFrontLeft:
- natt = NATIVE_ATTACHMENT_FRONT_LEFT;
- desc = "DRI2 Fake Front Buffer";
- dri2surf->have_fake = TRUE;
- break;
- case DRI2BufferBackLeft:
- natt = NATIVE_ATTACHMENT_BACK_LEFT;
- desc = "DRI2 Back Buffer";
- dri2surf->have_back = TRUE;
- break;
- default:
- desc = NULL;
- break;
- }
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(buffer_mask, att)) {
+ assert(!dri2surf->textures[att]);
- if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
- (textures && textures[natt])) {
- if (!desc)
- _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
- else if (!native_attachment_mask_test(attachment_mask, natt))
- _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
- else
- _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
- continue;
- }
+ dri2surf->textures[att] = screen->texture_create(screen, &templ);
+ if (!dri2surf->textures[att])
+ break;
- if (textures) {
- struct pipe_texture *ptex =
- dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
- dri2dpy->base.screen, &templ,
- desc, xbuf->pitch, xbuf->name);
- if (ptex) {
- /* the caller owns the textures */
- textures[natt] = ptex;
+ new_valid |= 1 << att;
+ if (new_valid == buffer_mask)
+ break;
}
}
+ dri2surf->valid_mask |= new_valid;
+ /* no need to update the stamps */
+ }
+ else {
+ dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
+ }
+
+ return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
+}
+
+/**
+ * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
+ */
+static INLINE boolean
+dri2_surface_receive_events(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ return (dri2surf->dri2dpy->dri_minor >= 3);
+}
+
+static boolean
+dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to real front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+
+ /* force buffers to be updated in next validation call */
+ if (!dri2_surface_receive_events(&dri2surf->base)) {
+ dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
}
- free(xbufs);
+ return TRUE;
+}
+
+static boolean
+dri2_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to front buffer */
+ if (dri2surf->have_back)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferBackLeft, DRI2BufferFrontLeft);
+
+ /* and update fake front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+
+ /* force buffers to be updated in next validation call */
+ if (!dri2_surface_receive_events(&dri2surf->base)) {
+ dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
+ }
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+
+ if (dri2surf->server_stamp != dri2surf->client_stamp ||
+ (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
+ if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
+ return FALSE;
+ }
if (seq_num)
- *seq_num = dri2surf->sequence_number;
+ *seq_num = dri2surf->client_stamp;
+
+ if (textures) {
+ int att;
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(attachment_mask, att)) {
+ struct pipe_texture *ptex = dri2surf->textures[att];
+
+ textures[att] = NULL;
+ pipe_texture_reference(&textures[att], ptex);
+ }
+ }
+ }
+
if (width)
*width = dri2surf->width;
if (height)
@@ -320,14 +425,21 @@ dri2_surface_destroy(struct native_surface *nsurf)
struct dri2_surface *dri2surf = dri2_surface(nsurf);
int i;
+ if (dri2surf->last_xbufs)
+ free(dri2surf->last_xbufs);
+
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct pipe_texture *ptex = dri2surf->pbuffer_textures[i];
+ struct pipe_texture *ptex = dri2surf->textures[i];
pipe_texture_reference(&ptex, NULL);
}
- if (dri2surf->drawable)
+ if (dri2surf->drawable) {
x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
dri2surf->drawable, FALSE);
+
+ util_hash_table_remove(dri2surf->dri2dpy->surfaces,
+ (void *) dri2surf->drawable);
+ }
free(dri2surf);
}
@@ -345,9 +457,6 @@ dri2_display_create_surface(struct native_display *ndpy,
if (!dri2surf)
return NULL;
- if (drawable)
- x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
-
dri2surf->dri2dpy = dri2dpy;
dri2surf->type = type;
dri2surf->drawable = drawable;
@@ -359,6 +468,15 @@ dri2_display_create_surface(struct native_display *ndpy,
dri2surf->base.validate = dri2_surface_validate;
dri2surf->base.wait = dri2_surface_wait;
+ if (drawable) {
+ x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
+ /* initialize the geometry */
+ dri2_surface_update_buffers(&dri2surf->base, 0x0);
+
+ util_hash_table_set(dri2surf->dri2dpy->surfaces,
+ (void *) dri2surf->drawable, (void *) &dri2surf->base);
+ }
+
return dri2surf;
}
@@ -409,17 +527,17 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
switch (mode->rgbBits) {
case 32:
- formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
break;
case 24:
- formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
- formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
break;
case 16:
- formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
+ formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
break;
@@ -440,12 +558,12 @@ choose_depth_stencil_format(const __GLcontextModes *mode,
break;
case 24:
if (mode->stencilBits) {
- formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
+ formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
}
else {
- formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
+ formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
}
break;
case 16:
@@ -592,6 +710,25 @@ dri2_display_is_pixmap_supported(struct native_display *ndpy,
return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
}
+static int
+dri2_display_get_param(struct native_display *ndpy,
+ enum native_param_type param)
+{
+ int val;
+
+ switch (param) {
+ case NATIVE_PARAM_USE_NATIVE_BUFFER:
+ /* DRI2GetBuffers use the native buffers */
+ val = TRUE;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
static void
dri2_display_destroy(struct native_display *ndpy)
{
@@ -603,6 +740,9 @@ dri2_display_destroy(struct native_display *ndpy)
if (dri2dpy->base.screen)
dri2dpy->base.screen->destroy(dri2dpy->base.screen);
+ if (dri2dpy->surfaces)
+ util_hash_table_destroy(dri2dpy->surfaces);
+
if (dri2dpy->xscr)
x11_screen_destroy(dri2dpy->xscr);
if (dri2dpy->own_dpy)
@@ -612,6 +752,27 @@ dri2_display_destroy(struct native_display *ndpy)
free(dri2dpy);
}
+static void
+dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
+ void *user_data)
+{
+ struct native_display *ndpy = (struct native_display* ) user_data;
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct native_surface *nsurf;
+ struct dri2_surface *dri2surf;
+
+ nsurf = (struct native_surface *)
+ util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
+ if (!nsurf)
+ return;
+
+ dri2surf = dri2_surface(nsurf);
+
+ dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
+}
+
/**
* Initialize DRI2 and pipe screen.
*/
@@ -629,7 +790,17 @@ dri2_display_init_screen(struct native_display *ndpy)
return FALSE;
}
- fd = x11_screen_enable_dri2(dri2dpy->xscr, driver);
+ dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
+ &dri2dpy->dri_major, &dri2dpy->dri_minor);
+ if (!dri2dpy->dri_driver || !driver ||
+ strcmp(dri2dpy->dri_driver, driver) != 0) {
+ _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
+ dri2dpy->dri_driver, dri2dpy->api->name);
+ return FALSE;
+ }
+
+ fd = x11_screen_enable_dri2(dri2dpy->xscr,
+ dri2_display_invalidate_buffers, &dri2dpy->base);
if (fd < 0)
return FALSE;
@@ -644,8 +815,23 @@ dri2_display_init_screen(struct native_display *ndpy)
return TRUE;
}
+static unsigned
+dri2_display_hash_table_hash(void *key)
+{
+ XID drawable = pointer_to_uintptr(key);
+ return (unsigned) drawable;
+}
+
+static int
+dri2_display_hash_table_compare(void *key1, void *key2)
+{
+ return (key1 - key2);
+}
+
struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ struct drm_api *api)
{
struct dri2_display *dri2dpy;
@@ -653,12 +839,8 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
if (!dri2dpy)
return NULL;
+ dri2dpy->event_handler = event_handler;
dri2dpy->api = api;
- if (!dri2dpy->api) {
- _eglLog(_EGL_WARNING, "failed to create DRM API");
- free(dri2dpy);
- return NULL;
- }
dri2dpy->dpy = dpy;
if (!dri2dpy->dpy) {
@@ -682,7 +864,15 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
return NULL;
}
+ dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
+ dri2_display_hash_table_compare);
+ if (!dri2dpy->surfaces) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
dri2dpy->base.destroy = dri2_display_destroy;
+ dri2dpy->base.get_param = dri2_display_get_param;
dri2dpy->base.get_configs = dri2_display_get_configs;
dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c
index 8eb542bd827..c6eb17ab1ac 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.c
+++ b/src/gallium/state_trackers/egl/x11/native_x11.c
@@ -70,7 +70,7 @@ native_create_probe(EGLNativeDisplayType dpy)
xscr = x11_screen_create(xdpy, scr);
if (xscr) {
if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) {
- driver_name = x11_screen_probe_dri2(xscr);
+ driver_name = x11_screen_probe_dri2(xscr, NULL, NULL);
if (driver_name)
nprobe->data = strdup(driver_name);
}
@@ -126,7 +126,8 @@ native_get_name(void)
}
struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
+native_create_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler)
{
struct native_display *ndpy = NULL;
boolean force_sw;
@@ -136,14 +137,14 @@ native_create_display(EGLNativeDisplayType dpy)
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (api && !force_sw) {
- ndpy = x11_create_dri2_display(dpy, api);
+ ndpy = x11_create_dri2_display(dpy, event_handler, api);
}
if (!ndpy) {
EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
_eglLog(level, "use software fallback");
- ndpy = x11_create_ximage_display(dpy, TRUE);
+ ndpy = x11_create_ximage_display(dpy, event_handler);
}
return ndpy;
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h
index 622ddac5df6..1566524926a 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.h
+++ b/src/gallium/state_trackers/egl/x11/native_x11.h
@@ -29,9 +29,12 @@
#include "common/native.h"
struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler);
struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ struct drm_api *api);
#endif /* _NATIVE_X11_H_ */
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c
index 92a62f230e0..e0d12acabe8 100644
--- a/src/gallium/state_trackers/egl/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl/x11/native_ximage.c
@@ -28,17 +28,19 @@
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/extensions/XShm.h>
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "pipe/p_compiler.h"
-#include "util/u_simple_screen.h"
#include "util/u_inlines.h"
-#include "softpipe/sp_winsys.h"
+#include "state_tracker/xlib_sw_winsys.h"
+#include "target-helpers/wrap_screen.h"
+#include "util/u_debug.h"
+#include "softpipe/sp_public.h"
+#include "llvmpipe/lp_public.h"
+#include "cell/ppu/cell_public.h"
#include "egllog.h"
-#include "sw_winsys.h"
#include "native_x11.h"
#include "x11_screen.h"
@@ -53,22 +55,18 @@ struct ximage_display {
Display *dpy;
boolean own_dpy;
+ struct native_event_handler *event_handler;
+
struct x11_screen *xscr;
int xscr_number;
- boolean use_xshm;
-
- struct pipe_winsys *winsys;
struct ximage_config *configs;
int num_configs;
};
struct ximage_buffer {
- XImage *ximage;
-
struct pipe_texture *texture;
- XShmSegmentInfo *shm_info;
- boolean xshm_attached;
+ struct xlib_drawable xdraw;
};
struct ximage_surface {
@@ -79,11 +77,11 @@ struct ximage_surface {
XVisualInfo visual;
struct ximage_display *xdpy;
+ unsigned int server_stamp;
+ unsigned int client_stamp;
int width, height;
- GC gc;
-
struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
- unsigned int sequence_number;
+ uint valid_mask;
};
struct ximage_config {
@@ -117,18 +115,6 @@ ximage_surface_free_buffer(struct native_surface *nsurf,
struct ximage_buffer *xbuf = &xsurf->buffers[which];
pipe_texture_reference(&xbuf->texture, NULL);
-
- if (xbuf->shm_info) {
- if (xbuf->xshm_attached)
- XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info);
- if (xbuf->shm_info->shmaddr != (void *) -1)
- shmdt(xbuf->shm_info->shmaddr);
- if (xbuf->shm_info->shmid != -1)
- shmctl(xbuf->shm_info->shmid, IPC_RMID, 0);
-
- xbuf->shm_info->shmaddr = (void *) -1;
- xbuf->shm_info->shmid = -1;
- }
}
static boolean
@@ -152,40 +138,25 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf,
templ.depth0 = 1;
templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- if (xbuf->shm_info) {
- struct pipe_buffer *pbuf;
- unsigned stride, size;
- void *addr = NULL;
-
- stride = util_format_get_stride(xsurf->color_format, xsurf->width);
- /* alignment should depend on visual? */
- stride = align(stride, 4);
- size = stride * xsurf->height;
-
- /* create and attach shm object */
- xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755);
- if (xbuf->shm_info->shmid != -1) {
- xbuf->shm_info->shmaddr =
- shmat(xbuf->shm_info->shmid, NULL, 0);
- if (xbuf->shm_info->shmaddr != (void *) -1) {
- if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) {
- addr = xbuf->shm_info->shmaddr;
- xbuf->xshm_attached = TRUE;
- }
- }
- }
-
- if (addr) {
- pbuf = screen->user_buffer_create(screen, addr, size);
- if (pbuf) {
- xbuf->texture =
- screen->texture_blanket(screen, &templ, &stride, pbuf);
- pipe_buffer_reference(&pbuf, NULL);
- }
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
+ switch (which) {
+ case NATIVE_ATTACHMENT_FRONT_LEFT:
+ case NATIVE_ATTACHMENT_FRONT_RIGHT:
+ templ.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT;
+ break;
+ case NATIVE_ATTACHMENT_BACK_LEFT:
+ case NATIVE_ATTACHMENT_BACK_RIGHT:
+ templ.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+ break;
+ default:
+ break;
}
}
- else {
- xbuf->texture = screen->texture_create(screen, &templ);
+ xbuf->texture = screen->texture_create(screen, &templ);
+ if (xbuf->texture) {
+ xbuf->xdraw.visual = xsurf->visual.visual;
+ xbuf->xdraw.depth = xsurf->visual.depth;
+ xbuf->xdraw.drawable = xsurf->drawable;
}
/* clean up the buffer if allocation failed */
@@ -195,6 +166,92 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf,
return (xbuf->texture != NULL);
}
+/**
+ * Update the geometry of the surface. Return TRUE if the geometry has changed
+ * since last call.
+ */
+static boolean
+ximage_surface_update_geometry(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ Status ok;
+ Window root;
+ int x, y;
+ unsigned int w, h, border, depth;
+ boolean updated = FALSE;
+
+ /* pbuffer has fixed geometry */
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return FALSE;
+
+ ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
+ &root, &x, &y, &w, &h, &border, &depth);
+ if (ok && (xsurf->width != w || xsurf->height != h)) {
+ xsurf->width = w;
+ xsurf->height = h;
+
+ xsurf->server_stamp++;
+ updated = TRUE;
+ }
+
+ return updated;
+}
+
+static void
+ximage_surface_notify_invalid(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_display *xdpy = xsurf->xdpy;
+
+ xdpy->event_handler->invalid_surface(&xdpy->base,
+ &xsurf->base, xsurf->server_stamp);
+}
+
+/**
+ * Update the buffers of the surface. It is a slow function due to the
+ * round-trip to the server.
+ */
+static boolean
+ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ boolean updated;
+ uint new_valid;
+ int att;
+
+ updated = ximage_surface_update_geometry(&xsurf->base);
+ if (updated) {
+ /* all buffers become invalid */
+ xsurf->valid_mask = 0x0;
+ }
+ else {
+ buffer_mask &= ~xsurf->valid_mask;
+ /* all requested buffers are valid */
+ if (!buffer_mask) {
+ xsurf->client_stamp = xsurf->server_stamp;
+ return TRUE;
+ }
+ }
+
+ new_valid = 0x0;
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(buffer_mask, att)) {
+ /* reallocate the texture */
+ if (!ximage_surface_alloc_buffer(&xsurf->base, att))
+ break;
+
+ new_valid |= (1 << att);
+ if (buffer_mask == new_valid)
+ break;
+ }
+ }
+
+ xsurf->valid_mask |= new_valid;
+ xsurf->client_stamp = xsurf->server_stamp;
+
+ return (new_valid == buffer_mask);
+}
+
static boolean
ximage_surface_draw_buffer(struct native_surface *nsurf,
enum native_attachment which)
@@ -202,43 +259,22 @@ ximage_surface_draw_buffer(struct native_surface *nsurf,
struct ximage_surface *xsurf = ximage_surface(nsurf);
struct ximage_buffer *xbuf = &xsurf->buffers[which];
struct pipe_screen *screen = xsurf->xdpy->base.screen;
- struct pipe_transfer *transfer;
+ struct pipe_surface *psurf;
if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
return TRUE;
- assert(xsurf->drawable && xbuf->ximage && xbuf->texture);
+ assert(xsurf->drawable && xbuf->texture);
- transfer = screen->get_tex_transfer(screen, xbuf->texture,
- 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height);
- if (!transfer)
+ /* what's the cost of surface creation? */
+ psurf = screen->get_tex_surface(screen,
+ xbuf->texture, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ);
+ if (!psurf)
return FALSE;
- xbuf->ximage->bytes_per_line = transfer->stride;
- xbuf->ximage->data = screen->transfer_map(screen, transfer);
- if (!xbuf->ximage->data) {
- screen->tex_transfer_destroy(transfer);
- return FALSE;
- }
-
-
- if (xbuf->shm_info)
- XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
- xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False);
- else
- XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
- xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height);
-
- xbuf->ximage->data = NULL;
- screen->transfer_unmap(screen, transfer);
+ screen->flush_frontbuffer(screen, psurf, &xbuf->xdraw);
- /*
- * softpipe allows the pipe transfer to be re-used, but we don't want to
- * rely on that behavior.
- */
- screen->tex_transfer_destroy(transfer);
-
- XSync(xsurf->xdpy->dpy, FALSE);
+ pipe_surface_reference(&psurf, NULL);
return TRUE;
}
@@ -246,7 +282,16 @@ ximage_surface_draw_buffer(struct native_surface *nsurf,
static boolean
ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
{
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ boolean ret;
+
+ ret = ximage_surface_draw_buffer(&xsurf->base,
+ NATIVE_ATTACHMENT_FRONT_LEFT);
+ /* force buffers to be updated in next validation call */
+ xsurf->server_stamp++;
+ ximage_surface_notify_invalid(&xsurf->base);
+
+ return ret;
}
static boolean
@@ -254,44 +299,26 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
struct ximage_buffer *xfront, *xback, xtmp;
+ boolean ret;
+
+ /* display the back buffer first */
+ ret = ximage_surface_draw_buffer(&xsurf->base,
+ NATIVE_ATTACHMENT_BACK_LEFT);
+ /* force buffers to be updated in next validation call */
+ xsurf->server_stamp++;
+ ximage_surface_notify_invalid(&xsurf->base);
xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
- /* draw the back buffer directly if there is no front buffer */
- if (!xfront->texture)
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
-
- /* swap the buffers */
- xtmp = *xfront;
- *xfront = *xback;
- *xback = xtmp;
-
- /* the front/back textures are swapped */
- xsurf->sequence_number++;
-
- return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
-}
-
-static void
-ximage_surface_update_geometry(struct native_surface *nsurf)
-{
- struct ximage_surface *xsurf = ximage_surface(nsurf);
- Status ok;
- Window root;
- int x, y;
- unsigned int w, h, border, depth;
-
- /* pbuffer has fixed geometry */
- if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
- return;
-
- ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
- &root, &x, &y, &w, &h, &border, &depth);
- if (ok) {
- xsurf->width = w;
- xsurf->height = h;
+ /* skip swapping unless there is a front buffer */
+ if (xfront->texture) {
+ xtmp = *xfront;
+ *xfront = *xback;
+ *xback = xtmp;
}
+
+ return ret;
}
static boolean
@@ -300,44 +327,28 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
int *width, int *height)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
- boolean new_buffers = FALSE;
- int att;
- ximage_surface_update_geometry(&xsurf->base);
+ if (xsurf->client_stamp != xsurf->server_stamp ||
+ (xsurf->valid_mask & attachment_mask) != attachment_mask) {
+ if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask))
+ return FALSE;
+ }
- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[att];
-
- /* delay the allocation */
- if (!native_attachment_mask_test(attachment_mask, att))
- continue;
-
- /* reallocate the texture */
- if (!xbuf->texture ||
- xsurf->width != xbuf->texture->width0 ||
- xsurf->height != xbuf->texture->height0) {
- new_buffers = TRUE;
- if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
- /* update ximage */
- if (xbuf->ximage) {
- xbuf->ximage->width = xsurf->width;
- xbuf->ximage->height = xsurf->height;
- }
- }
- }
+ if (seq_num)
+ *seq_num = xsurf->client_stamp;
- if (textures) {
- textures[att] = NULL;
- pipe_texture_reference(&textures[att], xbuf->texture);
+ if (textures) {
+ int att;
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(attachment_mask, att)) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[att];
+
+ textures[att] = NULL;
+ pipe_texture_reference(&textures[att], xbuf->texture);
+ }
}
}
- /* increase the sequence number so that caller knows */
- if (new_buffers)
- xsurf->sequence_number++;
-
- if (seq_num)
- *seq_num = xsurf->sequence_number;
if (width)
*width = xsurf->width;
if (height)
@@ -360,18 +371,9 @@ ximage_surface_destroy(struct native_surface *nsurf)
struct ximage_surface *xsurf = ximage_surface(nsurf);
int i;
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[i];
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
ximage_surface_free_buffer(&xsurf->base, i);
- /* xbuf->shm_info is owned by xbuf->ximage? */
- if (xbuf->ximage) {
- XDestroyImage(xbuf->ximage);
- xbuf->ximage = NULL;
- }
- }
- if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER)
- XFreeGC(xsurf->xdpy->dpy, xsurf->gc);
free(xsurf);
}
@@ -384,7 +386,6 @@ ximage_display_create_surface(struct native_display *ndpy,
struct ximage_display *xdpy = ximage_display(ndpy);
struct ximage_config *xconf = ximage_config(nconf);
struct ximage_surface *xsurf;
- int i;
xsurf = CALLOC_STRUCT(ximage_surface);
if (!xsurf)
@@ -398,49 +399,8 @@ ximage_display_create_surface(struct native_display *ndpy,
if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
xsurf->drawable = drawable;
xsurf->visual = *xconf->visual;
-
- xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL);
- if (!xsurf->gc) {
- free(xsurf);
- return NULL;
- }
-
- for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
- struct ximage_buffer *xbuf = &xsurf->buffers[i];
-
- if (xdpy->use_xshm) {
- xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info));
- if (xbuf->shm_info) {
- /* initialize shm info */
- xbuf->shm_info->shmid = -1;
- xbuf->shm_info->shmaddr = (void *) -1;
- xbuf->shm_info->readOnly = TRUE;
-
- xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy,
- xsurf->visual.visual,
- xsurf->visual.depth,
- ZPixmap, NULL,
- xbuf->shm_info,
- 0, 0);
- }
- }
- else {
- xbuf->ximage = XCreateImage(xsurf->xdpy->dpy,
- xsurf->visual.visual,
- xsurf->visual.depth,
- ZPixmap, 0, /* format, offset */
- NULL, /* data */
- 0, 0, /* size */
- 8, /* bitmap_pad */
- 0); /* bytes_per_line */
- }
-
- if (!xbuf->ximage) {
- XFreeGC(xdpy->dpy, xsurf->gc);
- free(xsurf);
- return NULL;
- }
- }
+ /* initialize the geometry */
+ ximage_surface_update_buffers(&xsurf->base, 0x0);
}
xsurf->base.destroy = ximage_surface_destroy;
@@ -499,13 +459,13 @@ choose_format(const XVisualInfo *vinfo)
/* TODO elaborate the formats */
switch (vinfo->depth) {
case 32:
- fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 24:
- fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ fmt = PIPE_FORMAT_B8G8R8X8_UNORM;
break;
case 16:
- fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ fmt = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
fmt = PIPE_FORMAT_NONE;
@@ -558,8 +518,8 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
xconf->base.stencil_format = PIPE_FORMAT_NONE;
/* create the second config with depth/stencil buffer */
if (j == 1) {
- xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM;
- xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM;
+ xconf->base.depth_format = PIPE_FORMAT_Z24S8_UNORM;
+ xconf->base.stencil_format = PIPE_FORMAT_Z24S8_UNORM;
mode->depthBits = 24;
mode->stencilBits = 8;
mode->haveDepthBuffer = TRUE;
@@ -607,13 +567,13 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy,
depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix);
switch (depth) {
case 32:
- fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 24:
- fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ fmt = PIPE_FORMAT_B8G8R8X8_UNORM;
break;
case 16:
- fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ fmt = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
fmt = PIPE_FORMAT_NONE;
@@ -623,6 +583,25 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy,
return (fmt == nconf->color_format);
}
+static int
+ximage_display_get_param(struct native_display *ndpy,
+ enum native_param_type param)
+{
+ int val;
+
+ switch (param) {
+ case NATIVE_PARAM_USE_NATIVE_BUFFER:
+ /* private buffers are allocated */
+ val = FALSE;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
static void
ximage_display_destroy(struct native_display *ndpy)
{
@@ -632,7 +611,6 @@ ximage_display_destroy(struct native_display *ndpy)
free(xdpy->configs);
xdpy->base.screen->destroy(xdpy->base.screen);
- free(xdpy->winsys);
x11_screen_destroy(xdpy->xscr);
if (xdpy->own_dpy)
@@ -640,8 +618,63 @@ ximage_display_destroy(struct native_display *ndpy)
free(xdpy);
}
+
+/* Helper function to build a subset of a driver stack consisting of
+ * one of the software rasterizers (cell, llvmpipe, softpipe) and the
+ * xlib winsys.
+ *
+ * This function could be shared, but currently causes headaches for
+ * the build systems, particularly scons if we try.
+ *
+ * Long term, want to avoid having global #defines for things like
+ * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates
+ * those #defines, so things that are painful for it now are likely to
+ * be painful for other build systems in the future.
+ */
+static struct pipe_screen *
+swrast_xlib_create_screen( Display *display )
+{
+ struct sw_winsys *winsys;
+ struct pipe_screen *screen = NULL;
+
+ /* Create the underlying winsys, which performs presents to Xlib
+ * drawables:
+ */
+ winsys = xlib_create_sw_winsys( display );
+ if (winsys == NULL)
+ return NULL;
+
+ /* Create a software rasterizer on top of that winsys. Use
+ * llvmpipe if it is available.
+ */
+#if defined(GALLIUM_LLVMPIPE)
+ if (screen == NULL &&
+ !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE))
+ screen = llvmpipe_create_screen( winsys );
+#endif
+
+ if (screen == NULL)
+ screen = softpipe_create_screen( winsys );
+
+ if (screen == NULL)
+ goto fail;
+
+ /* Inject any wrapping layers we want to here:
+ */
+ return gallium_wrap_screen( screen );
+
+fail:
+ if (winsys)
+ winsys->destroy( winsys );
+
+ return NULL;
+}
+
+
+
struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler)
{
struct ximage_display *xdpy;
@@ -659,6 +692,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
xdpy->own_dpy = TRUE;
}
+ xdpy->event_handler = event_handler;
+
xdpy->xscr_number = DefaultScreen(xdpy->dpy);
xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
if (!xdpy->xscr) {
@@ -666,13 +701,10 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
return NULL;
}
- xdpy->use_xshm =
- (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
-
- xdpy->winsys = create_sw_winsys();
- xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
+ xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy);
xdpy->base.destroy = ximage_display_destroy;
+ xdpy->base.get_param = ximage_display_get_param;
xdpy->base.get_configs = ximage_display_get_configs;
xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported;
diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c
deleted file mode 100644
index 33328aadf26..00000000000
--- a/src/gallium/state_trackers/egl/x11/sw_winsys.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * Totally software-based winsys layer.
- * Note that the one winsys function that we can't implement here
- * is flush_frontbuffer().
- * Whoever uses this code will have to provide that.
- *
- * Authors: Brian Paul
- */
-
-
-#include "util/u_simple_screen.h"
-#include "pipe/p_state.h"
-#include "util/u_inlines.h"
-#include "util/u_format.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
-
-#include "sw_winsys.h"
-
-
-
-/** Subclass of pipe_winsys */
-struct sw_pipe_winsys
-{
- struct pipe_winsys Base;
- /* no extra fields for now */
-};
-
-
-/** subclass of pipe_buffer */
-struct sw_pipe_buffer
-{
- struct pipe_buffer Base;
- boolean UserBuffer; /** Is this a user-space buffer? */
- void *Data;
- void *Mapped;
-};
-
-
-/** cast wrapper */
-static INLINE struct sw_pipe_buffer *
-sw_pipe_buffer(struct pipe_buffer *b)
-{
- return (struct sw_pipe_buffer *) b;
-}
-
-
-static const char *
-get_name(struct pipe_winsys *pws)
-{
- return "software";
-}
-
-
-/** Create new pipe_buffer and allocate storage of given size */
-static struct pipe_buffer *
-buffer_create(struct pipe_winsys *pws,
- unsigned alignment,
- unsigned usage,
- unsigned size)
-{
- struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
- if (!buffer)
- return NULL;
-
- pipe_reference_init(&buffer->Base.reference, 1);
- buffer->Base.alignment = alignment;
- buffer->Base.usage = usage;
- buffer->Base.size = size;
-
- /* align to 16-byte multiple for Cell */
- buffer->Data = align_malloc(size, MAX2(alignment, 16));
-
- return &buffer->Base;
-}
-
-
-/**
- * Create buffer which wraps user-space data.
- */
-static struct pipe_buffer *
-user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
-{
- struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
- if (!buffer)
- return NULL;
-
- pipe_reference_init(&buffer->Base.reference, 1);
- buffer->Base.size = bytes;
- buffer->UserBuffer = TRUE;
- buffer->Data = ptr;
-
- return &buffer->Base;
-}
-
-
-static void *
-buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
- buffer->Mapped = buffer->Data;
- return buffer->Mapped;
-}
-
-
-static void
-buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
- buffer->Mapped = NULL;
-}
-
-
-static void
-buffer_destroy(struct pipe_buffer *buf)
-{
- struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
-
- if (buffer->Data && !buffer->UserBuffer) {
- align_free(buffer->Data);
- buffer->Data = NULL;
- }
-
- free(buffer);
-}
-
-
-static struct pipe_buffer *
-surface_buffer_create(struct pipe_winsys *winsys,
- unsigned width, unsigned height,
- enum pipe_format format,
- unsigned usage,
- unsigned tex_usage,
- unsigned *stride)
-{
- const unsigned alignment = 64;
- unsigned nblocksy;
-
- nblocksy = util_format_get_nblocksy(format, height);
- *stride = align(util_format_get_stride(format, width), alignment);
-
- return winsys->buffer_create(winsys, alignment,
- usage,
- *stride * nblocksy);
-}
-
-
-static void
-fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
- struct pipe_fence_handle *fence)
-{
- /* no-op */
-}
-
-
-static int
-fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
- unsigned flag)
-{
- /* no-op */
- return 0;
-}
-
-
-static int
-fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
- unsigned flag)
-{
- /* no-op */
- return 0;
-}
-
-
-/**
- * Create/return a new pipe_winsys object.
- */
-struct pipe_winsys *
-create_sw_winsys(void)
-{
- struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
- if (!ws)
- return NULL;
-
- /* Fill in this struct with callbacks that pipe will need to
- * communicate with the window system, buffer manager, etc.
- */
- ws->Base.buffer_create = buffer_create;
- ws->Base.user_buffer_create = user_buffer_create;
- ws->Base.buffer_map = buffer_map;
- ws->Base.buffer_unmap = buffer_unmap;
- ws->Base.buffer_destroy = buffer_destroy;
-
- ws->Base.surface_buffer_create = surface_buffer_create;
-
- ws->Base.fence_reference = fence_reference;
- ws->Base.fence_signalled = fence_signalled;
- ws->Base.fence_finish = fence_finish;
-
- ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
-
- ws->Base.get_name = get_name;
-
- return &ws->Base;
-}
diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.h b/src/gallium/state_trackers/egl/x11/sw_winsys.h
deleted file mode 100644
index f96c5a14b0a..00000000000
--- a/src/gallium/state_trackers/egl/x11/sw_winsys.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#ifndef SW_WINSYS_H
-#define SW_WINSYS_H
-
-
-struct pipe_winsys;
-
-
-extern struct pipe_winsys *
-create_sw_winsys(void);
-
-
-#endif /* SW_WINSYS_H */
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c
index d72bfc99d3e..f4096114844 100644
--- a/src/gallium/state_trackers/egl/x11/x11_screen.c
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.c
@@ -39,6 +39,9 @@
#include "glxinit.h"
struct x11_screen {
+ /* dummy base class */
+ struct __GLXDRIdisplayRec base;
+
Display *dpy;
int number;
@@ -53,6 +56,9 @@ struct x11_screen {
char *dri_device;
int dri_fd;
+ x11_drawable_invalidate_buffers dri_invalidate_buffers;
+ void *dri_user_data;
+
XVisualInfo *visuals;
int num_visuals;
@@ -98,6 +104,8 @@ x11_screen_destroy(struct x11_screen *xscr)
Xfree(xscr->dri_device);
/* xscr->glx_dpy will be destroyed with the X display */
+ if (xscr->glx_dpy)
+ xscr->glx_dpy->dri2Display = NULL;
if (xscr->visuals)
XFree(xscr->visuals);
@@ -247,24 +255,25 @@ x11_screen_get_glx_visuals(struct x11_screen *xscr)
: NULL;
}
-static boolean
-x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
-{
- return (strcmp(xscr->dri_driver, driver) == 0);
-}
-
/**
* Probe the screen for the DRI2 driver name.
*/
const char *
-x11_screen_probe_dri2(struct x11_screen *xscr)
+x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor)
{
+ if (!x11_screen_init_dri2(xscr))
+ return NULL;
+
/* get the driver name and the device name */
if (!xscr->dri_driver) {
if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
&xscr->dri_driver, &xscr->dri_device))
xscr->dri_driver = xscr->dri_device = NULL;
}
+ if (major)
+ *major = xscr->dri_major;
+ if (minor)
+ *minor = xscr->dri_minor;
return xscr->dri_driver;
}
@@ -274,21 +283,17 @@ x11_screen_probe_dri2(struct x11_screen *xscr)
* descriptor will be closed automatically when the screen is destoryed.
*/
int
-x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
+x11_screen_enable_dri2(struct x11_screen *xscr,
+ x11_drawable_invalidate_buffers invalidate_buffers,
+ void *user_data)
{
if (xscr->dri_fd < 0) {
int fd;
drm_magic_t magic;
/* get the driver name and the device name first */
- if (!x11_screen_probe_dri2(xscr))
- return -1;
-
- if (!x11_screen_is_driver_equal(xscr, driver)) {
- _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
- xscr->dri_driver, driver);
+ if (!x11_screen_probe_dri2(xscr, NULL, NULL))
return -1;
- }
fd = open(xscr->dri_device, O_RDWR);
if (fd < 0) {
@@ -310,6 +315,22 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
return -1;
}
+ if (!x11_screen_init_glx(xscr)) {
+ _eglLog(_EGL_WARNING, "failed to initialize GLX");
+ close(fd);
+ return -1;
+ }
+ if (xscr->glx_dpy->dri2Display) {
+ _eglLog(_EGL_WARNING,
+ "display is already managed by another x11 screen");
+ close(fd);
+ return -1;
+ }
+
+ xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr;
+ xscr->dri_invalidate_buffers = invalidate_buffers;
+ xscr->dri_user_data = user_data;
+
xscr->dri_fd = fd;
}
@@ -451,3 +472,20 @@ x11_context_modes_count(const __GLcontextModes *modes)
count++;
return count;
}
+
+/**
+ * This is called from src/glx/dri2.c.
+ */
+void
+dri2InvalidateBuffers(Display *dpy, XID drawable)
+{
+ __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+ struct x11_screen *xscr = NULL;
+
+ if (priv && priv->dri2Display)
+ xscr = (struct x11_screen *) priv->dri2Display;
+ if (!xscr || !xscr->dri_invalidate_buffers)
+ return;
+
+ xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data);
+}
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h
index 5432858ac3e..37e8d5a40e6 100644
--- a/src/gallium/state_trackers/egl/x11/x11_screen.h
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.h
@@ -48,6 +48,10 @@ struct x11_drawable_buffer {
struct x11_screen;
+typedef void (*x11_drawable_invalidate_buffers)(struct x11_screen *xscr,
+ Drawable drawable,
+ void *user_data);
+
struct x11_screen *
x11_screen_create(Display *dpy, int screen);
@@ -71,10 +75,12 @@ const __GLcontextModes *
x11_screen_get_glx_visuals(struct x11_screen *xscr);
const char *
-x11_screen_probe_dri2(struct x11_screen *xscr);
+x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor);
int
-x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);
+x11_screen_enable_dri2(struct x11_screen *xscr,
+ x11_drawable_invalidate_buffers invalidate_buffers,
+ void *user_data);
__GLcontextModes *
x11_context_modes_create(unsigned count);