blob: b2e2b5e771a2c4802031511aa90e823aadee8538 [file] [log] [blame]
RALOVICH, Kristóf58b72102008-10-11 14:27:07 +02001/* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002/*
Adam Jacksondc8058c2008-09-19 17:16:53 -04003 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
4 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice including the dates of first publication and
14 * either this permission notice or a reference to
15 * http://oss.sgi.com/projects/FreeB/
16 * shall be included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Except as contained in this notice, the name of Silicon Graphics, Inc.
27 * shall not be used in advertising or otherwise to promote the sale, use or
28 * other dealings in this Software without prior written authorization from
29 * Silicon Graphics, Inc.
30 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +000031
32/**
33 * \file glxcmds.c
34 * Client-side GLX interface.
35 */
36
Adam Jacksoncb3610e2004-10-25 21:09:16 +000037#include "glxclient.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000038#include "glapi.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000039#include "glxextensions.h"
40#include "glcontextmodes.h"
George Sapountzisdf04ffb2008-04-18 17:28:34 +030041
42#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +000043#include <sys/time.h>
George Sapountzisdf04ffb2008-04-18 17:28:34 +030044#include <X11/extensions/xf86vmode.h>
45#include "xf86dri.h"
46#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +000047
Adam Jacksoncb3610e2004-10-25 21:09:16 +000048static const char __glXGLXClientVendorName[] = "SGI";
49static const char __glXGLXClientVersion[] = "1.4";
50
51
Adam Jacksoncb3610e2004-10-25 21:09:16 +000052/****************************************************************************/
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050053
54#ifdef GLX_DIRECT_RENDERING
55
56static Bool windowExistsFlag;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020057static int
58windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050059{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020060 if (xerr->error_code == BadWindow) {
61 windowExistsFlag = GL_FALSE;
62 }
63 return 0;
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050064}
65
66/**
67 * Find drawables in the local hash that have been destroyed on the
68 * server.
69 *
70 * \param dpy Display to destroy drawables for
71 * \param screen Screen number to destroy drawables for
72 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020073static void
74GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050075{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020076 XID draw;
77 __GLXDRIdrawable *pdraw;
78 XWindowAttributes xwa;
79 int (*oldXErrorHandler) (Display *, XErrorEvent *);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050080
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020081 /* Set no-op error handler so Xlib doesn't bail out if the windows
82 * has alreay been destroyed on the server. */
83 XSync(dpy, GL_FALSE);
84 oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050085
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020086 if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
87 do {
88 windowExistsFlag = GL_TRUE;
89 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
90 if (!windowExistsFlag) {
91 /* Destroy the local drawable data, if the drawable no
92 longer exists in the Xserver */
93 (*pdraw->destroyDrawable) (pdraw);
94 __glxHashDelete(sc->drawHash, draw);
95 }
96 } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
97 }
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050098
RALOVICH, Kristóf12933562008-10-13 14:06:30 +020099 XSync(dpy, GL_FALSE);
100 XSetErrorHandler(oldXErrorHandler);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500101}
102
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200103extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
104 GLXDrawable drawable,
105 int *const scrn_num);
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400106
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000107/**
108 * Get the __DRIdrawable for the drawable associated with a GLXContext
109 *
110 * \param dpy The display associated with \c drawable.
111 * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500112 * \param scrn_num If non-NULL, the drawables screen is stored there
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000113 * \returns A pointer to the context's __DRIdrawable on success, or NULL if
114 * the drawable is not associated with a direct-rendering context.
115 */
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400116_X_HIDDEN __GLXDRIdrawable *
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200117GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000118{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200119 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
120 __GLXDRIdrawable *pdraw;
121 const unsigned screen_count = ScreenCount(dpy);
122 unsigned i;
123 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000124
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200125 if (priv == NULL)
126 return NULL;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400127
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200128 for (i = 0; i < screen_count; i++) {
129 psc = &priv->screenConfigs[i];
130 if (psc->drawHash == NULL)
131 continue;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000132
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200133 if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
134 if (scrn_num != NULL)
135 *scrn_num = i;
136 return pdraw;
137 }
138 }
139
140 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000141}
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500142
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000143#endif
144
145
146/**
147 * Get the GLX per-screen data structure associated with a GLX context.
148 *
149 * \param dpy Display for which the GLX per-screen information is to be
150 * retrieved.
151 * \param scrn Screen on \c dpy for which the GLX per-screen information is
152 * to be retrieved.
153 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
154 * specify a valid GLX screen, or NULL otherwise.
155 *
156 * \todo Should this function validate that \c scrn is within the screen
157 * number range for \c dpy?
158 */
159
160static __GLXscreenConfigs *
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200161GetGLXScreenConfigs(Display * dpy, int scrn)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000162{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200163 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000164
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200165 return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000166}
167
168
169static int
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200170GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
171 __GLXscreenConfigs ** ppsc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000172{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200173 /* Initialize the extension, if needed . This has the added value
174 * of initializing/allocating the display private
175 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000176
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200177 if (dpy == NULL) {
178 return GLX_NO_EXTENSION;
179 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000180
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200181 *ppriv = __glXInitialize(dpy);
182 if (*ppriv == NULL) {
183 return GLX_NO_EXTENSION;
184 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000185
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200186 /* Check screen number to see if its valid */
187 if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
188 return GLX_BAD_SCREEN;
189 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000190
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200191 /* Check to see if the GL is supported on this screen */
192 *ppsc = &((*ppriv)->screenConfigs[scrn]);
193 if ((*ppsc)->configs == NULL) {
194 /* No support for GL on this screen regardless of visual */
195 return GLX_BAD_VISUAL;
196 }
197
198 return Success;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000199}
200
201
202/**
203 * Determine if a \c GLXFBConfig supplied by the application is valid.
204 *
205 * \param dpy Application supplied \c Display pointer.
206 * \param config Application supplied \c GLXFBConfig.
207 *
208 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
209 * \c __GLcontextModes structure is returned. Otherwise, \c NULL
210 * is returned.
211 */
212static __GLcontextModes *
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200213ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000214{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200215 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
216 const unsigned num_screens = ScreenCount(dpy);
217 unsigned i;
218 const __GLcontextModes *modes;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000219
220
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200221 if (priv != NULL) {
222 for (i = 0; i < num_screens; i++) {
223 for (modes = priv->screenConfigs[i].configs; modes != NULL;
224 modes = modes->next) {
225 if (modes == (__GLcontextModes *) config) {
226 return (__GLcontextModes *) config;
227 }
228 }
229 }
230 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000231
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200232 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000233}
234
235
236/**
237 * \todo It should be possible to move the allocate of \c client_state_private
238 * later in the function for direct-rendering contexts. Direct-rendering
239 * contexts don't need to track client state, so they don't need that memory
240 * at all.
241 *
242 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
243 * function called \c __glXAllocateClientState that allocates the memory and
244 * does all the initialization (including the pixel pack / unpack).
245 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200246static GLXContext
247AllocateGLXContext(Display * dpy)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000248{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200249 GLXContext gc;
250 int bufSize;
251 CARD8 opcode;
252 __GLXattribute *state;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000253
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200254 if (!dpy)
255 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000256
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200257 opcode = __glXSetupForCommand(dpy);
258 if (!opcode) {
259 return NULL;
260 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000261
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200262 /* Allocate our context record */
263 gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
264 if (!gc) {
265 /* Out of memory */
266 return NULL;
267 }
268 memset(gc, 0, sizeof(struct __GLXcontextRec));
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000269
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200270 state = Xmalloc(sizeof(struct __GLXattributeRec));
271 if (state == NULL) {
272 /* Out of memory */
273 Xfree(gc);
274 return NULL;
275 }
276 gc->client_state_private = state;
277 memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
278 state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000279
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200280 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000281 ** Create a temporary buffer to hold GLX rendering commands. The size
282 ** of the buffer is selected so that the maximum number of GLX rendering
283 ** commands can fit in a single X packet and still have room in the X
284 ** packet for the GLXRenderReq header.
285 */
286
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200287 bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
288 gc->buf = (GLubyte *) Xmalloc(bufSize);
289 if (!gc->buf) {
290 Xfree(gc->client_state_private);
291 Xfree(gc);
292 return NULL;
293 }
294 gc->bufSize = bufSize;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000295
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200296 /* Fill in the new context */
297 gc->renderMode = GL_RENDER;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000298
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200299 state->storePack.alignment = 4;
300 state->storeUnpack.alignment = 4;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000301
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200302 gc->attributes.stackPointer = &gc->attributes.stack[0];
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000303
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200304 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000305 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
306 ** Other code uses the fastImageUnpack bit, but it is never set
307 ** to GL_TRUE.
308 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200309 gc->fastImageUnpack = GL_FALSE;
310 gc->fillImage = __glFillImage;
311 gc->pc = gc->buf;
312 gc->bufEnd = gc->buf + bufSize;
313 gc->isDirect = GL_FALSE;
314 if (__glXDebug) {
315 /*
316 ** Set limit register so that there will be one command per packet
317 */
318 gc->limit = gc->buf;
319 }
320 else {
321 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
322 }
323 gc->createDpy = dpy;
324 gc->majorOpcode = opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000325
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200326 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000327 ** Constrain the maximum drawing command size allowed to be
328 ** transfered using the X_GLXRender protocol request. First
329 ** constrain by a software limit, then constrain by the protocl
330 ** limit.
331 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200332 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
333 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
334 }
335 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
336 bufSize = __GLX_MAX_RENDER_CMD_SIZE;
337 }
338 gc->maxSmallRenderCommandSize = bufSize;
339 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000340}
341
342
343/**
344 * Create a new context. Exactly one of \c vis and \c fbconfig should be
345 * non-NULL.
346 *
347 * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or
348 * SGIX_fbconfig protocol be used?
349 * \param renderType For FBConfigs, what is the rendering type?
350 */
351
352static GLXContext
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200353CreateContext(Display * dpy, XVisualInfo * vis,
354 const __GLcontextModes * const fbconfig,
355 GLXContext shareList,
356 Bool allowDirect, GLXContextID contextID,
357 Bool use_glx_1_3, int renderType)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000358{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200359 GLXContext gc;
Kristian Høgsberg37311592008-03-10 17:59:46 -0400360#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200361 int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
362 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
Kristian Høgsberg37311592008-03-10 17:59:46 -0400363#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000364
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200365 if (dpy == NULL)
366 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000367
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200368 gc = AllocateGLXContext(dpy);
369 if (!gc)
370 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000371
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200372 if (None == contextID) {
373 if ((vis == NULL) && (fbconfig == NULL))
374 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000375
376#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200377 if (allowDirect && psc->driScreen) {
378 const __GLcontextModes *mode;
Kristian Høgsberg8e66c3d2007-11-05 17:02:03 -0500379
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200380 if (fbconfig == NULL) {
381 mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
382 if (mode == NULL) {
383 xError error;
Kristian Høgsberg8e66c3d2007-11-05 17:02:03 -0500384
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200385 error.errorCode = BadValue;
386 error.resourceID = vis->visualid;
387 error.sequenceNumber = dpy->request;
388 error.type = X_Error;
389 error.majorCode = gc->majorOpcode;
390 error.minorCode = X_GLXCreateContext;
391 _XError(dpy, &error);
392 return None;
393 }
394 }
395 else {
396 mode = fbconfig;
397 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000398
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200399 gc->driContext = psc->driScreen->createContext(psc, mode, gc,
400 shareList,
401 renderType);
402 if (gc->driContext != NULL) {
403 gc->screen = mode->screen;
404 gc->psc = psc;
405 gc->mode = mode;
406 gc->isDirect = GL_TRUE;
407 }
408 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000409#endif
410
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200411 LockDisplay(dpy);
412 if (fbconfig == NULL) {
413 xGLXCreateContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000414
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200415 /* Send the glXCreateContext request */
416 GetReq(GLXCreateContext, req);
417 req->reqType = gc->majorOpcode;
418 req->glxCode = X_GLXCreateContext;
419 req->context = gc->xid = XAllocID(dpy);
420 req->visual = vis->visualid;
421 req->screen = vis->screen;
422 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700423#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200424 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700425#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200426 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700427#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200428 }
429 else if (use_glx_1_3) {
430 xGLXCreateNewContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000431
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200432 /* Send the glXCreateNewContext request */
433 GetReq(GLXCreateNewContext, req);
434 req->reqType = gc->majorOpcode;
435 req->glxCode = X_GLXCreateNewContext;
436 req->context = gc->xid = XAllocID(dpy);
437 req->fbconfig = fbconfig->fbconfigID;
438 req->screen = fbconfig->screen;
439 req->renderType = renderType;
440 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700441#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200442 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700443#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200444 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700445#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200446 }
447 else {
448 xGLXVendorPrivateWithReplyReq *vpreq;
449 xGLXCreateContextWithConfigSGIXReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000450
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200451 /* Send the glXCreateNewContext request */
452 GetReqExtra(GLXVendorPrivateWithReply,
453 sz_xGLXCreateContextWithConfigSGIXReq -
454 sz_xGLXVendorPrivateWithReplyReq, vpreq);
455 req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
456 req->reqType = gc->majorOpcode;
457 req->glxCode = X_GLXVendorPrivateWithReply;
458 req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
459 req->context = gc->xid = XAllocID(dpy);
460 req->fbconfig = fbconfig->fbconfigID;
461 req->screen = fbconfig->screen;
462 req->renderType = renderType;
463 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700464#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200465 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700466#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200467 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700468#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200469 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000470
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200471 UnlockDisplay(dpy);
472 SyncHandle();
473 gc->imported = GL_FALSE;
474 }
475 else {
476 gc->xid = contextID;
477 gc->imported = GL_TRUE;
478 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000479
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200480 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000481}
482
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200483PUBLIC GLXContext
484glXCreateContext(Display * dpy, XVisualInfo * vis,
485 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000486{
487 return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200488 False, 0);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000489}
490
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200491_X_HIDDEN void
492__glXFreeContext(__GLXcontext * gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000493{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200494 if (gc->vendor)
495 XFree((char *) gc->vendor);
496 if (gc->renderer)
497 XFree((char *) gc->renderer);
498 if (gc->version)
499 XFree((char *) gc->version);
500 if (gc->extensions)
501 XFree((char *) gc->extensions);
502 __glFreeAttributeState(gc);
503 XFree((char *) gc->buf);
504 Xfree((char *) gc->client_state_private);
505 XFree((char *) gc);
506
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000507}
508
509/*
510** Destroy the named context
511*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200512static void
513DestroyContext(Display * dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000514{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200515 xGLXDestroyContextReq *req;
516 GLXContextID xid;
517 CARD8 opcode;
518 GLboolean imported;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000519
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200520 opcode = __glXSetupForCommand(dpy);
521 if (!opcode || !gc) {
522 return;
523 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000524
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200525 __glXLock();
526 xid = gc->xid;
527 imported = gc->imported;
528 gc->xid = None;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000529
530#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200531 /* Destroy the direct rendering context */
532 if (gc->driContext) {
533 (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy);
534 gc->driContext = NULL;
535 GarbageCollectDRIDrawables(dpy, gc->psc);
536 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000537#endif
538
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200539 __glXFreeVertexArrayState(gc);
Kristof Raloviche2060342008-08-20 15:18:38 -0600540
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200541 if (gc->currentDpy) {
542 /* Have to free later cuz it's in use now */
543 __glXUnlock();
544 }
545 else {
546 /* Destroy the handle if not current to anybody */
547 __glXUnlock();
548 __glXFreeContext(gc);
549 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000550
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200551 if (!imported) {
552 /*
553 ** This dpy also created the server side part of the context.
554 ** Send the glXDestroyContext request.
555 */
556 LockDisplay(dpy);
557 GetReq(GLXDestroyContext, req);
558 req->reqType = opcode;
559 req->glxCode = X_GLXDestroyContext;
560 req->context = xid;
561 UnlockDisplay(dpy);
562 SyncHandle();
563 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000564}
Adam Jackson489ccef2004-12-15 17:18:06 +0000565
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200566PUBLIC void
567glXDestroyContext(Display * dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000568{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200569 DestroyContext(dpy, gc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000570}
571
572/*
573** Return the major and minor version #s for the GLX extension
574*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200575PUBLIC Bool
576glXQueryVersion(Display * dpy, int *major, int *minor)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000577{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200578 __GLXdisplayPrivate *priv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000579
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200580 /* Init the extension. This fetches the major and minor version. */
581 priv = __glXInitialize(dpy);
582 if (!priv)
583 return GL_FALSE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000584
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200585 if (major)
586 *major = priv->majorVersion;
587 if (minor)
588 *minor = priv->minorVersion;
589 return GL_TRUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000590}
591
592/*
593** Query the existance of the GLX extension
594*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200595PUBLIC Bool
596glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000597{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200598 int major_op, erb, evb;
599 Bool rv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000600
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200601 rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
602 if (rv) {
603 if (errorBase)
604 *errorBase = erb;
605 if (eventBase)
606 *eventBase = evb;
607 }
608 return rv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000609}
610
611/*
612** Put a barrier in the token stream that forces the GL to finish its
613** work before X can proceed.
614*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200615PUBLIC void
616glXWaitGL(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000617{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200618 xGLXWaitGLReq *req;
619 GLXContext gc = __glXGetCurrentContext();
620 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000621
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200622 if (!dpy)
623 return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000624
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200625 /* Flush any pending commands out */
626 __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000627
628#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200629 if (gc->driContext) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000630/* This bit of ugliness unwraps the glFinish function */
631#ifdef glFinish
632#undef glFinish
633#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200634 glFinish();
635 return;
636 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000637#endif
638
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200639 /* Send the glXWaitGL request */
640 LockDisplay(dpy);
641 GetReq(GLXWaitGL, req);
642 req->reqType = gc->majorOpcode;
643 req->glxCode = X_GLXWaitGL;
644 req->contextTag = gc->currentContextTag;
645 UnlockDisplay(dpy);
646 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000647}
648
649/*
650** Put a barrier in the token stream that forces X to finish its
651** work before GL can proceed.
652*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200653PUBLIC void
654glXWaitX(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000655{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200656 xGLXWaitXReq *req;
657 GLXContext gc = __glXGetCurrentContext();
658 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000659
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200660 if (!dpy)
661 return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000662
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200663 /* Flush any pending commands out */
664 __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000665
666#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200667 if (gc->driContext) {
668 XSync(dpy, False);
669 return;
670 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000671#endif
672
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200673 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000674 ** Send the glXWaitX request.
675 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200676 LockDisplay(dpy);
677 GetReq(GLXWaitX, req);
678 req->reqType = gc->majorOpcode;
679 req->glxCode = X_GLXWaitX;
680 req->contextTag = gc->currentContextTag;
681 UnlockDisplay(dpy);
682 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000683}
684
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200685PUBLIC void
686glXUseXFont(Font font, int first, int count, int listBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000687{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200688 xGLXUseXFontReq *req;
689 GLXContext gc = __glXGetCurrentContext();
690 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000691
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200692 if (!dpy)
693 return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000694
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200695 /* Flush any pending commands out */
696 (void) __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000697
698#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200699 if (gc->driContext) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000700 DRI_glXUseXFont(font, first, count, listBase);
701 return;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200702 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000703#endif
704
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200705 /* Send the glXUseFont request */
706 LockDisplay(dpy);
707 GetReq(GLXUseXFont, req);
708 req->reqType = gc->majorOpcode;
709 req->glxCode = X_GLXUseXFont;
710 req->contextTag = gc->currentContextTag;
711 req->font = font;
712 req->first = first;
713 req->count = count;
714 req->listBase = listBase;
715 UnlockDisplay(dpy);
716 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000717}
718
719/************************************************************************/
720
721/*
722** Copy the source context to the destination context using the
723** attribute "mask".
724*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200725PUBLIC void
726glXCopyContext(Display * dpy, GLXContext source,
727 GLXContext dest, unsigned long mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000728{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200729 xGLXCopyContextReq *req;
730 GLXContext gc = __glXGetCurrentContext();
731 GLXContextTag tag;
732 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000733
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200734 opcode = __glXSetupForCommand(dpy);
735 if (!opcode) {
736 return;
737 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000738
739#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200740 if (gc->driContext) {
741 /* NOT_DONE: This does not work yet */
742 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000743#endif
744
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200745 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000746 ** If the source is the current context, send its tag so that the context
747 ** can be flushed before the copy.
748 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200749 if (source == gc && dpy == gc->currentDpy) {
750 tag = gc->currentContextTag;
751 }
752 else {
753 tag = 0;
754 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000755
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200756 /* Send the glXCopyContext request */
757 LockDisplay(dpy);
758 GetReq(GLXCopyContext, req);
759 req->reqType = opcode;
760 req->glxCode = X_GLXCopyContext;
761 req->source = source ? source->xid : None;
762 req->dest = dest ? dest->xid : None;
763 req->mask = mask;
764 req->contextTag = tag;
765 UnlockDisplay(dpy);
766 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000767}
768
769
770/**
771 * Determine if a context uses direct rendering.
772 *
773 * \param dpy Display where the context was created.
774 * \param contextID ID of the context to be tested.
775 *
776 * \returns \c GL_TRUE if the context is direct rendering or not.
777 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200778static Bool
779__glXIsDirect(Display * dpy, GLXContextID contextID)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000780{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200781 xGLXIsDirectReq *req;
782 xGLXIsDirectReply reply;
783 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000784
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200785 opcode = __glXSetupForCommand(dpy);
786 if (!opcode) {
787 return GL_FALSE;
788 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000789
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200790 /* Send the glXIsDirect request */
791 LockDisplay(dpy);
792 GetReq(GLXIsDirect, req);
793 req->reqType = opcode;
794 req->glxCode = X_GLXIsDirect;
795 req->context = contextID;
796 _XReply(dpy, (xReply *) & reply, 0, False);
797 UnlockDisplay(dpy);
798 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000799
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200800 return reply.isDirect;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000801}
802
Ian Romanickc39bf5e2005-07-24 06:29:14 +0000803/**
804 * \todo
805 * Shouldn't this function \b always return \c GL_FALSE when
806 * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with
807 * the GLX protocol here at all?
808 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200809PUBLIC Bool
810glXIsDirect(Display * dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000811{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200812 if (!gc) {
813 return GL_FALSE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000814#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200815 }
816 else if (gc->driContext) {
817 return GL_TRUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000818#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200819 }
820 return __glXIsDirect(dpy, gc->xid);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000821}
822
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200823PUBLIC GLXPixmap
824glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000825{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200826 xGLXCreateGLXPixmapReq *req;
827 GLXPixmap xid;
828 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000829
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200830 opcode = __glXSetupForCommand(dpy);
831 if (!opcode) {
832 return None;
833 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000834
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200835 /* Send the glXCreateGLXPixmap request */
836 LockDisplay(dpy);
837 GetReq(GLXCreateGLXPixmap, req);
838 req->reqType = opcode;
839 req->glxCode = X_GLXCreateGLXPixmap;
840 req->screen = vis->screen;
841 req->visual = vis->visualid;
842 req->pixmap = pixmap;
843 req->glxpixmap = xid = XAllocID(dpy);
844 UnlockDisplay(dpy);
845 SyncHandle();
846 return xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000847}
848
849/*
850** Destroy the named pixmap
851*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200852PUBLIC void
853glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000854{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200855 xGLXDestroyGLXPixmapReq *req;
856 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000857
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200858 opcode = __glXSetupForCommand(dpy);
859 if (!opcode) {
860 return;
861 }
862
863 /* Send the glXDestroyGLXPixmap request */
864 LockDisplay(dpy);
865 GetReq(GLXDestroyGLXPixmap, req);
866 req->reqType = opcode;
867 req->glxCode = X_GLXDestroyGLXPixmap;
868 req->glxpixmap = glxpixmap;
869 UnlockDisplay(dpy);
870 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000871}
872
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200873PUBLIC void
874glXSwapBuffers(Display * dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000875{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200876 xGLXSwapBuffersReq *req;
877 GLXContext gc;
878 GLXContextTag tag;
879 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000880#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200881 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000882
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200883 if (pdraw != NULL) {
884 glFlush();
885 (*pdraw->psc->driScreen->swapBuffers) (pdraw);
886 return;
887 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000888#endif
889
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200890 opcode = __glXSetupForCommand(dpy);
891 if (!opcode) {
892 return;
893 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000894
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200895 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000896 ** The calling thread may or may not have a current context. If it
897 ** does, send the context tag so the server can do a flush.
898 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200899 gc = __glXGetCurrentContext();
900 if ((gc != NULL) && (dpy == gc->currentDpy) &&
901 ((drawable == gc->currentDrawable)
902 || (drawable == gc->currentReadable))) {
903 tag = gc->currentContextTag;
904 }
905 else {
906 tag = 0;
907 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000908
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200909 /* Send the glXSwapBuffers request */
910 LockDisplay(dpy);
911 GetReq(GLXSwapBuffers, req);
912 req->reqType = opcode;
913 req->glxCode = X_GLXSwapBuffers;
914 req->drawable = drawable;
915 req->contextTag = tag;
916 UnlockDisplay(dpy);
917 SyncHandle();
918 XFlush(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000919}
920
921
922/*
923** Return configuration information for the given display, screen and
924** visual combination.
925*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200926PUBLIC int
927glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
928 int *value_return)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000929{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200930 __GLXdisplayPrivate *priv;
931 __GLXscreenConfigs *psc;
932 __GLcontextModes *modes;
933 int status;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000934
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200935 status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
936 if (status == Success) {
937 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000938
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200939 /* Lookup attribute after first finding a match on the visual */
940 if (modes != NULL) {
941 return _gl_get_context_mode_data(modes, attribute, value_return);
942 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000943
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200944 status = GLX_BAD_VISUAL;
945 }
946
947 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000948 ** If we can't find the config for this visual, this visual is not
949 ** supported by the OpenGL implementation on the server.
950 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200951 if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
952 *value_return = GL_FALSE;
953 status = Success;
954 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000955
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200956 return status;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000957}
958
959/************************************************************************/
960
961static void
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200962init_fbconfig_for_chooser(__GLcontextModes * config,
963 GLboolean fbconfig_style_tags)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000964{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200965 memset(config, 0, sizeof(__GLcontextModes));
966 config->visualID = (XID) GLX_DONT_CARE;
967 config->visualType = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000968
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200969 /* glXChooseFBConfig specifies different defaults for these two than
970 * glXChooseVisual.
971 */
972 if (fbconfig_style_tags) {
973 config->rgbMode = GL_TRUE;
974 config->doubleBufferMode = GLX_DONT_CARE;
975 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000976
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200977 config->visualRating = GLX_DONT_CARE;
978 config->transparentPixel = GLX_NONE;
979 config->transparentRed = GLX_DONT_CARE;
980 config->transparentGreen = GLX_DONT_CARE;
981 config->transparentBlue = GLX_DONT_CARE;
982 config->transparentAlpha = GLX_DONT_CARE;
983 config->transparentIndex = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000984
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200985 config->drawableType = GLX_WINDOW_BIT;
986 config->renderType =
987 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
988 config->xRenderable = GLX_DONT_CARE;
989 config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000990
RALOVICH, Kristóf12933562008-10-13 14:06:30 +0200991 config->swapMethod = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000992}
993
994#define MATCH_DONT_CARE( param ) \
995 do { \
996 if ( (a-> param != GLX_DONT_CARE) \
997 && (a-> param != b-> param) ) { \
998 return False; \
999 } \
1000 } while ( 0 )
1001
1002#define MATCH_MINIMUM( param ) \
1003 do { \
1004 if ( (a-> param != GLX_DONT_CARE) \
1005 && (a-> param > b-> param) ) { \
1006 return False; \
1007 } \
1008 } while ( 0 )
1009
1010#define MATCH_EXACT( param ) \
1011 do { \
1012 if ( a-> param != b-> param) { \
1013 return False; \
1014 } \
1015 } while ( 0 )
1016
1017/**
1018 * Determine if two GLXFBConfigs are compatible.
1019 *
1020 * \param a Application specified config to test.
1021 * \param b Server specified config to test against \c a.
1022 */
1023static Bool
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001024fbconfigs_compatible(const __GLcontextModes * const a,
1025 const __GLcontextModes * const b)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001026{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001027 MATCH_DONT_CARE(doubleBufferMode);
1028 MATCH_DONT_CARE(visualType);
1029 MATCH_DONT_CARE(visualRating);
1030 MATCH_DONT_CARE(xRenderable);
1031 MATCH_DONT_CARE(fbconfigID);
1032 MATCH_DONT_CARE(swapMethod);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001033
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001034 MATCH_MINIMUM(rgbBits);
1035 MATCH_MINIMUM(numAuxBuffers);
1036 MATCH_MINIMUM(redBits);
1037 MATCH_MINIMUM(greenBits);
1038 MATCH_MINIMUM(blueBits);
1039 MATCH_MINIMUM(alphaBits);
1040 MATCH_MINIMUM(depthBits);
1041 MATCH_MINIMUM(stencilBits);
1042 MATCH_MINIMUM(accumRedBits);
1043 MATCH_MINIMUM(accumGreenBits);
1044 MATCH_MINIMUM(accumBlueBits);
1045 MATCH_MINIMUM(accumAlphaBits);
1046 MATCH_MINIMUM(sampleBuffers);
1047 MATCH_MINIMUM(maxPbufferWidth);
1048 MATCH_MINIMUM(maxPbufferHeight);
1049 MATCH_MINIMUM(maxPbufferPixels);
1050 MATCH_MINIMUM(samples);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001051
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001052 MATCH_DONT_CARE(stereoMode);
1053 MATCH_EXACT(level);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001054
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001055 if (((a->drawableType & b->drawableType) == 0)
1056 || ((a->renderType & b->renderType) == 0)) {
1057 return False;
1058 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001059
1060
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001061 /* There is a bug in a few of the XFree86 DDX drivers. They contain
1062 * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1063 * Technically speaking, it is a bug in the DDX driver, but there is
1064 * enough of an installed base to work around the problem here. In any
1065 * case, 0 is not a valid value of the transparent type, so we'll treat 0
1066 * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1067 * 0 from the server to be a match to maintain backward compatibility with
1068 * the (broken) drivers.
1069 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001070
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001071 if (a->transparentPixel != GLX_DONT_CARE && a->transparentPixel != 0) {
1072 if (a->transparentPixel == GLX_NONE) {
1073 if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
1074 return False;
1075 }
1076 else {
1077 MATCH_EXACT(transparentPixel);
1078 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001079
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001080 switch (a->transparentPixel) {
1081 case GLX_TRANSPARENT_RGB:
1082 MATCH_DONT_CARE(transparentRed);
1083 MATCH_DONT_CARE(transparentGreen);
1084 MATCH_DONT_CARE(transparentBlue);
1085 MATCH_DONT_CARE(transparentAlpha);
1086 break;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001087
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001088 case GLX_TRANSPARENT_INDEX:
1089 MATCH_DONT_CARE(transparentIndex);
1090 break;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001091
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001092 default:
1093 break;
1094 }
1095 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001096
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001097 return True;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001098}
1099
1100
1101/* There's some trickly language in the GLX spec about how this is supposed
1102 * to work. Basically, if a given component size is either not specified
1103 * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1104 * Well, that's really hard to do with the code as-is. This behavior is
1105 * closer to correct, but still not technically right.
1106 */
1107#define PREFER_LARGER_OR_ZERO(comp) \
1108 do { \
1109 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1110 if ( ((*a)-> comp) == 0 ) { \
1111 return -1; \
1112 } \
1113 else if ( ((*b)-> comp) == 0 ) { \
1114 return 1; \
1115 } \
1116 else { \
1117 return ((*b)-> comp) - ((*a)-> comp) ; \
1118 } \
1119 } \
1120 } while( 0 )
1121
1122#define PREFER_LARGER(comp) \
1123 do { \
1124 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1125 return ((*b)-> comp) - ((*a)-> comp) ; \
1126 } \
1127 } while( 0 )
1128
1129#define PREFER_SMALLER(comp) \
1130 do { \
1131 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1132 return ((*a)-> comp) - ((*b)-> comp) ; \
1133 } \
1134 } while( 0 )
1135
1136/**
1137 * Compare two GLXFBConfigs. This function is intended to be used as the
1138 * compare function passed in to qsort.
1139 *
1140 * \returns If \c a is a "better" config, according to the specification of
1141 * SGIX_fbconfig, a number less than zero is returned. If \c b is
1142 * better, then a number greater than zero is return. If both are
1143 * equal, zero is returned.
1144 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1145 */
1146static int
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001147fbconfig_compare(const __GLcontextModes * const *const a,
1148 const __GLcontextModes * const *const b)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001149{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001150 /* The order of these comparisons must NOT change. It is defined by
1151 * the GLX 1.3 spec and ARB_multisample.
1152 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001153
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001154 PREFER_SMALLER(visualSelectGroup);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001155
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001156 /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1157 * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
1158 * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1159 */
1160 PREFER_SMALLER(visualRating);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001161
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001162 /* This isn't quite right. It is supposed to compare the sum of the
1163 * components the user specifically set minimums for.
1164 */
1165 PREFER_LARGER_OR_ZERO(redBits);
1166 PREFER_LARGER_OR_ZERO(greenBits);
1167 PREFER_LARGER_OR_ZERO(blueBits);
1168 PREFER_LARGER_OR_ZERO(alphaBits);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001169
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001170 PREFER_SMALLER(rgbBits);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001171
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001172 if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
1173 /* Prefer single-buffer.
1174 */
1175 return (!(*a)->doubleBufferMode) ? -1 : 1;
1176 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001177
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001178 PREFER_SMALLER(numAuxBuffers);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001179
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001180 PREFER_LARGER_OR_ZERO(depthBits);
1181 PREFER_SMALLER(stencilBits);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001182
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001183 /* This isn't quite right. It is supposed to compare the sum of the
1184 * components the user specifically set minimums for.
1185 */
1186 PREFER_LARGER_OR_ZERO(accumRedBits);
1187 PREFER_LARGER_OR_ZERO(accumGreenBits);
1188 PREFER_LARGER_OR_ZERO(accumBlueBits);
1189 PREFER_LARGER_OR_ZERO(accumAlphaBits);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001190
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001191 PREFER_SMALLER(visualType);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001192
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001193 /* None of the multisample specs say where this comparison should happen,
1194 * so I put it near the end.
1195 */
1196 PREFER_SMALLER(sampleBuffers);
1197 PREFER_SMALLER(samples);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001198
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001199 /* None of the pbuffer or fbconfig specs say that this comparison needs
1200 * to happen at all, but it seems like it should.
1201 */
1202 PREFER_LARGER(maxPbufferWidth);
1203 PREFER_LARGER(maxPbufferHeight);
1204 PREFER_LARGER(maxPbufferPixels);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001205
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001206 return 0;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001207}
1208
1209
1210/**
1211 * Selects and sorts a subset of the supplied configs based on the attributes.
1212 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1213 * and \c glXChooseFBConfigSGIX.
1214 *
1215 * \param configs Array of pointers to possible configs. The elements of
1216 * this array that do not meet the criteria will be set to
1217 * NULL. The remaining elements will be sorted according to
1218 * the various visual / FBConfig selection rules.
1219 * \param num_configs Number of elements in the \c configs array.
1220 * \param attribList Attributes used select from \c configs. This array is
1221 * terminated by a \c None tag. The array can either take
1222 * the form expected by \c glXChooseVisual (where boolean
1223 * tags do not have a value) or by \c glXChooseFBConfig
1224 * (where every tag has a value).
1225 * \param fbconfig_style_tags Selects whether \c attribList is in
1226 * \c glXChooseVisual style or
1227 * \c glXChooseFBConfig style.
1228 * \returns The number of valid elements left in \c configs.
1229 *
1230 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1231 */
1232static int
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001233choose_visual(__GLcontextModes ** configs, int num_configs,
1234 const int *attribList, GLboolean fbconfig_style_tags)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001235{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001236 __GLcontextModes test_config;
1237 int base;
1238 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001239
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001240 /* This is a fairly direct implementation of the selection method
1241 * described by GLX_SGIX_fbconfig. Start by culling out all the
1242 * configs that are not compatible with the selected parameter
1243 * list.
1244 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001245
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001246 init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
1247 __glXInitializeVisualConfigFromTags(&test_config, 512,
1248 (const INT32 *) attribList,
1249 GL_TRUE, fbconfig_style_tags);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001250
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001251 base = 0;
1252 for (i = 0; i < num_configs; i++) {
1253 if (fbconfigs_compatible(&test_config, configs[i])) {
1254 configs[base] = configs[i];
1255 base++;
1256 }
1257 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001258
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001259 if (base == 0) {
1260 return 0;
1261 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001262
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001263 if (base < num_configs) {
1264 (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
1265 }
1266
1267 /* After the incompatible configs are removed, the resulting
1268 * list is sorted according to the rules set out in the various
1269 * specifications.
1270 */
1271
1272 qsort(configs, base, sizeof(__GLcontextModes *),
1273 (int (*)(const void *, const void *)) fbconfig_compare);
1274 return base;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001275}
1276
1277
1278
1279
1280/*
1281** Return the visual that best matches the template. Return None if no
1282** visual matches the template.
1283*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001284PUBLIC XVisualInfo *
1285glXChooseVisual(Display * dpy, int screen, int *attribList)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001286{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001287 XVisualInfo *visualList = NULL;
1288 __GLXdisplayPrivate *priv;
1289 __GLXscreenConfigs *psc;
1290 __GLcontextModes test_config;
1291 __GLcontextModes *modes;
1292 const __GLcontextModes *best_config = NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001293
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001294 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001295 ** Get a list of all visuals, return if list is empty
1296 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001297 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1298 return None;
1299 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001300
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001301
1302 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001303 ** Build a template from the defaults and the attribute list
1304 ** Free visual list and return if an unexpected token is encountered
1305 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001306 init_fbconfig_for_chooser(&test_config, GL_FALSE);
1307 __glXInitializeVisualConfigFromTags(&test_config, 512,
1308 (const INT32 *) attribList,
1309 GL_TRUE, GL_FALSE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001310
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001311 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001312 ** Eliminate visuals that don't meet minimum requirements
1313 ** Compute a score for those that do
1314 ** Remember which visual, if any, got the highest score
1315 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001316 for (modes = psc->visuals; modes != NULL; modes = modes->next) {
1317 if (fbconfigs_compatible(&test_config, modes)
1318 && ((best_config == NULL)
1319 ||
1320 (fbconfig_compare
1321 ((const __GLcontextModes * const *const) &modes,
1322 &best_config) < 0))) {
1323 best_config = modes;
1324 }
1325 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001326
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001327 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001328 ** If no visual is acceptable, return None
1329 ** Otherwise, create an XVisualInfo list with just the selected X visual
1330 ** and return this.
1331 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001332 if (best_config != NULL) {
1333 XVisualInfo visualTemplate;
1334 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001335
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001336 visualTemplate.screen = screen;
1337 visualTemplate.visualid = best_config->visualID;
1338 visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
1339 &visualTemplate, &i);
1340 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001341
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001342 return visualList;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001343}
1344
1345
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001346PUBLIC const char *
1347glXQueryExtensionsString(Display * dpy, int screen)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001348{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001349 __GLXscreenConfigs *psc;
1350 __GLXdisplayPrivate *priv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001351
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001352 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1353 return NULL;
1354 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001355
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001356 if (!psc->effectiveGLXexts) {
1357 if (!psc->serverGLXexts) {
1358 psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode,
1359 X_GLXQueryServerString,
1360 screen,
1361 GLX_EXTENSIONS);
1362 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001363
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001364 __glXCalculateUsableExtensions(psc,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001365#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001366 (psc->driScreen != NULL),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001367#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001368 GL_FALSE,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001369#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001370 priv->minorVersion);
1371 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001372
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001373 return psc->effectiveGLXexts;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001374}
1375
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001376PUBLIC const char *
1377glXGetClientString(Display * dpy, int name)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001378{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001379 switch (name) {
1380 case GLX_VENDOR:
1381 return (__glXGLXClientVendorName);
1382 case GLX_VERSION:
1383 return (__glXGLXClientVersion);
1384 case GLX_EXTENSIONS:
1385 return (__glXGetClientExtensions());
1386 default:
1387 return NULL;
1388 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001389}
1390
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001391PUBLIC const char *
1392glXQueryServerString(Display * dpy, int screen, int name)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001393{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001394 __GLXscreenConfigs *psc;
1395 __GLXdisplayPrivate *priv;
1396 const char **str;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001397
1398
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001399 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1400 return NULL;
1401 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001402
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001403 switch (name) {
1404 case GLX_VENDOR:
1405 str = &priv->serverGLXvendor;
1406 break;
1407 case GLX_VERSION:
1408 str = &priv->serverGLXversion;
1409 break;
1410 case GLX_EXTENSIONS:
1411 str = &psc->serverGLXexts;
1412 break;
1413 default:
1414 return NULL;
1415 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001416
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001417 if (*str == NULL) {
1418 *str = __glXGetStringFromServer(dpy, priv->majorOpcode,
1419 X_GLXQueryServerString, screen, name);
1420 }
1421
1422 return *str;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001423}
1424
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001425void
1426__glXClientInfo(Display * dpy, int opcode)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001427{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001428 xGLXClientInfoReq *req;
1429 int size;
1430 char *ext_str = __glXGetClientGLExtensionString();
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001431
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001432 /* Send the glXClientInfo request */
1433 LockDisplay(dpy);
1434 GetReq(GLXClientInfo, req);
1435 req->reqType = opcode;
1436 req->glxCode = X_GLXClientInfo;
1437 req->major = GLX_MAJOR_VERSION;
1438 req->minor = GLX_MINOR_VERSION;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001439
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001440 size = strlen(ext_str) + 1;
1441 req->length += (size + 3) >> 2;
1442 req->numbytes = size;
1443 Data(dpy, ext_str, size);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001444
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001445 UnlockDisplay(dpy);
1446 SyncHandle();
1447
1448 Xfree(ext_str);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001449}
1450
1451
1452/*
1453** EXT_import_context
1454*/
1455
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001456PUBLIC Display *
1457glXGetCurrentDisplay(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001458{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001459 GLXContext gc = __glXGetCurrentContext();
1460 if (NULL == gc)
1461 return NULL;
1462 return gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001463}
1464
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001465PUBLIC
1466GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1467 glXGetCurrentDisplay)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001468
1469/**
1470 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
1471 * to the X-server.
1472 *
1473 * \param dpy Display where \c ctx was created.
1474 * \param ctx Context to query.
1475 * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid,
1476 * or zero if the request failed due to internal problems (i.e.,
1477 * unable to allocate temporary memory, etc.)
1478 *
1479 * \note
1480 * This function dynamically determines whether to use the EXT_import_context
1481 * version of the protocol or the GLX 1.3 version of the protocol.
1482 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001483 static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001484{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001485 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1486 xGLXQueryContextReply reply;
1487 CARD8 opcode;
1488 GLuint numValues;
1489 int retval;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001490
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001491 if (ctx == NULL) {
1492 return GLX_BAD_CONTEXT;
1493 }
1494 opcode = __glXSetupForCommand(dpy);
1495 if (!opcode) {
1496 return 0;
1497 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001498
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001499 /* Send the glXQueryContextInfoEXT request */
1500 LockDisplay(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001501
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001502 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
1503 xGLXQueryContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001504
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001505 GetReq(GLXQueryContext, req);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001506
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001507 req->reqType = opcode;
1508 req->glxCode = X_GLXQueryContext;
1509 req->context = (unsigned int) (ctx->xid);
1510 }
1511 else {
1512 xGLXVendorPrivateReq *vpreq;
1513 xGLXQueryContextInfoEXTReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001514
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001515 GetReqExtra(GLXVendorPrivate,
1516 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1517 vpreq);
1518 req = (xGLXQueryContextInfoEXTReq *) vpreq;
1519 req->reqType = opcode;
1520 req->glxCode = X_GLXVendorPrivateWithReply;
1521 req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1522 req->context = (unsigned int) (ctx->xid);
1523 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001524
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001525 _XReply(dpy, (xReply *) & reply, 0, False);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001526
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001527 numValues = reply.n;
1528 if (numValues == 0)
1529 retval = Success;
1530 else if (numValues > __GLX_MAX_CONTEXT_PROPS)
1531 retval = 0;
1532 else {
1533 int *propList, *pProp;
1534 int nPropListBytes;
1535 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001536
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001537 nPropListBytes = numValues << 3;
1538 propList = (int *) Xmalloc(nPropListBytes);
1539 if (NULL == propList) {
1540 retval = 0;
1541 }
1542 else {
1543 _XRead(dpy, (char *) propList, nPropListBytes);
1544 pProp = propList;
1545 for (i = 0; i < numValues; i++) {
1546 switch (*pProp++) {
1547 case GLX_SHARE_CONTEXT_EXT:
1548 ctx->share_xid = *pProp++;
1549 break;
1550 case GLX_VISUAL_ID_EXT:
1551 ctx->mode =
1552 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
1553 break;
1554 case GLX_SCREEN:
1555 ctx->screen = *pProp++;
1556 break;
1557 case GLX_FBCONFIG_ID:
1558 ctx->mode =
1559 _gl_context_modes_find_fbconfig(ctx->psc->configs,
1560 *pProp++);
1561 break;
1562 case GLX_RENDER_TYPE:
1563 ctx->renderType = *pProp++;
1564 break;
1565 default:
1566 pProp++;
1567 continue;
1568 }
1569 }
1570 Xfree((char *) propList);
1571 retval = Success;
1572 }
1573 }
1574 UnlockDisplay(dpy);
1575 SyncHandle();
1576 return retval;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001577}
1578
Adam Jackson489ccef2004-12-15 17:18:06 +00001579PUBLIC int
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001580glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001581{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001582 int retVal;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001583
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001584 /* get the information from the server if we don't have it already */
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001585#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001586 if (!ctx->driContext && (ctx->mode == NULL)) {
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001587#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001588 if (ctx->mode == NULL) {
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001589#endif
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001590 retVal = __glXQueryContextInfo(dpy, ctx);
1591 if (Success != retVal)
1592 return retVal;
1593 }
1594 switch (attribute) {
1595 case GLX_SHARE_CONTEXT_EXT:
1596 *value = (int) (ctx->share_xid);
1597 break;
1598 case GLX_VISUAL_ID_EXT:
1599 *value = ctx->mode ? ctx->mode->visualID : None;
1600 break;
1601 case GLX_SCREEN:
1602 *value = (int) (ctx->screen);
1603 break;
1604 case GLX_FBCONFIG_ID:
1605 *value = ctx->mode ? ctx->mode->fbconfigID : None;
1606 break;
1607 case GLX_RENDER_TYPE:
1608 *value = (int) (ctx->renderType);
1609 break;
1610 default:
1611 return GLX_BAD_ATTRIBUTE;
1612 }
1613 return Success;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001614}
1615
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001616PUBLIC
1617GLX_ALIAS(int, glXQueryContextInfoEXT,
1618 (Display * dpy, GLXContext ctx, int attribute, int *value),
1619 (dpy, ctx, attribute, value), glXQueryContext)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001620
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001621 PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001622{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001623 return ctx->xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001624}
1625
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001626PUBLIC GLXContext
1627glXImportContextEXT(Display * dpy, GLXContextID contextID)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001628{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001629 GLXContext ctx;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001630
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001631 if (contextID == None) {
1632 return NULL;
1633 }
1634 if (__glXIsDirect(dpy, contextID)) {
1635 return NULL;
1636 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001637
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001638 ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
1639 if (NULL != ctx) {
1640 if (Success != __glXQueryContextInfo(dpy, ctx)) {
1641 return NULL;
1642 }
1643 }
1644 return ctx;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001645}
1646
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001647PUBLIC void
1648glXFreeContextEXT(Display * dpy, GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001649{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001650 DestroyContext(dpy, ctx);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001651}
1652
1653
1654
1655/*
1656 * GLX 1.3 functions - these are just stubs for now!
1657 */
1658
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001659PUBLIC GLXFBConfig *
1660glXChooseFBConfig(Display * dpy, int screen,
1661 const int *attribList, int *nitems)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001662{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001663 __GLcontextModes **config_list;
1664 int list_size;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001665
1666
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001667 config_list = (__GLcontextModes **)
1668 glXGetFBConfigs(dpy, screen, &list_size);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001669
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001670 if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1671 list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
1672 if (list_size == 0) {
1673 XFree(config_list);
1674 config_list = NULL;
1675 }
1676 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001677
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001678 *nitems = list_size;
1679 return (GLXFBConfig *) config_list;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001680}
1681
1682
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001683PUBLIC GLXContext
1684glXCreateNewContext(Display * dpy, GLXFBConfig config,
1685 int renderType, GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001686{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001687 return CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
1688 allowDirect, None, True, renderType);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001689}
1690
1691
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001692PUBLIC GLXDrawable
1693glXGetCurrentReadDrawable(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001694{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001695 GLXContext gc = __glXGetCurrentContext();
1696 return gc->currentReadable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001697}
1698
1699
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001700PUBLIC GLXFBConfig *
1701glXGetFBConfigs(Display * dpy, int screen, int *nelements)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001702{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001703 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1704 __GLcontextModes **config = NULL;
1705 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001706
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001707 *nelements = 0;
1708 if ((priv->screenConfigs != NULL)
1709 && (screen >= 0) && (screen <= ScreenCount(dpy))
1710 && (priv->screenConfigs[screen].configs != NULL)
1711 && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE)) {
1712 unsigned num_configs = 0;
1713 __GLcontextModes *modes;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001714
1715
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001716 for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1717 modes = modes->next) {
1718 if (modes->fbconfigID != GLX_DONT_CARE) {
1719 num_configs++;
1720 }
1721 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001722
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001723 config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
1724 * num_configs);
1725 if (config != NULL) {
1726 *nelements = num_configs;
1727 i = 0;
1728 for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1729 modes = modes->next) {
1730 if (modes->fbconfigID != GLX_DONT_CARE) {
1731 config[i] = modes;
1732 i++;
1733 }
1734 }
1735 }
1736 }
1737 return (GLXFBConfig *) config;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001738}
1739
1740
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001741PUBLIC int
1742glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
1743 int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001744{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001745 __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001746
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001747 return (modes != NULL)
1748 ? _gl_get_context_mode_data(modes, attribute, value)
1749 : GLXBadFBConfig;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001750}
1751
1752
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001753PUBLIC XVisualInfo *
1754glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001755{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001756 XVisualInfo visualTemplate;
1757 __GLcontextModes *fbconfig = (__GLcontextModes *) config;
1758 int count;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001759
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001760 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001761 ** Get a list of all visuals, return if list is empty
1762 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001763 visualTemplate.visualid = fbconfig->visualID;
1764 return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001765}
1766
1767
1768/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001769** GLX_SGI_swap_control
1770*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001771static int
1772__glXSwapIntervalSGI(int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001773{
1774 xGLXVendorPrivateReq *req;
1775 GLXContext gc = __glXGetCurrentContext();
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001776 Display *dpy;
1777 CARD32 *interval_ptr;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001778 CARD8 opcode;
1779
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001780 if (gc == NULL) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001781 return GLX_BAD_CONTEXT;
1782 }
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001783
1784 if (interval <= 0) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001785 return GLX_BAD_VALUE;
1786 }
1787
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001788#ifdef __DRI_SWAP_CONTROL
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001789 if (gc->driContext) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001790 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1791 gc->screen);
1792 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
1793 gc->currentDrawable,
1794 NULL);
1795 if (psc->swapControl != NULL && pdraw != NULL) {
1796 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1797 return 0;
1798 }
1799 else {
1800 return GLX_BAD_CONTEXT;
1801 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001802 }
1803#endif
1804 dpy = gc->currentDpy;
1805 opcode = __glXSetupForCommand(dpy);
1806 if (!opcode) {
1807 return 0;
1808 }
1809
1810 /* Send the glXSwapIntervalSGI request */
1811 LockDisplay(dpy);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001812 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001813 req->reqType = opcode;
1814 req->glxCode = X_GLXVendorPrivate;
1815 req->vendorCode = X_GLXvop_SwapIntervalSGI;
1816 req->contextTag = gc->currentContextTag;
1817
Ian Romanicka70d5642006-08-30 23:15:02 +00001818 interval_ptr = (CARD32 *) (req + 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001819 *interval_ptr = interval;
1820
1821 UnlockDisplay(dpy);
1822 SyncHandle();
1823 XFlush(dpy);
1824
1825 return 0;
1826}
1827
1828
1829/*
1830** GLX_MESA_swap_control
1831*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001832static int
1833__glXSwapIntervalMESA(unsigned int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001834{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001835#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001836 GLXContext gc = __glXGetCurrentContext();
1837
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001838 if (interval < 0) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001839 return GLX_BAD_VALUE;
1840 }
1841
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001842 if (gc != NULL && gc->driContext) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001843 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1844 gc->screen);
1845
1846 if ((psc != NULL) && (psc->driScreen != NULL)) {
1847 __GLXDRIdrawable *pdraw =
1848 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1849 if (psc->swapControl != NULL && pdraw != NULL) {
1850 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1851 return 0;
1852 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001853 }
1854 }
1855#else
1856 (void) interval;
1857#endif
1858
1859 return GLX_BAD_CONTEXT;
1860}
Brian Paul841a8232006-03-09 16:25:46 +00001861
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001862
1863static int
1864__glXGetSwapIntervalMESA(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001865{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001866#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001867 GLXContext gc = __glXGetCurrentContext();
1868
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001869 if (gc != NULL && gc->driContext) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001870 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1871 gc->screen);
1872
1873 if ((psc != NULL) && (psc->driScreen != NULL)) {
1874 __GLXDRIdrawable *pdraw =
1875 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1876 if (psc->swapControl != NULL && pdraw != NULL) {
1877 return psc->swapControl->getSwapInterval(pdraw->driDrawable);
1878 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001879 }
1880 }
1881#endif
1882
1883 return 0;
1884}
1885
1886
1887/*
1888** GLX_MESA_swap_frame_usage
1889*/
1890
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001891static GLint
1892__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001893{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001894 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001895#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001896 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001897 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001898 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001899
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001900 if (pdraw != NULL && psc->frameTracking != NULL)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001901 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001902#else
1903 (void) dpy;
1904 (void) drawable;
1905#endif
1906 return status;
1907}
1908
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001909
1910static GLint
1911__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001912{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001913 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001914#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001915 int screen;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001916 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001917 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001918
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001919 if (pdraw != NULL && psc->frameTracking != NULL)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001920 status = psc->frameTracking->frameTracking(pdraw->driDrawable,
1921 GL_FALSE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001922#else
1923 (void) dpy;
1924 (void) drawable;
1925#endif
1926 return status;
1927}
1928
1929
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001930static GLint
1931__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001932{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001933 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001934#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001935 int screen;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001936 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1937 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001938
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001939 if (pdraw != NULL && psc->frameTracking != NULL) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001940 int64_t sbc, missedFrames;
1941 float lastMissedUsage;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001942
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001943 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
1944 &sbc,
1945 &missedFrames,
1946 &lastMissedUsage,
1947 usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001948 }
1949#else
1950 (void) dpy;
1951 (void) drawable;
1952 (void) usage;
1953#endif
1954 return status;
1955}
1956
1957
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001958static GLint
1959__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
1960 int64_t * sbc, int64_t * missedFrames,
1961 GLfloat * lastMissedUsage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001962{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001963 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001964#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001965 int screen;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001966 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1967 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001968
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001969 if (pdraw != NULL && psc->frameTracking != NULL) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001970 float usage;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001971
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001972 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001973 sbc, missedFrames,
1974 lastMissedUsage,
1975 &usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001976 }
1977#else
1978 (void) dpy;
1979 (void) drawable;
1980 (void) sbc;
1981 (void) missedFrames;
1982 (void) lastMissedUsage;
1983#endif
1984 return status;
1985}
1986
1987
1988/*
1989** GLX_SGI_video_sync
1990*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02001991static int
1992__glXGetVideoSyncSGI(unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001993{
1994 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1995 * FIXME: there should be a GLX encoding for this call. I can find no
1996 * FIXME: documentation for the GLX encoding.
1997 */
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04001998#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001999 GLXContext gc = __glXGetCurrentContext();
2000
2001
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05002002 if (gc != NULL && gc->driContext) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002003 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2004 gc->screen);
2005 if (psc->msc && psc->driScreen) {
2006 __GLXDRIdrawable *pdraw =
2007 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2008 int64_t temp;
2009 int ret;
Kristian Høgsberg6e8d21d2008-02-25 16:14:37 -05002010
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002011 ret = (*psc->msc->getDrawableMSC) (psc->__driScreen,
2012 pdraw->driDrawable, &temp);
2013 *count = (unsigned) temp;
2014
2015 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002016 }
2017 }
2018#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002019 (void) count;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002020#endif
2021 return GLX_BAD_CONTEXT;
2022}
2023
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002024static int
2025__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002026{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002027#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002028 GLXContext gc = __glXGetCurrentContext();
2029
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002030 if (divisor <= 0 || remainder < 0)
2031 return GLX_BAD_VALUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002032
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05002033 if (gc != NULL && gc->driContext) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002034 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2035 gc->screen);
2036 if (psc->msc != NULL && psc->driScreen) {
2037 __GLXDRIdrawable *pdraw =
2038 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2039 int ret;
2040 int64_t msc;
2041 int64_t sbc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002042
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002043 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, 0,
2044 divisor, remainder, &msc, &sbc);
2045 *count = (unsigned) msc;
2046 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002047 }
2048 }
2049#else
2050 (void) count;
2051#endif
2052 return GLX_BAD_CONTEXT;
2053}
2054
2055
2056/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002057** GLX_SGIX_fbconfig
2058** Many of these functions are aliased to GLX 1.3 entry points in the
2059** GLX_functions table.
2060*/
2061
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002062PUBLIC
2063GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
2064 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
2065 (dpy, config, attribute, value), glXGetFBConfigAttrib)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002066
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002067 PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
2068 (Display * dpy, int screen, int *attrib_list,
2069 int *nelements), (dpy, screen, attrib_list, nelements),
2070 glXChooseFBConfig)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002071
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002072 PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
2073 (Display * dpy, GLXFBConfigSGIX config),
2074 (dpy, config), glXGetVisualFromFBConfig)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002075
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002076 PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
2077 GLXFBConfigSGIX config,
2078 Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002079{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002080 xGLXVendorPrivateWithReplyReq *vpreq;
2081 xGLXCreateGLXPixmapWithConfigSGIXReq *req;
2082 GLXPixmap xid = None;
2083 CARD8 opcode;
2084 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2085 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002086
2087
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002088 if ((dpy == NULL) || (config == NULL)) {
2089 return None;
2090 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002091
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002092 psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2093 if ((psc != NULL)
2094 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2095 opcode = __glXSetupForCommand(dpy);
2096 if (!opcode) {
2097 return None;
2098 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002099
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002100 /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2101 LockDisplay(dpy);
2102 GetReqExtra(GLXVendorPrivateWithReply,
2103 sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
2104 sz_xGLXVendorPrivateWithReplyReq, vpreq);
2105 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
2106 req->reqType = opcode;
2107 req->glxCode = X_GLXVendorPrivateWithReply;
2108 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2109 req->screen = fbconfig->screen;
2110 req->fbconfig = fbconfig->fbconfigID;
2111 req->pixmap = pixmap;
2112 req->glxpixmap = xid = XAllocID(dpy);
2113 UnlockDisplay(dpy);
2114 SyncHandle();
2115 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002116
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002117 return xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002118}
2119
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002120PUBLIC GLXContext
2121glXCreateContextWithConfigSGIX(Display * dpy,
2122 GLXFBConfigSGIX config, int renderType,
2123 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002124{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002125 GLXContext gc = NULL;
2126 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2127 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002128
2129
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002130 if ((dpy == NULL) || (config == NULL)) {
2131 return None;
2132 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002133
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002134 psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2135 if ((psc != NULL)
2136 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2137 gc = CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
2138 allowDirect, None, False, renderType);
2139 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002140
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002141 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002142}
2143
2144
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002145PUBLIC GLXFBConfigSGIX
2146glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002147{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002148 __GLXdisplayPrivate *priv;
2149 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002150
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002151 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
2152 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2153 && (psc->configs->fbconfigID != GLX_DONT_CARE)) {
2154 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
2155 vis->visualid);
2156 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002157
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002158 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002159}
2160
2161
2162/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002163** GLX_SGIX_swap_group
2164*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002165static void
2166__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
2167 GLXDrawable member)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002168{
2169 (void) dpy;
2170 (void) drawable;
2171 (void) member;
2172}
2173
2174
2175/*
2176** GLX_SGIX_swap_barrier
2177*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002178static void
2179__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002180{
2181 (void) dpy;
2182 (void) drawable;
2183 (void) barrier;
2184}
2185
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002186static Bool
2187__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002188{
2189 (void) dpy;
2190 (void) screen;
2191 (void) max;
2192 return False;
2193}
2194
2195
2196/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002197** GLX_OML_sync_control
2198*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002199static Bool
2200__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2201 int64_t * ust, int64_t * msc, int64_t * sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002202{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002203#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002204 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002205
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002206 if (priv != NULL) {
2207 int i;
2208 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
2209 __GLXscreenConfigs *const psc = &priv->screenConfigs[i];
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002210
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002211 assert((pdraw == NULL) || (i != -1));
2212 return ((pdraw && psc->sbc && psc->msc)
2213 && ((*psc->msc->getMSC) (psc->driScreen, msc) == 0)
2214 && ((*psc->sbc->getSBC) (pdraw->driDrawable, sbc) == 0)
2215 && (__glXGetUST(ust) == 0));
2216 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002217#else
2218 (void) dpy;
2219 (void) drawable;
2220 (void) ust;
2221 (void) msc;
2222 (void) sbc;
2223#endif
2224 return False;
2225}
2226
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002227#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg3d28a262008-03-08 22:28:01 -05002228_X_HIDDEN GLboolean
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002229__driGetMscRateOML(__DRIdrawable * draw,
2230 int32_t * numerator, int32_t * denominator, void *private)
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002231{
2232#ifdef XF86VIDMODE
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002233 __GLXscreenConfigs *psc;
2234 XF86VidModeModeLine mode_line;
2235 int dot_clock;
2236 int i;
2237 __GLXDRIdrawable *glxDraw = private;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002238
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002239 psc = glxDraw->psc;
2240 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2241 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2242 unsigned n = dot_clock * 1000;
2243 unsigned d = mode_line.vtotal * mode_line.htotal;
2244
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002245# define V_INTERLACE 0x010
2246# define V_DBLSCAN 0x020
2247
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002248 if (mode_line.flags & V_INTERLACE)
2249 n *= 2;
2250 else if (mode_line.flags & V_DBLSCAN)
2251 d *= 2;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002252
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002253 /* The OML_sync_control spec requires that if the refresh rate is a
2254 * whole number, that the returned numerator be equal to the refresh
2255 * rate and the denominator be 1.
2256 */
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002257
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002258 if (n % d == 0) {
2259 n /= d;
2260 d = 1;
2261 }
2262 else {
2263 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002264
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002265 /* This is a poor man's way to reduce a fraction. It's far from
2266 * perfect, but it will work well enough for this situation.
2267 */
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002268
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002269 for (i = 0; f[i] != 0; i++) {
2270 while (n % f[i] == 0 && d % f[i] == 0) {
2271 d /= f[i];
2272 n /= f[i];
2273 }
2274 }
2275 }
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002276
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002277 *numerator = n;
2278 *denominator = d;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002279
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002280 return True;
2281 }
2282 else
2283 return False;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002284#else
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002285 return False;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002286#endif
2287}
2288#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002289
2290/**
2291 * Determine the refresh rate of the specified drawable and display.
2292 *
2293 * \param dpy Display whose refresh rate is to be determined.
2294 * \param drawable Drawable whose refresh rate is to be determined.
2295 * \param numerator Numerator of the refresh rate.
2296 * \param demoninator Denominator of the refresh rate.
2297 * \return If the refresh rate for the specified display and drawable could
2298 * be calculated, True is returned. Otherwise False is returned.
2299 *
2300 * \note This function is implemented entirely client-side. A lot of other
2301 * functionality is required to export GLX_OML_sync_control, so on
2302 * XFree86 this function can be called for direct-rendering contexts
2303 * when GLX_OML_sync_control appears in the client extension string.
2304 */
2305
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002306_X_HIDDEN GLboolean
2307__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2308 int32_t * numerator, int32_t * denominator)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002309{
2310#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002311 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002312
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002313 if (draw == NULL)
2314 return False;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002315
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002316 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002317#else
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002318 (void) dpy;
2319 (void) drawable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002320 (void) numerator;
2321 (void) denominator;
2322#endif
2323 return False;
2324}
2325
2326
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002327static int64_t
2328__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
2329 int64_t target_msc, int64_t divisor, int64_t remainder)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002330{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002331#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002332 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002333 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002334 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002335
2336 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2337 * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2338 * of -1 if the function failed because of errors detected in the input
2339 * parameters"
2340 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002341 if (divisor < 0 || remainder < 0 || target_msc < 0)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002342 return -1;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002343 if (divisor > 0 && remainder >= divisor)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002344 return -1;
2345
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002346 if (pdraw != NULL && psc->counters != NULL)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002347 return (*psc->sbc->swapBuffersMSC) (pdraw->driDrawable, target_msc,
2348 divisor, remainder);
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002349
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002350#else
2351 (void) dpy;
2352 (void) drawable;
2353 (void) target_msc;
2354 (void) divisor;
2355 (void) remainder;
2356#endif
2357 return 0;
2358}
2359
2360
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002361static Bool
2362__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2363 int64_t target_msc, int64_t divisor,
2364 int64_t remainder, int64_t * ust,
2365 int64_t * msc, int64_t * sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002366{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002367#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002368 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002369 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002370 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2371 int ret;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002372
2373 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2374 * error", but the return type in the spec is Bool.
2375 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002376 if (divisor < 0 || remainder < 0 || target_msc < 0)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002377 return False;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002378 if (divisor > 0 && remainder >= divisor)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002379 return False;
2380
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002381 if (pdraw != NULL && psc->msc != NULL) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002382 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
2383 divisor, remainder, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002384
2385 /* __glXGetUST returns zero on success and non-zero on failure.
2386 * This function returns True on success and False on failure.
2387 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002388 return ((ret == 0) && (__glXGetUST(ust) == 0));
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002389 }
2390#else
2391 (void) dpy;
2392 (void) drawable;
2393 (void) target_msc;
2394 (void) divisor;
2395 (void) remainder;
2396 (void) ust;
2397 (void) msc;
2398 (void) sbc;
2399#endif
2400 return False;
2401}
2402
2403
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002404static Bool
2405__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2406 int64_t target_sbc, int64_t * ust,
2407 int64_t * msc, int64_t * sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002408{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002409#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002410 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002411 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002412 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2413 int ret;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002414
2415 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2416 * error", but the return type in the spec is Bool.
2417 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002418 if (target_sbc < 0)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002419 return False;
2420
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002421 if (pdraw != NULL && psc->sbc != NULL) {
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002422 ret =
2423 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002424
2425 /* __glXGetUST returns zero on success and non-zero on failure.
2426 * This function returns True on success and False on failure.
2427 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002428 return ((ret == 0) && (__glXGetUST(ust) == 0));
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002429 }
2430#else
2431 (void) dpy;
2432 (void) drawable;
2433 (void) target_sbc;
2434 (void) ust;
2435 (void) msc;
2436 (void) sbc;
2437#endif
2438 return False;
2439}
2440
2441
2442/**
2443 * GLX_MESA_allocate_memory
2444 */
2445/*@{*/
2446
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002447PUBLIC void *
2448glXAllocateMemoryMESA(Display * dpy, int scrn,
2449 size_t size, float readFreq,
2450 float writeFreq, float priority)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002451{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002452#ifdef __DRI_ALLOCATE
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002453 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002454
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002455 if (psc && psc->allocate)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002456 return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
2457 readFreq, writeFreq, priority);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002458
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002459#else
2460 (void) dpy;
2461 (void) scrn;
2462 (void) size;
2463 (void) readFreq;
2464 (void) writeFreq;
2465 (void) priority;
2466#endif /* GLX_DIRECT_RENDERING */
2467
2468 return NULL;
2469}
2470
2471
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002472PUBLIC void
2473glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002474{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002475#ifdef __DRI_ALLOCATE
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002476 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002477
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002478 if (psc && psc->allocate)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002479 (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002480
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002481#else
2482 (void) dpy;
2483 (void) scrn;
2484 (void) pointer;
2485#endif /* GLX_DIRECT_RENDERING */
2486}
2487
2488
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002489PUBLIC GLuint
2490glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002491{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002492#ifdef __DRI_ALLOCATE
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002493 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002494
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002495 if (psc && psc->allocate)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002496 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002497
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002498#else
2499 (void) dpy;
2500 (void) scrn;
2501 (void) pointer;
2502#endif /* GLX_DIRECT_RENDERING */
2503
2504 return ~0L;
2505}
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002506
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002507/*@}*/
2508
2509
2510/**
2511 * Mesa extension stubs. These will help reduce portability problems.
2512 */
2513/*@{*/
2514
2515/**
2516 * Release all buffers associated with the specified GLX drawable.
2517 *
2518 * \todo
2519 * This function was intended for stand-alone Mesa. The issue there is that
2520 * the library doesn't get any notification when a window is closed. In
2521 * DRI there is a similar but slightly different issue. When GLX 1.3 is
2522 * supported, there are 3 different functions to destroy a drawable. It
2523 * should be possible to create GLX protocol (or have it determine which
2524 * protocol to use based on the type of the drawable) to have one function
2525 * do the work of 3. For the direct-rendering case, this function could
2526 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2527 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2528 * would need to be used. This really should be done as part of the new DRI
2529 * interface work.
2530 *
2531 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2532 * __driGarbageCollectDrawables
2533 * glXDestroyGLXPixmap
2534 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2535 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2536 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002537static Bool
2538__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002539{
2540 (void) dpy;
2541 (void) d;
2542 return False;
2543}
2544
2545
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002546PUBLIC GLXPixmap
2547glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
2548 Pixmap pixmap, Colormap cmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002549{
2550 (void) dpy;
2551 (void) visual;
2552 (void) pixmap;
2553 (void) cmap;
2554 return 0;
2555}
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002556
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002557/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002558
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002559
2560/**
2561 * GLX_MESA_copy_sub_buffer
2562 */
Brian Paulf2ad1b62006-03-31 15:48:04 +00002563#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002564static void
2565__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
2566 int x, int y, int width, int height)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002567{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002568 xGLXVendorPrivateReq *req;
2569 GLXContext gc;
2570 GLXContextTag tag;
2571 CARD32 *drawable_ptr;
2572 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2573 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002574
Kristian Høgsbergac3e8382007-05-15 15:17:30 -04002575#ifdef __DRI_COPY_SUB_BUFFER
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002576 int screen;
2577 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2578 if (pdraw != NULL) {
2579 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2580 if (psc->copySubBuffer != NULL) {
2581 (*psc->copySubBuffer->copySubBuffer) (pdraw->driDrawable,
2582 x, y, width, height);
2583 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002584
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002585 return;
2586 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002587#endif
2588
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002589 opcode = __glXSetupForCommand(dpy);
2590 if (!opcode)
2591 return;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002592
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002593 /*
Brian Paulf2ad1b62006-03-31 15:48:04 +00002594 ** The calling thread may or may not have a current context. If it
2595 ** does, send the context tag so the server can do a flush.
2596 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002597 gc = __glXGetCurrentContext();
2598 if ((gc != NULL) && (dpy == gc->currentDpy) &&
2599 ((drawable == gc->currentDrawable) ||
2600 (drawable == gc->currentReadable))) {
2601 tag = gc->currentContextTag;
2602 }
2603 else {
2604 tag = 0;
2605 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002606
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002607 LockDisplay(dpy);
2608 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
2609 req->reqType = opcode;
2610 req->glxCode = X_GLXVendorPrivate;
2611 req->vendorCode = X_GLXvop_CopySubBufferMESA;
2612 req->contextTag = tag;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002613
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002614 drawable_ptr = (CARD32 *) (req + 1);
2615 x_ptr = (INT32 *) (drawable_ptr + 1);
2616 y_ptr = (INT32 *) (drawable_ptr + 2);
2617 w_ptr = (INT32 *) (drawable_ptr + 3);
2618 h_ptr = (INT32 *) (drawable_ptr + 4);
Brian Paulf2ad1b62006-03-31 15:48:04 +00002619
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002620 *drawable_ptr = drawable;
2621 *x_ptr = x;
2622 *y_ptr = y;
2623 *w_ptr = width;
2624 *h_ptr = height;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002625
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002626 UnlockDisplay(dpy);
2627 SyncHandle();
Brian Paulf2ad1b62006-03-31 15:48:04 +00002628}
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002629
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002630
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002631/**
2632 * GLX_EXT_texture_from_pixmap
2633 */
2634/*@{*/
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002635static void
2636__glXBindTexImageEXT(Display * dpy,
2637 GLXDrawable drawable, int buffer, const int *attrib_list)
Brian Paul42725d62006-02-07 00:39:56 +00002638{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002639 xGLXVendorPrivateReq *req;
2640 GLXContext gc = __glXGetCurrentContext();
2641 CARD32 *drawable_ptr;
2642 INT32 *buffer_ptr;
2643 CARD32 *num_attrib_ptr;
2644 CARD32 *attrib_ptr;
2645 CARD8 opcode;
2646 unsigned int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002647
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002648 if (gc == NULL)
2649 return;
Brian Paul42725d62006-02-07 00:39:56 +00002650
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002651 i = 0;
2652 if (attrib_list) {
2653 while (attrib_list[i * 2] != None)
2654 i++;
2655 }
Brian Paul42725d62006-02-07 00:39:56 +00002656
2657#ifdef GLX_DIRECT_RENDERING
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002658 if (gc->driContext) {
2659 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
2660
2661 if (pdraw != NULL)
2662 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext,
2663 pdraw->textureTarget,
2664 pdraw->driDrawable);
2665
2666 return;
2667 }
Brian Paul42725d62006-02-07 00:39:56 +00002668#endif
2669
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002670 opcode = __glXSetupForCommand(dpy);
2671 if (!opcode)
2672 return;
Brian Paul42725d62006-02-07 00:39:56 +00002673
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002674 LockDisplay(dpy);
2675 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
2676 req->reqType = opcode;
2677 req->glxCode = X_GLXVendorPrivate;
2678 req->vendorCode = X_GLXvop_BindTexImageEXT;
2679 req->contextTag = gc->currentContextTag;
Brian Paul42725d62006-02-07 00:39:56 +00002680
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002681 drawable_ptr = (CARD32 *) (req + 1);
2682 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2683 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2684 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
Brian Paul42725d62006-02-07 00:39:56 +00002685
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002686 *drawable_ptr = drawable;
2687 *buffer_ptr = buffer;
2688 *num_attrib_ptr = (CARD32) i;
Brian Paul42725d62006-02-07 00:39:56 +00002689
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002690 i = 0;
2691 if (attrib_list) {
2692 while (attrib_list[i * 2] != None) {
2693 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2694 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2695 i++;
2696 }
2697 }
2698
2699 UnlockDisplay(dpy);
2700 SyncHandle();
Brian Paul42725d62006-02-07 00:39:56 +00002701}
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002702
2703static void
2704__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
2705{
2706 xGLXVendorPrivateReq *req;
2707 GLXContext gc = __glXGetCurrentContext();
2708 CARD32 *drawable_ptr;
2709 INT32 *buffer_ptr;
2710 CARD8 opcode;
2711
2712 if (gc == NULL)
2713 return;
2714
2715#ifdef GLX_DIRECT_RENDERING
2716 if (gc->driContext)
2717 return;
2718#endif
2719
2720 opcode = __glXSetupForCommand(dpy);
2721 if (!opcode)
2722 return;
2723
2724 LockDisplay(dpy);
2725 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
2726 req->reqType = opcode;
2727 req->glxCode = X_GLXVendorPrivate;
2728 req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
2729 req->contextTag = gc->currentContextTag;
2730
2731 drawable_ptr = (CARD32 *) (req + 1);
2732 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2733
2734 *drawable_ptr = drawable;
2735 *buffer_ptr = buffer;
2736
2737 UnlockDisplay(dpy);
2738 SyncHandle();
2739}
2740
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002741/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002742
2743/**
2744 * \c strdup is actually not a standard ANSI C or POSIX routine.
2745 * Irix will not define it if ANSI mode is in effect.
2746 *
2747 * \sa strdup
2748 */
Kristian Høgsberg3d28a262008-03-08 22:28:01 -05002749_X_HIDDEN char *
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002750__glXstrdup(const char *str)
2751{
2752 char *copy;
2753 copy = (char *) Xmalloc(strlen(str) + 1);
2754 if (!copy)
2755 return NULL;
2756 strcpy(copy, str);
2757 return copy;
2758}
2759
2760/*
2761** glXGetProcAddress support
2762*/
2763
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002764struct name_address_pair
2765{
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002766 const char *Name;
2767 GLvoid *Address;
2768};
2769
2770#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2771#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2772
2773static const struct name_address_pair GLX_functions[] = {
2774 /*** GLX_VERSION_1_0 ***/
2775 GLX_FUNCTION( glXChooseVisual ),
2776 GLX_FUNCTION( glXCopyContext ),
2777 GLX_FUNCTION( glXCreateContext ),
2778 GLX_FUNCTION( glXCreateGLXPixmap ),
2779 GLX_FUNCTION( glXDestroyContext ),
2780 GLX_FUNCTION( glXDestroyGLXPixmap ),
2781 GLX_FUNCTION( glXGetConfig ),
2782 GLX_FUNCTION( glXGetCurrentContext ),
2783 GLX_FUNCTION( glXGetCurrentDrawable ),
2784 GLX_FUNCTION( glXIsDirect ),
2785 GLX_FUNCTION( glXMakeCurrent ),
2786 GLX_FUNCTION( glXQueryExtension ),
2787 GLX_FUNCTION( glXQueryVersion ),
2788 GLX_FUNCTION( glXSwapBuffers ),
2789 GLX_FUNCTION( glXUseXFont ),
2790 GLX_FUNCTION( glXWaitGL ),
2791 GLX_FUNCTION( glXWaitX ),
2792
2793 /*** GLX_VERSION_1_1 ***/
2794 GLX_FUNCTION( glXGetClientString ),
2795 GLX_FUNCTION( glXQueryExtensionsString ),
2796 GLX_FUNCTION( glXQueryServerString ),
2797
2798 /*** GLX_VERSION_1_2 ***/
2799 GLX_FUNCTION( glXGetCurrentDisplay ),
2800
2801 /*** GLX_VERSION_1_3 ***/
2802 GLX_FUNCTION( glXChooseFBConfig ),
2803 GLX_FUNCTION( glXCreateNewContext ),
2804 GLX_FUNCTION( glXCreatePbuffer ),
2805 GLX_FUNCTION( glXCreatePixmap ),
2806 GLX_FUNCTION( glXCreateWindow ),
2807 GLX_FUNCTION( glXDestroyPbuffer ),
2808 GLX_FUNCTION( glXDestroyPixmap ),
2809 GLX_FUNCTION( glXDestroyWindow ),
2810 GLX_FUNCTION( glXGetCurrentReadDrawable ),
2811 GLX_FUNCTION( glXGetFBConfigAttrib ),
2812 GLX_FUNCTION( glXGetFBConfigs ),
2813 GLX_FUNCTION( glXGetSelectedEvent ),
2814 GLX_FUNCTION( glXGetVisualFromFBConfig ),
2815 GLX_FUNCTION( glXMakeContextCurrent ),
2816 GLX_FUNCTION( glXQueryContext ),
2817 GLX_FUNCTION( glXQueryDrawable ),
2818 GLX_FUNCTION( glXSelectEvent ),
2819
2820 /*** GLX_SGI_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002821 GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002822
2823 /*** GLX_SGI_video_sync ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002824 GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ),
2825 GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002826
2827 /*** GLX_SGI_make_current_read ***/
2828 GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ),
2829 GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ),
2830
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002831 /*** GLX_EXT_import_context ***/
2832 GLX_FUNCTION( glXFreeContextEXT ),
2833 GLX_FUNCTION( glXGetContextIDEXT ),
2834 GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ),
2835 GLX_FUNCTION( glXImportContextEXT ),
2836 GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ),
2837
2838 /*** GLX_SGIX_fbconfig ***/
2839 GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ),
2840 GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ),
2841 GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ),
2842 GLX_FUNCTION( glXCreateContextWithConfigSGIX ),
2843 GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ),
2844 GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ),
2845
2846 /*** GLX_SGIX_pbuffer ***/
2847 GLX_FUNCTION( glXCreateGLXPbufferSGIX ),
2848 GLX_FUNCTION( glXDestroyGLXPbufferSGIX ),
2849 GLX_FUNCTION( glXQueryGLXPbufferSGIX ),
2850 GLX_FUNCTION( glXSelectEventSGIX ),
2851 GLX_FUNCTION( glXGetSelectedEventSGIX ),
2852
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002853 /*** GLX_SGIX_swap_group ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002854 GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002855
2856 /*** GLX_SGIX_swap_barrier ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002857 GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ),
2858 GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002859
2860 /*** GLX_MESA_allocate_memory ***/
2861 GLX_FUNCTION( glXAllocateMemoryMESA ),
2862 GLX_FUNCTION( glXFreeMemoryMESA ),
2863 GLX_FUNCTION( glXGetMemoryOffsetMESA ),
2864
2865 /*** GLX_MESA_copy_sub_buffer ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002866 GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002867
2868 /*** GLX_MESA_pixmap_colormap ***/
2869 GLX_FUNCTION( glXCreateGLXPixmapMESA ),
2870
2871 /*** GLX_MESA_release_buffers ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002872 GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002873
2874 /*** GLX_MESA_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002875 GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ),
2876 GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002877
2878 /*** GLX_MESA_swap_frame_usage ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002879 GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ),
2880 GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ),
2881 GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ),
2882 GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002883
2884 /*** GLX_ARB_get_proc_address ***/
2885 GLX_FUNCTION( glXGetProcAddressARB ),
2886
2887 /*** GLX 1.4 ***/
2888 GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ),
2889
2890 /*** GLX_OML_sync_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002891 GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ),
2892 GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ),
2893 GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ),
2894 GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ),
2895 GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002896
Brian Paul42725d62006-02-07 00:39:56 +00002897 /*** GLX_EXT_texture_from_pixmap ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002898 GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ),
2899 GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ),
Brian Paul42725d62006-02-07 00:39:56 +00002900
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002901#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002902 /*** DRI configuration ***/
2903 GLX_FUNCTION( glXGetScreenDriver ),
2904 GLX_FUNCTION( glXGetDriverConfig ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002905#endif
2906
2907 { NULL, NULL } /* end of list */
2908};
2909
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002910static const GLvoid *
2911get_glx_proc_address(const char *funcName)
2912{
2913 GLuint i;
2914
2915 /* try static functions */
2916 for (i = 0; GLX_functions[i].Name; i++) {
2917 if (strcmp(GLX_functions[i].Name, funcName) == 0)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002918 return GLX_functions[i].Address;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002919 }
2920
2921 return NULL;
2922}
2923
2924
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002925/**
2926 * Get the address of a named GL function. This is the pre-GLX 1.4 name for
2927 * \c glXGetProcAddress.
2928 *
2929 * \param procName Name of a GL or GLX function.
2930 * \returns A pointer to the named function
2931 *
2932 * \sa glXGetProcAddress
2933 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002934PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002935{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002936 typedef void (*gl_function) (void);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002937 gl_function f;
2938
2939
2940 /* Search the table of GLX and internal functions first. If that
2941 * fails and the supplied name could be a valid core GL name, try
2942 * searching the core GL function table. This check is done to prevent
2943 * DRI based drivers from searching the core GL function table for
2944 * internal API functions.
2945 */
2946
2947 f = (gl_function) get_glx_proc_address((const char *) procName);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002948 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2949 && (procName[2] != 'X')) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002950 f = (gl_function) _glapi_get_proc_address((const char *) procName);
2951 }
2952
2953 return f;
2954}
2955
2956/**
2957 * Get the address of a named GL function. This is the GLX 1.4 name for
2958 * \c glXGetProcAddressARB.
2959 *
2960 * \param procName Name of a GL or GLX function.
2961 * \returns A pointer to the named function
2962 *
2963 * \sa glXGetProcAddressARB
2964 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002965PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002966#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002967 __attribute__ ((alias("glXGetProcAddressARB")));
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002968#else
2969{
2970 return glXGetProcAddressARB(procName);
2971}
2972#endif /* __GNUC__ */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002973
2974
2975#ifdef GLX_DIRECT_RENDERING
2976/**
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002977 * Get the unadjusted system time (UST). Currently, the UST is measured in
2978 * microseconds since Epoc. The actual resolution of the UST may vary from
2979 * system to system, and the units may vary from release to release.
2980 * Drivers should not call this function directly. They should instead use
2981 * \c glXGetProcAddress to obtain a pointer to the function.
2982 *
2983 * \param ust Location to store the 64-bit UST
2984 * \returns Zero on success or a negative errno value on failure.
2985 *
2986 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2987 *
2988 * \since Internal API version 20030317.
2989 */
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002990_X_HIDDEN int
2991__glXGetUST(int64_t * ust)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002992{
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002993 struct timeval tv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002994
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002995 if (ust == NULL) {
2996 return -EFAULT;
2997 }
2998
2999 if (gettimeofday(&tv, NULL) == 0) {
3000 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
3001 return 0;
3002 }
3003 else {
3004 return -errno;
3005 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00003006}
3007#endif /* GLX_DIRECT_RENDERING */