dri2_glx.c revision 7d9e0ea7393c14cbf2d58364726951b14e0d4fc7
1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Copyright © 2008 Red Hat, Inc. 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Permission is hereby granted, free of charge, to any person obtaining a 5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * copy of this software and associated documentation files (the "Soft- 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ware"), to deal in the Software without restriction, including without 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * limitation the rights to use, copy, modify, merge, publish, distribute, 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * and/or sell copies of the Software, and to permit persons to whom the 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software is furnished to do so, provided that the above copyright 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * notice(s) and this permission notice appear in all copies of the Soft- 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ware and that both the above copyright notice(s) and this permission 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * notice appear in supporting documentation. 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * MANCE OF THIS SOFTWARE. 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Except as contained in this notice, the name of a copyright holder shall 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * not be used in advertising or otherwise to promote the sale, use or 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * other dealings in this Software without prior written authorization of 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * the copyright holder. 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Authors: 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Kristian Høgsberg (krh@redhat.com) 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <X11/Xlib.h> 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <X11/extensions/Xfixes.h> 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <X11/extensions/Xdamage.h> 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "glapi.h" 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "glxclient.h" 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <X11/extensions/dri2proto.h> 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "xf86dri.h" 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <dlfcn.h> 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <fcntl.h> 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <unistd.h> 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <sys/types.h> 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include <sys/mman.h> 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "xf86drm.h" 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "dri2.h" 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#include "dri_common.h" 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* From xmlpool/options.h, user exposed so should be stable */ 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#define DRI_CONF_VBLANK_NEVER 0 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#undef DRI2_MINOR 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato#define DRI2_MINOR 1 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostruct dri2_display 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __GLXDRIdisplay base; 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /* 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ** XFree86-DRI version information 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int driMajor; 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int driMinor; 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int driPatch; 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int swapAvailable; 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int invalidateAvailable; 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __glxHashTable *dri2Hash; 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRIextension *loader_extensions[4]; 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}; 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostruct dri2_screen { 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato struct glx_screen base; 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __DRIscreen *driScreen; 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __GLXDRIscreen vtable; 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRIdri2Extension *dri2; 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRIcoreExtension *core; 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRI2flushExtension *f; 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRI2configQueryExtension *config; 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRItexBufferExtension *texBuffer; 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato const __DRIconfig **driver_configs; 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato void *driver; 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int fd; 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}; 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostruct dri2_context 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato struct glx_context base; 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __DRIcontext *driContext; 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}; 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostruct dri2_drawable 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __GLXDRIdrawable base; 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __DRIdrawable *driDrawable; 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato __DRIbuffer buffers[5]; 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int bufferCount; 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int width, height; 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int have_back; 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int have_fake_front; 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int swap_interval; 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}; 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostatic const struct glx_context_vtable dri2_context_vtable; 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratostatic void 116dri2_destroy_context(struct glx_context *context) 117{ 118 struct dri2_context *pcp = (struct dri2_context *) context; 119 struct dri2_screen *psc = (struct dri2_screen *) context->psc; 120 121 driReleaseDrawables(&pcp->base); 122 123 if (context->xid) 124 glx_send_destroy_context(psc->base.dpy, context->xid); 125 126 if (context->extensions) 127 XFree((char *) context->extensions); 128 129 (*psc->core->destroyContext) (pcp->driContext); 130 131 Xfree(pcp); 132} 133 134static Bool 135dri2_bind_context(struct glx_context *context, struct glx_context *old, 136 GLXDrawable draw, GLXDrawable read) 137{ 138 struct dri2_context *pcp = (struct dri2_context *) context; 139 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 140 struct dri2_drawable *pdraw, *pread; 141 struct dri2_display *pdp; 142 143 pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw); 144 pread = (struct dri2_drawable *) driFetchDrawable(context, read); 145 146 if (pdraw == NULL || pread == NULL) 147 return GLXBadDrawable; 148 149 if (!(*psc->core->bindContext) (pcp->driContext, 150 pdraw->driDrawable, pread->driDrawable)) 151 return GLXBadContext; 152 153 /* If the server doesn't send invalidate events, we may miss a 154 * resize before the rendering starts. Invalidate the buffers now 155 * so the driver will recheck before rendering starts. */ 156 pdp = (struct dri2_display *) psc->base.display; 157 if (!pdp->invalidateAvailable) { 158 dri2InvalidateBuffers(psc->base.dpy, pdraw->base.xDrawable); 159 if (pread != pdraw) 160 dri2InvalidateBuffers(psc->base.dpy, pread->base.xDrawable); 161 } 162 163 return Success; 164} 165 166static void 167dri2_unbind_context(struct glx_context *context, struct glx_context *new) 168{ 169 struct dri2_context *pcp = (struct dri2_context *) context; 170 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 171 172 (*psc->core->unbindContext) (pcp->driContext); 173 174 if (context == new) 175 driReleaseDrawables(&pcp->base); 176} 177 178static struct glx_context * 179dri2_create_context(struct glx_screen *base, 180 struct glx_config *config_base, 181 struct glx_context *shareList, int renderType) 182{ 183 struct dri2_context *pcp, *pcp_shared; 184 struct dri2_screen *psc = (struct dri2_screen *) base; 185 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 186 __DRIcontext *shared = NULL; 187 188 if (shareList) { 189 pcp_shared = (struct dri2_context *) shareList; 190 shared = pcp_shared->driContext; 191 } 192 193 pcp = Xmalloc(sizeof *pcp); 194 if (pcp == NULL) 195 return NULL; 196 197 memset(pcp, 0, sizeof *pcp); 198 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 199 Xfree(pcp); 200 return NULL; 201 } 202 203 pcp->driContext = 204 (*psc->dri2->createNewContext) (psc->driScreen, 205 config->driConfig, shared, pcp); 206 207 if (pcp->driContext == NULL) { 208 Xfree(pcp); 209 return NULL; 210 } 211 212 pcp->base.vtable = &dri2_context_vtable; 213 214 return &pcp->base; 215} 216 217static void 218dri2DestroyDrawable(__GLXDRIdrawable *base) 219{ 220 struct dri2_screen *psc = (struct dri2_screen *) base->psc; 221 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 222 struct glx_display *dpyPriv = psc->base.display; 223 struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display; 224 225 __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable); 226 (*psc->core->destroyDrawable) (pdraw->driDrawable); 227 228 /* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable 229 * now, as the application explicitly asked to destroy the GLX 230 * drawable. Otherwise, for legacy drawables, we let the DRI2 231 * drawable linger on the server, since there's no good way of 232 * knowing when the application is done with it. The server will 233 * destroy the DRI2 drawable when it destroys the X drawable or the 234 * client exits anyway. */ 235 if (pdraw->base.xDrawable != pdraw->base.drawable) 236 DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable); 237 238 Xfree(pdraw); 239} 240 241static __GLXDRIdrawable * 242dri2CreateDrawable(struct glx_screen *base, XID xDrawable, 243 GLXDrawable drawable, struct glx_config *config_base) 244{ 245 struct dri2_drawable *pdraw; 246 struct dri2_screen *psc = (struct dri2_screen *) base; 247 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 248 struct glx_display *dpyPriv; 249 struct dri2_display *pdp; 250 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 251 252 pdraw = Xmalloc(sizeof(*pdraw)); 253 if (!pdraw) 254 return NULL; 255 256 memset(pdraw, 0, sizeof *pdraw); 257 pdraw->base.destroyDrawable = dri2DestroyDrawable; 258 pdraw->base.xDrawable = xDrawable; 259 pdraw->base.drawable = drawable; 260 pdraw->base.psc = &psc->base; 261 pdraw->bufferCount = 0; 262 pdraw->swap_interval = 1; /* default may be overridden below */ 263 pdraw->have_back = 0; 264 265 if (psc->config) 266 psc->config->configQueryi(psc->driScreen, 267 "vblank_mode", &vblank_mode); 268 269 switch (vblank_mode) { 270 case DRI_CONF_VBLANK_NEVER: 271 case DRI_CONF_VBLANK_DEF_INTERVAL_0: 272 pdraw->swap_interval = 0; 273 break; 274 case DRI_CONF_VBLANK_DEF_INTERVAL_1: 275 case DRI_CONF_VBLANK_ALWAYS_SYNC: 276 default: 277 pdraw->swap_interval = 1; 278 break; 279 } 280 281 DRI2CreateDrawable(psc->base.dpy, xDrawable); 282 283 dpyPriv = __glXInitialize(psc->base.dpy); 284 pdp = (struct dri2_display *)dpyPriv->dri2Display;; 285 /* Create a new drawable */ 286 pdraw->driDrawable = 287 (*psc->dri2->createNewDrawable) (psc->driScreen, 288 config->driConfig, pdraw); 289 290 if (!pdraw->driDrawable) { 291 DRI2DestroyDrawable(psc->base.dpy, xDrawable); 292 Xfree(pdraw); 293 return NULL; 294 } 295 296 if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) { 297 (*psc->core->destroyDrawable) (pdraw->driDrawable); 298 DRI2DestroyDrawable(psc->base.dpy, xDrawable); 299 Xfree(pdraw); 300 return None; 301 } 302 303 304#ifdef X_DRI2SwapInterval 305 /* 306 * Make sure server has the same swap interval we do for the new 307 * drawable. 308 */ 309 if (pdp->swapAvailable) 310 DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval); 311#endif 312 313 return &pdraw->base; 314} 315 316#ifdef X_DRI2GetMSC 317 318static int 319dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw, 320 int64_t *ust, int64_t *msc, int64_t *sbc) 321{ 322 CARD64 dri2_ust, dri2_msc, dri2_sbc; 323 int ret; 324 325 ret = DRI2GetMSC(psc->dpy, pdraw->xDrawable, 326 &dri2_ust, &dri2_msc, &dri2_sbc); 327 *ust = dri2_ust; 328 *msc = dri2_msc; 329 *sbc = dri2_sbc; 330 331 return ret; 332} 333 334#endif 335 336 337#ifdef X_DRI2WaitMSC 338 339static int 340dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 341 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 342{ 343 CARD64 dri2_ust, dri2_msc, dri2_sbc; 344 int ret; 345 346 ret = DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 347 remainder, &dri2_ust, &dri2_msc, &dri2_sbc); 348 *ust = dri2_ust; 349 *msc = dri2_msc; 350 *sbc = dri2_sbc; 351 352 return ret; 353} 354 355static int 356dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 357 int64_t *msc, int64_t *sbc) 358{ 359 CARD64 dri2_ust, dri2_msc, dri2_sbc; 360 int ret; 361 362 ret = DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, 363 target_sbc, &dri2_ust, &dri2_msc, &dri2_sbc); 364 *ust = dri2_ust; 365 *msc = dri2_msc; 366 *sbc = dri2_sbc; 367 368 return ret; 369} 370 371#endif /* X_DRI2WaitMSC */ 372 373static void 374dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 375{ 376 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 377 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 378 XRectangle xrect; 379 XserverRegion region; 380 381 /* Check we have the right attachments */ 382 if (!priv->have_back) 383 return; 384 385 xrect.x = x; 386 xrect.y = priv->height - y - height; 387 xrect.width = width; 388 xrect.height = height; 389 390#ifdef __DRI2_FLUSH 391 if (psc->f) 392 (*psc->f->flush) (priv->driDrawable); 393#endif 394 395 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 396 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 397 DRI2BufferFrontLeft, DRI2BufferBackLeft); 398 399 /* Refresh the fake front (if present) after we just damaged the real 400 * front. 401 */ 402 if (priv->have_fake_front) 403 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 404 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 405 406 XFixesDestroyRegion(psc->base.dpy, region); 407} 408 409static void 410dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) 411{ 412 XRectangle xrect; 413 XserverRegion region; 414 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 415 416 xrect.x = 0; 417 xrect.y = 0; 418 xrect.width = priv->width; 419 xrect.height = priv->height; 420 421#ifdef __DRI2_FLUSH 422 if (psc->f) 423 (*psc->f->flush) (priv->driDrawable); 424#endif 425 426 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 427 DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src); 428 XFixesDestroyRegion(psc->base.dpy, region); 429 430} 431 432static void 433dri2_wait_x(struct glx_context *gc) 434{ 435 struct dri2_drawable *priv = (struct dri2_drawable *) 436 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 437 438 if (priv == NULL || !priv->have_fake_front) 439 return; 440 441 dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 442} 443 444static void 445dri2_wait_gl(struct glx_context *gc) 446{ 447 struct dri2_drawable *priv = (struct dri2_drawable *) 448 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 449 450 if (priv == NULL || !priv->have_fake_front) 451 return; 452 453 dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 454} 455 456static void 457dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 458{ 459 struct dri2_drawable *pdraw = loaderPrivate; 460 struct glx_display *priv = __glXInitialize(pdraw->base.psc->dpy); 461 struct dri2_display *pdp = (struct dri2_display *)priv->dri2Display; 462 struct glx_context *gc = __glXGetCurrentContext(); 463 464 /* Old servers don't send invalidate events */ 465 if (!pdp->invalidateAvailable) 466 dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable); 467 468 dri2_wait_gl(gc); 469} 470 471 472static void 473dri2DestroyScreen(struct glx_screen *base) 474{ 475 struct dri2_screen *psc = (struct dri2_screen *) base; 476 477 /* Free the direct rendering per screen data */ 478 (*psc->core->destroyScreen) (psc->driScreen); 479 driDestroyConfigs(psc->driver_configs); 480 close(psc->fd); 481 Xfree(psc); 482} 483 484/** 485 * Process list of buffer received from the server 486 * 487 * Processes the list of buffers received in a reply from the server to either 488 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 489 */ 490static void 491process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers, 492 unsigned count) 493{ 494 int i; 495 496 pdraw->bufferCount = count; 497 pdraw->have_fake_front = 0; 498 pdraw->have_back = 0; 499 500 /* This assumes the DRI2 buffer attachment tokens matches the 501 * __DRIbuffer tokens. */ 502 for (i = 0; i < count; i++) { 503 pdraw->buffers[i].attachment = buffers[i].attachment; 504 pdraw->buffers[i].name = buffers[i].name; 505 pdraw->buffers[i].pitch = buffers[i].pitch; 506 pdraw->buffers[i].cpp = buffers[i].cpp; 507 pdraw->buffers[i].flags = buffers[i].flags; 508 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 509 pdraw->have_fake_front = 1; 510 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 511 pdraw->have_back = 1; 512 } 513 514} 515 516unsigned dri2GetSwapEventType(Display* dpy, XID drawable) 517{ 518 struct glx_display *glx_dpy = __glXInitialize(dpy); 519 __GLXDRIdrawable *pdraw; 520 pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 521 if (!pdraw || !(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) 522 return 0; 523 return glx_dpy->codes->first_event + GLX_BufferSwapComplete; 524} 525 526static int64_t 527dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 528 int64_t remainder) 529{ 530 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 531 struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy); 532 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 533 struct dri2_display *pdp = 534 (struct dri2_display *)dpyPriv->dri2Display; 535 CARD64 ret = 0; 536 537#ifdef __DRI2_FLUSH 538 if (psc->f) 539 (*psc->f->flush)(priv->driDrawable); 540#endif 541 542 /* Old servers don't send invalidate events */ 543 if (!pdp->invalidateAvailable) 544 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable); 545 546 /* Old servers can't handle swapbuffers */ 547 if (!pdp->swapAvailable) { 548 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 549 return 0; 550 } 551 552#ifdef X_DRI2SwapBuffers 553 DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, target_msc, divisor, 554 remainder, &ret); 555#endif 556 557 return ret; 558} 559 560static __DRIbuffer * 561dri2GetBuffers(__DRIdrawable * driDrawable, 562 int *width, int *height, 563 unsigned int *attachments, int count, 564 int *out_count, void *loaderPrivate) 565{ 566 struct dri2_drawable *pdraw = loaderPrivate; 567 DRI2Buffer *buffers; 568 569 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 570 width, height, attachments, count, out_count); 571 if (buffers == NULL) 572 return NULL; 573 574 pdraw->width = *width; 575 pdraw->height = *height; 576 process_buffers(pdraw, buffers, *out_count); 577 578 Xfree(buffers); 579 580 return pdraw->buffers; 581} 582 583static __DRIbuffer * 584dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 585 int *width, int *height, 586 unsigned int *attachments, int count, 587 int *out_count, void *loaderPrivate) 588{ 589 struct dri2_drawable *pdraw = loaderPrivate; 590 DRI2Buffer *buffers; 591 592 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 593 pdraw->base.xDrawable, 594 width, height, attachments, 595 count, out_count); 596 if (buffers == NULL) 597 return NULL; 598 599 pdraw->width = *width; 600 pdraw->height = *height; 601 process_buffers(pdraw, buffers, *out_count); 602 603 Xfree(buffers); 604 605 return pdraw->buffers; 606} 607 608#ifdef X_DRI2SwapInterval 609 610static int 611dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 612{ 613 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 614 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 615 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 616 617 if (psc->config) 618 psc->config->configQueryi(psc->driScreen, 619 "vblank_mode", &vblank_mode); 620 621 switch (vblank_mode) { 622 case DRI_CONF_VBLANK_NEVER: 623 return GLX_BAD_VALUE; 624 case DRI_CONF_VBLANK_ALWAYS_SYNC: 625 if (interval <= 0) 626 return GLX_BAD_VALUE; 627 break; 628 default: 629 break; 630 } 631 632 DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval); 633 priv->swap_interval = interval; 634 635 return 0; 636} 637 638static int 639dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 640{ 641 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 642 643 return priv->swap_interval; 644} 645 646#endif /* X_DRI2SwapInterval */ 647 648static const __DRIdri2LoaderExtension dri2LoaderExtension = { 649 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 650 dri2GetBuffers, 651 dri2FlushFrontBuffer, 652 dri2GetBuffersWithFormat, 653}; 654 655static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 656 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 657 dri2GetBuffers, 658 dri2FlushFrontBuffer, 659 NULL, 660}; 661 662#ifdef __DRI_USE_INVALIDATE 663static const __DRIuseInvalidateExtension dri2UseInvalidate = { 664 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 665}; 666#endif 667 668_X_HIDDEN void 669dri2InvalidateBuffers(Display *dpy, XID drawable) 670{ 671 __GLXDRIdrawable *pdraw = 672 dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 673 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 674 struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw; 675 676#if __DRI2_FLUSH_VERSION >= 3 677 if (pdraw && psc->f) 678 psc->f->invalidate(pdp->driDrawable); 679#endif 680} 681 682static void 683dri2_bind_tex_image(Display * dpy, 684 GLXDrawable drawable, 685 int buffer, const int *attrib_list) 686{ 687 struct glx_context *gc = __glXGetCurrentContext(); 688 struct dri2_context *pcp = (struct dri2_context *) gc; 689 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 690 struct glx_display *dpyPriv = __glXInitialize(dpy); 691 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 692 struct dri2_display *pdp = 693 (struct dri2_display *) dpyPriv->dri2Display; 694 struct dri2_screen *psc; 695 696 if (pdraw != NULL) { 697 psc = (struct dri2_screen *) base->psc; 698 699#if __DRI2_FLUSH_VERSION >= 3 700 if (!pdp->invalidateAvailable && psc->f) 701 psc->f->invalidate(pdraw->driDrawable); 702#endif 703 704 if (psc->texBuffer->base.version >= 2 && 705 psc->texBuffer->setTexBuffer2 != NULL) { 706 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 707 pdraw->base.textureTarget, 708 pdraw->base.textureFormat, 709 pdraw->driDrawable); 710 } 711 else { 712 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 713 pdraw->base.textureTarget, 714 pdraw->driDrawable); 715 } 716 } 717} 718 719static void 720dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 721{ 722#if __DRI_TEX_BUFFER_VERSION >= 3 723 struct glx_context *gc = __glXGetCurrentContext(); 724 struct dri2_context *pcp = (struct dri2_context *) gc; 725 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 726 struct glx_display *dpyPriv = __glXInitialize(dpy); 727 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 728 struct dri2_display *pdp = 729 (struct dri2_display *) dpyPriv->dri2Display; 730 struct dri2_screen *psc; 731 732 if (pdraw != NULL) { 733 psc = (struct dri2_screen *) base->psc; 734 735 if (psc->texBuffer->base.version >= 3 && 736 psc->texBuffer->releaseTexBuffer != NULL) { 737 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext, 738 pdraw->base.textureTarget, 739 pdraw->driDrawable); 740 } 741 } 742#endif 743} 744 745static const struct glx_context_vtable dri2_context_vtable = { 746 dri2_destroy_context, 747 dri2_bind_context, 748 dri2_unbind_context, 749 dri2_wait_gl, 750 dri2_wait_x, 751 DRI_glXUseXFont, 752 dri2_bind_tex_image, 753 dri2_release_tex_image, 754}; 755 756static void 757dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions) 758{ 759 int i; 760 761 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 762 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 763 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 764 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 765 766 /* FIXME: if DRI2 version supports it... */ 767 __glXEnableDirectExtension(&psc->base, "INTEL_swap_event"); 768 769 for (i = 0; extensions[i]; i++) { 770 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 771 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 772 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 773 } 774 775 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 776 psc->f = (__DRI2flushExtension *) extensions[i]; 777 /* internal driver extension, no GL extension exposed */ 778 } 779 780 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 781 psc->config = (__DRI2configQueryExtension *) extensions[i]; 782 } 783} 784 785static const struct glx_screen_vtable dri2_screen_vtable = { 786 dri2_create_context 787}; 788 789static struct glx_screen * 790dri2CreateScreen(int screen, struct glx_display * priv) 791{ 792 const __DRIconfig **driver_configs; 793 const __DRIextension **extensions; 794 const struct dri2_display *const pdp = (struct dri2_display *) 795 priv->dri2Display; 796 struct dri2_screen *psc; 797 __GLXDRIscreen *psp; 798 char *driverName, *deviceName; 799 drm_magic_t magic; 800 int i; 801 802 psc = Xmalloc(sizeof *psc); 803 if (psc == NULL) 804 return NULL; 805 806 memset(psc, 0, sizeof *psc); 807 psc->fd = -1; 808 809 if (!glx_screen_init(&psc->base, screen, priv)) { 810 Xfree(psc); 811 return NULL; 812 } 813 814 if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen), 815 &driverName, &deviceName)) { 816 glx_screen_cleanup(&psc->base); 817 XFree(psc); 818 return NULL; 819 } 820 821 psc->driver = driOpenDriver(driverName); 822 if (psc->driver == NULL) { 823 ErrorMessageF("driver pointer missing\n"); 824 goto handle_error; 825 } 826 827 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 828 if (extensions == NULL) { 829 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 830 goto handle_error; 831 } 832 833 for (i = 0; extensions[i]; i++) { 834 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 835 psc->core = (__DRIcoreExtension *) extensions[i]; 836 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 837 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 838 } 839 840 if (psc->core == NULL || psc->dri2 == NULL) { 841 ErrorMessageF("core dri or dri2 extension not found\n"); 842 goto handle_error; 843 } 844 845 psc->fd = open(deviceName, O_RDWR); 846 if (psc->fd < 0) { 847 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 848 goto handle_error; 849 } 850 851 if (drmGetMagic(psc->fd, &magic)) { 852 ErrorMessageF("failed to get magic\n"); 853 goto handle_error; 854 } 855 856 if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) { 857 ErrorMessageF("failed to authenticate magic %d\n", magic); 858 goto handle_error; 859 } 860 861 862 /* If the server does not support the protocol for 863 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 864 */ 865 psc->driScreen = 866 psc->dri2->createNewScreen(screen, psc->fd, 867 (const __DRIextension **) 868 &pdp->loader_extensions[0], 869 &driver_configs, psc); 870 871 if (psc->driScreen == NULL) { 872 ErrorMessageF("failed to create dri screen\n"); 873 goto handle_error; 874 } 875 876 extensions = psc->core->getExtensions(psc->driScreen); 877 dri2BindExtensions(psc, extensions); 878 879 psc->base.configs = 880 driConvertConfigs(psc->core, psc->base.configs, driver_configs); 881 psc->base.visuals = 882 driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 883 884 psc->driver_configs = driver_configs; 885 886 psc->base.vtable = &dri2_screen_vtable; 887 psp = &psc->vtable; 888 psc->base.driScreen = psp; 889 psp->destroyScreen = dri2DestroyScreen; 890 psp->createDrawable = dri2CreateDrawable; 891 psp->swapBuffers = dri2SwapBuffers; 892 psp->getDrawableMSC = NULL; 893 psp->waitForMSC = NULL; 894 psp->waitForSBC = NULL; 895 psp->setSwapInterval = NULL; 896 psp->getSwapInterval = NULL; 897 898 if (pdp->driMinor >= 2) { 899#ifdef X_DRI2GetMSC 900 psp->getDrawableMSC = dri2DrawableGetMSC; 901#endif 902#ifdef X_DRI2WaitMSC 903 psp->waitForMSC = dri2WaitForMSC; 904 psp->waitForSBC = dri2WaitForSBC; 905#endif 906#ifdef X_DRI2SwapInterval 907 psp->setSwapInterval = dri2SetSwapInterval; 908 psp->getSwapInterval = dri2GetSwapInterval; 909#endif 910#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 911 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control"); 912#endif 913 } 914 915 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 916 * available.*/ 917 psp->copySubBuffer = dri2CopySubBuffer; 918 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 919 920 Xfree(driverName); 921 Xfree(deviceName); 922 923 return &psc->base; 924 925handle_error: 926 if (psc->fd >= 0) 927 close(psc->fd); 928 if (psc->driver) 929 dlclose(psc->driver); 930 Xfree(driverName); 931 Xfree(deviceName); 932 glx_screen_cleanup(&psc->base); 933 XFree(psc); 934 935 return NULL; 936} 937 938/* Called from __glXFreeDisplayPrivate. 939 */ 940static void 941dri2DestroyDisplay(__GLXDRIdisplay * dpy) 942{ 943 Xfree(dpy); 944} 945 946_X_HIDDEN __GLXDRIdrawable * 947dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id) 948{ 949 struct glx_display *d = __glXInitialize(dpy); 950 struct dri2_display *pdp = (struct dri2_display *) d->dri2Display; 951 __GLXDRIdrawable *pdraw; 952 953 if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0) 954 return pdraw; 955 956 return NULL; 957} 958 959/* 960 * Allocate, initialize and return a __DRIdisplayPrivate object. 961 * This is called from __glXInitialize() when we are given a new 962 * display pointer. 963 */ 964_X_HIDDEN __GLXDRIdisplay * 965dri2CreateDisplay(Display * dpy) 966{ 967 struct dri2_display *pdp; 968 int eventBase, errorBase, i; 969 970 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 971 return NULL; 972 973 pdp = Xmalloc(sizeof *pdp); 974 if (pdp == NULL) 975 return NULL; 976 977 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 978 Xfree(pdp); 979 return NULL; 980 } 981 982 pdp->driPatch = 0; 983 pdp->swapAvailable = (pdp->driMinor >= 2); 984 pdp->invalidateAvailable = (pdp->driMinor >= 3); 985 986 pdp->base.destroyDisplay = dri2DestroyDisplay; 987 pdp->base.createScreen = dri2CreateScreen; 988 989 i = 0; 990 if (pdp->driMinor < 1) 991 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 992 else 993 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 994 995 pdp->loader_extensions[i++] = &systemTimeExtension.base; 996 997#ifdef __DRI_USE_INVALIDATE 998 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 999#endif 1000 pdp->loader_extensions[i++] = NULL; 1001 1002 pdp->dri2Hash = __glxHashCreate(); 1003 if (pdp->dri2Hash == NULL) { 1004 Xfree(pdp); 1005 return NULL; 1006 } 1007 1008 return &pdp->base; 1009} 1010 1011#endif /* GLX_DIRECT_RENDERING */ 1012