native_dri2.c revision ed47d65c7c05d7dd5a5b4cafaa32afbd4fff0bef
1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Mesa 3-D graphics library 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Version: 7.8 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Permission is hereby granted, free of charge, to any person obtaining a 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * copy of this software and associated documentation files (the "Software"), 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * to deal in the Software without restriction, including without limitation 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * and/or sell copies of the Software, and to permit persons to whom the 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Software is furnished to do so, subject to the following conditions: 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * The above copyright notice and this permission notice shall be included 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in all copies or substantial portions of the Software. 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 170c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 180c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 190c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * DEALINGS IN THE SOFTWARE. 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_memory.h" 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_math.h" 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_format.h" 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_inlines.h" 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_hash_table.h" 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_compiler.h" 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_screen.h" 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_context.h" 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_state.h" 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "state_tracker/drm_driver.h" 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "egllog.h" 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "native_x11.h" 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "x11_screen.h" 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "common/native_helper.h" 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef HAVE_WAYLAND_BACKEND 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "common/native_wayland_drm_bufmgr_helper.h" 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef GLX_DIRECT_RENDERING 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_display { 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct native_display base; 5074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org Display *dpy; 5174f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org boolean own_dpy; 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5374f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org const struct native_event_handler *event_handler; 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct x11_screen *xscr; 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int xscr_number; 5774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org const char *dri_driver; 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int dri_major, dri_minor; 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct dri2_config *configs; 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int num_configs; 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct util_hash_table *surfaces; 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef HAVE_WAYLAND_BACKEND 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */ 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_surface { 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct native_surface base; 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Drawable drawable; 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enum pipe_format color_format; 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct dri2_display *dri2dpy; 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org unsigned int server_stamp; 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int client_stamp; 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int width, height; 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint valid_mask; 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org boolean have_back, have_fake; 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct x11_drawable_buffer *last_xbufs; 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int last_num_xbufs; 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_config { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct native_config base; 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic INLINE struct dri2_display * 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_display(const struct native_display *ndpy) 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (struct dri2_display *) ndpy; 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgstatic INLINE struct dri2_surface * 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface(const struct native_surface *nsurf) 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (struct dri2_surface *) nsurf; 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic INLINE struct dri2_config * 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_config(const struct native_config *nconf) 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (struct dri2_config *) nconf; 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/** 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Process the buffers returned by the server. 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface_process_drawable_buffers(struct native_surface *nsurf, 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct x11_drawable_buffer *xbufs, 11574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org int num_xbufs) 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct dri2_surface *dri2surf = dri2_surface(nsurf); 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct dri2_display *dri2dpy = dri2surf->dri2dpy; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct pipe_resource templ; 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct winsys_handle whandle; 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint valid_mask; 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* free the old textures */ 12574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) 12674f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org pipe_resource_reference(&dri2surf->textures[i], NULL); 12774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org dri2surf->valid_mask = 0x0; 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->have_back = FALSE; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->have_fake = FALSE; 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!xbufs) 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return; 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&templ, 0, sizeof(templ)); 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.target = PIPE_TEXTURE_2D; 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.last_level = 0; 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.width0 = dri2surf->width; 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.height0 = dri2surf->height; 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.depth0 = 1; 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.array_size = 1; 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.format = dri2surf->color_format; 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org templ.bind = PIPE_BIND_RENDER_TARGET; 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org valid_mask = 0x0; 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < num_xbufs; i++) { 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct x11_drawable_buffer *xbuf = &xbufs[i]; 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *desc; 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enum native_attachment natt; 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (xbuf->attachment) { 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case DRI2BufferFrontLeft: 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org natt = NATIVE_ATTACHMENT_FRONT_LEFT; 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org desc = "DRI2 Front Buffer"; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case DRI2BufferFakeFrontLeft: 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org natt = NATIVE_ATTACHMENT_FRONT_LEFT; 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org desc = "DRI2 Fake Front Buffer"; 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->have_fake = TRUE; 16074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org break; 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case DRI2BufferBackLeft: 16274f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org natt = NATIVE_ATTACHMENT_BACK_LEFT; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org desc = "DRI2 Back Buffer"; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->have_back = TRUE; 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org desc = NULL; 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!desc || dri2surf->textures[natt]) { 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!desc) 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&whandle, 0, sizeof(whandle)); 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org whandle.stride = xbuf->pitch; 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org whandle.handle = xbuf->name; 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2dpy->base.screen, &templ, &whandle); 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dri2surf->textures[natt]) 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org valid_mask |= 1 << natt; 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dri2surf->valid_mask = valid_mask; 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/** 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Get the buffers from the server. 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1973b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org struct dri2_surface *dri2surf = dri2_surface(nsurf); 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct dri2_display *dri2dpy = dri2surf->dri2dpy; 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2]; 200 int num_ins, num_outs, att; 201 struct x11_drawable_buffer *xbufs; 202 uint bpp = util_format_get_blocksizebits(dri2surf->color_format); 203 boolean with_format = FALSE; /* never ask for depth/stencil */ 204 205 /* We must get the front on servers which doesn't support with format 206 * due to a silly bug in core dri2. You can't copy to/from a buffer 207 * that you haven't requested and you recive BadValue errors */ 208 if (dri2surf->dri2dpy->dri_minor < 1) { 209 with_format = FALSE; 210 buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT); 211 } 212 213 /* prepare the attachments */ 214 num_ins = 0; 215 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 216 if (native_attachment_mask_test(buffer_mask, att)) { 217 unsigned int dri2att; 218 219 switch (att) { 220 case NATIVE_ATTACHMENT_FRONT_LEFT: 221 dri2att = DRI2BufferFrontLeft; 222 break; 223 case NATIVE_ATTACHMENT_BACK_LEFT: 224 dri2att = DRI2BufferBackLeft; 225 break; 226 case NATIVE_ATTACHMENT_FRONT_RIGHT: 227 dri2att = DRI2BufferFrontRight; 228 break; 229 case NATIVE_ATTACHMENT_BACK_RIGHT: 230 dri2att = DRI2BufferBackRight; 231 break; 232 default: 233 assert(0); 234 dri2att = 0; 235 break; 236 } 237 238 dri2atts[num_ins++] = dri2att; 239 if (with_format) 240 dri2atts[num_ins++] = bpp; 241 } 242 } 243 if (with_format) 244 num_ins /= 2; 245 246 xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, 247 &dri2surf->width, &dri2surf->height, 248 dri2atts, with_format, num_ins, &num_outs); 249 250 /* we should be able to do better... */ 251 if (xbufs && dri2surf->last_num_xbufs == num_outs && 252 memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { 253 FREE(xbufs); 254 dri2surf->client_stamp = dri2surf->server_stamp; 255 return; 256 } 257 258 dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs); 259 260 dri2surf->server_stamp++; 261 dri2surf->client_stamp = dri2surf->server_stamp; 262 263 if (dri2surf->last_xbufs) 264 FREE(dri2surf->last_xbufs); 265 dri2surf->last_xbufs = xbufs; 266 dri2surf->last_num_xbufs = num_outs; 267} 268 269/** 270 * Update the buffers of the surface. This is a slow function due to the 271 * round-trip to the server. 272 */ 273static boolean 274dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) 275{ 276 struct dri2_surface *dri2surf = dri2_surface(nsurf); 277 278 dri2_surface_get_buffers(&dri2surf->base, buffer_mask); 279 280 return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); 281} 282 283/** 284 * Return TRUE if the surface receives DRI2_InvalidateBuffers events. 285 */ 286static INLINE boolean 287dri2_surface_receive_events(struct native_surface *nsurf) 288{ 289 struct dri2_surface *dri2surf = dri2_surface(nsurf); 290 return (dri2surf->dri2dpy->dri_minor >= 3); 291} 292 293static boolean 294dri2_surface_flush_frontbuffer(struct native_surface *nsurf) 295{ 296 struct dri2_surface *dri2surf = dri2_surface(nsurf); 297 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 298 299 /* copy to real front buffer */ 300 if (dri2surf->have_fake) 301 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 302 0, 0, dri2surf->width, dri2surf->height, 303 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 304 305 /* force buffers to be updated in next validation call */ 306 if (!dri2_surface_receive_events(&dri2surf->base)) { 307 dri2surf->server_stamp++; 308 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 309 &dri2surf->base, dri2surf->server_stamp); 310 } 311 312 return TRUE; 313} 314 315static boolean 316dri2_surface_swap_buffers(struct native_surface *nsurf) 317{ 318 struct dri2_surface *dri2surf = dri2_surface(nsurf); 319 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 320 321 /* copy to front buffer */ 322 if (dri2surf->have_back) 323 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 324 0, 0, dri2surf->width, dri2surf->height, 325 DRI2BufferBackLeft, DRI2BufferFrontLeft); 326 327 /* and update fake front buffer */ 328 if (dri2surf->have_fake) 329 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 330 0, 0, dri2surf->width, dri2surf->height, 331 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 332 333 /* force buffers to be updated in next validation call */ 334 if (!dri2_surface_receive_events(&dri2surf->base)) { 335 dri2surf->server_stamp++; 336 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 337 &dri2surf->base, dri2surf->server_stamp); 338 } 339 340 return TRUE; 341} 342 343static boolean 344dri2_surface_present(struct native_surface *nsurf, 345 enum native_attachment natt, 346 boolean preserve, 347 uint swap_interval) 348{ 349 boolean ret; 350 351 if (swap_interval) 352 return FALSE; 353 354 switch (natt) { 355 case NATIVE_ATTACHMENT_FRONT_LEFT: 356 ret = dri2_surface_flush_frontbuffer(nsurf); 357 break; 358 case NATIVE_ATTACHMENT_BACK_LEFT: 359 ret = dri2_surface_swap_buffers(nsurf); 360 break; 361 default: 362 ret = FALSE; 363 break; 364 } 365 366 return ret; 367} 368 369static boolean 370dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, 371 unsigned int *seq_num, struct pipe_resource **textures, 372 int *width, int *height) 373{ 374 struct dri2_surface *dri2surf = dri2_surface(nsurf); 375 376 if (dri2surf->server_stamp != dri2surf->client_stamp || 377 (dri2surf->valid_mask & attachment_mask) != attachment_mask) { 378 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) 379 return FALSE; 380 } 381 382 if (seq_num) 383 *seq_num = dri2surf->client_stamp; 384 385 if (textures) { 386 int att; 387 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 388 if (native_attachment_mask_test(attachment_mask, att)) { 389 struct pipe_resource *ptex = dri2surf->textures[att]; 390 391 textures[att] = NULL; 392 pipe_resource_reference(&textures[att], ptex); 393 } 394 } 395 } 396 397 if (width) 398 *width = dri2surf->width; 399 if (height) 400 *height = dri2surf->height; 401 402 return TRUE; 403} 404 405static void 406dri2_surface_wait(struct native_surface *nsurf) 407{ 408 struct dri2_surface *dri2surf = dri2_surface(nsurf); 409 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 410 411 if (dri2surf->have_fake) { 412 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 413 0, 0, dri2surf->width, dri2surf->height, 414 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 415 } 416} 417 418static void 419dri2_surface_destroy(struct native_surface *nsurf) 420{ 421 struct dri2_surface *dri2surf = dri2_surface(nsurf); 422 int i; 423 424 if (dri2surf->last_xbufs) 425 FREE(dri2surf->last_xbufs); 426 427 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { 428 struct pipe_resource *ptex = dri2surf->textures[i]; 429 pipe_resource_reference(&ptex, NULL); 430 } 431 432 if (dri2surf->drawable) { 433 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, 434 dri2surf->drawable, FALSE); 435 436 util_hash_table_remove(dri2surf->dri2dpy->surfaces, 437 (void *) dri2surf->drawable); 438 } 439 FREE(dri2surf); 440} 441 442static struct dri2_surface * 443dri2_display_create_surface(struct native_display *ndpy, 444 Drawable drawable, 445 enum pipe_format color_format) 446{ 447 struct dri2_display *dri2dpy = dri2_display(ndpy); 448 struct dri2_surface *dri2surf; 449 450 dri2surf = CALLOC_STRUCT(dri2_surface); 451 if (!dri2surf) 452 return NULL; 453 454 dri2surf->dri2dpy = dri2dpy; 455 dri2surf->drawable = drawable; 456 dri2surf->color_format = color_format; 457 458 dri2surf->base.destroy = dri2_surface_destroy; 459 dri2surf->base.present = dri2_surface_present; 460 dri2surf->base.validate = dri2_surface_validate; 461 dri2surf->base.wait = dri2_surface_wait; 462 463 if (drawable) { 464 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); 465 /* initialize the geometry */ 466 dri2_surface_update_buffers(&dri2surf->base, 0x0); 467 468 util_hash_table_set(dri2surf->dri2dpy->surfaces, 469 (void *) dri2surf->drawable, (void *) &dri2surf->base); 470 } 471 472 return dri2surf; 473} 474 475static struct native_surface * 476dri2_display_create_window_surface(struct native_display *ndpy, 477 EGLNativeWindowType win, 478 const struct native_config *nconf) 479{ 480 struct dri2_surface *dri2surf; 481 482 dri2surf = dri2_display_create_surface(ndpy, 483 (Drawable) win, nconf->color_format); 484 return (dri2surf) ? &dri2surf->base : NULL; 485} 486 487static struct native_surface * 488dri2_display_create_pixmap_surface(struct native_display *ndpy, 489 EGLNativePixmapType pix, 490 const struct native_config *nconf) 491{ 492 struct dri2_surface *dri2surf; 493 494 if (!nconf) { 495 struct dri2_display *dri2dpy = dri2_display(ndpy); 496 uint depth, nconf_depth; 497 int i; 498 499 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 500 for (i = 0; i < dri2dpy->num_configs; i++) { 501 nconf_depth = util_format_get_blocksizebits( 502 dri2dpy->configs[i].base.color_format); 503 /* simple depth match for now */ 504 if (depth == nconf_depth || 505 (depth == 24 && depth + 8 == nconf_depth)) { 506 nconf = &dri2dpy->configs[i].base; 507 break; 508 } 509 } 510 511 if (!nconf) 512 return NULL; 513 } 514 515 dri2surf = dri2_display_create_surface(ndpy, 516 (Drawable) pix, nconf->color_format); 517 return (dri2surf) ? &dri2surf->base : NULL; 518} 519 520static int 521choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) 522{ 523 int count = 0; 524 525 switch (mode->rgbBits) { 526 case 32: 527 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 528 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 529 break; 530 case 24: 531 formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM; 532 formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; 533 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 534 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 535 break; 536 case 16: 537 formats[count++] = PIPE_FORMAT_B5G6R5_UNORM; 538 break; 539 default: 540 break; 541 } 542 543 return count; 544} 545 546static boolean 547is_format_supported(struct pipe_screen *screen, 548 enum pipe_format fmt, unsigned sample_count, boolean is_color) 549{ 550 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count, 551 (is_color) ? PIPE_BIND_RENDER_TARGET : 552 PIPE_BIND_DEPTH_STENCIL); 553} 554 555static boolean 556dri2_display_convert_config(struct native_display *ndpy, 557 const __GLcontextModes *mode, 558 struct native_config *nconf) 559{ 560 enum pipe_format formats[32]; 561 int num_formats, i; 562 int sample_count = 0; 563 564 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode) 565 return FALSE; 566 567 /* only interested in native renderable configs */ 568 if (!mode->xRenderable || !mode->drawableType) 569 return FALSE; 570 571 /* fast/slow configs are probably not relevant */ 572 if (mode->visualRating == GLX_SLOW_CONFIG) 573 return FALSE; 574 575 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; 576 if (mode->doubleBufferMode) 577 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; 578 if (mode->stereoMode) { 579 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; 580 if (mode->doubleBufferMode) 581 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; 582 } 583 584 /* choose color format */ 585 num_formats = choose_color_format(mode, formats); 586 for (i = 0; i < num_formats; i++) { 587 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) { 588 nconf->color_format = formats[i]; 589 break; 590 } 591 } 592 if (nconf->color_format == PIPE_FORMAT_NONE) 593 return FALSE; 594 595 if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID) 596 nconf->window_bit = TRUE; 597 if (mode->drawableType & GLX_PIXMAP_BIT) 598 nconf->pixmap_bit = TRUE; 599 600 nconf->native_visual_id = mode->visualID; 601 switch (mode->visualType) { 602 case GLX_TRUE_COLOR: 603 nconf->native_visual_type = TrueColor; 604 break; 605 case GLX_DIRECT_COLOR: 606 nconf->native_visual_type = DirectColor; 607 break; 608 case GLX_PSEUDO_COLOR: 609 nconf->native_visual_type = PseudoColor; 610 break; 611 case GLX_STATIC_COLOR: 612 nconf->native_visual_type = StaticColor; 613 break; 614 case GLX_GRAY_SCALE: 615 nconf->native_visual_type = GrayScale; 616 break; 617 case GLX_STATIC_GRAY: 618 nconf->native_visual_type = StaticGray; 619 break; 620 } 621 nconf->level = mode->level; 622 623 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { 624 nconf->transparent_rgb = TRUE; 625 nconf->transparent_rgb_values[0] = mode->transparentRed; 626 nconf->transparent_rgb_values[1] = mode->transparentGreen; 627 nconf->transparent_rgb_values[2] = mode->transparentBlue; 628 } 629 630 return TRUE; 631} 632 633static const struct native_config ** 634dri2_display_get_configs(struct native_display *ndpy, int *num_configs) 635{ 636 struct dri2_display *dri2dpy = dri2_display(ndpy); 637 const struct native_config **configs; 638 int i; 639 640 /* first time */ 641 if (!dri2dpy->configs) { 642 const __GLcontextModes *modes; 643 int num_modes, count; 644 645 modes = x11_screen_get_glx_configs(dri2dpy->xscr); 646 if (!modes) 647 return NULL; 648 num_modes = x11_context_modes_count(modes); 649 650 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); 651 if (!dri2dpy->configs) 652 return NULL; 653 654 count = 0; 655 for (i = 0; i < num_modes; i++) { 656 struct native_config *nconf = &dri2dpy->configs[count].base; 657 658 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) { 659 int j; 660 /* look for duplicates */ 661 for (j = 0; j < count; j++) { 662 if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0) 663 break; 664 } 665 if (j == count) 666 count++; 667 } 668 modes = modes->next; 669 } 670 671 dri2dpy->num_configs = count; 672 } 673 674 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); 675 if (configs) { 676 for (i = 0; i < dri2dpy->num_configs; i++) 677 configs[i] = (const struct native_config *) &dri2dpy->configs[i]; 678 if (num_configs) 679 *num_configs = dri2dpy->num_configs; 680 } 681 682 return configs; 683} 684 685static boolean 686dri2_display_get_pixmap_format(struct native_display *ndpy, 687 EGLNativePixmapType pix, 688 enum pipe_format *format) 689{ 690 struct dri2_display *dri2dpy = dri2_display(ndpy); 691 boolean ret = EGL_TRUE; 692 uint depth; 693 694 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 695 switch (depth) { 696 case 32: 697 case 24: 698 *format = PIPE_FORMAT_B8G8R8A8_UNORM; 699 break; 700 case 16: 701 *format = PIPE_FORMAT_B5G6R5_UNORM; 702 break; 703 default: 704 *format = PIPE_FORMAT_NONE; 705 ret = EGL_FALSE; 706 break; 707 } 708 709 return ret; 710} 711 712static int 713dri2_display_get_param(struct native_display *ndpy, 714 enum native_param_type param) 715{ 716 int val; 717 718 switch (param) { 719 case NATIVE_PARAM_USE_NATIVE_BUFFER: 720 /* DRI2GetBuffers uses the native buffers */ 721 val = TRUE; 722 break; 723 case NATIVE_PARAM_PRESERVE_BUFFER: 724 /* DRI2CopyRegion is used */ 725 val = TRUE; 726 break; 727 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 728 default: 729 val = 0; 730 break; 731 } 732 733 return val; 734} 735 736static void 737dri2_display_destroy(struct native_display *ndpy) 738{ 739 struct dri2_display *dri2dpy = dri2_display(ndpy); 740 741 if (dri2dpy->configs) 742 FREE(dri2dpy->configs); 743 744 if (dri2dpy->base.screen) 745 dri2dpy->base.screen->destroy(dri2dpy->base.screen); 746 747 if (dri2dpy->surfaces) 748 util_hash_table_destroy(dri2dpy->surfaces); 749 750 if (dri2dpy->xscr) 751 x11_screen_destroy(dri2dpy->xscr); 752 if (dri2dpy->own_dpy) 753 XCloseDisplay(dri2dpy->dpy); 754 FREE(dri2dpy); 755} 756 757static void 758dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, 759 void *user_data) 760{ 761 struct native_display *ndpy = (struct native_display* ) user_data; 762 struct dri2_display *dri2dpy = dri2_display(ndpy); 763 struct native_surface *nsurf; 764 struct dri2_surface *dri2surf; 765 766 nsurf = (struct native_surface *) 767 util_hash_table_get(dri2dpy->surfaces, (void *) drawable); 768 if (!nsurf) 769 return; 770 771 dri2surf = dri2_surface(nsurf); 772 773 dri2surf->server_stamp++; 774 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 775 &dri2surf->base, dri2surf->server_stamp); 776} 777 778/** 779 * Initialize DRI2 and pipe screen. 780 */ 781static boolean 782dri2_display_init_screen(struct native_display *ndpy) 783{ 784 struct dri2_display *dri2dpy = dri2_display(ndpy); 785 int fd; 786 787 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || 788 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) { 789 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported"); 790 return FALSE; 791 } 792 793 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, 794 &dri2dpy->dri_major, &dri2dpy->dri_minor); 795 796 fd = x11_screen_enable_dri2(dri2dpy->xscr, 797 dri2_display_invalidate_buffers, &dri2dpy->base); 798 if (fd < 0) 799 return FALSE; 800 801 dri2dpy->base.screen = 802 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, 803 dri2dpy->dri_driver, fd); 804 if (!dri2dpy->base.screen) { 805 _eglLog(_EGL_DEBUG, "failed to create DRM screen"); 806 return FALSE; 807 } 808 809 return TRUE; 810} 811 812static unsigned 813dri2_display_hash_table_hash(void *key) 814{ 815 XID drawable = pointer_to_uintptr(key); 816 return (unsigned) drawable; 817} 818 819static int 820dri2_display_hash_table_compare(void *key1, void *key2) 821{ 822 return ((char *) key1 - (char *) key2); 823} 824 825static int 826dri2_display_authenticate(void *user_data, uint32_t magic) 827{ 828 struct native_display *ndpy = user_data; 829 struct dri2_display *dri2dpy = dri2_display(ndpy); 830 831 return x11_screen_authenticate(dri2dpy->xscr, magic); 832} 833 834#ifdef HAVE_WAYLAND_BACKEND 835 836static struct wayland_drm_callbacks wl_drm_callbacks = { 837 dri2_display_authenticate, 838 egl_g3d_wl_drm_helper_reference_buffer, 839 egl_g3d_wl_drm_helper_unreference_buffer 840}; 841 842static boolean 843dri2_display_bind_wayland_display(struct native_display *ndpy, 844 struct wl_display *wl_dpy) 845{ 846 struct dri2_display *dri2dpy = dri2_display(ndpy); 847 848 if (dri2dpy->wl_server_drm) 849 return FALSE; 850 851 dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy, 852 x11_screen_get_device_name(dri2dpy->xscr), 853 &wl_drm_callbacks, ndpy); 854 855 if (!dri2dpy->wl_server_drm) 856 return FALSE; 857 858 return TRUE; 859} 860 861static boolean 862dri2_display_unbind_wayland_display(struct native_display *ndpy, 863 struct wl_display *wl_dpy) 864{ 865 struct dri2_display *dri2dpy = dri2_display(ndpy); 866 867 if (!dri2dpy->wl_server_drm) 868 return FALSE; 869 870 wayland_drm_uninit(dri2dpy->wl_server_drm); 871 dri2dpy->wl_server_drm = NULL; 872 873 return TRUE; 874} 875 876static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = { 877 dri2_display_bind_wayland_display, 878 dri2_display_unbind_wayland_display, 879 egl_g3d_wl_drm_common_wl_buffer_get_resource 880}; 881 882#endif /* HAVE_WAYLAND_BACKEND */ 883 884struct native_display * 885x11_create_dri2_display(Display *dpy, 886 const struct native_event_handler *event_handler) 887{ 888 struct dri2_display *dri2dpy; 889 890 dri2dpy = CALLOC_STRUCT(dri2_display); 891 if (!dri2dpy) 892 return NULL; 893 894 dri2dpy->event_handler = event_handler; 895 896 dri2dpy->dpy = dpy; 897 if (!dri2dpy->dpy) { 898 dri2dpy->dpy = XOpenDisplay(NULL); 899 if (!dri2dpy->dpy) { 900 dri2_display_destroy(&dri2dpy->base); 901 return NULL; 902 } 903 dri2dpy->own_dpy = TRUE; 904 } 905 906 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy); 907 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number); 908 if (!dri2dpy->xscr) { 909 dri2_display_destroy(&dri2dpy->base); 910 return NULL; 911 } 912 913 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, 914 dri2_display_hash_table_compare); 915 if (!dri2dpy->surfaces) { 916 dri2_display_destroy(&dri2dpy->base); 917 return NULL; 918 } 919 920 dri2dpy->base.init_screen = dri2_display_init_screen; 921 dri2dpy->base.destroy = dri2_display_destroy; 922 dri2dpy->base.get_param = dri2_display_get_param; 923 dri2dpy->base.get_configs = dri2_display_get_configs; 924 dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format; 925 dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap; 926 dri2dpy->base.create_window_surface = dri2_display_create_window_surface; 927 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; 928#ifdef HAVE_WAYLAND_BACKEND 929 dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr; 930#endif 931 932 return &dri2dpy->base; 933} 934 935#else /* GLX_DIRECT_RENDERING */ 936 937struct native_display * 938x11_create_dri2_display(Display *dpy, 939 const struct native_event_handler *event_handler) 940{ 941 return NULL; 942} 943 944#endif /* GLX_DIRECT_RENDERING */ 945