826 lines
22 KiB
C
826 lines
22 KiB
C
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/Xproto.h>
|
|
#include "misc.h"
|
|
#include "os.h"
|
|
#include "dixstruct.h"
|
|
#include "resource.h"
|
|
#include "scrnintstr.h"
|
|
#include "extnsionst.h"
|
|
#include "extinit.h"
|
|
#include "servermd.h"
|
|
#include <X11/Xfuncproto.h>
|
|
#include "xvdix.h"
|
|
#include <X11/extensions/XvMC.h>
|
|
#include <X11/extensions/Xvproto.h>
|
|
#include <X11/extensions/XvMCproto.h>
|
|
#include "xvmcext.h"
|
|
#include "protocol-versions.h"
|
|
|
|
#ifdef HAS_XVMCSHM
|
|
#include <sys/ipc.h>
|
|
#include <sys/types.h>
|
|
#include <sys/shm.h>
|
|
#endif /* HAS_XVMCSHM */
|
|
|
|
#define DR_CLIENT_DRIVER_NAME_SIZE 48
|
|
#define DR_BUSID_SIZE 48
|
|
|
|
static DevPrivateKeyRec XvMCScreenKeyRec;
|
|
|
|
#define XvMCScreenKey (&XvMCScreenKeyRec)
|
|
static Bool XvMCInUse;
|
|
|
|
int XvMCReqCode;
|
|
int XvMCEventBase;
|
|
|
|
static RESTYPE XvMCRTContext;
|
|
static RESTYPE XvMCRTSurface;
|
|
static RESTYPE XvMCRTSubpicture;
|
|
|
|
int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr) = NULL;
|
|
|
|
typedef struct {
|
|
int num_adaptors;
|
|
XvMCAdaptorPtr adaptors;
|
|
CloseScreenProcPtr CloseScreen;
|
|
char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE];
|
|
char busID[DR_BUSID_SIZE];
|
|
int major;
|
|
int minor;
|
|
int patchLevel;
|
|
} XvMCScreenRec, *XvMCScreenPtr;
|
|
|
|
#define XVMC_GET_PRIVATE(pScreen) \
|
|
(XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey))
|
|
|
|
static int
|
|
XvMCDestroyContextRes(void *data, XID id)
|
|
{
|
|
XvMCContextPtr pContext = (XvMCContextPtr) data;
|
|
|
|
pContext->refcnt--;
|
|
|
|
if (!pContext->refcnt) {
|
|
XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
|
|
|
|
(*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext) (pContext);
|
|
free(pContext);
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
XvMCDestroySurfaceRes(void *data, XID id)
|
|
{
|
|
XvMCSurfacePtr pSurface = (XvMCSurfacePtr) data;
|
|
XvMCContextPtr pContext = pSurface->context;
|
|
XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
|
|
|
|
(*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface) (pSurface);
|
|
free(pSurface);
|
|
|
|
XvMCDestroyContextRes((void *) pContext, pContext->context_id);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
XvMCDestroySubpictureRes(void *data, XID id)
|
|
{
|
|
XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr) data;
|
|
XvMCContextPtr pContext = pSubpict->context;
|
|
XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
|
|
|
|
(*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture) (pSubpict);
|
|
free(pSubpict);
|
|
|
|
XvMCDestroyContextRes((void *) pContext, pContext->context_id);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCQueryVersion(ClientPtr client)
|
|
{
|
|
xvmcQueryVersionReply rep = {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = 0,
|
|
.major = SERVER_XVMC_MAJOR_VERSION,
|
|
.minor = SERVER_XVMC_MINOR_VERSION
|
|
};
|
|
|
|
/* REQUEST(xvmcQueryVersionReq); */
|
|
REQUEST_SIZE_MATCH(xvmcQueryVersionReq);
|
|
|
|
WriteToClient(client, sizeof(xvmcQueryVersionReply), &rep);
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCListSurfaceTypes(ClientPtr client)
|
|
{
|
|
XvPortPtr pPort;
|
|
int i;
|
|
XvMCScreenPtr pScreenPriv;
|
|
xvmcListSurfaceTypesReply rep;
|
|
xvmcSurfaceInfo info;
|
|
XvMCAdaptorPtr adaptor = NULL;
|
|
XvMCSurfaceInfoPtr surface;
|
|
int num_surfaces;
|
|
|
|
REQUEST(xvmcListSurfaceTypesReq);
|
|
REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq);
|
|
|
|
VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
|
|
|
|
if (XvMCInUse) { /* any adaptors at all */
|
|
ScreenPtr pScreen = pPort->pAdaptor->pScreen;
|
|
|
|
if ((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */
|
|
for (i = 0; i < pScreenPriv->num_adaptors; i++) {
|
|
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
|
|
adaptor = &(pScreenPriv->adaptors[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
num_surfaces = (adaptor) ? adaptor->num_surfaces : 0;
|
|
rep = (xvmcListSurfaceTypesReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.num = num_surfaces,
|
|
.length = bytes_to_int32(num_surfaces * sizeof(xvmcSurfaceInfo)),
|
|
};
|
|
|
|
WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), &rep);
|
|
|
|
for (i = 0; i < num_surfaces; i++) {
|
|
surface = adaptor->surfaces[i];
|
|
info.surface_type_id = surface->surface_type_id;
|
|
info.chroma_format = surface->chroma_format;
|
|
info.max_width = surface->max_width;
|
|
info.max_height = surface->max_height;
|
|
info.subpicture_max_width = surface->subpicture_max_width;
|
|
info.subpicture_max_height = surface->subpicture_max_height;
|
|
info.mc_type = surface->mc_type;
|
|
info.flags = surface->flags;
|
|
WriteToClient(client, sizeof(xvmcSurfaceInfo), &info);
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCCreateContext(ClientPtr client)
|
|
{
|
|
XvPortPtr pPort;
|
|
CARD32 *data = NULL;
|
|
int dwords = 0;
|
|
int i, result, adapt_num = -1;
|
|
ScreenPtr pScreen;
|
|
XvMCContextPtr pContext;
|
|
XvMCScreenPtr pScreenPriv;
|
|
XvMCAdaptorPtr adaptor = NULL;
|
|
XvMCSurfaceInfoPtr surface = NULL;
|
|
xvmcCreateContextReply rep;
|
|
|
|
REQUEST(xvmcCreateContextReq);
|
|
REQUEST_SIZE_MATCH(xvmcCreateContextReq);
|
|
|
|
VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
|
|
|
|
pScreen = pPort->pAdaptor->pScreen;
|
|
|
|
if (!XvMCInUse) /* no XvMC adaptors */
|
|
return BadMatch;
|
|
|
|
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */
|
|
return BadMatch;
|
|
|
|
for (i = 0; i < pScreenPriv->num_adaptors; i++) {
|
|
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
|
|
adaptor = &(pScreenPriv->adaptors[i]);
|
|
adapt_num = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (adapt_num < 0) /* none this port */
|
|
return BadMatch;
|
|
|
|
for (i = 0; i < adaptor->num_surfaces; i++) {
|
|
if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
|
|
surface = adaptor->surfaces[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* adaptor doesn't support this suface_type_id */
|
|
if (!surface)
|
|
return BadMatch;
|
|
|
|
if ((stuff->width > surface->max_width) ||
|
|
(stuff->height > surface->max_height))
|
|
return BadValue;
|
|
|
|
if (!(pContext = malloc(sizeof(XvMCContextRec)))) {
|
|
return BadAlloc;
|
|
}
|
|
|
|
pContext->pScreen = pScreen;
|
|
pContext->adapt_num = adapt_num;
|
|
pContext->context_id = stuff->context_id;
|
|
pContext->surface_type_id = stuff->surface_type_id;
|
|
pContext->width = stuff->width;
|
|
pContext->height = stuff->height;
|
|
pContext->flags = stuff->flags;
|
|
pContext->refcnt = 1;
|
|
|
|
result = (*adaptor->CreateContext) (pPort, pContext, &dwords, &data);
|
|
|
|
if (result != Success) {
|
|
free(pContext);
|
|
return result;
|
|
}
|
|
if (!AddResource(pContext->context_id, XvMCRTContext, pContext)) {
|
|
free(data);
|
|
return BadAlloc;
|
|
}
|
|
|
|
rep = (xvmcCreateContextReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = dwords,
|
|
.width_actual = pContext->width,
|
|
.height_actual = pContext->height,
|
|
.flags_return = pContext->flags
|
|
};
|
|
|
|
WriteToClient(client, sizeof(xvmcCreateContextReply), &rep);
|
|
if (dwords)
|
|
WriteToClient(client, dwords << 2, data);
|
|
|
|
free(data);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCDestroyContext(ClientPtr client)
|
|
{
|
|
void *val;
|
|
int rc;
|
|
|
|
REQUEST(xvmcDestroyContextReq);
|
|
REQUEST_SIZE_MATCH(xvmcDestroyContextReq);
|
|
|
|
rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext,
|
|
client, DixDestroyAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
FreeResource(stuff->context_id, RT_NONE);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCCreateSurface(ClientPtr client)
|
|
{
|
|
CARD32 *data = NULL;
|
|
int dwords = 0;
|
|
int result;
|
|
XvMCContextPtr pContext;
|
|
XvMCSurfacePtr pSurface;
|
|
XvMCScreenPtr pScreenPriv;
|
|
xvmcCreateSurfaceReply rep;
|
|
|
|
REQUEST(xvmcCreateSurfaceReq);
|
|
REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq);
|
|
|
|
result = dixLookupResourceByType((void **) &pContext, stuff->context_id,
|
|
XvMCRTContext, client, DixUseAccess);
|
|
if (result != Success)
|
|
return result;
|
|
|
|
pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
|
|
|
|
if (!(pSurface = malloc(sizeof(XvMCSurfaceRec))))
|
|
return BadAlloc;
|
|
|
|
pSurface->surface_id = stuff->surface_id;
|
|
pSurface->surface_type_id = pContext->surface_type_id;
|
|
pSurface->context = pContext;
|
|
|
|
result =
|
|
(*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface) (pSurface,
|
|
&dwords,
|
|
&data);
|
|
|
|
if (result != Success) {
|
|
free(pSurface);
|
|
return result;
|
|
}
|
|
if (!AddResource(pSurface->surface_id, XvMCRTSurface, pSurface)) {
|
|
free(data);
|
|
return BadAlloc;
|
|
}
|
|
|
|
rep = (xvmcCreateSurfaceReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = dwords
|
|
};
|
|
|
|
WriteToClient(client, sizeof(xvmcCreateSurfaceReply), &rep);
|
|
if (dwords)
|
|
WriteToClient(client, dwords << 2, data);
|
|
|
|
free(data);
|
|
|
|
pContext->refcnt++;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCDestroySurface(ClientPtr client)
|
|
{
|
|
void *val;
|
|
int rc;
|
|
|
|
REQUEST(xvmcDestroySurfaceReq);
|
|
REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq);
|
|
|
|
rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface,
|
|
client, DixDestroyAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
FreeResource(stuff->surface_id, RT_NONE);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCCreateSubpicture(ClientPtr client)
|
|
{
|
|
Bool image_supported = FALSE;
|
|
CARD32 *data = NULL;
|
|
int i, result, dwords = 0;
|
|
XvMCContextPtr pContext;
|
|
XvMCSubpicturePtr pSubpicture;
|
|
XvMCScreenPtr pScreenPriv;
|
|
xvmcCreateSubpictureReply rep;
|
|
XvMCAdaptorPtr adaptor;
|
|
XvMCSurfaceInfoPtr surface = NULL;
|
|
|
|
REQUEST(xvmcCreateSubpictureReq);
|
|
REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq);
|
|
|
|
result = dixLookupResourceByType((void **) &pContext, stuff->context_id,
|
|
XvMCRTContext, client, DixUseAccess);
|
|
if (result != Success)
|
|
return result;
|
|
|
|
pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
|
|
|
|
adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]);
|
|
|
|
/* find which surface this context supports */
|
|
for (i = 0; i < adaptor->num_surfaces; i++) {
|
|
if (adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id) {
|
|
surface = adaptor->surfaces[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!surface)
|
|
return BadMatch;
|
|
|
|
/* make sure this surface supports that xvimage format */
|
|
if (!surface->compatible_subpictures)
|
|
return BadMatch;
|
|
|
|
for (i = 0; i < surface->compatible_subpictures->num_xvimages; i++) {
|
|
if (surface->compatible_subpictures->xvimage_ids[i] ==
|
|
stuff->xvimage_id) {
|
|
image_supported = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!image_supported)
|
|
return BadMatch;
|
|
|
|
/* make sure the size is OK */
|
|
if ((stuff->width > surface->subpicture_max_width) ||
|
|
(stuff->height > surface->subpicture_max_height))
|
|
return BadValue;
|
|
|
|
if (!(pSubpicture = malloc(sizeof(XvMCSubpictureRec))))
|
|
return BadAlloc;
|
|
|
|
pSubpicture->subpicture_id = stuff->subpicture_id;
|
|
pSubpicture->xvimage_id = stuff->xvimage_id;
|
|
pSubpicture->width = stuff->width;
|
|
pSubpicture->height = stuff->height;
|
|
pSubpicture->num_palette_entries = 0; /* overwritten by DDX */
|
|
pSubpicture->entry_bytes = 0; /* overwritten by DDX */
|
|
pSubpicture->component_order[0] = 0; /* overwritten by DDX */
|
|
pSubpicture->component_order[1] = 0;
|
|
pSubpicture->component_order[2] = 0;
|
|
pSubpicture->component_order[3] = 0;
|
|
pSubpicture->context = pContext;
|
|
|
|
result =
|
|
(*pScreenPriv->adaptors[pContext->adapt_num].
|
|
CreateSubpicture) (pSubpicture, &dwords, &data);
|
|
|
|
if (result != Success) {
|
|
free(pSubpicture);
|
|
return result;
|
|
}
|
|
if (!AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture)) {
|
|
free(data);
|
|
return BadAlloc;
|
|
}
|
|
|
|
rep = (xvmcCreateSubpictureReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = dwords,
|
|
.width_actual = pSubpicture->width,
|
|
.height_actual = pSubpicture->height,
|
|
.num_palette_entries = pSubpicture->num_palette_entries,
|
|
.entry_bytes = pSubpicture->entry_bytes,
|
|
.component_order[0] = pSubpicture->component_order[0],
|
|
.component_order[1] = pSubpicture->component_order[1],
|
|
.component_order[2] = pSubpicture->component_order[2],
|
|
.component_order[3] = pSubpicture->component_order[3]
|
|
};
|
|
|
|
WriteToClient(client, sizeof(xvmcCreateSubpictureReply), &rep);
|
|
if (dwords)
|
|
WriteToClient(client, dwords << 2, data);
|
|
|
|
free(data);
|
|
|
|
pContext->refcnt++;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCDestroySubpicture(ClientPtr client)
|
|
{
|
|
void *val;
|
|
int rc;
|
|
|
|
REQUEST(xvmcDestroySubpictureReq);
|
|
REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq);
|
|
|
|
rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture,
|
|
client, DixDestroyAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
FreeResource(stuff->subpicture_id, RT_NONE);
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCListSubpictureTypes(ClientPtr client)
|
|
{
|
|
XvPortPtr pPort;
|
|
xvmcListSubpictureTypesReply rep;
|
|
XvMCScreenPtr pScreenPriv;
|
|
ScreenPtr pScreen;
|
|
XvMCAdaptorPtr adaptor = NULL;
|
|
XvMCSurfaceInfoPtr surface = NULL;
|
|
xvImageFormatInfo info;
|
|
XvImagePtr pImage;
|
|
int i, j;
|
|
|
|
REQUEST(xvmcListSubpictureTypesReq);
|
|
REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq);
|
|
|
|
VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
|
|
|
|
pScreen = pPort->pAdaptor->pScreen;
|
|
|
|
if (!dixPrivateKeyRegistered(XvMCScreenKey))
|
|
return BadMatch; /* No XvMC adaptors */
|
|
|
|
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
|
|
return BadMatch; /* None this screen */
|
|
|
|
for (i = 0; i < pScreenPriv->num_adaptors; i++) {
|
|
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
|
|
adaptor = &(pScreenPriv->adaptors[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!adaptor)
|
|
return BadMatch;
|
|
|
|
for (i = 0; i < adaptor->num_surfaces; i++) {
|
|
if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
|
|
surface = adaptor->surfaces[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!surface)
|
|
return BadMatch;
|
|
|
|
rep = (xvmcListSubpictureTypesReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.num = 0
|
|
};
|
|
if (surface->compatible_subpictures)
|
|
rep.num = surface->compatible_subpictures->num_xvimages;
|
|
|
|
rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo));
|
|
|
|
WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), &rep);
|
|
|
|
for (i = 0; i < rep.num; i++) {
|
|
pImage = NULL;
|
|
for (j = 0; j < adaptor->num_subpictures; j++) {
|
|
if (surface->compatible_subpictures->xvimage_ids[i] ==
|
|
adaptor->subpictures[j]->id) {
|
|
pImage = adaptor->subpictures[j];
|
|
break;
|
|
}
|
|
}
|
|
if (!pImage)
|
|
return BadImplementation;
|
|
|
|
info.id = pImage->id;
|
|
info.type = pImage->type;
|
|
info.byte_order = pImage->byte_order;
|
|
memcpy(&info.guid, pImage->guid, 16);
|
|
info.bpp = pImage->bits_per_pixel;
|
|
info.num_planes = pImage->num_planes;
|
|
info.depth = pImage->depth;
|
|
info.red_mask = pImage->red_mask;
|
|
info.green_mask = pImage->green_mask;
|
|
info.blue_mask = pImage->blue_mask;
|
|
info.format = pImage->format;
|
|
info.y_sample_bits = pImage->y_sample_bits;
|
|
info.u_sample_bits = pImage->u_sample_bits;
|
|
info.v_sample_bits = pImage->v_sample_bits;
|
|
info.horz_y_period = pImage->horz_y_period;
|
|
info.horz_u_period = pImage->horz_u_period;
|
|
info.horz_v_period = pImage->horz_v_period;
|
|
info.vert_y_period = pImage->vert_y_period;
|
|
info.vert_u_period = pImage->vert_u_period;
|
|
info.vert_v_period = pImage->vert_v_period;
|
|
memcpy(&info.comp_order, pImage->component_order, 32);
|
|
info.scanline_order = pImage->scanline_order;
|
|
WriteToClient(client, sizeof(xvImageFormatInfo), &info);
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXvMCGetDRInfo(ClientPtr client)
|
|
{
|
|
xvmcGetDRInfoReply rep;
|
|
XvPortPtr pPort;
|
|
ScreenPtr pScreen;
|
|
XvMCScreenPtr pScreenPriv;
|
|
|
|
#ifdef HAS_XVMCSHM
|
|
volatile CARD32 *patternP;
|
|
#endif
|
|
|
|
REQUEST(xvmcGetDRInfoReq);
|
|
REQUEST_SIZE_MATCH(xvmcGetDRInfoReq);
|
|
|
|
VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
|
|
|
|
pScreen = pPort->pAdaptor->pScreen;
|
|
pScreenPriv = XVMC_GET_PRIVATE(pScreen);
|
|
|
|
rep = (xvmcGetDRInfoReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.major = pScreenPriv->major,
|
|
.minor = pScreenPriv->minor,
|
|
.patchLevel = pScreenPriv->patchLevel,
|
|
.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1),
|
|
.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1),
|
|
.isLocal = 1
|
|
};
|
|
|
|
rep.length = rep.nameLen + rep.busIDLen;
|
|
rep.nameLen <<= 2;
|
|
rep.busIDLen <<= 2;
|
|
|
|
/*
|
|
* Read back to the client what she has put in the shared memory
|
|
* segment she prepared for us.
|
|
*/
|
|
|
|
#ifdef HAS_XVMCSHM
|
|
patternP = (CARD32 *) shmat(stuff->shmKey, NULL, SHM_RDONLY);
|
|
if (-1 != (long) patternP) {
|
|
volatile CARD32 *patternC = patternP;
|
|
int i;
|
|
CARD32 magic = stuff->magic;
|
|
|
|
rep.isLocal = 1;
|
|
i = 1024 / sizeof(CARD32);
|
|
|
|
while (i--) {
|
|
if (*patternC++ != magic) {
|
|
rep.isLocal = 0;
|
|
break;
|
|
}
|
|
magic = ~magic;
|
|
}
|
|
shmdt((char *) patternP);
|
|
}
|
|
#endif /* HAS_XVMCSHM */
|
|
|
|
WriteToClient(client, sizeof(xvmcGetDRInfoReply), &rep);
|
|
if (rep.length) {
|
|
WriteToClient(client, rep.nameLen, pScreenPriv->clientDriverName);
|
|
WriteToClient(client, rep.busIDLen, pScreenPriv->busID);
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
int (*ProcXvMCVector[xvmcNumRequest]) (ClientPtr) = {
|
|
ProcXvMCQueryVersion,
|
|
ProcXvMCListSurfaceTypes,
|
|
ProcXvMCCreateContext,
|
|
ProcXvMCDestroyContext,
|
|
ProcXvMCCreateSurface,
|
|
ProcXvMCDestroySurface,
|
|
ProcXvMCCreateSubpicture,
|
|
ProcXvMCDestroySubpicture,
|
|
ProcXvMCListSubpictureTypes, ProcXvMCGetDRInfo};
|
|
|
|
static int
|
|
ProcXvMCDispatch(ClientPtr client)
|
|
{
|
|
REQUEST(xReq);
|
|
|
|
if (stuff->data < xvmcNumRequest)
|
|
return (*ProcXvMCVector[stuff->data]) (client);
|
|
else
|
|
return BadRequest;
|
|
}
|
|
|
|
static int _X_COLD
|
|
SProcXvMCDispatch(ClientPtr client)
|
|
{
|
|
/* We only support local */
|
|
return BadImplementation;
|
|
}
|
|
|
|
void
|
|
XvMCExtensionInit(void)
|
|
{
|
|
ExtensionEntry *extEntry;
|
|
|
|
if (!dixPrivateKeyRegistered(XvMCScreenKey))
|
|
return;
|
|
|
|
if (!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes,
|
|
"XvMCRTContext")))
|
|
return;
|
|
|
|
if (!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes,
|
|
"XvMCRTSurface")))
|
|
return;
|
|
|
|
if (!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes,
|
|
"XvMCRTSubpicture")))
|
|
return;
|
|
|
|
extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors,
|
|
ProcXvMCDispatch, SProcXvMCDispatch,
|
|
NULL, StandardMinorOpcode);
|
|
|
|
if (!extEntry)
|
|
return;
|
|
|
|
XvMCReqCode = extEntry->base;
|
|
XvMCEventBase = extEntry->eventBase;
|
|
SetResourceTypeErrorValue(XvMCRTContext,
|
|
extEntry->errorBase + XvMCBadContext);
|
|
SetResourceTypeErrorValue(XvMCRTSurface,
|
|
extEntry->errorBase + XvMCBadSurface);
|
|
SetResourceTypeErrorValue(XvMCRTSubpicture,
|
|
extEntry->errorBase + XvMCBadSubpicture);
|
|
}
|
|
|
|
static Bool
|
|
XvMCCloseScreen(ScreenPtr pScreen)
|
|
{
|
|
XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
|
|
|
|
pScreen->CloseScreen = pScreenPriv->CloseScreen;
|
|
|
|
free(pScreenPriv);
|
|
|
|
return (*pScreen->CloseScreen) (pScreen);
|
|
}
|
|
|
|
int
|
|
XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt)
|
|
{
|
|
XvMCScreenPtr pScreenPriv;
|
|
|
|
if (!dixRegisterPrivateKey(&XvMCScreenKeyRec, PRIVATE_SCREEN, 0))
|
|
return BadAlloc;
|
|
|
|
if (!(pScreenPriv = malloc(sizeof(XvMCScreenRec))))
|
|
return BadAlloc;
|
|
|
|
dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv);
|
|
|
|
pScreenPriv->CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = XvMCCloseScreen;
|
|
|
|
pScreenPriv->num_adaptors = num;
|
|
pScreenPriv->adaptors = pAdapt;
|
|
pScreenPriv->clientDriverName[0] = 0;
|
|
pScreenPriv->busID[0] = 0;
|
|
pScreenPriv->major = 0;
|
|
pScreenPriv->minor = 0;
|
|
pScreenPriv->patchLevel = 0;
|
|
|
|
XvMCInUse = TRUE;
|
|
|
|
return Success;
|
|
}
|
|
|
|
XvImagePtr
|
|
XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
|
|
{
|
|
XvImagePtr pImage = NULL;
|
|
ScreenPtr pScreen = pPort->pAdaptor->pScreen;
|
|
XvMCScreenPtr pScreenPriv;
|
|
XvMCAdaptorPtr adaptor = NULL;
|
|
int i;
|
|
|
|
if (!dixPrivateKeyRegistered(XvMCScreenKey))
|
|
return NULL;
|
|
|
|
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
|
|
return NULL;
|
|
|
|
for (i = 0; i < pScreenPriv->num_adaptors; i++) {
|
|
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
|
|
adaptor = &(pScreenPriv->adaptors[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!adaptor)
|
|
return NULL;
|
|
|
|
for (i = 0; i < adaptor->num_subpictures; i++) {
|
|
if (adaptor->subpictures[i]->id == id) {
|
|
pImage = adaptor->subpictures[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pImage;
|
|
}
|
|
|
|
int
|
|
xf86XvMCRegisterDRInfo(ScreenPtr pScreen, const char *name,
|
|
const char *busID, int major, int minor, int patchLevel)
|
|
{
|
|
XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
|
|
|
|
strlcpy(pScreenPriv->clientDriverName, name, DR_CLIENT_DRIVER_NAME_SIZE);
|
|
strlcpy(pScreenPriv->busID, busID, DR_BUSID_SIZE);
|
|
pScreenPriv->major = major;
|
|
pScreenPriv->minor = minor;
|
|
pScreenPriv->patchLevel = patchLevel;
|
|
return Success;
|
|
}
|