1169 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1169 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2006 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>
 | 
						|
#include <damage.h>
 | 
						|
 | 
						|
#define _XF86DRI_SERVER_
 | 
						|
#include <drm_sarea.h>
 | 
						|
#include <xf86drm.h>
 | 
						|
#include <X11/dri/xf86driproto.h>
 | 
						|
#include <xf86str.h>
 | 
						|
#include <xf86.h>
 | 
						|
#include <dri.h>
 | 
						|
 | 
						|
#include "servermd.h"
 | 
						|
 | 
						|
#define DRI_NEW_INTERFACE_ONLY
 | 
						|
#include "glxserver.h"
 | 
						|
#include "glxutil.h"
 | 
						|
#include "glxdricommon.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;
 | 
						|
 | 
						|
struct __GLXDRIscreen {
 | 
						|
    __GLXscreen		 base;
 | 
						|
    __DRIscreen		*driScreen;
 | 
						|
    void		*driver;
 | 
						|
 | 
						|
    xf86EnterVTProc	*enterVT;
 | 
						|
    xf86LeaveVTProc	*leaveVT;
 | 
						|
 | 
						|
    const __DRIcoreExtension *core;
 | 
						|
    const __DRIlegacyExtension *legacy;
 | 
						|
    const __DRIcopySubBufferExtension *copySubBuffer;
 | 
						|
    const __DRIswapControlExtension *swapControl;
 | 
						|
 | 
						|
#ifdef __DRI_TEX_OFFSET
 | 
						|
    const __DRItexOffsetExtension *texOffset;
 | 
						|
    DRITexOffsetStartProcPtr texOffsetStart;
 | 
						|
    DRITexOffsetFinishProcPtr texOffsetFinish;
 | 
						|
    __GLXDRIdrawable *texOffsetOverride[16];
 | 
						|
    GLuint lastTexOffsetOverride;
 | 
						|
#endif
 | 
						|
 | 
						|
    unsigned char glx_enable_bits[__GLX_EXT_BYTES];
 | 
						|
};
 | 
						|
 | 
						|
struct __GLXDRIcontext {
 | 
						|
    __GLXcontext base;
 | 
						|
    __DRIcontext *driContext;
 | 
						|
    XID hwContextID;
 | 
						|
};
 | 
						|
 | 
						|
struct __GLXDRIdrawable {
 | 
						|
    __GLXdrawable base;
 | 
						|
    __DRIdrawable *driDrawable;
 | 
						|
 | 
						|
    /* Pulled in from old __GLXpixmap */
 | 
						|
#ifdef __DRI_TEX_OFFSET
 | 
						|
    GLint texname;
 | 
						|
    __GLXDRIcontext *ctx;
 | 
						|
    unsigned long long offset;
 | 
						|
    DamagePtr pDamage;
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIleaveServer(GLboolean rendering)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; rendering && i < screenInfo.numScreens; i++) {
 | 
						|
	__GLXDRIscreen * const screen =
 | 
						|
	    (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
 | 
						|
	GLuint lastOverride = screen->lastTexOffsetOverride;
 | 
						|
 | 
						|
	if (lastOverride) {
 | 
						|
	    __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
 | 
						|
	    int j;
 | 
						|
 | 
						|
	    for (j = 0; j < lastOverride; j++) {
 | 
						|
		__GLXDRIdrawable *pGlxPix = texOffsetOverride[j];
 | 
						|
 | 
						|
		if (pGlxPix && pGlxPix->texname) {
 | 
						|
		    pGlxPix->offset =
 | 
						|
			screen->texOffsetStart((PixmapPtr)pGlxPix->base.pDraw);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    DRIBlockHandler(NULL, NULL, NULL);
 | 
						|
 | 
						|
    for (i = 0; rendering && i < screenInfo.numScreens; i++) {
 | 
						|
	__GLXDRIscreen * const screen =
 | 
						|
	    (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
 | 
						|
	GLuint lastOverride = screen->lastTexOffsetOverride;
 | 
						|
 | 
						|
	if (lastOverride) {
 | 
						|
	    __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
 | 
						|
	    int j;
 | 
						|
 | 
						|
	    for (j = 0; j < lastOverride; j++) {
 | 
						|
		__GLXDRIdrawable *pGlxPix = texOffsetOverride[j];
 | 
						|
 | 
						|
		if (pGlxPix && pGlxPix->texname) {
 | 
						|
		    screen->texOffset->setTexOffset(pGlxPix->ctx->driContext,
 | 
						|
						    pGlxPix->texname,
 | 
						|
						    pGlxPix->offset,
 | 
						|
						    pGlxPix->base.pDraw->depth,
 | 
						|
						    ((PixmapPtr)pGlxPix->base.pDraw)->devKind);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
    
 | 
						|
static void
 | 
						|
__glXDRIenterServer(GLboolean rendering)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; rendering && i < screenInfo.numScreens; i++) {
 | 
						|
	__GLXDRIscreen * const screen = (__GLXDRIscreen *)
 | 
						|
	    glxGetScreen(screenInfo.screens[i]);
 | 
						|
 | 
						|
	if (screen->lastTexOffsetOverride) {
 | 
						|
	    CALL_Flush(GET_DISPATCH(), ());
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    DRIWakeupHandler(NULL, 0, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIdoReleaseTexImage(__GLXDRIscreen *screen, __GLXDRIdrawable *drawable)
 | 
						|
{
 | 
						|
    GLuint lastOverride = screen->lastTexOffsetOverride;
 | 
						|
 | 
						|
    if (lastOverride) {
 | 
						|
	__GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0; i < lastOverride; i++) {
 | 
						|
	    if (texOffsetOverride[i] == drawable) {
 | 
						|
		if (screen->texOffsetFinish)
 | 
						|
		    screen->texOffsetFinish((PixmapPtr)drawable->base.pDraw);
 | 
						|
 | 
						|
		texOffsetOverride[i] = NULL;
 | 
						|
 | 
						|
		if (i + 1 == lastOverride) {
 | 
						|
		    lastOverride = 0;
 | 
						|
 | 
						|
		    while (i--) {
 | 
						|
			if (texOffsetOverride[i]) {
 | 
						|
			    lastOverride = i + 1;
 | 
						|
			    break;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
 | 
						|
		    screen->lastTexOffsetOverride = lastOverride;
 | 
						|
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIdrawableDestroy(__GLXdrawable *drawable)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
 | 
						|
    __GLXDRIscreen *screen;
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < screenInfo.numScreens; i++) {
 | 
						|
	screen = (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
 | 
						|
	__glXDRIdoReleaseTexImage(screen, private);
 | 
						|
    }
 | 
						|
 | 
						|
    /* 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) {
 | 
						|
	screen = (__GLXDRIscreen *) glxGetScreen(drawable->pDraw->pScreen);
 | 
						|
	(*screen->core->destroyDrawable)(private->driDrawable);
 | 
						|
 | 
						|
	__glXenterServer(GL_FALSE);
 | 
						|
	DRIDestroyDrawable(drawable->pDraw->pScreen,
 | 
						|
			   serverClient, drawable->pDraw);
 | 
						|
	__glXleaveServer(GL_FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    __glXDrawableRelease(drawable);
 | 
						|
 | 
						|
    free(private);
 | 
						|
}
 | 
						|
 | 
						|
static GLboolean
 | 
						|
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
 | 
						|
    __GLXDRIscreen *screen =
 | 
						|
	(__GLXDRIscreen *) glxGetScreen(basePrivate->pDraw->pScreen);
 | 
						|
 | 
						|
    (*screen->core->swapBuffers)(private->driDrawable);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
__glXDRIdrawableSwapInterval(__GLXdrawable *baseDrawable, int interval)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseDrawable;
 | 
						|
    __GLXDRIscreen *screen =
 | 
						|
	(__GLXDRIscreen *) glxGetScreen(baseDrawable->pDraw->pScreen);
 | 
						|
 | 
						|
    if (screen->swapControl)
 | 
						|
	screen->swapControl->setSwapInterval(draw->driDrawable, interval);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
 | 
						|
			       int x, int y, int w, int h)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *)
 | 
						|
	glxGetScreen(basePrivate->pDraw->pScreen);
 | 
						|
 | 
						|
    if (screen->copySubBuffer)
 | 
						|
	screen->copySubBuffer->copySubBuffer(private->driDrawable, x, y, w, h);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIcontextDestroy(__GLXcontext *baseContext)
 | 
						|
{
 | 
						|
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
 | 
						|
    Bool retval;
 | 
						|
 | 
						|
    screen->core->destroyContext(context->driContext);
 | 
						|
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
    retval = DRIDestroyContext(baseContext->pGlxScreen->pScreen,
 | 
						|
			       context->hwContextID);
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
    __glXContextDestroy(&context->base);
 | 
						|
    free(context);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
 | 
						|
{
 | 
						|
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
 | 
						|
    __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
 | 
						|
    __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
 | 
						|
 | 
						|
    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 void
 | 
						|
glxFillAlphaChannel (CARD32 *pixels, CARD32 rowstride, int width, int height)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    CARD32 *p, *end;
 | 
						|
 | 
						|
    rowstride /= 4;
 | 
						|
    
 | 
						|
    for (i = 0; i < height; i++)
 | 
						|
    {
 | 
						|
	p = pixels;
 | 
						|
	end = p + width;
 | 
						|
	while (p < end)
 | 
						|
	  *p++ |= 0xFF000000;
 | 
						|
	pixels += rowstride;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
testTexOffset(__GLXDRIscreen * const screen, PixmapPtr pPixmap)
 | 
						|
{
 | 
						|
    Bool ret;
 | 
						|
 | 
						|
    if (!screen->texOffsetStart || !screen->texOffset)
 | 
						|
	return FALSE;
 | 
						|
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
    ret = screen->texOffsetStart(pPixmap) != ~0ULL;
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * (sticking this here for lack of a better place)
 | 
						|
 * Known issues with the GLX_EXT_texture_from_pixmap implementation:
 | 
						|
 * - In general we ignore the fbconfig, lots of examples follow
 | 
						|
 * - No fbconfig handling for multiple mipmap levels
 | 
						|
 * - No fbconfig handling for 1D textures
 | 
						|
 * - No fbconfig handling for TEXTURE_TARGET
 | 
						|
 * - No fbconfig exposure of Y inversion state
 | 
						|
 * - No GenerateMipmapEXT support (due to no FBO support)
 | 
						|
 * - No support for anything but 16bpp and 32bpp-sparse pixmaps
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
__glXDRIbindTexImage(__GLXcontext *baseContext,
 | 
						|
		     int buffer,
 | 
						|
		     __GLXdrawable *glxPixmap)
 | 
						|
{
 | 
						|
    RegionPtr	pRegion = NULL;
 | 
						|
    PixmapPtr	pixmap;
 | 
						|
    int		bpp, override = 0, texname;
 | 
						|
    GLenum	format, type;
 | 
						|
    ScreenPtr pScreen = glxPixmap->pDraw->pScreen;
 | 
						|
    __GLXDRIdrawable *driDraw = (__GLXDRIdrawable *) glxPixmap;
 | 
						|
    __GLXDRIscreen * const screen = (__GLXDRIscreen *) glxGetScreen(pScreen);
 | 
						|
 | 
						|
    CALL_GetIntegerv(GET_DISPATCH(), (glxPixmap->target == GL_TEXTURE_2D ?
 | 
						|
				      GL_TEXTURE_BINDING_2D :
 | 
						|
				      GL_TEXTURE_BINDING_RECTANGLE_NV,
 | 
						|
				      &texname));
 | 
						|
 | 
						|
    if (!texname)
 | 
						|
	return __glXError(GLXBadContextState);
 | 
						|
 | 
						|
    pixmap = (PixmapPtr) glxPixmap->pDraw;
 | 
						|
 | 
						|
    if (testTexOffset(screen, pixmap)) {
 | 
						|
	__GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
 | 
						|
	int i, firstEmpty = 16;
 | 
						|
 | 
						|
	for (i = 0; i < 16; i++) {
 | 
						|
	    if (texOffsetOverride[i] == driDraw)
 | 
						|
		goto alreadyin; 
 | 
						|
 | 
						|
	    if (firstEmpty == 16 && !texOffsetOverride[i])
 | 
						|
		firstEmpty = i;
 | 
						|
	}
 | 
						|
 | 
						|
	if (firstEmpty == 16) {
 | 
						|
	    ErrorF("%s: Failed to register texture offset override\n", __func__);
 | 
						|
	    goto nooverride;
 | 
						|
	}
 | 
						|
 | 
						|
	if (firstEmpty >= screen->lastTexOffsetOverride)
 | 
						|
	    screen->lastTexOffsetOverride = firstEmpty + 1;
 | 
						|
 | 
						|
	texOffsetOverride[firstEmpty] = driDraw;
 | 
						|
 | 
						|
alreadyin:
 | 
						|
	override = 1;
 | 
						|
 | 
						|
	driDraw->ctx = (__GLXDRIcontext*)baseContext;
 | 
						|
 | 
						|
	if (texname == driDraw->texname)
 | 
						|
	    return Success;
 | 
						|
 | 
						|
	driDraw->texname = texname;
 | 
						|
 | 
						|
	screen->texOffset->setTexOffset(driDraw->ctx->driContext, texname, 0,
 | 
						|
					pixmap->drawable.depth,
 | 
						|
					pixmap->devKind);
 | 
						|
    }
 | 
						|
nooverride:
 | 
						|
 | 
						|
    if (!driDraw->pDamage) {
 | 
						|
	if (!override) {
 | 
						|
	    driDraw->pDamage = DamageCreate(NULL, NULL, DamageReportNone,
 | 
						|
					    TRUE, pScreen, NULL);
 | 
						|
	    if (!driDraw->pDamage)
 | 
						|
		return BadAlloc;
 | 
						|
 | 
						|
	    DamageRegister ((DrawablePtr) pixmap, driDraw->pDamage);
 | 
						|
	}
 | 
						|
 | 
						|
	pRegion = NULL;
 | 
						|
    } else {
 | 
						|
	pRegion = DamageRegion(driDraw->pDamage);
 | 
						|
	if (RegionNil(pRegion))
 | 
						|
	    return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* XXX 24bpp packed, 8, etc */
 | 
						|
    if (pixmap->drawable.depth >= 24) {
 | 
						|
	bpp = 4;
 | 
						|
	format = GL_BGRA;
 | 
						|
	type =
 | 
						|
#if X_BYTE_ORDER == X_BIG_ENDIAN
 | 
						|
	    !override ? GL_UNSIGNED_INT_8_8_8_8_REV :
 | 
						|
#endif
 | 
						|
	    GL_UNSIGNED_BYTE;
 | 
						|
    } else {
 | 
						|
	bpp = 2;
 | 
						|
	format = GL_RGB;
 | 
						|
	type = GL_UNSIGNED_SHORT_5_6_5;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pRegion == NULL)
 | 
						|
    {
 | 
						|
	void *data = NULL;
 | 
						|
 | 
						|
	if (!override) {
 | 
						|
	    unsigned pitch = PixmapBytePad(pixmap->drawable.width,
 | 
						|
					   pixmap->drawable.depth); 
 | 
						|
 | 
						|
	    data = malloc(pitch * pixmap->drawable.height);
 | 
						|
 | 
						|
	    __glXenterServer(GL_FALSE);
 | 
						|
	    pScreen->GetImage(&pixmap->drawable, 0 /*pixmap->drawable.x*/,
 | 
						|
			      0 /*pixmap->drawable.y*/, pixmap->drawable.width,
 | 
						|
			      pixmap->drawable.height, ZPixmap, ~0, data);
 | 
						|
	    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
	    if (pixmap->drawable.depth == 24)
 | 
						|
		glxFillAlphaChannel(data,
 | 
						|
				    pitch,
 | 
						|
				    pixmap->drawable.width,
 | 
						|
				    pixmap->drawable.height);
 | 
						|
 | 
						|
	    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
 | 
						|
					       pitch / bpp) );
 | 
						|
	    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
 | 
						|
	    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
 | 
						|
	}
 | 
						|
 | 
						|
	CALL_TexImage2D( GET_DISPATCH(),
 | 
						|
			 (glxPixmap->target,
 | 
						|
			  0,
 | 
						|
			  bpp == 4 ? 4 : 3,
 | 
						|
			  pixmap->drawable.width,
 | 
						|
			  pixmap->drawable.height,
 | 
						|
			  0,
 | 
						|
			  format,
 | 
						|
			  type,
 | 
						|
			  data) );
 | 
						|
 | 
						|
	free(data);
 | 
						|
    } else if (!override) {
 | 
						|
        int i, numRects;
 | 
						|
	BoxPtr p;
 | 
						|
 | 
						|
	numRects = RegionNumRects (pRegion);
 | 
						|
	p = RegionRects (pRegion);
 | 
						|
 | 
						|
	CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
 | 
						|
	CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
 | 
						|
 | 
						|
	for (i = 0; i < numRects; i++)
 | 
						|
	{
 | 
						|
	    unsigned pitch = PixmapBytePad(p[i].x2 - p[i].x1,
 | 
						|
					   pixmap->drawable.depth);
 | 
						|
	    void *data = malloc(pitch * (p[i].y2 - p[i].y1));
 | 
						|
 | 
						|
	    __glXenterServer(GL_FALSE);
 | 
						|
	    pScreen->GetImage(&pixmap->drawable, /*pixmap->drawable.x +*/ p[i].x1,
 | 
						|
			      /*pixmap->drawable.y*/ + p[i].y1, p[i].x2 - p[i].x1,
 | 
						|
			      p[i].y2 - p[i].y1, ZPixmap, ~0, data);
 | 
						|
	    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
	    if (pixmap->drawable.depth == 24)
 | 
						|
		glxFillAlphaChannel(data,
 | 
						|
				    pitch,
 | 
						|
				    p[i].x2 - p[i].x1,
 | 
						|
				    p[i].y2 - p[i].y1);
 | 
						|
 | 
						|
	    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
 | 
						|
					       pitch / bpp) );
 | 
						|
 | 
						|
	    CALL_TexSubImage2D( GET_DISPATCH(),
 | 
						|
				(glxPixmap->target,
 | 
						|
				 0,
 | 
						|
				 p[i].x1, p[i].y1,
 | 
						|
				 p[i].x2 - p[i].x1, p[i].y2 - p[i].y1,
 | 
						|
				 format,
 | 
						|
				 type,
 | 
						|
				 data) );
 | 
						|
 | 
						|
	    free(data);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!override)
 | 
						|
	DamageEmpty(driDraw->pDamage);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
__glXDRIreleaseTexImage(__GLXcontext *baseContext,
 | 
						|
			int buffer,
 | 
						|
			__GLXdrawable *pixmap)
 | 
						|
{
 | 
						|
    __GLXDRIscreen *screen =
 | 
						|
	(__GLXDRIscreen *) glxGetScreen(pixmap->pDraw->pScreen);
 | 
						|
    __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) pixmap;
 | 
						|
 | 
						|
    __glXDRIdoReleaseTexImage(screen, drawable);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
 | 
						|
    __glXDRIbindTexImage,
 | 
						|
    __glXDRIreleaseTexImage
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
__glXDRIscreenDestroy(__GLXscreen *baseScreen)
 | 
						|
{
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
 | 
						|
 | 
						|
    screen->core->destroyScreen(screen->driScreen);
 | 
						|
 | 
						|
    dlclose(screen->driver);
 | 
						|
 | 
						|
    __glXScreenDestroy(baseScreen);
 | 
						|
 | 
						|
    free(screen);
 | 
						|
}
 | 
						|
 | 
						|
static __GLXcontext *
 | 
						|
__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
 | 
						|
			    __GLXconfig *glxConfig,
 | 
						|
			    __GLXcontext *baseShareContext)
 | 
						|
{
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
 | 
						|
    __GLXDRIcontext *context, *shareContext;
 | 
						|
    __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
 | 
						|
    VisualPtr visual;
 | 
						|
    int i;
 | 
						|
    GLboolean retval;
 | 
						|
    __DRIcontext *driShare;
 | 
						|
    drm_context_t hwContext;
 | 
						|
    ScreenPtr pScreen = baseScreen->pScreen;
 | 
						|
 | 
						|
    shareContext = (__GLXDRIcontext *) baseShareContext;
 | 
						|
    if (shareContext)
 | 
						|
	driShare = shareContext->driContext;
 | 
						|
    else
 | 
						|
	driShare = NULL;
 | 
						|
 | 
						|
    if (baseShareContext && baseShareContext->isDirect)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    context = calloc(1, sizeof *context);
 | 
						|
    if (context == NULL)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    context->base.destroy           = __glXDRIcontextDestroy;
 | 
						|
    context->base.makeCurrent       = __glXDRIcontextMakeCurrent;
 | 
						|
    context->base.loseCurrent       = __glXDRIcontextLoseCurrent;
 | 
						|
    context->base.copy              = __glXDRIcontextCopy;
 | 
						|
 | 
						|
    context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
 | 
						|
    /* Find the requested X visual */
 | 
						|
    visual = pScreen->visuals;
 | 
						|
    for (i = 0; i < pScreen->numVisuals; i++, visual++)
 | 
						|
	if (visual->vid == glxConfig->visualID)
 | 
						|
	    break;
 | 
						|
    if (i == pScreen->numVisuals)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    context->hwContextID = FakeClientID(0);
 | 
						|
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
    retval = DRICreateContext(baseScreen->pScreen, visual,
 | 
						|
			      context->hwContextID, &hwContext);
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
    if (!retval)
 | 
						|
    	return NULL;
 | 
						|
 | 
						|
    context->driContext =
 | 
						|
	screen->legacy->createNewContext(screen->driScreen,
 | 
						|
					 config->driConfig,
 | 
						|
					 0, /* render type */
 | 
						|
					 driShare,
 | 
						|
					 hwContext,
 | 
						|
					 context);
 | 
						|
 | 
						|
    if (context->driContext == NULL) {
 | 
						|
    	__glXenterServer(GL_FALSE);
 | 
						|
	retval = DRIDestroyContext(baseScreen->pScreen, context->hwContextID);
 | 
						|
    	__glXleaveServer(GL_FALSE);
 | 
						|
	free(context);
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return &context->base;
 | 
						|
}
 | 
						|
 | 
						|
static __GLXdrawable *
 | 
						|
__glXDRIscreenCreateDrawable(ClientPtr client,
 | 
						|
			     __GLXscreen *screen,
 | 
						|
			     DrawablePtr pDraw,
 | 
						|
			     XID drawId,
 | 
						|
			     int type,
 | 
						|
			     XID glxDrawId,
 | 
						|
			     __GLXconfig *glxConfig)
 | 
						|
{
 | 
						|
    __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
 | 
						|
    __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
 | 
						|
    __GLXDRIdrawable *private;
 | 
						|
    GLboolean retval;
 | 
						|
    drm_drawable_t hwDrawable;
 | 
						|
 | 
						|
    private = calloc(1, sizeof *private);
 | 
						|
    if (private == NULL)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    if (!__glXDrawableInit(&private->base, screen,
 | 
						|
			   pDraw, type, glxDrawId, glxConfig)) {
 | 
						|
        free(private);
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    private->base.destroy       = __glXDRIdrawableDestroy;
 | 
						|
    private->base.swapBuffers   = __glXDRIdrawableSwapBuffers;
 | 
						|
    private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
 | 
						|
    private->base.waitX		= NULL;
 | 
						|
    private->base.waitGL	= NULL;
 | 
						|
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
    retval = DRICreateDrawable(screen->pScreen, serverClient,
 | 
						|
			       pDraw, &hwDrawable);
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
    if (!retval) {
 | 
						|
        free(private);
 | 
						|
    	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* The last argument is 'attrs', which is used with pbuffers which
 | 
						|
     * we currently don't support. */
 | 
						|
 | 
						|
    private->driDrawable =
 | 
						|
	(driScreen->legacy->createNewDrawable)(driScreen->driScreen,
 | 
						|
					       config->driConfig,
 | 
						|
					       hwDrawable, 0, NULL, private);
 | 
						|
 | 
						|
    if (private->driDrawable == NULL) {
 | 
						|
	__glXenterServer(GL_FALSE);
 | 
						|
	DRIDestroyDrawable(screen->pScreen, serverClient, pDraw);
 | 
						|
	__glXleaveServer(GL_FALSE);
 | 
						|
	free(private);
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return &private->base;
 | 
						|
}
 | 
						|
 | 
						|
static GLboolean
 | 
						|
getDrawableInfo(__DRIdrawable *driDrawable,
 | 
						|
		unsigned int *index, unsigned int *stamp,
 | 
						|
		int *x, int *y, int *width, int *height,
 | 
						|
		int *numClipRects, drm_clip_rect_t **ppClipRects,
 | 
						|
		int *backX, int *backY,
 | 
						|
		int *numBackClipRects, drm_clip_rect_t **ppBackClipRects,
 | 
						|
		void *data)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *drawable = data;
 | 
						|
    ScreenPtr pScreen;
 | 
						|
    drm_clip_rect_t *pClipRects, *pBackClipRects;
 | 
						|
    GLboolean retval;
 | 
						|
    size_t size;
 | 
						|
 | 
						|
    /* If the X window has been destroyed, give up here. */
 | 
						|
    if (drawable->base.pDraw == NULL)
 | 
						|
	return GL_FALSE;
 | 
						|
 | 
						|
    pScreen = drawable->base.pDraw->pScreen;
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
    retval = DRIGetDrawableInfo(pScreen, drawable->base.pDraw, index, stamp,
 | 
						|
				x, y, width, height,
 | 
						|
				numClipRects, &pClipRects,
 | 
						|
				backX, backY,
 | 
						|
				numBackClipRects, &pBackClipRects);
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
 | 
						|
    if (retval && *numClipRects > 0) {
 | 
						|
	size = sizeof (drm_clip_rect_t) * *numClipRects;
 | 
						|
	*ppClipRects = malloc(size);
 | 
						|
 | 
						|
	/* Clip cliprects to screen dimensions (redirected windows) */
 | 
						|
	if (*ppClipRects != NULL) {
 | 
						|
	    int i, j;
 | 
						|
 | 
						|
	    for (i = 0, j = 0; i < *numClipRects; i++) {
 | 
						|
	        (*ppClipRects)[j].x1 = max(pClipRects[i].x1, 0);
 | 
						|
		(*ppClipRects)[j].y1 = max(pClipRects[i].y1, 0);
 | 
						|
		(*ppClipRects)[j].x2 = min(pClipRects[i].x2, pScreen->width);
 | 
						|
		(*ppClipRects)[j].y2 = min(pClipRects[i].y2, pScreen->height);
 | 
						|
 | 
						|
		if ((*ppClipRects)[j].x1 < (*ppClipRects)[j].x2 &&
 | 
						|
		    (*ppClipRects)[j].y1 < (*ppClipRects)[j].y2) {
 | 
						|
		    j++;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (*numClipRects != j) {
 | 
						|
		*numClipRects = j;
 | 
						|
		*ppClipRects = realloc(*ppClipRects,
 | 
						|
					 sizeof (drm_clip_rect_t) *
 | 
						|
					 *numClipRects);
 | 
						|
	    }
 | 
						|
	} else
 | 
						|
	    *numClipRects = 0;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      *ppClipRects = NULL;
 | 
						|
      *numClipRects = 0;
 | 
						|
    }
 | 
						|
      
 | 
						|
    if (retval && *numBackClipRects > 0) {
 | 
						|
	size = sizeof (drm_clip_rect_t) * *numBackClipRects;
 | 
						|
	*ppBackClipRects = malloc(size);
 | 
						|
	if (*ppBackClipRects != NULL)
 | 
						|
	    memcpy (*ppBackClipRects, pBackClipRects, size);
 | 
						|
	else
 | 
						|
	    *numBackClipRects = 0;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      *ppBackClipRects = NULL;
 | 
						|
      *numBackClipRects = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
static void __glXReportDamage(__DRIdrawable *driDraw,
 | 
						|
			      int x, int y,
 | 
						|
			      drm_clip_rect_t *rects, int num_rects,
 | 
						|
			      GLboolean front_buffer,
 | 
						|
			      void *data)
 | 
						|
{
 | 
						|
    __GLXDRIdrawable *drawable = data;
 | 
						|
    DrawablePtr pDraw = drawable->base.pDraw;
 | 
						|
    RegionRec region;
 | 
						|
 | 
						|
    __glXenterServer(GL_FALSE);
 | 
						|
 | 
						|
    if (RegionInitBoxes(®ion, (BoxPtr) rects, num_rects)) {
 | 
						|
	RegionTranslate(®ion, pDraw->x, pDraw->y);
 | 
						|
	DamageDamageRegion(pDraw, ®ion);
 | 
						|
	RegionUninit(®ion);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	while (num_rects--) {
 | 
						|
	    RegionInit (®ion, (BoxPtr) rects++, 1);
 | 
						|
	    RegionTranslate(®ion, pDraw->x, pDraw->y);
 | 
						|
	    DamageDamageRegion(pDraw, ®ion);
 | 
						|
	    RegionUninit(®ion);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    __glXleaveServer(GL_FALSE);
 | 
						|
}
 | 
						|
 | 
						|
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
 | 
						|
    { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
 | 
						|
    getDrawableInfo
 | 
						|
};
 | 
						|
 | 
						|
static const __DRIdamageExtension damageExtension = {
 | 
						|
    { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
 | 
						|
    __glXReportDamage,
 | 
						|
};
 | 
						|
 | 
						|
static const __DRIextension *loader_extensions[] = {
 | 
						|
    &systemTimeExtension.base,
 | 
						|
    &getDrawableInfoExtension.base,
 | 
						|
    &damageExtension.base,
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static Bool
 | 
						|
glxDRIEnterVT (int index, int flags)
 | 
						|
{
 | 
						|
    ScrnInfoPtr scrn = xf86Screens[index];
 | 
						|
    Bool	ret;
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *) 
 | 
						|
	glxGetScreen(screenInfo.screens[index]);
 | 
						|
 | 
						|
    LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
 | 
						|
 | 
						|
    scrn->EnterVT = screen->enterVT;
 | 
						|
 | 
						|
    ret = scrn->EnterVT (index, flags);
 | 
						|
 | 
						|
    screen->enterVT = scrn->EnterVT;
 | 
						|
    scrn->EnterVT = glxDRIEnterVT;
 | 
						|
 | 
						|
    if (!ret)
 | 
						|
	return FALSE;
 | 
						|
    
 | 
						|
    glxResumeClients();
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
glxDRILeaveVT (int index, int flags)
 | 
						|
{
 | 
						|
    ScrnInfoPtr scrn = xf86Screens[index];
 | 
						|
    __GLXDRIscreen *screen = (__GLXDRIscreen *)
 | 
						|
	glxGetScreen(screenInfo.screens[index]);
 | 
						|
 | 
						|
    LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
 | 
						|
 | 
						|
    glxSuspendClients();
 | 
						|
 | 
						|
    scrn->LeaveVT = screen->leaveVT;
 | 
						|
    (*screen->leaveVT) (index, flags);
 | 
						|
    screen->leaveVT = scrn->LeaveVT;
 | 
						|
    scrn->LeaveVT = glxDRILeaveVT;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
initializeExtensions(__GLXDRIscreen *screen)
 | 
						|
{
 | 
						|
    const __DRIextension **extensions;
 | 
						|
    int i;
 | 
						|
 | 
						|
    extensions = screen->core->getExtensions(screen->driScreen);
 | 
						|
 | 
						|
    for (i = 0; extensions[i]; i++) {
 | 
						|
#ifdef __DRI_READ_DRAWABLE
 | 
						|
	if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
 | 
						|
	    __glXEnableExtension(screen->glx_enable_bits,
 | 
						|
				 "GLX_SGI_make_current_read");
 | 
						|
	    
 | 
						|
	    LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef __DRI_COPY_SUB_BUFFER
 | 
						|
	if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
 | 
						|
	    screen->copySubBuffer = (__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 = (__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_OFFSET
 | 
						|
	if (strcmp(extensions[i]->name, __DRI_TEX_OFFSET) == 0) {
 | 
						|
	    screen->texOffset = (__DRItexOffsetExtension *) extensions[i];
 | 
						|
	    LogMessage(X_INFO, "AIGLX: enabled GLX_texture_from_pixmap with driver support\n");
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	/* Ignore unknown extensions */
 | 
						|
    }
 | 
						|
}
 | 
						|
    
 | 
						|
static __GLXscreen *
 | 
						|
__glXDRIscreenProbe(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    drm_handle_t hSAREA;
 | 
						|
    drmAddress pSAREA = NULL;
 | 
						|
    char *BusID;
 | 
						|
    __DRIversion   ddx_version;
 | 
						|
    __DRIversion   dri_version;
 | 
						|
    __DRIversion   drm_version;
 | 
						|
    __DRIframebuffer  framebuffer;
 | 
						|
    int   fd = -1;
 | 
						|
    int   status;
 | 
						|
    drm_magic_t magic;
 | 
						|
    drmVersionPtr version;
 | 
						|
    int newlyopened;
 | 
						|
    char *driverName;
 | 
						|
    drm_handle_t  hFB;
 | 
						|
    int        junk;
 | 
						|
    __GLXDRIscreen *screen;
 | 
						|
    Bool isCapable;
 | 
						|
    size_t buffer_size;
 | 
						|
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 | 
						|
    const __DRIconfig **driConfigs;
 | 
						|
 | 
						|
    if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable") ||
 | 
						|
	!DRIQueryDirectRenderingCapable(pScreen, &isCapable) ||
 | 
						|
	!isCapable) {
 | 
						|
	LogMessage(X_INFO,
 | 
						|
		   "AIGLX: Screen %d is not DRI capable\n", pScreen->myNum);
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    screen = calloc(1, sizeof *screen);
 | 
						|
    if (screen == NULL)
 | 
						|
      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);
 | 
						|
 | 
						|
    /* DRI protocol version. */
 | 
						|
    dri_version.major = XF86DRI_MAJOR_VERSION;
 | 
						|
    dri_version.minor = XF86DRI_MINOR_VERSION;
 | 
						|
    dri_version.patch = XF86DRI_PATCH_VERSION;
 | 
						|
 | 
						|
    if (!DRIOpenConnection(pScreen, &hSAREA, &BusID)) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: DRIOpenConnection failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    fd = drmOpenOnce(NULL, BusID, &newlyopened);
 | 
						|
 | 
						|
    if (fd < 0) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: drmOpenOnce failed (%s)\n",
 | 
						|
		   strerror(-fd));
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    if (drmGetMagic(fd, &magic)) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: drmGetMagic failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    version = drmGetVersion(fd);
 | 
						|
    if (version) {
 | 
						|
	drm_version.major = version->version_major;
 | 
						|
	drm_version.minor = version->version_minor;
 | 
						|
	drm_version.patch = version->version_patchlevel;
 | 
						|
	drmFreeVersion(version);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	drm_version.major = -1;
 | 
						|
	drm_version.minor = -1;
 | 
						|
	drm_version.patch = -1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (newlyopened && !DRIAuthConnection(pScreen, magic)) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: DRIAuthConnection failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Get device name (like "tdfx") and the ddx version numbers.
 | 
						|
     * We'll check the version in each DRI driver's "createNewScreen"
 | 
						|
     * function. */
 | 
						|
    if (!DRIGetClientDriverName(pScreen,
 | 
						|
				&ddx_version.major,
 | 
						|
				&ddx_version.minor,
 | 
						|
				&ddx_version.patch,
 | 
						|
				&driverName)) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: DRIGetClientDriverName failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    screen->driver = glxProbeDriver(driverName,
 | 
						|
				    (void **)&screen->core,
 | 
						|
				    __DRI_CORE, __DRI_CORE_VERSION,
 | 
						|
				    (void **)&screen->legacy,
 | 
						|
				    __DRI_LEGACY, __DRI_LEGACY_VERSION);
 | 
						|
    if (screen->driver == NULL) {
 | 
						|
        goto handle_error;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Get device-specific info.  pDevPriv will point to a struct
 | 
						|
     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
 | 
						|
     * has information about the screen size, depth, pitch, ancilliary
 | 
						|
     * buffers, DRM mmap handles, etc.
 | 
						|
     */
 | 
						|
    if (!DRIGetDeviceInfo(pScreen, &hFB, &junk,
 | 
						|
			  &framebuffer.size, &framebuffer.stride,
 | 
						|
			  &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: XF86DRIGetDeviceInfo failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    framebuffer.width = pScreen->width;
 | 
						|
    framebuffer.height = pScreen->height;
 | 
						|
 | 
						|
    /* Map the framebuffer region. */
 | 
						|
    status = drmMap(fd, hFB, framebuffer.size, 
 | 
						|
		    (drmAddressPtr)&framebuffer.base);
 | 
						|
    if (status != 0) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: drmMap of framebuffer failed (%s)\n",
 | 
						|
		   strerror(-status));
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Map the SAREA region.  Further mmap regions may be setup in
 | 
						|
     * each DRI driver's "createNewScreen" function.
 | 
						|
     */
 | 
						|
    status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
 | 
						|
    if (status != 0) {
 | 
						|
	LogMessage(X_ERROR, "AIGLX error: drmMap of SAREA failed (%s)\n",
 | 
						|
		   strerror(-status));
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
    
 | 
						|
    screen->driScreen =
 | 
						|
	(*screen->legacy->createNewScreen)(pScreen->myNum,
 | 
						|
					   &ddx_version,
 | 
						|
					   &dri_version,
 | 
						|
					   &drm_version,
 | 
						|
					   &framebuffer,
 | 
						|
					   pSAREA,
 | 
						|
					   fd,
 | 
						|
					   loader_extensions,
 | 
						|
					   &driConfigs,
 | 
						|
					   screen);
 | 
						|
 | 
						|
    if (screen->driScreen == NULL) {
 | 
						|
	LogMessage(X_ERROR,
 | 
						|
		   "AIGLX error: Calling driver entry point failed\n");
 | 
						|
	goto handle_error;
 | 
						|
    }
 | 
						|
 | 
						|
    screen->base.fbconfigs = glxConvertConfigs(screen->core,
 | 
						|
					       driConfigs, GLX_WINDOW_BIT);
 | 
						|
 | 
						|
    initializeExtensions(screen);
 | 
						|
 | 
						|
    DRIGetTexOffsetFuncs(pScreen, &screen->texOffsetStart,
 | 
						|
			 &screen->texOffsetFinish);
 | 
						|
 | 
						|
    __glXScreenInit(&screen->base, pScreen);
 | 
						|
 | 
						|
    /* The first call simply determines the length of the extension string.
 | 
						|
     * This allows us to allocate some memory to hold the extension string,
 | 
						|
     * but it requires that we call __glXGetExtensionString a second time.
 | 
						|
     */
 | 
						|
    buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
 | 
						|
    if (buffer_size > 0) {
 | 
						|
	free(screen->base.GLXextensions);
 | 
						|
 | 
						|
	screen->base.GLXextensions = xnfalloc(buffer_size);
 | 
						|
	(void) __glXGetExtensionString(screen->glx_enable_bits, 
 | 
						|
				       screen->base.GLXextensions);
 | 
						|
    }
 | 
						|
 | 
						|
    __glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer);
 | 
						|
 | 
						|
    screen->enterVT = pScrn->EnterVT;
 | 
						|
    pScrn->EnterVT = glxDRIEnterVT;
 | 
						|
    screen->leaveVT = pScrn->LeaveVT;
 | 
						|
    pScrn->LeaveVT = glxDRILeaveVT;
 | 
						|
 | 
						|
    LogMessage(X_INFO,
 | 
						|
	       "AIGLX: Loaded and initialized %s\n", driverName);
 | 
						|
 | 
						|
    return &screen->base;
 | 
						|
 | 
						|
 handle_error:
 | 
						|
    if (pSAREA != NULL)
 | 
						|
	drmUnmap(pSAREA, SAREA_MAX);
 | 
						|
 | 
						|
    if (framebuffer.base != NULL)
 | 
						|
	drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
 | 
						|
 | 
						|
    if (fd >= 0)
 | 
						|
	drmCloseOnce(fd);
 | 
						|
 | 
						|
    DRICloseConnection(pScreen);
 | 
						|
 | 
						|
    if (screen->driver)
 | 
						|
        dlclose(screen->driver);
 | 
						|
 | 
						|
    free(screen);
 | 
						|
 | 
						|
    LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
_X_EXPORT __GLXprovider __glXDRIProvider = {
 | 
						|
    __glXDRIscreenProbe,
 | 
						|
    "DRI",
 | 
						|
    NULL
 | 
						|
};
 |