mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 13:48:06 +02:00
add missed files for DRI2 merge
This commit is contained in:
parent
1bcb817167
commit
5e9fe62c70
11 changed files with 2866 additions and 0 deletions
134
include/GL/internal/dri_sarea.h
Normal file
134
include/GL/internal/dri_sarea.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2007 Red Hat, Inc
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DRI_SAREA_H
|
||||
#define DRI_SAREA_H
|
||||
|
||||
#include <drm.h>
|
||||
|
||||
/* The DRI2 SAREA holds a list of self-describing blocks. Each block
|
||||
* is 8 byte aligned and has a common 32-bit header word. The upper
|
||||
* 16 bits describe the type of the block and the lower 16 bits the
|
||||
* size. DRI2 only defines a couple of blocks and allows drivers to
|
||||
* define driver specific blocks using type codes from 0x8000 and up.
|
||||
* The type code 0x0000 defines the end of the sarea. */
|
||||
|
||||
#define DRI2_SAREA_BLOCK_HEADER(type, size) (((type) << 16) | (size))
|
||||
#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16)
|
||||
#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff)
|
||||
#define DRI2_SAREA_BLOCK_NEXT(p) \
|
||||
((void *) ((unsigned char *) (p) + \
|
||||
DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p)))
|
||||
|
||||
#define DRI2_SAREA_BLOCK_END 0x0000
|
||||
#define DRI2_SAREA_BLOCK_LOCK 0x0001
|
||||
#define DRI2_SAREA_BLOCK_EVENT_BUFFER 0x0002
|
||||
|
||||
/* Chipset specific blocks start at 0x8000, 0xffff is reserved. */
|
||||
|
||||
typedef struct __DRILock __DRILock;
|
||||
typedef struct __DRIEventBuffer __DRIEventBuffer;
|
||||
typedef struct __DRIDrawableBuffer __DRIDrawableBuffer;
|
||||
typedef struct __DRIDrawableConfigEvent __DRIDrawableConfigEvent;
|
||||
typedef struct __DRIBufferAttachEvent __DRIBufferAttachEvent;
|
||||
|
||||
struct __DRILock {
|
||||
unsigned int block_header;
|
||||
drm_hw_lock_t lock;
|
||||
|
||||
/* We use this with DRM_CAS to allocate lock IDs for the real lock.*/
|
||||
unsigned int next_id;
|
||||
};
|
||||
|
||||
struct __DRIEventBuffer {
|
||||
unsigned int block_header;
|
||||
unsigned int head; /* last valid event */
|
||||
unsigned int prealloc; /* event currently being written */
|
||||
unsigned int size; /* size of data */
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
enum {
|
||||
/* the four standard color buffers */
|
||||
DRI_DRAWABLE_BUFFER_FRONT_LEFT = 0,
|
||||
DRI_DRAWABLE_BUFFER_BACK_LEFT = 1,
|
||||
DRI_DRAWABLE_BUFFER_FRONT_RIGHT = 2,
|
||||
DRI_DRAWABLE_BUFFER_BACK_RIGHT = 3,
|
||||
/* optional aux buffer */
|
||||
DRI_DRAWABLE_BUFFER_AUX0 = 4,
|
||||
DRI_DRAWABLE_BUFFER_AUX1 = 5,
|
||||
DRI_DRAWABLE_BUFFER_AUX2 = 6,
|
||||
DRI_DRAWABLE_BUFFER_AUX3 = 7,
|
||||
DRI_DRAWABLE_BUFFER_DEPTH = 8,
|
||||
DRI_DRAWABLE_BUFFER_STENCIL = 9,
|
||||
DRI_DRAWABLE_BUFFER_ACCUM = 10,
|
||||
/* generic renderbuffers */
|
||||
DRI_DRAWABLE_BUFFER_COLOR0 = 11,
|
||||
DRI_DRAWABLE_BUFFER_COLOR1 = 12,
|
||||
DRI_DRAWABLE_BUFFER_COLOR2 = 13,
|
||||
DRI_DRAWABLE_BUFFER_COLOR3 = 14,
|
||||
DRI_DRAWABLE_BUFFER_COLOR4 = 15,
|
||||
DRI_DRAWABLE_BUFFER_COLOR5 = 16,
|
||||
DRI_DRAWABLE_BUFFER_COLOR6 = 17,
|
||||
DRI_DRAWABLE_BUFFER_COLOR7 = 18,
|
||||
DRI_DRAWABLE_BUFFER_COUNT = 19
|
||||
};
|
||||
|
||||
struct __DRIDrawableBuffer {
|
||||
unsigned int attachment;
|
||||
unsigned int handle;
|
||||
unsigned int pitch;
|
||||
unsigned short cpp;
|
||||
|
||||
/* Upper 8 bits are driver specific, lower 8 bits generic. The
|
||||
* bits can inidicate buffer properties such as tiled, swizzled etc. */
|
||||
unsigned short flags;
|
||||
};
|
||||
|
||||
#define DRI2_EVENT_HEADER(type, size) (((type) << 16) | (size))
|
||||
#define DRI2_EVENT_TYPE(b) ((b) >> 16)
|
||||
#define DRI2_EVENT_SIZE(b) ((b) & 0xffff)
|
||||
|
||||
#define DRI2_EVENT_PAD 0x0000
|
||||
#define DRI2_EVENT_DRAWABLE_CONFIG 0x0001
|
||||
#define DRI2_EVENT_BUFFER_ATTACH 0x0002
|
||||
|
||||
struct __DRIDrawableConfigEvent {
|
||||
unsigned int event_header;
|
||||
unsigned int drawable;
|
||||
short x;
|
||||
short y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int num_rects;
|
||||
struct drm_clip_rect rects[0];
|
||||
};
|
||||
|
||||
struct __DRIBufferAttachEvent {
|
||||
unsigned int event_header;
|
||||
unsigned int drawable;
|
||||
__DRIDrawableBuffer buffer;
|
||||
};
|
||||
|
||||
#endif /* DRI_SAREA_H */
|
||||
252
src/glx/x11/dri2.c
Normal file
252
src/glx/x11/dri2.c
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
*/
|
||||
|
||||
|
||||
#define NEED_REPLIES
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/extensions/Xext.h>
|
||||
#include <X11/extensions/extutil.h>
|
||||
#include <X11/extensions/dri2proto.h>
|
||||
#include "glheader.h"
|
||||
#include "xf86drm.h"
|
||||
#include "dri2.h"
|
||||
|
||||
static char dri2ExtensionName[] = DRI2_NAME;
|
||||
static XExtensionInfo *dri2Info;
|
||||
static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
|
||||
static /* const */ XExtensionHooks dri2ExtensionHooks = {
|
||||
NULL, /* create_gc */
|
||||
NULL, /* copy_gc */
|
||||
NULL, /* flush_gc */
|
||||
NULL, /* free_gc */
|
||||
NULL, /* create_font */
|
||||
NULL, /* free_font */
|
||||
DRI2CloseDisplay, /* close_display */
|
||||
NULL, /* wire_to_event */
|
||||
NULL, /* event_to_wire */
|
||||
NULL, /* error */
|
||||
NULL, /* error_string */
|
||||
};
|
||||
|
||||
static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info,
|
||||
dri2ExtensionName,
|
||||
&dri2ExtensionHooks,
|
||||
0, NULL)
|
||||
|
||||
Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
|
||||
if (XextHasExtension(info)) {
|
||||
*eventBase = info->codes->first_event;
|
||||
*errorBase = info->codes->first_error;
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
Bool DRI2QueryVersion(Display *dpy, int *major, int *minor)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay (dpy);
|
||||
xDRI2QueryVersionReply rep;
|
||||
xDRI2QueryVersionReq *req;
|
||||
|
||||
XextCheckExtension (dpy, info, dri2ExtensionName, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2QueryVersion, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2QueryVersion;
|
||||
req->majorVersion = DRI2_MAJOR;
|
||||
req->minorVersion = DRI2_MINOR;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
*major = rep.majorVersion;
|
||||
*minor = rep.minorVersion;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool DRI2Connect(Display *dpy, int screen,
|
||||
char **driverName, char **busId, unsigned int *sareaHandle)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
xDRI2ConnectReply rep;
|
||||
xDRI2ConnectReq *req;
|
||||
|
||||
XextCheckExtension (dpy, info, dri2ExtensionName, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2Connect, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2Connect;
|
||||
req->screen = screen;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
|
||||
*sareaHandle = rep.sareaHandle;
|
||||
|
||||
*driverName = Xmalloc(rep.driverNameLength + 1);
|
||||
if (*driverName == NULL) {
|
||||
_XEatData(dpy,
|
||||
((rep.driverNameLength + 3) & ~3) +
|
||||
((rep.busIdLength + 3) & ~3));
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
_XReadPad(dpy, *driverName, rep.driverNameLength);
|
||||
(*driverName)[rep.driverNameLength] = '\0';
|
||||
|
||||
*busId = Xmalloc(rep.busIdLength + 1);
|
||||
if (*busId == NULL) {
|
||||
Xfree(*driverName);
|
||||
_XEatData(dpy, ((rep.busIdLength + 3) & ~3));
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
_XReadPad(dpy, *busId, rep.busIdLength);
|
||||
(*busId)[rep.busIdLength] = '\0';
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return rep.sareaHandle != 0;
|
||||
}
|
||||
|
||||
Bool DRI2AuthConnection(Display *dpy, int screen, drm_magic_t magic)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
xDRI2AuthConnectionReq *req;
|
||||
xDRI2AuthConnectionReply rep;
|
||||
|
||||
XextCheckExtension (dpy, info, dri2ExtensionName, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2AuthConnection, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2AuthConnection;
|
||||
req->screen = screen;
|
||||
req->magic = magic;
|
||||
rep.authenticated = 0;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return rep.authenticated;
|
||||
}
|
||||
|
||||
Bool DRI2CreateDrawable(Display *dpy, XID drawable,
|
||||
unsigned int *handle, unsigned int *head)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
xDRI2CreateDrawableReply rep;
|
||||
xDRI2CreateDrawableReq *req;
|
||||
|
||||
XextCheckExtension (dpy, info, dri2ExtensionName, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2CreateDrawable, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2CreateDrawable;
|
||||
req->drawable = drawable;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
*handle = rep.handle;
|
||||
*head = rep.head;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
void DRI2DestroyDrawable(Display *dpy, XID drawable)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
xDRI2DestroyDrawableReq *req;
|
||||
|
||||
XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
|
||||
|
||||
XSync(dpy, GL_FALSE);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2DestroyDrawable, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2DestroyDrawable;
|
||||
req->drawable = drawable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
|
||||
Bool DRI2ReemitDrawableInfo(Display *dpy, XID drawable, unsigned int *head)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
xDRI2ReemitDrawableInfoReply rep;
|
||||
xDRI2ReemitDrawableInfoReq *req;
|
||||
|
||||
XextCheckExtension (dpy, info, dri2ExtensionName, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(DRI2ReemitDrawableInfo, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->dri2ReqType = X_DRI2ReemitDrawableInfo;
|
||||
req->drawable = drawable;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
*head = rep.head;
|
||||
|
||||
return True;
|
||||
}
|
||||
53
src/glx/x11/dri2.h
Normal file
53
src/glx/x11/dri2.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright © 2007,2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
*/
|
||||
|
||||
#ifndef _DRI2_H_
|
||||
#define _DRI2_H_
|
||||
|
||||
extern Bool
|
||||
DRI2QueryExtension(Display *display, int *eventBase, int *errorBase);
|
||||
extern Bool
|
||||
DRI2QueryVersion(Display *display, int *major, int *minor);
|
||||
extern Bool
|
||||
DRI2Connect(Display *display, int screen,
|
||||
char **driverName, char **busId, unsigned int *sareaHandle);
|
||||
extern Bool
|
||||
DRI2AuthConnection(Display *display, int screen, drm_magic_t magic);
|
||||
extern Bool
|
||||
DRI2CreateDrawable(Display *display, XID drawable,
|
||||
unsigned int *handle, unsigned int *head);
|
||||
extern void
|
||||
DRI2DestroyDrawable(Display *display, XID handle);
|
||||
extern Bool
|
||||
DRI2ReemitDrawableInfo(Display *dpy, XID handle, unsigned int *head);
|
||||
|
||||
#endif
|
||||
371
src/glx/x11/dri2_glx.c
Normal file
371
src/glx/x11/dri2_glx.c
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
*/
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include "glheader.h"
|
||||
#include "glxclient.h"
|
||||
#include "glcontextmodes.h"
|
||||
#include "xf86dri.h"
|
||||
#include "sarea.h"
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include "xf86drm.h"
|
||||
#include "dri2.h"
|
||||
#include "dri_common.h"
|
||||
|
||||
typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
|
||||
typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
|
||||
|
||||
struct __GLXDRIdisplayPrivateRec {
|
||||
__GLXDRIdisplay base;
|
||||
|
||||
/*
|
||||
** XFree86-DRI version information
|
||||
*/
|
||||
int driMajor;
|
||||
int driMinor;
|
||||
int driPatch;
|
||||
};
|
||||
|
||||
struct __GLXDRIcontextPrivateRec {
|
||||
__GLXDRIcontext base;
|
||||
__DRIcontext *driContext;
|
||||
__GLXscreenConfigs *psc;
|
||||
};
|
||||
|
||||
static void dri2DestroyContext(__GLXDRIcontext *context,
|
||||
__GLXscreenConfigs *psc, Display *dpy)
|
||||
{
|
||||
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
|
||||
const __DRIcoreExtension *core = pcp->psc->core;
|
||||
|
||||
(*core->destroyContext)(pcp->driContext);
|
||||
|
||||
Xfree(pcp);
|
||||
}
|
||||
|
||||
static Bool dri2BindContext(__GLXDRIcontext *context,
|
||||
__GLXDRIdrawable *draw, __GLXDRIdrawable *read)
|
||||
{
|
||||
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
|
||||
const __DRIcoreExtension *core = pcp->psc->core;
|
||||
|
||||
return (*core->bindContext)(pcp->driContext,
|
||||
draw->driDrawable,
|
||||
read->driDrawable);
|
||||
}
|
||||
|
||||
static void dri2UnbindContext(__GLXDRIcontext *context)
|
||||
{
|
||||
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
|
||||
const __DRIcoreExtension *core = pcp->psc->core;
|
||||
|
||||
(*core->unbindContext)(pcp->driContext);
|
||||
}
|
||||
|
||||
static __GLXDRIcontext *dri2CreateContext(__GLXscreenConfigs *psc,
|
||||
const __GLcontextModes *mode,
|
||||
GLXContext gc,
|
||||
GLXContext shareList, int renderType)
|
||||
{
|
||||
__GLXDRIcontextPrivate *pcp, *pcp_shared;
|
||||
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
|
||||
const __DRIcoreExtension *core = psc->core;
|
||||
__DRIcontext *shared = NULL;
|
||||
|
||||
if (shareList) {
|
||||
pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
|
||||
shared = pcp_shared->driContext;
|
||||
}
|
||||
|
||||
pcp = Xmalloc(sizeof *pcp);
|
||||
if (pcp == NULL)
|
||||
return NULL;
|
||||
|
||||
pcp->psc = psc;
|
||||
pcp->driContext =
|
||||
(*core->createNewContext)(psc->__driScreen,
|
||||
config->driConfig, shared, pcp);
|
||||
gc->__driContext = pcp->driContext;
|
||||
|
||||
if (pcp->driContext == NULL) {
|
||||
Xfree(pcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp->base.destroyContext = dri2DestroyContext;
|
||||
pcp->base.bindContext = dri2BindContext;
|
||||
pcp->base.unbindContext = dri2UnbindContext;
|
||||
|
||||
return &pcp->base;
|
||||
}
|
||||
|
||||
static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
|
||||
{
|
||||
const __DRIcoreExtension *core = pdraw->psc->core;
|
||||
|
||||
(*core->destroyDrawable)(pdraw->driDrawable);
|
||||
DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable);
|
||||
Xfree(pdraw);
|
||||
}
|
||||
|
||||
static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc,
|
||||
XID xDrawable,
|
||||
GLXDrawable drawable,
|
||||
const __GLcontextModes *modes)
|
||||
{
|
||||
__GLXDRIdrawable *pdraw;
|
||||
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
|
||||
unsigned int handle, head;
|
||||
const __DRIcoreExtension *core = psc->core;
|
||||
|
||||
pdraw = Xmalloc(sizeof(*pdraw));
|
||||
if (!pdraw)
|
||||
return NULL;
|
||||
|
||||
pdraw->destroyDrawable = dri2DestroyDrawable;
|
||||
pdraw->xDrawable = xDrawable;
|
||||
pdraw->drawable = drawable;
|
||||
pdraw->psc = psc;
|
||||
|
||||
fprintf(stderr, "calling DRI2CreateDrawable, XID 0x%lx, GLX ID 0x%lx\n",
|
||||
xDrawable, drawable);
|
||||
|
||||
if (!DRI2CreateDrawable(psc->dpy, xDrawable, &handle, &head)) {
|
||||
Xfree(pdraw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fprintf(stderr, "success, head 0x%x, handle 0x%x\n", head, handle);
|
||||
|
||||
/* Create a new drawable */
|
||||
pdraw->driDrawable =
|
||||
(*core->createNewDrawable)(psc->__driScreen,
|
||||
config->driConfig,
|
||||
handle,
|
||||
head,
|
||||
pdraw);
|
||||
|
||||
if (!pdraw->driDrawable) {
|
||||
DRI2DestroyDrawable(psc->dpy, drawable);
|
||||
Xfree(pdraw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pdraw;
|
||||
}
|
||||
|
||||
static void dri2DestroyScreen(__GLXscreenConfigs *psc)
|
||||
{
|
||||
/* Free the direct rendering per screen data */
|
||||
(*psc->core->destroyScreen)(psc->__driScreen);
|
||||
drmClose(psc->fd);
|
||||
psc->__driScreen = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void dri2ReemitDrawableInfo(__DRIdrawable *draw, unsigned int *tail,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
__GLXDRIdrawable *pdraw = loaderPrivate;
|
||||
|
||||
DRI2ReemitDrawableInfo(pdraw->psc->dpy, pdraw->drawable, tail);
|
||||
}
|
||||
|
||||
static void dri2PostDamage(__DRIdrawable *draw,
|
||||
struct drm_clip_rect *rects,
|
||||
int numRects, void *loaderPrivate)
|
||||
{
|
||||
XRectangle *xrects;
|
||||
XserverRegion region;
|
||||
__GLXDRIdrawable *glxDraw = loaderPrivate;
|
||||
__GLXscreenConfigs *psc = glxDraw->psc;
|
||||
Display *dpy = psc->dpy;
|
||||
int i;
|
||||
|
||||
xrects = malloc(sizeof(XRectangle) * numRects);
|
||||
if (xrects == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < numRects; i++) {
|
||||
xrects[i].x = rects[i].x1;
|
||||
xrects[i].y = rects[i].y1;
|
||||
xrects[i].width = rects[i].x2 - rects[i].x1;
|
||||
xrects[i].height = rects[i].y2 - rects[i].y1;
|
||||
}
|
||||
region = XFixesCreateRegion(dpy, xrects, numRects);
|
||||
free(xrects);
|
||||
XDamageAdd(dpy, glxDraw->xDrawable, region);
|
||||
XFixesDestroyRegion(dpy, region);
|
||||
}
|
||||
|
||||
static const __DRIloaderExtension dri2LoaderExtension = {
|
||||
{ __DRI_LOADER, __DRI_LOADER_VERSION },
|
||||
dri2ReemitDrawableInfo,
|
||||
dri2PostDamage
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions[] = {
|
||||
&dri2LoaderExtension.base,
|
||||
&systemTimeExtension.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen,
|
||||
__GLXdisplayPrivate *priv)
|
||||
{
|
||||
const __DRIconfig **driver_configs;
|
||||
const __DRIextension **extensions;
|
||||
__GLXDRIscreen *psp;
|
||||
unsigned int sareaHandle;
|
||||
char *driverName, *busID;
|
||||
drm_magic_t magic;
|
||||
int i;
|
||||
|
||||
psp = Xmalloc(sizeof *psp);
|
||||
if (psp == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Initialize per screen dynamic client GLX extensions */
|
||||
psc->ext_list_first_time = GL_TRUE;
|
||||
|
||||
if (!DRI2Connect(psc->dpy, screen, &driverName, &busID, &sareaHandle))
|
||||
return NULL;
|
||||
|
||||
psc->driver = driOpenDriver(driverName);
|
||||
if (psc->driver == NULL)
|
||||
goto handle_error;
|
||||
|
||||
extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
|
||||
if (extensions == NULL) {
|
||||
ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
for (i = 0; extensions[i]; i++) {
|
||||
if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
|
||||
psc->core = (__DRIcoreExtension *) extensions[i];
|
||||
}
|
||||
|
||||
if (psc->core == NULL) {
|
||||
ErrorMessageF("core dri extension not found\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
psc->fd = drmOpen(NULL, busID);
|
||||
if (psc->fd < 0) {
|
||||
ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (drmGetMagic(psc->fd, &magic))
|
||||
return NULL;
|
||||
|
||||
if (!DRI2AuthConnection(psc->dpy, screen, magic)) {
|
||||
ErrorMessageF("failed to authenticate drm access\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
psc->__driScreen =
|
||||
psc->core->createNewScreen(screen, psc->fd, sareaHandle,
|
||||
loader_extensions, &driver_configs, psc);
|
||||
if (psc->__driScreen == NULL) {
|
||||
ErrorMessageF("failed to create dri screen\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driBindExtensions(psc);
|
||||
|
||||
psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
|
||||
psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
|
||||
|
||||
psp->destroyScreen = dri2DestroyScreen;
|
||||
psp->createContext = dri2CreateContext;
|
||||
psp->createDrawable = dri2CreateDrawable;
|
||||
|
||||
Xfree(driverName);
|
||||
Xfree(busID);
|
||||
|
||||
return psp;
|
||||
|
||||
handle_error:
|
||||
Xfree(driverName);
|
||||
Xfree(busID);
|
||||
|
||||
/* FIXME: clean up here */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Called from __glXFreeDisplayPrivate.
|
||||
*/
|
||||
static void dri2DestroyDisplay(__GLXDRIdisplay *dpy)
|
||||
{
|
||||
Xfree(dpy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate, initialize and return a __DRIdisplayPrivate object.
|
||||
* This is called from __glXInitialize() when we are given a new
|
||||
* display pointer.
|
||||
*/
|
||||
_X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
|
||||
{
|
||||
__GLXDRIdisplayPrivate *pdp;
|
||||
int eventBase, errorBase;
|
||||
|
||||
if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
|
||||
return NULL;
|
||||
|
||||
pdp = Xmalloc(sizeof *pdp);
|
||||
if (pdp == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
|
||||
Xfree(pdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdp->driPatch = 0;
|
||||
|
||||
pdp->base.destroyDisplay = dri2DestroyDisplay;
|
||||
pdp->base.createScreen = dri2CreateScreen;
|
||||
|
||||
return &pdp->base;
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
399
src/glx/x11/dri_common.c
Normal file
399
src/glx/x11/dri_common.c
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||
* Brian Paul <brian@precisioninsight.com>
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
*/
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include "glheader.h"
|
||||
#include "glxclient.h"
|
||||
#include "glcontextmodes.h"
|
||||
#include "dri_common.h"
|
||||
|
||||
#ifndef RTLD_NOW
|
||||
#define RTLD_NOW 0
|
||||
#endif
|
||||
#ifndef RTLD_GLOBAL
|
||||
#define RTLD_GLOBAL 0
|
||||
#endif
|
||||
|
||||
_X_HIDDEN void InfoMessageF(const char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
|
||||
fprintf(stderr, "libGL: ");
|
||||
va_start(args, f);
|
||||
vfprintf(stderr, f, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error to stderr, unless LIBGL_DEBUG=="quiet".
|
||||
*/
|
||||
_X_HIDDEN void ErrorMessageF(const char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
|
||||
fprintf(stderr, "libGL error: ");
|
||||
va_start(args, f);
|
||||
vfprintf(stderr, f, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DEFAULT_DRIVER_DIR
|
||||
/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
|
||||
#define DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Try to \c dlopen the named driver.
|
||||
*
|
||||
* This function adds the "_dri.so" suffix to the driver name and searches the
|
||||
* directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
|
||||
* order to find the driver.
|
||||
*
|
||||
* \param driverName - a name like "tdfx", "i810", "mga", etc.
|
||||
*
|
||||
* \returns
|
||||
* A handle from \c dlopen, or \c NULL if driver file not found.
|
||||
*/
|
||||
_X_HIDDEN void *driOpenDriver(const char *driverName)
|
||||
{
|
||||
void *glhandle, *handle;
|
||||
const char *libPaths, *p, *next;
|
||||
char realDriverName[200];
|
||||
int len;
|
||||
|
||||
/* Attempt to make sure libGL symbols will be visible to the driver */
|
||||
glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
libPaths = NULL;
|
||||
if (geteuid() == getuid()) {
|
||||
/* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
|
||||
libPaths = getenv("LIBGL_DRIVERS_PATH");
|
||||
if (!libPaths)
|
||||
libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
|
||||
}
|
||||
if (libPaths == NULL)
|
||||
libPaths = DEFAULT_DRIVER_DIR;
|
||||
|
||||
handle = NULL;
|
||||
for (p = libPaths; *p; p = next) {
|
||||
next = strchr(p, ':');
|
||||
if (next == NULL) {
|
||||
len = strlen(p);
|
||||
next = p + len;
|
||||
} else {
|
||||
len = next - p;
|
||||
next++;
|
||||
}
|
||||
|
||||
#ifdef GLX_USE_TLS
|
||||
snprintf(realDriverName, sizeof realDriverName,
|
||||
"%.*s/tls/%s_dri.so", len, p, driverName);
|
||||
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
|
||||
handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
|
||||
#endif
|
||||
|
||||
if ( handle == NULL ) {
|
||||
snprintf(realDriverName, sizeof realDriverName,
|
||||
"%.*s/%s_dri.so", len, p, driverName);
|
||||
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
|
||||
handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
|
||||
if ( handle != NULL )
|
||||
break;
|
||||
else
|
||||
ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
|
||||
}
|
||||
|
||||
if (!handle)
|
||||
ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);
|
||||
|
||||
if (glhandle)
|
||||
dlclose(glhandle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = {
|
||||
{ __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
|
||||
__glXGetUST,
|
||||
__driGetMscRateOML
|
||||
};
|
||||
|
||||
#define __ATTRIB(attrib, field) \
|
||||
{ attrib, offsetof(__GLcontextModes, 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),
|
||||
#if 0
|
||||
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
|
||||
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex),
|
||||
__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_RED_MASK, redMask),
|
||||
__ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
|
||||
__ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
|
||||
__ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
|
||||
#endif
|
||||
__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),
|
||||
#if 0
|
||||
__ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
|
||||
#endif
|
||||
__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 int
|
||||
scalarEqual(__GLcontextModes *mode, unsigned int attrib, unsigned int value)
|
||||
{
|
||||
unsigned int glxValue;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(attribMap); i++)
|
||||
if (attribMap[i].attrib == attrib) {
|
||||
glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
|
||||
return glxValue == GLX_DONT_CARE || glxValue == value;
|
||||
}
|
||||
|
||||
return GL_TRUE; /* Is a non-existing attribute equal to value? */
|
||||
}
|
||||
|
||||
static int
|
||||
driConfigEqual(const __DRIcoreExtension *core,
|
||||
__GLcontextModes *modes, const __DRIconfig *driConfig)
|
||||
{
|
||||
unsigned int attrib, value, glxValue;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
|
||||
switch (attrib) {
|
||||
case __DRI_ATTRIB_RENDER_TYPE:
|
||||
glxValue = 0;
|
||||
if (value & __DRI_ATTRIB_RGBA_BIT) {
|
||||
glxValue |= GLX_RGBA_BIT;
|
||||
} else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
|
||||
glxValue |= GLX_COLOR_INDEX_BIT;
|
||||
}
|
||||
if (glxValue != modes->renderType)
|
||||
return GL_FALSE;
|
||||
break;
|
||||
|
||||
case __DRI_ATTRIB_CONFIG_CAVEAT:
|
||||
if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
|
||||
glxValue = GLX_NON_CONFORMANT_CONFIG;
|
||||
else if (value & __DRI_ATTRIB_SLOW_BIT)
|
||||
glxValue = GLX_SLOW_CONFIG;
|
||||
else
|
||||
glxValue = GLX_NONE;
|
||||
if (glxValue != modes->visualRating)
|
||||
return GL_FALSE;
|
||||
break;
|
||||
|
||||
case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
|
||||
glxValue = 0;
|
||||
if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
|
||||
glxValue |= GLX_TEXTURE_1D_BIT_EXT;
|
||||
if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
|
||||
glxValue |= GLX_TEXTURE_2D_BIT_EXT;
|
||||
if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
|
||||
glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
|
||||
if (modes->bindToTextureTargets != GLX_DONT_CARE &&
|
||||
glxValue != modes->bindToTextureTargets)
|
||||
return GL_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!scalarEqual(modes, attrib, value))
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static __GLcontextModes *
|
||||
createDriMode(const __DRIcoreExtension *core,
|
||||
__GLcontextModes *modes, const __DRIconfig **driConfigs)
|
||||
{
|
||||
__GLXDRIconfigPrivate *config;
|
||||
int i;
|
||||
|
||||
for (i = 0; driConfigs[i]; i++) {
|
||||
if (driConfigEqual(core, modes, driConfigs[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (driConfigs[i] == NULL)
|
||||
return NULL;
|
||||
|
||||
config = Xmalloc(sizeof *config);
|
||||
if (config == NULL)
|
||||
return NULL;
|
||||
|
||||
config->modes = *modes;
|
||||
config->driConfig = driConfigs[i];
|
||||
|
||||
return &config->modes;
|
||||
}
|
||||
|
||||
_X_HIDDEN __GLcontextModes *
|
||||
driConvertConfigs(const __DRIcoreExtension *core,
|
||||
__GLcontextModes *modes, const __DRIconfig **configs)
|
||||
{
|
||||
__GLcontextModes head, *tail, *m;
|
||||
|
||||
tail = &head;
|
||||
head.next = NULL;
|
||||
for (m = modes; m; m = m->next) {
|
||||
tail->next = createDriMode(core, m, configs);
|
||||
if (tail->next == NULL) {
|
||||
/* no matching dri config for m */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
tail = tail->next;
|
||||
}
|
||||
|
||||
_gl_context_modes_destroy(modes);
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
_X_HIDDEN void
|
||||
driBindExtensions(__GLXscreenConfigs *psc)
|
||||
{
|
||||
const __DRIextension **extensions;
|
||||
int i;
|
||||
|
||||
extensions = psc->core->getExtensions(psc->__driScreen);
|
||||
|
||||
for (i = 0; extensions[i]; i++) {
|
||||
#ifdef __DRI_COPY_SUB_BUFFER
|
||||
if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
|
||||
psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer_bit");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_SWAP_CONTROL
|
||||
if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
|
||||
psc->swapControl = (__DRIswapControlExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
|
||||
__glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_ALLOCATE
|
||||
if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) {
|
||||
psc->allocate = (__DRIallocateExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_FRAME_TRACKING
|
||||
if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) {
|
||||
psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_MEDIA_STREAM_COUNTER
|
||||
if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
|
||||
psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_SWAP_BUFFER_COUNTER
|
||||
/* No driver supports this at this time and the extension is
|
||||
* not defined in dri_interface.h. Will enable
|
||||
* GLX_OML_sync_control if implemented. */
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_READ_DRAWABLE
|
||||
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
|
||||
__glXEnableDirectExtension(psc, "GLX_SGI_make_current_read");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_TEX_BUFFER
|
||||
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
|
||||
psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
|
||||
__glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ignore unknown extensions */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
60
src/glx/x11/dri_common.h
Normal file
60
src/glx/x11/dri_common.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||
* Brian Paul <brian@precisioninsight.com>
|
||||
* Kristian Høgsberg (krh@redhat.com)
|
||||
*/
|
||||
|
||||
#ifndef _DRI_COMMON_H
|
||||
#define _DRI_COMMON_H
|
||||
|
||||
typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate;
|
||||
|
||||
struct __GLXDRIconfigPrivateRec {
|
||||
__GLcontextModes modes;
|
||||
const __DRIconfig *driConfig;
|
||||
};
|
||||
|
||||
extern __GLcontextModes *
|
||||
driConvertConfigs(const __DRIcoreExtension *core,
|
||||
__GLcontextModes *modes, const __DRIconfig **configs);
|
||||
|
||||
extern const __DRIsystemTimeExtension systemTimeExtension;
|
||||
|
||||
extern void InfoMessageF(const char *f, ...);
|
||||
|
||||
extern void ErrorMessageF(const char *f, ...);
|
||||
|
||||
extern void *driOpenDriver(const char *driverName);
|
||||
|
||||
extern void driBindExtensions(__GLXscreenConfigs *psc);
|
||||
|
||||
#endif /* _DRI_COMMON_H */
|
||||
510
src/glx/x11/glxcurrent.c
Normal file
510
src/glx/x11/glxcurrent.c
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
** License Applicability. Except to the extent portions of this file are
|
||||
** made subject to an alternative license as permitted in the SGI Free
|
||||
** Software License B, Version 1.1 (the "License"), the contents of this
|
||||
** file are subject only to the provisions of the License. You may not use
|
||||
** this file except in compliance with the License. You may obtain a copy
|
||||
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
||||
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
||||
**
|
||||
** http://oss.sgi.com/projects/FreeB
|
||||
**
|
||||
** Note that, as provided in the License, the Software is distributed on an
|
||||
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
||||
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
||||
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
||||
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
||||
**
|
||||
** Original Code. The Original Code is: OpenGL Sample Implementation,
|
||||
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
||||
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
||||
** Copyright in any portions created by third parties is as indicated
|
||||
** elsewhere herein. All Rights Reserved.
|
||||
**
|
||||
** Additional Notice Provisions: The application programming interfaces
|
||||
** established by SGI in conjunction with the Original Code are The
|
||||
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
|
||||
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
|
||||
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
|
||||
** Window System(R) (Version 1.3), released October 19, 1998. This software
|
||||
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
|
||||
** published by SGI, but has not been independently verified as being
|
||||
** compliant with the OpenGL(R) version 1.2.1 Specification.
|
||||
**
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxcurrent.c
|
||||
* Client-side GLX interface for current context management.
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "glapi.h"
|
||||
#include "glheader.h"
|
||||
#include "indirect_init.h"
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
#include "xf86dri.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We setup some dummy structures here so that the API can be used
|
||||
** even if no context is current.
|
||||
*/
|
||||
|
||||
static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
|
||||
|
||||
/*
|
||||
** Dummy context used by small commands when there is no current context.
|
||||
** All the
|
||||
** gl and glx entry points are designed to operate as nop's when using
|
||||
** the dummy context structure.
|
||||
*/
|
||||
static __GLXcontext dummyContext = {
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
|
||||
sizeof(dummyBuffer),
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** All indirect rendering contexts will share the same indirect dispatch table.
|
||||
*/
|
||||
static __GLapi *IndirectAPI = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Current context management and locking
|
||||
*/
|
||||
|
||||
#if defined( USE_XTHREADS )
|
||||
|
||||
/* thread safe */
|
||||
static GLboolean TSDinitialized = GL_FALSE;
|
||||
static xthread_key_t ContextTSD;
|
||||
|
||||
_X_HIDDEN __GLXcontext *__glXGetCurrentContext(void)
|
||||
{
|
||||
if (!TSDinitialized) {
|
||||
xthread_key_create(&ContextTSD, NULL);
|
||||
TSDinitialized = GL_TRUE;
|
||||
return &dummyContext;
|
||||
}
|
||||
else {
|
||||
void *p;
|
||||
xthread_get_specific(ContextTSD, &p);
|
||||
if (!p)
|
||||
return &dummyContext;
|
||||
else
|
||||
return (__GLXcontext *) p;
|
||||
}
|
||||
}
|
||||
|
||||
_X_HIDDEN void __glXSetCurrentContext(__GLXcontext *c)
|
||||
{
|
||||
if (!TSDinitialized) {
|
||||
xthread_key_create(&ContextTSD, NULL);
|
||||
TSDinitialized = GL_TRUE;
|
||||
}
|
||||
xthread_set_specific(ContextTSD, c);
|
||||
}
|
||||
|
||||
|
||||
/* Used by the __glXLock() and __glXUnlock() macros */
|
||||
_X_HIDDEN xmutex_rec __glXmutex;
|
||||
|
||||
#elif defined( PTHREADS )
|
||||
|
||||
_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
# if defined( GLX_USE_TLS )
|
||||
|
||||
/**
|
||||
* Per-thread GLX context pointer.
|
||||
*
|
||||
* \c __glXSetCurrentContext is written is such a way that this pointer can
|
||||
* \b never be \c NULL. This is important! Because of this
|
||||
* \c __glXGetCurrentContext can be implemented as trivial macro.
|
||||
*/
|
||||
__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
|
||||
= &dummyContext;
|
||||
|
||||
_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
|
||||
{
|
||||
__glX_tls_Context = (c != NULL) ? c : &dummyContext;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
/**
|
||||
* Per-thread data key.
|
||||
*
|
||||
* Once \c init_thread_data has been called, the per-thread data key will
|
||||
* take a value of \c NULL. As each new thread is created the default
|
||||
* value, in that thread, will be \c NULL.
|
||||
*/
|
||||
static pthread_key_t ContextTSD;
|
||||
|
||||
/**
|
||||
* Initialize the per-thread data key.
|
||||
*
|
||||
* This function is called \b exactly once per-process (not per-thread!) to
|
||||
* initialize the per-thread data key. This is ideally done using the
|
||||
* \c pthread_once mechanism.
|
||||
*/
|
||||
static void init_thread_data( void )
|
||||
{
|
||||
if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
|
||||
perror( "pthread_key_create" );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
|
||||
{
|
||||
pthread_once( & once_control, init_thread_data );
|
||||
pthread_setspecific( ContextTSD, c );
|
||||
}
|
||||
|
||||
_X_HIDDEN __GLXcontext * __glXGetCurrentContext( void )
|
||||
{
|
||||
void * v;
|
||||
|
||||
pthread_once( & once_control, init_thread_data );
|
||||
|
||||
v = pthread_getspecific( ContextTSD );
|
||||
return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
|
||||
}
|
||||
|
||||
# endif /* defined( GLX_USE_TLS ) */
|
||||
|
||||
#elif defined( THREADS )
|
||||
|
||||
#error Unknown threading method specified.
|
||||
|
||||
#else
|
||||
|
||||
/* not thread safe */
|
||||
_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
_X_HIDDEN void __glXSetCurrentContextNull(void)
|
||||
{
|
||||
__glXSetCurrentContext(&dummyContext);
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
_glapi_set_dispatch(NULL); /* no-op functions */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
PUBLIC GLXContext glXGetCurrentContext(void)
|
||||
{
|
||||
GLXContext cx = __glXGetCurrentContext();
|
||||
|
||||
if (cx == &dummyContext) {
|
||||
return NULL;
|
||||
} else {
|
||||
return cx;
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC GLXDrawable glXGetCurrentDrawable(void)
|
||||
{
|
||||
GLXContext gc = __glXGetCurrentContext();
|
||||
return gc->currentDrawable;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Sends a GLX protocol message to the specified display to make the context
|
||||
* and the drawables current.
|
||||
*
|
||||
* \param dpy Display to send the message to.
|
||||
* \param opcode Major opcode value for the display.
|
||||
* \param gc_id Context tag for the context to be made current.
|
||||
* \param draw Drawable ID for the "draw" drawable.
|
||||
* \param read Drawable ID for the "read" drawable.
|
||||
* \param reply Space to store the X-server's reply.
|
||||
*
|
||||
* \warning
|
||||
* This function assumes that \c dpy is locked with \c LockDisplay on entry.
|
||||
*/
|
||||
static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode,
|
||||
GLXContextID gc_id, GLXContextTag gc_tag,
|
||||
GLXDrawable draw, GLXDrawable read,
|
||||
xGLXMakeCurrentReply *reply)
|
||||
{
|
||||
Bool ret;
|
||||
|
||||
|
||||
LockDisplay(dpy);
|
||||
|
||||
if (draw == read) {
|
||||
xGLXMakeCurrentReq *req;
|
||||
|
||||
GetReq(GLXMakeCurrent,req);
|
||||
req->reqType = opcode;
|
||||
req->glxCode = X_GLXMakeCurrent;
|
||||
req->drawable = draw;
|
||||
req->context = gc_id;
|
||||
req->oldContextTag = gc_tag;
|
||||
}
|
||||
else {
|
||||
__GLXdisplayPrivate *priv = __glXInitialize(dpy);
|
||||
|
||||
/* If the server can support the GLX 1.3 version, we should
|
||||
* perfer that. Not only that, some servers support GLX 1.3 but
|
||||
* not the SGI extension.
|
||||
*/
|
||||
|
||||
if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
|
||||
xGLXMakeContextCurrentReq *req;
|
||||
|
||||
GetReq(GLXMakeContextCurrent,req);
|
||||
req->reqType = opcode;
|
||||
req->glxCode = X_GLXMakeContextCurrent;
|
||||
req->drawable = draw;
|
||||
req->readdrawable = read;
|
||||
req->context = gc_id;
|
||||
req->oldContextTag = gc_tag;
|
||||
}
|
||||
else {
|
||||
xGLXVendorPrivateWithReplyReq *vpreq;
|
||||
xGLXMakeCurrentReadSGIReq *req;
|
||||
|
||||
GetReqExtra(GLXVendorPrivateWithReply,
|
||||
sz_xGLXMakeCurrentReadSGIReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
|
||||
req = (xGLXMakeCurrentReadSGIReq *)vpreq;
|
||||
req->reqType = opcode;
|
||||
req->glxCode = X_GLXVendorPrivateWithReply;
|
||||
req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
|
||||
req->drawable = draw;
|
||||
req->readable = read;
|
||||
req->context = gc_id;
|
||||
req->oldContextTag = gc_tag;
|
||||
}
|
||||
}
|
||||
|
||||
ret = _XReply(dpy, (xReply*) reply, 0, False);
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
static __GLXDRIdrawable *
|
||||
FetchDRIDrawable(Display *dpy,
|
||||
GLXDrawable glxDrawable, GLXContext gc, Bool pre13)
|
||||
{
|
||||
__GLXdisplayPrivate * const priv = __glXInitialize(dpy);
|
||||
__GLXDRIdrawable *pdraw;
|
||||
__GLXscreenConfigs *psc;
|
||||
XID drawable;
|
||||
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
psc = &priv->screenConfigs[gc->screen];
|
||||
if (psc->drawHash == NULL)
|
||||
return NULL;
|
||||
|
||||
if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0)
|
||||
return pdraw;
|
||||
|
||||
/* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the
|
||||
* GLX drawable on the fly. Otherwise we pass None as the X
|
||||
* drawable */
|
||||
if (pre13)
|
||||
drawable = glxDrawable;
|
||||
else
|
||||
drawable = None;
|
||||
|
||||
pdraw = psc->driScreen->createDrawable(psc, drawable,
|
||||
glxDrawable, gc->mode);
|
||||
if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) {
|
||||
(*pdraw->destroyDrawable)(pdraw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pdraw;
|
||||
}
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
|
||||
|
||||
/**
|
||||
* Make a particular context current.
|
||||
*
|
||||
* \note This is in this file so that it can access dummyContext.
|
||||
*/
|
||||
static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
|
||||
GLXDrawable read, GLXContext gc,
|
||||
Bool pre13)
|
||||
{
|
||||
xGLXMakeCurrentReply reply;
|
||||
const GLXContext oldGC = __glXGetCurrentContext();
|
||||
const CARD8 opcode = __glXSetupForCommand(dpy);
|
||||
const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext))
|
||||
? opcode : __glXSetupForCommand(oldGC->currentDpy);
|
||||
Bool bindReturnValue;
|
||||
|
||||
|
||||
if (!opcode || !oldOpcode) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Make sure that the new context has a nonzero ID. In the request,
|
||||
* a zero context ID is used only to mean that we bind to no current
|
||||
* context.
|
||||
*/
|
||||
if ((gc != NULL) && (gc->xid == None)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
_glapi_check_multithread();
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
/* Bind the direct rendering context to the drawable */
|
||||
if (gc && gc->driContext) {
|
||||
__GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13);
|
||||
__GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13);
|
||||
|
||||
bindReturnValue =
|
||||
(gc->driContext->bindContext) (gc->driContext, pdraw, pread);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Send a glXMakeCurrent request to bind the new context. */
|
||||
bindReturnValue =
|
||||
SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None,
|
||||
((dpy != oldGC->currentDpy) || oldGC->isDirect)
|
||||
? None : oldGC->currentContextTag,
|
||||
draw, read, &reply);
|
||||
}
|
||||
|
||||
|
||||
if (!bindReturnValue) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) &&
|
||||
!oldGC->isDirect && oldGC != &dummyContext) {
|
||||
xGLXMakeCurrentReply dummy_reply;
|
||||
|
||||
/* We are either switching from one dpy to another and have to
|
||||
* send a request to the previous dpy to unbind the previous
|
||||
* context, or we are switching away from a indirect context to
|
||||
* a direct context and have to send a request to the dpy to
|
||||
* unbind the previous context.
|
||||
*/
|
||||
(void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None,
|
||||
oldGC->currentContextTag, None, None,
|
||||
& dummy_reply);
|
||||
}
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
else if (oldGC->driContext) {
|
||||
oldGC->driContext->unbindContext(oldGC->driContext);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Update our notion of what is current */
|
||||
__glXLock();
|
||||
if (gc == oldGC) {
|
||||
/* Even though the contexts are the same the drawable might have
|
||||
* changed. Note that gc cannot be the dummy, and that oldGC
|
||||
* cannot be NULL, therefore if they are the same, gc is not
|
||||
* NULL and not the dummy.
|
||||
*/
|
||||
gc->currentDrawable = draw;
|
||||
gc->currentReadable = read;
|
||||
} else {
|
||||
if (oldGC != &dummyContext) {
|
||||
/* Old current context is no longer current to anybody */
|
||||
oldGC->currentDpy = 0;
|
||||
oldGC->currentDrawable = None;
|
||||
oldGC->currentReadable = None;
|
||||
oldGC->currentContextTag = 0;
|
||||
|
||||
if (oldGC->xid == None) {
|
||||
/* We are switching away from a context that was
|
||||
* previously destroyed, so we need to free the memory
|
||||
* for the old handle.
|
||||
*/
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
/* Destroy the old direct rendering context */
|
||||
if (oldGC->driContext) {
|
||||
oldGC->driContext->destroyContext(oldGC->driContext,
|
||||
oldGC->psc,
|
||||
oldGC->createDpy);
|
||||
oldGC->driContext = NULL;
|
||||
}
|
||||
#endif
|
||||
__glXFreeContext(oldGC);
|
||||
}
|
||||
}
|
||||
if (gc) {
|
||||
__glXSetCurrentContext(gc);
|
||||
|
||||
gc->currentDpy = dpy;
|
||||
gc->currentDrawable = draw;
|
||||
gc->currentReadable = read;
|
||||
|
||||
if (!gc->driContext) {
|
||||
if (!IndirectAPI)
|
||||
IndirectAPI = __glXNewIndirectAPI();
|
||||
_glapi_set_dispatch(IndirectAPI);
|
||||
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
do {
|
||||
extern void XAppleDRIUseIndirectDispatch(void);
|
||||
XAppleDRIUseIndirectDispatch();
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
__GLXattribute *state =
|
||||
(__GLXattribute *)(gc->client_state_private);
|
||||
|
||||
gc->currentContextTag = reply.contextTag;
|
||||
if (state->array_state == NULL) {
|
||||
(void) glGetString(GL_EXTENSIONS);
|
||||
(void) glGetString(GL_VERSION);
|
||||
__glXInitVertexArrayState(gc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gc->currentContextTag = -1;
|
||||
}
|
||||
} else {
|
||||
__glXSetCurrentContextNull();
|
||||
}
|
||||
}
|
||||
__glXUnlock();
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc)
|
||||
{
|
||||
return MakeContextCurrent(dpy, draw, draw, gc, True);
|
||||
}
|
||||
|
||||
PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
|
||||
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
|
||||
(dpy, d, r, ctx, False), MakeContextCurrent)
|
||||
|
||||
PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent,
|
||||
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
|
||||
(dpy, d, r, ctx, False), MakeContextCurrent)
|
||||
416
src/glx/x11/glxhash.c
Normal file
416
src/glx/x11/glxhash.c
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
/* glxhash.c -- Small hash table support for integer -> integer mapping
|
||||
* Taken from libdrm.
|
||||
*
|
||||
* Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file contains a straightforward implementation of a fixed-sized
|
||||
* hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
|
||||
* collision resolution. There are two potentially interesting things
|
||||
* about this implementation:
|
||||
*
|
||||
* 1) The table is power-of-two sized. Prime sized tables are more
|
||||
* traditional, but do not have a significant advantage over power-of-two
|
||||
* sized table, especially when double hashing is not used for collision
|
||||
* resolution.
|
||||
*
|
||||
* 2) The hash computation uses a table of random integers [Hanson97,
|
||||
* pp. 39-41].
|
||||
*
|
||||
* FUTURE ENHANCEMENTS
|
||||
*
|
||||
* With a table size of 512, the current implementation is sufficient for a
|
||||
* few hundred keys. Since this is well above the expected size of the
|
||||
* tables for which this implementation was designed, the implementation of
|
||||
* dynamic hash tables was postponed until the need arises. A common (and
|
||||
* naive) approach to dynamic hash table implementation simply creates a
|
||||
* new hash table when necessary, rehashes all the data into the new table,
|
||||
* and destroys the old table. The approach in [Larson88] is superior in
|
||||
* two ways: 1) only a portion of the table is expanded when needed,
|
||||
* distributing the expansion cost over several insertions, and 2) portions
|
||||
* of the table can be locked, enabling a scalable thread-safe
|
||||
* implementation.
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Hanson97] David R. Hanson. C Interfaces and Implementations:
|
||||
* Techniques for Creating Reusable Software. Reading, Massachusetts:
|
||||
* Addison-Wesley, 1997.
|
||||
*
|
||||
* [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
|
||||
* Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
|
||||
*
|
||||
* [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
|
||||
* 1988, pp. 446-457.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glxhash.h"
|
||||
#include <X11/Xfuncproto.h>
|
||||
|
||||
#define HASH_MAIN 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HASH_MAGIC 0xdeadbeef
|
||||
#define HASH_DEBUG 0
|
||||
#define HASH_SIZE 512 /* Good for about 100 entries */
|
||||
/* If you change this value, you probably
|
||||
have to change the HashHash hashing
|
||||
function! */
|
||||
|
||||
#define HASH_ALLOC malloc
|
||||
#define HASH_FREE free
|
||||
#define HASH_RANDOM_DECL
|
||||
#define HASH_RANDOM_INIT(seed) srandom(seed)
|
||||
#define HASH_RANDOM random()
|
||||
#define HASH_RANDOM_DESTROY
|
||||
|
||||
typedef struct __glxHashBucket {
|
||||
unsigned long key;
|
||||
void *value;
|
||||
struct __glxHashBucket *next;
|
||||
} __glxHashBucket, *__glxHashBucketPtr;
|
||||
|
||||
typedef struct __glxHashTable *__glxHashTablePtr;
|
||||
struct __glxHashTable {
|
||||
unsigned long magic;
|
||||
unsigned long entries;
|
||||
unsigned long hits; /* At top of linked list */
|
||||
unsigned long partials; /* Not at top of linked list */
|
||||
unsigned long misses; /* Not in table */
|
||||
__glxHashBucketPtr buckets[HASH_SIZE];
|
||||
int p0;
|
||||
__glxHashBucketPtr p1;
|
||||
};
|
||||
|
||||
static unsigned long HashHash(unsigned long key)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
unsigned long tmp = key;
|
||||
static int init = 0;
|
||||
static unsigned long scatter[256];
|
||||
int i;
|
||||
|
||||
if (!init) {
|
||||
HASH_RANDOM_DECL;
|
||||
HASH_RANDOM_INIT(37);
|
||||
for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM;
|
||||
HASH_RANDOM_DESTROY;
|
||||
++init;
|
||||
}
|
||||
|
||||
while (tmp) {
|
||||
hash = (hash << 1) + scatter[tmp & 0xff];
|
||||
tmp >>= 8;
|
||||
}
|
||||
|
||||
hash %= HASH_SIZE;
|
||||
#if HASH_DEBUG
|
||||
printf( "Hash(%d) = %d\n", key, hash);
|
||||
#endif
|
||||
return hash;
|
||||
}
|
||||
|
||||
_X_HIDDEN __glxHashTable *__glxHashCreate(void)
|
||||
{
|
||||
__glxHashTablePtr table;
|
||||
int i;
|
||||
|
||||
table = HASH_ALLOC(sizeof(*table));
|
||||
if (!table) return NULL;
|
||||
table->magic = HASH_MAGIC;
|
||||
table->entries = 0;
|
||||
table->hits = 0;
|
||||
table->partials = 0;
|
||||
table->misses = 0;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL;
|
||||
return table;
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashDestroy(__glxHashTable *t)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
__glxHashBucketPtr bucket;
|
||||
__glxHashBucketPtr next;
|
||||
int i;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
for (bucket = table->buckets[i]; bucket;) {
|
||||
next = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
bucket = next;
|
||||
}
|
||||
}
|
||||
HASH_FREE(table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the bucket and organize the list so that this bucket is at the
|
||||
top. */
|
||||
|
||||
static __glxHashBucketPtr HashFind(__glxHashTablePtr table,
|
||||
unsigned long key, unsigned long *h)
|
||||
{
|
||||
unsigned long hash = HashHash(key);
|
||||
__glxHashBucketPtr prev = NULL;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (h) *h = hash;
|
||||
|
||||
for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
|
||||
if (bucket->key == key) {
|
||||
if (prev) {
|
||||
/* Organize */
|
||||
prev->next = bucket->next;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
++table->partials;
|
||||
} else {
|
||||
++table->hits;
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
prev = bucket;
|
||||
}
|
||||
++table->misses;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashLookup(__glxHashTable *t,
|
||||
unsigned long key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, NULL);
|
||||
if (!bucket) return 1; /* Not found */
|
||||
*value = bucket->value;
|
||||
return 0; /* Found */
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashInsert(__glxHashTable *t,
|
||||
unsigned long key, void *value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
__glxHashBucketPtr bucket;
|
||||
unsigned long hash;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
if (HashFind(table, key, &hash)) return 1; /* Already in table */
|
||||
|
||||
bucket = HASH_ALLOC(sizeof(*bucket));
|
||||
if (!bucket) return -1; /* Error */
|
||||
bucket->key = key;
|
||||
bucket->value = value;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
#if HASH_DEBUG
|
||||
printf("Inserted %d at %d/%p\n", key, hash, bucket);
|
||||
#endif
|
||||
return 0; /* Added to table */
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashDelete(__glxHashTable *t, unsigned long key)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
unsigned long hash;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, &hash);
|
||||
|
||||
if (!bucket) return 1; /* Not found */
|
||||
|
||||
table->buckets[hash] = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashNext(__glxHashTable *t,
|
||||
unsigned long *key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
|
||||
while (table->p0 < HASH_SIZE) {
|
||||
if (table->p1) {
|
||||
*key = table->p1->key;
|
||||
*value = table->p1->value;
|
||||
table->p1 = table->p1->next;
|
||||
return 1;
|
||||
}
|
||||
table->p1 = table->buckets[table->p0];
|
||||
++table->p0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
_X_HIDDEN int __glxHashFirst(__glxHashTable *t,
|
||||
unsigned long *key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr)t;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
table->p0 = 0;
|
||||
table->p1 = table->buckets[0];
|
||||
return __glxHashNext(table, key, value);
|
||||
}
|
||||
|
||||
#if HASH_MAIN
|
||||
#define DIST_LIMIT 10
|
||||
static int dist[DIST_LIMIT];
|
||||
|
||||
static void clear_dist(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0;
|
||||
}
|
||||
|
||||
static int count_entries(__glxHashBucketPtr bucket)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (; bucket; bucket = bucket->next) ++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void update_dist(int count)
|
||||
{
|
||||
if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1];
|
||||
else ++dist[count];
|
||||
}
|
||||
|
||||
static void compute_dist(__glxHashTablePtr table)
|
||||
{
|
||||
int i;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
|
||||
table->entries, table->hits, table->partials, table->misses);
|
||||
clear_dist();
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
bucket = table->buckets[i];
|
||||
update_dist(count_entries(bucket));
|
||||
}
|
||||
for (i = 0; i < DIST_LIMIT; i++) {
|
||||
if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]);
|
||||
else printf("other %10d\n", dist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_table(__glxHashTablePtr table,
|
||||
unsigned long key, unsigned long value)
|
||||
{
|
||||
unsigned long retval = 0;
|
||||
int retcode = __glxHashLookup(table, key, &retval);
|
||||
|
||||
switch (retcode) {
|
||||
case -1:
|
||||
printf("Bad magic = 0x%08lx:"
|
||||
" key = %lu, expected = %lu, returned = %lu\n",
|
||||
table->magic, key, value, retval);
|
||||
break;
|
||||
case 1:
|
||||
printf("Not found: key = %lu, expected = %lu returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
case 0:
|
||||
if (value != retval)
|
||||
printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
default:
|
||||
printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
|
||||
retcode, key, value, retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
__glxHashTablePtr table;
|
||||
int i;
|
||||
|
||||
printf("\n***** 256 consecutive integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 256; i++) __glxHashInsert(table, i, i);
|
||||
for (i = 0; i < 256; i++) check_table(table, i, i);
|
||||
for (i = 256; i >= 0; i--) check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 consecutive integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 1024; i++) __glxHashInsert(table, i, i);
|
||||
for (i = 0; i < 1024; i++) check_table(table, i, i);
|
||||
for (i = 1024; i >= 0; i--) check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 1024; i++) __glxHashInsert(table, i*4096, i);
|
||||
for (i = 0; i < 1024; i++) check_table(table, i*4096, i);
|
||||
for (i = 1024; i >= 0; i--) check_table(table, i*4096, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 random integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) __glxHashInsert(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 5000 random integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) __glxHashInsert(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
16
src/glx/x11/glxhash.h
Normal file
16
src/glx/x11/glxhash.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef _GLX_HASH_H_
|
||||
#define _GLX_HASH_H_
|
||||
|
||||
|
||||
typedef struct __glxHashTable __glxHashTable;
|
||||
|
||||
/* Hash table routines */
|
||||
extern __glxHashTable *__glxHashCreate(void);
|
||||
extern int __glxHashDestroy(__glxHashTable *t);
|
||||
extern int __glxHashLookup(__glxHashTable *t, unsigned long key, void **value);
|
||||
extern int __glxHashInsert(__glxHashTable *t, unsigned long key, void *value);
|
||||
extern int __glxHashDelete(__glxHashTable *t, unsigned long key);
|
||||
extern int __glxHashFirst(__glxHashTable *t, unsigned long *key, void **value);
|
||||
extern int __glxHashNext(__glxHashTable *t, unsigned long *key, void **value);
|
||||
|
||||
#endif /* _GLX_HASH_H_ */
|
||||
347
src/glx/x11/indirect_texture_compression.c
Normal file
347
src/glx/x11/indirect_texture_compression.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2004
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glx_texture_compression.c
|
||||
* Contains the routines required to implement GLX protocol for
|
||||
* ARB_texture_compression and related extensions.
|
||||
*
|
||||
* \sa http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_compression.txt
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
#include "packsingle.h"
|
||||
#include "indirect.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetCompressedTexImageARB( GLenum target, GLint level,
|
||||
GLvoid * img )
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXGetTexImageReply reply;
|
||||
size_t image_bytes;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN( X_GLsop_GetCompressedTexImage, 8 );
|
||||
__GLX_SINGLE_PUT_LONG( 0, target );
|
||||
__GLX_SINGLE_PUT_LONG( 4, level );
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
|
||||
image_bytes = reply.width;
|
||||
assert( image_bytes <= ((4 * reply.length) - 0) );
|
||||
assert( image_bytes >= ((4 * reply.length) - 3) );
|
||||
|
||||
if ( image_bytes != 0 ) {
|
||||
_XRead( dpy, (char *) img, image_bytes );
|
||||
if ( image_bytes < (4 * reply.length) ) {
|
||||
_XEatData( dpy, (4 * reply.length) - image_bytes );
|
||||
}
|
||||
}
|
||||
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal function used for \c glCompressedTexImage1D and
|
||||
* \c glCompressedTexImage2D.
|
||||
*/
|
||||
static void
|
||||
CompressedTexImage1D2D( GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid *data, CARD32 rop )
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if ( gc->currentDpy == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (target == GL_PROXY_TEXTURE_1D)
|
||||
|| (target == GL_PROXY_TEXTURE_2D)
|
||||
|| (target == GL_PROXY_TEXTURE_CUBE_MAP) ) {
|
||||
compsize = 0;
|
||||
}
|
||||
else {
|
||||
compsize = image_size;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE
|
||||
+ compsize );
|
||||
if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
|
||||
__GLX_BEGIN_VARIABLE( rop, cmdlen );
|
||||
__GLX_PUT_LONG( 4, target );
|
||||
__GLX_PUT_LONG( 8, level );
|
||||
__GLX_PUT_LONG( 12, internal_format );
|
||||
__GLX_PUT_LONG( 16, width );
|
||||
__GLX_PUT_LONG( 20, height );
|
||||
__GLX_PUT_LONG( 24, border );
|
||||
__GLX_PUT_LONG( 28, image_size );
|
||||
if ( compsize != 0 ) {
|
||||
__GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE,
|
||||
data, image_size );
|
||||
}
|
||||
__GLX_END( cmdlen );
|
||||
}
|
||||
else {
|
||||
assert( compsize != 0 );
|
||||
|
||||
__GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
|
||||
__GLX_PUT_LONG( 8, target );
|
||||
__GLX_PUT_LONG( 12, level );
|
||||
__GLX_PUT_LONG( 16, internal_format );
|
||||
__GLX_PUT_LONG( 20, width );
|
||||
__GLX_PUT_LONG( 24, height );
|
||||
__GLX_PUT_LONG( 28, border );
|
||||
__GLX_PUT_LONG( 32, image_size );
|
||||
__glXSendLargeCommand( gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + 4,
|
||||
data, image_size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal function used for \c glCompressedTexSubImage1D and
|
||||
* \c glCompressedTexSubImage2D.
|
||||
*/
|
||||
static void
|
||||
CompressedTexSubImage1D2D( GLenum target, GLint level,
|
||||
GLsizei xoffset, GLsizei yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid *data, CARD32 rop )
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if ( gc->currentDpy == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( target == GL_PROXY_TEXTURE_3D ) {
|
||||
compsize = 0;
|
||||
}
|
||||
else {
|
||||
compsize = image_size;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE
|
||||
+ compsize );
|
||||
if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
|
||||
__GLX_BEGIN_VARIABLE( rop, cmdlen );
|
||||
__GLX_PUT_LONG( 4, target );
|
||||
__GLX_PUT_LONG( 8, level );
|
||||
__GLX_PUT_LONG( 12, xoffset );
|
||||
__GLX_PUT_LONG( 16, yoffset );
|
||||
__GLX_PUT_LONG( 20, width );
|
||||
__GLX_PUT_LONG( 24, height );
|
||||
__GLX_PUT_LONG( 28, format );
|
||||
__GLX_PUT_LONG( 32, image_size );
|
||||
if ( compsize != 0 ) {
|
||||
__GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE,
|
||||
data, image_size );
|
||||
}
|
||||
__GLX_END( cmdlen );
|
||||
}
|
||||
else {
|
||||
assert( compsize != 0 );
|
||||
|
||||
__GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
|
||||
__GLX_PUT_LONG( 8, target );
|
||||
__GLX_PUT_LONG( 12, level );
|
||||
__GLX_PUT_LONG( 16, xoffset );
|
||||
__GLX_PUT_LONG( 20, yoffset );
|
||||
__GLX_PUT_LONG( 24, width );
|
||||
__GLX_PUT_LONG( 28, height );
|
||||
__GLX_PUT_LONG( 32, format );
|
||||
__GLX_PUT_LONG( 36, image_size );
|
||||
__glXSendLargeCommand( gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + 4,
|
||||
data, image_size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage1DARB( GLenum target, GLint level,
|
||||
GLenum internal_format, GLsizei width,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
CompressedTexImage1D2D( target, level, internal_format, width, 0,
|
||||
border, image_size, data,
|
||||
X_GLrop_CompressedTexImage1D );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage2DARB( GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
CompressedTexImage1D2D( target, level, internal_format, width, height,
|
||||
border, image_size, data,
|
||||
X_GLrop_CompressedTexImage2D );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage3DARB( GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if ( gc->currentDpy == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE
|
||||
+ image_size );
|
||||
if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
|
||||
__GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexImage3D, cmdlen );
|
||||
__GLX_PUT_LONG( 4, target );
|
||||
__GLX_PUT_LONG( 8, level );
|
||||
__GLX_PUT_LONG( 12, internal_format );
|
||||
__GLX_PUT_LONG( 16, width );
|
||||
__GLX_PUT_LONG( 20, height );
|
||||
__GLX_PUT_LONG( 24, depth );
|
||||
__GLX_PUT_LONG( 28, border );
|
||||
__GLX_PUT_LONG( 32, image_size );
|
||||
if ( image_size != 0 ) {
|
||||
__GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE,
|
||||
data, image_size );
|
||||
}
|
||||
__GLX_END( cmdlen );
|
||||
}
|
||||
else {
|
||||
__GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexImage3D,
|
||||
cmdlen + 4 );
|
||||
__GLX_PUT_LONG( 8, target );
|
||||
__GLX_PUT_LONG( 12, level );
|
||||
__GLX_PUT_LONG( 16, internal_format );
|
||||
__GLX_PUT_LONG( 20, width );
|
||||
__GLX_PUT_LONG( 24, height );
|
||||
__GLX_PUT_LONG( 28, depth );
|
||||
__GLX_PUT_LONG( 32, border );
|
||||
__GLX_PUT_LONG( 36, image_size );
|
||||
__glXSendLargeCommand( gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + 4,
|
||||
data, image_size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage1DARB( GLenum target, GLint level,
|
||||
GLint xoffset,
|
||||
GLsizei width,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
CompressedTexSubImage1D2D( target, level, xoffset, 0, width, 0,
|
||||
format, image_size, data,
|
||||
X_GLrop_CompressedTexSubImage1D );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage2DARB( GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
CompressedTexSubImage1D2D( target, level, xoffset, yoffset, width, height,
|
||||
format, image_size, data,
|
||||
X_GLrop_CompressedTexSubImage2D );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage3DARB( GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid *data )
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if ( gc->currentDpy == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE
|
||||
+ image_size );
|
||||
if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
|
||||
__GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexSubImage3D, cmdlen );
|
||||
__GLX_PUT_LONG( 4, target );
|
||||
__GLX_PUT_LONG( 8, level );
|
||||
__GLX_PUT_LONG( 12, xoffset );
|
||||
__GLX_PUT_LONG( 16, yoffset );
|
||||
__GLX_PUT_LONG( 20, zoffset );
|
||||
__GLX_PUT_LONG( 24, width );
|
||||
__GLX_PUT_LONG( 28, height );
|
||||
__GLX_PUT_LONG( 32, depth );
|
||||
__GLX_PUT_LONG( 36, format );
|
||||
__GLX_PUT_LONG( 40, image_size );
|
||||
if ( image_size != 0 ) {
|
||||
__GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE,
|
||||
data, image_size );
|
||||
}
|
||||
__GLX_END( cmdlen );
|
||||
}
|
||||
else {
|
||||
__GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexSubImage3D,
|
||||
cmdlen + 4 );
|
||||
__GLX_PUT_LONG( 8, target );
|
||||
__GLX_PUT_LONG( 12, level );
|
||||
__GLX_PUT_LONG( 16, xoffset );
|
||||
__GLX_PUT_LONG( 20, yoffset );
|
||||
__GLX_PUT_LONG( 24, zoffset );
|
||||
__GLX_PUT_LONG( 28, width );
|
||||
__GLX_PUT_LONG( 32, height );
|
||||
__GLX_PUT_LONG( 36, depth );
|
||||
__GLX_PUT_LONG( 40, format );
|
||||
__GLX_PUT_LONG( 44, image_size );
|
||||
__glXSendLargeCommand( gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE + 4,
|
||||
data, image_size );
|
||||
}
|
||||
}
|
||||
308
src/glx/x11/indirect_vertex_array_priv.h
Normal file
308
src/glx/x11/indirect_vertex_array_priv.h
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* (C) Copyright IBM Corporation 2004, 2005
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM,
|
||||
* AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _INDIRECT_VA_PRIVATE_
|
||||
#define _INDIRECT_VA_PRIVATE_
|
||||
|
||||
/**
|
||||
* \file indirect_va_private.h
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include <GL/glxproto.h>
|
||||
|
||||
|
||||
/**
|
||||
* State descriptor for a single array of vertex data.
|
||||
*/
|
||||
struct array_state {
|
||||
/**
|
||||
* Pointer to the application supplied data.
|
||||
*/
|
||||
const void * data;
|
||||
|
||||
/**
|
||||
* Enum representing the type of the application supplied data.
|
||||
*/
|
||||
GLenum data_type;
|
||||
|
||||
/**
|
||||
* Stride value supplied by the application. This value is not used
|
||||
* internally. It is only kept so that it can be queried by the
|
||||
* application using glGet*v.
|
||||
*/
|
||||
GLsizei user_stride;
|
||||
|
||||
/**
|
||||
* Calculated size, in bytes, of a single element in the array. This
|
||||
* is calculated based on \c count and the size of the data type
|
||||
* represented by \c data_type.
|
||||
*/
|
||||
GLsizei element_size;
|
||||
|
||||
/**
|
||||
* Actual byte-stride from one element to the next. This value will
|
||||
* be equal to either \c user_stride or \c element_stride.
|
||||
*/
|
||||
GLsizei true_stride;
|
||||
|
||||
/**
|
||||
* Number of data values in each element.
|
||||
*/
|
||||
GLint count;
|
||||
|
||||
/**
|
||||
* "Normalized" data is on the range [0,1] (unsigned) or [-1,1] (signed).
|
||||
* This is used for mapping integral types to floating point types.
|
||||
*/
|
||||
GLboolean normalized;
|
||||
|
||||
/**
|
||||
* Pre-calculated GLX protocol command header.
|
||||
*/
|
||||
uint32_t header[2];
|
||||
|
||||
/**
|
||||
* Size of the header data. For simple data, like glColorPointerfv,
|
||||
* this is 4. For complex data that requires either a count (e.g.,
|
||||
* glWeightfvARB), an index (e.g., glVertexAttrib1fvARB), or a
|
||||
* selector enum (e.g., glMultiTexCoord2fv) this is 8.
|
||||
*/
|
||||
unsigned header_size;
|
||||
|
||||
/**
|
||||
* Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
|
||||
* to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean enabled;
|
||||
|
||||
/**
|
||||
* For multi-arrayed data (e.g., texture coordinates, generic vertex
|
||||
* program attributes, etc.), this specifies which array this is.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
/**
|
||||
* Per-array-type key. For most arrays, this will be the GL enum for
|
||||
* that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
|
||||
* for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
|
||||
* etc.).
|
||||
*/
|
||||
GLenum key;
|
||||
|
||||
/**
|
||||
* If this array can be used with the "classic" \c glDrawArrays protocol,
|
||||
* this is set to \c GL_TRUE. Otherwise, it is set to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean old_DrawArrays_possible;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Array state that is pushed / poped by \c glPushClientAttrib and
|
||||
* \c glPopClientAttrib.
|
||||
*/
|
||||
struct array_stack_state {
|
||||
/**
|
||||
* Pointer to the application supplied data.
|
||||
*/
|
||||
const void * data;
|
||||
|
||||
/**
|
||||
* Enum representing the type of the application supplied data.
|
||||
*/
|
||||
GLenum data_type;
|
||||
|
||||
/**
|
||||
* Stride value supplied by the application. This value is not used
|
||||
* internally. It is only kept so that it can be queried by the
|
||||
* application using glGet*v.
|
||||
*/
|
||||
GLsizei user_stride;
|
||||
|
||||
/**
|
||||
* Number of data values in each element.
|
||||
*/
|
||||
GLint count;
|
||||
|
||||
/**
|
||||
* Per-array-type key. For most arrays, this will be the GL enum for
|
||||
* that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
|
||||
* for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
|
||||
* etc.).
|
||||
*/
|
||||
GLenum key;
|
||||
|
||||
/**
|
||||
* For multi-arrayed data (e.g., texture coordinates, generic vertex
|
||||
* program attributes, etc.), this specifies which array this is.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
/**
|
||||
* Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
|
||||
* to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Collection of all the vertex array state.
|
||||
*/
|
||||
struct array_state_vector {
|
||||
/**
|
||||
* Number of arrays tracked by \c ::arrays.
|
||||
*/
|
||||
size_t num_arrays;
|
||||
|
||||
/**
|
||||
* Array of vertex array state. This array contains all of the valid
|
||||
* vertex arrays. If a vertex array isn't in this array, then it isn't
|
||||
* valid. For example, if an implementation does not support
|
||||
* EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
|
||||
* array.
|
||||
*/
|
||||
struct array_state * arrays;
|
||||
|
||||
/**
|
||||
* Number of currently enabled client-side arrays. The value of this
|
||||
* field is only valid if \c array_info_cache_valid is true.
|
||||
*/
|
||||
size_t enabled_client_array_count;
|
||||
|
||||
/**
|
||||
* \name ARRAY_INFO cache.
|
||||
*
|
||||
* These fields track the state of the ARRAY_INFO cache. The
|
||||
* \c array_info_cache_size is the size of the actual data stored in
|
||||
* \c array_info_cache. \c array_info_cache_buffer_size is the size of
|
||||
* the buffer. This will always be greater than or equal to
|
||||
* \c array_info_cache_size.
|
||||
*
|
||||
* \note
|
||||
* There are some bytes of extra data before \c array_info_cache that is
|
||||
* used to hold the header for RenderLarge commands. This is
|
||||
* \b not included in \c array_info_cache_size or
|
||||
* \c array_info_cache_buffer_size. \c array_info_cache_base stores a
|
||||
* pointer to the true start of the buffer (i.e., what malloc returned).
|
||||
*/
|
||||
/*@{*/
|
||||
size_t array_info_cache_size;
|
||||
size_t array_info_cache_buffer_size;
|
||||
void * array_info_cache;
|
||||
void * array_info_cache_base;
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* Is the cache of ARRAY_INFO data valid? The cache can become invalid
|
||||
* when one of several state changes occur. Among these chages are
|
||||
* modifying the array settings for an enabled array and enabling /
|
||||
* disabling an array.
|
||||
*/
|
||||
GLboolean array_info_cache_valid;
|
||||
|
||||
/**
|
||||
* Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol? Use
|
||||
* of this protocol is disabled with really old servers (i.e., servers
|
||||
* that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
|
||||
* variable is set.
|
||||
*
|
||||
* \todo
|
||||
* GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
|
||||
* opcodes for \c glDrawArrays. For servers that advertise one or the
|
||||
* other, there should be a way to select which opcode to use.
|
||||
*/
|
||||
GLboolean old_DrawArrays_possible;
|
||||
|
||||
/**
|
||||
* Is it possible to use the new GL X.X / ARB_vertex_buffer_object
|
||||
* protocol?
|
||||
*
|
||||
* \todo
|
||||
* This protocol has not yet been defined by the ARB, but is currently a
|
||||
* work in progress. This field is a place-holder.
|
||||
*/
|
||||
GLboolean new_DrawArrays_possible;
|
||||
|
||||
/**
|
||||
* Active texture unit set by \c glClientActiveTexture.
|
||||
*
|
||||
* \sa __glXGetActiveTextureUnit
|
||||
*/
|
||||
unsigned active_texture_unit;
|
||||
|
||||
/**
|
||||
* Number of supported texture units. Even if ARB_multitexture /
|
||||
* GL 1.3 are not supported, this will be at least 1. When multitexture
|
||||
* is supported, this will be the value queried by calling
|
||||
* \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
|
||||
*
|
||||
* \todo
|
||||
* Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
|
||||
* instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
|
||||
* NV_fragment_program are supported).
|
||||
*/
|
||||
unsigned num_texture_units;
|
||||
|
||||
/**
|
||||
* Number of generic vertex program attribs. If GL_ARB_vertex_program
|
||||
* is not supported, this will be zero. Otherwise it will be the value
|
||||
* queries by calling \c glGetProgramiv with \c GL_VERTEX_PROGRAM_ARB
|
||||
* and \c GL_MAX_PROGRAM_ATTRIBS_ARB.
|
||||
*/
|
||||
unsigned num_vertex_program_attribs;
|
||||
|
||||
/**
|
||||
* \n Methods for implementing various GL functions.
|
||||
*
|
||||
* These method pointers are only valid \c array_info_cache_valid is set.
|
||||
* When each function starts, it much check \c array_info_cache_valid.
|
||||
* If it is not set, it must call \c fill_array_info_cache and call
|
||||
* the new method.
|
||||
*
|
||||
* \sa fill_array_info_cache
|
||||
*
|
||||
* \todo
|
||||
* Write code to plug these functions directly into the dispatch table.
|
||||
*/
|
||||
/*@{*/
|
||||
void (*DrawArrays)( GLenum, GLint, GLsizei );
|
||||
void (*DrawElements)( GLenum mode, GLsizei count, GLenum type,
|
||||
const GLvoid *indices );
|
||||
/*@}*/
|
||||
|
||||
struct array_stack_state * stack;
|
||||
unsigned active_texture_unit_stack[ __GL_CLIENT_ATTRIB_STACK_DEPTH ];
|
||||
unsigned stack_index;
|
||||
};
|
||||
|
||||
#endif /* _INDIRECT_VA_PRIVATE_ */
|
||||
Loading…
Add table
Reference in a new issue