1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Code to interface a DRI driver to libEGL.
31 * Note that unlike previous DRI/EGL interfaces, this one is meant to
32 * be used _with_ X. Applications will use eglCreateWindowSurface()
33 * to render into X-created windows.
35 * This is an EGL driver that, in turn, loads a regular DRI driver.
36 * There are some dependencies on code in libGL, but those could be
37 * removed with some effort.
45 #include <sys/types.h>
52 #include "glxclient.h"
54 #include "drm_sarea.h"
56 #define _EGL_PLATFORM_X
58 #include "eglconfig.h"
59 #include "eglcontext.h"
60 #include "egldisplay.h"
61 #include "egldriver.h"
62 #include "eglglobals.h"
65 #include "eglsurface.h"
69 typedef void (*glGetIntegerv_t
)(GLenum
, GLint
*);
70 typedef void (*glBindTexture_t
)(GLenum
, GLuint
);
71 typedef void (*glCopyTexImage2D_t
)(GLenum
, GLint
, GLenum
, GLint
, GLint
,
75 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
78 /** subclass of _EGLDriver */
79 struct xdri_egl_driver
81 _EGLDriver Base
; /**< base class */
83 const char *dri_driver_name
; /**< name of DRI driver to load */
84 void *dri_driver_handle
; /**< returned by dlopen(dri_driver_name) */
86 __GLXdisplayPrivate
*glx_priv
;
89 /* XXX we're not actually using these at this time: */
94 __DRIframebuffer framebuffer
;
102 /** subclass of _EGLContext */
103 struct xdri_egl_context
105 _EGLContext Base
; /**< base class */
107 __DRIcontext driContext
;
109 GLint bound_tex_object
;
113 /** subclass of _EGLSurface */
114 struct xdri_egl_surface
116 _EGLSurface Base
; /**< base class */
118 __DRIid driDrawable
; /**< DRI surface */
119 drm_drawable_t hDrawable
;
123 /** subclass of _EGLConfig */
124 struct xdri_egl_config
126 _EGLConfig Base
; /**< base class */
128 const __GLcontextModes
*mode
; /**< corresponding GLX mode */
134 static struct xdri_egl_driver
*
135 xdri_egl_driver(_EGLDriver
*drv
)
137 return (struct xdri_egl_driver
*) drv
;
141 /** Map EGLSurface handle to xdri_egl_surface object */
142 static struct xdri_egl_surface
*
143 lookup_surface(EGLSurface surf
)
145 _EGLSurface
*surface
= _eglLookupSurface(surf
);
146 return (struct xdri_egl_surface
*) surface
;
150 /** Map EGLContext handle to xdri_egl_context object */
151 static struct xdri_egl_context
*
152 lookup_context(EGLContext c
)
154 _EGLContext
*context
= _eglLookupContext(c
);
155 return (struct xdri_egl_context
*) context
;
158 static struct xdri_egl_context
*
159 current_context(void)
161 return (struct xdri_egl_context
*) _eglGetCurrentContext();
164 /** Map EGLConfig handle to xdri_egl_config object */
165 static struct xdri_egl_config
*
166 lookup_config(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
)
168 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
169 return (struct xdri_egl_config
*) conf
;
174 /** Get size of given window */
176 get_drawable_size(Display
*dpy
, Drawable d
, uint
*width
, uint
*height
)
181 unsigned int w
, h
, bw
, depth
;
182 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
190 * Produce a set of EGL configs.
191 * Note that we get the list of GLcontextModes from the GLX library.
192 * This dependency on GLX lib will be removed someday.
195 create_configs(_EGLDisplay
*disp
, __GLXdisplayPrivate
*glx_priv
)
197 static const EGLint all_apis
= (EGL_OPENGL_ES_BIT
|
201 __GLXscreenConfigs
*scrn
= glx_priv
->screenConfigs
;
202 const __GLcontextModes
*m
;
205 for (m
= scrn
->configs
; m
; m
= m
->next
) {
206 /* EGL requires double-buffered configs */
207 if (m
->doubleBufferMode
) {
208 struct xdri_egl_config
*config
= CALLOC_STRUCT(xdri_egl_config
);
210 _eglInitConfig(&config
->Base
, id
++);
212 SET_CONFIG_ATTRIB(&config
->Base
, EGL_BUFFER_SIZE
, m
->rgbBits
);
213 SET_CONFIG_ATTRIB(&config
->Base
, EGL_RED_SIZE
, m
->redBits
);
214 SET_CONFIG_ATTRIB(&config
->Base
, EGL_GREEN_SIZE
, m
->greenBits
);
215 SET_CONFIG_ATTRIB(&config
->Base
, EGL_BLUE_SIZE
, m
->blueBits
);
216 SET_CONFIG_ATTRIB(&config
->Base
, EGL_ALPHA_SIZE
, m
->alphaBits
);
217 SET_CONFIG_ATTRIB(&config
->Base
, EGL_DEPTH_SIZE
, m
->depthBits
);
218 SET_CONFIG_ATTRIB(&config
->Base
, EGL_STENCIL_SIZE
, m
->stencilBits
);
219 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SAMPLES
, m
->samples
);
220 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SAMPLE_BUFFERS
, m
->sampleBuffers
);
221 SET_CONFIG_ATTRIB(&config
->Base
, EGL_NATIVE_VISUAL_ID
, m
->visualID
);
222 SET_CONFIG_ATTRIB(&config
->Base
, EGL_NATIVE_VISUAL_TYPE
, m
->visualType
);
223 SET_CONFIG_ATTRIB(&config
->Base
, EGL_CONFORMANT
, all_apis
);
224 SET_CONFIG_ATTRIB(&config
->Base
, EGL_RENDERABLE_TYPE
, all_apis
);
225 /* XXX only window rendering allowed ATM */
226 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SURFACE_TYPE
,
227 (EGL_WINDOW_BIT
| EGL_PBUFFER_BIT
));
229 /* XXX possibly other things to init... */
231 /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
234 _eglAddConfig(disp
, &config
->Base
);
241 * Called via __DRIinterfaceMethods object
244 dri_get_proc_address(const char * proc_name
)
251 dri_context_modes_destroy(__GLcontextModes
*modes
)
253 _eglLog(_EGL_DEBUG
, "%s", __FUNCTION__
);
256 __GLcontextModes
* const next
= modes
->next
;
264 * Create a linked list of 'count' GLcontextModes.
265 * These are used during the client/server visual negotiation phase,
268 static __GLcontextModes
*
269 dri_context_modes_create(unsigned count
, size_t minimum_size
)
271 /* This code copied from libGLX, and modified */
272 const size_t size
= (minimum_size
> sizeof(__GLcontextModes
))
273 ? minimum_size
: sizeof(__GLcontextModes
);
274 __GLcontextModes
* head
= NULL
;
275 __GLcontextModes
** next
;
279 for (i
= 0 ; i
< count
; i
++) {
280 *next
= (__GLcontextModes
*) calloc(1, size
);
282 dri_context_modes_destroy(head
);
287 (*next
)->doubleBufferMode
= 1;
288 (*next
)->visualID
= GLX_DONT_CARE
;
289 (*next
)->visualType
= GLX_DONT_CARE
;
290 (*next
)->visualRating
= GLX_NONE
;
291 (*next
)->transparentPixel
= GLX_NONE
;
292 (*next
)->transparentRed
= GLX_DONT_CARE
;
293 (*next
)->transparentGreen
= GLX_DONT_CARE
;
294 (*next
)->transparentBlue
= GLX_DONT_CARE
;
295 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
296 (*next
)->transparentIndex
= GLX_DONT_CARE
;
297 (*next
)->xRenderable
= GLX_DONT_CARE
;
298 (*next
)->fbconfigID
= GLX_DONT_CARE
;
299 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
300 (*next
)->bindToTextureRgb
= GLX_DONT_CARE
;
301 (*next
)->bindToTextureRgba
= GLX_DONT_CARE
;
302 (*next
)->bindToMipmapTexture
= GLX_DONT_CARE
;
303 (*next
)->bindToTextureTargets
= 0;
304 (*next
)->yInverted
= GLX_DONT_CARE
;
306 next
= & ((*next
)->next
);
314 dri_find_dri_screen(__DRInativeDisplay
*ndpy
, int scrn
)
316 __GLXdisplayPrivate
*priv
= __glXInitialize(ndpy
);
317 __GLXscreenConfigs
*scrnConf
= priv
->screenConfigs
;
318 return &scrnConf
->driScreen
;
323 dri_window_exists(__DRInativeDisplay
*ndpy
, __DRIid draw
)
330 dri_create_context(__DRInativeDisplay
*ndpy
, int screenNum
, int configID
,
331 void * contextID
, drm_context_t
* hw_context
)
333 assert(configID
>= 0);
334 return XF86DRICreateContextWithConfig(ndpy
, screenNum
,
335 configID
, contextID
, hw_context
);
340 dri_destroy_context(__DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
342 return XF86DRIDestroyContext(ndpy
, screen
, context
);
347 dri_create_drawable(__DRInativeDisplay
* ndpy
, int screen
,
348 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
350 _eglLog(_EGL_DEBUG
, "XDRI: %s", __FUNCTION__
);
352 /* Create DRI drawable for given window ID (drawable) */
353 if (!XF86DRICreateDrawable(ndpy
, screen
, drawable
, hHWDrawable
))
361 dri_destroy_drawable(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
363 _eglLog(_EGL_DEBUG
, "XDRI: %s", __FUNCTION__
);
364 return XF86DRIDestroyDrawable(ndpy
, screen
, drawable
);
369 dri_get_drawable_info(__DRInativeDisplay
*ndpy
, int scrn
,
370 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
371 int * x
, int * y
, int * width
, int * height
,
372 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
373 int * backX
, int * backY
,
374 int * numBackClipRects
,
375 drm_clip_rect_t
** pBackClipRects
)
377 _eglLog(_EGL_DEBUG
, "XDRI: %s", __FUNCTION__
);
379 if (!XF86DRIGetDrawableInfo(ndpy
, scrn
, draw
, index
, stamp
,
381 numClipRects
, pClipRects
,
383 numBackClipRects
, pBackClipRects
)) {
392 * Table of functions exported by the loader to the driver.
394 static const __DRIinterfaceMethods interface_methods
= {
395 dri_get_proc_address
,
397 dri_context_modes_create
,
398 dri_context_modes_destroy
,
407 dri_destroy_drawable
,
408 dri_get_drawable_info
,
410 NULL
,/*__eglGetUST,*/
411 NULL
,/*__eglGetMSCRate,*/
417 init_drm(struct xdri_egl_driver
*xdri_drv
, _EGLDisplay
*disp
)
419 __DRIversion ddx_version
;
420 __DRIversion dri_version
;
421 __DRIversion drm_version
;
422 drmVersionPtr version
;
426 int scrn
= DefaultScreen(disp
->Xdpy
);
429 createNewScreen
= (PFNCREATENEWSCREENFUNC
)
430 dlsym(xdri_drv
->dri_driver_handle
, createNewScreenName
);
431 if (!createNewScreen
) {
432 _eglLog(_EGL_WARNING
, "XDRI: Couldn't find %s function in the driver.",
433 createNewScreenName
);
437 _eglLog(_EGL_DEBUG
, "XDRI: Found %s", createNewScreenName
);
442 * Get the DRI X extension version.
444 dri_version
.major
= 4;
445 dri_version
.minor
= 0;
446 dri_version
.patch
= 0;
448 if (!XF86DRIOpenConnection(disp
->Xdpy
, scrn
,
449 &xdri_drv
->hSAREA
, &xdri_drv
->busID
)) {
450 _eglLog(_EGL_WARNING
, "XF86DRIOpenConnection failed");
453 xdri_drv
->drmFD
= drmOpenOnce(NULL
, xdri_drv
->busID
, &newlyopened
);
454 if (xdri_drv
->drmFD
< 0) {
455 perror("drmOpenOnce failed: ");
459 _eglLog(_EGL_DEBUG
, "XDRI: drmOpenOnce returned %d", xdri_drv
->drmFD
);
463 if (drmGetMagic(xdri_drv
->drmFD
, &xdri_drv
->magic
)) {
464 perror("drmGetMagic failed: ");
468 version
= drmGetVersion(xdri_drv
->drmFD
);
470 drm_version
.major
= version
->version_major
;
471 drm_version
.minor
= version
->version_minor
;
472 drm_version
.patch
= version
->version_patchlevel
;
473 drmFreeVersion(version
);
474 _eglLog(_EGL_DEBUG
, "XDRI: Got DRM version %d.%d.%d",
480 drm_version
.major
= -1;
481 drm_version
.minor
= -1;
482 drm_version
.patch
= -1;
483 _eglLog(_EGL_WARNING
, "XDRI: drmGetVersion() failed");
487 /* Authenticate w/ server.
489 if (!XF86DRIAuthConnection(disp
->Xdpy
, scrn
, xdri_drv
->magic
)) {
490 _eglLog(_EGL_WARNING
, "XDRI: XF86DRIAuthConnection() failed");
494 _eglLog(_EGL_DEBUG
, "XDRI: XF86DRIAuthConnection() success");
503 * Get device name (like "tdfx") and the ddx version
504 * numbers. We'll check the version in each DRI driver's
505 * "createNewScreen" function.
507 if (!XF86DRIGetClientDriverName(disp
->Xdpy
, scrn
,
512 _eglLog(_EGL_WARNING
, "XDRI: XF86DRIGetClientDriverName failed");
516 _eglLog(_EGL_DEBUG
, "XDRI: XF86DRIGetClientDriverName returned %s", driverName
);
520 /* Get framebuffer info.
524 if (!XF86DRIGetDeviceInfo(disp
->Xdpy
, scrn
,
527 &xdri_drv
->framebuffer
.size
,
528 &xdri_drv
->framebuffer
.stride
,
529 &xdri_drv
->framebuffer
.dev_priv_size
,
530 &xdri_drv
->framebuffer
.dev_priv
)) {
531 _eglLog(_EGL_WARNING
, "XDRI: XF86DRIGetDeviceInfo() failed");
535 _eglLog(_EGL_DEBUG
, "XDRI: XF86DRIGetDeviceInfo() success");
537 xdri_drv
->framebuffer
.width
= DisplayWidth(disp
->Xdpy
, scrn
);
538 xdri_drv
->framebuffer
.height
= DisplayHeight(disp
->Xdpy
, scrn
);
541 /* Map the framebuffer region. (this may not be needed)
543 status
= drmMap(xdri_drv
->drmFD
, hFB
, xdri_drv
->framebuffer
.size
,
544 (drmAddressPtr
) &xdri_drv
->framebuffer
.base
);
546 _eglLog(_EGL_WARNING
, "XDRI: drmMap(framebuffer) failed");
550 _eglLog(_EGL_DEBUG
, "XDRI: drmMap(framebuffer) success");
553 /* Map the SAREA region.
555 status
= drmMap(xdri_drv
->drmFD
, xdri_drv
->hSAREA
, SAREA_MAX
, &xdri_drv
->pSAREA
);
557 _eglLog(_EGL_WARNING
, "XDRI: drmMap(sarea) failed");
561 _eglLog(_EGL_DEBUG
, "XDRI: drmMap(sarea) success");
569 * Load the DRI driver named by "xdri_drv->dri_driver_name".
570 * Basically, dlopen() the library to set "xdri_drv->dri_driver_handle".
572 * Later, we'll call dlsym(createNewScreenName) to get a pointer to
573 * the driver's createNewScreen() function which is the bootstrap function.
575 * \return EGL_TRUE for success, EGL_FALSE for failure
578 load_dri_driver(struct xdri_egl_driver
*xdri_drv
)
581 int flags
= RTLD_NOW
;
583 /* try "egl_xxx_dri.so" first */
584 snprintf(filename
, sizeof(filename
), "egl_%s.so", xdri_drv
->dri_driver_name
);
585 _eglLog(_EGL_DEBUG
, "XDRI: dlopen(%s)", filename
);
586 xdri_drv
->dri_driver_handle
= dlopen(filename
, flags
);
587 if (xdri_drv
->dri_driver_handle
) {
588 _eglLog(_EGL_DEBUG
, "XDRI: dlopen(%s) OK", filename
);
592 _eglLog(_EGL_DEBUG
, "XDRI: dlopen(%s) fail (%s)", filename
, dlerror());
595 /* try regular "xxx_dri.so" next */
596 snprintf(filename
, sizeof(filename
), "%s.so", xdri_drv
->dri_driver_name
);
597 _eglLog(_EGL_DEBUG
, "XDRI: dlopen(%s)", filename
);
598 xdri_drv
->dri_driver_handle
= dlopen(filename
, flags
);
599 if (xdri_drv
->dri_driver_handle
) {
600 _eglLog(_EGL_DEBUG
, "XDRI: dlopen(%s) OK", filename
);
604 _eglLog(_EGL_WARNING
, "XDRI Could not open %s (%s)", filename
, dlerror());
610 * Called via eglInitialize(), xdri_drv->API.Initialize().
613 xdri_eglInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
614 EGLint
*minor
, EGLint
*major
)
616 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
617 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
618 static char name
[100];
620 _eglLog(_EGL_DEBUG
, "XDRI: eglInitialize");
623 disp
->Xdpy
= XOpenDisplay(NULL
);
625 _eglLog(_EGL_WARNING
, "XDRI: XOpenDisplay failed");
631 /* choose the DRI driver to load */
632 xdri_drv
->dri_driver_name
= _eglChooseDRMDriver(0);
633 if (!load_dri_driver(xdri_drv
))
636 (void) load_dri_driver
;
640 if (!init_drm(xdri_drv
, disp
))
647 * NOTE: this call to __glXInitialize() bootstraps the whole GLX/DRI
648 * interface, loads the DRI driver, etc.
649 * This replaces the load_dri_driver() and init_drm() code above.
651 xdri_drv
->glx_priv
= __glXInitialize(disp
->Xdpy
);
653 create_configs(disp
, xdri_drv
->glx_priv
);
655 xdri_drv
->Base
.Initialized
= EGL_TRUE
;
657 snprintf(name
, sizeof(name
), "X/DRI:%s", xdri_drv
->dri_driver_name
);
658 xdri_drv
->Base
.Name
= name
;
660 /* we're supporting EGL 1.4 */
669 * Do some clean-up that normally occurs in XCloseDisplay().
670 * We do this here because we're about to unload a dynamic library
671 * that has added some per-display extension data and callbacks.
672 * If we don't do this here we'll crash in XCloseDisplay() because it'll
673 * try to call functions that went away when the driver library was unloaded.
676 FreeDisplayExt(Display
*dpy
)
678 _XExtension
*ext
, *next
;
680 for (ext
= dpy
->ext_procs
; ext
; ext
= next
) {
682 if (ext
->close_display
) {
683 ext
->close_display(dpy
, &ext
->codes
);
684 ext
->close_display
= NULL
;
690 dpy
->ext_procs
= NULL
;
692 _XFreeExtData (dpy
->ext_data
);
693 dpy
->ext_data
= NULL
;
698 * Called via eglTerminate(), drv->API.Terminate().
701 xdri_eglTerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
703 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
704 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
706 _eglLog(_EGL_DEBUG
, "XDRI: eglTerminate");
708 _eglLog(_EGL_DEBUG
, "XDRI: Closing %s", xdri_drv
->dri_driver_name
);
710 FreeDisplayExt(disp
->Xdpy
);
713 /* this causes a segfault for some reason */
714 dlclose(xdri_drv
->dri_driver_handle
);
716 xdri_drv
->dri_driver_handle
= NULL
;
718 free((void*) xdri_drv
->dri_driver_name
);
725 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
728 xdri_eglGetProcAddress(const char *procname
)
731 _EGLDriver
*drv
= NULL
;
733 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
734 /*_EGLDisplay *disp = _eglLookupDisplay(dpy);*/
735 _EGLProc
*proc
= xdri_drv
->driScreen
.getProcAddress(procname
);
738 /* This is a bit of a hack to get at the gallium/Mesa state tracker
739 * function st_get_proc_address(). This will probably change at
742 _EGLProc (*st_get_proc_addr
)(const char *procname
);
743 st_get_proc_addr
= dlsym(NULL
, "st_get_proc_address");
744 if (st_get_proc_addr
) {
745 return st_get_proc_addr(procname
);
755 * Called via eglCreateContext(), drv->API.CreateContext().
758 xdri_eglCreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
759 EGLContext share_list
, const EGLint
*attrib_list
)
761 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
762 struct xdri_egl_config
*xdri_config
= lookup_config(drv
, dpy
, config
);
764 int renderType
= GLX_RGBA_BIT
;
766 struct xdri_egl_context
*xdri_ctx
= CALLOC_STRUCT(xdri_egl_context
);
768 return EGL_NO_CONTEXT
;
770 if (!_eglInitContext(drv
, dpy
, &xdri_ctx
->Base
, config
, attrib_list
)) {
772 return EGL_NO_CONTEXT
;
778 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
779 __GLXscreenConfigs
*scrnConf
= xdri_drv
->glx_priv
->screenConfigs
;
780 xdri_ctx
->driContext
.private =
781 scrnConf
->driScreen
.createNewContext(disp
->Xdpy
,
782 xdri_config
->mode
, renderType
,
783 shared
, &xdri_ctx
->driContext
);
786 if (!xdri_ctx
->driContext
.private) {
787 _eglLog(_EGL_DEBUG
, "driScreen.createNewContext failed");
789 return EGL_NO_CONTEXT
;
792 xdri_ctx
->driContext
.mode
= xdri_config
->mode
;
794 return _eglGetContextHandle(&xdri_ctx
->Base
);
799 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
802 xdri_eglMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface d
,
803 EGLSurface r
, EGLContext context
)
805 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
806 struct xdri_egl_context
*xdri_ctx
= lookup_context(context
);
807 struct xdri_egl_surface
*xdri_draw
= lookup_surface(d
);
808 struct xdri_egl_surface
*xdri_read
= lookup_surface(r
);
809 __DRIid draw
= xdri_draw
? xdri_draw
->driDrawable
: 0;
810 __DRIid read
= xdri_read
? xdri_read
->driDrawable
: 0;
811 int scrn
= DefaultScreen(disp
->Xdpy
);
813 if (!_eglMakeCurrent(drv
, dpy
, d
, r
, context
))
818 !xdri_ctx
->driContext
.bindContext(disp
->Xdpy
, scrn
, draw
, read
,
819 &xdri_ctx
->driContext
)) {
828 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
831 xdri_eglCreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
832 NativeWindowType window
, const EGLint
*attrib_list
)
834 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
835 struct xdri_egl_surface
*xdri_surf
;
836 int scrn
= DefaultScreen(disp
->Xdpy
);
839 xdri_surf
= CALLOC_STRUCT(xdri_egl_surface
);
841 return EGL_NO_SURFACE
;
843 if (!_eglInitSurface(drv
, dpy
, &xdri_surf
->Base
, EGL_WINDOW_BIT
,
844 config
, attrib_list
)) {
849 if (!XF86DRICreateDrawable(disp
->Xdpy
, scrn
, window
, &xdri_surf
->hDrawable
)) {
854 xdri_surf
->driDrawable
= window
;
856 _eglSaveSurface(&xdri_surf
->Base
);
858 get_drawable_size(disp
->Xdpy
, window
, &width
, &height
);
859 xdri_surf
->Base
.Width
= width
;
860 xdri_surf
->Base
.Height
= height
;
863 "XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d",
864 (int) window
, _eglGetSurfaceHandle(&xdri_surf
->Base
),
865 (int) xdri_surf
->hDrawable
);
867 return _eglGetSurfaceHandle(&xdri_surf
->Base
);
872 * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
875 xdri_eglCreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
876 const EGLint
*attrib_list
)
878 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
879 struct xdri_egl_surface
*xdri_surf
;
880 struct xdri_egl_config
*xdri_config
= lookup_config(drv
, dpy
, config
);
881 int scrn
= DefaultScreen(disp
->Xdpy
);
884 xdri_surf
= CALLOC_STRUCT(xdri_egl_surface
);
886 return EGL_NO_SURFACE
;
888 if (!_eglInitSurface(drv
, dpy
, &xdri_surf
->Base
, EGL_PBUFFER_BIT
,
889 config
, attrib_list
)) {
894 /* Create a dummy X window */
896 Window root
= RootWindow(disp
->Xdpy
, scrn
);
897 XSetWindowAttributes attr
;
898 XVisualInfo
*visInfo
, visTemplate
;
902 visTemplate
.visualid
= xdri_config
->mode
->visualID
;
903 visInfo
= XGetVisualInfo(disp
->Xdpy
, VisualIDMask
, &visTemplate
, &nvis
);
905 return EGL_NO_SURFACE
;
908 attr
.background_pixel
= 0;
909 attr
.border_pixel
= 0;
910 attr
.colormap
= XCreateColormap(disp
->Xdpy
, root
,
911 visInfo
->visual
, AllocNone
);
912 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
913 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
915 window
= XCreateWindow(disp
->Xdpy
, root
, 0, 0,
916 xdri_surf
->Base
.Width
, xdri_surf
->Base
.Height
,
917 0, visInfo
->depth
, InputOutput
,
918 visInfo
->visual
, mask
, &attr
);
920 /*XMapWindow(disp->Xdpy, window);*/
923 /* set hints and properties */
925 sizehints.width = xdri_surf->Base.Width;
926 sizehints.height = xdri_surf->Base.Height;
927 sizehints.flags = USPosition;
928 XSetNormalHints(disp->Xdpy, window, &sizehints);
932 if (!XF86DRICreateDrawable(disp
->Xdpy
, scrn
, window
, &xdri_surf
->hDrawable
)) {
937 xdri_surf
->driDrawable
= window
;
939 _eglSaveSurface(&xdri_surf
->Base
);
942 "XDRI: CreatePbufferSurface handle %d hDrawable %d",
943 _eglGetSurfaceHandle(&xdri_surf
->Base
),
944 (int) xdri_surf
->hDrawable
);
946 return _eglGetSurfaceHandle(&xdri_surf
->Base
);
952 xdri_eglDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
954 struct xdri_egl_surface
*xdri_surf
= lookup_surface(surface
);
956 _eglHashRemove(_eglGlobal
.Surfaces
, (EGLuint
) surface
);
957 if (xdri_surf
->Base
.IsBound
) {
958 xdri_surf
->Base
.DeletePending
= EGL_TRUE
;
962 st_unreference_framebuffer(&surf->Framebuffer);
969 _eglError(EGL_BAD_SURFACE
, "eglDestroySurface");
976 xdri_eglBindTexImage(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
,
979 typedef int (*bind_teximage
)(__DRInativeDisplay
*dpy
,
980 __DRIid surface
, __DRIscreen
*psc
,
981 int buffer
, int target
, int format
,
982 int level
, int mipmap
);
984 bind_teximage egl_dri_bind_teximage
;
986 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
988 struct xdri_egl_context
*xdri_ctx
= current_context();
989 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
990 struct xdri_egl_surface
*xdri_surf
= lookup_surface(surface
);
992 __DRIid dri_surf
= xdri_surf
? xdri_surf
->driDrawable
: 0;
994 __GLXscreenConfigs
*scrnConf
= xdri_drv
->glx_priv
->screenConfigs
;
995 __DRIscreen
*psc
= &scrnConf
->driScreen
;
997 /* this call just does error checking */
998 if (!_eglBindTexImage(drv
, dpy
, surface
, buffer
)) {
1002 egl_dri_bind_teximage
=
1003 (bind_teximage
) dlsym(NULL
, "egl_dri_bind_teximage");
1004 if (egl_dri_bind_teximage
) {
1005 return egl_dri_bind_teximage(disp
->Xdpy
, dri_surf
, psc
,
1007 xdri_surf
->Base
.TextureTarget
,
1008 xdri_surf
->Base
.TextureFormat
,
1009 xdri_surf
->Base
.MipmapLevel
,
1010 xdri_surf
->Base
.MipmapTexture
);
1013 /* fallback path based on glCopyTexImage() */
1014 /* Get/save currently bound 2D texobj name */
1015 glGetIntegerv_t glGetIntegerv_func
=
1016 (glGetIntegerv_t
) dlsym(NULL
, "glGetIntegerv");
1017 GLint curTexObj
= 0;
1018 if (glGetIntegerv_func
) {
1019 (*glGetIntegerv_func
)(GL_TEXTURE_BINDING_2D
, &curTexObj
);
1021 xdri_ctx
->bound_tex_object
= curTexObj
;
1029 xdri_eglReleaseTexImage(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
,
1032 typedef int (*release_teximage
)(__DRInativeDisplay
*dpy
,
1033 __DRIid surface
, __DRIscreen
*psc
,
1034 int buffer
, int target
, int format
,
1035 int level
, int mipmap
);
1036 release_teximage egl_dri_release_teximage
;
1038 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1040 struct xdri_egl_context
*xdri_ctx
= current_context();
1041 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
1042 struct xdri_egl_surface
*xdri_surf
= lookup_surface(surface
);
1044 __DRIid dri_surf
= xdri_surf
? xdri_surf
->driDrawable
: 0;
1046 __GLXscreenConfigs
*scrnConf
= xdri_drv
->glx_priv
->screenConfigs
;
1047 __DRIscreen
*psc
= &scrnConf
->driScreen
;
1049 /* this call just does error checking */
1050 if (!_eglReleaseTexImage(drv
, dpy
, surface
, buffer
)) {
1054 egl_dri_release_teximage
=
1055 (release_teximage
) dlsym(NULL
, "egl_dri_release_teximage");
1056 if (egl_dri_release_teximage
) {
1057 return egl_dri_release_teximage(disp
->Xdpy
, dri_surf
, psc
,
1059 xdri_surf
->Base
.TextureTarget
,
1060 xdri_surf
->Base
.TextureFormat
,
1061 xdri_surf
->Base
.MipmapLevel
,
1062 xdri_surf
->Base
.MipmapTexture
);
1065 /* fallback path based on glCopyTexImage() */
1066 glGetIntegerv_t glGetIntegerv_func
=
1067 (glGetIntegerv_t
) dlsym(NULL
, "glGetIntegerv");
1068 glBindTexture_t glBindTexture_func
=
1069 (glBindTexture_t
) dlsym(NULL
, "glBindTexture");
1070 glCopyTexImage2D_t glCopyTexImage2D_func
=
1071 (glCopyTexImage2D_t
) dlsym(NULL
, "glCopyTexImage2D");
1074 GLint level
, width
, height
;
1076 if (xdri_surf
->Base
.TextureFormat
== EGL_TEXTURE_RGBA
)
1077 intFormat
= GL_RGBA
;
1080 level
= xdri_surf
->Base
.MipmapLevel
;
1081 width
= xdri_surf
->Base
.Width
>> level
;
1082 height
= xdri_surf
->Base
.Height
>> level
;
1084 if (width
> 0 && height
> 0 &&
1085 glGetIntegerv_func
&& glBindTexture_func
&& glCopyTexImage2D_func
) {
1086 glGetIntegerv_func(GL_TEXTURE_BINDING_2D
, &curTexObj
);
1087 /* restore texobj from time of eglBindTexImage() call */
1088 if (curTexObj
!= xdri_ctx
->bound_tex_object
)
1089 glBindTexture_func(GL_TEXTURE_2D
, xdri_ctx
->bound_tex_object
);
1090 /* copy pbuffer image to texture */
1091 glCopyTexImage2D_func(GL_TEXTURE_2D
,
1094 0, 0, width
, height
, 0);
1095 /* restore current texture */
1096 if (curTexObj
!= xdri_ctx
->bound_tex_object
)
1097 glBindTexture_func(GL_TEXTURE_2D
, curTexObj
);
1099 xdri_ctx
->bound_tex_object
= -1;
1107 xdri_eglSwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
1109 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1111 _eglLog(_EGL_DEBUG
, "XDRI: EGL SwapBuffers");
1113 /* error checking step: */
1114 if (!_eglSwapBuffers(drv
, dpy
, draw
))
1118 struct xdri_egl_surface
*xdri_surf
= lookup_surface(draw
);
1119 struct xdri_egl_driver
*xdri_drv
= xdri_egl_driver(drv
);
1120 __GLXscreenConfigs
*scrnConf
= xdri_drv
->glx_priv
->screenConfigs
;
1121 __DRIscreen
*psc
= &scrnConf
->driScreen
;
1122 __DRIdrawable
* const pdraw
= psc
->getDrawable(disp
->Xdpy
,
1123 xdri_surf
->driDrawable
,
1127 pdraw
->swapBuffers(disp
->Xdpy
, pdraw
->private);
1129 _eglLog(_EGL_WARNING
, "pdraw is null in SwapBuffers");
1137 * This is the main entrypoint into the driver, called by libEGL.
1138 * Create a new _EGLDriver object and init its dispatch table.
1141 _eglMain(_EGLDisplay
*disp
, const char *args
)
1143 struct xdri_egl_driver
*xdri_drv
= CALLOC_STRUCT(xdri_egl_driver
);
1147 /* Tell libGL to prefer the EGL drivers over regular DRI drivers */
1150 _eglInitDriverFallbacks(&xdri_drv
->Base
);
1151 xdri_drv
->Base
.API
.Initialize
= xdri_eglInitialize
;
1152 xdri_drv
->Base
.API
.Terminate
= xdri_eglTerminate
;
1154 xdri_drv
->Base
.API
.GetProcAddress
= xdri_eglGetProcAddress
;
1156 xdri_drv
->Base
.API
.CreateContext
= xdri_eglCreateContext
;
1157 xdri_drv
->Base
.API
.MakeCurrent
= xdri_eglMakeCurrent
;
1158 xdri_drv
->Base
.API
.CreateWindowSurface
= xdri_eglCreateWindowSurface
;
1159 xdri_drv
->Base
.API
.CreatePbufferSurface
= xdri_eglCreatePbufferSurface
;
1160 xdri_drv
->Base
.API
.DestroySurface
= xdri_eglDestroySurface
;
1161 xdri_drv
->Base
.API
.BindTexImage
= xdri_eglBindTexImage
;
1162 xdri_drv
->Base
.API
.ReleaseTexImage
= xdri_eglReleaseTexImage
;
1163 xdri_drv
->Base
.API
.SwapBuffers
= xdri_eglSwapBuffers
;
1165 xdri_drv
->Base
.ClientAPIsMask
= (EGL_OPENGL_BIT
|
1167 EGL_OPENGL_ES2_BIT
|
1169 xdri_drv
->Base
.Name
= "X/DRI";
1171 _eglLog(_EGL_DEBUG
, "XDRI: main(%s)", args
);
1173 return &xdri_drv
->Base
;