mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-05-21 13:18:25 +02:00
Get rid of glcontextmodes.[ch] from build, rename __GlcontextModes to
__GLXcontext. Drop all #includes of glcontextmodes.h and glcore.h.
Drop the DRI context modes extension.
Add protocol code to DRI2 module and load DRI2 extension by default.
(cherry picked from commit c40e0b51f0)
762 lines
21 KiB
C
762 lines
21 KiB
C
/*
|
|
* Copyright © 2007 Red Hat, Inc
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
* and its documentation for any purpose is hereby granted without
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
* and that both that copyright notice and this permission notice
|
|
* appear in supporting documentation, and that the name of Red Hat,
|
|
* Inc not be used in advertising or publicity pertaining to
|
|
* distribution of the software without specific, written prior
|
|
* permission. Red Hat, Inc makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as
|
|
* is" without express or implied warranty.
|
|
*
|
|
* RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
* NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/time.h>
|
|
#include <dlfcn.h>
|
|
|
|
#include <drm.h>
|
|
#include <GL/gl.h>
|
|
#include <GL/internal/dri_interface.h>
|
|
#include <GL/glxtokens.h>
|
|
|
|
#include <windowstr.h>
|
|
#include <os.h>
|
|
|
|
#define _XF86DRI_SERVER_
|
|
#include <xf86drm.h>
|
|
#include <xf86.h>
|
|
#include <dri2.h>
|
|
|
|
#include "glxserver.h"
|
|
#include "glxutil.h"
|
|
|
|
#include "g_disptab.h"
|
|
#include "glapitable.h"
|
|
#include "glapi.h"
|
|
#include "glthread.h"
|
|
#include "dispatch.h"
|
|
#include "extension_string.h"
|
|
|
|
typedef struct __GLXDRIscreen __GLXDRIscreen;
|
|
typedef struct __GLXDRIcontext __GLXDRIcontext;
|
|
typedef struct __GLXDRIdrawable __GLXDRIdrawable;
|
|
typedef struct __GLXDRIconfig __GLXDRIconfig;
|
|
|
|
struct __GLXDRIscreen {
|
|
__GLXscreen base;
|
|
__DRIscreen *driScreen;
|
|
void *driver;
|
|
int fd;
|
|
|
|
xf86EnterVTProc *enterVT;
|
|
xf86LeaveVTProc *leaveVT;
|
|
|
|
const __DRIcoreExtension *core;
|
|
const __DRIcopySubBufferExtension *copySubBuffer;
|
|
const __DRIswapControlExtension *swapControl;
|
|
const __DRItexBufferExtension *texBuffer;
|
|
|
|
unsigned char glx_enable_bits[__GLX_EXT_BYTES];
|
|
};
|
|
|
|
struct __GLXDRIcontext {
|
|
__GLXcontext base;
|
|
__DRIcontext *driContext;
|
|
};
|
|
|
|
struct __GLXDRIdrawable {
|
|
__GLXdrawable base;
|
|
__DRIdrawable *driDrawable;
|
|
__GLXDRIscreen *screen;
|
|
};
|
|
|
|
struct __GLXDRIconfig {
|
|
__GLXconfig config;
|
|
const __DRIconfig *driConfig;
|
|
};
|
|
|
|
static void
|
|
__glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
|
{
|
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
|
const __DRIcoreExtension *core = private->screen->core;
|
|
|
|
(*core->destroyDrawable)(private->driDrawable);
|
|
|
|
/* If the X window was destroyed, the dri DestroyWindow hook will
|
|
* aready have taken care of this, so only call if pDraw isn't NULL. */
|
|
if (drawable->pDraw != NULL)
|
|
DRI2DestroyDrawable(drawable->pDraw);
|
|
|
|
xfree(private);
|
|
}
|
|
|
|
static GLboolean
|
|
__glXDRIdrawableResize(__GLXdrawable *glxPriv)
|
|
{
|
|
/* Nothing to do here, the DRI driver asks the server for drawable
|
|
* geometry when it sess the SAREA timestamps change.*/
|
|
|
|
return GL_TRUE;
|
|
}
|
|
|
|
static GLboolean
|
|
__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
|
|
{
|
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
|
const __DRIcoreExtension *core = private->screen->core;
|
|
|
|
(*core->swapBuffers)(private->driDrawable);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static int
|
|
__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
|
|
{
|
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
|
const __DRIswapControlExtension *swapControl = private->screen->swapControl;
|
|
|
|
if (swapControl)
|
|
swapControl->setSwapInterval(private->driDrawable, interval);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
__glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
|
|
int x, int y, int w, int h)
|
|
{
|
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
|
|
const __DRIcopySubBufferExtension *copySubBuffer =
|
|
private->screen->copySubBuffer;
|
|
|
|
if (copySubBuffer)
|
|
(*copySubBuffer->copySubBuffer)(private->driDrawable, x, y, w, h);
|
|
}
|
|
|
|
static void
|
|
__glXDRIcontextDestroy(__GLXcontext *baseContext)
|
|
{
|
|
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
|
|
|
|
(*screen->core->destroyContext)(context->driContext);
|
|
__glXContextDestroy(&context->base);
|
|
xfree(context);
|
|
}
|
|
|
|
static int
|
|
__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
|
|
{
|
|
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
|
|
__GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
|
|
__GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
|
|
|
|
return (*screen->core->bindContext)(context->driContext,
|
|
draw->driDrawable,
|
|
read->driDrawable);
|
|
}
|
|
|
|
static int
|
|
__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
|
|
{
|
|
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
|
|
|
|
return (*screen->core->unbindContext)(context->driContext);
|
|
}
|
|
|
|
static int
|
|
__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
|
|
unsigned long mask)
|
|
{
|
|
__GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
|
|
__GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
|
|
|
|
return (*screen->core->copyContext)(dst->driContext,
|
|
src->driContext, mask);
|
|
}
|
|
|
|
static int
|
|
__glXDRIcontextForceCurrent(__GLXcontext *baseContext)
|
|
{
|
|
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
|
|
__GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
|
|
__GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
|
|
|
|
return (*screen->core->bindContext)(context->driContext,
|
|
draw->driDrawable,
|
|
read->driDrawable);
|
|
}
|
|
|
|
#ifdef __DRI_TEX_BUFFER
|
|
|
|
static int
|
|
__glXDRIbindTexImage(__GLXcontext *baseContext,
|
|
int buffer,
|
|
__GLXdrawable *glxPixmap)
|
|
{
|
|
__GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
|
|
const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
|
|
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
|
|
|
|
if (texBuffer == NULL)
|
|
return Success;
|
|
|
|
texBuffer->setTexBuffer(context->driContext,
|
|
glxPixmap->target,
|
|
drawable->driDrawable);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
__glXDRIreleaseTexImage(__GLXcontext *baseContext,
|
|
int buffer,
|
|
__GLXdrawable *pixmap)
|
|
{
|
|
/* FIXME: Just unbind the texture? */
|
|
return Success;
|
|
}
|
|
|
|
#else
|
|
|
|
static int
|
|
__glXDRIbindTexImage(__GLXcontext *baseContext,
|
|
int buffer,
|
|
__GLXdrawable *glxPixmap)
|
|
{
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
__glXDRIreleaseTexImage(__GLXcontext *baseContext,
|
|
int buffer,
|
|
__GLXdrawable *pixmap)
|
|
{
|
|
return Success;
|
|
}
|
|
|
|
#endif
|
|
|
|
static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
|
|
__glXDRIbindTexImage,
|
|
__glXDRIreleaseTexImage
|
|
};
|
|
|
|
static void
|
|
__glXDRIscreenDestroy(__GLXscreen *baseScreen)
|
|
{
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
|
|
|
|
(*screen->core->destroyScreen)(screen->driScreen);
|
|
|
|
dlclose(screen->driver);
|
|
|
|
__glXScreenDestroy(baseScreen);
|
|
|
|
xfree(screen);
|
|
}
|
|
|
|
static __GLXcontext *
|
|
__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
|
|
__GLXconfig *glxConfig,
|
|
__GLXcontext *baseShareContext)
|
|
{
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
|
|
__GLXDRIcontext *context, *shareContext;
|
|
__GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
|
|
const __DRIcoreExtension *core = screen->core;
|
|
__DRIcontext *driShare;
|
|
|
|
shareContext = (__GLXDRIcontext *) baseShareContext;
|
|
if (shareContext)
|
|
driShare = shareContext->driContext;
|
|
else
|
|
driShare = NULL;
|
|
|
|
context = xalloc(sizeof *context);
|
|
if (context == NULL)
|
|
return NULL;
|
|
|
|
memset(context, 0, sizeof *context);
|
|
context->base.destroy = __glXDRIcontextDestroy;
|
|
context->base.makeCurrent = __glXDRIcontextMakeCurrent;
|
|
context->base.loseCurrent = __glXDRIcontextLoseCurrent;
|
|
context->base.copy = __glXDRIcontextCopy;
|
|
context->base.forceCurrent = __glXDRIcontextForceCurrent;
|
|
context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
|
|
|
|
context->driContext =
|
|
(*core->createNewContext)(screen->driScreen,
|
|
config->driConfig, driShare, context);
|
|
|
|
return &context->base;
|
|
}
|
|
|
|
static __GLXdrawable *
|
|
__glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
DrawablePtr pDraw,
|
|
int type,
|
|
XID drawId,
|
|
__GLXconfig *glxConfig)
|
|
{
|
|
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
|
|
__GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
|
|
__GLXDRIdrawable *private;
|
|
GLboolean retval;
|
|
unsigned int handle, head;
|
|
|
|
private = xalloc(sizeof *private);
|
|
if (private == NULL)
|
|
return NULL;
|
|
|
|
memset(private, 0, sizeof *private);
|
|
|
|
private->screen = driScreen;
|
|
if (!__glXDrawableInit(&private->base, screen,
|
|
pDraw, type, drawId, glxConfig)) {
|
|
xfree(private);
|
|
return NULL;
|
|
}
|
|
|
|
private->base.destroy = __glXDRIdrawableDestroy;
|
|
private->base.resize = __glXDRIdrawableResize;
|
|
private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
|
|
private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
|
|
|
|
retval = DRI2CreateDrawable(pDraw, &handle, &head);
|
|
|
|
private->driDrawable =
|
|
(*driScreen->core->createNewDrawable)(driScreen->driScreen,
|
|
config->driConfig,
|
|
handle, head, private);
|
|
|
|
return &private->base;
|
|
}
|
|
|
|
static int
|
|
getUST(int64_t *ust)
|
|
{
|
|
struct timeval tv;
|
|
|
|
if (ust == NULL)
|
|
return -EFAULT;
|
|
|
|
if (gettimeofday(&tv, NULL) == 0) {
|
|
ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
return 0;
|
|
} else {
|
|
return -errno;
|
|
}
|
|
}
|
|
|
|
static const __DRIsystemTimeExtension systemTimeExtension = {
|
|
{ __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
|
|
getUST,
|
|
NULL,
|
|
};
|
|
|
|
static void dri2ReemitDrawableInfo(__DRIdrawable *draw, unsigned int *tail,
|
|
void *loaderPrivate)
|
|
{
|
|
__GLXDRIdrawable *pdraw = loaderPrivate;
|
|
|
|
DRI2ReemitDrawableInfo(pdraw->base.pDraw, tail);
|
|
}
|
|
|
|
static void dri2PostDamage(__DRIdrawable *draw,
|
|
struct drm_clip_rect *rects,
|
|
int numRects, void *loaderPrivate)
|
|
{
|
|
__GLXDRIdrawable *drawable = loaderPrivate;
|
|
DrawablePtr pDraw = drawable->base.pDraw;
|
|
RegionRec region;
|
|
|
|
REGION_INIT(pDraw->pScreen, ®ion, (BoxPtr) rects, numRects);
|
|
REGION_TRANSLATE(pScreen, ®ion, pDraw->x, pDraw->y);
|
|
DamageDamageRegion(pDraw, ®ion);
|
|
REGION_UNINIT(pDraw->pScreen, ®ion);
|
|
}
|
|
|
|
static const __DRIloaderExtension loaderExtension = {
|
|
{ __DRI_LOADER, __DRI_LOADER_VERSION },
|
|
dri2ReemitDrawableInfo,
|
|
dri2PostDamage
|
|
};
|
|
|
|
static const __DRIextension *loader_extensions[] = {
|
|
&systemTimeExtension.base,
|
|
&loaderExtension.base,
|
|
NULL
|
|
};
|
|
|
|
static const char dri_driver_path[] = DRI_DRIVER_PATH;
|
|
|
|
static Bool
|
|
glxDRIEnterVT (int index, int flags)
|
|
{
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *)
|
|
glxGetScreen(screenInfo.screens[index]);
|
|
|
|
LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
|
|
|
|
if (!(*screen->enterVT) (index, flags))
|
|
return FALSE;
|
|
|
|
glxResumeClients();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
glxDRILeaveVT (int index, int flags)
|
|
{
|
|
__GLXDRIscreen *screen = (__GLXDRIscreen *)
|
|
glxGetScreen(screenInfo.screens[index]);
|
|
|
|
LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
|
|
|
|
glxSuspendClients();
|
|
|
|
return (*screen->leaveVT) (index, flags);
|
|
}
|
|
|
|
static void
|
|
initializeExtensions(__GLXDRIscreen *screen)
|
|
{
|
|
const __DRIextension **extensions;
|
|
int i;
|
|
|
|
extensions = screen->core->getExtensions(screen->driScreen);
|
|
|
|
for (i = 0; extensions[i]; i++) {
|
|
#ifdef __DRI_COPY_SUB_BUFFER
|
|
if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
|
|
screen->copySubBuffer =
|
|
(const __DRIcopySubBufferExtension *) extensions[i];
|
|
__glXEnableExtension(screen->glx_enable_bits,
|
|
"GLX_MESA_copy_sub_buffer");
|
|
|
|
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
|
|
}
|
|
#endif
|
|
|
|
#ifdef __DRI_SWAP_CONTROL
|
|
if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
|
|
screen->swapControl =
|
|
(const __DRIswapControlExtension *) extensions[i];
|
|
__glXEnableExtension(screen->glx_enable_bits,
|
|
"GLX_SGI_swap_control");
|
|
__glXEnableExtension(screen->glx_enable_bits,
|
|
"GLX_MESA_swap_control");
|
|
|
|
LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
|
|
}
|
|
#endif
|
|
|
|
#ifdef __DRI_TEX_BUFFER
|
|
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
|
|
screen->texBuffer =
|
|
(const __DRItexBufferExtension *) extensions[i];
|
|
/* GLX_EXT_texture_from_pixmap is always enabled. */
|
|
LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
|
|
}
|
|
#endif
|
|
/* Ignore unknown extensions */
|
|
}
|
|
}
|
|
|
|
#define __ATTRIB(attrib, field) \
|
|
{ attrib, offsetof(__GLXconfig, field) }
|
|
|
|
static const struct { unsigned int attrib, offset; } attribMap[] = {
|
|
__ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
|
|
__ATTRIB(__DRI_ATTRIB_LEVEL, level),
|
|
__ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
|
|
__ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
|
|
__ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
|
|
__ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
|
|
__ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
|
|
__ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
|
|
__ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
|
|
__ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
|
|
__ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
|
|
__ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
|
|
__ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
|
|
__ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
|
|
__ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
|
|
__ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
|
|
__ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
|
|
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
|
|
__ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode),
|
|
__ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
|
|
__ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
|
|
__ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
|
|
__ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
|
|
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
|
|
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
|
|
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
|
|
__ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
|
|
__ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
|
|
__ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
|
|
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
|
|
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
|
|
__ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
|
|
__ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
|
|
};
|
|
|
|
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
|
|
|
static void
|
|
setScalar(__GLXconfig *config, unsigned int attrib, unsigned int value)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(attribMap); i++)
|
|
if (attribMap[i].attrib == attrib) {
|
|
*(unsigned int *) ((char *) config + attribMap[i].offset) = value;
|
|
return;
|
|
}
|
|
}
|
|
|
|
static __GLXconfig *
|
|
createModeFromConfig(const __DRIcoreExtension *core,
|
|
const __DRIconfig *driConfig,
|
|
unsigned int visualType)
|
|
{
|
|
__GLXDRIconfig *config;
|
|
unsigned int attrib, value;
|
|
int i;
|
|
|
|
config = xalloc(sizeof *config);
|
|
|
|
config->driConfig = driConfig;
|
|
|
|
i = 0;
|
|
while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
|
|
switch (attrib) {
|
|
case __DRI_ATTRIB_RENDER_TYPE:
|
|
if (value & __DRI_ATTRIB_RGBA_BIT) {
|
|
config->config.renderType |= GLX_RGBA_BIT;
|
|
config->config.rgbMode = GL_TRUE;
|
|
} else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
|
|
config->config.renderType |= GLX_COLOR_INDEX_BIT;
|
|
config->config.rgbMode = GL_FALSE;
|
|
} else {
|
|
config->config.renderType = 0;
|
|
config->config.rgbMode = GL_FALSE;
|
|
}
|
|
break;
|
|
case __DRI_ATTRIB_CONFIG_CAVEAT:
|
|
if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
|
|
config->config.visualRating = GLX_NON_CONFORMANT_CONFIG;
|
|
else if (value & __DRI_ATTRIB_SLOW_BIT)
|
|
config->config.visualRating = GLX_SLOW_CONFIG;
|
|
else
|
|
config->config.visualRating = GLX_NONE;
|
|
break;
|
|
case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
|
|
config->config.bindToTextureTargets = 0;
|
|
if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
|
|
config->config.bindToTextureTargets |= GLX_TEXTURE_1D_BIT_EXT;
|
|
if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
|
|
config->config.bindToTextureTargets |= GLX_TEXTURE_2D_BIT_EXT;
|
|
if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
|
|
config->config.bindToTextureTargets |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
|
|
break;
|
|
default:
|
|
setScalar(&config->config, attrib, value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
config->config.next = NULL;
|
|
config->config.xRenderable = GL_TRUE;
|
|
config->config.visualType = visualType;
|
|
config->config.drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
|
|
|
|
return &config->config;
|
|
}
|
|
|
|
__GLXconfig *
|
|
glxConvertConfigs(const __DRIcoreExtension *core, const __DRIconfig **configs);
|
|
|
|
__GLXconfig *
|
|
glxConvertConfigs(const __DRIcoreExtension *core, const __DRIconfig **configs)
|
|
{
|
|
__GLXconfig head, *tail;
|
|
int i;
|
|
|
|
tail = &head;
|
|
head.next = NULL;
|
|
|
|
for (i = 0; configs[i]; i++) {
|
|
tail->next = createModeFromConfig(core,
|
|
configs[i], GLX_TRUE_COLOR);
|
|
if (tail->next == NULL)
|
|
break;
|
|
|
|
tail = tail->next;
|
|
}
|
|
|
|
for (i = 0; configs[i]; i++) {
|
|
tail->next = createModeFromConfig(core,
|
|
configs[i], GLX_DIRECT_COLOR);
|
|
if (tail->next == NULL)
|
|
break;
|
|
|
|
tail = tail->next;
|
|
}
|
|
|
|
return head.next;
|
|
}
|
|
|
|
static __GLXscreen *
|
|
__glXDRIscreenProbe(ScreenPtr pScreen)
|
|
{
|
|
const char *driverName;
|
|
__GLXDRIscreen *screen;
|
|
char filename[128];
|
|
size_t buffer_size;
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
unsigned int sareaHandle;
|
|
const __DRIextension **extensions;
|
|
const __DRIconfig **driConfigs;
|
|
int i;
|
|
|
|
screen = xalloc(sizeof *screen);
|
|
if (screen == NULL)
|
|
return NULL;
|
|
memset(screen, 0, sizeof *screen);
|
|
|
|
if (!xf86LoaderCheckSymbol("DRI2Connect") ||
|
|
!DRI2Connect(pScreen, &screen->fd, &driverName, &sareaHandle)) {
|
|
LogMessage(X_INFO,
|
|
"AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
|
|
return NULL;
|
|
}
|
|
|
|
screen->base.destroy = __glXDRIscreenDestroy;
|
|
screen->base.createContext = __glXDRIscreenCreateContext;
|
|
screen->base.createDrawable = __glXDRIscreenCreateDrawable;
|
|
screen->base.swapInterval = __glXDRIdrawableSwapInterval;
|
|
screen->base.pScreen = pScreen;
|
|
|
|
__glXInitExtensionEnableBits(screen->glx_enable_bits);
|
|
|
|
snprintf(filename, sizeof filename,
|
|
"%s/%s_dri.so", dri_driver_path, driverName);
|
|
|
|
screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
|
|
if (screen->driver == NULL) {
|
|
LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
|
|
filename, dlerror());
|
|
goto handle_error;
|
|
}
|
|
|
|
extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS);
|
|
if (extensions == NULL) {
|
|
LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
|
|
driverName, dlerror());
|
|
goto handle_error;
|
|
}
|
|
|
|
for (i = 0; extensions[i]; i++) {
|
|
if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
|
|
extensions[i]->version >= __DRI_CORE_VERSION) {
|
|
screen->core = (const __DRIcoreExtension *) extensions[i];
|
|
}
|
|
}
|
|
|
|
if (screen->core == NULL) {
|
|
LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
|
|
driverName);
|
|
goto handle_error;
|
|
}
|
|
|
|
screen->driScreen =
|
|
(*screen->core->createNewScreen)(pScreen->myNum,
|
|
screen->fd,
|
|
sareaHandle,
|
|
loader_extensions,
|
|
&driConfigs,
|
|
screen);
|
|
|
|
if (screen->driScreen == NULL) {
|
|
LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed");
|
|
goto handle_error;
|
|
}
|
|
|
|
initializeExtensions(screen);
|
|
|
|
screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs);
|
|
|
|
__glXScreenInit(&screen->base, pScreen);
|
|
|
|
buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
|
|
if (buffer_size > 0) {
|
|
if (screen->base.GLXextensions != NULL) {
|
|
xfree(screen->base.GLXextensions);
|
|
}
|
|
|
|
screen->base.GLXextensions = xnfalloc(buffer_size);
|
|
(void) __glXGetExtensionString(screen->glx_enable_bits,
|
|
screen->base.GLXextensions);
|
|
}
|
|
|
|
screen->enterVT = pScrn->EnterVT;
|
|
pScrn->EnterVT = glxDRIEnterVT;
|
|
screen->leaveVT = pScrn->LeaveVT;
|
|
pScrn->LeaveVT = glxDRILeaveVT;
|
|
|
|
LogMessage(X_INFO,
|
|
"AIGLX: Loaded and initialized %s\n", filename);
|
|
|
|
return &screen->base;
|
|
|
|
handle_error:
|
|
if (screen->driver)
|
|
dlclose(screen->driver);
|
|
|
|
xfree(screen);
|
|
|
|
LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
__GLXprovider __glXDRI2Provider = {
|
|
__glXDRIscreenProbe,
|
|
"DRI2",
|
|
NULL
|
|
};
|