dri_glx.c revision 6ddf66e9230ee862ac341c4767cf6b3b2dd2552b
127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/**************************************************************************
227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiAll Rights Reserved.
527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiPermission is hereby granted, free of charge, to any person obtaining a
727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshicopy of this software and associated documentation files (the
827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi"Software"), to deal in the Software without restriction, including
927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiwithout limitation the rights to use, copy, modify, merge, publish,
1027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshidistribute, sub license, and/or sell copies of the Software, and to
1127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshipermit persons to whom the Software is furnished to do so, subject to
1227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshithe following conditions:
1327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
1427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiThe above copyright notice and this permission notice (including the
1527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshinext paragraph) shall be included in all copies or substantial portions
1627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiof the Software.
172272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi
1827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
2627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi**************************************************************************/
2727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
2827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/*
2927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Authors:
3027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *   Kevin E. Martin <kevin@precisioninsight.com>
318d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang *   Brian Paul <brian@precisioninsight.com>
328d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang *
338d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang */
3427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
3527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
368f00151cbe693d52f3e233757c57fab3b6396d21Gloria Wang
378f00151cbe693d52f3e233757c57fab3b6396d21Gloria Wang#include <X11/Xlib.h>
388f00151cbe693d52f3e233757c57fab3b6396d21Gloria Wang#include <X11/extensions/Xfixes.h>
398f00151cbe693d52f3e233757c57fab3b6396d21Gloria Wang#include <X11/extensions/Xdamage.h>
4027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "glxclient.h"
4127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "xf86dri.h"
4227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "dri2.h"
4327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "sarea.h"
442272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi#include <dlfcn.h>
4527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <sys/types.h>
4627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <sys/mman.h>
4727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "xf86drm.h"
488d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang#include "dri_common.h"
498d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang
5027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistruct dri_display
5127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
5227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __GLXDRIdisplay base;
5327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
5427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   /*
5527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    ** XFree86-DRI version information
5627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    */
5727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int driMajor;
5827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int driMinor;
5927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int driPatch;
6027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi};
6127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
6227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistruct dri_screen
638d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang{
648d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   __GLXscreenConfigs base;
658d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang
668d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   __DRIscreen *driScreen;
678d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   __GLXDRIscreen vtable;
6827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   const __DRIlegacyExtension *legacy;
698d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   const __DRIcoreExtension *core;
7027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   const __DRIswapControlExtension *swapControl;
7127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   const __DRImediaStreamCounterExtension *msc;
72e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi   const __DRIconfig **driver_configs;
73e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi   const __DRIcopySubBufferExtension *driCopySubBuffer;
7427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
7527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   void *driver;
76e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi   int fd;
77e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi};
7827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
7927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistruct dri_context
8027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
81b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   __GLXcontext base;
82b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   __GLXDRIcontext dri_vtable;
8327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIcontext *driContext;
8427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   XID hwContextID;
85c618b5af98dec06d49374a61a5a94016f9fec2d3Takeshi Aimi};
86c618b5af98dec06d49374a61a5a94016f9fec2d3Takeshi Aimi
8727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistruct dri_drawable
8827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
89b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   __GLXDRIdrawable base;
90b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
9127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIdrawable *driDrawable;
9227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi};
9327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
9427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const struct glx_context_vtable dri_context_vtable;
9527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
9627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/*
9727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Given a display pointer and screen number, determine the name of
9827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
9927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Return True for success, False for failure.
10027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi */
10127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic Bool
102b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria WangdriGetDriverName(Display * dpy, int scrNum, char **driverName)
103b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang{
10427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int directCapable;
10527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   Bool b;
10627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int event, error;
10727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int driverMajor, driverMinor, driverPatch;
1083473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi
1093473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi   *driverName = NULL;
1103473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi
1113473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi   if (XF86DRIQueryExtension(dpy, &event, &error)) {    /* DRI1 */
1123473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi      if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
1133473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi         ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
1143473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi         return False;
1153473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi      }
116b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      if (!directCapable) {
117b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang         ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
11827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         return False;
11927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      }
12027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
12127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
12227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                                     &driverPatch, driverName);
12327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      if (!b) {
12427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         ErrorMessageF("Cannot determine driver name for screen %d\n",
125b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                       scrNum);
126b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang         return False;
12727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      }
12827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
12927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
13027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                   driverMajor, driverMinor, driverPatch, *driverName,
13127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                   scrNum);
13227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
13327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      return True;
134b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   }
135b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   else if (DRI2QueryExtension(dpy, &event, &error)) {  /* DRI2 */
13627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      char *dev;
13727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
13827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
13927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      if (ret)
14027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         Xfree(dev);
14127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
14227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      return ret;
1432272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi   }
14427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
1458d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   return False;
146b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang}
14727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
14827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/*
149b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * Exported function for querying the DRI driver for a given screen.
150b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang *
15127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * The returned char pointer points to a static array that will be
15227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * overwritten by subsequent calls.
15327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi */
15427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiPUBLIC const char *
15527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiglXGetScreenDriver(Display * dpy, int scrNum)
15627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
15727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   static char ret[32];
15827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   char *driverName;
15927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   if (driGetDriverName(dpy, scrNum, &driverName)) {
16027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      int len;
16127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      if (!driverName)
162b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang         return NULL;
163b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      len = strlen(driverName);
16427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      if (len >= 31)
16527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         return NULL;
16627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      memcpy(ret, driverName, len + 1);
16727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      Xfree(driverName);
16827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      return ret;
16927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   }
17027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   return NULL;
17127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi}
172b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
173b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang/*
17427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
17527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
17627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * The returned char pointer points directly into the driver. Therefore
17727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * it should be treated as a constant.
1782272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi *
179b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * If the driver was not found or does not support configuration NULL is
180b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * returned.
1812272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi *
182b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * Note: The driver remains opened after this function returns.
183b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang */
184b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria WangPUBLIC const char *
18527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiglXGetDriverConfig(const char *driverName)
1862272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi{
18727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   void *handle = driOpenDriver(driverName);
18827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   if (handle)
1892272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi      return dlsym(handle, "__driConfigOptions");
190b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   else
191b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      return NULL;
1922272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi}
193b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
1942272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi#ifdef XDAMAGE_1_1_INTERFACE
195b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
19627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic GLboolean
1972272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimihas_damage_post(Display * dpy)
19827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
19927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   static GLboolean inited = GL_FALSE;
20027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   static GLboolean has_damage;
201b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
202b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   if (!inited) {
20327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      int major, minor;
20427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
205b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      if (XDamageQueryVersion(dpy, &major, &minor) &&
206b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang          major == 1 && minor >= 1) {
20727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         has_damage = GL_TRUE;
20827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      }
20927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      else {
21027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi         has_damage = GL_FALSE;
2112272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi      }
2122272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi      inited = GL_TRUE;
21327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   }
2142272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi
21527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   return has_damage;
2162272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi}
21727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
21827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic void
2192272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi__glXReportDamage(__DRIdrawable * driDraw,
2202272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi                  int x, int y,
22127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                  drm_clip_rect_t * rects, int num_rects,
22227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                  GLboolean front_buffer, void *loaderPrivate)
223b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang{
224b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   XRectangle *xrects;
22527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   XserverRegion region;
22627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int i;
22727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int x_off, y_off;
22827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __GLXDRIdrawable *glxDraw = loaderPrivate;
22927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __GLXscreenConfigs *psc = glxDraw->psc;
23027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   Display *dpy = psc->dpy;
23127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   Drawable drawable;
23227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
23327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   if (!has_damage_post(dpy))
23427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      return;
23527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
236b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   if (front_buffer) {
237b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      x_off = x;
23827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      y_off = y;
23927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      drawable = RootWindow(dpy, psc->scr);
24027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   }
24127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   else {
242b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      x_off = 0;
243b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      y_off = 0;
24427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      drawable = glxDraw->xDrawable;
24527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   }
24627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
24727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   xrects = malloc(sizeof(XRectangle) * num_rects);
24827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   if (xrects == NULL)
24927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      return;
25027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
251b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   for (i = 0; i < num_rects; i++) {
252b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang      xrects[i].x = rects[i].x1 + x_off;
25327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      xrects[i].y = rects[i].y1 + y_off;
25427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      xrects[i].width = rects[i].x2 - rects[i].x1;
25527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi      xrects[i].height = rects[i].y2 - rects[i].y1;
25627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   }
257b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   region = XFixesCreateRegion(dpy, xrects, num_rects);
258a2cd44cb5067b4fe98794860690394254d3ac73cGloria Wang   free(xrects);
25927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   XDamageAdd(dpy, drawable, region);
26027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   XFixesDestroyRegion(dpy, region);
26127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi}
262b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
263b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangstatic const __DRIdamageExtension damageExtension = {
264e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi   {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
265e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi   __glXReportDamage,
266e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi};
267e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi
268e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi#endif
269e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi
270e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimistatic GLboolean
271b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang__glXDRIGetDrawableInfo(__DRIdrawable * drawable,
272b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                        unsigned int *index, unsigned int *stamp,
2732272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi                        int *X, int *Y, int *W, int *H,
274b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                        int *numClipRects, drm_clip_rect_t ** pClipRects,
275b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                        int *backX, int *backY,
276b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                        int *numBackClipRects,
27727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                        drm_clip_rect_t ** pBackClipRects,
2782272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi                        void *loaderPrivate)
27927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{
28027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __GLXDRIdrawable *glxDraw = loaderPrivate;
281b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   __GLXscreenConfigs *psc = glxDraw->psc;
282b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   Display *dpy = psc->dpy;
283b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
2842272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi   return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
285b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                                 index, stamp, X, Y, W, H,
2862272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi                                 numClipRects, pClipRects,
287b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                                 backX, backY,
28827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                                 numBackClipRects, pBackClipRects);
2892272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi}
29027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
29127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
292b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
293b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   __glXDRIGetDrawableInfo
294b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang};
295b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang
29627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const __DRIextension *loader_extensions[] = {
297b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   &systemTimeExtension.base,
29827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   &getDrawableInfoExtension.base,
29927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#ifdef XDAMAGE_1_1_INTERFACE
300b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang   &damageExtension.base,
301b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang#endif
30227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   NULL
30327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi};
30427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
30527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/**
3062272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi * Perform the required libGL-side initialization and call the client-side
307b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * driver's \c __driCreateNewScreen function.
3082272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi *
309b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * \param dpy    Display pointer.
310b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * \param scrn   Screen number on the display.
311b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang * \param psc    DRI screen information.
31227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * \param driDpy DRI display information.
3132272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi * \param createNewScreen  Pointer to the client-side driver's
31427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *               \c __driCreateNewScreen function.
31527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * \returns A pointer to the \c __DRIscreen structure returned by
316b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang *          the client-side driver on success, or \c NULL on failure.
317a2cd44cb5067b4fe98794860690394254d3ac73cGloria Wang */
31827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic void *
319b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria WangCallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
320b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang                    struct dri_display * driDpy)
321b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang{
32227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   void *psp = NULL;
32327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   drm_handle_t hSAREA;
32427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   drmAddress pSAREA = MAP_FAILED;
32527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   char *BusID;
32627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIversion ddx_version;
32727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIversion dri_version;
32827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIversion drm_version;
32927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   __DRIframebuffer framebuffer;
33027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int fd = -1;
33127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   int status;
33227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
33327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   drm_magic_t magic;
33427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi   drmVersionPtr version;
3358d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   int newlyopened;
3368d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   char *driverName;
3378d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   drm_handle_t hFB;
3388d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   int junk;
3398d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   const __DRIconfig **driver_configs;
3408d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   struct glx_config *visual;
3418d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang
3428d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   /* DRI protocol version. */
3438d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   dri_version.major = driDpy->driMajor;
3448d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   dri_version.minor = driDpy->driMinor;
3458d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   dri_version.patch = driDpy->driPatch;
3468d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang
3478d2577b9ac2f95f218db59a78447efd3c6a742ddGloria Wang   framebuffer.base = MAP_FAILED;
348   framebuffer.dev_priv = NULL;
349   framebuffer.size = 0;
350
351   if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
352      ErrorMessageF("XF86DRIOpenConnection failed\n");
353      goto handle_error;
354   }
355
356   fd = drmOpenOnce(NULL, BusID, &newlyopened);
357
358   Xfree(BusID);                /* No longer needed */
359
360   if (fd < 0) {
361      ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
362      goto handle_error;
363   }
364
365   if (drmGetMagic(fd, &magic)) {
366      ErrorMessageF("drmGetMagic failed\n");
367      goto handle_error;
368   }
369
370   version = drmGetVersion(fd);
371   if (version) {
372      drm_version.major = version->version_major;
373      drm_version.minor = version->version_minor;
374      drm_version.patch = version->version_patchlevel;
375      drmFreeVersion(version);
376   }
377   else {
378      drm_version.major = -1;
379      drm_version.minor = -1;
380      drm_version.patch = -1;
381   }
382
383   if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
384      ErrorMessageF("XF86DRIAuthConnection failed\n");
385      goto handle_error;
386   }
387
388   /* Get device name (like "tdfx") and the ddx version numbers.
389    * We'll check the version in each DRI driver's "createNewScreen"
390    * function. */
391   if (!XF86DRIGetClientDriverName(dpy, scrn,
392                                   &ddx_version.major,
393                                   &ddx_version.minor,
394                                   &ddx_version.patch, &driverName)) {
395      ErrorMessageF("XF86DRIGetClientDriverName failed\n");
396      goto handle_error;
397   }
398
399   Xfree(driverName);           /* No longer needed. */
400
401   /*
402    * Get device-specific info.  pDevPriv will point to a struct
403    * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
404    * has information about the screen size, depth, pitch, ancilliary
405    * buffers, DRM mmap handles, etc.
406    */
407   if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
408                             &framebuffer.size, &framebuffer.stride,
409                             &framebuffer.dev_priv_size,
410                             &framebuffer.dev_priv)) {
411      ErrorMessageF("XF86DRIGetDeviceInfo failed");
412      goto handle_error;
413   }
414
415   framebuffer.width = DisplayWidth(dpy, scrn);
416   framebuffer.height = DisplayHeight(dpy, scrn);
417
418   /* Map the framebuffer region. */
419   status = drmMap(fd, hFB, framebuffer.size,
420                   (drmAddressPtr) & framebuffer.base);
421   if (status != 0) {
422      ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
423      goto handle_error;
424   }
425
426   /* Map the SAREA region.  Further mmap regions may be setup in
427    * each DRI driver's "createNewScreen" function.
428    */
429   status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
430   if (status != 0) {
431      ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
432      goto handle_error;
433   }
434
435   psp = (*psc->legacy->createNewScreen) (scrn,
436                                          &ddx_version,
437                                          &dri_version,
438                                          &drm_version,
439                                          &framebuffer,
440                                          pSAREA,
441                                          fd,
442                                          loader_extensions,
443                                          &driver_configs, psc);
444
445   if (psp == NULL) {
446      ErrorMessageF("Calling driver entry point failed");
447      goto handle_error;
448   }
449
450   psc->base.configs =
451      driConvertConfigs(psc->core, psc->base.configs, driver_configs);
452   psc->base.visuals =
453      driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
454
455   psc->driver_configs = driver_configs;
456
457   /* Visuals with depth != screen depth are subject to automatic compositing
458    * in the X server, so DRI1 can't render to them properly. Mark them as
459    * non-conformant to prevent apps from picking them up accidentally.
460    */
461   for (visual = psc->base.visuals; visual; visual = visual->next) {
462      XVisualInfo template;
463      XVisualInfo *visuals;
464      int num_visuals;
465      long mask;
466
467      template.visualid = visual->visualID;
468      mask = VisualIDMask;
469      visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
470
471      if (visuals) {
472         if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
473            visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
474
475         XFree(visuals);
476      }
477   }
478
479   return psp;
480
481 handle_error:
482   if (pSAREA != MAP_FAILED)
483      drmUnmap(pSAREA, SAREA_MAX);
484
485   if (framebuffer.base != MAP_FAILED)
486      drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
487
488   if (framebuffer.dev_priv != NULL)
489      Xfree(framebuffer.dev_priv);
490
491   if (fd >= 0)
492      drmCloseOnce(fd);
493
494   XF86DRICloseConnection(dpy, scrn);
495
496   ErrorMessageF("reverting to software direct rendering\n");
497
498   return NULL;
499}
500
501static void
502dri_destroy_context(__GLXcontext * context)
503{
504   struct dri_context *pcp = (struct dri_context *) context;
505   struct dri_screen *psc = (struct dri_screen *) context->psc;
506
507   if (context->xid)
508      glx_send_destroy_context(psc->base.dpy, context->xid);
509
510   if (context->extensions)
511      XFree((char *) context->extensions);
512
513   GarbageCollectDRIDrawables(context->psc);
514
515   (*psc->core->destroyContext) (pcp->driContext);
516
517   XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
518   Xfree(pcp);
519}
520
521static Bool
522driBindContext(__GLXcontext *context,
523	       __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
524{
525   struct dri_context *pcp = (struct dri_context *) context;
526   struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
527   struct dri_drawable *pdr = (struct dri_drawable *) draw;
528   struct dri_drawable *prd = (struct dri_drawable *) read;
529
530   return (*psc->core->bindContext) (pcp->driContext,
531				     pdr->driDrawable, prd->driDrawable);
532}
533
534static void
535driUnbindContext(__GLXcontext * context)
536{
537   struct dri_context *pcp = (struct dri_context *) context;
538   struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
539
540   (*psc->core->unbindContext) (pcp->driContext);
541}
542
543static const struct glx_context_vtable dri_context_vtable = {
544   dri_destroy_context,
545   NULL,
546   NULL,
547   DRI_glXUseXFont,
548   NULL,
549   NULL,
550};
551
552static __GLXcontext *
553dri_create_context(__GLXscreenConfigs *base,
554		   struct glx_config *config_base,
555		   GLXContext shareList, int renderType)
556{
557   struct dri_context *pcp, *pcp_shared;
558   struct dri_screen *psc = (struct dri_screen *) base;
559   drm_context_t hwContext;
560   __DRIcontext *shared = NULL;
561   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
562
563   if (!psc->base.driScreen)
564      return NULL;
565
566   if (shareList) {
567      pcp_shared = (struct dri_context *) shareList->driContext;
568      shared = pcp_shared->driContext;
569   }
570
571   pcp = Xmalloc(sizeof *pcp);
572   if (pcp == NULL)
573      return NULL;
574
575   memset(pcp, 0, sizeof *pcp);
576   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
577      Xfree(pcp);
578      return NULL;
579   }
580
581   if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
582                                       config->base.visualID,
583                                       &pcp->hwContextID, &hwContext)) {
584      Xfree(pcp);
585      return NULL;
586   }
587
588   pcp->driContext =
589      (*psc->legacy->createNewContext) (psc->driScreen,
590                                        config->driConfig,
591                                        renderType, shared, hwContext, pcp);
592   if (pcp->driContext == NULL) {
593      XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
594      Xfree(pcp);
595      return NULL;
596   }
597
598   pcp->base.vtable = &dri_context_vtable;
599   pcp->base.driContext = &pcp->dri_vtable;
600   pcp->dri_vtable.bindContext = driBindContext;
601   pcp->dri_vtable.unbindContext = driUnbindContext;
602
603   return &pcp->base;
604}
605
606static void
607driDestroyDrawable(__GLXDRIdrawable * pdraw)
608{
609   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
610   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
611
612   (*psc->core->destroyDrawable) (pdp->driDrawable);
613   XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
614   Xfree(pdraw);
615}
616
617static __GLXDRIdrawable *
618driCreateDrawable(__GLXscreenConfigs *base,
619                  XID xDrawable,
620                  GLXDrawable drawable, struct glx_config *config_base)
621{
622   drm_drawable_t hwDrawable;
623   void *empty_attribute_list = NULL;
624   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
625   struct dri_screen *psc = (struct dri_screen *) base;
626   struct dri_drawable *pdp;
627
628   /* Old dri can't handle GLX 1.3+ drawable constructors. */
629   if (xDrawable != drawable)
630      return NULL;
631
632   pdp = Xmalloc(sizeof *pdp);
633   if (!pdp)
634      return NULL;
635
636   memset(pdp, 0, sizeof *pdp);
637   pdp->base.drawable = drawable;
638   pdp->base.psc = &psc->base;
639
640   if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
641			      drawable, &hwDrawable)) {
642      Xfree(pdp);
643      return NULL;
644   }
645
646   /* Create a new drawable */
647   pdp->driDrawable =
648      (*psc->legacy->createNewDrawable) (psc->driScreen,
649                                         config->driConfig,
650                                         hwDrawable,
651                                         GLX_WINDOW_BIT,
652                                         empty_attribute_list, pdp);
653
654   if (!pdp->driDrawable) {
655      XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
656      Xfree(pdp);
657      return NULL;
658   }
659
660   pdp->base.destroyDrawable = driDestroyDrawable;
661
662   return &pdp->base;
663}
664
665static int64_t
666driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
667	       int64_t unused3)
668{
669   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
670   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
671
672   (*psc->core->swapBuffers) (pdp->driDrawable);
673   return 0;
674}
675
676static void
677driCopySubBuffer(__GLXDRIdrawable * pdraw,
678                 int x, int y, int width, int height)
679{
680   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
681   struct dri_screen *psc = (struct dri_screen *) pdp->base.psc;
682
683   (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable,
684					    x, y, width, height);
685}
686
687static void
688driDestroyScreen(__GLXscreenConfigs *base)
689{
690   struct dri_screen *psc = (struct dri_screen *) base;
691
692   /* Free the direct rendering per screen data */
693   if (psc->driScreen)
694      (*psc->core->destroyScreen) (psc->driScreen);
695   driDestroyConfigs(psc->driver_configs);
696   psc->driScreen = NULL;
697   if (psc->driver)
698      dlclose(psc->driver);
699}
700
701#ifdef __DRI_SWAP_BUFFER_COUNTER
702
703static int
704driDrawableGetMSC(__GLXscreenConfigs *base, __GLXDRIdrawable *pdraw,
705		   int64_t *ust, int64_t *msc, int64_t *sbc)
706{
707   struct dri_screen *psc = (struct dri_screen *) base;
708   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
709
710   if (pdp && psc->sbc && psc->msc)
711      return ( (*psc->msc->getMSC)(psc->driScreen, msc) == 0 &&
712	       (*psc->sbc->getSBC)(pdp->driDrawable, sbc) == 0 &&
713	       __glXGetUST(ust) == 0 );
714}
715
716static int
717driWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
718	       int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
719{
720   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
721   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
722
723   if (pdp != NULL && psc->msc != NULL) {
724      ret = (*psc->msc->waitForMSC) (pdp->driDrawable, target_msc,
725				     divisor, remainder, msc, sbc);
726
727      /* __glXGetUST returns zero on success and non-zero on failure.
728       * This function returns True on success and False on failure.
729       */
730      return ret == 0 && __glXGetUST(ust) == 0;
731   }
732}
733
734static int
735driWaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
736	       int64_t *msc, int64_t *sbc)
737{
738   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
739
740   if (pdp != NULL && psc->sbc != NULL) {
741      ret =
742         (*psc->sbc->waitForSBC) (pdp->driDrawable, target_sbc, msc, sbc);
743
744      /* __glXGetUST returns zero on success and non-zero on failure.
745       * This function returns True on success and False on failure.
746       */
747      return ((ret == 0) && (__glXGetUST(ust) == 0));
748   }
749
750   return DRI2WaitSBC(pdp->base.psc->dpy,
751		      pdp->base.xDrawable, target_sbc, ust, msc, sbc);
752}
753
754#endif
755
756static int
757driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
758{
759   GLXContext gc = __glXGetCurrentContext();
760   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
761   struct dri_screen *psc;
762
763   if (gc->driContext) {
764      psc = (struct dri_screen *) pdraw->psc;
765
766      if (psc->swapControl != NULL && pdraw != NULL) {
767	 psc->swapControl->setSwapInterval(pdp->driDrawable, interval);
768	 return 0;
769      }
770   }
771
772   return GLX_BAD_CONTEXT;
773}
774
775static int
776driGetSwapInterval(__GLXDRIdrawable *pdraw)
777{
778   GLXContext gc = __glXGetCurrentContext();
779   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
780   struct dri_screen *psc;
781
782   if (gc != NULL && gc->driContext) {
783      psc = (struct dri_screen *) pdraw->psc;
784
785      if (psc->swapControl != NULL && pdraw != NULL) {
786	 return psc->swapControl->getSwapInterval(pdp->driDrawable);
787      }
788   }
789
790   return 0;
791}
792
793/* Bind DRI1 specific extensions */
794static void
795driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
796{
797   int i;
798
799   for (i = 0; extensions[i]; i++) {
800      /* No DRI2 support for swap_control at the moment, since SwapBuffers
801       * is done by the X server */
802      if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
803	 psc->swapControl = (__DRIswapControlExtension *) extensions[i];
804	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
805	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
806      }
807
808      if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
809         psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
810         __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
811      }
812
813      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
814	 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
815	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
816      }
817
818      if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
819	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
820      }
821      /* Ignore unknown extensions */
822   }
823}
824
825static const struct glx_screen_vtable dri_screen_vtable = {
826   dri_create_context
827};
828
829static __GLXscreenConfigs *
830driCreateScreen(int screen, __GLXdisplayPrivate *priv)
831{
832   struct dri_display *pdp;
833   __GLXDRIscreen *psp;
834   const __DRIextension **extensions;
835   struct dri_screen *psc;
836   char *driverName;
837   int i;
838
839   psc = Xcalloc(1, sizeof *psc);
840   if (psc == NULL)
841      return NULL;
842
843   memset(psc, 0, sizeof *psc);
844   if (!glx_screen_init(&psc->base, screen, priv))
845       return NULL;
846
847   if (!driGetDriverName(priv->dpy, screen, &driverName)) {
848      Xfree(psc);
849      return NULL;
850   }
851
852   psc->driver = driOpenDriver(driverName);
853   Xfree(driverName);
854   if (psc->driver == NULL) {
855      Xfree(psc);
856      return NULL;
857   }
858
859   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
860   if (extensions == NULL) {
861      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
862      Xfree(psc);
863      return NULL;
864   }
865
866   for (i = 0; extensions[i]; i++) {
867      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
868	 psc->core = (__DRIcoreExtension *) extensions[i];
869      if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
870	 psc->legacy = (__DRIlegacyExtension *) extensions[i];
871   }
872
873   if (psc->core == NULL || psc->legacy == NULL) {
874      Xfree(psc);
875      return NULL;
876   }
877
878   pdp = (struct dri_display *) priv->driDisplay;
879   psc->driScreen =
880      CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
881   if (psc->driScreen == NULL) {
882      dlclose(psc->driver);
883      Xfree(psc);
884      return NULL;
885   }
886
887   extensions = psc->core->getExtensions(psc->driScreen);
888   driBindExtensions(psc, extensions);
889
890   psc->base.vtable = &dri_screen_vtable;
891   psp = &psc->vtable;
892   psc->base.driScreen = psp;
893   if (psc->driCopySubBuffer)
894      psp->copySubBuffer = driCopySubBuffer;
895
896   psp->destroyScreen = driDestroyScreen;
897   psp->createDrawable = driCreateDrawable;
898   psp->swapBuffers = driSwapBuffers;
899
900#ifdef __DRI_SWAP_BUFFER_COUNTER
901   psp->getDrawableMSC = driDrawableGetMSC;
902   psp->waitForMSC = driWaitForMSC;
903   psp->waitForSBC = driWaitForSBC;
904#endif
905
906   psp->setSwapInterval = driSetSwapInterval;
907   psp->getSwapInterval = driGetSwapInterval;
908
909   return &psc->base;
910}
911
912/* Called from __glXFreeDisplayPrivate.
913 */
914static void
915driDestroyDisplay(__GLXDRIdisplay * dpy)
916{
917   Xfree(dpy);
918}
919
920/*
921 * Allocate, initialize and return a __DRIdisplayPrivate object.
922 * This is called from __glXInitialize() when we are given a new
923 * display pointer.
924 */
925_X_HIDDEN __GLXDRIdisplay *
926driCreateDisplay(Display * dpy)
927{
928   struct dri_display *pdpyp;
929   int eventBase, errorBase;
930   int major, minor, patch;
931
932   if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
933      return NULL;
934   }
935
936   if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
937      return NULL;
938   }
939
940   pdpyp = Xmalloc(sizeof *pdpyp);
941   if (!pdpyp) {
942      return NULL;
943   }
944
945   pdpyp->driMajor = major;
946   pdpyp->driMinor = minor;
947   pdpyp->driPatch = patch;
948
949   pdpyp->base.destroyDisplay = driDestroyDisplay;
950   pdpyp->base.createScreen = driCreateScreen;
951
952   return &pdpyp->base;
953}
954
955#endif /* GLX_DIRECT_RENDERING */
956