Commit 8aacf47e authored by Adam Jackson's avatar Adam Jackson 🎧
Browse files

glx: Remove DRI1 AIGLX (v2)



Mesa doesn't ship DRI1 drivers as of 8.0, which is about 18 months and
three releases ago.  The main reason to have wanted DRI1 AIGLX was to
get a GLX compositor working, but DRI1's (lack of) memory management API
meant that the cost of a GLX compositor was breaking direct GLX apps,
which isn't a great tradeoff.

Of the DRI1 drivers Mesa has dropped, I believe only mga stands to lose
some functionality here, since it and only it has support for
NV_texture_rectangle.  Since that's required for every extant GLX
compositor I know of, I conclude that anybody with a savage, say, would
probably not notice AIGLX going away, since they wouldn't be running a
GLX compositor in the first place.

In the future we'd like to use GL in the server in a more natural way,
as just another EGL client, including in the GLX implementation itself.
Since there's no EGL implemented for DRI1 drivers, this would already
doom AIGLX on DRI1 (short of entirely forking the GLX implementation,
which I'm not enthusiastic about).

v2: Remove DRI1 from AIGLX conditionals in configure.ac [anholt]
Reviewed-by: Emma Anholt's avatarEric Anholt <eric@anholt.net>
Signed-off-by: Adam Jackson's avatarAdam Jackson <ajax@redhat.com>
parent 7f5adf73
......@@ -1080,10 +1080,10 @@ if test "x$GLX" = xno; then
AIGLX=no
fi
if test "x$AIGLX" = xyes -a \( "x$DRI" = xyes -o "x$DRI2" = xyes \); then
if test "x$AIGLX" = xyes -a \( "x$DRI2" = xyes \); then
AC_DEFINE(AIGLX, 1, [Build AIGLX loader])
fi
AM_CONDITIONAL(AIGLX_DRI_LOADER, { test "x$DRI" = xyes || test "x$DRI2" = xyes; } && test "x$AIGLX" = xyes)
AM_CONDITIONAL(AIGLX_DRI_LOADER, { test "x$DRI2" = xyes; } && test "x$AIGLX" = xyes)
if test "x$GLX_USE_TLS" = xyes ; then
GLX_DEFINES="-DGLX_USE_TLS -DPTHREADS"
......
......@@ -47,10 +47,6 @@ glapi_sources = \
libglxdri_la_SOURCES =
if DRI
libglxdri_la_SOURCES += glxdri.c
endif
if DRI2_AIGLX
libglxdri_la_SOURCES += glxdri2.c
endif
......
/*
* 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;
const __DRIconfig **driConfigs;
#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)
{
int i;
__GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
screen->core->destroyScreen(screen->driScreen);
dlclose(screen->driver);
__glXScreenDestroy(baseScreen);
if (screen->driConfigs) {
for (i = 0; screen->driConfigs[i] != NULL; i++)
free((__DRIconfig **) screen->driConfigs[i]);
free(screen->driConfigs);
}
free(screen);
}
static __GLXcontext *
__glXDRIscreenCreateContext(__GLXscreen * baseScreen,
__GLXconfig * glxConfig,
__GLXcontext * baseShareContext,
unsigned num_attribs,
const uint32_t *attribs,
int *error)