vl: rewrite vl DRI backend using XCB

v2: also set array_size of texture

Signed-off-by: Christian König <deathsimple@vodafone.de>
This commit is contained in:
Christian König 2012-02-23 11:13:57 +01:00
parent 6b024464e8
commit 80b40a4841
7 changed files with 148 additions and 859 deletions

View file

@ -1579,19 +1579,19 @@ if test "x$enable_gallium_g3dvl" = xyes; then
fi
if test "x$enable_xvmc" = xyes; then
PKG_CHECK_MODULES([XVMC], [xvmc >= 1.0.6])
PKG_CHECK_MODULES([XVMC], [xvmc >= 1.0.6 x11-xcb xcb-dri2 xcb-xfixes])
GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS xvmc"
HAVE_ST_XVMC="yes"
fi
if test "x$enable_vdpau" = xyes; then
PKG_CHECK_MODULES([VDPAU], [vdpau >= 0.4.1])
PKG_CHECK_MODULES([VDPAU], [vdpau >= 0.4.1 x11-xcb xcb-dri2 xcb-xfixes])
GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS vdpau"
HAVE_ST_VDPAU="yes"
fi
if test "x$enable_va" = xyes; then
PKG_CHECK_MODULES([LIBVA], [libva = 0.31.1])
PKG_CHECK_MODULES([LIBVA], [libva = 0.31.1 x11-xcb xcb-dri2 xcb-xfixes])
AC_MSG_WARN([vaapi state tracker currently unmaintained])
GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS va"
HAVE_ST_VA="yes"

View file

@ -11,7 +11,7 @@ INCLUDES = -I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/winsys/g3dvl \
$(DRIVER_INCLUDES)
DEFINES = -DGALLIUM_TRACE -DVER_MAJOR=$(VDPAU_MAJOR) -DVER_MINOR=$(VDPAU_MINOR) $(DRIVER_DEFINES)
LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lvdpau -lXext -lX11 -lm -lrt
LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lvdpau -lX11-xcb -lxcb-dri2 -lxcb-xfixes -lm -lrt
STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/vdpau/libvdpautracker.a
ifeq ($(MESA_LLVM),1)

View file

@ -11,7 +11,7 @@ INCLUDES = -I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/winsys/g3dvl \
$(DRIVER_INCLUDES)
DEFINES = -DGALLIUM_TRACE $(DRIVER_DEFINES)
LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lXv -lX11 -lm
LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lXv -lX11-xcb -lxcb-dri2 -lxcb-xfixes -lm
STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/xvmc/libxvmctracker.a
ifeq ($(MESA_LLVM),1)

View file

@ -7,7 +7,6 @@ LIBRARY_INCLUDES = -I$(TOP)/src/gallium/winsys/g3dvl \
$(shell $(PKG_CONFIG) libdrm --cflags-only-I)
C_SOURCES = \
dri2.c \
dri_winsys.c
include ../../../Makefile.template

View file

@ -1,666 +0,0 @@
/*
* 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 <stdio.h>
#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/dri2proto.h>
#include "xf86drm.h"
#include "dri2.h"
#if 0
#include "glxclient.h"
#include "GL/glxext.h"
#endif
/* Allow the build to work with an older versions of dri2proto.h and
* dri2tokens.h.
*/
#if DRI2_MINOR < 1
#undef DRI2_MINOR
#define DRI2_MINOR 1
#define X_DRI2GetBuffersWithFormat 7
#endif
static char dri2ExtensionName[] = DRI2_NAME;
static XExtensionInfo *dri2Info;
static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
static Status
DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
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 */
DRI2WireToEvent, /* wire_to_event */
DRI2EventToWire, /* event_to_wire */
NULL, /* error */
NULL, /* error_string */
};
static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
dri2Info,
dri2ExtensionName,
&dri2ExtensionHooks,
0, NULL)
static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
{
#if 0
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
XExtDisplayInfo *glx_info = __glXFindDisplay(dpy);
XextCheckExtension(dpy, info, dri2ExtensionName, False);
switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
#ifdef X_DRI2SwapBuffers
case DRI2_BufferSwapComplete:
{
GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->type =
(glx_info->codes->first_event + GLX_BufferSwapComplete) & 0x75;
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->drawable = awire->drawable;
switch (awire->event_type) {
case DRI2_EXCHANGE_COMPLETE:
aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
break;
case DRI2_BLIT_COMPLETE:
aevent->event_type = GLX_BLIT_COMPLETE_INTEL;
break;
case DRI2_FLIP_COMPLETE:
aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
break;
default:
/* unknown swap completion type */
return False;
}
aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
return True;
}
#endif
#ifdef DRI2_InvalidateBuffers
case DRI2_InvalidateBuffers:
{
xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
dri2InvalidateBuffers(dpy, awire->drawable);
return False;
}
#endif
default:
/* client doesn't support server event */
break;
}
#endif
return False;
}
/* We don't actually support this. It doesn't make sense for clients to
* send each other DRI2 events.
*/
static Status
DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
XextCheckExtension(dpy, info, dri2ExtensionName, False);
switch (event->type) {
default:
/* client doesn't support server event */
break;
}
return Success;
}
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;
int i, nevents;
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();
switch (rep.minorVersion) {
case 1:
nevents = 0;
break;
case 2:
nevents = 1;
break;
case 3:
default:
nevents = 2;
break;
}
for (i = 0; i < nevents; i++) {
XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
}
return True;
}
Bool
DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
{
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->window = window;
req->driverType = DRI2DriverDRI;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*driverName = Xmalloc(rep.driverNameLength + 1);
if (*driverName == NULL) {
_XEatData(dpy,
((rep.driverNameLength + 3) & ~3) +
((rep.deviceNameLength + 3) & ~3));
UnlockDisplay(dpy);
SyncHandle();
return False;
}
_XReadPad(dpy, *driverName, rep.driverNameLength);
(*driverName)[rep.driverNameLength] = '\0';
*deviceName = Xmalloc(rep.deviceNameLength + 1);
if (*deviceName == NULL) {
Xfree(*driverName);
_XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
UnlockDisplay(dpy);
SyncHandle();
return False;
}
_XReadPad(dpy, *deviceName, rep.deviceNameLength);
(*deviceName)[rep.deviceNameLength] = '\0';
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Bool
DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2AuthenticateReq *req;
xDRI2AuthenticateReply rep;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2Authenticate, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2Authenticate;
req->window = window;
req->magic = magic;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.authenticated;
}
void
DRI2CreateDrawable(Display * dpy, XID drawable)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2CreateDrawableReq *req;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2CreateDrawable, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2CreateDrawable;
req->drawable = drawable;
UnlockDisplay(dpy);
SyncHandle();
}
void
DRI2DestroyDrawable(Display * dpy, XID drawable)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2DestroyDrawableReq *req;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
XSync(dpy, False);
LockDisplay(dpy);
GetReq(DRI2DestroyDrawable, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2DestroyDrawable;
req->drawable = drawable;
UnlockDisplay(dpy);
SyncHandle();
}
DRI2Buffer *
DRI2GetBuffers(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count, int *outCount)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetBuffersReply rep;
xDRI2GetBuffersReq *req;
DRI2Buffer *buffers;
xDRI2Buffer repBuffer;
CARD32 *p;
int i;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReqExtra(DRI2GetBuffers, count * 4, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetBuffers;
req->drawable = drawable;
req->count = count;
p = (CARD32 *) & req[1];
for (i = 0; i < count; i++)
p[i] = attachments[i];
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
*width = rep.width;
*height = rep.height;
*outCount = rep.count;
buffers = Xmalloc(rep.count * sizeof buffers[0]);
if (buffers == NULL) {
_XEatData(dpy, rep.count * sizeof repBuffer);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
for (i = 0; i < rep.count; i++) {
_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
buffers[i].attachment = repBuffer.attachment;
buffers[i].name = repBuffer.name;
buffers[i].pitch = repBuffer.pitch;
buffers[i].cpp = repBuffer.cpp;
buffers[i].flags = repBuffer.flags;
}
UnlockDisplay(dpy);
SyncHandle();
return buffers;
}
DRI2Buffer *
DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count, int *outCount)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetBuffersReply rep;
xDRI2GetBuffersReq *req;
DRI2Buffer *buffers;
xDRI2Buffer repBuffer;
CARD32 *p;
int i;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetBuffersWithFormat;
req->drawable = drawable;
req->count = count;
p = (CARD32 *) & req[1];
for (i = 0; i < (count * 2); i++)
p[i] = attachments[i];
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
*width = rep.width;
*height = rep.height;
*outCount = rep.count;
buffers = Xmalloc(rep.count * sizeof buffers[0]);
if (buffers == NULL) {
_XEatData(dpy, rep.count * sizeof repBuffer);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
for (i = 0; i < rep.count; i++) {
_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
buffers[i].attachment = repBuffer.attachment;
buffers[i].name = repBuffer.name;
buffers[i].pitch = repBuffer.pitch;
buffers[i].cpp = repBuffer.cpp;
buffers[i].flags = repBuffer.flags;
}
UnlockDisplay(dpy);
SyncHandle();
return buffers;
}
void
DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
CARD32 dest, CARD32 src)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2CopyRegionReq *req;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2CopyRegion, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2CopyRegion;
req->drawable = drawable;
req->region = region;
req->dest = dest;
req->src = src;
UnlockDisplay(dpy);
SyncHandle();
}
#ifdef X_DRI2SwapBuffers
static void
load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
CARD64 remainder)
{
req->target_msc_hi = target >> 32;
req->target_msc_lo = target & 0xffffffff;
req->divisor_hi = divisor >> 32;
req->divisor_lo = divisor & 0xffffffff;
req->remainder_hi = remainder >> 32;
req->remainder_lo = remainder & 0xffffffff;
}
static CARD64
vals_to_card64(CARD32 lo, CARD32 hi)
{
return (CARD64)hi << 32 | lo;
}
void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
CARD64 divisor, CARD64 remainder, CARD64 *count)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2SwapBuffersReq *req;
xDRI2SwapBuffersReply rep;
XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2SwapBuffers, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2SwapBuffers;
req->drawable = drawable;
load_swap_req(req, target_msc, divisor, remainder);
_XReply(dpy, (xReply *)&rep, 0, xFalse);
*count = vals_to_card64(rep.swap_lo, rep.swap_hi);
UnlockDisplay(dpy);
SyncHandle();
}
#endif
#ifdef X_DRI2GetMSC
Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
CARD64 *sbc)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetMSCReq *req;
xDRI2MSCReply rep;
XextCheckExtension (dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2GetMSC, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetMSC;
req->drawable = drawable;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
*msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
*sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
UnlockDisplay(dpy);
SyncHandle();
return True;
}
#endif
#ifdef X_DRI2WaitMSC
static void
load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
CARD64 remainder)
{
req->target_msc_hi = target >> 32;
req->target_msc_lo = target & 0xffffffff;
req->divisor_hi = divisor >> 32;
req->divisor_lo = divisor & 0xffffffff;
req->remainder_hi = remainder >> 32;
req->remainder_lo = remainder & 0xffffffff;
}
Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2WaitMSCReq *req;
xDRI2MSCReply rep;
XextCheckExtension (dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2WaitMSC, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2WaitMSC;
req->drawable = drawable;
load_msc_req(req, target_msc, divisor, remainder);
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
*msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
*sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
#endif
#ifdef X_DRI2WaitSBC
static void
load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
{
req->target_sbc_hi = target >> 32;
req->target_sbc_lo = target & 0xffffffff;
}
Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
CARD64 *msc, CARD64 *sbc)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2WaitSBCReq *req;
xDRI2MSCReply rep;
XextCheckExtension (dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2WaitSBC, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2WaitSBC;
req->drawable = drawable;
load_sbc_req(req, target_sbc);
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
*msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
*sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
#endif
#ifdef X_DRI2SwapInterval
void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2SwapIntervalReq *req;
XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2SwapInterval, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2SwapInterval;
req->drawable = drawable;
req->interval = interval;
UnlockDisplay(dpy);
SyncHandle();
}
#endif

View file

@ -1,106 +0,0 @@
/*
* 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_
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/dri2tokens.h>
typedef struct
{
unsigned int attachment;
unsigned int name;
unsigned int pitch;
unsigned int cpp;
unsigned int flags;
} DRI2Buffer;
extern Bool
DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
extern Bool
DRI2QueryVersion(Display * display, int *major, int *minor);
extern Bool
DRI2Connect(Display * display, XID window,
char **driverName, char **deviceName);
extern Bool
DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
extern void
DRI2CreateDrawable(Display * display, XID drawable);
extern void
DRI2DestroyDrawable(Display * display, XID handle);
extern DRI2Buffer*
DRI2GetBuffers(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count,
int *outCount);
/**
* \note
* This function is only supported with DRI2 version 1.1 or later.
*/
extern DRI2Buffer*
DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments,
int count, int *outCount);
extern void
DRI2CopyRegion(Display * dpy, XID drawable,
XserverRegion region,
CARD32 dest, CARD32 src);
extern void
DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
CARD64 remainder, CARD64 *count);
extern Bool
DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
extern Bool
DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
extern Bool
DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
CARD64 *msc, CARD64 *sbc);
extern void
DRI2SwapInterval(Display *dpy, XID drawable, int interval);
#endif

View file

@ -29,8 +29,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <X11/Xlibint.h>
#include <X11/extensions/dri2tokens.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xfixes.h>
#include <xcb/dri2.h>
#include <xf86drm.h>
#include "pipe/p_screen.h"
@ -44,14 +45,16 @@
#include "util/u_inlines.h"
#include "vl_winsys.h"
#include "dri2.h"
struct vl_dri_screen
{
struct vl_screen base;
Display *display;
struct util_hash_table *drawable_table;
Drawable last_seen_drawable;
xcb_connection_t *conn;
xcb_drawable_t drawable;
xcb_xfixes_region_t region;
bool flushed;
xcb_dri2_copy_region_cookie_t flush_cookie;
};
static void
@ -60,67 +63,93 @@ vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
unsigned level, unsigned layer,
void *context_private)
{
struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)context_private;
XserverRegion region;
struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private;
assert(screen);
assert(resource);
assert(context_private);
region = XFixesCreateRegionFromWindow(vl_dri_scrn->display, vl_dri_scrn->last_seen_drawable, WindowRegionBounding);
DRI2CopyRegion(vl_dri_scrn->display, vl_dri_scrn->last_seen_drawable, region,
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
XFixesDestroyRegion(vl_dri_scrn->display, region);
if (scrn->flushed)
free(xcb_dri2_copy_region_reply(scrn->conn, scrn->flush_cookie, NULL));
else
scrn->flushed = true;
scrn->flush_cookie = xcb_dri2_copy_region_unchecked(scrn->conn, scrn->drawable, scrn->region,
XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
}
static void
vl_dri2_destroy_drawable(struct vl_dri_screen *scrn)
{
xcb_void_cookie_t destroy_cookie;
if (scrn->drawable) {
destroy_cookie = xcb_dri2_destroy_drawable_checked(scrn->conn, scrn->drawable);
/* ignore any error here, since the drawable can be destroyed long ago */
free(xcb_request_check(scrn->conn, destroy_cookie));
}
}
struct pipe_resource*
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable)
{
struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
unsigned int attachments[1] = {DRI2BufferFrontLeft};
static const unsigned int attachments[1] = { XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT };
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
struct winsys_handle dri2_front_handle;
struct pipe_resource template, *tex;
DRI2Buffer *dri2_front;
int w, h, count;
assert(vl_dri_scrn);
xcb_dri2_get_buffers_cookie_t cookie;
xcb_dri2_get_buffers_reply_t *reply;
xcb_dri2_dri2_buffer_t *buffers;
if (vl_dri_scrn->last_seen_drawable != drawable) {
/* Hash table business depends on this equality */
assert(None == NULL);
Drawable lookup_drawable = (Drawable)util_hash_table_get(vl_dri_scrn->drawable_table, (void*)drawable);
if (lookup_drawable == None) {
DRI2CreateDrawable(vl_dri_scrn->display, drawable);
util_hash_table_set(vl_dri_scrn->drawable_table, (void*)drawable, (void*)drawable);
}
vl_dri_scrn->last_seen_drawable = drawable;
assert(scrn);
if (scrn->drawable != drawable) {
vl_dri2_destroy_drawable(scrn);
xcb_dri2_create_drawable(scrn->conn, drawable);
scrn->drawable = drawable;
}
dri2_front = DRI2GetBuffers(vl_dri_scrn->display, drawable, &w, &h, attachments, 1, &count);
if (scrn->region)
xcb_xfixes_destroy_region(scrn->conn, scrn->region);
else
scrn->region = xcb_generate_id(scrn->conn);
assert(count == 1);
xcb_xfixes_create_region_from_window(scrn->conn, scrn->region, drawable, XCB_SHAPE_SK_BOUNDING);
if (!dri2_front)
cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, drawable, 1, 1, attachments);
reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL);
if (!reply)
return NULL;
buffers = xcb_dri2_get_buffers_buffers(reply);
if (!buffers) {
free(reply);
return NULL;
}
assert(reply->count == 1);
memset(&dri2_front_handle, 0, sizeof(dri2_front_handle));
dri2_front_handle.type = DRM_API_HANDLE_TYPE_SHARED;
dri2_front_handle.handle = dri2_front->name;
dri2_front_handle.stride = dri2_front->pitch;
dri2_front_handle.handle = buffers[0].name;
dri2_front_handle.stride = buffers[0].pitch;
memset(&template, 0, sizeof(template));
template.target = PIPE_TEXTURE_2D;
template.format = PIPE_FORMAT_B8G8R8X8_UNORM;
template.last_level = 0;
template.width0 = w;
template.height0 = h;
template.width0 = reply->width;
template.height0 = reply->height;
template.depth0 = 1;
template.array_size = 1;
template.usage = PIPE_USAGE_STATIC;
template.bind = PIPE_BIND_RENDER_TARGET;
template.flags = 0;
tex = vl_dri_scrn->base.pscreen->resource_from_handle(vl_dri_scrn->base.pscreen, &template, &dri2_front_handle);
Xfree(dri2_front);
tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &template, &dri2_front_handle);
free(reply);
return tex;
}
@ -131,44 +160,67 @@ vl_screen_get_private(struct vl_screen *vscreen)
return vscreen;
}
static unsigned drawable_hash(void *key)
{
Drawable drawable = (Drawable)key;
assert(drawable != None);
return util_hash_crc32(&drawable, sizeof(Drawable));
}
static int drawable_cmp(void *key1, void *key2)
{
Drawable d1 = (Drawable)key1;
Drawable d2 = (Drawable)key2;
assert(d1 != None);
assert(d2 != None);
return d1 != d2;
}
struct vl_screen*
vl_screen_create(Display *display, int screen)
{
struct vl_dri_screen *vl_dri_scrn;
drm_magic_t magic;
char *drvName;
char *devName;
struct vl_dri_screen *scrn;
const xcb_query_extension_reply_t *extension;
xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
xcb_xfixes_query_version_reply_t *xfixes_query = NULL;
xcb_dri2_query_version_cookie_t dri2_query_cookie;
xcb_dri2_query_version_reply_t *dri2_query = NULL;
xcb_dri2_connect_cookie_t connect_cookie;
xcb_dri2_connect_reply_t *connect = NULL;
xcb_dri2_authenticate_cookie_t authenticate_cookie;
xcb_dri2_authenticate_reply_t *authenticate = NULL;
xcb_screen_iterator_t s;
xcb_generic_error_t *error = NULL;
char *device_name;
int fd;
drm_magic_t magic;
assert(display);
vl_dri_scrn = CALLOC_STRUCT(vl_dri_screen);
if (!vl_dri_scrn)
goto no_struct;
scrn = CALLOC_STRUCT(vl_dri_screen);
if (!scrn)
return NULL;
vl_dri_scrn->display = display;
if (!DRI2Connect(display, XRootWindow(display, screen), &drvName, &devName))
scrn->conn = XGetXCBConnection(display);
if (!scrn->conn)
goto free_screen;
fd = open(devName, O_RDWR);
Xfree(drvName);
Xfree(devName);
xcb_prefetch_extension_data(scrn->conn, &xcb_xfixes_id);
xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id);
extension = xcb_get_extension_data(scrn->conn, &xcb_xfixes_id);
if (!(extension && extension->present))
goto free_screen;
extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id);
if (!(extension && extension->present))
goto free_screen;
xfixes_query_cookie = xcb_xfixes_query_version(scrn->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
xfixes_query = xcb_xfixes_query_version_reply (scrn->conn, xfixes_query_cookie, &error);
if (xfixes_query == NULL || error != NULL || xfixes_query->major_version < 2)
goto free_screen;
dri2_query_cookie = xcb_dri2_query_version (scrn->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION);
dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error);
if (dri2_query == NULL || error != NULL)
goto free_screen;
s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn));
connect_cookie = xcb_dri2_connect_unchecked(scrn->conn, s.data->root, XCB_DRI2_DRIVER_TYPE_DRI);
connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL);
if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0)
goto free_screen;
device_name = xcb_dri2_connect_device_name(connect);
device_name = strndup(device_name, xcb_dri2_connect_device_name_length(connect));
fd = open(device_name, O_RDWR);
free(device_name);
if (fd < 0)
goto free_screen;
@ -176,38 +228,48 @@ vl_screen_create(Display *display, int screen)
if (drmGetMagic(fd, &magic))
goto free_screen;
if (!DRI2Authenticate(display, RootWindow(display, screen), magic))
authenticate_cookie = xcb_dri2_authenticate_unchecked(scrn->conn, s.data->root, magic);
authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL);
if (authenticate == NULL || !authenticate->authenticated)
goto free_screen;
vl_dri_scrn->base.pscreen = driver_descriptor.create_screen(fd);
if (!vl_dri_scrn->base.pscreen)
scrn->base.pscreen = driver_descriptor.create_screen(fd);
if (!scrn->base.pscreen)
goto free_screen;
vl_dri_scrn->drawable_table = util_hash_table_create(&drawable_hash, &drawable_cmp);
if (!vl_dri_scrn->drawable_table)
goto no_hash;
scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
vl_dri_scrn->last_seen_drawable = None;
vl_dri_scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
free(xfixes_query);
free(dri2_query);
free(connect);
free(authenticate);
return &vl_dri_scrn->base;
return &scrn->base;
no_hash:
vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
free_screen:
FREE(vl_dri_scrn);
no_struct:
FREE(scrn);
free(xfixes_query);
free(dri2_query);
free(connect);
free(authenticate);
free(error);
return NULL;
}
void vl_screen_destroy(struct vl_screen *vscreen)
{
struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
assert(vscreen);
util_hash_table_destroy(vl_dri_scrn->drawable_table);
vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
FREE(vl_dri_scrn);
if (scrn->flushed)
free(xcb_dri2_copy_region_reply(scrn->conn, scrn->flush_cookie, NULL));
if (scrn->region)
xcb_xfixes_destroy_region(scrn->conn, scrn->region);
vl_dri2_destroy_drawable(scrn);
scrn->base.pscreen->destroy(scrn->base.pscreen);
FREE(scrn);
}